connect non-resources to providers they reference

Any non-resource (outputs, variables, locals) that references a resource
type must also be connected to that resources provider. This is required
during apply, because the graph built from the diff may not include the
referenced resources because they are being evaluated from the state.

If the provider isn't present already, add a NodeEvalableProvider to
fetch the provider schema.

The provider transformers now need to happen after the outputs, locals,
and variables are transformed.
This commit is contained in:
James Bardin 2018-05-25 19:27:11 -04:00 committed by Martin Atkins
parent 1f859ba8d4
commit 4d2da4d733
5 changed files with 45 additions and 8 deletions

View File

@ -84,9 +84,6 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
// Attach the state
&AttachStateTransformer{State: b.State},
// add providers
TransformProviders(b.Components.ResourceProviders(), concreteProvider, b.Config),
// Destruction ordering
&DestroyEdgeTransformer{
Config: b.Config,
@ -118,6 +115,9 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
// Add module variables
&ModuleVariableTransformer{Config: b.Config},
// add providers
TransformProviders(b.Components.ResourceProviders(), concreteProvider, b.Config),
// Remove modules no longer present in the config
&RemovedModuleTransformer{Config: b.Config, State: b.State},

View File

@ -101,8 +101,6 @@ func (b *PlanGraphBuilder) Steps() []GraphTransformer {
// Add root variables
&RootVariableTransformer{Config: b.Config},
TransformProviders(b.Components.ResourceProviders(), b.ConcreteProvider, b.Config),
&MissingProvisionerTransformer{Provisioners: b.Components.ResourceProvisioners()},
&AttachSchemaTransformer{Components: b.Components},
@ -112,6 +110,8 @@ func (b *PlanGraphBuilder) Steps() []GraphTransformer {
Config: b.Config,
},
TransformProviders(b.Components.ResourceProviders(), b.ConcreteProvider, b.Config),
// Remove modules no longer present in the config
&RemovedModuleTransformer{Config: b.Config, State: b.State},

View File

@ -125,8 +125,6 @@ func (b *RefreshGraphBuilder) Steps() []GraphTransformer {
// Add root variables
&RootVariableTransformer{Config: b.Config},
TransformProviders(b.Components.ResourceProviders(), concreteProvider, b.Config),
// Add the local values
&LocalTransformer{Config: b.Config},
@ -136,6 +134,8 @@ func (b *RefreshGraphBuilder) Steps() []GraphTransformer {
// Add module variables
&ModuleVariableTransformer{Config: b.Config},
TransformProviders(b.Components.ResourceProviders(), concreteProvider, b.Config),
// Must be before ReferenceTransformer, since schema is required to
// extract references from config.
&AttachSchemaTransformer{Components: b.Components},

View File

@ -2,7 +2,7 @@ resource "aws_instance" "foo" {
}
output "instance_id" {
# Even though we're targeting just the resource a bove, this should still
# Even though we're targeting just the resource above, this should still
# be populated because outputs are implicitly targeted when their
# dependencies are
value = "${aws_instance.foo.id}"

View File

@ -134,6 +134,43 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
pv.SetProvider(target.ProviderAddr())
g.Connect(dag.BasicEdge(v, target))
}
if pv, ok := v.(GraphNodeReferencer); ok {
// not a provider consumer, so check if this node references any
// providers
for _, r := range pv.References() {
var res addrs.Resource
switch sub := r.Subject.(type) {
case addrs.ResourceInstance:
res = sub.Resource
case addrs.Resource:
res = sub
default:
continue
}
providerCfg := res.DefaultProviderConfig()
providerName := providerCfg.String()
provider := m[providerName]
if provider == nil {
// create the missing top-level provider
// This provider node will only be initialized to provide
// the schema for its referrers.
provider = &NodeEvalableProvider{
&NodeAbstractProvider{
Addr: addrs.RootModuleInstance.ProviderConfigDefault(providerCfg.Type),
},
}
g.Add(provider)
m[providerName] = provider
}
log.Printf("[DEBUG] %s references %s", dag.VertexName(pv), providerName)
g.Connect(dag.BasicEdge(pv, provider))
}
}
}
return err