config: TestString
This commit is contained in:
parent
292f57ea0a
commit
c0a30d3337
|
@ -0,0 +1,297 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// TestString is a Stringer-like function that outputs a string that can
|
||||
// be used to easily compare multiple Config structures in unit tests.
|
||||
//
|
||||
// This function has no practical use outside of unit tests and debugging.
|
||||
func (c *Config) TestString() string {
|
||||
if c == nil {
|
||||
return "<nil config>"
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if len(c.Modules) > 0 {
|
||||
buf.WriteString("Modules:\n\n")
|
||||
buf.WriteString(modulesStr(c.Modules))
|
||||
buf.WriteString("\n\n")
|
||||
}
|
||||
|
||||
if len(c.Variables) > 0 {
|
||||
buf.WriteString("Variables:\n\n")
|
||||
buf.WriteString(variablesStr(c.Variables))
|
||||
buf.WriteString("\n\n")
|
||||
}
|
||||
|
||||
if len(c.ProviderConfigs) > 0 {
|
||||
buf.WriteString("Provider Configs:\n\n")
|
||||
buf.WriteString(providerConfigsStr(c.ProviderConfigs))
|
||||
buf.WriteString("\n\n")
|
||||
}
|
||||
|
||||
if len(c.Resources) > 0 {
|
||||
buf.WriteString("Resources:\n\n")
|
||||
buf.WriteString(resourcesStr(c.Resources))
|
||||
buf.WriteString("\n\n")
|
||||
}
|
||||
|
||||
if len(c.Outputs) > 0 {
|
||||
buf.WriteString("Outputs:\n\n")
|
||||
buf.WriteString(outputsStr(c.Outputs))
|
||||
buf.WriteString("\n")
|
||||
}
|
||||
|
||||
return strings.TrimSpace(buf.String())
|
||||
}
|
||||
|
||||
func modulesStr(ms []*Module) string {
|
||||
result := ""
|
||||
order := make([]int, 0, len(ms))
|
||||
ks := make([]string, 0, len(ms))
|
||||
mapping := make(map[string]int)
|
||||
for i, m := range ms {
|
||||
k := m.Id()
|
||||
ks = append(ks, k)
|
||||
mapping[k] = i
|
||||
}
|
||||
sort.Strings(ks)
|
||||
for _, k := range ks {
|
||||
order = append(order, mapping[k])
|
||||
}
|
||||
|
||||
for _, i := range order {
|
||||
m := ms[i]
|
||||
result += fmt.Sprintf("%s\n", m.Id())
|
||||
|
||||
ks := make([]string, 0, len(m.RawConfig.Raw))
|
||||
for k, _ := range m.RawConfig.Raw {
|
||||
ks = append(ks, k)
|
||||
}
|
||||
sort.Strings(ks)
|
||||
|
||||
result += fmt.Sprintf(" source = %s\n", m.Source)
|
||||
|
||||
for _, k := range ks {
|
||||
result += fmt.Sprintf(" %s\n", k)
|
||||
}
|
||||
}
|
||||
|
||||
return strings.TrimSpace(result)
|
||||
}
|
||||
|
||||
func outputsStr(os []*Output) string {
|
||||
ns := make([]string, 0, len(os))
|
||||
m := make(map[string]*Output)
|
||||
for _, o := range os {
|
||||
ns = append(ns, o.Name)
|
||||
m[o.Name] = o
|
||||
}
|
||||
sort.Strings(ns)
|
||||
|
||||
result := ""
|
||||
for _, n := range ns {
|
||||
o := m[n]
|
||||
|
||||
result += fmt.Sprintf("%s\n", n)
|
||||
|
||||
if len(o.RawConfig.Variables) > 0 {
|
||||
result += fmt.Sprintf(" vars\n")
|
||||
for _, rawV := range o.RawConfig.Variables {
|
||||
kind := "unknown"
|
||||
str := rawV.FullKey()
|
||||
|
||||
switch rawV.(type) {
|
||||
case *ResourceVariable:
|
||||
kind = "resource"
|
||||
case *UserVariable:
|
||||
kind = "user"
|
||||
}
|
||||
|
||||
result += fmt.Sprintf(" %s: %s\n", kind, str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return strings.TrimSpace(result)
|
||||
}
|
||||
|
||||
// This helper turns a provider configs field into a deterministic
|
||||
// string value for comparison in tests.
|
||||
func providerConfigsStr(pcs []*ProviderConfig) string {
|
||||
result := ""
|
||||
|
||||
ns := make([]string, 0, len(pcs))
|
||||
m := make(map[string]*ProviderConfig)
|
||||
for _, n := range pcs {
|
||||
ns = append(ns, n.Name)
|
||||
m[n.Name] = n
|
||||
}
|
||||
sort.Strings(ns)
|
||||
|
||||
for _, n := range ns {
|
||||
pc := m[n]
|
||||
|
||||
result += fmt.Sprintf("%s\n", n)
|
||||
|
||||
keys := make([]string, 0, len(pc.RawConfig.Raw))
|
||||
for k, _ := range pc.RawConfig.Raw {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
for _, k := range keys {
|
||||
result += fmt.Sprintf(" %s\n", k)
|
||||
}
|
||||
|
||||
if len(pc.RawConfig.Variables) > 0 {
|
||||
result += fmt.Sprintf(" vars\n")
|
||||
for _, rawV := range pc.RawConfig.Variables {
|
||||
kind := "unknown"
|
||||
str := rawV.FullKey()
|
||||
|
||||
switch rawV.(type) {
|
||||
case *ResourceVariable:
|
||||
kind = "resource"
|
||||
case *UserVariable:
|
||||
kind = "user"
|
||||
}
|
||||
|
||||
result += fmt.Sprintf(" %s: %s\n", kind, str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return strings.TrimSpace(result)
|
||||
}
|
||||
|
||||
// This helper turns a resources field into a deterministic
|
||||
// string value for comparison in tests.
|
||||
func resourcesStr(rs []*Resource) string {
|
||||
result := ""
|
||||
order := make([]int, 0, len(rs))
|
||||
ks := make([]string, 0, len(rs))
|
||||
mapping := make(map[string]int)
|
||||
for i, r := range rs {
|
||||
k := fmt.Sprintf("%s[%s]", r.Type, r.Name)
|
||||
ks = append(ks, k)
|
||||
mapping[k] = i
|
||||
}
|
||||
sort.Strings(ks)
|
||||
for _, k := range ks {
|
||||
order = append(order, mapping[k])
|
||||
}
|
||||
|
||||
for _, i := range order {
|
||||
r := rs[i]
|
||||
result += fmt.Sprintf(
|
||||
"%s[%s] (x%d)\n",
|
||||
r.Type,
|
||||
r.Name,
|
||||
r.Count)
|
||||
|
||||
ks := make([]string, 0, len(r.RawConfig.Raw))
|
||||
for k, _ := range r.RawConfig.Raw {
|
||||
ks = append(ks, k)
|
||||
}
|
||||
sort.Strings(ks)
|
||||
|
||||
for _, k := range ks {
|
||||
result += fmt.Sprintf(" %s\n", k)
|
||||
}
|
||||
|
||||
if len(r.Provisioners) > 0 {
|
||||
result += fmt.Sprintf(" provisioners\n")
|
||||
for _, p := range r.Provisioners {
|
||||
result += fmt.Sprintf(" %s\n", p.Type)
|
||||
|
||||
ks := make([]string, 0, len(p.RawConfig.Raw))
|
||||
for k, _ := range p.RawConfig.Raw {
|
||||
ks = append(ks, k)
|
||||
}
|
||||
sort.Strings(ks)
|
||||
|
||||
for _, k := range ks {
|
||||
result += fmt.Sprintf(" %s\n", k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.DependsOn) > 0 {
|
||||
result += fmt.Sprintf(" dependsOn\n")
|
||||
for _, d := range r.DependsOn {
|
||||
result += fmt.Sprintf(" %s\n", d)
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.RawConfig.Variables) > 0 {
|
||||
result += fmt.Sprintf(" vars\n")
|
||||
|
||||
ks := make([]string, 0, len(r.RawConfig.Variables))
|
||||
for k, _ := range r.RawConfig.Variables {
|
||||
ks = append(ks, k)
|
||||
}
|
||||
sort.Strings(ks)
|
||||
|
||||
for _, k := range ks {
|
||||
rawV := r.RawConfig.Variables[k]
|
||||
kind := "unknown"
|
||||
str := rawV.FullKey()
|
||||
|
||||
switch rawV.(type) {
|
||||
case *ResourceVariable:
|
||||
kind = "resource"
|
||||
case *UserVariable:
|
||||
kind = "user"
|
||||
}
|
||||
|
||||
result += fmt.Sprintf(" %s: %s\n", kind, str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return strings.TrimSpace(result)
|
||||
}
|
||||
|
||||
// This helper turns a variables field into a deterministic
|
||||
// string value for comparison in tests.
|
||||
func variablesStr(vs []*Variable) string {
|
||||
result := ""
|
||||
ks := make([]string, 0, len(vs))
|
||||
m := make(map[string]*Variable)
|
||||
for _, v := range vs {
|
||||
ks = append(ks, v.Name)
|
||||
m[v.Name] = v
|
||||
}
|
||||
sort.Strings(ks)
|
||||
|
||||
for _, k := range ks {
|
||||
v := m[k]
|
||||
|
||||
required := ""
|
||||
if v.Required() {
|
||||
required = " (required)"
|
||||
}
|
||||
|
||||
if v.Default == nil || v.Default == "" {
|
||||
v.Default = "<>"
|
||||
}
|
||||
if v.Description == "" {
|
||||
v.Description = "<>"
|
||||
}
|
||||
|
||||
result += fmt.Sprintf(
|
||||
"%s%s\n %v\n %s\n",
|
||||
k,
|
||||
required,
|
||||
v.Default,
|
||||
v.Description)
|
||||
}
|
||||
|
||||
return strings.TrimSpace(result)
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
@ -264,42 +262,6 @@ func TestLoadDir_override(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func outputsStr(os []*Output) string {
|
||||
ns := make([]string, 0, len(os))
|
||||
m := make(map[string]*Output)
|
||||
for _, o := range os {
|
||||
ns = append(ns, o.Name)
|
||||
m[o.Name] = o
|
||||
}
|
||||
sort.Strings(ns)
|
||||
|
||||
result := ""
|
||||
for _, n := range ns {
|
||||
o := m[n]
|
||||
|
||||
result += fmt.Sprintf("%s\n", n)
|
||||
|
||||
if len(o.RawConfig.Variables) > 0 {
|
||||
result += fmt.Sprintf(" vars\n")
|
||||
for _, rawV := range o.RawConfig.Variables {
|
||||
kind := "unknown"
|
||||
str := rawV.FullKey()
|
||||
|
||||
switch rawV.(type) {
|
||||
case *ResourceVariable:
|
||||
kind = "resource"
|
||||
case *UserVariable:
|
||||
kind = "user"
|
||||
}
|
||||
|
||||
result += fmt.Sprintf(" %s: %s\n", kind, str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return strings.TrimSpace(result)
|
||||
}
|
||||
|
||||
func TestLoad_provisioners(t *testing.T) {
|
||||
c, err := Load(filepath.Join(fixtureDir, "provisioners.tf"))
|
||||
if err != nil {
|
||||
|
@ -354,216 +316,6 @@ func TestLoad_connections(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func modulesStr(ms []*Module) string {
|
||||
result := ""
|
||||
order := make([]int, 0, len(ms))
|
||||
ks := make([]string, 0, len(ms))
|
||||
mapping := make(map[string]int)
|
||||
for i, m := range ms {
|
||||
k := m.Id()
|
||||
ks = append(ks, k)
|
||||
mapping[k] = i
|
||||
}
|
||||
sort.Strings(ks)
|
||||
for _, k := range ks {
|
||||
order = append(order, mapping[k])
|
||||
}
|
||||
|
||||
for _, i := range order {
|
||||
m := ms[i]
|
||||
result += fmt.Sprintf("%s\n", m.Id())
|
||||
|
||||
ks := make([]string, 0, len(m.RawConfig.Raw))
|
||||
for k, _ := range m.RawConfig.Raw {
|
||||
ks = append(ks, k)
|
||||
}
|
||||
sort.Strings(ks)
|
||||
|
||||
result += fmt.Sprintf(" source = %s\n", m.Source)
|
||||
|
||||
for _, k := range ks {
|
||||
result += fmt.Sprintf(" %s\n", k)
|
||||
}
|
||||
}
|
||||
|
||||
return strings.TrimSpace(result)
|
||||
}
|
||||
|
||||
// This helper turns a provider configs field into a deterministic
|
||||
// string value for comparison in tests.
|
||||
func providerConfigsStr(pcs []*ProviderConfig) string {
|
||||
result := ""
|
||||
|
||||
ns := make([]string, 0, len(pcs))
|
||||
m := make(map[string]*ProviderConfig)
|
||||
for _, n := range pcs {
|
||||
ns = append(ns, n.Name)
|
||||
m[n.Name] = n
|
||||
}
|
||||
sort.Strings(ns)
|
||||
|
||||
for _, n := range ns {
|
||||
pc := m[n]
|
||||
|
||||
result += fmt.Sprintf("%s\n", n)
|
||||
|
||||
keys := make([]string, 0, len(pc.RawConfig.Raw))
|
||||
for k, _ := range pc.RawConfig.Raw {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
for _, k := range keys {
|
||||
result += fmt.Sprintf(" %s\n", k)
|
||||
}
|
||||
|
||||
if len(pc.RawConfig.Variables) > 0 {
|
||||
result += fmt.Sprintf(" vars\n")
|
||||
for _, rawV := range pc.RawConfig.Variables {
|
||||
kind := "unknown"
|
||||
str := rawV.FullKey()
|
||||
|
||||
switch rawV.(type) {
|
||||
case *ResourceVariable:
|
||||
kind = "resource"
|
||||
case *UserVariable:
|
||||
kind = "user"
|
||||
}
|
||||
|
||||
result += fmt.Sprintf(" %s: %s\n", kind, str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return strings.TrimSpace(result)
|
||||
}
|
||||
|
||||
// This helper turns a resources field into a deterministic
|
||||
// string value for comparison in tests.
|
||||
func resourcesStr(rs []*Resource) string {
|
||||
result := ""
|
||||
order := make([]int, 0, len(rs))
|
||||
ks := make([]string, 0, len(rs))
|
||||
mapping := make(map[string]int)
|
||||
for i, r := range rs {
|
||||
k := fmt.Sprintf("%s[%s]", r.Type, r.Name)
|
||||
ks = append(ks, k)
|
||||
mapping[k] = i
|
||||
}
|
||||
sort.Strings(ks)
|
||||
for _, k := range ks {
|
||||
order = append(order, mapping[k])
|
||||
}
|
||||
|
||||
for _, i := range order {
|
||||
r := rs[i]
|
||||
result += fmt.Sprintf(
|
||||
"%s[%s] (x%d)\n",
|
||||
r.Type,
|
||||
r.Name,
|
||||
r.Count)
|
||||
|
||||
ks := make([]string, 0, len(r.RawConfig.Raw))
|
||||
for k, _ := range r.RawConfig.Raw {
|
||||
ks = append(ks, k)
|
||||
}
|
||||
sort.Strings(ks)
|
||||
|
||||
for _, k := range ks {
|
||||
result += fmt.Sprintf(" %s\n", k)
|
||||
}
|
||||
|
||||
if len(r.Provisioners) > 0 {
|
||||
result += fmt.Sprintf(" provisioners\n")
|
||||
for _, p := range r.Provisioners {
|
||||
result += fmt.Sprintf(" %s\n", p.Type)
|
||||
|
||||
ks := make([]string, 0, len(p.RawConfig.Raw))
|
||||
for k, _ := range p.RawConfig.Raw {
|
||||
ks = append(ks, k)
|
||||
}
|
||||
sort.Strings(ks)
|
||||
|
||||
for _, k := range ks {
|
||||
result += fmt.Sprintf(" %s\n", k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.DependsOn) > 0 {
|
||||
result += fmt.Sprintf(" dependsOn\n")
|
||||
for _, d := range r.DependsOn {
|
||||
result += fmt.Sprintf(" %s\n", d)
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.RawConfig.Variables) > 0 {
|
||||
result += fmt.Sprintf(" vars\n")
|
||||
|
||||
ks := make([]string, 0, len(r.RawConfig.Variables))
|
||||
for k, _ := range r.RawConfig.Variables {
|
||||
ks = append(ks, k)
|
||||
}
|
||||
sort.Strings(ks)
|
||||
|
||||
for _, k := range ks {
|
||||
rawV := r.RawConfig.Variables[k]
|
||||
kind := "unknown"
|
||||
str := rawV.FullKey()
|
||||
|
||||
switch rawV.(type) {
|
||||
case *ResourceVariable:
|
||||
kind = "resource"
|
||||
case *UserVariable:
|
||||
kind = "user"
|
||||
}
|
||||
|
||||
result += fmt.Sprintf(" %s: %s\n", kind, str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return strings.TrimSpace(result)
|
||||
}
|
||||
|
||||
// This helper turns a variables field into a deterministic
|
||||
// string value for comparison in tests.
|
||||
func variablesStr(vs []*Variable) string {
|
||||
result := ""
|
||||
ks := make([]string, 0, len(vs))
|
||||
m := make(map[string]*Variable)
|
||||
for _, v := range vs {
|
||||
ks = append(ks, v.Name)
|
||||
m[v.Name] = v
|
||||
}
|
||||
sort.Strings(ks)
|
||||
|
||||
for _, k := range ks {
|
||||
v := m[k]
|
||||
|
||||
required := ""
|
||||
if v.Required() {
|
||||
required = " (required)"
|
||||
}
|
||||
|
||||
if v.Default == nil || v.Default == "" {
|
||||
v.Default = "<>"
|
||||
}
|
||||
if v.Description == "" {
|
||||
v.Description = "<>"
|
||||
}
|
||||
|
||||
result += fmt.Sprintf(
|
||||
"%s%s\n %v\n %s\n",
|
||||
k,
|
||||
required,
|
||||
v.Default,
|
||||
v.Description)
|
||||
}
|
||||
|
||||
return strings.TrimSpace(result)
|
||||
}
|
||||
|
||||
const basicOutputsStr = `
|
||||
web_ip
|
||||
vars
|
||||
|
|
|
@ -56,17 +56,6 @@ func (t *Tree) Children() map[string]*Tree {
|
|||
return t.children
|
||||
}
|
||||
|
||||
// Flatten takes the entire module tree and flattens it into a single
|
||||
// namespace in *config.Config with no module imports.
|
||||
//
|
||||
// Validate is called here implicitly, since it is important that semantic
|
||||
// checks pass before flattening the configuration. Otherwise, encapsulation
|
||||
// breaks in horrible ways and the errors that come out the other side
|
||||
// will be surprising.
|
||||
func (t *Tree) Flatten() (*config.Config, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Loaded says whether or not this tree has been loaded or not yet.
|
||||
func (t *Tree) Loaded() bool {
|
||||
t.lock.RLock()
|
||||
|
@ -212,7 +201,7 @@ func (t *Tree) Validate() error {
|
|||
}
|
||||
|
||||
// If something goes wrong, here is our error template
|
||||
newErr := &ValidateError{Name: []string{t.Name()}}
|
||||
newErr := &TreeError{Name: []string{t.Name()}}
|
||||
|
||||
// Validate our configuration first.
|
||||
if err := t.config.Validate(); err != nil {
|
||||
|
@ -230,7 +219,7 @@ func (t *Tree) Validate() error {
|
|||
continue
|
||||
}
|
||||
|
||||
verr, ok := err.(*ValidateError)
|
||||
verr, ok := err.(*TreeError)
|
||||
if !ok {
|
||||
// Unknown error, just return...
|
||||
return err
|
||||
|
@ -301,14 +290,14 @@ func (t *Tree) Validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ValidateError is an error returned by Tree.Validate if an error occurs
|
||||
// TreeError is an error returned by Tree.Validate if an error occurs
|
||||
// with validation.
|
||||
type ValidateError struct {
|
||||
type TreeError struct {
|
||||
Name []string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *ValidateError) Error() string {
|
||||
func (e *TreeError) Error() string {
|
||||
// Build up the name
|
||||
var buf bytes.Buffer
|
||||
for _, n := range e.Name {
|
||||
|
|
Loading…
Reference in New Issue