kubeform.dev/terraform-backend-sdk@v0.0.0-20220310143633-45f07fe731c5/terraform/transform_output.go (about)

     1  package terraform
     2  
     3  import (
     4  	"log"
     5  
     6  	"kubeform.dev/terraform-backend-sdk/addrs"
     7  	"kubeform.dev/terraform-backend-sdk/configs"
     8  	"kubeform.dev/terraform-backend-sdk/dag"
     9  	"kubeform.dev/terraform-backend-sdk/plans"
    10  )
    11  
    12  // OutputTransformer is a GraphTransformer that adds all the outputs
    13  // in the configuration to the graph.
    14  //
    15  // This is done for the apply graph builder even if dependent nodes
    16  // aren't changing since there is no downside: the state will be available
    17  // even if the dependent items aren't changing.
    18  type OutputTransformer struct {
    19  	Config  *configs.Config
    20  	Changes *plans.Changes
    21  
    22  	// if this is a planed destroy, root outputs are still in the configuration
    23  	// so we need to record that we wish to remove them
    24  	Destroy bool
    25  }
    26  
    27  func (t *OutputTransformer) Transform(g *Graph) error {
    28  	return t.transform(g, t.Config)
    29  }
    30  
    31  func (t *OutputTransformer) transform(g *Graph, c *configs.Config) error {
    32  	// If we have no config then there can be no outputs.
    33  	if c == nil {
    34  		return nil
    35  	}
    36  
    37  	// Transform all the children. We must do this first because
    38  	// we can reference module outputs and they must show up in the
    39  	// reference map.
    40  	for _, cc := range c.Children {
    41  		if err := t.transform(g, cc); err != nil {
    42  			return err
    43  		}
    44  	}
    45  
    46  	// Add outputs to the graph, which will be dynamically expanded
    47  	// into NodeApplyableOutputs to reflect possible expansion
    48  	// through the presence of "count" or "for_each" on the modules.
    49  
    50  	var changes []*plans.OutputChangeSrc
    51  	if t.Changes != nil {
    52  		changes = t.Changes.Outputs
    53  	}
    54  
    55  	for _, o := range c.Module.Outputs {
    56  		addr := addrs.OutputValue{Name: o.Name}
    57  
    58  		var rootChange *plans.OutputChangeSrc
    59  		for _, c := range changes {
    60  			if c.Addr.Module.IsRoot() && c.Addr.OutputValue.Name == o.Name {
    61  				rootChange = c
    62  			}
    63  		}
    64  
    65  		destroy := t.Destroy
    66  		if rootChange != nil {
    67  			destroy = rootChange.Action == plans.Delete
    68  		}
    69  
    70  		// If this is a root output, we add the apply or destroy node directly,
    71  		// as the root modules does not expand.
    72  
    73  		var node dag.Vertex
    74  		switch {
    75  		case c.Path.IsRoot() && destroy:
    76  			node = &NodeDestroyableOutput{
    77  				Addr:   addr.Absolute(addrs.RootModuleInstance),
    78  				Config: o,
    79  			}
    80  
    81  		case c.Path.IsRoot():
    82  			node = &NodeApplyableOutput{
    83  				Addr:   addr.Absolute(addrs.RootModuleInstance),
    84  				Config: o,
    85  				Change: rootChange,
    86  			}
    87  
    88  		default:
    89  			node = &nodeExpandOutput{
    90  				Addr:    addr,
    91  				Module:  c.Path,
    92  				Config:  o,
    93  				Changes: changes,
    94  				Destroy: t.Destroy,
    95  			}
    96  		}
    97  
    98  		log.Printf("[TRACE] OutputTransformer: adding %s as %T", o.Name, node)
    99  		g.Add(node)
   100  	}
   101  
   102  	return nil
   103  }