github.com/boyvanduuren/terraform@v0.7.0-rc2.0.20160805175930-de822d909c40/command/graph.go (about)

     1  package command
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"os"
     7  	"strings"
     8  
     9  	"github.com/hashicorp/terraform/terraform"
    10  )
    11  
    12  // GraphCommand is a Command implementation that takes a Terraform
    13  // configuration and outputs the dependency tree in graphical form.
    14  type GraphCommand struct {
    15  	Meta
    16  }
    17  
    18  func (c *GraphCommand) Run(args []string) int {
    19  	var moduleDepth int
    20  	var verbose bool
    21  	var drawCycles bool
    22  
    23  	args = c.Meta.process(args, false)
    24  
    25  	cmdFlags := flag.NewFlagSet("graph", flag.ContinueOnError)
    26  	c.addModuleDepthFlag(cmdFlags, &moduleDepth)
    27  	cmdFlags.BoolVar(&verbose, "verbose", false, "verbose")
    28  	cmdFlags.BoolVar(&drawCycles, "draw-cycles", false, "draw-cycles")
    29  	cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
    30  	if err := cmdFlags.Parse(args); err != nil {
    31  		return 1
    32  	}
    33  
    34  	var path string
    35  	args = cmdFlags.Args()
    36  	if len(args) > 1 {
    37  		c.Ui.Error("The graph command expects one argument.\n")
    38  		cmdFlags.Usage()
    39  		return 1
    40  	} else if len(args) == 1 {
    41  		path = args[0]
    42  	} else {
    43  		var err error
    44  		path, err = os.Getwd()
    45  		if err != nil {
    46  			c.Ui.Error(fmt.Sprintf("Error getting pwd: %s", err))
    47  		}
    48  	}
    49  
    50  	ctx, _, err := c.Context(contextOpts{
    51  		Path:      path,
    52  		StatePath: "",
    53  	})
    54  	if err != nil {
    55  		c.Ui.Error(fmt.Sprintf("Error loading Terraform: %s", err))
    56  		return 1
    57  	}
    58  
    59  	// Skip validation during graph generation - we want to see the graph even if
    60  	// it is invalid for some reason.
    61  	g, err := ctx.Graph(&terraform.ContextGraphOpts{
    62  		Verbose:  verbose,
    63  		Validate: false,
    64  	})
    65  	if err != nil {
    66  		c.Ui.Error(fmt.Sprintf("Error creating graph: %s", err))
    67  		return 1
    68  	}
    69  
    70  	graphStr, err := terraform.GraphDot(g, &terraform.GraphDotOpts{
    71  		DrawCycles: drawCycles,
    72  		MaxDepth:   moduleDepth,
    73  		Verbose:    verbose,
    74  	})
    75  	if err != nil {
    76  		c.Ui.Error(fmt.Sprintf("Error converting graph: %s", err))
    77  		return 1
    78  	}
    79  
    80  	c.Ui.Output(graphStr)
    81  
    82  	return 0
    83  }
    84  
    85  func (c *GraphCommand) Help() string {
    86  	helpText := `
    87  Usage: terraform graph [options] [DIR]
    88  
    89    Outputs the visual dependency graph of Terraform resources according to
    90    configuration files in DIR (or the current directory if omitted).
    91  
    92    The graph is outputted in DOT format. The typical program that can
    93    read this format is GraphViz, but many web services are also available
    94    to read this format.
    95  
    96  Options:
    97  
    98    -draw-cycles         Highlight any cycles in the graph with colored edges.
    99                         This helps when diagnosing cycle errors.
   100  
   101    -module-depth=n      The maximum depth to expand modules. By default this is
   102                         -1, which will expand resources within all modules.
   103  
   104    -verbose             Generate a verbose, "worst-case" graph, with all nodes
   105                         for potential operations in place.
   106  
   107    -no-color           If specified, output won't contain any color.
   108  
   109  `
   110  	return strings.TrimSpace(helpText)
   111  }
   112  
   113  func (c *GraphCommand) Synopsis() string {
   114  	return "Create a visual graph of Terraform resources"
   115  }