opentofu/terraform/transform_attach_schema.go
Kristin Laemmert c7cc0afb80
Mildwonkey/ps schema (#24312)
* add Config to AttachSchemaTransformer for providerFqn lookup
* terraform: refactor ProvidedBy() to return nil when provider is not set
in config or state
2020-03-10 14:43:57 -04:00

125 lines
4.2 KiB
Go

package terraform
import (
"fmt"
"log"
"github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/dag"
)
// GraphNodeAttachResourceSchema is an interface implemented by node types
// that need a resource schema attached.
type GraphNodeAttachResourceSchema interface {
GraphNodeResource
GraphNodeProviderConsumer
AttachResourceSchema(schema *configschema.Block, version uint64)
}
// GraphNodeAttachProviderConfigSchema is an interface implemented by node types
// that need a provider configuration schema attached.
type GraphNodeAttachProviderConfigSchema interface {
GraphNodeProvider
AttachProviderConfigSchema(*configschema.Block)
}
// 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.
type AttachSchemaTransformer struct {
Schemas *Schemas
Config *configs.Config
}
func (t *AttachSchemaTransformer) Transform(g *Graph) error {
if t.Schemas == nil {
// Should never happen with a reasonable caller, but we'll return a
// proper error here anyway so that we'll fail gracefully.
return fmt.Errorf("AttachSchemaTransformer used with nil Schemas")
}
for _, v := range g.Vertices() {
if tv, ok := v.(GraphNodeAttachResourceSchema); ok {
addr := tv.ResourceAddr()
mode := addr.Resource.Mode
typeName := addr.Resource.Type
providerAddr, _ := tv.ProvidedBy()
var providerFqn addrs.Provider
switch p := providerAddr.(type) {
case addrs.LocalProviderConfig:
if t.Config == nil {
providerFqn = addrs.NewLegacyProvider(p.LocalName)
} else {
modConfig := t.Config.DescendentForInstance(tv.Path())
if modConfig == nil {
providerFqn = addrs.NewLegacyProvider(p.LocalName)
} else {
providerFqn = modConfig.Module.ProviderForLocalConfig(addrs.LocalProviderConfig{LocalName: p.LocalName})
}
}
case addrs.AbsProviderConfig:
providerFqn = p.Provider
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))
}
schema, version := t.Schemas.ResourceTypeConfig(providerFqn, mode, typeName)
if schema == nil {
log.Printf("[ERROR] AttachSchemaTransformer: No resource schema available for %s", addr)
continue
}
log.Printf("[TRACE] AttachSchemaTransformer: attaching resource schema to %s", dag.VertexName(v))
tv.AttachResourceSchema(schema, version)
}
if tv, ok := v.(GraphNodeAttachProviderConfigSchema); ok {
providerAddr := tv.ProviderAddr()
schema := t.Schemas.ProviderConfig(providerAddr.Provider)
if schema == nil {
log.Printf("[ERROR] AttachSchemaTransformer: No provider config schema available for %s", providerAddr)
continue
}
log.Printf("[TRACE] AttachSchemaTransformer: attaching provider config schema to %s", dag.VertexName(v))
tv.AttachProviderConfigSchema(schema)
}
if tv, ok := v.(GraphNodeAttachProvisionerSchema); ok {
names := tv.ProvisionedBy()
for _, name := range names {
schema := t.Schemas.ProvisionerConfig(name)
if schema == nil {
log.Printf("[ERROR] AttachSchemaTransformer: No schema available for provisioner %q on %q", name, dag.VertexName(v))
continue
}
log.Printf("[TRACE] AttachSchemaTransformer: attaching provisioner %q config schema to %s", name, dag.VertexName(v))
tv.AttachProvisionerSchema(name, schema)
}
}
}
return nil
}