From 0986d0122302e89ec88d4258751f9c69f79c77a4 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Tue, 31 Oct 2017 13:13:24 -0400 Subject: [PATCH] add providers directly from the configuration The first step in only using the required provider nodes in a graph is to be able to specifically add them from the configuration. The MissingProviderTransformer was previously responsible for adding all providers. Now it is really just adding any that are missing from the config. --- terraform/graph_builder_apply.go | 7 +++ terraform/graph_builder_plan.go | 7 +++ terraform/transform_config.go | 75 ++++++++++++++++++++++++++++++++ terraform/transform_provider.go | 30 +++++++------ 4 files changed, 105 insertions(+), 14 deletions(-) diff --git a/terraform/graph_builder_apply.go b/terraform/graph_builder_apply.go index 430195c7f..1b898926e 100644 --- a/terraform/graph_builder_apply.go +++ b/terraform/graph_builder_apply.go @@ -87,6 +87,13 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer { // Attach the state &AttachStateTransformer{State: b.State}, + // add configured providers + &ProviderConfigTransformer{ + Module: b.Module, + Providers: b.Providers, + Concrete: concreteProvider, + }, + // Create all the providers &MissingProviderTransformer{Providers: b.Providers, Concrete: concreteProvider}, &ProviderTransformer{}, diff --git a/terraform/graph_builder_plan.go b/terraform/graph_builder_plan.go index 429e42481..1b93a5ab3 100644 --- a/terraform/graph_builder_plan.go +++ b/terraform/graph_builder_plan.go @@ -93,6 +93,13 @@ func (b *PlanGraphBuilder) Steps() []GraphTransformer { // Add root variables &RootVariableTransformer{Module: b.Module}, + // add configured providers + &ProviderConfigTransformer{ + Module: b.Module, + Providers: b.Providers, + Concrete: b.ConcreteProvider, + }, + // Create all the providers &MissingProviderTransformer{Providers: b.Providers, Concrete: b.ConcreteProvider}, &ProviderTransformer{}, diff --git a/terraform/transform_config.go b/terraform/transform_config.go index 61bce8532..7ec7744a7 100644 --- a/terraform/transform_config.go +++ b/terraform/transform_config.go @@ -133,3 +133,78 @@ func (t *ConfigTransformer) transformSingle(g *Graph, m *module.Tree) error { return nil } + +type ProviderConfigTransformer struct { + Providers []string + Concrete ConcreteProviderNodeFunc + + // Module is the module to add resources from. + Module *module.Tree +} + +func (t *ProviderConfigTransformer) Transform(g *Graph) error { + // If no module is given, we don't do anything + if t.Module == nil { + return nil + } + + // If the module isn't loaded, that is simply an error + if !t.Module.Loaded() { + return errors.New("module must be loaded for ProviderConfigTransformer") + } + + // Start the transformation process + return t.transform(g, t.Module) +} + +func (t *ProviderConfigTransformer) transform(g *Graph, m *module.Tree) error { + // If no config, do nothing + if m == nil { + return nil + } + + // Add our resources + if err := t.transformSingle(g, m); err != nil { + return err + } + + // Transform all the children. + for _, c := range m.Children() { + if err := t.transform(g, c); err != nil { + return err + } + } + + return nil +} + +func (t *ProviderConfigTransformer) transformSingle(g *Graph, m *module.Tree) error { + log.Printf("[TRACE] ProviderConfigTransformer: Starting for path: %v", m.Path()) + + // Get the configuration for this module + conf := m.Config() + + // Build the path we're at + path := m.Path() + if len(path) > 0 { + path = append([]string{RootModuleName}, path...) + } + + // Write all the resources out + for _, p := range conf.ProviderConfigs { + name := p.Name + if p.Alias != "" { + name += "." + p.Alias + } + + v := t.Concrete(&NodeAbstractProvider{ + NameValue: name, + PathValue: path, + }).(dag.Vertex) + + // Add it to the graph + g.Add(v) + } + + return nil +} diff --git a/terraform/transform_provider.go b/terraform/transform_provider.go index b9695d524..baf3016b9 100644 --- a/terraform/transform_provider.go +++ b/terraform/transform_provider.go @@ -104,10 +104,10 @@ func (t *CloseProviderTransformer) Transform(g *Graph) error { return err } -// MissingProviderTransformer is a GraphTransformer that adds nodes -// for missing providers into the graph. Specifically, it creates provider -// configuration nodes for all the providers that we support. These are -// pruned later during an optimization pass. +// MissingProviderTransformer is a GraphTransformer that adds nodes for all +// required providers into the graph. Specifically, it creates provider +// configuration nodes for all the providers that we support. These are pruned +// later during an optimization pass. type MissingProviderTransformer struct { // Providers is the list of providers we support. Providers []string @@ -160,6 +160,18 @@ func (t *MissingProviderTransformer) Transform(g *Graph) error { } for _, p := range pv.ProvidedBy() { + // always add the parent nodes to check, since configured providers + // may have already been added for modules. + if len(path) > 0 { + // We'll need the parent provider as well, so let's + // add a dummy node to check to make sure that we add + // that parent provider. + check = append(check, &graphNodeProviderConsumerDummy{ + ProviderValue: p, + PathValue: path[:len(path)-1], + }) + } + key := providerMapKey(p, pv) if _, ok := m[key]; ok { // This provider already exists as a configure node @@ -185,16 +197,6 @@ func (t *MissingProviderTransformer) Transform(g *Graph) error { NameValue: p, PathValue: path, }).(dag.Vertex) - if len(path) > 0 { - // We'll need the parent provider as well, so let's - // add a dummy node to check to make sure that we add - // that parent provider. - check = append(check, &graphNodeProviderConsumerDummy{ - ProviderValue: p, - PathValue: path[:len(path)-1], - }) - } - m[key] = g.Add(v) } }