github.com/vic3lord/terraform@v0.8.0-rc1.0.20170626102919-16c6dd2cb372/command/graph.go (about) 1 package command 2 3 import ( 4 "flag" 5 "fmt" 6 "strings" 7 8 "github.com/hashicorp/terraform/backend" 9 "github.com/hashicorp/terraform/config" 10 "github.com/hashicorp/terraform/config/module" 11 "github.com/hashicorp/terraform/dag" 12 "github.com/hashicorp/terraform/terraform" 13 ) 14 15 // GraphCommand is a Command implementation that takes a Terraform 16 // configuration and outputs the dependency tree in graphical form. 17 type GraphCommand struct { 18 Meta 19 } 20 21 func (c *GraphCommand) Run(args []string) int { 22 var moduleDepth int 23 var verbose bool 24 var drawCycles bool 25 var graphTypeStr string 26 27 args = c.Meta.process(args, false) 28 29 cmdFlags := flag.NewFlagSet("graph", flag.ContinueOnError) 30 c.addModuleDepthFlag(cmdFlags, &moduleDepth) 31 cmdFlags.BoolVar(&verbose, "verbose", false, "verbose") 32 cmdFlags.BoolVar(&drawCycles, "draw-cycles", false, "draw-cycles") 33 cmdFlags.StringVar(&graphTypeStr, "type", "", "type") 34 cmdFlags.Usage = func() { c.Ui.Error(c.Help()) } 35 if err := cmdFlags.Parse(args); err != nil { 36 return 1 37 } 38 39 configPath, err := ModulePath(cmdFlags.Args()) 40 if err != nil { 41 c.Ui.Error(err.Error()) 42 return 1 43 } 44 45 // Check if the path is a plan 46 plan, err := c.Plan(configPath) 47 if err != nil { 48 c.Ui.Error(err.Error()) 49 return 1 50 } 51 if plan != nil { 52 // Reset for backend loading 53 configPath = "" 54 } 55 56 // Load the module 57 var mod *module.Tree 58 if plan == nil { 59 mod, err = c.Module(configPath) 60 if err != nil { 61 c.Ui.Error(fmt.Sprintf("Failed to load root config module: %s", err)) 62 return 1 63 } 64 } 65 66 var conf *config.Config 67 if mod != nil { 68 conf = mod.Config() 69 } 70 71 // Load the backend 72 b, err := c.Backend(&BackendOpts{ 73 Config: conf, 74 Plan: plan, 75 }) 76 if err != nil { 77 c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err)) 78 return 1 79 } 80 81 // We require a local backend 82 local, ok := b.(backend.Local) 83 if !ok { 84 c.Ui.Error(ErrUnsupportedLocalOp) 85 return 1 86 } 87 88 // Build the operation 89 opReq := c.Operation() 90 opReq.Module = mod 91 opReq.Plan = plan 92 93 // Get the context 94 ctx, _, err := local.Context(opReq) 95 if err != nil { 96 c.Ui.Error(err.Error()) 97 return 1 98 } 99 100 // Determine the graph type 101 graphType := terraform.GraphTypePlan 102 if plan != nil { 103 graphType = terraform.GraphTypeApply 104 } 105 106 if graphTypeStr != "" { 107 v, ok := terraform.GraphTypeMap[graphTypeStr] 108 if !ok { 109 c.Ui.Error(fmt.Sprintf("Invalid graph type requested: %s", graphTypeStr)) 110 return 1 111 } 112 113 graphType = v 114 } 115 116 // Skip validation during graph generation - we want to see the graph even if 117 // it is invalid for some reason. 118 g, err := ctx.Graph(graphType, &terraform.ContextGraphOpts{ 119 Verbose: verbose, 120 Validate: false, 121 }) 122 if err != nil { 123 c.Ui.Error(fmt.Sprintf("Error creating graph: %s", err)) 124 return 1 125 } 126 127 graphStr, err := terraform.GraphDot(g, &dag.DotOpts{ 128 DrawCycles: drawCycles, 129 MaxDepth: moduleDepth, 130 Verbose: verbose, 131 }) 132 if err != nil { 133 c.Ui.Error(fmt.Sprintf("Error converting graph: %s", err)) 134 return 1 135 } 136 137 c.Ui.Output(graphStr) 138 139 return 0 140 } 141 142 func (c *GraphCommand) Help() string { 143 helpText := ` 144 Usage: terraform graph [options] [DIR] 145 146 Outputs the visual execution graph of Terraform resources according to 147 configuration files in DIR (or the current directory if omitted). 148 149 The graph is outputted in DOT format. The typical program that can 150 read this format is GraphViz, but many web services are also available 151 to read this format. 152 153 The -type flag can be used to control the type of graph shown. Terraform 154 creates different graphs for different operations. See the options below 155 for the list of types supported. The default type is "plan" if a 156 configuration is given, and "apply" if a plan file is passed as an 157 argument. 158 159 Options: 160 161 -draw-cycles Highlight any cycles in the graph with colored edges. 162 This helps when diagnosing cycle errors. 163 164 -no-color If specified, output won't contain any color. 165 166 -type=plan Type of graph to output. Can be: plan, plan-destroy, apply, 167 validate, input, refresh. 168 169 170 ` 171 return strings.TrimSpace(helpText) 172 } 173 174 func (c *GraphCommand) Synopsis() string { 175 return "Create a visual graph of Terraform resources" 176 }