2015-01-21 16:20:51 -06:00
|
|
|
package terraform
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
|
2015-01-23 17:21:27 -06:00
|
|
|
"github.com/hashicorp/go-multierror"
|
2015-01-21 16:20:51 -06:00
|
|
|
"github.com/hashicorp/terraform/config"
|
|
|
|
"github.com/hashicorp/terraform/config/module"
|
|
|
|
)
|
|
|
|
|
2015-01-26 23:23:27 -06:00
|
|
|
// ConfigTransformer is a GraphTransformer that adds the configuration
|
2015-01-30 15:31:39 -06:00
|
|
|
// to the graph. The module used to configure this transformer must be
|
|
|
|
// the root module. We'll look up the child module by the Path in the
|
|
|
|
// Graph.
|
2015-01-26 23:23:27 -06:00
|
|
|
type ConfigTransformer struct {
|
|
|
|
Module *module.Tree
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *ConfigTransformer) Transform(g *Graph) error {
|
2015-01-21 16:20:51 -06:00
|
|
|
// A module is required and also must be completely loaded.
|
2015-01-26 23:23:27 -06:00
|
|
|
if t.Module == nil {
|
|
|
|
return errors.New("module must not be nil")
|
2015-01-21 16:20:51 -06:00
|
|
|
}
|
2015-01-26 23:23:27 -06:00
|
|
|
if !t.Module.Loaded() {
|
|
|
|
return errors.New("module must be loaded")
|
2015-01-21 16:20:51 -06:00
|
|
|
}
|
|
|
|
|
2015-01-30 15:31:39 -06:00
|
|
|
// Get the module we care about
|
|
|
|
module := t.Module.Child(g.Path[1:])
|
|
|
|
if module == nil {
|
2015-02-11 19:47:30 -06:00
|
|
|
return nil
|
2015-01-30 15:31:39 -06:00
|
|
|
}
|
|
|
|
|
2015-01-21 16:20:51 -06:00
|
|
|
// Get the configuration for this module
|
2015-01-30 15:31:39 -06:00
|
|
|
config := module.Config()
|
2015-01-21 16:20:51 -06:00
|
|
|
|
|
|
|
// Create the node list we'll use for the graph
|
|
|
|
nodes := make([]graphNodeConfig, 0,
|
2015-04-30 18:27:20 -05:00
|
|
|
(len(config.Variables)+
|
|
|
|
len(config.ProviderConfigs)+
|
|
|
|
len(config.Modules)+
|
|
|
|
len(config.Resources)+
|
|
|
|
len(config.Outputs))*2)
|
|
|
|
|
|
|
|
// Write all the variables out
|
|
|
|
for _, v := range config.Variables {
|
2016-04-15 14:07:54 -05:00
|
|
|
nodes = append(nodes, &GraphNodeConfigVariable{
|
|
|
|
Variable: v,
|
|
|
|
ModuleTree: t.Module,
|
|
|
|
ModulePath: g.Path,
|
|
|
|
})
|
2015-04-30 18:27:20 -05:00
|
|
|
}
|
2015-01-21 16:20:51 -06:00
|
|
|
|
2015-01-21 16:39:16 -06:00
|
|
|
// Write all the provider configs out
|
|
|
|
for _, pc := range config.ProviderConfigs {
|
|
|
|
nodes = append(nodes, &GraphNodeConfigProvider{Provider: pc})
|
|
|
|
}
|
|
|
|
|
2015-01-21 16:20:51 -06:00
|
|
|
// Write all the resources out
|
|
|
|
for _, r := range config.Resources {
|
2015-05-01 11:01:49 -05:00
|
|
|
nodes = append(nodes, &GraphNodeConfigResource{
|
|
|
|
Resource: r,
|
|
|
|
Path: g.Path,
|
|
|
|
})
|
2015-01-21 16:20:51 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Write all the modules out
|
2015-01-30 15:31:39 -06:00
|
|
|
children := module.Children()
|
2015-01-21 16:53:50 -06:00
|
|
|
for _, m := range config.Modules {
|
2015-02-07 18:19:08 -06:00
|
|
|
path := make([]string, len(g.Path), len(g.Path)+1)
|
|
|
|
copy(path, g.Path)
|
|
|
|
path = append(path, m.Name)
|
|
|
|
|
2015-01-23 19:52:51 -06:00
|
|
|
nodes = append(nodes, &GraphNodeConfigModule{
|
2015-02-07 18:19:08 -06:00
|
|
|
Path: path,
|
2015-01-23 19:52:51 -06:00
|
|
|
Module: m,
|
|
|
|
Tree: children[m.Name],
|
|
|
|
})
|
2015-01-21 16:53:50 -06:00
|
|
|
}
|
2015-01-21 16:20:51 -06:00
|
|
|
|
2015-02-12 00:21:17 -06:00
|
|
|
// Write all the outputs out
|
|
|
|
for _, o := range config.Outputs {
|
|
|
|
nodes = append(nodes, &GraphNodeConfigOutput{Output: o})
|
|
|
|
}
|
|
|
|
|
2015-01-26 23:23:27 -06:00
|
|
|
// Err is where the final error value will go if there is one
|
|
|
|
var err error
|
2015-01-21 16:20:51 -06:00
|
|
|
|
2015-01-23 17:11:11 -06:00
|
|
|
// Build the graph vertices
|
|
|
|
for _, n := range nodes {
|
|
|
|
g.Add(n)
|
|
|
|
}
|
|
|
|
|
2015-01-26 23:23:27 -06:00
|
|
|
// Build up the dependencies. We have to do this outside of the above
|
|
|
|
// loop since the nodes need to be in place for us to build the deps.
|
2015-01-21 16:20:51 -06:00
|
|
|
for _, n := range nodes {
|
2015-01-27 16:56:01 -06:00
|
|
|
if missing := g.ConnectDependent(n); len(missing) > 0 {
|
2015-01-26 23:23:27 -06:00
|
|
|
for _, m := range missing {
|
2015-01-23 17:21:27 -06:00
|
|
|
err = multierror.Append(err, fmt.Errorf(
|
2015-01-26 23:23:27 -06:00
|
|
|
"%s: missing dependency: %s", n.Name(), m))
|
2015-01-23 17:11:11 -06:00
|
|
|
}
|
2015-01-21 16:20:51 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-26 23:23:27 -06:00
|
|
|
return err
|
2015-01-21 16:20:51 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// varNameForVar returns the VarName value for an interpolated variable.
|
|
|
|
// This value is compared to the VarName() value for the nodes within the
|
|
|
|
// graph to build the graph edges.
|
|
|
|
func varNameForVar(raw config.InterpolatedVariable) string {
|
|
|
|
switch v := raw.(type) {
|
|
|
|
case *config.ModuleVariable:
|
2015-05-01 13:26:58 -05:00
|
|
|
return fmt.Sprintf("module.%s.output.%s", v.Name, v.Field)
|
2015-01-21 16:20:51 -06:00
|
|
|
case *config.ResourceVariable:
|
|
|
|
return v.ResourceId()
|
2015-04-30 18:27:20 -05:00
|
|
|
case *config.UserVariable:
|
|
|
|
return fmt.Sprintf("var.%s", v.Name)
|
2015-01-21 16:20:51 -06:00
|
|
|
default:
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
}
|