Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eval diagnostics #26738

Merged
merged 12 commits into from
Oct 28, 2020
2 changes: 1 addition & 1 deletion command/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -924,7 +924,7 @@ func TestApply_shutdown(t *testing.T) {
"-auto-approve",
testFixturePath("apply-shutdown"),
}
if code := c.Run(args); code != 0 {
if code := c.Run(args); code != 1 {
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
}

Expand Down
8 changes: 2 additions & 6 deletions command/plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -845,12 +845,8 @@ func TestPlan_shutdown(t *testing.T) {
"-state=nonexistent.tfstate",
testFixturePath("apply-shutdown"),
})
if code != 0 {
// FIXME: In retrospect cancellation ought to be an unsuccessful exit
// case, but we need to do that cautiously in case it impacts automation
// wrappers. See the note about this in the terraform.stopHook
// implementation for more.
t.Errorf("wrong exit code %d; want 0\noutput:\n%s", code, ui.OutputWriter.String())
if code != 1 {
t.Errorf("wrong exit code %d; want 1\noutput:\n%s", code, ui.OutputWriter.String())
}

select {
Expand Down
86 changes: 81 additions & 5 deletions terraform/context_apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1734,8 +1734,16 @@ func TestContext2Apply_cancel(t *testing.T) {
}()

state := <-stateCh
if applyDiags.HasErrors() {
t.Fatalf("unexpected errors: %s", applyDiags.Err())
// only expecting an early exit error
if !applyDiags.HasErrors() {
t.Fatal("expected early exit error")
}

for _, d := range applyDiags {
desc := d.Description()
if desc.Summary != "execution halted" {
t.Fatalf("unexpected error: %v", applyDiags.Err())
}
}

actual := strings.TrimSpace(state.String())
Expand Down Expand Up @@ -1812,8 +1820,16 @@ func TestContext2Apply_cancelBlock(t *testing.T) {

// Wait for apply to complete
state := <-stateCh
if applyDiags.HasErrors() {
t.Fatalf("unexpected error: %s", applyDiags.Err())
// only expecting an early exit error
if !applyDiags.HasErrors() {
t.Fatal("expected early exit error")
}

for _, d := range applyDiags {
desc := d.Description()
if desc.Summary != "execution halted" {
t.Fatalf("unexpected error: %v", applyDiags.Err())
}
}

checkStateString(t, state, `
Expand Down Expand Up @@ -1882,7 +1898,18 @@ func TestContext2Apply_cancelProvisioner(t *testing.T) {

// Wait for completion
state := <-stateCh
assertNoErrors(t, applyDiags)

// we are expecting only an early exit error
if !applyDiags.HasErrors() {
t.Fatal("expected early exit error")
}

for _, d := range applyDiags {
desc := d.Description()
if desc.Summary != "execution halted" {
t.Fatalf("unexpected error: %v", applyDiags.Err())
}
}

checkStateString(t, state, `
aws_instance.foo: (tainted)
Expand Down Expand Up @@ -12203,3 +12230,52 @@ resource "test_resource" "foo" {
t.Fatal("missing 'test_resource.foo' in state:", state)
}
}

func TestContext2Apply_rpcDiagnostics(t *testing.T) {
m := testModuleInline(t, map[string]string{
"main.tf": `
resource "test_instance" "a" {
}
`,
})

p := testProvider("test")
p.PlanResourceChangeFn = testDiffFn
p.ApplyResourceChangeFn = testApplyFn
p.GetSchemaReturn = &ProviderSchema{
ResourceTypes: map[string]*configschema.Block{
"test_instance": {
Attributes: map[string]*configschema.Attribute{
"id": {Type: cty.String, Computed: true},
},
},
},
}

p.ValidateResourceTypeConfigResponse = providers.ValidateResourceTypeConfigResponse{
Diagnostics: tfdiags.Diagnostics(nil).Append(tfdiags.SimpleWarning("don't frobble")),
}

ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
},
})
_, diags := ctx.Plan()
if diags.HasErrors() {
t.Fatal(diags.Err())
}

_, diags = ctx.Apply()
if diags.HasErrors() {
t.Fatal(diags.Err())
}

for _, d := range diags {
des := d.Description().Summary
if !strings.Contains(des, "frobble") {
t.Fatalf(`expected frobble, got %q`, des)
}
}
}
43 changes: 43 additions & 0 deletions terraform/context_plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6421,3 +6421,46 @@ data "test_data_source" "b" {
t.Fatal("data source b was not read during plan")
}
}

func TestContext2Plan_rpcDiagnostics(t *testing.T) {
m := testModuleInline(t, map[string]string{
"main.tf": `
resource "test_instance" "a" {
}
`,
})

p := testProvider("test")
p.PlanResourceChangeFn = testDiffFn
p.GetSchemaReturn = &ProviderSchema{
ResourceTypes: map[string]*configschema.Block{
"test_instance": {
Attributes: map[string]*configschema.Attribute{
"id": {Type: cty.String, Computed: true},
},
},
},
}

p.ValidateResourceTypeConfigResponse = providers.ValidateResourceTypeConfigResponse{
Diagnostics: tfdiags.Diagnostics(nil).Append(tfdiags.SimpleWarning("don't herd cats")),
}

ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
},
})
_, diags := ctx.Plan()
if diags.HasErrors() {
t.Fatal(diags.Err())
}

for _, d := range diags {
des := d.Description().Summary
if !strings.Contains(des, "cats") {
t.Fatalf(`expected cats, got %q`, des)
}
}
}
43 changes: 43 additions & 0 deletions terraform/context_validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1795,3 +1795,46 @@ resource "test_instance" "a" {
}
}
}

func TestContext2Validate_rpcDiagnostics(t *testing.T) {
// validate module and output depends_on
m := testModuleInline(t, map[string]string{
"main.tf": `
resource "test_instance" "a" {
}
`,
})

p := testProvider("test")
p.GetSchemaReturn = &ProviderSchema{
ResourceTypes: map[string]*configschema.Block{
"test_instance": {
Attributes: map[string]*configschema.Attribute{
"id": {Type: cty.String, Computed: true},
},
},
},
}

p.ValidateResourceTypeConfigResponse = providers.ValidateResourceTypeConfigResponse{
Diagnostics: tfdiags.Diagnostics(nil).Append(tfdiags.SimpleWarning("don't frobble")),
}

ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
},
})
diags := ctx.Validate()
if diags.HasErrors() {
t.Fatal(diags.Err())
}

for _, d := range diags {
des := d.Description().Summary
if !strings.Contains(des, "frobble") {
t.Fatalf(`expected frobble, got %q`, des)
}
}
}
Loading