github.com/medzin/terraform@v0.11.11/config/config_string.go (about) 1 package config 2 3 import ( 4 "bytes" 5 "fmt" 6 "sort" 7 "strings" 8 ) 9 10 // TestString is a Stringer-like function that outputs a string that can 11 // be used to easily compare multiple Config structures in unit tests. 12 // 13 // This function has no practical use outside of unit tests and debugging. 14 func (c *Config) TestString() string { 15 if c == nil { 16 return "<nil config>" 17 } 18 19 var buf bytes.Buffer 20 if len(c.Modules) > 0 { 21 buf.WriteString("Modules:\n\n") 22 buf.WriteString(modulesStr(c.Modules)) 23 buf.WriteString("\n\n") 24 } 25 26 if len(c.Variables) > 0 { 27 buf.WriteString("Variables:\n\n") 28 buf.WriteString(variablesStr(c.Variables)) 29 buf.WriteString("\n\n") 30 } 31 32 if len(c.ProviderConfigs) > 0 { 33 buf.WriteString("Provider Configs:\n\n") 34 buf.WriteString(providerConfigsStr(c.ProviderConfigs)) 35 buf.WriteString("\n\n") 36 } 37 38 if len(c.Resources) > 0 { 39 buf.WriteString("Resources:\n\n") 40 buf.WriteString(resourcesStr(c.Resources)) 41 buf.WriteString("\n\n") 42 } 43 44 if len(c.Outputs) > 0 { 45 buf.WriteString("Outputs:\n\n") 46 buf.WriteString(outputsStr(c.Outputs)) 47 buf.WriteString("\n") 48 } 49 50 return strings.TrimSpace(buf.String()) 51 } 52 53 func terraformStr(t *Terraform) string { 54 result := "" 55 56 if b := t.Backend; b != nil { 57 result += fmt.Sprintf("backend (%s)\n", b.Type) 58 59 keys := make([]string, 0, len(b.RawConfig.Raw)) 60 for k, _ := range b.RawConfig.Raw { 61 keys = append(keys, k) 62 } 63 sort.Strings(keys) 64 65 for _, k := range keys { 66 result += fmt.Sprintf(" %s\n", k) 67 } 68 } 69 70 return strings.TrimSpace(result) 71 } 72 73 func modulesStr(ms []*Module) string { 74 result := "" 75 order := make([]int, 0, len(ms)) 76 ks := make([]string, 0, len(ms)) 77 mapping := make(map[string]int) 78 for i, m := range ms { 79 k := m.Id() 80 ks = append(ks, k) 81 mapping[k] = i 82 } 83 sort.Strings(ks) 84 for _, k := range ks { 85 order = append(order, mapping[k]) 86 } 87 88 for _, i := range order { 89 m := ms[i] 90 result += fmt.Sprintf("%s\n", m.Id()) 91 92 ks := make([]string, 0, len(m.RawConfig.Raw)) 93 for k, _ := range m.RawConfig.Raw { 94 ks = append(ks, k) 95 } 96 sort.Strings(ks) 97 98 result += fmt.Sprintf(" source = %s\n", m.Source) 99 100 for _, k := range ks { 101 result += fmt.Sprintf(" %s\n", k) 102 } 103 } 104 105 return strings.TrimSpace(result) 106 } 107 108 func outputsStr(os []*Output) string { 109 ns := make([]string, 0, len(os)) 110 m := make(map[string]*Output) 111 for _, o := range os { 112 ns = append(ns, o.Name) 113 m[o.Name] = o 114 } 115 sort.Strings(ns) 116 117 result := "" 118 for _, n := range ns { 119 o := m[n] 120 121 result += fmt.Sprintf("%s\n", n) 122 123 if len(o.DependsOn) > 0 { 124 result += fmt.Sprintf(" dependsOn\n") 125 for _, d := range o.DependsOn { 126 result += fmt.Sprintf(" %s\n", d) 127 } 128 } 129 130 if len(o.RawConfig.Variables) > 0 { 131 result += fmt.Sprintf(" vars\n") 132 for _, rawV := range o.RawConfig.Variables { 133 kind := "unknown" 134 str := rawV.FullKey() 135 136 switch rawV.(type) { 137 case *ResourceVariable: 138 kind = "resource" 139 case *UserVariable: 140 kind = "user" 141 } 142 143 result += fmt.Sprintf(" %s: %s\n", kind, str) 144 } 145 } 146 147 if o.Description != "" { 148 result += fmt.Sprintf(" description\n %s\n", o.Description) 149 } 150 } 151 152 return strings.TrimSpace(result) 153 } 154 155 func localsStr(ls []*Local) string { 156 ns := make([]string, 0, len(ls)) 157 m := make(map[string]*Local) 158 for _, l := range ls { 159 ns = append(ns, l.Name) 160 m[l.Name] = l 161 } 162 sort.Strings(ns) 163 164 result := "" 165 for _, n := range ns { 166 l := m[n] 167 168 result += fmt.Sprintf("%s\n", n) 169 170 if len(l.RawConfig.Variables) > 0 { 171 result += fmt.Sprintf(" vars\n") 172 for _, rawV := range l.RawConfig.Variables { 173 kind := "unknown" 174 str := rawV.FullKey() 175 176 switch rawV.(type) { 177 case *ResourceVariable: 178 kind = "resource" 179 case *UserVariable: 180 kind = "user" 181 } 182 183 result += fmt.Sprintf(" %s: %s\n", kind, str) 184 } 185 } 186 } 187 188 return strings.TrimSpace(result) 189 } 190 191 // This helper turns a provider configs field into a deterministic 192 // string value for comparison in tests. 193 func providerConfigsStr(pcs []*ProviderConfig) string { 194 result := "" 195 196 ns := make([]string, 0, len(pcs)) 197 m := make(map[string]*ProviderConfig) 198 for _, n := range pcs { 199 ns = append(ns, n.Name) 200 m[n.Name] = n 201 } 202 sort.Strings(ns) 203 204 for _, n := range ns { 205 pc := m[n] 206 207 result += fmt.Sprintf("%s\n", n) 208 209 keys := make([]string, 0, len(pc.RawConfig.Raw)) 210 for k, _ := range pc.RawConfig.Raw { 211 keys = append(keys, k) 212 } 213 sort.Strings(keys) 214 215 for _, k := range keys { 216 result += fmt.Sprintf(" %s\n", k) 217 } 218 219 if len(pc.RawConfig.Variables) > 0 { 220 result += fmt.Sprintf(" vars\n") 221 for _, rawV := range pc.RawConfig.Variables { 222 kind := "unknown" 223 str := rawV.FullKey() 224 225 switch rawV.(type) { 226 case *ResourceVariable: 227 kind = "resource" 228 case *UserVariable: 229 kind = "user" 230 } 231 232 result += fmt.Sprintf(" %s: %s\n", kind, str) 233 } 234 } 235 } 236 237 return strings.TrimSpace(result) 238 } 239 240 // This helper turns a resources field into a deterministic 241 // string value for comparison in tests. 242 func resourcesStr(rs []*Resource) string { 243 result := "" 244 order := make([]int, 0, len(rs)) 245 ks := make([]string, 0, len(rs)) 246 mapping := make(map[string]int) 247 for i, r := range rs { 248 k := r.Id() 249 ks = append(ks, k) 250 mapping[k] = i 251 } 252 sort.Strings(ks) 253 for _, k := range ks { 254 order = append(order, mapping[k]) 255 } 256 257 for _, i := range order { 258 r := rs[i] 259 result += fmt.Sprintf( 260 "%s (x%s)\n", 261 r.Id(), 262 r.RawCount.Value()) 263 264 ks := make([]string, 0, len(r.RawConfig.Raw)) 265 for k, _ := range r.RawConfig.Raw { 266 ks = append(ks, k) 267 } 268 sort.Strings(ks) 269 270 for _, k := range ks { 271 result += fmt.Sprintf(" %s\n", k) 272 } 273 274 if len(r.Provisioners) > 0 { 275 result += fmt.Sprintf(" provisioners\n") 276 for _, p := range r.Provisioners { 277 when := "" 278 if p.When != ProvisionerWhenCreate { 279 when = fmt.Sprintf(" (%s)", p.When.String()) 280 } 281 282 result += fmt.Sprintf(" %s%s\n", p.Type, when) 283 284 if p.OnFailure != ProvisionerOnFailureFail { 285 result += fmt.Sprintf(" on_failure = %s\n", p.OnFailure.String()) 286 } 287 288 ks := make([]string, 0, len(p.RawConfig.Raw)) 289 for k, _ := range p.RawConfig.Raw { 290 ks = append(ks, k) 291 } 292 sort.Strings(ks) 293 294 for _, k := range ks { 295 result += fmt.Sprintf(" %s\n", k) 296 } 297 } 298 } 299 300 if len(r.DependsOn) > 0 { 301 result += fmt.Sprintf(" dependsOn\n") 302 for _, d := range r.DependsOn { 303 result += fmt.Sprintf(" %s\n", d) 304 } 305 } 306 307 if len(r.RawConfig.Variables) > 0 { 308 result += fmt.Sprintf(" vars\n") 309 310 ks := make([]string, 0, len(r.RawConfig.Variables)) 311 for k, _ := range r.RawConfig.Variables { 312 ks = append(ks, k) 313 } 314 sort.Strings(ks) 315 316 for _, k := range ks { 317 rawV := r.RawConfig.Variables[k] 318 kind := "unknown" 319 str := rawV.FullKey() 320 321 switch rawV.(type) { 322 case *ResourceVariable: 323 kind = "resource" 324 case *UserVariable: 325 kind = "user" 326 } 327 328 result += fmt.Sprintf(" %s: %s\n", kind, str) 329 } 330 } 331 } 332 333 return strings.TrimSpace(result) 334 } 335 336 // This helper turns a variables field into a deterministic 337 // string value for comparison in tests. 338 func variablesStr(vs []*Variable) string { 339 result := "" 340 ks := make([]string, 0, len(vs)) 341 m := make(map[string]*Variable) 342 for _, v := range vs { 343 ks = append(ks, v.Name) 344 m[v.Name] = v 345 } 346 sort.Strings(ks) 347 348 for _, k := range ks { 349 v := m[k] 350 351 required := "" 352 if v.Required() { 353 required = " (required)" 354 } 355 356 declaredType := "" 357 if v.DeclaredType != "" { 358 declaredType = fmt.Sprintf(" (%s)", v.DeclaredType) 359 } 360 361 if v.Default == nil || v.Default == "" { 362 v.Default = "<>" 363 } 364 if v.Description == "" { 365 v.Description = "<>" 366 } 367 368 result += fmt.Sprintf( 369 "%s%s%s\n %v\n %s\n", 370 k, 371 required, 372 declaredType, 373 v.Default, 374 v.Description) 375 } 376 377 return strings.TrimSpace(result) 378 }