// checkRequiredVersion verifies that any version requirements specified by // the configuration are met. // // This checks the root module as well as any additional version requirements // from child modules. // // This is tested in context_test.go. func checkRequiredVersion(m *module.Tree) error { // Check any children for _, c := range m.Children() { if err := checkRequiredVersion(c); err != nil { return err } } var tf *config.Terraform if c := m.Config(); c != nil { tf = c.Terraform } // If there is no Terraform config or the required version isn't set, // we move on. if tf == nil || tf.RequiredVersion == "" { return nil } // Path for errors module := "root" if path := normalizeModulePath(m.Path()); len(path) > 1 { module = modulePrefixStr(path) } // Check this version requirement of this module cs, err := version.NewConstraint(tf.RequiredVersion) if err != nil { return fmt.Errorf( "%s: terraform.required_version %q syntax error: %s", module, tf.RequiredVersion, err) } if !cs.Check(SemVersion) { return fmt.Errorf( "The currently running version of Terraform doesn't meet the\n"+ "version requirements explicitly specified by the configuration.\n"+ "Please use the required version or update the configuration.\n"+ "Note that version requirements are usually set for a reason, so\n"+ "we recommend verifying with whoever set the version requirements\n"+ "prior to making any manual changes.\n\n"+ " Module: %s\n"+ " Required version: %s\n"+ " Current version: %s", module, tf.RequiredVersion, SemVersion) } return nil }
func (t *ConfigTransformer) transform(g *Graph, m *module.Tree) error { // If no config, do nothing if m == nil { return nil } // Add our resources if err := t.transformSingle(g, m); err != nil { return err } // Transform all the children. for _, c := range m.Children() { if err := t.transform(g, c); err != nil { return err } } return nil }
func (t *FlatConfigTransformer) transform(g *Graph, m *module.Tree) error { // If no module, no problem if m == nil { return nil } // Transform all the children. for _, c := range m.Children() { if err := t.transform(g, c); err != nil { return err } } // Get the configuration for this module config := m.Config() // Write all the resources out for _, r := range config.Resources { // Grab the address for this resource addr, err := parseResourceAddressConfig(r) if err != nil { return err } addr.Path = m.Path() // Build the abstract resource. We have the config already so // we'll just pre-populate that. abstract := &NodeAbstractResource{ Addr: addr, Config: r, } var node dag.Vertex = abstract if f := t.Concrete; f != nil { node = f(abstract) } g.Add(node) } return nil }
func (t *OutputTransformer) transform(g *Graph, m *module.Tree) error { // If no config, no outputs if m == nil { return nil } // Transform all the children. We must do this first because // we can reference module outputs and they must show up in the // reference map. for _, c := range m.Children() { if err := t.transform(g, c); err != nil { return err } } // If we have no outputs, we're done! os := m.Config().Outputs if len(os) == 0 { return nil } // Add all outputs here for _, o := range os { // Build the node. // // NOTE: For now this is just an "applyable" output. As we build // new graph builders for the other operations I suspect we'll // find a way to parameterize this, require new transforms, etc. node := &NodeApplyableOutput{ PathValue: normalizeModulePath(m.Path()), Config: o, } // Add it! g.Add(node) } return nil }
func (t *OrphanOutputTransformer) transform(g *Graph, m *module.Tree) error { // Get our configuration, and recurse into children var c *config.Config if m != nil { c = m.Config() for _, child := range m.Children() { if err := t.transform(g, child); err != nil { return err } } } // Get the state. If there is no state, then we have no orphans! path := normalizeModulePath(m.Path()) state := t.State.ModuleByPath(path) if state == nil { return nil } // Make a map of the valid outputs valid := make(map[string]struct{}) for _, o := range c.Outputs { valid[o.Name] = struct{}{} } // Go through the outputs and find the ones that aren't in our config. for n, _ := range state.Outputs { // If it is in the valid map, then ignore if _, ok := valid[n]; ok { continue } // Orphan! g.Add(&NodeOutputOrphan{OutputName: n, PathValue: path}) } return nil }
func (t *ModuleVariableTransformer) transform(g *Graph, parent, m *module.Tree) error { // If no config, no variables if m == nil { return nil } // Transform all the children. This must be done BEFORE the transform // above since child module variables can reference parent module variables. for _, c := range m.Children() { if err := t.transform(g, m, c); err != nil { return err } } // If we have a parent, we can determine if a module variable is being // used, so we transform this. if parent != nil { if err := t.transformSingle(g, parent, m); err != nil { return err } } return nil }