github.com/hashicorp/terraform-plugin-sdk@v1.17.2/terraform/transform_attach_schema.go (about) 1 package terraform 2 3 import ( 4 "fmt" 5 "log" 6 7 "github.com/hashicorp/terraform-plugin-sdk/internal/configs/configschema" 8 "github.com/hashicorp/terraform-plugin-sdk/internal/dag" 9 ) 10 11 // GraphNodeAttachResourceSchema is an interface implemented by node types 12 // that need a resource schema attached. 13 type GraphNodeAttachResourceSchema interface { 14 GraphNodeResource 15 GraphNodeProviderConsumer 16 17 AttachResourceSchema(schema *configschema.Block, version uint64) 18 } 19 20 // GraphNodeAttachProviderConfigSchema is an interface implemented by node types 21 // that need a provider configuration schema attached. 22 type GraphNodeAttachProviderConfigSchema interface { 23 GraphNodeProvider 24 25 AttachProviderConfigSchema(*configschema.Block) 26 } 27 28 // GraphNodeAttachProvisionerSchema is an interface implemented by node types 29 // that need one or more provisioner schemas attached. 30 type GraphNodeAttachProvisionerSchema interface { 31 ProvisionedBy() []string 32 33 // SetProvisionerSchema is called during transform for each provisioner 34 // type returned from ProvisionedBy, providing the configuration schema 35 // for each provisioner in turn. The implementer should save these for 36 // later use in evaluating provisioner configuration blocks. 37 AttachProvisionerSchema(name string, schema *configschema.Block) 38 } 39 40 // AttachSchemaTransformer finds nodes that implement 41 // GraphNodeAttachResourceSchema, GraphNodeAttachProviderConfigSchema, or 42 // GraphNodeAttachProvisionerSchema, looks up the needed schemas for each 43 // and then passes them to a method implemented by the node. 44 type AttachSchemaTransformer struct { 45 Schemas *Schemas 46 } 47 48 func (t *AttachSchemaTransformer) Transform(g *Graph) error { 49 if t.Schemas == nil { 50 // Should never happen with a reasonable caller, but we'll return a 51 // proper error here anyway so that we'll fail gracefully. 52 return fmt.Errorf("AttachSchemaTransformer used with nil Schemas") 53 } 54 55 for _, v := range g.Vertices() { 56 57 if tv, ok := v.(GraphNodeAttachResourceSchema); ok { 58 addr := tv.ResourceAddr() 59 mode := addr.Resource.Mode 60 typeName := addr.Resource.Type 61 providerAddr, _ := tv.ProvidedBy() 62 providerType := providerAddr.ProviderConfig.Type 63 64 schema, version := t.Schemas.ResourceTypeConfig(providerType, mode, typeName) 65 if schema == nil { 66 log.Printf("[ERROR] AttachSchemaTransformer: No resource schema available for %s", addr) 67 continue 68 } 69 log.Printf("[TRACE] AttachSchemaTransformer: attaching resource schema to %s", dag.VertexName(v)) 70 tv.AttachResourceSchema(schema, version) 71 } 72 73 if tv, ok := v.(GraphNodeAttachProviderConfigSchema); ok { 74 providerAddr := tv.ProviderAddr() 75 schema := t.Schemas.ProviderConfig(providerAddr.ProviderConfig.Type) 76 if schema == nil { 77 log.Printf("[ERROR] AttachSchemaTransformer: No provider config schema available for %s", providerAddr) 78 continue 79 } 80 log.Printf("[TRACE] AttachSchemaTransformer: attaching provider config schema to %s", dag.VertexName(v)) 81 tv.AttachProviderConfigSchema(schema) 82 } 83 84 if tv, ok := v.(GraphNodeAttachProvisionerSchema); ok { 85 names := tv.ProvisionedBy() 86 for _, name := range names { 87 schema := t.Schemas.ProvisionerConfig(name) 88 if schema == nil { 89 log.Printf("[ERROR] AttachSchemaTransformer: No schema available for provisioner %q on %q", name, dag.VertexName(v)) 90 continue 91 } 92 log.Printf("[TRACE] AttachSchemaTransformer: attaching provisioner %q config schema to %s", name, dag.VertexName(v)) 93 tv.AttachProvisionerSchema(name, schema) 94 } 95 } 96 } 97 98 return nil 99 }