terraform: outputs are computed for the state
This commit is contained in:
parent
ed1860de61
commit
4b5f5aec65
|
@ -105,6 +105,18 @@ func (c *Context) Apply() (*State, error) {
|
|||
// Update our state, even if we have an error, for partial updates
|
||||
c.state = s
|
||||
|
||||
// If we have no errors, then calculate the outputs if we have any
|
||||
if err == nil && len(c.config.Outputs) > 0 {
|
||||
s.Outputs = make(map[string]string)
|
||||
for _, o := range c.config.Outputs {
|
||||
if err = c.computeVars(s, o.RawConfig); err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
s.Outputs[o.Name] = o.RawConfig.Config()["value"].(string)
|
||||
}
|
||||
}
|
||||
|
||||
return s, err
|
||||
}
|
||||
|
||||
|
@ -232,6 +244,48 @@ func (c *Context) Validate() ([]string, []error) {
|
|||
return warns, errs
|
||||
}
|
||||
|
||||
// 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 *Context) computeVars(s *State, raw *config.RawConfig) error {
|
||||
// If there are on variables, then we're done
|
||||
if len(raw.Variables) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Go through each variable and find it
|
||||
vs := make(map[string]string)
|
||||
for n, rawV := range raw.Variables {
|
||||
switch v := rawV.(type) {
|
||||
case *config.ResourceVariable:
|
||||
r, ok := s.Resources[v.ResourceId()]
|
||||
if !ok {
|
||||
return fmt.Errorf(
|
||||
"Resource '%s' not found for variable '%s'",
|
||||
v.ResourceId(),
|
||||
v.FullKey())
|
||||
}
|
||||
|
||||
attr, ok := r.Attributes[v.Field]
|
||||
if !ok {
|
||||
return fmt.Errorf(
|
||||
"Resource '%s' does not have attribute '%s' "+
|
||||
"for variable '%s'",
|
||||
v.ResourceId(),
|
||||
v.Field,
|
||||
v.FullKey())
|
||||
}
|
||||
|
||||
vs[n] = attr
|
||||
case *config.UserVariable:
|
||||
vs[n] = c.variables[v.Name]
|
||||
}
|
||||
}
|
||||
|
||||
// Interpolate the variables
|
||||
return raw.Interpolate(vs)
|
||||
}
|
||||
|
||||
func (c *Context) graph() (*depgraph.Graph, error) {
|
||||
return Graph(&GraphOpts{
|
||||
Config: c.config,
|
||||
|
|
|
@ -508,6 +508,34 @@ func TestContextApply_hook(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestContextApply_output(t *testing.T) {
|
||||
c := testConfig(t, "apply-output")
|
||||
p := testProvider("aws")
|
||||
p.ApplyFn = testApplyFn
|
||||
p.DiffFn = testDiffFn
|
||||
ctx := testContext(t, &ContextOpts{
|
||||
Config: c,
|
||||
Providers: map[string]ResourceProviderFactory{
|
||||
"aws": testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
|
||||
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(testTerraformApplyOutputStr)
|
||||
if actual != expected {
|
||||
t.Fatalf("bad: \n%s", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestContextApply_unknownAttribute(t *testing.T) {
|
||||
c := testConfig(t, "apply-unknown")
|
||||
p := testProvider("aws")
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
// can use to keep track of what real world resources it is actually
|
||||
// managing.
|
||||
type State struct {
|
||||
Outputs map[string]string
|
||||
Resources map[string]*ResourceState
|
||||
|
||||
once sync.Once
|
||||
|
@ -96,6 +97,21 @@ func (s *State) String() string {
|
|||
}
|
||||
}
|
||||
|
||||
if len(s.Outputs) > 0 {
|
||||
buf.WriteString("\nOutputs:\n\n")
|
||||
|
||||
ks := make([]string, 0, len(s.Outputs))
|
||||
for k, _ := range s.Outputs {
|
||||
ks = append(ks, k)
|
||||
}
|
||||
sort.Strings(ks)
|
||||
|
||||
for _, k := range ks {
|
||||
v := s.Outputs[k]
|
||||
buf.WriteString(fmt.Sprintf("%s = %s\n", k, v))
|
||||
}
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
|
|
|
@ -106,6 +106,21 @@ aws_instance.foo:
|
|||
num = 2
|
||||
`
|
||||
|
||||
const testTerraformApplyOutputStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
num = 2
|
||||
type = aws_instance
|
||||
|
||||
Outputs:
|
||||
|
||||
foo_num = 2
|
||||
`
|
||||
|
||||
const testTerraformApplyUnknownAttrStr = `
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
resource "aws_instance" "foo" {
|
||||
num = "2"
|
||||
}
|
||||
|
||||
resource "aws_instance" "bar" {
|
||||
foo = "bar"
|
||||
}
|
||||
|
||||
output "foo_num" {
|
||||
value = "${aws_instance.foo.num}"
|
||||
}
|
Loading…
Reference in New Issue