8 // configurable is an interface that must be implemented by any configuration
9 // formats of Terraform in order to return a *Config.
10 type configurable interface {
11 Config() (*Config, error)
14 // importTree is the result of the first-pass load of the configuration
15 // files. It is a tree of raw configurables and then any children (their
18 // An importTree can be turned into a configTree.
19 type importTree struct {
22 Children []*importTree
25 // This is the function type that must be implemented by the configuration
26 // file loader to turn a single file into a configurable and any additional
28 type fileLoaderFunc func(path string) (configurable, []string, error)
30 // loadTree takes a single file and loads the entire importTree for that
31 // file. This function detects what kind of configuration file it is an
32 // executes the proper fileLoaderFunc.
33 func loadTree(root string) (*importTree, error) {
36 case ".tf", ".tf.json":
42 return nil, fmt.Errorf(
43 "%s: unknown configuration format. Use '.tf' or '.tf.json' extension",
47 c, imps, err := f(root)
52 children := make([]*importTree, len(imps))
53 for i, imp := range imps {
54 t, err := loadTree(imp)
69 // Close releases any resources we might be holding open for the importTree.
71 // This can safely be called even while ConfigTree results are alive. The
72 // importTree is not bound to these.
73 func (t *importTree) Close() error {
74 if c, ok := t.Raw.(io.Closer); ok {
77 for _, ct := range t.Children {
84 // ConfigTree traverses the importTree and turns each node into a *Config
85 // object, ultimately returning a *configTree.
86 func (t *importTree) ConfigTree() (*configTree, error) {
87 config, err := t.Raw.Config()
89 return nil, fmt.Errorf(
90 "Error loading %s: %s",
96 result := &configTree{
101 // Build the config trees for the children
102 result.Children = make([]*configTree, len(t.Children))
103 for i, ct := range t.Children {
104 t, err := ct.ConfigTree()
109 result.Children[i] = t