Example #1
0
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
}
Example #2
0
// 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
}