Skip to content

Commit ea18b62

Browse files
committed
terraform: count.index
1 parent 2e63a69 commit ea18b62

7 files changed

Lines changed: 69 additions & 15 deletions

File tree

terraform/context.go

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ func (c *walkContext) Walk() error {
498498

499499
outputs := make(map[string]string)
500500
for _, o := range conf.Outputs {
501-
if err := c.computeVars(o.RawConfig); err != nil {
501+
if err := c.computeVars(o.RawConfig, nil); err != nil {
502502
return err
503503
}
504504
vraw := o.RawConfig.Config()["value"]
@@ -619,7 +619,7 @@ func (c *walkContext) applyWalkFn() depgraph.WalkFunc {
619619

620620
if !diff.Destroy {
621621
// Since we need the configuration, interpolate the variables
622-
if err := r.Config.interpolate(c); err != nil {
622+
if err := r.Config.interpolate(c, r); err != nil {
623623
return err
624624
}
625625

@@ -780,7 +780,7 @@ func (c *walkContext) planWalkFn() depgraph.WalkFunc {
780780
diff = &InstanceDiff{Destroy: true}
781781
} else {
782782
// Make sure the configuration is interpolated
783-
if err := r.Config.interpolate(c); err != nil {
783+
if err := r.Config.interpolate(c, r); err != nil {
784784
return err
785785
}
786786

@@ -993,7 +993,7 @@ func (c *walkContext) validateWalkFn() depgraph.WalkFunc {
993993
if rn.ExpandMode > ResourceExpandNone {
994994
// Interpolate the count and verify it is non-negative
995995
rc := NewResourceConfig(rn.Config.RawCount)
996-
rc.interpolate(c)
996+
rc.interpolate(c, rn.Resource)
997997
count, err := rn.Config.Count()
998998
if err == nil {
999999
if count < 0 {
@@ -1063,7 +1063,7 @@ func (c *walkContext) validateWalkFn() depgraph.WalkFunc {
10631063
for k, p := range sharedProvider.Providers {
10641064
// Merge the configurations to get what we use to configure with
10651065
rc := sharedProvider.MergeConfig(false, cs[k])
1066-
rc.interpolate(c)
1066+
rc.interpolate(c, nil)
10671067

10681068
log.Printf("[INFO] Validating provider: %s", k)
10691069
ws, es := p.Validate(rc)
@@ -1125,7 +1125,7 @@ func (c *walkContext) genericWalkFn(cb genericWalkFunc) depgraph.WalkFunc {
11251125
wc.Variables = make(map[string]string)
11261126

11271127
rc := NewResourceConfig(m.Config.RawConfig)
1128-
rc.interpolate(c)
1128+
rc.interpolate(c, nil)
11291129
for k, v := range rc.Config {
11301130
wc.Variables[k] = v.(string)
11311131
}
@@ -1151,7 +1151,7 @@ func (c *walkContext) genericWalkFn(cb genericWalkFunc) depgraph.WalkFunc {
11511151
for k, p := range sharedProvider.Providers {
11521152
// Merge the configurations to get what we use to configure with
11531153
rc := sharedProvider.MergeConfig(false, cs[k])
1154-
rc.interpolate(c)
1154+
rc.interpolate(c, nil)
11551155

11561156
log.Printf("[INFO] Configuring provider: %s", k)
11571157
err := p.Configure(rc)
@@ -1211,7 +1211,7 @@ func (c *walkContext) genericWalkResource(
12111211
rn *GraphNodeResource, fn depgraph.WalkFunc) error {
12121212
// Interpolate the count
12131213
rc := NewResourceConfig(rn.Config.RawCount)
1214-
rc.interpolate(c)
1214+
rc.interpolate(c, rn.Resource)
12151215

12161216
// Expand the node to the actual resources
12171217
ns, err := rn.Expand()
@@ -1260,13 +1260,13 @@ func (c *walkContext) applyProvisioners(r *Resource, is *InstanceState) error {
12601260
for _, prov := range r.Provisioners {
12611261
// Interpolate since we may have variables that depend on the
12621262
// local resource.
1263-
if err := prov.Config.interpolate(c); err != nil {
1263+
if err := prov.Config.interpolate(c, r); err != nil {
12641264
return err
12651265
}
12661266

12671267
// Interpolate the conn info, since it may contain variables
12681268
connInfo := NewResourceConfig(prov.ConnInfo)
1269-
if err := connInfo.interpolate(c); err != nil {
1269+
if err := connInfo.interpolate(c, r); err != nil {
12701270
return err
12711271
}
12721272

@@ -1396,7 +1396,8 @@ func (c *walkContext) persistState(r *Resource) {
13961396
// computeVars takes the State and given RawConfig and processes all
13971397
// the variables. This dynamically discovers the attributes instead of
13981398
// using a static map[string]string that the genericWalkFn uses.
1399-
func (c *walkContext) computeVars(raw *config.RawConfig) error {
1399+
func (c *walkContext) computeVars(
1400+
raw *config.RawConfig, r *Resource) error {
14001401
// If there isn't a raw configuration, don't do anything
14011402
if raw == nil {
14021403
return nil
@@ -1411,6 +1412,11 @@ func (c *walkContext) computeVars(raw *config.RawConfig) error {
14111412
// Next, the actual computed variables
14121413
for n, rawV := range raw.Variables {
14131414
switch v := rawV.(type) {
1415+
case *config.CountVariable:
1416+
switch v.Type {
1417+
case config.CountValueIndex:
1418+
vs[n] = strconv.FormatInt(int64(r.CountIndex), 10)
1419+
}
14141420
case *config.ModuleVariable:
14151421
value, err := c.computeModuleVariable(v)
14161422
if err != nil {

terraform/context_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2464,6 +2464,29 @@ func TestContextPlan_countComputed(t *testing.T) {
24642464
}
24652465
}
24662466

2467+
func TestContextPlan_countIndex(t *testing.T) {
2468+
m := testModule(t, "plan-count-index")
2469+
p := testProvider("aws")
2470+
p.DiffFn = testDiffFn
2471+
ctx := testContext(t, &ContextOpts{
2472+
Module: m,
2473+
Providers: map[string]ResourceProviderFactory{
2474+
"aws": testProviderFuncFixed(p),
2475+
},
2476+
})
2477+
2478+
plan, err := ctx.Plan(nil)
2479+
if err != nil {
2480+
t.Fatalf("err: %s", err)
2481+
}
2482+
2483+
actual := strings.TrimSpace(plan.String())
2484+
expected := strings.TrimSpace(testTerraformPlanCountIndexStr)
2485+
if actual != expected {
2486+
t.Fatalf("bad:\n%s", actual)
2487+
}
2488+
}
2489+
24672490
func TestContextPlan_countVar(t *testing.T) {
24682491
m := testModule(t, "plan-count-var")
24692492
p := testProvider("aws")

terraform/graph.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1704,6 +1704,7 @@ func (n *GraphNodeResource) expand(g *depgraph.Graph, count int) {
17041704

17051705
// Copy the base resource so we can fill it in
17061706
resource := n.copyResource(name)
1707+
resource.CountIndex = i
17071708
resource.State = state.Primary
17081709
resource.Flags = flags
17091710

terraform/resource.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type Resource struct {
3434
Provider ResourceProvider
3535
State *InstanceState
3636
Provisioners []*ResourceProvisionerConfig
37+
CountIndex int
3738
Flags ResourceFlag
3839
TaintedIndex int
3940
}
@@ -92,7 +93,7 @@ type ResourceConfig struct {
9293
// NewResourceConfig creates a new ResourceConfig from a config.RawConfig.
9394
func NewResourceConfig(c *config.RawConfig) *ResourceConfig {
9495
result := &ResourceConfig{raw: c}
95-
result.interpolate(nil)
96+
result.interpolate(nil, nil)
9697
return result
9798
}
9899

@@ -190,13 +191,14 @@ func (c *ResourceConfig) get(
190191
return current, true
191192
}
192193

193-
func (c *ResourceConfig) interpolate(ctx *walkContext) error {
194+
func (c *ResourceConfig) interpolate(
195+
ctx *walkContext, r *Resource) error {
194196
if c == nil {
195197
return nil
196198
}
197199

198200
if ctx != nil {
199-
if err := ctx.computeVars(c.raw); err != nil {
201+
if err := ctx.computeVars(c.raw, r); err != nil {
200202
return err
201203
}
202204
}

terraform/resource_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,10 @@ func TestResourceConfigGet(t *testing.T) {
102102
rc := NewResourceConfig(rawC)
103103
if tc.Vars != nil {
104104
ctx := NewContext(&ContextOpts{Variables: tc.Vars})
105-
if err := rc.interpolate(ctx.walkContext(walkInvalid, rootModulePath)); err != nil {
105+
err := rc.interpolate(
106+
ctx.walkContext(walkInvalid, rootModulePath),
107+
nil)
108+
if err != nil {
106109
t.Fatalf("err: %s", err)
107110
}
108111
}

terraform/terraform_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,21 @@ STATE:
477477
<no state>
478478
`
479479

480+
const testTerraformPlanCountIndexStr = `
481+
DIFF:
482+
483+
CREATE: aws_instance.foo.0
484+
foo: "" => "0"
485+
type: "" => "aws_instance"
486+
CREATE: aws_instance.foo.1
487+
foo: "" => "1"
488+
type: "" => "aws_instance"
489+
490+
STATE:
491+
492+
<no state>
493+
`
494+
480495
const testTerraformPlanCountOneIndexStr = `
481496
DIFF:
482497
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
resource "aws_instance" "foo" {
2+
count = 2
3+
foo = "${count.index}"
4+
}

0 commit comments

Comments
 (0)