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  }