- log.Printf("[TRACE] DiffTransformer: starting")
- var nodes []dag.Vertex
- for _, m := range t.Diff.Modules {
- log.Printf("[TRACE] DiffTransformer: Module: %s", m)
- // TODO: If this is a destroy diff then add a module destroy node
-
- // Go through all the resources in this module.
- for name, inst := range m.Resources {
- log.Printf("[TRACE] DiffTransformer: Resource %q: %#v", name, inst)
-
- // We have changes! This is a create or update operation.
- // First grab the address so we have a unique way to
- // reference this resource.
- addr, err := parseResourceAddressInternal(name)
- if err != nil {
- panic(fmt.Sprintf(
- "Error parsing internal name, this is a bug: %q", name))
- }
+ log.Printf("[TRACE] DiffTransformer starting")
+
+ var diags tfdiags.Diagnostics
+ state := t.State
+ changes := t.Changes
+
+ // DiffTransformer creates resource _instance_ nodes. If there are any
+ // whole-resource nodes already in the graph, we must ensure that they
+ // get evaluated before any of the corresponding instances by creating
+ // dependency edges, so we'll do some prep work here to ensure we'll only
+ // create connections to nodes that existed before we started here.
+ resourceNodes := map[string][]GraphNodeResource{}
+ for _, node := range g.Vertices() {
+ rn, ok := node.(GraphNodeResource)
+ if !ok {
+ continue
+ }
+ // We ignore any instances that _also_ implement
+ // GraphNodeResourceInstance, since in the unlikely event that they
+ // do exist we'd probably end up creating cycles by connecting them.
+ if _, ok := node.(GraphNodeResourceInstance); ok {
+ continue
+ }
+
+ addr := rn.ResourceAddr().String()
+ resourceNodes[addr] = append(resourceNodes[addr], rn)
+ }
+
+ for _, rc := range changes.Resources {
+ addr := rc.Addr
+ dk := rc.DeposedKey
+
+ log.Printf("[TRACE] DiffTransformer: found %s change for %s %s", rc.Action, addr, dk)
+
+ // Depending on the action we'll need some different combinations of
+ // nodes, because destroying uses a special node type separate from
+ // other actions.
+ var update, delete, createBeforeDestroy bool
+ switch rc.Action {
+ case plans.NoOp:
+ continue
+ case plans.Delete:
+ delete = true
+ case plans.DeleteThenCreate, plans.CreateThenDelete:
+ update = true
+ delete = true
+ createBeforeDestroy = (rc.Action == plans.CreateThenDelete)
+ default:
+ update = true
+ }
+
+ if dk != states.NotDeposed && update {
+ diags = diags.Append(tfdiags.Sourceless(
+ tfdiags.Error,
+ "Invalid planned change for deposed object",
+ fmt.Sprintf("The plan contains a non-delete change for %s deposed object %s. The only valid action for a deposed object is to destroy it, so this is a bug in Terraform.", addr, dk),
+ ))
+ continue
+ }