terraform: abstract resource nodes
This commit is contained in:
parent
046faf247a
commit
6622ca001d
|
@ -2,6 +2,7 @@ package terraform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/hashicorp/terraform/config/module"
|
"github.com/hashicorp/terraform/config/module"
|
||||||
|
"github.com/hashicorp/terraform/dag"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ApplyGraphBuilder implements GraphBuilder and is responsible for building
|
// 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{
|
steps := []GraphTransformer{
|
||||||
// Creates all the nodes represented in the diff.
|
// Creates all the nodes represented in the diff.
|
||||||
&DiffTransformer{
|
&DiffTransformer{
|
||||||
|
Concrete: concreteResource,
|
||||||
|
|
||||||
Diff: b.Diff,
|
Diff: b.Diff,
|
||||||
Module: b.Module,
|
Module: b.Module,
|
||||||
State: b.State,
|
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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/config"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NodeApplyableResource represents a resource that is "applyable":
|
// NodeApplyableResource represents a resource that is "applyable":
|
||||||
// it is ready to be applied and is represented by a diff.
|
// it is ready to be applied and is represented by a diff.
|
||||||
type NodeApplyableResource struct {
|
type NodeApplyableResource struct {
|
||||||
Addr *ResourceAddress // Addr is the address for this resource
|
*NodeAbstractResource
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GraphNodeCreator
|
// GraphNodeCreator
|
||||||
func (n *NodeApplyableResource) CreateAddr() *ResourceAddress {
|
func (n *NodeApplyableResource) CreateAddr() *ResourceAddress {
|
||||||
return n.Addr
|
return n.NodeAbstractResource.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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GraphNodeEvalable
|
// GraphNodeEvalable
|
||||||
func (n *NodeApplyableResource) EvalTree() EvalNode {
|
func (n *NodeApplyableResource) EvalTree() EvalNode {
|
||||||
|
addr := n.NodeAbstractResource.Addr
|
||||||
|
|
||||||
// stateId is the ID to put into the state
|
// stateId is the ID to put into the state
|
||||||
stateId := n.Addr.stateId()
|
stateId := addr.stateId()
|
||||||
if n.Addr.Index > -1 {
|
if addr.Index > -1 {
|
||||||
stateId = fmt.Sprintf("%s.%d", stateId, n.Addr.Index)
|
stateId = fmt.Sprintf("%s.%d", stateId, addr.Index)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the instance info. More of this will be populated during eval
|
// Build the instance info. More of this will be populated during eval
|
||||||
info := &InstanceInfo{
|
info := &InstanceInfo{
|
||||||
Id: stateId,
|
Id: stateId,
|
||||||
Type: n.Addr.Type,
|
Type: addr.Type,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the resource for eval
|
// Build the resource for eval
|
||||||
resource := &Resource{
|
resource := &Resource{
|
||||||
Name: n.Addr.Name,
|
Name: addr.Name,
|
||||||
Type: n.Addr.Type,
|
Type: addr.Type,
|
||||||
CountIndex: n.Addr.Index,
|
CountIndex: addr.Index,
|
||||||
}
|
}
|
||||||
if resource.CountIndex < 0 {
|
if resource.CountIndex < 0 {
|
||||||
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
|
// 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
|
// find the dependencies we need to: build a graph and use the
|
||||||
// attach config and state transformers then ask for references.
|
// attach config and state transformers then ask for references.
|
||||||
node := &NodeApplyableResource{Addr: addr}
|
node := &NodeAbstractResource{Addr: addr}
|
||||||
{
|
{
|
||||||
var g Graph
|
var g Graph
|
||||||
g.Add(node)
|
g.Add(node)
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/config/module"
|
"github.com/hashicorp/terraform/config/module"
|
||||||
|
"github.com/hashicorp/terraform/dag"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DiffTransformer is a GraphTransformer that adds the elements of
|
// 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
|
// is built based on the diff first, though, ensuring that only resources
|
||||||
// that are being modified are present in the graph.
|
// that are being modified are present in the graph.
|
||||||
type DiffTransformer struct {
|
type DiffTransformer struct {
|
||||||
|
Concrete ConcreteResourceNodeFunc
|
||||||
|
|
||||||
Diff *Diff
|
Diff *Diff
|
||||||
Module *module.Tree
|
Module *module.Tree
|
||||||
State *State
|
State *State
|
||||||
|
@ -32,7 +35,7 @@ func (t *DiffTransformer) Transform(g *Graph) error {
|
||||||
|
|
||||||
// Go through all the modules in the diff.
|
// Go through all the modules in the diff.
|
||||||
log.Printf("[TRACE] DiffTransformer: starting")
|
log.Printf("[TRACE] DiffTransformer: starting")
|
||||||
var nodes []*NodeApplyableResource
|
var nodes []dag.Vertex
|
||||||
for _, m := range t.Diff.Modules {
|
for _, m := range t.Diff.Modules {
|
||||||
log.Printf("[TRACE] DiffTransformer: Module: %s", m)
|
log.Printf("[TRACE] DiffTransformer: Module: %s", m)
|
||||||
// TODO: If this is a destroy diff then add a module destroy node
|
// 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 we have changes, then add the applyable version
|
||||||
if len(inst.Attributes) > 0 {
|
if len(inst.Attributes) > 0 {
|
||||||
// Add the resource to the graph
|
// Add the resource to the graph
|
||||||
nodes = append(nodes, &NodeApplyableResource{
|
abstract := &NodeAbstractResource{Addr: addr}
|
||||||
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