don't send an invalid config to a provisioner

The config diagnostics weren't checked before sending to the
provisioner, and may have contained invalid values.
This commit is contained in:
James Bardin 2019-09-06 17:40:45 -04:00
parent 72f9385285
commit 102c575f04
3 changed files with 78 additions and 0 deletions

View File

@ -2018,6 +2018,72 @@ aws_instance.foo:
`)
}
// for_each values cannot be used in the provisioner during destroy.
// There may be a way to handle this, but for now make sure we print an error
// rather than crashing with an invalid config.
func TestContext2Apply_provisionerDestroyForEach(t *testing.T) {
m := testModule(t, "apply-provisioner-each")
p := testProvider("aws")
pr := testProvisioner()
p.DiffFn = testDiffFn
p.ApplyFn = testApplyFn
s := &states.State{
Modules: map[string]*states.Module{
"": &states.Module{
Resources: map[string]*states.Resource{
"aws_instance.bar": &states.Resource{
Addr: addrs.Resource{Mode: 77, Type: "aws_instance", Name: "bar"},
EachMode: states.EachMap,
Instances: map[addrs.InstanceKey]*states.ResourceInstance{
addrs.StringKey("a"): &states.ResourceInstance{
Current: &states.ResourceInstanceObjectSrc{
AttrsJSON: []byte(`{"foo":"bar","id":"foo"}`),
},
},
addrs.StringKey("b"): &states.ResourceInstance{
Current: &states.ResourceInstanceObjectSrc{
AttrsJSON: []byte(`{"foo":"bar","id":"foo"}`),
},
},
},
ProviderConfig: addrs.AbsProviderConfig{
Module: addrs.ModuleInstance(nil),
ProviderConfig: addrs.ProviderConfig{Type: "aws", Alias: ""},
},
},
},
},
},
}
ctx := testContext2(t, &ContextOpts{
Config: m,
ProviderResolver: providers.ResolverFixed(
map[string]providers.Factory{
"aws": testProviderFuncFixed(p),
},
),
Provisioners: map[string]ProvisionerFactory{
"shell": testProvisionerFuncFixed(pr),
},
State: s,
Destroy: true,
})
if _, diags := ctx.Plan(); diags.HasErrors() {
t.Fatalf("plan errors: %s", diags.Err())
}
_, diags := ctx.Apply()
if diags == nil {
t.Fatal("should error")
}
if !strings.Contains(diags.Err().Error(), `Reference to "each" in context without for_each`) {
t.Fatal("unexpected error:", diags.Err())
}
}
func TestContext2Apply_cancelProvisioner(t *testing.T) {
m := testModule(t, "apply-cancel-provisioner")
p := testProvider("aws")

View File

@ -557,6 +557,11 @@ func (n *EvalApplyProvisioners) apply(ctx EvalContext, provs []*configs.Provisio
config, _, configDiags := ctx.EvaluateBlock(prov.Config, schema, instanceAddr, keyData)
diags = diags.Append(configDiags)
// we can't apply the provisioner if the config has errors
if diags.HasErrors() {
return diags.Err()
}
// If the provisioner block contains a connection block of its own then
// it can override the base connection configuration, if any.
var localConn hcl.Body

View File

@ -0,0 +1,7 @@
resource "aws_instance" "bar" {
for_each = toset(["a"])
provisioner "shell" {
when = "destroy"
command = "echo ${each.value}"
}
}