Skip to content

Commit c965bd7

Browse files
detect deprecation marks in more places
1 parent 42cee35 commit c965bd7

13 files changed

+194
-9
lines changed

internal/terraform/eval_for_each.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ func (ev *forEachEvaluator) ResourceValue() (map[string]cty.Value, bool, tfdiags
9090
return res, false, diags
9191
}
9292

93+
forEachVal = marks.RemoveDeprecationMarks(forEachVal)
9394
if forEachVal.IsNull() || !forEachVal.IsKnown() || markSafeLengthInt(forEachVal) == 0 {
9495
// we check length, because an empty set returns a nil map which will panic below
9596
return res, true, diags

internal/terraform/node_action_instance.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,10 @@ func (n *NodeActionDeclarationInstance) Execute(ctx EvalContext, _ walkOperation
7171
valDiags := validateResourceForbiddenEphemeralValues(ctx, configVal, n.Schema.ConfigSchema)
7272
diags = diags.Append(valDiags.InConfigBody(n.Config.Config, n.Addr.String()))
7373

74-
if valDiags.HasErrors() {
74+
deprecationDiags := ctx.Deprecations().ValidateAsConfig(configVal, n.ModulePath())
75+
diags = diags.Append(deprecationDiags.InConfigBody(n.Config.Config, n.Addr.String()))
76+
77+
if diags.HasErrors() {
7578
return diags
7679
}
7780
}

internal/terraform/node_action_partialexp.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ func (n *NodeActionDeclarationPartialExpanded) Execute(ctx EvalContext, op walkO
6868
if diags.HasErrors() {
6969
return diags
7070
}
71+
72+
deprecationDiags := ctx.Deprecations().ValidateAsConfig(configVal, n.ActionAddr().Module)
73+
diags = diags.Append(deprecationDiags)
74+
if diags.HasErrors() {
75+
return diags
76+
}
7177
}
7278
ctx.Actions().AddPartialExpandedAction(n.addr, configVal, n.resolvedProvider)
7379
return nil

internal/terraform/node_action_validate.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ func (n *NodeValidatableAction) Execute(ctx EvalContext, _ walkOperation) tfdiag
107107
valDiags = validateResourceForbiddenEphemeralValues(ctx, configVal, schema.ConfigSchema)
108108
diags = diags.Append(valDiags.InConfigBody(config, n.Addr.String()))
109109

110+
if diags.HasErrors() {
111+
return diags
112+
}
113+
110114
// Use unmarked value for validate request
111115
unmarkedConfigVal, _ := configVal.UnmarkDeep()
112116
log.Printf("[TRACE] Validating config for %q", n.Addr)

internal/terraform/node_local.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,5 +237,10 @@ func evaluateLocalValue(config *configs.Local, localAddr addrs.LocalValue, addrS
237237
if val == cty.NilVal {
238238
val = cty.DynamicVal
239239
}
240+
241+
var deprecationDiags tfdiags.Diagnostics
242+
val, deprecationDiags = ctx.Deprecations().Validate(val, ctx.Path().Module(), expr.Range().Ptr())
243+
diags = diags.Append(deprecationDiags)
244+
240245
return val, diags
241246
}

internal/terraform/node_local_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,11 @@ func TestNodeLocalExecute(t *testing.T) {
5959

6060
EvaluateExprResult: test.Want,
6161
}
62+
scopedCtx := ctx.withScope(evalContextModuleInstance{
63+
Addr: addrs.RootModuleInstance,
64+
})
6265

63-
err := n.Execute(ctx, walkApply)
66+
err := n.Execute(scopedCtx, walkApply)
6467
if (err != nil) != test.Err {
6568
if err != nil {
6669
t.Errorf("unexpected error: %s", err)

internal/terraform/node_provider.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,16 @@ func (n *NodeApplyableProvider) ValidateProvider(ctx EvalContext, provider provi
7878
}
7979

8080
configVal, _, evalDiags := ctx.EvaluateBlock(configBody, configSchema, nil, EvalDataForNoInstanceKey)
81-
if evalDiags.HasErrors() {
82-
return diags.Append(evalDiags)
83-
}
8481
diags = diags.Append(evalDiags)
82+
if diags.HasErrors() {
83+
return diags
84+
}
85+
86+
deprecationDiags := ctx.Deprecations().ValidateAsConfig(configVal, n.Addr.Module)
87+
diags = diags.Append(deprecationDiags.InConfigBody(configBody, n.Addr.String()))
88+
if diags.HasErrors() {
89+
return diags
90+
}
8591

8692
// If our config value contains any marked values, ensure those are
8793
// stripped out before sending this to the provider

internal/terraform/node_resource_abstract_instance.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1772,6 +1772,10 @@ func (n *NodeAbstractResourceInstance) providerMetas(ctx EvalContext) (cty.Value
17721772
var configDiags tfdiags.Diagnostics
17731773
metaConfigVal, _, configDiags = ctx.EvaluateBlock(m.Config, providerSchema.ProviderMeta.Body, nil, EvalDataForNoInstanceKey)
17741774
diags = diags.Append(configDiags)
1775+
diags = diags.Append(
1776+
ctx.Deprecations().ValidateAsConfig(metaConfigVal, ctx.Path().Module()).InConfigBody(m.Config, n.Addr.String()),
1777+
)
1778+
metaConfigVal = marks.RemoveDeprecationMarks(metaConfigVal)
17751779
}
17761780
}
17771781
}
@@ -1848,6 +1852,10 @@ func (n *NodeAbstractResourceInstance) planDataSource(ctx EvalContext, checkRule
18481852
diags = diags.Append(
18491853
validateResourceForbiddenEphemeralValues(ctx, configVal, schema.Body).InConfigBody(n.Config.Config, n.Addr.String()),
18501854
)
1855+
diags = diags.Append(
1856+
ctx.Deprecations().ValidateAsConfig(configVal, ctx.Path().Module()).InConfigBody(n.Config.Config, n.Addr.String()),
1857+
)
1858+
configVal = marks.RemoveDeprecationMarks(configVal)
18511859
if diags.HasErrors() {
18521860
return nil, nil, deferred, keyData, diags
18531861
}
@@ -2185,6 +2193,14 @@ func (n *NodeAbstractResourceInstance) applyDataSource(ctx EvalContext, planned
21852193
return nil, keyData, diags
21862194
}
21872195

2196+
diags = diags.Append(
2197+
ctx.Deprecations().ValidateAsConfig(configVal, n.ModulePath()).InConfigBody(n.Config.Config, n.Addr.String()),
2198+
)
2199+
if diags.HasErrors() {
2200+
return nil, keyData, diags
2201+
}
2202+
configVal = marks.RemoveDeprecationMarks(configVal)
2203+
21882204
newVal, readDeferred, readDiags := n.readDataSource(ctx, configVal)
21892205
if check, nested := n.nestedInCheckBlock(); nested {
21902206
addr := check.Addr().Absolute(n.Addr.Module)
@@ -2496,6 +2512,8 @@ func (n *NodeAbstractResourceInstance) evalProvisionerConfig(ctx EvalContext, bo
24962512

24972513
config, _, configDiags := ctx.EvaluateBlock(body, schema, n.ResourceInstanceAddr().Resource, keyData)
24982514
diags = diags.Append(configDiags)
2515+
diags = diags.Append(ctx.Deprecations().ValidateAsConfig(config, n.ModulePath()).InConfigBody(body, n.Addr.String()))
2516+
config = marks.RemoveDeprecationMarks(config)
24992517

25002518
return config, diags
25012519
}
@@ -2513,7 +2531,8 @@ func (n *NodeAbstractResourceInstance) evalDestroyProvisionerConfig(ctx EvalCont
25132531
evalScope := ctx.EvaluationScope(n.ResourceInstanceAddr().Resource, nil, keyData)
25142532
config, evalDiags := evalScope.EvalSelfBlock(body, self, schema, keyData)
25152533
diags = diags.Append(evalDiags)
2516-
2534+
diags = diags.Append(ctx.Deprecations().ValidateAsConfig(config, n.ModulePath()).InConfigBody(body, n.Addr.String()))
2535+
config = marks.RemoveDeprecationMarks(config)
25172536
return config, diags
25182537
}
25192538

internal/terraform/node_resource_ephemeral.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ func ephemeralResourceOpen(ctx EvalContext, inp ephemeralResourceInput) (*provid
7676
if diags.HasErrors() {
7777
return nil, diags
7878
}
79+
diags = diags.Append(ctx.Deprecations().ValidateAsConfig(configVal, ctx.Path().Module()).InConfigBody(config.Config, inp.addr.String()))
80+
if diags.HasErrors() {
81+
return nil, diags
82+
}
83+
7984
unmarkedConfigVal, configMarks := configVal.UnmarkDeepWithPaths()
8085

8186
if !unmarkedConfigVal.IsWhollyKnown() {

internal/terraform/node_resource_plan_instance.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ import (
1515

1616
"github.com/hashicorp/terraform/internal/addrs"
1717
"github.com/hashicorp/terraform/internal/configs"
18+
"github.com/hashicorp/terraform/internal/configs/configschema"
1819
"github.com/hashicorp/terraform/internal/genconfig"
1920
"github.com/hashicorp/terraform/internal/instances"
2021
"github.com/hashicorp/terraform/internal/lang/ephemeral"
2122
"github.com/hashicorp/terraform/internal/moduletest/mocking"
2223
"github.com/hashicorp/terraform/internal/plans"
2324
"github.com/hashicorp/terraform/internal/plans/deferring"
2425
"github.com/hashicorp/terraform/internal/providers"
26+
"github.com/hashicorp/terraform/internal/provisioners"
2527
"github.com/hashicorp/terraform/internal/states"
2628
"github.com/hashicorp/terraform/internal/tfdiags"
2729
)
@@ -347,6 +349,16 @@ func (n *NodePlannableResourceInstance) managedResourceExecute(ctx EvalContext)
347349
repData.EachValue = cty.DynamicVal
348350
}
349351

352+
// Even if we don't run the provisioners during plan we need to make sure they are valid
353+
if n.Config != nil && n.Config.Managed != nil {
354+
for _, p := range n.Config.Managed.Provisioners {
355+
diags = diags.Append(n.validateProvisioner(ctx, p, n.Config.Managed.Connection, repData))
356+
if diags.HasErrors() {
357+
return diags
358+
}
359+
}
360+
}
361+
350362
diags = diags.Append(n.replaceTriggered(ctx, repData))
351363
if diags.HasErrors() {
352364
return diags
@@ -638,6 +650,11 @@ func (n *NodePlannableResourceInstance) importState(ctx EvalContext, addr addrs.
638650
diags = diags.Append(configDiags)
639651
return nil, deferred, diags
640652
}
653+
diags = diags.Append(ctx.Deprecations().ValidateAsConfig(configVal, n.ModulePath()).InConfigBody(n.Config.Config, absAddr.String()))
654+
if diags.HasErrors() {
655+
return nil, deferred, diags
656+
}
657+
641658
configVal, _ = configVal.UnmarkDeep()
642659

643660
// Let's pretend we're reading the value as a data source so we
@@ -1009,6 +1026,75 @@ func (n *NodePlannableResourceInstance) generateResourceConfig(ctx EvalContext,
10091026
return genconfig.ExtractLegacyConfigFromState(schema.Body, state), diags
10101027
}
10111028

1029+
func (n *NodePlannableResourceInstance) validateProvisioner(ctx EvalContext, p *configs.Provisioner, baseConn *configs.Connection, repData instances.RepetitionData) tfdiags.Diagnostics {
1030+
var diags tfdiags.Diagnostics
1031+
provisioner, err := ctx.Provisioner(p.Type)
1032+
if err != nil {
1033+
diags = diags.Append(err)
1034+
return diags
1035+
}
1036+
1037+
if provisioner == nil {
1038+
return diags.Append(fmt.Errorf("provisioner %s not initialized", p.Type))
1039+
}
1040+
provisionerSchema, err := ctx.ProvisionerSchema(p.Type)
1041+
if err != nil {
1042+
return diags.Append(fmt.Errorf("failed to read schema for provisioner %s: %s", p.Type, err))
1043+
}
1044+
if provisionerSchema == nil {
1045+
return diags.Append(fmt.Errorf("provisioner %s has no schema", p.Type))
1046+
}
1047+
1048+
// Validate the provisioner's own config first
1049+
configVal, _, configDiags := n.evaluateBlock(ctx, p.Config, provisionerSchema, repData)
1050+
diags = diags.Append(configDiags)
1051+
1052+
if configVal == cty.NilVal {
1053+
// Should never happen for a well-behaved EvaluateBlock implementation
1054+
return diags.Append(fmt.Errorf("EvaluateBlock returned nil value"))
1055+
}
1056+
1057+
// Use unmarked value for validate request
1058+
unmarkedConfigVal, _ := configVal.UnmarkDeep()
1059+
req := provisioners.ValidateProvisionerConfigRequest{
1060+
Config: unmarkedConfigVal,
1061+
}
1062+
1063+
resp := provisioner.ValidateProvisionerConfig(req)
1064+
diags = diags.Append(resp.Diagnostics)
1065+
1066+
if p.Connection != nil {
1067+
// We can't comprehensively validate the connection config since its
1068+
// final structure is decided by the communicator and we can't instantiate
1069+
// that until we have a complete instance state. However, we *can* catch
1070+
// configuration keys that are not valid for *any* communicator, catching
1071+
// typos early rather than waiting until we actually try to run one of
1072+
// the resource's provisioners.
1073+
1074+
cfg := p.Connection.Config
1075+
if baseConn != nil {
1076+
// Merge the local config into the base connection config, if we
1077+
// both specified.
1078+
cfg = configs.MergeBodies(baseConn.Config, cfg)
1079+
}
1080+
1081+
_, _, connDiags := n.evaluateBlock(ctx, cfg, connectionBlockSupersetSchema, repData)
1082+
diags = diags.Append(connDiags)
1083+
} else if baseConn != nil {
1084+
// Just validate the baseConn directly.
1085+
_, _, connDiags := n.evaluateBlock(ctx, baseConn.Config, connectionBlockSupersetSchema, repData)
1086+
diags = diags.Append(connDiags)
1087+
1088+
}
1089+
return diags
1090+
}
1091+
1092+
func (n *NodePlannableResourceInstance) evaluateBlock(ctx EvalContext, body hcl.Body, schema *configschema.Block, keyData instances.RepetitionData) (cty.Value, hcl.Body, tfdiags.Diagnostics) {
1093+
val, hclBody, diags := ctx.EvaluateBlock(body, schema, n.Addr.Resource, keyData)
1094+
diags = diags.Append(ctx.Deprecations().ValidateAsConfig(val, n.ModulePath()).InConfigBody(body, n.Addr.String()))
1095+
return val, hclBody, diags
1096+
}
1097+
10121098
// mergeDeps returns the union of 2 sets of dependencies
10131099
func mergeDeps(a, b []addrs.ConfigResource) []addrs.ConfigResource {
10141100
switch {

0 commit comments

Comments
 (0)