Skip to content

Commit 3aedb8e

Browse files
Liam Cervantegenx7up
authored andcommitted
Add support for scoped resources (hashicorp#32732)
1 parent 7cd34f8 commit 3aedb8e

20 files changed

+78
-37
lines changed

internal/configs/container.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package configs
2+
3+
import "github.com/hashicorp/terraform/internal/addrs"
4+
5+
// Container provides an interface for scoped resources.
6+
//
7+
// Any resources contained within a Container should not be accessible from
8+
// outside the container.
9+
type Container interface {
10+
// Accessible should return true if the resource specified by addr can
11+
// reference other items within this Container.
12+
//
13+
// Typically, that means that addr will either be the container itself or
14+
// something within the container.
15+
Accessible(addr addrs.Referenceable) bool
16+
}

internal/configs/resource.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ type Resource struct {
3737
// For all other resource modes, this field is nil.
3838
Managed *ManagedResource
3939

40+
// Container links a scoped resource back up to the resources that contains
41+
// it. This field is referenced during static analysis to check whether any
42+
// references are also made from within the same container.
43+
//
44+
// If this is nil, then this resource is essentially public.
45+
Container Container
46+
4047
DeclRange hcl.Range
4148
TypeRange hcl.Range
4249
}

internal/lang/data.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020
// cases where it's not possible to even determine a suitable result type,
2121
// cty.DynamicVal is returned along with errors describing the problem.
2222
type Data interface {
23-
StaticValidateReferences(refs []*addrs.Reference, self addrs.Referenceable) tfdiags.Diagnostics
23+
StaticValidateReferences(refs []*addrs.Reference, self addrs.Referenceable, source addrs.Referenceable) tfdiags.Diagnostics
2424

2525
GetCountAttr(addrs.CountAttr, tfdiags.SourceRange) (cty.Value, tfdiags.Diagnostics)
2626
GetForEachAttr(addrs.ForEachAttr, tfdiags.SourceRange) (cty.Value, tfdiags.Diagnostics)

internal/lang/data_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ type dataForTests struct {
1919

2020
var _ Data = &dataForTests{}
2121

22-
func (d *dataForTests) StaticValidateReferences(refs []*addrs.Reference, self addrs.Referenceable) tfdiags.Diagnostics {
22+
func (d *dataForTests) StaticValidateReferences(refs []*addrs.Reference, self addrs.Referenceable, source addrs.Referenceable) tfdiags.Diagnostics {
2323
return nil // does nothing in this stub implementation
2424
}
2525

internal/lang/eval.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ func (s *Scope) evalContext(refs []*addrs.Reference, selfAddr addrs.Referenceabl
259259
// First we'll do static validation of the references. This catches things
260260
// early that might otherwise not get caught due to unknown values being
261261
// present in the scope during planning.
262-
staticDiags := s.Data.StaticValidateReferences(refs, selfAddr)
262+
staticDiags := s.Data.StaticValidateReferences(refs, selfAddr, s.SourceAddr)
263263
diags = diags.Append(staticDiags)
264264
if staticDiags.HasErrors() {
265265
return ctx, diags

internal/lang/scope.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ type Scope struct {
2020
// or nil if the "self" object should not be available at all.
2121
SelfAddr addrs.Referenceable
2222

23+
// SourceAddr is the address of the source item for the scope. This will
24+
// affect any scoped resources that can be accessed from within this scope.
25+
//
26+
// If nil, access is assumed to be at the module level. So, in practice this
27+
// only needs to be set for items that should be able to access something
28+
// hidden in their own scope.
29+
SourceAddr addrs.Referenceable
30+
2331
// BaseDir is the base directory used by any interpolation functions that
2432
// accept filesystem paths as arguments.
2533
BaseDir string

internal/terraform/context_eval.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,5 +92,5 @@ func (c *Context) Eval(config *configs.Config, state *states.State, moduleAddr a
9292
// caches its contexts, so we should get hold of the context that was
9393
// previously used for evaluation here, unless we skipped walking.
9494
evalCtx := walker.EnterPath(moduleAddr)
95-
return evalCtx.EvaluationScope(nil, EvalDataForNoInstanceKey), diags
95+
return evalCtx.EvaluationScope(nil, nil, EvalDataForNoInstanceKey), diags
9696
}

internal/terraform/eval_conditions.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func evalCheckRule(typ addrs.CheckType, rule *configs.CheckRule, ctx EvalContext
8787
panic(fmt.Sprintf("Invalid self reference type %t", self))
8888
}
8989
}
90-
scope := ctx.EvaluationScope(selfReference, keyData)
90+
scope := ctx.EvaluationScope(selfReference, nil, keyData)
9191

9292
hclCtx, moreDiags := scope.EvalContext(refs)
9393
diags = diags.Append(moreDiags)

internal/terraform/eval_context.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ type EvalContext interface {
125125

126126
// EvaluationScope returns a scope that can be used to evaluate reference
127127
// addresses in this context.
128-
EvaluationScope(self addrs.Referenceable, keyData InstanceKeyEvalData) *lang.Scope
128+
EvaluationScope(self addrs.Referenceable, source addrs.Referenceable, keyData InstanceKeyEvalData) *lang.Scope
129129

130130
// SetRootModuleArgument defines the value for one variable of the root
131131
// module. The caller must ensure that given value is a suitable

internal/terraform/eval_context_builtin.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ func (ctx *BuiltinEvalContext) CloseProvisioners() error {
270270

271271
func (ctx *BuiltinEvalContext) EvaluateBlock(body hcl.Body, schema *configschema.Block, self addrs.Referenceable, keyData InstanceKeyEvalData) (cty.Value, hcl.Body, tfdiags.Diagnostics) {
272272
var diags tfdiags.Diagnostics
273-
scope := ctx.EvaluationScope(self, keyData)
273+
scope := ctx.EvaluationScope(self, nil, keyData)
274274
body, evalDiags := scope.ExpandBlock(body, schema)
275275
diags = diags.Append(evalDiags)
276276
val, evalDiags := scope.EvalBlock(body, schema)
@@ -279,7 +279,7 @@ func (ctx *BuiltinEvalContext) EvaluateBlock(body hcl.Body, schema *configschema
279279
}
280280

281281
func (ctx *BuiltinEvalContext) EvaluateExpr(expr hcl.Expression, wantType cty.Type, self addrs.Referenceable) (cty.Value, tfdiags.Diagnostics) {
282-
scope := ctx.EvaluationScope(self, EvalDataForNoInstanceKey)
282+
scope := ctx.EvaluationScope(self, nil, EvalDataForNoInstanceKey)
283283
return scope.EvalExpr(expr, wantType)
284284
}
285285

@@ -397,7 +397,7 @@ func (ctx *BuiltinEvalContext) EvaluateReplaceTriggeredBy(expr hcl.Expression, r
397397
return ref, replace, diags
398398
}
399399

400-
func (ctx *BuiltinEvalContext) EvaluationScope(self addrs.Referenceable, keyData instances.RepetitionData) *lang.Scope {
400+
func (ctx *BuiltinEvalContext) EvaluationScope(self addrs.Referenceable, source addrs.Referenceable, keyData InstanceKeyEvalData) *lang.Scope {
401401
if !ctx.pathSet {
402402
panic("context path not set")
403403
}
@@ -407,7 +407,7 @@ func (ctx *BuiltinEvalContext) EvaluationScope(self addrs.Referenceable, keyData
407407
InstanceKeyData: keyData,
408408
Operation: ctx.Evaluator.Operation,
409409
}
410-
scope := ctx.Evaluator.Scope(data, self)
410+
scope := ctx.Evaluator.Scope(data, self, source)
411411

412412
// ctx.PathValue is the path of the module that contains whatever
413413
// expression the caller will be trying to evaluate, so this will

0 commit comments

Comments
 (0)