terraform: new provider graph node for flattened world
This commit is contained in:
parent
b2ef4e9ac0
commit
79a742c1ae
|
@ -38,6 +38,14 @@ func (b *ApplyGraphBuilder) Build(path []string) (*Graph, error) {
|
||||||
|
|
||||||
// See GraphBuilder
|
// See GraphBuilder
|
||||||
func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
|
func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
|
||||||
|
// Custom factory for creating providers.
|
||||||
|
providerFactory := func(name string, path []string) GraphNodeProvider {
|
||||||
|
return &NodeApplyableProvider{
|
||||||
|
NameValue: name,
|
||||||
|
PathValue: path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
steps := []GraphTransformer{
|
steps := []GraphTransformer{
|
||||||
// Creates all the nodes represented in the diff.
|
// Creates all the nodes represented in the diff.
|
||||||
&DiffTransformer{
|
&DiffTransformer{
|
||||||
|
@ -47,10 +55,13 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
|
||||||
},
|
},
|
||||||
|
|
||||||
// Create all the providers
|
// Create all the providers
|
||||||
&MissingProviderTransformer{Providers: b.Providers},
|
&MissingProviderTransformer{Providers: b.Providers, Factory: providerFactory},
|
||||||
&ProviderTransformer{},
|
&ProviderTransformer{},
|
||||||
&ParentProviderTransformer{},
|
&ParentProviderTransformer{},
|
||||||
|
|
||||||
|
// Attach the configurations
|
||||||
|
&AttachConfigTransformer{Module: b.Module},
|
||||||
|
|
||||||
// Single root
|
// Single root
|
||||||
&RootTransformer{},
|
&RootTransformer{},
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
package terraform
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NodeApplyableProvider represents a provider during an apply.
|
||||||
|
//
|
||||||
|
// NOTE: There is a lot of logic here that will be shared with non-Apply.
|
||||||
|
// The plan is to abstract that eventually into an embedded abstract struct.
|
||||||
|
type NodeApplyableProvider struct {
|
||||||
|
NameValue string
|
||||||
|
PathValue []string
|
||||||
|
Config *config.ProviderConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NodeApplyableProvider) Name() string {
|
||||||
|
result := fmt.Sprintf("provider.%s", n.NameValue)
|
||||||
|
if len(n.PathValue) > 1 {
|
||||||
|
result = fmt.Sprintf("%s.%s", modulePrefixStr(n.PathValue), result)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// GraphNodeSubPath
|
||||||
|
func (n *NodeApplyableProvider) Path() []string {
|
||||||
|
return n.PathValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// GraphNodeProvider
|
||||||
|
func (n *NodeApplyableProvider) ProviderName() string {
|
||||||
|
return n.NameValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// GraphNodeProvider
|
||||||
|
func (n *NodeApplyableProvider) ProviderConfig() *config.RawConfig {
|
||||||
|
if n.Config == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return n.Config.RawConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// GraphNodeAttachProvider
|
||||||
|
func (n *NodeApplyableProvider) AttachProvider(c *config.ProviderConfig) {
|
||||||
|
n.Config = c
|
||||||
|
}
|
||||||
|
|
||||||
|
// GraphNodeEvalable
|
||||||
|
func (n *NodeApplyableProvider) EvalTree() EvalNode {
|
||||||
|
return ProviderEvalTree(n.NameValue, nil)
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
package terraform
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/config"
|
||||||
|
"github.com/hashicorp/terraform/config/module"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GraphNodeAttachProvider is an interface that must be implemented by nodes
|
||||||
|
// that want provider configurations attached.
|
||||||
|
type GraphNodeAttachProvider interface {
|
||||||
|
// Must be implemented to determine the path for the configuration
|
||||||
|
GraphNodeSubPath
|
||||||
|
|
||||||
|
// ProviderName with no module prefix. Example: "aws".
|
||||||
|
ProviderName() string
|
||||||
|
|
||||||
|
// Sets the configuration
|
||||||
|
AttachProvider(*config.ProviderConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AttachConfigTransformer goes through the graph and attaches configuration
|
||||||
|
// structures to nodes that implement the interfaces above.
|
||||||
|
//
|
||||||
|
// The attached configuration structures are directly from the configuration.
|
||||||
|
// If they're going to be modified, a copy should be made.
|
||||||
|
type AttachConfigTransformer struct {
|
||||||
|
Module *module.Tree // Module is the root module for the config
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *AttachConfigTransformer) Transform(g *Graph) error {
|
||||||
|
if err := t.attachProviders(g); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *AttachConfigTransformer) attachProviders(g *Graph) error {
|
||||||
|
// Go through and find GraphNodeAttachProvider
|
||||||
|
for _, v := range g.Vertices() {
|
||||||
|
// Only care about GraphNodeAttachProvider implementations
|
||||||
|
apn, ok := v.(GraphNodeAttachProvider)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: aliases?
|
||||||
|
|
||||||
|
// Determine what we're looking for
|
||||||
|
path := normalizeModulePath(apn.Path())
|
||||||
|
path = path[1:]
|
||||||
|
name := apn.ProviderName()
|
||||||
|
log.Printf("[TRACE] Attach provider request: %#v %s", path, name)
|
||||||
|
|
||||||
|
// Get the configuration.
|
||||||
|
tree := t.Module.Child(path)
|
||||||
|
if tree == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go through the provider configs to find the matching config
|
||||||
|
for _, p := range tree.Config().ProviderConfigs {
|
||||||
|
if p.Name == name {
|
||||||
|
log.Printf("[TRACE] Attaching provider config: %#v", p)
|
||||||
|
apn.AttachProvider(p)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -163,9 +163,19 @@ func (t *CloseProviderTransformer) Transform(g *Graph) error {
|
||||||
type MissingProviderTransformer struct {
|
type MissingProviderTransformer struct {
|
||||||
// Providers is the list of providers we support.
|
// Providers is the list of providers we support.
|
||||||
Providers []string
|
Providers []string
|
||||||
|
|
||||||
|
// Factory, if set, overrides how the providers are made.
|
||||||
|
Factory func(name string, path []string) GraphNodeProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *MissingProviderTransformer) Transform(g *Graph) error {
|
func (t *MissingProviderTransformer) Transform(g *Graph) error {
|
||||||
|
// Initialize factory
|
||||||
|
if t.Factory == nil {
|
||||||
|
t.Factory = func(name string, path []string) GraphNodeProvider {
|
||||||
|
return &graphNodeProvider{ProviderNameValue: name}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create a set of our supported providers
|
// Create a set of our supported providers
|
||||||
supported := make(map[string]struct{}, len(t.Providers))
|
supported := make(map[string]struct{}, len(t.Providers))
|
||||||
for _, v := range t.Providers {
|
for _, v := range t.Providers {
|
||||||
|
@ -217,17 +227,14 @@ func (t *MissingProviderTransformer) Transform(g *Graph) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the missing provider node to the graph
|
// Add the missing provider node to the graph
|
||||||
raw := &graphNodeProvider{
|
v := t.Factory(p, path).(dag.Vertex)
|
||||||
ProviderNameValue: p,
|
|
||||||
PathValue: path,
|
|
||||||
}
|
|
||||||
|
|
||||||
var v dag.Vertex = raw
|
|
||||||
if len(path) > 0 {
|
if len(path) > 0 {
|
||||||
var err error
|
if fn, ok := v.(GraphNodeFlattenable); ok {
|
||||||
v, err = raw.Flatten(path)
|
var err error
|
||||||
if err != nil {
|
v, err = fn.Flatten(path)
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll need the parent provider as well, so let's
|
// We'll need the parent provider as well, so let's
|
||||||
|
@ -347,7 +354,12 @@ func providerVertexMap(g *Graph) map[string]dag.Vertex {
|
||||||
m := make(map[string]dag.Vertex)
|
m := make(map[string]dag.Vertex)
|
||||||
for _, v := range g.Vertices() {
|
for _, v := range g.Vertices() {
|
||||||
if pv, ok := v.(GraphNodeProvider); ok {
|
if pv, ok := v.(GraphNodeProvider); ok {
|
||||||
m[pv.ProviderName()] = v
|
key := pv.ProviderName()
|
||||||
|
if _, ok := v.(*NodeApplyableProvider); ok {
|
||||||
|
key = providerMapKey(pv.ProviderName(), v)
|
||||||
|
}
|
||||||
|
|
||||||
|
m[key] = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,7 +524,6 @@ func (n *graphNodeCloseProvider) DotNode(name string, opts *GraphDotOpts) *dot.N
|
||||||
|
|
||||||
type graphNodeProvider struct {
|
type graphNodeProvider struct {
|
||||||
ProviderNameValue string
|
ProviderNameValue string
|
||||||
PathValue []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *graphNodeProvider) Name() string {
|
func (n *graphNodeProvider) Name() string {
|
||||||
|
@ -529,6 +540,7 @@ func (n *graphNodeProvider) DependableName() []string {
|
||||||
return []string{n.Name()}
|
return []string{n.Name()}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GraphNodeProvider
|
||||||
func (n *graphNodeProvider) ProviderName() string {
|
func (n *graphNodeProvider) ProviderName() string {
|
||||||
return n.ProviderNameValue
|
return n.ProviderNameValue
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue