add more tests for failing actions

pull/37390/head
Daniel Schmidt 7 months ago
parent f4da6c1c82
commit eaf3b90bc3

@ -24,7 +24,7 @@ func TestContext2Apply_actions(t *testing.T) {
mode plans.Mode
prevRunState *states.State
events []providers.InvokeActionEvent
callingInvokeReturnsDiagnostics tfdiags.Diagnostics
callingInvokeReturnsDiagnostics func(providers.InvokeActionRequest) tfdiags.Diagnostics
planOpts *PlanOpts
expectInvokeActionCalled bool
@ -181,7 +181,7 @@ resource "test_object" "a" {
},
},
"before_create failing to call invoke": {
"before_create failing when calling invoke": {
module: map[string]string{
"main.tf": `
action "act_unlinked" "hello" {}
@ -196,13 +196,121 @@ resource "test_object" "a" {
`,
},
expectInvokeActionCalled: true,
callingInvokeReturnsDiagnostics: tfdiags.Diagnostics{
callingInvokeReturnsDiagnostics: func(providers.InvokeActionRequest) tfdiags.Diagnostics {
return tfdiags.Diagnostics{
tfdiags.Sourceless(
tfdiags.Error,
"test case for failing",
"this simulates a provider failing before the action is invoked",
),
}
},
expectDiagnostics: tfdiags.Diagnostics{
tfdiags.Sourceless(
tfdiags.Error,
"test case for failing",
"this simulates a provider failing before the action is invoked",
),
},
},
"failing an action stops next actions in list": {
module: map[string]string{
"main.tf": `
action "act_unlinked" "hello" {}
action "act_unlinked" "failure" {
config {
attr = "failure"
}
}
action "act_unlinked" "goodbye" {}
resource "test_object" "a" {
lifecycle {
action_trigger {
events = [before_create]
actions = [action.act_unlinked.hello, action.act_unlinked.failure, action.act_unlinked.goodbye]
}
}
}
`,
},
expectInvokeActionCalled: true,
callingInvokeReturnsDiagnostics: func(r providers.InvokeActionRequest) tfdiags.Diagnostics {
if !r.PlannedActionData.IsNull() && r.PlannedActionData.GetAttr("attr").AsString() == "failure" {
// Simulate a failure for the second action
return tfdiags.Diagnostics{
tfdiags.Sourceless(
tfdiags.Error,
"test case for failing",
"this simulates a provider failing before the action is invoked",
),
}
}
return tfdiags.Diagnostics{}
},
expectDiagnostics: tfdiags.Diagnostics{
tfdiags.Sourceless(
tfdiags.Error,
"test case for failing",
"this simulates a provider failing before the action is invoked",
),
},
// We expect two calls but not the third one, because the second action fails
expectInvokeActionCalls: []providers.InvokeActionRequest{{
ActionType: "act_unlinked",
PlannedActionData: cty.NullVal(cty.Object(map[string]cty.Type{
"attr": cty.String,
})),
}, {
ActionType: "act_unlinked",
PlannedActionData: cty.ObjectVal(map[string]cty.Value{
"attr": cty.StringVal("failure"),
}),
}},
},
"failing an action stops next action triggers": {
module: map[string]string{
"main.tf": `
action "act_unlinked" "hello" {}
action "act_unlinked" "failure" {
config {
attr = "failure"
}
}
action "act_unlinked" "goodbye" {}
resource "test_object" "a" {
lifecycle {
action_trigger {
events = [before_create]
actions = [action.act_unlinked.hello]
}
action_trigger {
events = [before_create]
actions = [action.act_unlinked.failure]
}
action_trigger {
events = [before_create]
actions = [action.act_unlinked.goodbye]
}
}
}
`,
},
expectInvokeActionCalled: true,
callingInvokeReturnsDiagnostics: func(r providers.InvokeActionRequest) tfdiags.Diagnostics {
if !r.PlannedActionData.IsNull() && r.PlannedActionData.GetAttr("attr").AsString() == "failure" {
// Simulate a failure for the second action
return tfdiags.Diagnostics{
tfdiags.Sourceless(
tfdiags.Error,
"test case for failing",
"this simulates a provider failing before the action is invoked",
),
}
}
return tfdiags.Diagnostics{}
},
expectDiagnostics: tfdiags.Diagnostics{
tfdiags.Sourceless(
tfdiags.Error,
@ -210,6 +318,18 @@ resource "test_object" "a" {
"this simulates a provider failing before the action is invoked",
),
},
// We expect two calls but not the third one, because the second action fails
expectInvokeActionCalls: []providers.InvokeActionRequest{{
ActionType: "act_unlinked",
PlannedActionData: cty.NullVal(cty.Object(map[string]cty.Type{
"attr": cty.String,
})),
}, {
ActionType: "act_unlinked",
PlannedActionData: cty.ObjectVal(map[string]cty.Value{
"attr": cty.StringVal("failure"),
}),
}},
},
"action with configuration": {
@ -364,9 +484,9 @@ resource "test_object" "b" {
InvokeActionFn: func(req providers.InvokeActionRequest) providers.InvokeActionResponse {
invokeActionCalls = append(invokeActionCalls, req)
if len(tc.callingInvokeReturnsDiagnostics) > 0 {
if tc.callingInvokeReturnsDiagnostics != nil && len(tc.callingInvokeReturnsDiagnostics(req)) > 0 {
return providers.InvokeActionResponse{
Diagnostics: tc.callingInvokeReturnsDiagnostics,
Diagnostics: tc.callingInvokeReturnsDiagnostics(req),
}
}
@ -428,11 +548,12 @@ resource "test_object" "b" {
}
for i, expectedCall := range tc.expectInvokeActionCalls {
actualCall := invokeActionCalls[i]
if actualCall.ActionType != expectedCall.ActionType {
t.Fatalf("expected invoke action call %d ActionType to be %s, got %s", i, expectedCall.ActionType, actualCall.ActionType)
}
if !actualCall.PlannedActionData.RawEquals(expectedCall.PlannedActionData) {
t.Fatalf("expected invoke action call %d PlannedActionData to be %s, got %s", i, expectedCall.PlannedActionData, actualCall.PlannedActionData)
t.Fatalf("expected invoke action call %d PlannedActionData to be %s, got %s", i, expectedCall.PlannedActionData.GoString(), actualCall.PlannedActionData.GoString())
}
}
})

Loading…
Cancel
Save