diff --git a/terraform/context.go b/terraform/context.go index beb080447..15528beed 100644 --- a/terraform/context.go +++ b/terraform/context.go @@ -49,6 +49,7 @@ var ( // ContextOpts are the user-configurable options to create a context with // NewContext. type ContextOpts struct { + Meta *ContextMeta Destroy bool Diff *Diff Hooks []Hook @@ -65,6 +66,14 @@ type ContextOpts struct { UIInput UIInput } +// ContextMeta is metadata about the running context. This is information +// that this package or structure cannot determine on its own but exposes +// into Terraform in various ways. This must be provided by the Context +// initializer. +type ContextMeta struct { + Env string // Env is the state environment +} + // Context represents all the context that Terraform needs in order to // perform operations on infrastructure. This structure is built using // NewContext. See the documentation for that. @@ -80,6 +89,7 @@ type Context struct { diff *Diff diffLock sync.RWMutex hooks []Hook + meta *ContextMeta module *module.Tree sh *stopHook shadow bool @@ -178,6 +188,7 @@ func NewContext(opts *ContextOpts) (*Context, error) { destroy: opts.Destroy, diff: diff, hooks: hooks, + meta: opts.Meta, module: opts.Module, shadow: opts.Shadow, state: state, @@ -313,6 +324,7 @@ func (c *Context) Interpolater() *Interpolater { var stateLock sync.RWMutex return &Interpolater{ Operation: walkApply, + Meta: c.meta, Module: c.module, State: c.state.DeepCopy(), StateLock: &stateLock, diff --git a/terraform/interpolate.go b/terraform/interpolate.go index 11d5a53dc..993317e9e 100644 --- a/terraform/interpolate.go +++ b/terraform/interpolate.go @@ -25,6 +25,7 @@ const ( // for interpolations such as `aws_instance.foo.bar`. type Interpolater struct { Operation walkOperation + Meta *ContextMeta Module *module.Tree State *State StateLock *sync.RWMutex @@ -87,6 +88,8 @@ func (i *Interpolater) Values( err = i.valueSelfVar(scope, n, v, result) case *config.SimpleVariable: err = i.valueSimpleVar(scope, n, v, result) + case *config.TerraformVariable: + err = i.valueTerraformVar(scope, n, v, result) case *config.UserVariable: err = i.valueUserVar(scope, n, v, result) default: @@ -309,6 +312,25 @@ func (i *Interpolater) valueSimpleVar( n) } +func (i *Interpolater) valueTerraformVar( + scope *InterpolationScope, + n string, + v *config.TerraformVariable, + result map[string]ast.Variable) error { + if v.Field != "env" { + return fmt.Errorf( + "%s: only supported key for 'terraform.X' interpolations is 'env'", n) + } + + if i.Meta == nil { + return fmt.Errorf( + "%s: internal error: nil Meta. Please report a bug.", n) + } + + result[n] = ast.Variable{Type: ast.TypeString, Value: i.Meta.Env} + return nil +} + func (i *Interpolater) valueUserVar( scope *InterpolationScope, n string, diff --git a/terraform/interpolate_test.go b/terraform/interpolate_test.go index bdadedc4f..6f1d2c344 100644 --- a/terraform/interpolate_test.go +++ b/terraform/interpolate_test.go @@ -893,6 +893,33 @@ func TestInterpolater_resourceUnknownVariableList(t *testing.T) { interfaceToVariableSwallowError([]interface{}{})) } +func TestInterpolater_terraformEnv(t *testing.T) { + i := &Interpolater{ + Meta: &ContextMeta{Env: "foo"}, + } + + scope := &InterpolationScope{ + Path: rootModulePath, + } + + testInterpolate(t, i, scope, "terraform.env", ast.Variable{ + Value: "foo", + Type: ast.TypeString, + }) +} + +func TestInterpolater_terraformInvalid(t *testing.T) { + i := &Interpolater{ + Meta: &ContextMeta{Env: "foo"}, + } + + scope := &InterpolationScope{ + Path: rootModulePath, + } + + testInterpolateErr(t, i, scope, "terraform.nope") +} + func testInterpolate( t *testing.T, i *Interpolater, scope *InterpolationScope,