Example #1
0
func (t *ConfigTransformer) Transform(g *Graph) error {
	// A module is required and also must be completely loaded.
	if t.Module == nil {
		return errors.New("module must not be nil")
	}
	if !t.Module.Loaded() {
		return errors.New("module must be loaded")
	}

	// Get the module we care about
	module := t.Module.Child(g.Path[1:])
	if module == nil {
		return nil
	}

	// Get the configuration for this module
	config := module.Config()

	// Create the node list we'll use for the graph
	nodes := make([]graphNodeConfig, 0,
		(len(config.ProviderConfigs)+len(config.Modules)+len(config.Resources))*2)

	// Write all the provider configs out
	for _, pc := range config.ProviderConfigs {
		nodes = append(nodes, &GraphNodeConfigProvider{Provider: pc})
	}

	// Write all the resources out
	for _, r := range config.Resources {
		nodes = append(nodes, &GraphNodeConfigResource{Resource: r})
	}

	// Write all the modules out
	children := module.Children()
	for _, m := range config.Modules {
		path := make([]string, len(g.Path), len(g.Path)+1)
		copy(path, g.Path)
		path = append(path, m.Name)

		nodes = append(nodes, &GraphNodeConfigModule{
			Path:   path,
			Module: m,
			Tree:   children[m.Name],
		})
	}

	// Write all the outputs out
	for _, o := range config.Outputs {
		nodes = append(nodes, &GraphNodeConfigOutput{Output: o})
	}

	// Err is where the final error value will go if there is one
	var err error

	// Build the graph vertices
	for _, n := range nodes {
		g.Add(n)
	}

	// Build up the dependencies. We have to do this outside of the above
	// loop since the nodes need to be in place for us to build the deps.
	for _, n := range nodes {
		if missing := g.ConnectDependent(n); len(missing) > 0 {
			for _, m := range missing {
				err = multierror.Append(err, fmt.Errorf(
					"%s: missing dependency: %s", n.Name(), m))
			}
		}
	}

	return err
}
func (t *OrphanTransformer) Transform(g *Graph) error {
	if t.State == nil {
		// If the entire state is nil, there can't be any orphans
		return nil
	}

	if t.Targeting {
		log.Printf("Skipping orphan transformer because we have targets.")
		// If we are in a run where we are targeting nodes, we won't process
		// orphans for this run.
		return nil
	}

	// Build up all our state representatives
	resourceRep := make(map[string]struct{})
	for _, v := range g.Vertices() {
		if sr, ok := v.(GraphNodeStateRepresentative); ok {
			for _, k := range sr.StateId() {
				resourceRep[k] = struct{}{}
			}
		}
	}

	var config *config.Config
	if t.Module != nil {
		if module := t.Module.Child(g.Path[1:]); module != nil {
			config = module.Config()
		}
	}

	var resourceVertexes []dag.Vertex
	if state := t.State.ModuleByPath(g.Path); state != nil {
		// If we have state, then we can have orphan resources

		// If we have a view, get the view
		if t.View != "" {
			state = state.View(t.View)
		}

		// Go over each resource orphan and add it to the graph.
		resourceOrphans := state.Orphans(config)
		resourceVertexes = make([]dag.Vertex, len(resourceOrphans))
		for i, k := range resourceOrphans {
			// If this orphan is represented by some other node somehow,
			// then ignore it.
			if _, ok := resourceRep[k]; ok {
				continue
			}

			rs := state.Resources[k]

			resourceVertexes[i] = g.Add(&graphNodeOrphanResource{
				ResourceName: k,
				ResourceType: rs.Type,
				Provider:     rs.Provider,
				dependentOn:  rs.Dependencies,
			})
		}
	}

	// Go over each module orphan and add it to the graph. We store the
	// vertexes and states outside so that we can connect dependencies later.
	moduleOrphans := t.State.ModuleOrphans(g.Path, config)
	moduleVertexes := make([]dag.Vertex, len(moduleOrphans))
	for i, path := range moduleOrphans {
		moduleVertexes[i] = g.Add(&graphNodeOrphanModule{
			Path:        path,
			dependentOn: t.State.ModuleByPath(path).Dependencies,
		})
	}

	// Now do the dependencies. We do this _after_ adding all the orphan
	// nodes above because there are cases in which the orphans themselves
	// depend on other orphans.

	// Resource dependencies
	for _, v := range resourceVertexes {
		g.ConnectDependent(v)
	}

	// Module dependencies
	for _, v := range moduleVertexes {
		g.ConnectDependent(v)
	}

	return nil
}
func (t *OrphanTransformer) Transform(g *Graph) error {
	if t.State == nil {
		// If the entire state is nil, there can't be any orphans
		return nil
	}

	// Build up all our state representatives
	resourceRep := make(map[string]struct{})
	for _, v := range g.Vertices() {
		if sr, ok := v.(GraphNodeStateRepresentative); ok {
			for _, k := range sr.StateId() {
				resourceRep[k] = struct{}{}
			}
		}
	}

	var config *config.Config
	if t.Module != nil {
		if module := t.Module.Child(g.Path[1:]); module != nil {
			config = module.Config()
		}
	}

	var resourceVertexes []dag.Vertex
	if state := t.State.ModuleByPath(g.Path); state != nil {
		// If we have state, then we can have orphan resources

		// If we have a view, get the view
		if t.View != "" {
			state = state.View(t.View)
		}

		resourceOrphans := state.Orphans(config)
		if len(t.Targets) > 0 {
			var targetedOrphans []string
			for _, o := range resourceOrphans {
				targeted := false
				for _, t := range t.Targets {
					prefix := fmt.Sprintf("%s.%s.%d", t.Type, t.Name, t.Index)
					if strings.HasPrefix(o, prefix) {
						targeted = true
					}
				}
				if targeted {
					targetedOrphans = append(targetedOrphans, o)
				}
			}
			resourceOrphans = targetedOrphans
		}

		resourceVertexes = make([]dag.Vertex, len(resourceOrphans))
		for i, k := range resourceOrphans {
			// If this orphan is represented by some other node somehow,
			// then ignore it.
			if _, ok := resourceRep[k]; ok {
				continue
			}

			rs := state.Resources[k]

			resourceVertexes[i] = g.Add(&graphNodeOrphanResource{
				ResourceName: k,
				ResourceType: rs.Type,
				Provider:     rs.Provider,
				dependentOn:  rs.Dependencies,
			})
		}
	}

	// Go over each module orphan and add it to the graph. We store the
	// vertexes and states outside so that we can connect dependencies later.
	moduleOrphans := t.State.ModuleOrphans(g.Path, config)
	moduleVertexes := make([]dag.Vertex, len(moduleOrphans))
	for i, path := range moduleOrphans {
		var deps []string
		if s := t.State.ModuleByPath(path); s != nil {
			deps = s.Dependencies
		}

		moduleVertexes[i] = g.Add(&graphNodeOrphanModule{
			Path:        path,
			dependentOn: deps,
		})
	}

	// Now do the dependencies. We do this _after_ adding all the orphan
	// nodes above because there are cases in which the orphans themselves
	// depend on other orphans.

	// Resource dependencies
	for _, v := range resourceVertexes {
		g.ConnectDependent(v)
	}

	// Module dependencies
	for _, v := range moduleVertexes {
		g.ConnectDependent(v)
	}

	return nil
}