github.com/jmbataller/terraform@v0.6.8-0.20151125192640-b7a12e3a580c/command/format_state.go (about) 1 package command 2 3 import ( 4 "bytes" 5 "fmt" 6 "sort" 7 "strings" 8 9 "github.com/hashicorp/terraform/terraform" 10 "github.com/mitchellh/colorstring" 11 ) 12 13 // FormatStateOpts are the options for formatting a state. 14 type FormatStateOpts struct { 15 // State is the state to format. This is required. 16 State *terraform.State 17 18 // Color is the colorizer. This is optional. 19 Color *colorstring.Colorize 20 21 // ModuleDepth is the depth of the modules to expand. By default this 22 // is zero which will not expand modules at all. 23 ModuleDepth int 24 } 25 26 // FormatState takes a state and returns a string 27 func FormatState(opts *FormatStateOpts) string { 28 if opts.Color == nil { 29 panic("colorize not given") 30 } 31 32 s := opts.State 33 if len(s.Modules) == 0 { 34 return "The state file is empty. No resources are represented." 35 } 36 37 var buf bytes.Buffer 38 buf.WriteString("[reset]") 39 40 // Format all the modules 41 for _, m := range s.Modules { 42 if len(m.Path)-1 <= opts.ModuleDepth || opts.ModuleDepth == -1 { 43 formatStateModuleExpand(&buf, m, opts) 44 } else { 45 formatStateModuleSingle(&buf, m, opts) 46 } 47 } 48 49 // Write the outputs for the root module 50 m := s.RootModule() 51 if len(m.Outputs) > 0 { 52 buf.WriteString("\nOutputs:\n\n") 53 54 // Sort the outputs 55 ks := make([]string, 0, len(m.Outputs)) 56 for k, _ := range m.Outputs { 57 ks = append(ks, k) 58 } 59 sort.Strings(ks) 60 61 // Output each output k/v pair 62 for _, k := range ks { 63 v := m.Outputs[k] 64 buf.WriteString(fmt.Sprintf("%s = %s\n", k, v)) 65 } 66 } 67 68 return opts.Color.Color(strings.TrimSpace(buf.String())) 69 } 70 71 func formatStateModuleExpand( 72 buf *bytes.Buffer, m *terraform.ModuleState, opts *FormatStateOpts) { 73 var moduleName string 74 if !m.IsRoot() { 75 moduleName = fmt.Sprintf("module.%s", strings.Join(m.Path[1:], ".")) 76 } 77 78 // First get the names of all the resources so we can show them 79 // in alphabetical order. 80 names := make([]string, 0, len(m.Resources)) 81 for name, _ := range m.Resources { 82 names = append(names, name) 83 } 84 sort.Strings(names) 85 86 // Go through each resource and begin building up the output. 87 for _, k := range names { 88 name := k 89 if moduleName != "" { 90 name = moduleName + "." + name 91 } 92 93 rs := m.Resources[k] 94 is := rs.Primary 95 var id string 96 if is != nil { 97 id = is.ID 98 } 99 if id == "" { 100 id = "<not created>" 101 } 102 103 taintStr := "" 104 if len(rs.Tainted) > 0 { 105 taintStr = " (tainted)" 106 } 107 108 buf.WriteString(fmt.Sprintf("%s:%s\n", name, taintStr)) 109 buf.WriteString(fmt.Sprintf(" id = %s\n", id)) 110 111 if is != nil { 112 // Sort the attributes 113 attrKeys := make([]string, 0, len(is.Attributes)) 114 for ak, _ := range is.Attributes { 115 // Skip the id attribute since we just show the id directly 116 if ak == "id" { 117 continue 118 } 119 120 attrKeys = append(attrKeys, ak) 121 } 122 sort.Strings(attrKeys) 123 124 // Output each attribute 125 for _, ak := range attrKeys { 126 av := is.Attributes[ak] 127 buf.WriteString(fmt.Sprintf(" %s = %s\n", ak, av)) 128 } 129 } 130 } 131 132 buf.WriteString("[reset]\n") 133 } 134 135 func formatStateModuleSingle( 136 buf *bytes.Buffer, m *terraform.ModuleState, opts *FormatStateOpts) { 137 // Header with the module name 138 buf.WriteString(fmt.Sprintf("module.%s\n", strings.Join(m.Path[1:], "."))) 139 140 // Now just write how many resources are in here. 141 buf.WriteString(fmt.Sprintf(" %d resource(s)\n", len(m.Resources))) 142 }