test destroy with provider depending on a resource

This commit is contained in:
James Bardin 2020-07-15 19:15:39 -04:00
parent 79d74c9ba0
commit c0dbc95236
1 changed files with 194 additions and 2 deletions

View File

@ -11372,8 +11372,12 @@ output "myoutput" {
func TestContext2Apply_scaleInCBD(t *testing.T) { func TestContext2Apply_scaleInCBD(t *testing.T) {
m := testModuleInline(t, map[string]string{ m := testModuleInline(t, map[string]string{
"main.tf": ` "main.tf": `
variable "ct" {
type = number
}
resource "test_instance" "a" { resource "test_instance" "a" {
count = 1 count = var.ct
lifecycle { lifecycle {
create_before_destroy = true create_before_destroy = true
} }
@ -11425,6 +11429,12 @@ output "out" {
p.DiffFn = testDiffFn p.DiffFn = testDiffFn
ctx := testContext2(t, &ContextOpts{ ctx := testContext2(t, &ContextOpts{
Variables: InputValues{
"ct": &InputValue{
Value: cty.NumberIntVal(1),
SourceType: ValueFromCaller,
},
},
Config: m, Config: m,
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p), addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
@ -11447,6 +11457,188 @@ output "out" {
// check the output, as those can't cause an error planning the value // check the output, as those can't cause an error planning the value
out := state.RootModule().OutputValues["out"].Value.AsString() out := state.RootModule().OutputValues["out"].Value.AsString()
if out != "a0" { if out != "a0" {
t.Fatalf(`expected output "new", got: %q`, out) t.Fatalf(`expected output "a0", got: %q`, out)
}
// reduce the count to 0
ctx = testContext2(t, &ContextOpts{
Variables: InputValues{
"ct": &InputValue{
Value: cty.NumberIntVal(0),
SourceType: ValueFromCaller,
},
},
Config: m,
Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
},
State: state,
})
_, diags = ctx.Plan()
if diags.HasErrors() {
t.Fatal(diags.ErrWithWarnings())
}
// if resource b isn't going to apply correctly, we will get an error about
// an invalid plan value
state, diags = ctx.Apply()
if diags.HasErrors() {
t.Fatal(diags.ErrWithWarnings())
}
// check the output, as those can't cause an error planning the value
out = state.RootModule().OutputValues["out"].Value.AsString()
if out != "" {
t.Fatalf(`expected output "", got: %q`, out)
}
}
// Ensure that we can destroy when a provider references a resource that will
// also be destroyed
func TestContext2Apply_destroyProviderReference(t *testing.T) {
m := testModuleInline(t, map[string]string{
"main.tf": `
provider "null" {
value = ""
}
module "mod" {
source = "./mod"
}
provider "test" {
value = module.mod.output
}
resource "test_instance" "bar" {
}
`,
"mod/main.tf": `
data "null_data_source" "foo" {
count = 1
}
output "output" {
value = data.null_data_source.foo[0].output
}
`})
schemaFn := func(name string) *ProviderSchema {
return &ProviderSchema{
Provider: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"value": {
Type: cty.String,
Required: true,
},
},
},
ResourceTypes: map[string]*configschema.Block{
name + "_instance": {
Attributes: map[string]*configschema.Attribute{
"id": {
Type: cty.String,
Computed: true,
},
"foo": {
Type: cty.String,
Optional: true,
},
},
},
},
DataSources: map[string]*configschema.Block{
name + "_data_source": {
Attributes: map[string]*configschema.Attribute{
"id": {
Type: cty.String,
Computed: true,
},
"output": {
Type: cty.String,
Computed: true,
},
},
},
},
}
}
testP := new(MockProvider)
testP.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse {
return providers.ReadResourceResponse{NewState: req.PriorState}
}
testP.GetSchemaReturn = schemaFn("test")
providerConfig := ""
testP.ConfigureNewFn = func(req providers.ConfigureRequest) (resp providers.ConfigureResponse) {
value := req.Config.GetAttr("value")
if value.IsKnown() && !value.IsNull() {
providerConfig = value.AsString()
} else {
providerConfig = ""
}
return resp
}
testP.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) {
if providerConfig != "valid" {
return nil, fmt.Errorf("provider config is %q", providerConfig)
}
return testApplyFn(info, s, d)
}
testP.DiffFn = testDiffFn
nullP := new(MockProvider)
nullP.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse {
return providers.ReadResourceResponse{NewState: req.PriorState}
}
nullP.GetSchemaReturn = schemaFn("null")
nullP.ApplyFn = testApplyFn
nullP.DiffFn = testDiffFn
nullP.ReadDataSourceResponse = providers.ReadDataSourceResponse{
State: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("ID"),
"output": cty.StringVal("valid"),
}),
}
ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(testP),
addrs.NewDefaultProvider("null"): testProviderFuncFixed(nullP),
},
})
if _, diags := ctx.Plan(); diags.HasErrors() {
t.Fatalf("plan errors: %s", diags.Err())
}
state, diags := ctx.Apply()
if diags.HasErrors() {
t.Fatalf("apply errors: %s", diags.Err())
}
ctx = testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(testP),
addrs.NewDefaultProvider("null"): testProviderFuncFixed(nullP),
},
State: state,
Destroy: true,
})
if _, diags := ctx.Plan(); diags.HasErrors() {
t.Fatalf("destroy plan errors: %s", diags.Err())
}
if _, diags := ctx.Apply(); diags.HasErrors() {
t.Fatalf("destroy apply errors: %s", diags.Err())
} }
} }