github.com/r3labs/terraform@v0.8.4/terraform/node_resource_abstract.go (about) 1 package terraform 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/terraform/config" 7 "github.com/hashicorp/terraform/dag" 8 ) 9 10 // ConcreteResourceNodeFunc is a callback type used to convert an 11 // abstract resource to a concrete one of some type. 12 type ConcreteResourceNodeFunc func(*NodeAbstractResource) dag.Vertex 13 14 // GraphNodeResource is implemented by any nodes that represent a resource. 15 // The type of operation cannot be assumed, only that this node represents 16 // the given resource. 17 type GraphNodeResource interface { 18 ResourceAddr() *ResourceAddress 19 } 20 21 // NodeAbstractResource represents a resource that has no associated 22 // operations. It registers all the interfaces for a resource that common 23 // across multiple operation types. 24 type NodeAbstractResource struct { 25 Addr *ResourceAddress // Addr is the address for this resource 26 27 // The fields below will be automatically set using the Attach 28 // interfaces if you're running those transforms, but also be explicitly 29 // set if you already have that information. 30 31 Config *config.Resource // Config is the resource in the config 32 ResourceState *ResourceState // ResourceState is the ResourceState for this 33 34 Targets []ResourceAddress // Set from GraphNodeTargetable 35 } 36 37 func (n *NodeAbstractResource) Name() string { 38 return n.Addr.String() 39 } 40 41 // GraphNodeSubPath 42 func (n *NodeAbstractResource) Path() []string { 43 return n.Addr.Path 44 } 45 46 // GraphNodeReferenceable 47 func (n *NodeAbstractResource) ReferenceableName() []string { 48 // We always are referenceable as "type.name" as long as 49 // we have a config or address. Determine what that value is. 50 var id string 51 if n.Config != nil { 52 id = n.Config.Id() 53 } else if n.Addr != nil { 54 addrCopy := n.Addr.Copy() 55 addrCopy.Index = -1 56 id = addrCopy.String() 57 } else { 58 // No way to determine our type.name, just return 59 return nil 60 } 61 62 var result []string 63 64 // Always include our own ID. This is primarily for backwards 65 // compatibility with states that didn't yet support the more 66 // specific dep string. 67 result = append(result, id) 68 69 // We represent all multi-access 70 result = append(result, fmt.Sprintf("%s.*", id)) 71 72 // We represent either a specific number, or all numbers 73 suffix := "N" 74 if n.Addr != nil { 75 idx := n.Addr.Index 76 if idx == -1 { 77 idx = 0 78 } 79 80 suffix = fmt.Sprintf("%d", idx) 81 } 82 result = append(result, fmt.Sprintf("%s.%s", id, suffix)) 83 84 return result 85 } 86 87 // GraphNodeReferencer 88 func (n *NodeAbstractResource) References() []string { 89 // If we have a config, that is our source of truth 90 if c := n.Config; c != nil { 91 // Grab all the references 92 var result []string 93 result = append(result, c.DependsOn...) 94 result = append(result, ReferencesFromConfig(c.RawCount)...) 95 result = append(result, ReferencesFromConfig(c.RawConfig)...) 96 for _, p := range c.Provisioners { 97 result = append(result, ReferencesFromConfig(p.ConnInfo)...) 98 result = append(result, ReferencesFromConfig(p.RawConfig)...) 99 } 100 101 return result 102 } 103 104 // If we have state, that is our next source 105 if s := n.ResourceState; s != nil { 106 return s.Dependencies 107 } 108 109 return nil 110 } 111 112 // GraphNodeProviderConsumer 113 func (n *NodeAbstractResource) ProvidedBy() []string { 114 // If we have a config we prefer that above all else 115 if n.Config != nil { 116 return []string{resourceProvider(n.Config.Type, n.Config.Provider)} 117 } 118 119 // If we have state, then we will use the provider from there 120 if n.ResourceState != nil && n.ResourceState.Provider != "" { 121 return []string{n.ResourceState.Provider} 122 } 123 124 // Use our type 125 return []string{resourceProvider(n.Addr.Type, "")} 126 } 127 128 // GraphNodeProvisionerConsumer 129 func (n *NodeAbstractResource) ProvisionedBy() []string { 130 // If we have no configuration, then we have no provisioners 131 if n.Config == nil { 132 return nil 133 } 134 135 // Build the list of provisioners we need based on the configuration. 136 // It is okay to have duplicates here. 137 result := make([]string, len(n.Config.Provisioners)) 138 for i, p := range n.Config.Provisioners { 139 result[i] = p.Type 140 } 141 142 return result 143 } 144 145 // GraphNodeResource, GraphNodeAttachResourceState 146 func (n *NodeAbstractResource) ResourceAddr() *ResourceAddress { 147 return n.Addr 148 } 149 150 // GraphNodeAddressable, TODO: remove, used by target, should unify 151 func (n *NodeAbstractResource) ResourceAddress() *ResourceAddress { 152 return n.ResourceAddr() 153 } 154 155 // GraphNodeTargetable 156 func (n *NodeAbstractResource) SetTargets(targets []ResourceAddress) { 157 n.Targets = targets 158 } 159 160 // GraphNodeAttachResourceState 161 func (n *NodeAbstractResource) AttachResourceState(s *ResourceState) { 162 n.ResourceState = s 163 } 164 165 // GraphNodeAttachResourceConfig 166 func (n *NodeAbstractResource) AttachResourceConfig(c *config.Resource) { 167 n.Config = c 168 } 169 170 // GraphNodeDotter impl. 171 func (n *NodeAbstractResource) DotNode(name string, opts *dag.DotOpts) *dag.DotNode { 172 return &dag.DotNode{ 173 Name: name, 174 Attrs: map[string]string{ 175 "label": n.Name(), 176 "shape": "box", 177 }, 178 } 179 }