Skip to content

Commit 4451a17

Browse files
authored
Stop the validate node transforming the original config (#34026)
1 parent bdc38b6 commit 4451a17

File tree

2 files changed

+71
-14
lines changed

2 files changed

+71
-14
lines changed

internal/terraform/node_resource_validate.go

+16-10
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,7 @@ func (n *NodeValidatableResource) Execute(ctx EvalContext, op walkOperation) (di
5656
if managed := n.Config.Managed; managed != nil {
5757
// Validate all the provisioners
5858
for _, p := range managed.Provisioners {
59-
if p.Connection == nil {
60-
p.Connection = n.Config.Managed.Connection
61-
} else if n.Config.Managed.Connection != nil {
62-
p.Connection.Config = configs.MergeBodies(n.Config.Managed.Connection.Config, p.Connection.Config)
63-
}
64-
65-
// Validate Provisioner Config
66-
diags = diags.Append(n.validateProvisioner(ctx, p))
59+
diags = diags.Append(n.validateProvisioner(ctx, p, n.Config.Managed.Connection))
6760
if diags.HasErrors() {
6861
return diags
6962
}
@@ -75,7 +68,7 @@ func (n *NodeValidatableResource) Execute(ctx EvalContext, op walkOperation) (di
7568
// validateProvisioner validates the configuration of a provisioner belonging to
7669
// a resource. The provisioner config is expected to contain the merged
7770
// connection configurations.
78-
func (n *NodeValidatableResource) validateProvisioner(ctx EvalContext, p *configs.Provisioner) tfdiags.Diagnostics {
71+
func (n *NodeValidatableResource) validateProvisioner(ctx EvalContext, p *configs.Provisioner, baseConn *configs.Connection) tfdiags.Diagnostics {
7972
var diags tfdiags.Diagnostics
8073

8174
provisioner, err := ctx.Provisioner(p.Type)
@@ -120,8 +113,21 @@ func (n *NodeValidatableResource) validateProvisioner(ctx EvalContext, p *config
120113
// configuration keys that are not valid for *any* communicator, catching
121114
// typos early rather than waiting until we actually try to run one of
122115
// the resource's provisioners.
123-
_, _, connDiags := n.evaluateBlock(ctx, p.Connection.Config, connectionBlockSupersetSchema)
116+
117+
cfg := p.Connection.Config
118+
if baseConn != nil {
119+
// Merge the local config into the base connection config, if we
120+
// both specified.
121+
cfg = configs.MergeBodies(baseConn.Config, cfg)
122+
}
123+
124+
_, _, connDiags := n.evaluateBlock(ctx, cfg, connectionBlockSupersetSchema)
125+
diags = diags.Append(connDiags)
126+
} else if baseConn != nil {
127+
// Just validate the baseConn directly.
128+
_, _, connDiags := n.evaluateBlock(ctx, baseConn.Config, connectionBlockSupersetSchema)
124129
diags = diags.Append(connDiags)
130+
125131
}
126132
return diags
127133
}

internal/terraform/node_resource_validate_test.go

+55-4
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ import (
1010

1111
"github.com/hashicorp/hcl/v2"
1212
"github.com/hashicorp/hcl/v2/hcltest"
13+
"github.com/zclconf/go-cty/cty"
14+
1315
"github.com/hashicorp/terraform/internal/addrs"
1416
"github.com/hashicorp/terraform/internal/configs"
1517
"github.com/hashicorp/terraform/internal/configs/configschema"
1618
"github.com/hashicorp/terraform/internal/lang/marks"
1719
"github.com/hashicorp/terraform/internal/providers"
1820
"github.com/hashicorp/terraform/internal/provisioners"
1921
"github.com/hashicorp/terraform/internal/tfdiags"
20-
"github.com/zclconf/go-cty/cty"
2122
)
2223

2324
func TestNodeValidatableResource_ValidateProvisioner_valid(t *testing.T) {
@@ -54,7 +55,7 @@ func TestNodeValidatableResource_ValidateProvisioner_valid(t *testing.T) {
5455
},
5556
}
5657

57-
diags := node.validateProvisioner(ctx, pc)
58+
diags := node.validateProvisioner(ctx, pc, nil)
5859
if diags.HasErrors() {
5960
t.Fatalf("node.Eval failed: %s", diags.Err())
6061
}
@@ -99,7 +100,7 @@ func TestNodeValidatableResource_ValidateProvisioner__warning(t *testing.T) {
99100
}
100101
}
101102

102-
diags := node.validateProvisioner(ctx, pc)
103+
diags := node.validateProvisioner(ctx, pc, nil)
103104
if len(diags) != 1 {
104105
t.Fatalf("wrong number of diagnostics in %s; want one warning", diags.ErrWithWarnings())
105106
}
@@ -144,7 +145,57 @@ func TestNodeValidatableResource_ValidateProvisioner__connectionInvalid(t *testi
144145
},
145146
}
146147

147-
diags := node.validateProvisioner(ctx, pc)
148+
diags := node.validateProvisioner(ctx, pc, nil)
149+
if !diags.HasErrors() {
150+
t.Fatalf("node.Eval succeeded; want error")
151+
}
152+
if len(diags) != 3 {
153+
t.Fatalf("wrong number of diagnostics; want two errors\n\n%s", diags.Err())
154+
}
155+
156+
errStr := diags.Err().Error()
157+
if !(strings.Contains(errStr, "bananananananana") && strings.Contains(errStr, "bazaz")) {
158+
t.Fatalf("wrong errors %q; want something about each of our invalid connInfo keys", errStr)
159+
}
160+
}
161+
162+
func TestNodeValidatableResource_ValidateProvisioner_baseConnInvalid(t *testing.T) {
163+
ctx := &MockEvalContext{}
164+
ctx.installSimpleEval()
165+
mp := &MockProvisioner{}
166+
ps := &configschema.Block{}
167+
ctx.ProvisionerSchemaSchema = ps
168+
ctx.ProvisionerProvisioner = mp
169+
170+
pc := &configs.Provisioner{
171+
Type: "baz",
172+
Config: hcl.EmptyBody(),
173+
}
174+
175+
baseConn := &configs.Connection{
176+
Config: configs.SynthBody("", map[string]cty.Value{
177+
"type": cty.StringVal("ssh"),
178+
"bananananananana": cty.StringVal("foo"),
179+
"bazaz": cty.StringVal("bar"),
180+
}),
181+
}
182+
183+
rc := &configs.Resource{
184+
Mode: addrs.ManagedResourceMode,
185+
Type: "test_foo",
186+
Name: "bar",
187+
Config: configs.SynthBody("", map[string]cty.Value{}),
188+
Managed: &configs.ManagedResource{},
189+
}
190+
191+
node := NodeValidatableResource{
192+
NodeAbstractResource: &NodeAbstractResource{
193+
Addr: mustConfigResourceAddr("test_foo.bar"),
194+
Config: rc,
195+
},
196+
}
197+
198+
diags := node.validateProvisioner(ctx, pc, baseConn)
148199
if !diags.HasErrors() {
149200
t.Fatalf("node.Eval succeeded; want error")
150201
}

0 commit comments

Comments
 (0)