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