github.com/ns1/terraform@v0.7.10-0.20161109153551-8949419bef40/helper/schema/field_reader_config_test.go (about)

     1  package schema
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  
     7  	"github.com/hashicorp/hil/ast"
     8  	"github.com/hashicorp/terraform/config"
     9  	"github.com/hashicorp/terraform/terraform"
    10  )
    11  
    12  func TestConfigFieldReader_impl(t *testing.T) {
    13  	var _ FieldReader = new(ConfigFieldReader)
    14  }
    15  
    16  func TestConfigFieldReader(t *testing.T) {
    17  	testFieldReader(t, func(s map[string]*Schema) FieldReader {
    18  		return &ConfigFieldReader{
    19  			Schema: s,
    20  
    21  			Config: testConfig(t, map[string]interface{}{
    22  				"bool":   true,
    23  				"float":  3.1415,
    24  				"int":    42,
    25  				"string": "string",
    26  
    27  				"list": []interface{}{"foo", "bar"},
    28  
    29  				"listInt": []interface{}{21, 42},
    30  
    31  				"map": map[string]interface{}{
    32  					"foo": "bar",
    33  					"bar": "baz",
    34  				},
    35  
    36  				"set": []interface{}{10, 50},
    37  				"setDeep": []interface{}{
    38  					map[string]interface{}{
    39  						"index": 10,
    40  						"value": "foo",
    41  					},
    42  					map[string]interface{}{
    43  						"index": 50,
    44  						"value": "bar",
    45  					},
    46  				},
    47  			}),
    48  		}
    49  	})
    50  }
    51  
    52  // This contains custom table tests for our ConfigFieldReader
    53  func TestConfigFieldReader_custom(t *testing.T) {
    54  	schema := map[string]*Schema{
    55  		"bool": &Schema{
    56  			Type: TypeBool,
    57  		},
    58  	}
    59  
    60  	cases := map[string]struct {
    61  		Addr   []string
    62  		Result FieldReadResult
    63  		Config *terraform.ResourceConfig
    64  		Err    bool
    65  	}{
    66  		"basic": {
    67  			[]string{"bool"},
    68  			FieldReadResult{
    69  				Value:  true,
    70  				Exists: true,
    71  			},
    72  			testConfig(t, map[string]interface{}{
    73  				"bool": true,
    74  			}),
    75  			false,
    76  		},
    77  
    78  		"computed": {
    79  			[]string{"bool"},
    80  			FieldReadResult{
    81  				Exists:   true,
    82  				Computed: true,
    83  			},
    84  			testConfigInterpolate(t, map[string]interface{}{
    85  				"bool": "${var.foo}",
    86  			}, map[string]ast.Variable{
    87  				"var.foo": ast.Variable{
    88  					Value: config.UnknownVariableValue,
    89  					Type:  ast.TypeString,
    90  				},
    91  			}),
    92  			false,
    93  		},
    94  	}
    95  
    96  	for name, tc := range cases {
    97  		t.Run(name, func(t *testing.T) {
    98  			r := &ConfigFieldReader{
    99  				Schema: schema,
   100  				Config: tc.Config,
   101  			}
   102  			out, err := r.ReadField(tc.Addr)
   103  			if err != nil != tc.Err {
   104  				t.Fatalf("%s: err: %s", name, err)
   105  			}
   106  			if s, ok := out.Value.(*Set); ok {
   107  				// If it is a set, convert to a list so its more easily checked.
   108  				out.Value = s.List()
   109  			}
   110  			if !reflect.DeepEqual(tc.Result, out) {
   111  				t.Fatalf("%s: bad: %#v", name, out)
   112  			}
   113  		})
   114  	}
   115  }
   116  
   117  func TestConfigFieldReader_DefaultHandling(t *testing.T) {
   118  	schema := map[string]*Schema{
   119  		"strWithDefault": &Schema{
   120  			Type:    TypeString,
   121  			Default: "ImADefault",
   122  		},
   123  		"strWithDefaultFunc": &Schema{
   124  			Type: TypeString,
   125  			DefaultFunc: func() (interface{}, error) {
   126  				return "FuncDefault", nil
   127  			},
   128  		},
   129  	}
   130  
   131  	cases := map[string]struct {
   132  		Addr   []string
   133  		Result FieldReadResult
   134  		Config *terraform.ResourceConfig
   135  		Err    bool
   136  	}{
   137  		"gets default value when no config set": {
   138  			[]string{"strWithDefault"},
   139  			FieldReadResult{
   140  				Value:    "ImADefault",
   141  				Exists:   true,
   142  				Computed: false,
   143  			},
   144  			testConfig(t, map[string]interface{}{}),
   145  			false,
   146  		},
   147  		"config overrides default value": {
   148  			[]string{"strWithDefault"},
   149  			FieldReadResult{
   150  				Value:    "fromConfig",
   151  				Exists:   true,
   152  				Computed: false,
   153  			},
   154  			testConfig(t, map[string]interface{}{
   155  				"strWithDefault": "fromConfig",
   156  			}),
   157  			false,
   158  		},
   159  		"gets default from function when no config set": {
   160  			[]string{"strWithDefaultFunc"},
   161  			FieldReadResult{
   162  				Value:    "FuncDefault",
   163  				Exists:   true,
   164  				Computed: false,
   165  			},
   166  			testConfig(t, map[string]interface{}{}),
   167  			false,
   168  		},
   169  		"config overrides default function": {
   170  			[]string{"strWithDefaultFunc"},
   171  			FieldReadResult{
   172  				Value:    "fromConfig",
   173  				Exists:   true,
   174  				Computed: false,
   175  			},
   176  			testConfig(t, map[string]interface{}{
   177  				"strWithDefaultFunc": "fromConfig",
   178  			}),
   179  			false,
   180  		},
   181  	}
   182  
   183  	for name, tc := range cases {
   184  		r := &ConfigFieldReader{
   185  			Schema: schema,
   186  			Config: tc.Config,
   187  		}
   188  		out, err := r.ReadField(tc.Addr)
   189  		if err != nil != tc.Err {
   190  			t.Fatalf("%s: err: %s", name, err)
   191  		}
   192  		if s, ok := out.Value.(*Set); ok {
   193  			// If it is a set, convert to a list so its more easily checked.
   194  			out.Value = s.List()
   195  		}
   196  		if !reflect.DeepEqual(tc.Result, out) {
   197  			t.Fatalf("%s: bad: %#v", name, out)
   198  		}
   199  	}
   200  }
   201  
   202  func TestConfigFieldReader_ComputedMap(t *testing.T) {
   203  	schema := map[string]*Schema{
   204  		"map": &Schema{
   205  			Type:     TypeMap,
   206  			Computed: true,
   207  		},
   208  	}
   209  
   210  	cases := map[string]struct {
   211  		Addr   []string
   212  		Result FieldReadResult
   213  		Config *terraform.ResourceConfig
   214  		Err    bool
   215  	}{
   216  		"set, normal": {
   217  			[]string{"map"},
   218  			FieldReadResult{
   219  				Value: map[string]interface{}{
   220  					"foo": "bar",
   221  				},
   222  				Exists:   true,
   223  				Computed: false,
   224  			},
   225  			testConfig(t, map[string]interface{}{
   226  				"map": map[string]interface{}{
   227  					"foo": "bar",
   228  				},
   229  			}),
   230  			false,
   231  		},
   232  
   233  		"computed element": {
   234  			[]string{"map"},
   235  			FieldReadResult{
   236  				Exists:   true,
   237  				Computed: true,
   238  			},
   239  			testConfigInterpolate(t, map[string]interface{}{
   240  				"map": map[string]interface{}{
   241  					"foo": "${var.foo}",
   242  				},
   243  			}, map[string]ast.Variable{
   244  				"var.foo": ast.Variable{
   245  					Value: config.UnknownVariableValue,
   246  					Type:  ast.TypeString,
   247  				},
   248  			}),
   249  			false,
   250  		},
   251  
   252  		"native map": {
   253  			[]string{"map"},
   254  			FieldReadResult{
   255  				Value: map[string]interface{}{
   256  					"bar": "baz",
   257  					"baz": "bar",
   258  				},
   259  				Exists:   true,
   260  				Computed: false,
   261  			},
   262  			testConfigInterpolate(t, map[string]interface{}{
   263  				"map": "${var.foo}",
   264  			}, map[string]ast.Variable{
   265  				"var.foo": ast.Variable{
   266  					Type: ast.TypeMap,
   267  					Value: map[string]ast.Variable{
   268  						"bar": ast.Variable{
   269  							Type:  ast.TypeString,
   270  							Value: "baz",
   271  						},
   272  						"baz": ast.Variable{
   273  							Type:  ast.TypeString,
   274  							Value: "bar",
   275  						},
   276  					},
   277  				},
   278  			}),
   279  			false,
   280  		},
   281  	}
   282  
   283  	for name, tc := range cases {
   284  		r := &ConfigFieldReader{
   285  			Schema: schema,
   286  			Config: tc.Config,
   287  		}
   288  		out, err := r.ReadField(tc.Addr)
   289  		if err != nil != tc.Err {
   290  			t.Fatalf("%s: err: %s", name, err)
   291  		}
   292  		if s, ok := out.Value.(*Set); ok {
   293  			// If it is a set, convert to the raw map
   294  			out.Value = s.m
   295  			if len(s.m) == 0 {
   296  				out.Value = nil
   297  			}
   298  		}
   299  		if !reflect.DeepEqual(tc.Result, out) {
   300  			t.Fatalf("%s: bad: %#v", name, out)
   301  		}
   302  	}
   303  }
   304  
   305  func TestConfigFieldReader_ComputedSet(t *testing.T) {
   306  	schema := map[string]*Schema{
   307  		"strSet": &Schema{
   308  			Type: TypeSet,
   309  			Elem: &Schema{Type: TypeString},
   310  			Set:  HashString,
   311  		},
   312  	}
   313  
   314  	cases := map[string]struct {
   315  		Addr   []string
   316  		Result FieldReadResult
   317  		Config *terraform.ResourceConfig
   318  		Err    bool
   319  	}{
   320  		"set, normal": {
   321  			[]string{"strSet"},
   322  			FieldReadResult{
   323  				Value: map[string]interface{}{
   324  					"2356372769": "foo",
   325  				},
   326  				Exists:   true,
   327  				Computed: false,
   328  			},
   329  			testConfig(t, map[string]interface{}{
   330  				"strSet": []interface{}{"foo"},
   331  			}),
   332  			false,
   333  		},
   334  
   335  		"set, computed element": {
   336  			[]string{"strSet"},
   337  			FieldReadResult{
   338  				Value:    nil,
   339  				Exists:   true,
   340  				Computed: true,
   341  			},
   342  			testConfigInterpolate(t, map[string]interface{}{
   343  				"strSet": []interface{}{"${var.foo}"},
   344  			}, map[string]ast.Variable{
   345  				"var.foo": ast.Variable{
   346  					Value: config.UnknownVariableValue,
   347  					Type:  ast.TypeString,
   348  				},
   349  			}),
   350  			false,
   351  		},
   352  
   353  		"set, computed element substring": {
   354  			[]string{"strSet"},
   355  			FieldReadResult{
   356  				Value:    nil,
   357  				Exists:   true,
   358  				Computed: true,
   359  			},
   360  			testConfigInterpolate(t, map[string]interface{}{
   361  				"strSet": []interface{}{"${var.foo}/32"},
   362  			}, map[string]ast.Variable{
   363  				"var.foo": ast.Variable{
   364  					Value: config.UnknownVariableValue,
   365  					Type:  ast.TypeString,
   366  				},
   367  			}),
   368  			false,
   369  		},
   370  	}
   371  
   372  	for name, tc := range cases {
   373  		r := &ConfigFieldReader{
   374  			Schema: schema,
   375  			Config: tc.Config,
   376  		}
   377  		out, err := r.ReadField(tc.Addr)
   378  		if err != nil != tc.Err {
   379  			t.Fatalf("%s: err: %s", name, err)
   380  		}
   381  		if s, ok := out.Value.(*Set); ok {
   382  			// If it is a set, convert to the raw map
   383  			out.Value = s.m
   384  			if len(s.m) == 0 {
   385  				out.Value = nil
   386  			}
   387  		}
   388  		if !reflect.DeepEqual(tc.Result, out) {
   389  			t.Fatalf("%s: bad: %#v", name, out)
   390  		}
   391  	}
   392  }
   393  
   394  func testConfig(
   395  	t *testing.T, raw map[string]interface{}) *terraform.ResourceConfig {
   396  	return testConfigInterpolate(t, raw, nil)
   397  }
   398  
   399  func testConfigInterpolate(
   400  	t *testing.T,
   401  	raw map[string]interface{},
   402  	vs map[string]ast.Variable) *terraform.ResourceConfig {
   403  
   404  	rc, err := config.NewRawConfig(raw)
   405  	if err != nil {
   406  		t.Fatalf("err: %s", err)
   407  	}
   408  	if len(vs) > 0 {
   409  		if err := rc.Interpolate(vs); err != nil {
   410  			t.Fatalf("err: %s", err)
   411  		}
   412  	}
   413  
   414  	return terraform.NewResourceConfig(rc)
   415  }