summaryrefslogtreecommitdiff
path: root/vendor/github.com/hashicorp/terraform/terraform/semantics.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/terraform/semantics.go')
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/semantics.go132
1 files changed, 132 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/terraform/semantics.go b/vendor/github.com/hashicorp/terraform/terraform/semantics.go
new file mode 100644
index 00000000..20f1d8a2
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/terraform/semantics.go
@@ -0,0 +1,132 @@
+package terraform
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/hashicorp/go-multierror"
+ "github.com/hashicorp/terraform/config"
+ "github.com/hashicorp/terraform/dag"
+)
+
+// GraphSemanticChecker is the interface that semantic checks across
+// the entire Terraform graph implement.
+//
+// The graph should NOT be modified by the semantic checker.
+type GraphSemanticChecker interface {
+ Check(*dag.Graph) error
+}
+
+// UnorderedSemanticCheckRunner is an implementation of GraphSemanticChecker
+// that runs a list of SemanticCheckers against the vertices of the graph
+// in no specified order.
+type UnorderedSemanticCheckRunner struct {
+ Checks []SemanticChecker
+}
+
+func (sc *UnorderedSemanticCheckRunner) Check(g *dag.Graph) error {
+ var err error
+ for _, v := range g.Vertices() {
+ for _, check := range sc.Checks {
+ if e := check.Check(g, v); e != nil {
+ err = multierror.Append(err, e)
+ }
+ }
+ }
+
+ return err
+}
+
+// SemanticChecker is the interface that semantic checks across the
+// Terraform graph implement. Errors are accumulated. Even after an error
+// is returned, child vertices in the graph will still be visited.
+//
+// The graph should NOT be modified by the semantic checker.
+//
+// The order in which vertices are visited is left unspecified, so the
+// semantic checks should not rely on that.
+type SemanticChecker interface {
+ Check(*dag.Graph, dag.Vertex) error
+}
+
+// smcUserVariables does all the semantic checks to verify that the
+// variables given satisfy the configuration itself.
+func smcUserVariables(c *config.Config, vs map[string]interface{}) []error {
+ var errs []error
+
+ cvs := make(map[string]*config.Variable)
+ for _, v := range c.Variables {
+ cvs[v.Name] = v
+ }
+
+ // Check that all required variables are present
+ required := make(map[string]struct{})
+ for _, v := range c.Variables {
+ if v.Required() {
+ required[v.Name] = struct{}{}
+ }
+ }
+ for k, _ := range vs {
+ delete(required, k)
+ }
+ if len(required) > 0 {
+ for k, _ := range required {
+ errs = append(errs, fmt.Errorf(
+ "Required variable not set: %s", k))
+ }
+ }
+
+ // Check that types match up
+ for name, proposedValue := range vs {
+ // Check for "map.key" fields. These stopped working with Terraform
+ // 0.7 but we do this to surface a better error message informing
+ // the user what happened.
+ if idx := strings.Index(name, "."); idx > 0 {
+ key := name[:idx]
+ if _, ok := cvs[key]; ok {
+ errs = append(errs, fmt.Errorf(
+ "%s: Overriding map keys with the format `name.key` is no "+
+ "longer allowed. You may still override keys by setting "+
+ "`name = { key = value }`. The maps will be merged. This "+
+ "behavior appeared in 0.7.0.", name))
+ continue
+ }
+ }
+
+ schema, ok := cvs[name]
+ if !ok {
+ continue
+ }
+
+ declaredType := schema.Type()
+
+ switch declaredType {
+ case config.VariableTypeString:
+ switch proposedValue.(type) {
+ case string:
+ continue
+ }
+ case config.VariableTypeMap:
+ switch v := proposedValue.(type) {
+ case map[string]interface{}:
+ continue
+ case []map[string]interface{}:
+ // if we have a list of 1 map, it will get coerced later as needed
+ if len(v) == 1 {
+ continue
+ }
+ }
+ case config.VariableTypeList:
+ switch proposedValue.(type) {
+ case []interface{}:
+ continue
+ }
+ }
+ errs = append(errs, fmt.Errorf("variable %s should be type %s, got %s",
+ name, declaredType.Printable(), hclTypeName(proposedValue)))
+ }
+
+ // TODO(mitchellh): variables that are unknown
+
+ return errs
+}