// configGraph turns a configuration structure into a dependency graph. func graphAddConfigResources( g *depgraph.Graph, c *config.Config, s *State) { // This tracks all the resource nouns nouns := make(map[string]*depgraph.Noun) for _, r := range c.Resources { resourceNouns := make([]*depgraph.Noun, r.Count) for i := 0; i < r.Count; i++ { name := r.Id() index := -1 // If we have a count that is more than one, then make sure // we suffix with the number of the resource that this is. if r.Count > 1 { name = fmt.Sprintf("%s.%d", name, i) index = i } // Determine if this resource is tainted tainted := false if s != nil && s.Tainted != nil { _, tainted = s.Tainted[r.Id()] } var state *ResourceState if s != nil { state = s.Resources[name] if state == nil { if r.Count == 1 { // If the count is one, check the state for ".0" // appended, which might exist if we go from // count > 1 to count == 1. state = s.Resources[r.Id()+".0"] } else if i == 0 { // If count is greater than one, check for state // with just the ID, which might exist if we go // from count == 1 to count > 1 state = s.Resources[r.Id()] } } } if state == nil { state = &ResourceState{ Type: r.Type, } } resourceNouns[i] = &depgraph.Noun{ Name: name, Meta: &GraphNodeResource{ Index: index, Type: r.Type, Config: r, Resource: &Resource{ Id: name, State: state, Config: NewResourceConfig(r.RawConfig), Tainted: tainted, }, }, } } // If we have more than one, then create a meta node to track // the resources. if r.Count > 1 { metaNoun := &depgraph.Noun{ Name: r.Id(), Meta: &GraphNodeResourceMeta{ ID: r.Id(), Name: r.Name, Type: r.Type, Count: r.Count, }, } // Create the dependencies on this noun for _, n := range resourceNouns { metaNoun.Deps = append(metaNoun.Deps, &depgraph.Dependency{ Name: n.Name, Source: metaNoun, Target: n, }) } // Assign it to the map so that we have it nouns[metaNoun.Name] = metaNoun } for _, n := range resourceNouns { nouns[n.Name] = n } } // Build the list of nouns that we iterate over nounsList := make([]*depgraph.Noun, 0, len(nouns)) for _, n := range nouns { nounsList = append(nounsList, n) } g.Name = "terraform" g.Nouns = append(g.Nouns, nounsList...) }