func (m schemaMap) validateConflictingAttributes( k string, schema *Schema, c *terraform.ResourceConfig) error { if len(schema.ConflictsWith) == 0 { return nil } for _, conflicting_key := range schema.ConflictsWith { if value, ok := c.Get(conflicting_key); ok { return fmt.Errorf( "%q: conflicts with %s (%#v)", k, conflicting_key, value) } } return nil }
func (m schemaMap) validateObject( k string, schema map[string]*Schema, c *terraform.ResourceConfig) ([]string, []error) { raw, _ := c.GetRaw(k) if _, ok := raw.(map[string]interface{}); !ok { return nil, []error{fmt.Errorf( "%s: expected object, got %s", k, reflect.ValueOf(raw).Kind())} } var ws []string var es []error for subK, s := range schema { key := subK if k != "" { key = fmt.Sprintf("%s.%s", k, subK) } ws2, es2 := m.validate(key, s, c) if len(ws2) > 0 { ws = append(ws, ws2...) } if len(es2) > 0 { es = append(es, es2...) } } // Detect any extra/unknown keys and report those as errors. if m, ok := raw.(map[string]interface{}); ok { for subk, _ := range m { if _, ok := schema[subk]; !ok { es = append(es, fmt.Errorf( "%s: invalid or unknown key: %s", k, subk)) } } } return ws, es }
func (m schemaMap) validate( k string, schema *Schema, c *terraform.ResourceConfig) ([]string, []error) { raw, ok := c.Get(k) if !ok && schema.DefaultFunc != nil { // We have a dynamic default. Check if we have a value. var err error raw, err = schema.DefaultFunc() if err != nil { return nil, []error{fmt.Errorf( "%q, error loading default: %s", k, err)} } // We're okay as long as we had a value set ok = raw != nil } if !ok { if schema.Required { return nil, []error{fmt.Errorf( "%q: required field is not set", k)} } return nil, nil } if !schema.Required && !schema.Optional { // This is a computed-only field return nil, []error{fmt.Errorf( "%q: this field cannot be set", k)} } err := m.validateConflictingAttributes(k, schema, c) if err != nil { return nil, []error{err} } return m.validateType(k, raw, schema, c) }
func (m schemaMap) validatePrimitive( k string, raw interface{}, schema *Schema, c *terraform.ResourceConfig) ([]string, []error) { // Catch if the user gave a complex type where a primitive was // expected, so we can return a friendly error message that // doesn't contain Go type system terminology. switch reflect.ValueOf(raw).Type().Kind() { case reflect.Slice: return nil, []error{ fmt.Errorf("%s must be a single value, not a list", k), } case reflect.Map: return nil, []error{ fmt.Errorf("%s must be a single value, not a map", k), } default: // ok } if c.IsComputed(k) { // If the key is being computed, then it is not an error as // long as it's not a slice or map. return nil, nil } var decoded interface{} switch schema.Type { case TypeBool: // Verify that we can parse this as the correct type var n bool if err := mapstructure.WeakDecode(raw, &n); err != nil { return nil, []error{err} } decoded = n case TypeInt: // Verify that we can parse this as an int var n int if err := mapstructure.WeakDecode(raw, &n); err != nil { return nil, []error{err} } decoded = n case TypeFloat: // Verify that we can parse this as an int var n float64 if err := mapstructure.WeakDecode(raw, &n); err != nil { return nil, []error{err} } decoded = n case TypeString: // Verify that we can parse this as a string var n string if err := mapstructure.WeakDecode(raw, &n); err != nil { return nil, []error{err} } decoded = n default: panic(fmt.Sprintf("Unknown validation type: %#v", schema.Type)) } if schema.ValidateFunc != nil { return schema.ValidateFunc(decoded, k) } return nil, nil }