diff --git a/terraform/context_apply_test.go b/terraform/context_apply_test.go index af6ffa155a..a10c34ae4e 100644 --- a/terraform/context_apply_test.go +++ b/terraform/context_apply_test.go @@ -11338,14 +11338,526 @@ func TestContext2Apply_ProviderMeta_apply_set(t *testing.T) { ), }) - if _, diags := ctx.Plan(); diags.HasErrors() { - t.Fatalf("plan errors: %s", diags.Err()) + _, diags := ctx.Plan() + assertNoErrors(t, diags) + + _, diags = ctx.Apply() + assertNoErrors(t, diags) + + if !p.ApplyResourceChangeCalled { + t.Fatalf("ApplyResourceChange not called") + } + if p.ApplyResourceChangeRequest.ProviderMeta.IsNull() { + t.Fatalf("null ProviderMeta in ApplyResourceChange") + } + type metaStruct struct { + Baz string `cty:"baz"` + } + var meta metaStruct + err := gocty.FromCtyValue(p.ApplyResourceChangeRequest.ProviderMeta, &meta) + if err != nil { + t.Fatalf("Error parsing cty value: %s", err) + } + if meta.Baz != "quux" { + t.Fatalf("Expected meta.Baz to be \"quux\", got %q", meta.Baz) + } +} + +func TestContext2Apply_ProviderMeta_apply_setNoSchema(t *testing.T) { + m := testModule(t, "provider-meta-set") + p := testProvider("test") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + ctx := testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + }) + + if _, diags := ctx.Plan(); !diags.HasErrors() { + t.Fatalf("plan supposed to error, has no errors") + } + + // TODO: check we get the errors we want + + _, diags := ctx.Apply() + if !diags.HasErrors() { + t.Fatalf("apply supposed to error, has no errors") + } + + // TODO: check we get the errors we want +} + +func TestContext2Apply_ProviderMeta_apply_setInvalid(t *testing.T) { + m := testModule(t, "provider-meta-set") + p := testProvider("test") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + schema := p.GetSchemaReturn + schema.ProviderMeta = &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "quux": { + Type: cty.String, + Required: true, + }, + }, + } + p.GetSchemaReturn = schema + ctx := testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + }) + + if _, diags := ctx.Plan(); !diags.HasErrors() { + t.Fatalf("plan supposed to error, has no errors") + } + + // TODO: check we get the errors we want + + _, diags := ctx.Apply() + if !diags.HasErrors() { + t.Fatalf("apply supposed to error, has no errors") + } + + // TODO: check we get the errors we want +} + +func TestContext2Apply_ProviderMeta_apply_unset(t *testing.T) { + m := testModule(t, "provider-meta-unset") + p := testProvider("test") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + schema := p.GetSchemaReturn + schema.ProviderMeta = &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "baz": { + Type: cty.String, + Required: true, + }, + }, + } + p.GetSchemaReturn = schema + ctx := testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + }) + + _, diags := ctx.Plan() + assertNoErrors(t, diags) + + _, diags = ctx.Apply() + assertNoErrors(t, diags) + + if !p.ApplyResourceChangeCalled { + t.Fatalf("ApplyResourceChange not called") + } + if !p.ApplyResourceChangeRequest.ProviderMeta.IsNull() { + t.Fatalf("Expected ProviderMeta in ApplyResourceChange to be null, got %v", p.ApplyResourceChangeRequest.ProviderMeta) + } +} + +func TestContext2Apply_ProviderMeta_plan_set(t *testing.T) { + m := testModule(t, "provider-meta-set") + p := testProvider("test") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + schema := p.GetSchemaReturn + schema.ProviderMeta = &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "baz": { + Type: cty.String, + Required: true, + }, + }, + } + p.GetSchemaReturn = schema + ctx := testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + }) + + _, diags := ctx.Plan() + assertNoErrors(t, diags) + + if !p.PlanResourceChangeCalled { + t.Fatalf("PlanResourceChange not called") + } + if p.PlanResourceChangeRequest.ProviderMeta.IsNull() { + t.Fatalf("null ProviderMeta in PlanResourceChange") + } + type metaStruct struct { + Baz string `cty:"baz"` + } + var meta metaStruct + err := gocty.FromCtyValue(p.PlanResourceChangeRequest.ProviderMeta, &meta) + if err != nil { + t.Fatalf("Error parsing cty value: %s", err) + } + if meta.Baz != "quux" { + t.Fatalf("Expected meta.Baz to be \"quux\", got %q", meta.Baz) + } +} + +func TestContext2Apply_ProviderMeta_plan_unset(t *testing.T) { + m := testModule(t, "provider-meta-unset") + p := testProvider("test") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + schema := p.GetSchemaReturn + schema.ProviderMeta = &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "baz": { + Type: cty.String, + Required: true, + }, + }, + } + p.GetSchemaReturn = schema + ctx := testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + }) + + _, diags := ctx.Plan() + assertNoErrors(t, diags) + + if !p.PlanResourceChangeCalled { + t.Fatalf("PlanResourceChange not called") + } + if !p.PlanResourceChangeRequest.ProviderMeta.IsNull() { + t.Fatalf("Expected ProviderMeta in PlanResourceChange to be null, got %v", p.PlanResourceChangeRequest.ProviderMeta) + } +} + +func TestContext2Apply_ProviderMeta_plan_setNoSchema(t *testing.T) { + m := testModule(t, "provider-meta-set") + p := testProvider("test") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + ctx := testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + }) + + if _, diags := ctx.Plan(); !diags.HasErrors() { + t.Fatalf("plan supposed to error, has no errors") + } + + // TODO: check we get the errors we want +} + +func TestContext2Apply_ProviderMeta_plan_setInvalid(t *testing.T) { + m := testModule(t, "provider-meta-set") + p := testProvider("test") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + schema := p.GetSchemaReturn + schema.ProviderMeta = &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "quux": { + Type: cty.String, + Required: true, + }, + }, + } + p.GetSchemaReturn = schema + ctx := testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + }) + + if _, diags := ctx.Plan(); !diags.HasErrors() { + t.Fatalf("plan supposed to error, has no errors") + } + + // TODO: check we get the errors we want +} + +func TestContext2Apply_ProviderMeta_refresh_set(t *testing.T) { + m := testModule(t, "provider-meta-set") + p := testProvider("test") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + schema := p.GetSchemaReturn + schema.ProviderMeta = &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "baz": { + Type: cty.String, + Required: true, + }, + }, + } + p.GetSchemaReturn = schema + ctx := testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + }) + + _, diags := ctx.Plan() + assertNoErrors(t, diags) + + _, diags = ctx.Apply() + assertNoErrors(t, diags) + + _, diags = ctx.Refresh() + assertNoErrors(t, diags) + + if !p.ReadResourceCalled { + t.Fatalf("ReadResource not called") + } + if p.ReadResourceRequest.ProviderMeta.IsNull() { + t.Fatalf("null ProviderMeta in ReadResource") + } + type metaStruct struct { + Baz string `cty:"baz"` + } + var meta metaStruct + err := gocty.FromCtyValue(p.ReadResourceRequest.ProviderMeta, &meta) + if err != nil { + t.Fatalf("Error parsing cty value: %s", err) + } + if meta.Baz != "quux" { + t.Fatalf("Expected meta.Baz to be \"quux\", got %q", meta.Baz) + } +} + +func TestContext2Apply_ProviderMeta_refresh_unset(t *testing.T) { + m := testModule(t, "provider-meta-unset") + p := testProvider("test") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + schema := p.GetSchemaReturn + schema.ProviderMeta = &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "baz": { + Type: cty.String, + Required: true, + }, + }, + } + p.GetSchemaReturn = schema + ctx := testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + }) + + _, diags := ctx.Plan() + assertNoErrors(t, diags) + + _, diags = ctx.Apply() + assertNoErrors(t, diags) + + _, diags = ctx.Refresh() + assertNoErrors(t, diags) + + if !p.ReadResourceCalled { + t.Fatalf("ReadResource not called") + } + if !p.ReadResourceRequest.ProviderMeta.IsNull() { + t.Fatalf("Expected null ProviderMeta in ReadResource, got %v", p.ReadResourceRequest.ProviderMeta) + } +} + +func TestContext2Apply_ProviderMeta_refresh_setNoSchema(t *testing.T) { + m := testModule(t, "provider-meta-set") + p := testProvider("test") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + + // we need a schema for plan/apply so they don't error + schema := p.GetSchemaReturn + schema.ProviderMeta = &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "baz": { + Type: cty.String, + Required: true, + }, + }, + } + p.GetSchemaReturn = schema + ctx := testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + }) + + _, diags := ctx.Plan() + assertNoErrors(t, diags) + + _, diags = ctx.Apply() + assertNoErrors(t, diags) + + // drop the schema before refresh, to test that it errors + schema.ProviderMeta = nil + p.GetSchemaReturn = schema + ctx = testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + State: ctx.State(), + }) + + _, diags = ctx.Refresh() + if !diags.HasErrors() { + t.Fatalf("refresh supposed to error, has no errors") + } + + // TODO: check we get the errors we want +} + +func TestContext2Apply_ProviderMeta_refresh_setInvalid(t *testing.T) { + m := testModule(t, "provider-meta-set") + p := testProvider("test") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + + // we need a matching schema for plan/apply so they don't error + schema := p.GetSchemaReturn + schema.ProviderMeta = &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "baz": { + Type: cty.String, + Required: true, + }, + }, + } + p.GetSchemaReturn = schema + ctx := testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + }) + + _, diags := ctx.Plan() + assertNoErrors(t, diags) + + _, diags = ctx.Apply() + assertNoErrors(t, diags) + + // change the schema before refresh, to test that it errors + schema.ProviderMeta = &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "quux": { + Type: cty.String, + Required: true, + }, + }, } + p.GetSchemaReturn = schema + ctx = testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + State: ctx.State(), + }) + + _, diags = ctx.Refresh() + if !diags.HasErrors() { + t.Fatalf("refresh supposed to error, has no errors") + } + + // TODO: check we get the errors we want +} + +func TestContext2Apply_ProviderMeta_destroy_set(t *testing.T) { + m := testModule(t, "provider-meta-set") + p := testProvider("test") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + schema := p.GetSchemaReturn + schema.ProviderMeta = &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "baz": { + Type: cty.String, + Required: true, + }, + }, + } + p.GetSchemaReturn = schema + ctx := testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + }) + + _, diags := ctx.Plan() + assertNoErrors(t, diags) + + state, diags := ctx.Apply() + assertNoErrors(t, diags) + + // reset our mocks + // we don't care about the first apply, it's just to set up state + p.ApplyResourceChangeCalled = false + p.ApplyResourceChangeRequest = providers.ApplyResourceChangeRequest{} + + ctx = testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + State: state, + Destroy: true, + }) + + _, diags = ctx.Plan() + assertNoErrors(t, diags) + + _, diags = ctx.Apply() + assertNoErrors(t, diags) - _, diags := ctx.Apply() - if diags.HasErrors() { - t.Fatalf("diags: %s", diags.Err()) - } if !p.ApplyResourceChangeCalled { t.Fatalf("ApplyResourceChange not called") } @@ -11365,8 +11877,8 @@ func TestContext2Apply_ProviderMeta_apply_set(t *testing.T) { } } -func TestContext2Apply_ProviderMeta_plan_set(t *testing.T) { - m := testModule(t, "provider-meta-set") +func TestContext2Apply_ProviderMeta_destroy_unset(t *testing.T) { + m := testModule(t, "provider-meta-unset") p := testProvider("test") p.ApplyFn = testApplyFn p.DiffFn = testDiffFn @@ -11389,34 +11901,49 @@ func TestContext2Apply_ProviderMeta_plan_set(t *testing.T) { ), }) - if _, diags := ctx.Plan(); diags.HasErrors() { - t.Fatalf("plan errors: %s", diags.Err()) - } + _, diags := ctx.Plan() + assertNoErrors(t, diags) - if !p.PlanResourceChangeCalled { - t.Fatalf("PlanResourceChange not called") - } - if p.PlanResourceChangeRequest.ProviderMeta.IsNull() { - t.Fatalf("null ProviderMeta in PlanResourceChange") - } - type metaStruct struct { - Baz string `cty:"baz"` - } - var meta metaStruct - err := gocty.FromCtyValue(p.PlanResourceChangeRequest.ProviderMeta, &meta) - if err != nil { - t.Fatalf("Error parsing cty value: %s", err) + state, diags := ctx.Apply() + assertNoErrors(t, diags) + + // reset our mocks + // we don't care about the first apply, it's just to set up state + p.ApplyResourceChangeCalled = false + p.ApplyResourceChangeRequest = providers.ApplyResourceChangeRequest{} + + ctx = testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + State: state, + Destroy: true, + }) + + _, diags = ctx.Plan() + assertNoErrors(t, diags) + + _, diags = ctx.Apply() + assertNoErrors(t, diags) + + if !p.ApplyResourceChangeCalled { + t.Fatalf("ApplyResourceChange not called") } - if meta.Baz != "quux" { - t.Fatalf("Expected meta.Baz to be \"quux\", got %q", meta.Baz) + if !p.ApplyResourceChangeRequest.ProviderMeta.IsNull() { + t.Fatalf("Expected null ProviderMeta in ApplyResourceChange, got %v", p.ApplyResourceChangeRequest.ProviderMeta) } } -func TestContext2Apply_ProviderMeta_refresh_set(t *testing.T) { +func TestContext2Apply_ProviderMeta_destroy_setNoSchema(t *testing.T) { m := testModule(t, "provider-meta-set") p := testProvider("test") p.ApplyFn = testApplyFn p.DiffFn = testDiffFn + // we need a schema so the first apply succeeds + // that way there's something to destroy schema := p.GetSchemaReturn schema.ProviderMeta = &configschema.Block{ Attributes: map[string]*configschema.Attribute{ @@ -11439,36 +11966,57 @@ func TestContext2Apply_ProviderMeta_refresh_set(t *testing.T) { _, diags := ctx.Plan() assertNoErrors(t, diags) - _, diags = ctx.Apply() + state, diags := ctx.Apply() assertNoErrors(t, diags) - _, diags = ctx.Refresh() - assertNoErrors(t, diags) + // reset our mocks + // we don't care about the first apply, it's just to set up state + p.ApplyResourceChangeCalled = false + p.ApplyResourceChangeRequest = providers.ApplyResourceChangeRequest{} - if !p.ReadResourceCalled { - t.Fatalf("ReadResource not called") - } - if p.ReadResourceRequest.ProviderMeta.IsNull() { - t.Fatalf("null ProviderMeta in ReadResource") - } - type metaStruct struct { - Baz string `cty:"baz"` - } - var meta metaStruct - err := gocty.FromCtyValue(p.ReadResourceRequest.ProviderMeta, &meta) - if err != nil { - t.Fatalf("Error parsing cty value: %s", err) + // we also need to remove the schema to test the errors now + schema.ProviderMeta = nil + p.GetSchemaReturn = schema + ctx = testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + State: ctx.State(), + }) + ctx = testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + State: state, + Destroy: true, + }) + + if _, diags := ctx.Plan(); !diags.HasErrors() { + t.Fatalf("plan supposed to error, has no errors") } - if meta.Baz != "quux" { - t.Fatalf("Expected meta.Baz to be \"quux\", got %q", meta.Baz) + + // TODO: check we get the errors we want + + _, diags = ctx.Apply() + if !diags.HasErrors() { + t.Fatalf("apply supposed to error, has no errors") } + + // TODO: check we get the errors we want } -func TestContext2Apply_ProviderMeta_destroy_set(t *testing.T) { +func TestContext2Apply_ProviderMeta_destroy_setInvalid(t *testing.T) { m := testModule(t, "provider-meta-set") p := testProvider("test") p.ApplyFn = testApplyFn p.DiffFn = testDiffFn + // we need a valid schema to set up state schema := p.GetSchemaReturn schema.ProviderMeta = &configschema.Block{ Attributes: map[string]*configschema.Attribute{ @@ -11499,6 +12047,26 @@ func TestContext2Apply_ProviderMeta_destroy_set(t *testing.T) { p.ApplyResourceChangeCalled = false p.ApplyResourceChangeRequest = providers.ApplyResourceChangeRequest{} + // change our schema so our config is now invalid + schema.ProviderMeta = &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "quux": { + Type: cty.String, + Required: true, + }, + }, + } + p.GetSchemaReturn = schema + ctx = testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + State: ctx.State(), + }) + ctx = testContext2(t, &ContextOpts{ Config: m, ProviderResolver: providers.ResolverFixed( @@ -11510,23 +12078,70 @@ func TestContext2Apply_ProviderMeta_destroy_set(t *testing.T) { Destroy: true, }) + if _, diags := ctx.Plan(); !diags.HasErrors() { + t.Fatalf("plan supposed to error, has no errors") + } + + // TODO: check we get the errors we want + + _, diags = ctx.Apply() + if !diags.HasErrors() { + t.Fatalf("apply supposed to error, has no errors") + } + + // TODO: check we get the errors we want +} + +func TestContext2Apply_ProviderMeta_refreshdata_set(t *testing.T) { + m := testModule(t, "provider-meta-data-set") + p := testProvider("test") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + schema := p.GetSchemaReturn + schema.ProviderMeta = &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "baz": { + Type: cty.String, + Required: true, + }, + }, + } + p.GetSchemaReturn = schema + ctx := testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + }) + p.ReadDataSourceResponse = providers.ReadDataSourceResponse{ + State: cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("yo"), + "foo": cty.StringVal("bar"), + }), + } + + _, diags := ctx.Refresh() + assertNoErrors(t, diags) + _, diags = ctx.Plan() assertNoErrors(t, diags) _, diags = ctx.Apply() assertNoErrors(t, diags) - if !p.ApplyResourceChangeCalled { - t.Fatalf("ApplyResourceChange not called") + if !p.ReadDataSourceCalled { + t.Fatalf("ReadDataSource not called") } - if p.ApplyResourceChangeRequest.ProviderMeta.IsNull() { - t.Fatalf("null ProviderMeta in ApplyResourceChange") + if p.ReadDataSourceRequest.ProviderMeta.IsNull() { + t.Fatalf("null ProviderMeta in ReadDataSource") } type metaStruct struct { Baz string `cty:"baz"` } var meta metaStruct - err := gocty.FromCtyValue(p.ApplyResourceChangeRequest.ProviderMeta, &meta) + err := gocty.FromCtyValue(p.ReadDataSourceRequest.ProviderMeta, &meta) if err != nil { t.Fatalf("Error parsing cty value: %s", err) } @@ -11535,8 +12150,8 @@ func TestContext2Apply_ProviderMeta_destroy_set(t *testing.T) { } } -func TestContext2Apply_ProviderMeta_refreshdata_set(t *testing.T) { - m := testModule(t, "provider-meta-data-set") +func TestContext2Apply_ProviderMeta_refreshdata_unset(t *testing.T) { + m := testModule(t, "provider-meta-data-unset") p := testProvider("test") p.ApplyFn = testApplyFn p.DiffFn = testDiffFn @@ -11577,18 +12192,73 @@ func TestContext2Apply_ProviderMeta_refreshdata_set(t *testing.T) { if !p.ReadDataSourceCalled { t.Fatalf("ReadDataSource not called") } - if p.ReadDataSourceRequest.ProviderMeta.IsNull() { - t.Fatalf("null ProviderMeta in ReadDataSource") + if !p.ReadDataSourceRequest.ProviderMeta.IsNull() { + t.Fatalf("Expected null ProviderMeta in ReadDataSource, got %v", p.ReadDataSourceRequest.ProviderMeta) } - type metaStruct struct { - Baz string `cty:"baz"` +} + +func TestContext2Apply_ProviderMeta_refreshdata_setNoSchema(t *testing.T) { + m := testModule(t, "provider-meta-data-set") + p := testProvider("test") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + ctx := testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + }) + p.ReadDataSourceResponse = providers.ReadDataSourceResponse{ + State: cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("yo"), + "foo": cty.StringVal("bar"), + }), } - var meta metaStruct - err := gocty.FromCtyValue(p.ReadDataSourceRequest.ProviderMeta, &meta) - if err != nil { - t.Fatalf("Error parsing cty value: %s", err) + + _, diags := ctx.Refresh() + if !diags.HasErrors() { + t.Fatalf("refresh supposed to error, has no errors") } - if meta.Baz != "quux" { - t.Fatalf("Expected meta.Baz to be \"quux\", got %q", meta.Baz) + + // TODO: check we get the errors we want +} + +func TestContext2Apply_ProviderMeta_refreshdata_setInvalid(t *testing.T) { + m := testModule(t, "provider-meta-data-set") + p := testProvider("test") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + schema := p.GetSchemaReturn + schema.ProviderMeta = &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "quux": { + Type: cty.String, + Required: true, + }, + }, + } + p.GetSchemaReturn = schema + ctx := testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + }) + p.ReadDataSourceResponse = providers.ReadDataSourceResponse{ + State: cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("yo"), + "foo": cty.StringVal("bar"), + }), + } + + _, diags := ctx.Refresh() + if !diags.HasErrors() { + t.Fatalf("refresh supposed to error, has no errors") } + + // TODO: check we get the errors we want } diff --git a/terraform/eval_apply.go b/terraform/eval_apply.go index e389e6b928..cacb38a1b3 100644 --- a/terraform/eval_apply.go +++ b/terraform/eval_apply.go @@ -79,8 +79,10 @@ func (n *EvalApply) Eval(ctx EvalContext) (interface{}, error) { metaConfigVal := cty.NullVal(cty.DynamicPseudoType) if n.ProviderMeta != nil { + log.Printf("[DEBUG] EvalApply: ProviderMeta config value set") // if the provider doesn't support this feature, throw an error if (*n.ProviderSchema).ProviderMeta == nil { + log.Printf("[DEBUG] EvalApply: no ProviderMeta schema") diags = diags.Append(&hcl.Diagnostic{ Severity: hcl.DiagError, Summary: fmt.Sprintf("Provider %s doesn't support provider_meta", (*n.Config).ProviderConfigAddr()), @@ -88,6 +90,7 @@ func (n *EvalApply) Eval(ctx EvalContext) (interface{}, error) { Subject: &n.ProviderMeta.ProviderRange, }) } else { + log.Printf("[DEBUG] EvalApply: ProviderMeta schema found") var configDiags tfdiags.Diagnostics metaConfigVal, _, configDiags = ctx.EvaluateBlock(n.ProviderMeta.Config, (*n.ProviderSchema).ProviderMeta, nil, EvalDataForNoInstanceKey) diags = diags.Append(configDiags) diff --git a/terraform/eval_refresh.go b/terraform/eval_refresh.go index 2437b8b19c..4aa25a7e57 100644 --- a/terraform/eval_refresh.go +++ b/terraform/eval_refresh.go @@ -47,8 +47,10 @@ func (n *EvalRefresh) Eval(ctx EvalContext) (interface{}, error) { metaConfigVal := cty.NullVal(cty.DynamicPseudoType) if n.ProviderMeta != nil { + log.Printf("[DEBUG] EvalRefresh: ProviderMeta config value set") // if the provider doesn't support this feature, throw an error if (*n.ProviderSchema).ProviderMeta == nil { + log.Printf("[DEBUG] EvalRefresh: no ProviderMeta schema") diags = diags.Append(&hcl.Diagnostic{ Severity: hcl.DiagError, Summary: fmt.Sprintf("Provider %s doesn't support provider_meta", n.ProviderAddr), @@ -56,6 +58,7 @@ func (n *EvalRefresh) Eval(ctx EvalContext) (interface{}, error) { Subject: &n.ProviderMeta.ProviderRange, }) } else { + log.Printf("[DEBUG] EvalRefresh: ProviderMeta schema found: %+v", (*n.ProviderSchema).ProviderMeta) var configDiags tfdiags.Diagnostics metaConfigVal, _, configDiags = ctx.EvaluateBlock(n.ProviderMeta.Config, (*n.ProviderSchema).ProviderMeta, nil, EvalDataForNoInstanceKey) diags = diags.Append(configDiags) diff --git a/terraform/testdata/provider-meta-data-unset/main.tf b/terraform/testdata/provider-meta-data-unset/main.tf new file mode 100644 index 0000000000..c0d8db7d03 --- /dev/null +++ b/terraform/testdata/provider-meta-data-unset/main.tf @@ -0,0 +1,3 @@ +data "test_data_source" "foo" { + foo = "bar" +} diff --git a/terraform/testdata/provider-meta-unset/main.tf b/terraform/testdata/provider-meta-unset/main.tf new file mode 100644 index 0000000000..6eabd177bc --- /dev/null +++ b/terraform/testdata/provider-meta-unset/main.tf @@ -0,0 +1,7 @@ +resource "test_instance" "foo" { + num = 2 +} + +resource "test_instance" "bar" { + foo = "bar" +}