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  }