func (v *Validator) Validate( c *terraform.ResourceConfig) (ws []string, es []error) { // Flatten the configuration so it is easier to reason about flat := flatmap.Flatten(c.Raw) keySet := make(map[string]validatorKey) for i, vs := range [][]string{v.Required, v.Optional} { req := i == 0 for _, k := range vs { vk, err := newValidatorKey(k, req) if err != nil { es = append(es, err) continue } keySet[k] = vk } } purged := make([]string, 0) for _, kv := range keySet { p, w, e := kv.Validate(flat) if len(w) > 0 { ws = append(ws, w...) } if len(e) > 0 { es = append(es, e...) } purged = append(purged, p...) } // Delete all the keys we processed in order to find // the unknown keys. for _, p := range purged { delete(flat, p) } // The rest are unknown for k, _ := range flat { es = append(es, fmt.Errorf("Unknown configuration: %s", k)) } return }
// DefaultsMap returns a map of default values for this variable. func (v *Variable) DefaultsMap() map[string]string { if v.Default == nil { return nil } n := fmt.Sprintf("var.%s", v.Name) switch v.Type() { case VariableTypeString: return map[string]string{n: v.Default.(string)} case VariableTypeMap: result := flatmap.Flatten(map[string]interface{}{ n: v.Default.(map[string]string), }) result[n] = v.Name return result default: return nil } }
// Diff returns the ResourceDiff for a resource given its state and // configuration. func (b *ResourceBuilder) Diff( s *terraform.InstanceState, c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) { attrs := make(map[string]*terraform.ResourceAttrDiff) // We require a new resource if the ID is empty. Or, later, we set // this to true if any configuration changed that triggers a new resource. requiresNew := s.ID == "" // Flatten the raw and processed configuration flatRaw := flatmap.Flatten(c.Raw) flatConfig := flatmap.Flatten(c.Config) for ak, at := range b.Attrs { // Keep track of all the keys we saw in the raw structure // so that we can prune our attributes later. seenKeys := make([]string, 0) // Go through and find the added/changed keys in flatRaw for k, v := range flatRaw { // Find only the attributes that match our prefix if !strings.HasPrefix(k, ak) { continue } // Track that we saw this key seenKeys = append(seenKeys, k) // We keep track of this in case we have a pre-processor // so that we can store the original value still. originalV := v // If this key is in the cleaned config, then use that value // because it'll have its variables properly interpolated if cleanV, ok := flatConfig[k]; ok { v = cleanV originalV = v // If we have a pre-processor for this, run it. if pp, ok := b.PreProcess[k]; ok { v = pp(v) } } oldV, ok := s.Attributes[k] // If there is an old value and they're the same, no change if ok && oldV == v { continue } // Record the change attrs[k] = &terraform.ResourceAttrDiff{ Old: oldV, New: v, NewExtra: originalV, Type: terraform.DiffAttrInput, } // If this requires a new resource, record that and flag our // boolean. if at == AttrTypeCreate { attrs[k].RequiresNew = true requiresNew = true } } // Find all the keys that are in our attributes right now that // we also care about. matchingKeys := make(map[string]struct{}) for k, _ := range s.Attributes { // Find only the attributes that match our prefix if !strings.HasPrefix(k, ak) { continue } // If this key is computed, then we don't ever delete it comp := false for _, ck := range b.ComputedAttrs { if ck == k { comp = true break } // If the key is prefixed with the computed key, don't // mark it for delete, ever. if strings.HasPrefix(k, ck+".") { comp = true break } } if comp { continue } matchingKeys[k] = struct{}{} } // Delete the keys we saw in the configuration from the keys // that are currently set. for _, k := range seenKeys { delete(matchingKeys, k) } for k, _ := range matchingKeys { attrs[k] = &terraform.ResourceAttrDiff{ Old: s.Attributes[k], NewRemoved: true, Type: terraform.DiffAttrInput, } } } // If we require a new resource, then process all the attributes // that will be changing due to the creation of the resource. if requiresNew { for _, k := range b.ComputedAttrs { if _, ok := attrs[k]; ok { continue } old := s.Attributes[k] attrs[k] = &terraform.ResourceAttrDiff{ Old: old, NewComputed: true, Type: terraform.DiffAttrOutput, } } } // If we're changing anything, then mark the updated // attributes. if len(attrs) > 0 { for _, k := range b.ComputedAttrsUpdate { if _, ok := attrs[k]; ok { continue } old := s.Attributes[k] attrs[k] = &terraform.ResourceAttrDiff{ Old: old, NewComputed: true, Type: terraform.DiffAttrOutput, } } } // Build our resulting diff if we had attributes change var result *terraform.InstanceDiff if len(attrs) > 0 { result = &terraform.InstanceDiff{ Attributes: attrs, } } return result, nil }