github.com/r3labs/terraform@v0.8.4/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 }