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