mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-26 00:41:27 -06:00
terraform: count.index
This commit is contained in:
parent
2e63a69e57
commit
ea18b62e8f
@ -498,7 +498,7 @@ func (c *walkContext) Walk() error {
|
||||
|
||||
outputs := make(map[string]string)
|
||||
for _, o := range conf.Outputs {
|
||||
if err := c.computeVars(o.RawConfig); err != nil {
|
||||
if err := c.computeVars(o.RawConfig, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
vraw := o.RawConfig.Config()["value"]
|
||||
@ -619,7 +619,7 @@ func (c *walkContext) applyWalkFn() depgraph.WalkFunc {
|
||||
|
||||
if !diff.Destroy {
|
||||
// Since we need the configuration, interpolate the variables
|
||||
if err := r.Config.interpolate(c); err != nil {
|
||||
if err := r.Config.interpolate(c, r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -780,7 +780,7 @@ func (c *walkContext) planWalkFn() depgraph.WalkFunc {
|
||||
diff = &InstanceDiff{Destroy: true}
|
||||
} else {
|
||||
// Make sure the configuration is interpolated
|
||||
if err := r.Config.interpolate(c); err != nil {
|
||||
if err := r.Config.interpolate(c, r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -993,7 +993,7 @@ func (c *walkContext) validateWalkFn() depgraph.WalkFunc {
|
||||
if rn.ExpandMode > ResourceExpandNone {
|
||||
// Interpolate the count and verify it is non-negative
|
||||
rc := NewResourceConfig(rn.Config.RawCount)
|
||||
rc.interpolate(c)
|
||||
rc.interpolate(c, rn.Resource)
|
||||
count, err := rn.Config.Count()
|
||||
if err == nil {
|
||||
if count < 0 {
|
||||
@ -1063,7 +1063,7 @@ func (c *walkContext) validateWalkFn() depgraph.WalkFunc {
|
||||
for k, p := range sharedProvider.Providers {
|
||||
// Merge the configurations to get what we use to configure with
|
||||
rc := sharedProvider.MergeConfig(false, cs[k])
|
||||
rc.interpolate(c)
|
||||
rc.interpolate(c, nil)
|
||||
|
||||
log.Printf("[INFO] Validating provider: %s", k)
|
||||
ws, es := p.Validate(rc)
|
||||
@ -1125,7 +1125,7 @@ func (c *walkContext) genericWalkFn(cb genericWalkFunc) depgraph.WalkFunc {
|
||||
wc.Variables = make(map[string]string)
|
||||
|
||||
rc := NewResourceConfig(m.Config.RawConfig)
|
||||
rc.interpolate(c)
|
||||
rc.interpolate(c, nil)
|
||||
for k, v := range rc.Config {
|
||||
wc.Variables[k] = v.(string)
|
||||
}
|
||||
@ -1151,7 +1151,7 @@ func (c *walkContext) genericWalkFn(cb genericWalkFunc) depgraph.WalkFunc {
|
||||
for k, p := range sharedProvider.Providers {
|
||||
// Merge the configurations to get what we use to configure with
|
||||
rc := sharedProvider.MergeConfig(false, cs[k])
|
||||
rc.interpolate(c)
|
||||
rc.interpolate(c, nil)
|
||||
|
||||
log.Printf("[INFO] Configuring provider: %s", k)
|
||||
err := p.Configure(rc)
|
||||
@ -1211,7 +1211,7 @@ func (c *walkContext) genericWalkResource(
|
||||
rn *GraphNodeResource, fn depgraph.WalkFunc) error {
|
||||
// Interpolate the count
|
||||
rc := NewResourceConfig(rn.Config.RawCount)
|
||||
rc.interpolate(c)
|
||||
rc.interpolate(c, rn.Resource)
|
||||
|
||||
// Expand the node to the actual resources
|
||||
ns, err := rn.Expand()
|
||||
@ -1260,13 +1260,13 @@ func (c *walkContext) applyProvisioners(r *Resource, is *InstanceState) error {
|
||||
for _, prov := range r.Provisioners {
|
||||
// Interpolate since we may have variables that depend on the
|
||||
// local resource.
|
||||
if err := prov.Config.interpolate(c); err != nil {
|
||||
if err := prov.Config.interpolate(c, r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Interpolate the conn info, since it may contain variables
|
||||
connInfo := NewResourceConfig(prov.ConnInfo)
|
||||
if err := connInfo.interpolate(c); err != nil {
|
||||
if err := connInfo.interpolate(c, r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -1396,7 +1396,8 @@ func (c *walkContext) persistState(r *Resource) {
|
||||
// computeVars takes the State and given RawConfig and processes all
|
||||
// the variables. This dynamically discovers the attributes instead of
|
||||
// using a static map[string]string that the genericWalkFn uses.
|
||||
func (c *walkContext) computeVars(raw *config.RawConfig) error {
|
||||
func (c *walkContext) computeVars(
|
||||
raw *config.RawConfig, r *Resource) error {
|
||||
// If there isn't a raw configuration, don't do anything
|
||||
if raw == nil {
|
||||
return nil
|
||||
@ -1411,6 +1412,11 @@ func (c *walkContext) computeVars(raw *config.RawConfig) error {
|
||||
// Next, the actual computed variables
|
||||
for n, rawV := range raw.Variables {
|
||||
switch v := rawV.(type) {
|
||||
case *config.CountVariable:
|
||||
switch v.Type {
|
||||
case config.CountValueIndex:
|
||||
vs[n] = strconv.FormatInt(int64(r.CountIndex), 10)
|
||||
}
|
||||
case *config.ModuleVariable:
|
||||
value, err := c.computeModuleVariable(v)
|
||||
if err != nil {
|
||||
|
@ -2464,6 +2464,29 @@ func TestContextPlan_countComputed(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestContextPlan_countIndex(t *testing.T) {
|
||||
m := testModule(t, "plan-count-index")
|
||||
p := testProvider("aws")
|
||||
p.DiffFn = testDiffFn
|
||||
ctx := testContext(t, &ContextOpts{
|
||||
Module: m,
|
||||
Providers: map[string]ResourceProviderFactory{
|
||||
"aws": testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
|
||||
plan, err := ctx.Plan(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
actual := strings.TrimSpace(plan.String())
|
||||
expected := strings.TrimSpace(testTerraformPlanCountIndexStr)
|
||||
if actual != expected {
|
||||
t.Fatalf("bad:\n%s", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestContextPlan_countVar(t *testing.T) {
|
||||
m := testModule(t, "plan-count-var")
|
||||
p := testProvider("aws")
|
||||
|
@ -1704,6 +1704,7 @@ func (n *GraphNodeResource) expand(g *depgraph.Graph, count int) {
|
||||
|
||||
// Copy the base resource so we can fill it in
|
||||
resource := n.copyResource(name)
|
||||
resource.CountIndex = i
|
||||
resource.State = state.Primary
|
||||
resource.Flags = flags
|
||||
|
||||
|
@ -34,6 +34,7 @@ type Resource struct {
|
||||
Provider ResourceProvider
|
||||
State *InstanceState
|
||||
Provisioners []*ResourceProvisionerConfig
|
||||
CountIndex int
|
||||
Flags ResourceFlag
|
||||
TaintedIndex int
|
||||
}
|
||||
@ -92,7 +93,7 @@ type ResourceConfig struct {
|
||||
// NewResourceConfig creates a new ResourceConfig from a config.RawConfig.
|
||||
func NewResourceConfig(c *config.RawConfig) *ResourceConfig {
|
||||
result := &ResourceConfig{raw: c}
|
||||
result.interpolate(nil)
|
||||
result.interpolate(nil, nil)
|
||||
return result
|
||||
}
|
||||
|
||||
@ -190,13 +191,14 @@ func (c *ResourceConfig) get(
|
||||
return current, true
|
||||
}
|
||||
|
||||
func (c *ResourceConfig) interpolate(ctx *walkContext) error {
|
||||
func (c *ResourceConfig) interpolate(
|
||||
ctx *walkContext, r *Resource) error {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if ctx != nil {
|
||||
if err := ctx.computeVars(c.raw); err != nil {
|
||||
if err := ctx.computeVars(c.raw, r); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +102,10 @@ func TestResourceConfigGet(t *testing.T) {
|
||||
rc := NewResourceConfig(rawC)
|
||||
if tc.Vars != nil {
|
||||
ctx := NewContext(&ContextOpts{Variables: tc.Vars})
|
||||
if err := rc.interpolate(ctx.walkContext(walkInvalid, rootModulePath)); err != nil {
|
||||
err := rc.interpolate(
|
||||
ctx.walkContext(walkInvalid, rootModulePath),
|
||||
nil)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
@ -477,6 +477,21 @@ STATE:
|
||||
<no state>
|
||||
`
|
||||
|
||||
const testTerraformPlanCountIndexStr = `
|
||||
DIFF:
|
||||
|
||||
CREATE: aws_instance.foo.0
|
||||
foo: "" => "0"
|
||||
type: "" => "aws_instance"
|
||||
CREATE: aws_instance.foo.1
|
||||
foo: "" => "1"
|
||||
type: "" => "aws_instance"
|
||||
|
||||
STATE:
|
||||
|
||||
<no state>
|
||||
`
|
||||
|
||||
const testTerraformPlanCountOneIndexStr = `
|
||||
DIFF:
|
||||
|
||||
|
4
terraform/test-fixtures/plan-count-index/main.tf
Normal file
4
terraform/test-fixtures/plan-count-index/main.tf
Normal file
@ -0,0 +1,4 @@
|
||||
resource "aws_instance" "foo" {
|
||||
count = 2
|
||||
foo = "${count.index}"
|
||||
}
|
Loading…
Reference in New Issue
Block a user