2018-05-02 22:16:22 -05:00
|
|
|
package terraform
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
|
2020-03-06 07:33:44 -06:00
|
|
|
"github.com/hashicorp/terraform/addrs"
|
2020-03-10 13:43:57 -05:00
|
|
|
"github.com/hashicorp/terraform/configs"
|
2018-07-05 12:33:29 -05:00
|
|
|
"github.com/hashicorp/terraform/configs/configschema"
|
2018-05-31 14:39:45 -05:00
|
|
|
"github.com/hashicorp/terraform/dag"
|
2018-05-02 22:16:22 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
// GraphNodeAttachResourceSchema is an interface implemented by node types
|
|
|
|
// that need a resource schema attached.
|
|
|
|
type GraphNodeAttachResourceSchema interface {
|
|
|
|
GraphNodeResource
|
|
|
|
GraphNodeProviderConsumer
|
|
|
|
|
2018-11-27 17:30:18 -06:00
|
|
|
AttachResourceSchema(schema *configschema.Block, version uint64)
|
2018-05-02 22:16:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// GraphNodeAttachProviderConfigSchema is an interface implemented by node types
|
|
|
|
// that need a provider configuration schema attached.
|
|
|
|
type GraphNodeAttachProviderConfigSchema interface {
|
|
|
|
GraphNodeProvider
|
|
|
|
|
|
|
|
AttachProviderConfigSchema(*configschema.Block)
|
|
|
|
}
|
|
|
|
|
2018-05-24 18:00:26 -05:00
|
|
|
// GraphNodeAttachProvisionerSchema is an interface implemented by node types
|
|
|
|
// that need one or more provisioner schemas attached.
|
|
|
|
type GraphNodeAttachProvisionerSchema interface {
|
|
|
|
ProvisionedBy() []string
|
|
|
|
|
|
|
|
// SetProvisionerSchema is called during transform for each provisioner
|
|
|
|
// type returned from ProvisionedBy, providing the configuration schema
|
|
|
|
// for each provisioner in turn. The implementer should save these for
|
|
|
|
// later use in evaluating provisioner configuration blocks.
|
|
|
|
AttachProvisionerSchema(name string, schema *configschema.Block)
|
|
|
|
}
|
|
|
|
|
|
|
|
// AttachSchemaTransformer finds nodes that implement
|
|
|
|
// GraphNodeAttachResourceSchema, GraphNodeAttachProviderConfigSchema, or
|
|
|
|
// GraphNodeAttachProvisionerSchema, looks up the needed schemas for each
|
|
|
|
// and then passes them to a method implemented by the node.
|
2018-05-02 22:16:22 -05:00
|
|
|
type AttachSchemaTransformer struct {
|
2018-05-31 14:39:45 -05:00
|
|
|
Schemas *Schemas
|
2020-03-10 13:43:57 -05:00
|
|
|
Config *configs.Config
|
2018-05-02 22:16:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t *AttachSchemaTransformer) Transform(g *Graph) error {
|
2018-05-31 14:39:45 -05:00
|
|
|
if t.Schemas == nil {
|
2018-05-09 18:56:23 -05:00
|
|
|
// Should never happen with a reasonable caller, but we'll return a
|
|
|
|
// proper error here anyway so that we'll fail gracefully.
|
2018-05-31 14:39:45 -05:00
|
|
|
return fmt.Errorf("AttachSchemaTransformer used with nil Schemas")
|
2018-05-09 18:56:23 -05:00
|
|
|
}
|
|
|
|
|
2018-05-02 22:16:22 -05:00
|
|
|
for _, v := range g.Vertices() {
|
2018-05-31 19:14:20 -05:00
|
|
|
|
|
|
|
if tv, ok := v.(GraphNodeAttachResourceSchema); ok {
|
2018-05-02 22:16:22 -05:00
|
|
|
addr := tv.ResourceAddr()
|
|
|
|
mode := addr.Resource.Mode
|
|
|
|
typeName := addr.Resource.Type
|
|
|
|
providerAddr, _ := tv.ProvidedBy()
|
2018-05-31 14:39:45 -05:00
|
|
|
|
2020-03-10 13:43:57 -05:00
|
|
|
var providerFqn addrs.Provider
|
2020-03-06 07:33:44 -06:00
|
|
|
switch p := providerAddr.(type) {
|
|
|
|
case addrs.LocalProviderConfig:
|
2020-03-10 13:43:57 -05:00
|
|
|
if t.Config == nil {
|
|
|
|
providerFqn = addrs.NewLegacyProvider(p.LocalName)
|
|
|
|
} else {
|
2020-03-10 20:21:19 -05:00
|
|
|
modConfig := t.Config.Descendent(tv.ModulePath())
|
2020-03-10 13:43:57 -05:00
|
|
|
if modConfig == nil {
|
|
|
|
providerFqn = addrs.NewLegacyProvider(p.LocalName)
|
|
|
|
} else {
|
|
|
|
providerFqn = modConfig.Module.ProviderForLocalConfig(addrs.LocalProviderConfig{LocalName: p.LocalName})
|
|
|
|
}
|
|
|
|
}
|
2020-03-06 07:33:44 -06:00
|
|
|
case addrs.AbsProviderConfig:
|
|
|
|
providerFqn = p.Provider
|
2020-03-10 13:43:57 -05:00
|
|
|
case nil:
|
|
|
|
providerFqn = tv.ImpliedProvider()
|
|
|
|
default:
|
|
|
|
// This should never happen; the case statements are meant to be exhaustive
|
|
|
|
panic(fmt.Sprintf("%s: provider for %s couldn't be determined", dag.VertexName(v), addr))
|
2020-03-06 07:33:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
schema, version := t.Schemas.ResourceTypeConfig(providerFqn, mode, typeName)
|
2018-05-31 14:39:45 -05:00
|
|
|
if schema == nil {
|
|
|
|
log.Printf("[ERROR] AttachSchemaTransformer: No resource schema available for %s", addr)
|
|
|
|
continue
|
2018-05-02 22:16:22 -05:00
|
|
|
}
|
2018-05-31 14:39:45 -05:00
|
|
|
log.Printf("[TRACE] AttachSchemaTransformer: attaching resource schema to %s", dag.VertexName(v))
|
2018-11-27 17:30:18 -06:00
|
|
|
tv.AttachResourceSchema(schema, version)
|
2018-05-31 19:14:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if tv, ok := v.(GraphNodeAttachProviderConfigSchema); ok {
|
2018-05-02 22:16:22 -05:00
|
|
|
providerAddr := tv.ProviderAddr()
|
2020-02-13 14:32:58 -06:00
|
|
|
schema := t.Schemas.ProviderConfig(providerAddr.Provider)
|
2020-02-03 07:18:04 -06:00
|
|
|
|
2018-05-31 14:39:45 -05:00
|
|
|
if schema == nil {
|
2018-05-31 19:14:20 -05:00
|
|
|
log.Printf("[ERROR] AttachSchemaTransformer: No provider config schema available for %s", providerAddr)
|
2018-05-31 14:39:45 -05:00
|
|
|
continue
|
2018-05-02 22:16:22 -05:00
|
|
|
}
|
2018-05-31 19:14:20 -05:00
|
|
|
log.Printf("[TRACE] AttachSchemaTransformer: attaching provider config schema to %s", dag.VertexName(v))
|
2018-05-31 14:39:45 -05:00
|
|
|
tv.AttachProviderConfigSchema(schema)
|
2018-05-31 19:14:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if tv, ok := v.(GraphNodeAttachProvisionerSchema); ok {
|
2018-05-24 18:00:26 -05:00
|
|
|
names := tv.ProvisionedBy()
|
|
|
|
for _, name := range names {
|
2018-05-31 14:39:45 -05:00
|
|
|
schema := t.Schemas.ProvisionerConfig(name)
|
|
|
|
if schema == nil {
|
2018-05-24 18:00:26 -05:00
|
|
|
log.Printf("[ERROR] AttachSchemaTransformer: No schema available for provisioner %q on %q", name, dag.VertexName(v))
|
2018-05-31 14:39:45 -05:00
|
|
|
continue
|
2018-05-24 18:00:26 -05:00
|
|
|
}
|
2018-05-31 19:14:20 -05:00
|
|
|
log.Printf("[TRACE] AttachSchemaTransformer: attaching provisioner %q config schema to %s", name, dag.VertexName(v))
|
2018-05-31 14:39:45 -05:00
|
|
|
tv.AttachProvisionerSchema(name, schema)
|
2018-05-24 18:00:26 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|