// Diff returns the diff for a resource given the schema map, // state, and configuration. func (m schemaMap) Diff( s *terraform.InstanceState, c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) { result := new(terraform.InstanceDiff) result.Attributes = make(map[string]*terraform.ResourceAttrDiff) d := &ResourceData{ schema: m, state: s, config: c, } for k, schema := range m { err := m.diff(k, schema, result, d, false) if err != nil { return nil, err } } // If the diff requires a new resource, then we recompute the diff // so we have the complete new resource diff, and preserve the // RequiresNew fields where necessary so the user knows exactly what // caused that. if result.RequiresNew() { // Create the new diff result2 := new(terraform.InstanceDiff) result2.Attributes = make(map[string]*terraform.ResourceAttrDiff) // Reset the data to not contain state. We have to call init() // again in order to reset the FieldReaders. d.state = nil d.init() // Perform the diff again for k, schema := range m { err := m.diff(k, schema, result2, d, false) if err != nil { return nil, err } } // Force all the fields to not force a new since we know what we // want to force new. for k, attr := range result2.Attributes { if attr == nil { continue } if attr.RequiresNew { attr.RequiresNew = false } if s != nil { attr.Old = s.Attributes[k] } } // Now copy in all the requires new diffs... for k, attr := range result.Attributes { if attr == nil { continue } newAttr, ok := result2.Attributes[k] if !ok { newAttr = attr } if attr.RequiresNew { newAttr.RequiresNew = true } result2.Attributes[k] = newAttr } // And set the diff! result = result2 } // Remove any nil diffs just to keep things clean for k, v := range result.Attributes { if v == nil { delete(result.Attributes, k) } } // Go through and detect all of the ComputedWhens now that we've // finished the diff. // TODO if result.Empty() { // If we don't have any diff elements, just return nil return nil, nil } return result, nil }