terraform: abstract resource nodes
This commit is contained in:
parent
046faf247a
commit
6622ca001d
|
@ -2,6 +2,7 @@ package terraform
|
|||
|
||||
import (
|
||||
"github.com/hashicorp/terraform/config/module"
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
)
|
||||
|
||||
// ApplyGraphBuilder implements GraphBuilder and is responsible for building
|
||||
|
@ -46,9 +47,17 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
|
|||
}
|
||||
}
|
||||
|
||||
concreteResource := func(a *NodeAbstractResource) dag.Vertex {
|
||||
return &NodeApplyableResource{
|
||||
NodeAbstractResource: a,
|
||||
}
|
||||
}
|
||||
|
||||
steps := []GraphTransformer{
|
||||
// Creates all the nodes represented in the diff.
|
||||
&DiffTransformer{
|
||||
Concrete: concreteResource,
|
||||
|
||||
Diff: b.Diff,
|
||||
Module: b.Module,
|
||||
State: b.State,
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
package terraform
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform/config"
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
)
|
||||
|
||||
// ConcreteResourceNodeFunc is a callback type used to convert an
|
||||
// abstract resource to a concrete one of some type.
|
||||
type ConcreteResourceNodeFunc func(*NodeAbstractResource) dag.Vertex
|
||||
|
||||
// NodeAbstractResource represents a resource that has no associated
|
||||
// operations. It registers all the interfaces for a resource that common
|
||||
// across multiple operation types.
|
||||
type NodeAbstractResource struct {
|
||||
Addr *ResourceAddress // Addr is the address for this resource
|
||||
|
||||
// The fields below will be automatically set using the Attach
|
||||
// interfaces if you're running those transforms, but also be explicitly
|
||||
// set if you already have that information.
|
||||
|
||||
Config *config.Resource // Config is the resource in the config
|
||||
ResourceState *ResourceState // ResourceState is the ResourceState for this
|
||||
}
|
||||
|
||||
func (n *NodeAbstractResource) Name() string {
|
||||
return n.Addr.String()
|
||||
}
|
||||
|
||||
// GraphNodeSubPath
|
||||
func (n *NodeAbstractResource) Path() []string {
|
||||
return n.Addr.Path
|
||||
}
|
||||
|
||||
// GraphNodeReferenceable
|
||||
func (n *NodeAbstractResource) ReferenceableName() []string {
|
||||
if n.Config == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return []string{n.Config.Id()}
|
||||
}
|
||||
|
||||
// GraphNodeReferencer
|
||||
func (n *NodeAbstractResource) References() []string {
|
||||
// If we have a config, that is our source of truth
|
||||
if c := n.Config; c != nil {
|
||||
// Grab all the references
|
||||
var result []string
|
||||
result = append(result, c.DependsOn...)
|
||||
result = append(result, ReferencesFromConfig(c.RawCount)...)
|
||||
result = append(result, ReferencesFromConfig(c.RawConfig)...)
|
||||
for _, p := range c.Provisioners {
|
||||
result = append(result, ReferencesFromConfig(p.ConnInfo)...)
|
||||
result = append(result, ReferencesFromConfig(p.RawConfig)...)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// If we have state, that is our next source
|
||||
if s := n.ResourceState; s != nil {
|
||||
return s.Dependencies
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GraphNodeProviderConsumer
|
||||
func (n *NodeAbstractResource) ProvidedBy() []string {
|
||||
// If we have a config we prefer that above all else
|
||||
if n.Config != nil {
|
||||
return []string{resourceProvider(n.Config.Type, n.Config.Provider)}
|
||||
}
|
||||
|
||||
// If we have state, then we will use the provider from there
|
||||
if n.ResourceState != nil {
|
||||
return []string{n.ResourceState.Provider}
|
||||
}
|
||||
|
||||
// Use our type
|
||||
return []string{resourceProvider(n.Addr.Type, "")}
|
||||
}
|
||||
|
||||
// GraphNodeProvisionerConsumer
|
||||
func (n *NodeAbstractResource) ProvisionedBy() []string {
|
||||
// If we have no configuration, then we have no provisioners
|
||||
if n.Config == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build the list of provisioners we need based on the configuration.
|
||||
// It is okay to have duplicates here.
|
||||
result := make([]string, len(n.Config.Provisioners))
|
||||
for i, p := range n.Config.Provisioners {
|
||||
result[i] = p.Type
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// GraphNodeAttachResourceState
|
||||
func (n *NodeAbstractResource) ResourceAddr() *ResourceAddress {
|
||||
return n.Addr
|
||||
}
|
||||
|
||||
// GraphNodeAttachResourceState
|
||||
func (n *NodeAbstractResource) AttachResourceState(s *ResourceState) {
|
||||
n.ResourceState = s
|
||||
}
|
||||
|
||||
// GraphNodeAttachResourceConfig
|
||||
func (n *NodeAbstractResource) AttachResourceConfig(c *config.Resource) {
|
||||
n.Config = c
|
||||
}
|
|
@ -2,133 +2,40 @@ package terraform
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/terraform/config"
|
||||
)
|
||||
|
||||
// NodeApplyableResource represents a resource that is "applyable":
|
||||
// it is ready to be applied and is represented by a diff.
|
||||
type NodeApplyableResource struct {
|
||||
Addr *ResourceAddress // Addr is the address for this resource
|
||||
Config *config.Resource // Config is the resource in the config
|
||||
ResourceState *ResourceState // ResourceState is the ResourceState for this
|
||||
}
|
||||
|
||||
func (n *NodeApplyableResource) Name() string {
|
||||
return n.Addr.String()
|
||||
}
|
||||
|
||||
// GraphNodeSubPath
|
||||
func (n *NodeApplyableResource) Path() []string {
|
||||
return n.Addr.Path
|
||||
}
|
||||
|
||||
// GraphNodeReferenceable
|
||||
func (n *NodeApplyableResource) ReferenceableName() []string {
|
||||
if n.Config == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return []string{n.Config.Id()}
|
||||
}
|
||||
|
||||
// GraphNodeReferencer
|
||||
func (n *NodeApplyableResource) References() []string {
|
||||
// If we have a config, that is our source of truth
|
||||
if c := n.Config; c != nil {
|
||||
// Grab all the references
|
||||
var result []string
|
||||
result = append(result, c.DependsOn...)
|
||||
result = append(result, ReferencesFromConfig(c.RawCount)...)
|
||||
result = append(result, ReferencesFromConfig(c.RawConfig)...)
|
||||
for _, p := range c.Provisioners {
|
||||
result = append(result, ReferencesFromConfig(p.ConnInfo)...)
|
||||
result = append(result, ReferencesFromConfig(p.RawConfig)...)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// If we have state, that is our next source
|
||||
if s := n.ResourceState; s != nil {
|
||||
return s.Dependencies
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GraphNodeProviderConsumer
|
||||
func (n *NodeApplyableResource) ProvidedBy() []string {
|
||||
// If we have a config we prefer that above all else
|
||||
if n.Config != nil {
|
||||
return []string{resourceProvider(n.Config.Type, n.Config.Provider)}
|
||||
}
|
||||
|
||||
// If we have state, then we will use the provider from there
|
||||
if n.ResourceState != nil {
|
||||
return []string{n.ResourceState.Provider}
|
||||
}
|
||||
|
||||
// Use our type
|
||||
return []string{resourceProvider(n.Addr.Type, "")}
|
||||
}
|
||||
|
||||
// GraphNodeProvisionerConsumer
|
||||
func (n *NodeApplyableResource) ProvisionedBy() []string {
|
||||
// If we have no configuration, then we have no provisioners
|
||||
if n.Config == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build the list of provisioners we need based on the configuration.
|
||||
// It is okay to have duplicates here.
|
||||
result := make([]string, len(n.Config.Provisioners))
|
||||
for i, p := range n.Config.Provisioners {
|
||||
result[i] = p.Type
|
||||
}
|
||||
|
||||
return result
|
||||
*NodeAbstractResource
|
||||
}
|
||||
|
||||
// GraphNodeCreator
|
||||
func (n *NodeApplyableResource) CreateAddr() *ResourceAddress {
|
||||
return n.Addr
|
||||
}
|
||||
|
||||
// GraphNodeAttachResourceState
|
||||
func (n *NodeApplyableResource) ResourceAddr() *ResourceAddress {
|
||||
return n.Addr
|
||||
}
|
||||
|
||||
// GraphNodeAttachResource
|
||||
func (n *NodeApplyableResource) AttachResourceConfig(c *config.Resource) {
|
||||
n.Config = c
|
||||
}
|
||||
|
||||
// GraphNodeAttachResourceState
|
||||
func (n *NodeApplyableResource) AttachResourceState(s *ResourceState) {
|
||||
n.ResourceState = s
|
||||
return n.NodeAbstractResource.Addr
|
||||
}
|
||||
|
||||
// GraphNodeEvalable
|
||||
func (n *NodeApplyableResource) EvalTree() EvalNode {
|
||||
addr := n.NodeAbstractResource.Addr
|
||||
|
||||
// stateId is the ID to put into the state
|
||||
stateId := n.Addr.stateId()
|
||||
if n.Addr.Index > -1 {
|
||||
stateId = fmt.Sprintf("%s.%d", stateId, n.Addr.Index)
|
||||
stateId := addr.stateId()
|
||||
if addr.Index > -1 {
|
||||
stateId = fmt.Sprintf("%s.%d", stateId, addr.Index)
|
||||
}
|
||||
|
||||
// Build the instance info. More of this will be populated during eval
|
||||
info := &InstanceInfo{
|
||||
Id: stateId,
|
||||
Type: n.Addr.Type,
|
||||
Type: addr.Type,
|
||||
}
|
||||
|
||||
// Build the resource for eval
|
||||
resource := &Resource{
|
||||
Name: n.Addr.Name,
|
||||
Type: n.Addr.Type,
|
||||
CountIndex: n.Addr.Index,
|
||||
Name: addr.Name,
|
||||
Type: addr.Type,
|
||||
CountIndex: addr.Index,
|
||||
}
|
||||
if resource.CountIndex < 0 {
|
||||
resource.CountIndex = 0
|
||||
|
|
|
@ -134,7 +134,7 @@ func (t *DestroyEdgeTransformer) Transform(g *Graph) error {
|
|||
// This part is a little bit weird but is the best way to
|
||||
// find the dependencies we need to: build a graph and use the
|
||||
// attach config and state transformers then ask for references.
|
||||
node := &NodeApplyableResource{Addr: addr}
|
||||
node := &NodeAbstractResource{Addr: addr}
|
||||
{
|
||||
var g Graph
|
||||
g.Add(node)
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"log"
|
||||
|
||||
"github.com/hashicorp/terraform/config/module"
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
)
|
||||
|
||||
// DiffTransformer is a GraphTransformer that adds the elements of
|
||||
|
@ -19,6 +20,8 @@ import (
|
|||
// is built based on the diff first, though, ensuring that only resources
|
||||
// that are being modified are present in the graph.
|
||||
type DiffTransformer struct {
|
||||
Concrete ConcreteResourceNodeFunc
|
||||
|
||||
Diff *Diff
|
||||
Module *module.Tree
|
||||
State *State
|
||||
|
@ -32,7 +35,7 @@ func (t *DiffTransformer) Transform(g *Graph) error {
|
|||
|
||||
// Go through all the modules in the diff.
|
||||
log.Printf("[TRACE] DiffTransformer: starting")
|
||||
var nodes []*NodeApplyableResource
|
||||
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
|
||||
|
@ -62,9 +65,13 @@ func (t *DiffTransformer) Transform(g *Graph) error {
|
|||
// If we have changes, then add the applyable version
|
||||
if len(inst.Attributes) > 0 {
|
||||
// Add the resource to the graph
|
||||
nodes = append(nodes, &NodeApplyableResource{
|
||||
Addr: addr,
|
||||
})
|
||||
abstract := &NodeAbstractResource{Addr: addr}
|
||||
var node dag.Vertex = abstract
|
||||
if f := t.Concrete; f != nil {
|
||||
node = f(abstract)
|
||||
}
|
||||
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue