github.com/gettyimages/terraform@v0.7.6-0.20161219132226-dc052c5707a3/command/graph.go (about)

     1  package command
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"os"
     7  	"strings"
     8  
     9  	"github.com/hashicorp/terraform/dag"
    10  	"github.com/hashicorp/terraform/terraform"
    11  )
    12  
    13  // GraphCommand is a Command implementation that takes a Terraform
    14  // configuration and outputs the dependency tree in graphical form.
    15  type GraphCommand struct {
    16  	Meta
    17  }
    18  
    19  func (c *GraphCommand) Run(args []string) int {
    20  	var moduleDepth int
    21  	var verbose bool
    22  	var drawCycles bool
    23  	var graphTypeStr string
    24  
    25  	args = c.Meta.process(args, false)
    26  
    27  	cmdFlags := flag.NewFlagSet("graph", flag.ContinueOnError)
    28  	c.addModuleDepthFlag(cmdFlags, &moduleDepth)
    29  	cmdFlags.BoolVar(&verbose, "verbose", false, "verbose")
    30  	cmdFlags.BoolVar(&drawCycles, "draw-cycles", false, "draw-cycles")
    31  	cmdFlags.StringVar(&graphTypeStr, "type", "", "type")
    32  	cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
    33  	if err := cmdFlags.Parse(args); err != nil {
    34  		return 1
    35  	}
    36  
    37  	var path string
    38  	args = cmdFlags.Args()
    39  	if len(args) > 1 {
    40  		c.Ui.Error("The graph command expects one argument.\n")
    41  		cmdFlags.Usage()
    42  		return 1
    43  	} else if len(args) == 1 {
    44  		path = args[0]
    45  	} else {
    46  		var err error
    47  		path, err = os.Getwd()
    48  		if err != nil {
    49  			c.Ui.Error(fmt.Sprintf("Error getting pwd: %s", err))
    50  		}
    51  	}
    52  
    53  	ctx, planFile, err := c.Context(contextOpts{
    54  		Path:      path,
    55  		StatePath: "",
    56  	})
    57  	if err != nil {
    58  		c.Ui.Error(fmt.Sprintf("Error loading Terraform: %s", err))
    59  		return 1
    60  	}
    61  
    62  	// Determine the graph type
    63  	graphType := terraform.GraphTypePlan
    64  	if planFile {
    65  		graphType = terraform.GraphTypeApply
    66  	}
    67  
    68  	if graphTypeStr != "" {
    69  		v, ok := terraform.GraphTypeMap[graphTypeStr]
    70  		if !ok {
    71  			c.Ui.Error(fmt.Sprintf("Invalid graph type requested: %s", graphTypeStr))
    72  			return 1
    73  		}
    74  
    75  		graphType = v
    76  	}
    77  
    78  	// Skip validation during graph generation - we want to see the graph even if
    79  	// it is invalid for some reason.
    80  	g, err := ctx.Graph(graphType, &terraform.ContextGraphOpts{
    81  		Verbose:  verbose,
    82  		Validate: false,
    83  	})
    84  	if err != nil {
    85  		c.Ui.Error(fmt.Sprintf("Error creating graph: %s", err))
    86  		return 1
    87  	}
    88  
    89  	graphStr, err := terraform.GraphDot(g, &dag.DotOpts{
    90  		DrawCycles: drawCycles,
    91  		MaxDepth:   moduleDepth,
    92  		Verbose:    verbose,
    93  	})
    94  	if err != nil {
    95  		c.Ui.Error(fmt.Sprintf("Error converting graph: %s", err))
    96  		return 1
    97  	}
    98  
    99  	c.Ui.Output(graphStr)
   100  
   101  	return 0
   102  }
   103  
   104  func (c *GraphCommand) Help() string {
   105  	helpText := `
   106  Usage: terraform graph [options] [DIR]
   107  
   108    Outputs the visual execution graph of Terraform resources according to
   109    configuration files in DIR (or the current directory if omitted).
   110  
   111    The graph is outputted in DOT format. The typical program that can
   112    read this format is GraphViz, but many web services are also available
   113    to read this format.
   114  
   115    The -type flag can be used to control the type of graph shown. Terraform
   116    creates different graphs for different operations. See the options below
   117    for the list of types supported. The default type is "plan" if a
   118    configuration is given, and "apply" if a plan file is passed as an
   119    argument.
   120  
   121  Options:
   122  
   123    -draw-cycles   Highlight any cycles in the graph with colored edges.
   124                   This helps when diagnosing cycle errors.
   125  
   126    -no-color      If specified, output won't contain any color.
   127  
   128    -type=plan     Type of graph to output. Can be: plan, plan-destroy, apply,
   129                   legacy.
   130  
   131  `
   132  	return strings.TrimSpace(helpText)
   133  }
   134  
   135  func (c *GraphCommand) Synopsis() string {
   136  	return "Create a visual graph of Terraform resources"
   137  }