terraform: make our own graph meta
This commit is contained in:
parent
b6272a4a69
commit
0bf394dfe2
|
@ -11,19 +11,40 @@ import (
|
|||
// graph. This node is just a placemarker and has no associated functionality.
|
||||
const GraphRootNode = "root"
|
||||
|
||||
// GraphNodeResource is a node type in the graph that represents a resource.
|
||||
type GraphNodeResource struct {
|
||||
Type string
|
||||
Config *config.Resource
|
||||
Orphan bool
|
||||
Resource *Resource
|
||||
ResourceProviderID string
|
||||
}
|
||||
|
||||
// GraphNodeResourceProvider is a node type in the graph that represents
|
||||
// the configuration for a resource provider.
|
||||
type GraphNodeResourceProvider struct {
|
||||
ID string
|
||||
Provider ResourceProvider
|
||||
Config *config.ProviderConfig
|
||||
}
|
||||
|
||||
// Graph builds a dependency graph for the given configuration and state.
|
||||
//
|
||||
// Before using this graph, Validate should be called on it. This will perform
|
||||
// some initialization necessary such as setting up a root node. This function
|
||||
// doesn't perform the Validate automatically in case the caller wants to
|
||||
// modify the graph.
|
||||
//
|
||||
// This dependency graph shows the correct order that any resources need
|
||||
// to be operated on.
|
||||
//
|
||||
// The Meta field of a graph Noun can contain one of the follow types. A
|
||||
// description is next to each type to explain what it is.
|
||||
//
|
||||
// *config.Resource - A resource itself
|
||||
// *config.ProviderConfig - The configuration for a provider that
|
||||
// should be initialized.
|
||||
// *ResourceState - An orphan resource that we only have the state of
|
||||
// and no more configuration.
|
||||
// *GraphNodeResource - A resource. See the documentation of this
|
||||
// struct for more details.
|
||||
// *GraphNodeResourceProvider - A resource provider that needs to be
|
||||
// configured at this point.
|
||||
//
|
||||
func Graph(c *config.Config, s *State) *depgraph.Graph {
|
||||
g := new(depgraph.Graph)
|
||||
|
@ -56,7 +77,10 @@ func graphAddConfigResources(g *depgraph.Graph, c *config.Config) {
|
|||
for _, r := range c.Resources {
|
||||
noun := &depgraph.Noun{
|
||||
Name: r.Id(),
|
||||
Meta: r,
|
||||
Meta: &GraphNodeResource{
|
||||
Type: r.Type,
|
||||
Config: r,
|
||||
},
|
||||
}
|
||||
nouns[noun.Name] = noun
|
||||
}
|
||||
|
@ -77,7 +101,13 @@ func graphAddOrphans(g *depgraph.Graph, c *config.Config, s *State) {
|
|||
rs := s.Resources[k]
|
||||
noun := &depgraph.Noun{
|
||||
Name: k,
|
||||
Meta: rs,
|
||||
Meta: &GraphNodeResource{
|
||||
Type: rs.Type,
|
||||
Orphan: true,
|
||||
Resource: &Resource{
|
||||
State: rs,
|
||||
},
|
||||
},
|
||||
}
|
||||
g.Nouns = append(g.Nouns, noun)
|
||||
}
|
||||
|
@ -89,18 +119,10 @@ func graphAddProviderConfigs(g *depgraph.Graph, c *config.Config) {
|
|||
nounsList := make([]*depgraph.Noun, 0, 2)
|
||||
pcNouns := make(map[string]*depgraph.Noun)
|
||||
for _, noun := range g.Nouns {
|
||||
var rtype string
|
||||
switch m := noun.Meta.(type) {
|
||||
case *config.Resource:
|
||||
rtype = m.Type
|
||||
case *ResourceState:
|
||||
rtype = m.Type
|
||||
default:
|
||||
continue
|
||||
}
|
||||
resourceNode := noun.Meta.(*GraphNodeResource)
|
||||
|
||||
// Look up the provider config for this resource
|
||||
pcName := config.ProviderConfigName(rtype, c.ProviderConfigs)
|
||||
pcName := config.ProviderConfigName(resourceNode.Type, c.ProviderConfigs)
|
||||
if pcName == "" {
|
||||
continue
|
||||
}
|
||||
|
@ -110,12 +132,20 @@ func graphAddProviderConfigs(g *depgraph.Graph, c *config.Config) {
|
|||
if !ok {
|
||||
pcNoun = &depgraph.Noun{
|
||||
Name: fmt.Sprintf("provider.%s", pcName),
|
||||
Meta: c.ProviderConfigs[pcName],
|
||||
Meta: &GraphNodeResourceProvider{
|
||||
ID: pcName,
|
||||
Config: c.ProviderConfigs[pcName],
|
||||
},
|
||||
}
|
||||
pcNouns[pcName] = pcNoun
|
||||
nounsList = append(nounsList, pcNoun)
|
||||
}
|
||||
|
||||
// Set the resource provider ID for this noun so we can look it
|
||||
// up later easily.
|
||||
resourceNode.ResourceProviderID = pcName
|
||||
|
||||
// Add the provider configuration noun as a dependency
|
||||
dep := &depgraph.Dependency{
|
||||
Name: pcName,
|
||||
Source: noun,
|
||||
|
@ -148,10 +178,12 @@ func graphAddVariableDeps(g *depgraph.Graph) {
|
|||
for _, n := range g.Nouns {
|
||||
var vars map[string]config.InterpolatedVariable
|
||||
switch m := n.Meta.(type) {
|
||||
case *config.Resource:
|
||||
vars = m.RawConfig.Variables
|
||||
case *config.ProviderConfig:
|
||||
vars = m.RawConfig.Variables
|
||||
case *GraphNodeResource:
|
||||
if !m.Orphan {
|
||||
vars = m.Config.RawConfig.Variables
|
||||
}
|
||||
case *GraphNodeResourceProvider:
|
||||
vars = m.Config.RawConfig.Variables
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -78,13 +78,6 @@ func New(c *Config) (*Terraform, error) {
|
|||
errs = append(errs, tpErrs...)
|
||||
}
|
||||
}
|
||||
|
||||
// Build the resource graph
|
||||
graph := c.Config.Graph()
|
||||
if err := graph.Validate(); err != nil {
|
||||
errs = append(errs, fmt.Errorf(
|
||||
"Resource graph has an error: %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
// If we accumulated any errors, then return them all
|
||||
|
@ -100,13 +93,13 @@ func New(c *Config) (*Terraform, error) {
|
|||
}
|
||||
|
||||
func (t *Terraform) Apply(p *Plan) (*State, error) {
|
||||
graph := t.config.Graph()
|
||||
if err := graph.Validate(); err != nil {
|
||||
panic(fmt.Sprintf("Graph invalid after prior validation: %s", err))
|
||||
graph, err := t.Graph(p.Config, p.State)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := new(State)
|
||||
err := graph.Walk(t.applyWalkFn(p, result))
|
||||
err = graph.Walk(t.applyWalkFn(p, result))
|
||||
return result, err
|
||||
}
|
||||
|
||||
|
@ -116,22 +109,27 @@ func (t *Terraform) Apply(p *Plan) (*State, error) {
|
|||
// The resulting graph may have more resources than the configuration, because
|
||||
// it can contain resources in the state file that need to be modified.
|
||||
func (t *Terraform) Graph(c *config.Config, s *State) (*depgraph.Graph, error) {
|
||||
// Get the basic graph with the raw metadata
|
||||
g := Graph(c, s)
|
||||
if err := g.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Next, we want to go through the graph and make sure that we
|
||||
// map a provider to each of the resources.
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func (t *Terraform) Plan(s *State) (*Plan, error) {
|
||||
graph := t.config.Graph()
|
||||
if err := graph.Validate(); err != nil {
|
||||
panic(fmt.Sprintf("Graph invalid after prior validation: %s", err))
|
||||
// TODO: add config param
|
||||
graph, err := t.Graph(nil, s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := new(Plan)
|
||||
err := graph.Walk(t.planWalkFn(s, result))
|
||||
err = graph.Walk(t.planWalkFn(s, result))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue