github.com/kanishk98/terraform@v1.3.0-dev.0.20220917174235-661ca8088a6a/internal/terraform/transform_output.go (about)

     1  package terraform
     2  
     3  import (
     4  	"log"
     5  
     6  	"github.com/hashicorp/terraform/internal/addrs"
     7  	"github.com/hashicorp/terraform/internal/configs"
     8  	"github.com/hashicorp/terraform/internal/dag"
     9  	"github.com/hashicorp/terraform/internal/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 planned destroy, root outputs are still in the configuration
    23  	// so we need to record that we wish to remove them
    24  	removeRootOutputs bool
    25  
    26  	// Refresh-only mode means that any failing output preconditions are
    27  	// reported as warnings rather than errors
    28  	RefreshOnly bool
    29  }
    30  
    31  func (t *OutputTransformer) Transform(g *Graph) error {
    32  	return t.transform(g, t.Config)
    33  }
    34  
    35  func (t *OutputTransformer) transform(g *Graph, c *configs.Config) error {
    36  	// If we have no config then there can be no outputs.
    37  	if c == nil {
    38  		return nil
    39  	}
    40  
    41  	// Transform all the children. We must do this first because
    42  	// we can reference module outputs and they must show up in the
    43  	// reference map.
    44  	for _, cc := range c.Children {
    45  		if err := t.transform(g, cc); err != nil {
    46  			return err
    47  		}
    48  	}
    49  
    50  	// Add outputs to the graph, which will be dynamically expanded
    51  	// into NodeApplyableOutputs to reflect possible expansion
    52  	// through the presence of "count" or "for_each" on the modules.
    53  
    54  	var changes []*plans.OutputChangeSrc
    55  	if t.Changes != nil {
    56  		changes = t.Changes.Outputs
    57  	}
    58  
    59  	for _, o := range c.Module.Outputs {
    60  		addr := addrs.OutputValue{Name: o.Name}
    61  
    62  		var rootChange *plans.OutputChangeSrc
    63  		for _, c := range changes {
    64  			if c.Addr.Module.IsRoot() && c.Addr.OutputValue.Name == o.Name {
    65  				rootChange = c
    66  			}
    67  		}
    68  
    69  		destroy := t.removeRootOutputs
    70  		if rootChange != nil {
    71  			destroy = rootChange.Action == plans.Delete
    72  		}
    73  
    74  		// If this is a root output and we're destroying, we add the destroy
    75  		// node directly, as there is no need to expand.
    76  
    77  		var node dag.Vertex
    78  		switch {
    79  		case c.Path.IsRoot() && destroy:
    80  			node = &NodeDestroyableOutput{
    81  				Addr:   addr.Absolute(addrs.RootModuleInstance),
    82  				Config: o,
    83  			}
    84  
    85  		default:
    86  			node = &nodeExpandOutput{
    87  				Addr:        addr,
    88  				Module:      c.Path,
    89  				Config:      o,
    90  				Destroy:     t.removeRootOutputs,
    91  				RefreshOnly: t.RefreshOnly,
    92  			}
    93  		}
    94  
    95  		log.Printf("[TRACE] OutputTransformer: adding %s as %T", o.Name, node)
    96  		g.Add(node)
    97  	}
    98  
    99  	return nil
   100  }