terraform: enable self vars

This commit is contained in:
Mitchell Hashimoto 2015-02-23 14:56:02 -08:00
parent 965fe45b9e
commit 0e59acc2c9
6 changed files with 92 additions and 2 deletions

View File

@ -3766,6 +3766,52 @@ func TestContext2Apply_provisionerResourceRef(t *testing.T) {
}
}
func TestContext2Apply_provisionerSelfRef(t *testing.T) {
m := testModule(t, "apply-provisioner-self-ref")
p := testProvider("aws")
pr := testProvisioner()
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
val, ok := c.Config["command"]
if !ok || val != "bar" {
t.Fatalf("bad value for command: %v %#v", val, c)
}
return nil
}
ctx := testContext2(t, &ContextOpts{
Module: m,
Providers: map[string]ResourceProviderFactory{
"aws": testProviderFuncFixed(p),
},
Provisioners: map[string]ResourceProvisionerFactory{
"shell": testProvisionerFuncFixed(pr),
},
})
if _, err := ctx.Plan(nil); err != nil {
t.Fatalf("err: %s", err)
}
state, err := ctx.Apply()
if err != nil {
t.Fatalf("err: %s", err)
}
actual := strings.TrimSpace(state.String())
expected := strings.TrimSpace(testTerraformApplyProvisionerSelfRefStr)
if actual != expected {
t.Fatalf("bad: \n%s", actual)
}
// Verify apply was invoked
if !pr.ApplyCalled {
t.Fatalf("provisioner not invoked")
}
}
// Provisioner should NOT run on a diff, only create
func TestContext2Apply_Provisioner_Diff(t *testing.T) {
m := testModule(t, "apply-provisioner-diff")

View File

@ -62,6 +62,8 @@ func (i *Interpolater) Values(
err = i.valuePathVar(scope, n, v, result)
case *config.ResourceVariable:
err = i.valueResourceVar(scope, n, v, result)
case *config.SelfVariable:
err = i.valueSelfVar(scope, n, v, result)
case *config.UserVariable:
err = i.valueUserVar(scope, n, v, result)
default:
@ -217,6 +219,24 @@ func (i *Interpolater) valueResourceVar(
return nil
}
func (i *Interpolater) valueSelfVar(
scope *InterpolationScope,
n string,
v *config.SelfVariable,
result map[string]ast.Variable) error {
rv, err := config.NewResourceVariable(fmt.Sprintf(
"%s.%s.%d.%s",
scope.Resource.Type,
scope.Resource.Name,
scope.Resource.CountIndex,
v.Field))
if err != nil {
return err
}
return i.valueResourceVar(scope, n, rv, result)
}
func (i *Interpolater) valueUserVar(
scope *InterpolationScope,
n string,

View File

@ -26,6 +26,13 @@ type ResourceProvisionerConfig struct {
// its current state, and potentially a desired diff from the state it
// wants to reach.
type Resource struct {
// These are all used by the new EvalNode stuff.
Name string
Type string
CountIndex int
// These aren't really used anymore anywhere, but we keep them around
// since we haven't done a proper cleanup yet.
Id string
Info *InstanceInfo
Config *ResourceConfig
@ -34,7 +41,6 @@ type Resource struct {
Provider ResourceProvider
State *InstanceState
Provisioners []*ResourceProvisionerConfig
CountIndex int
Flags ResourceFlag
TaintedIndex int
}

View File

@ -359,6 +359,13 @@ aws_instance.bar:
type = aws_instance
`
const testTerraformApplyProvisionerSelfRefStr = `
aws_instance.foo:
ID = foo
foo = bar
type = aws_instance
`
const testTerraformApplyProvisionerDiffStr = `
aws_instance.bar:
ID = foo

View File

@ -0,0 +1,7 @@
resource "aws_instance" "foo" {
foo = "bar"
provisioner "shell" {
command = "${self.foo}"
}
}

View File

@ -109,7 +109,11 @@ func (n *graphNodeExpandedResource) EvalTree() EvalNode {
if index < 0 {
index = 0
}
resource := &Resource{CountIndex: index}
resource := &Resource{
Name: n.Resource.Name,
Type: n.Resource.Type,
CountIndex: index,
}
seq := &EvalSequence{Nodes: make([]EvalNode, 0, 5)}