github.com/ves/terraform@v0.8.0-beta2/helper/schema/field_reader_config_test.go (about)

     1  package schema
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"reflect"
     7  	"testing"
     8  
     9  	"github.com/hashicorp/hil/ast"
    10  	"github.com/hashicorp/terraform/config"
    11  	"github.com/hashicorp/terraform/helper/hashcode"
    12  	"github.com/hashicorp/terraform/terraform"
    13  )
    14  
    15  func TestConfigFieldReader_impl(t *testing.T) {
    16  	var _ FieldReader = new(ConfigFieldReader)
    17  }
    18  
    19  func TestConfigFieldReader(t *testing.T) {
    20  	testFieldReader(t, func(s map[string]*Schema) FieldReader {
    21  		return &ConfigFieldReader{
    22  			Schema: s,
    23  
    24  			Config: testConfig(t, map[string]interface{}{
    25  				"bool":   true,
    26  				"float":  3.1415,
    27  				"int":    42,
    28  				"string": "string",
    29  
    30  				"list": []interface{}{"foo", "bar"},
    31  
    32  				"listInt": []interface{}{21, 42},
    33  
    34  				"map": map[string]interface{}{
    35  					"foo": "bar",
    36  					"bar": "baz",
    37  				},
    38  
    39  				"set": []interface{}{10, 50},
    40  				"setDeep": []interface{}{
    41  					map[string]interface{}{
    42  						"index": 10,
    43  						"value": "foo",
    44  					},
    45  					map[string]interface{}{
    46  						"index": 50,
    47  						"value": "bar",
    48  					},
    49  				},
    50  			}),
    51  		}
    52  	})
    53  }
    54  
    55  // This contains custom table tests for our ConfigFieldReader
    56  func TestConfigFieldReader_custom(t *testing.T) {
    57  	schema := map[string]*Schema{
    58  		"bool": &Schema{
    59  			Type: TypeBool,
    60  		},
    61  	}
    62  
    63  	cases := map[string]struct {
    64  		Addr   []string
    65  		Result FieldReadResult
    66  		Config *terraform.ResourceConfig
    67  		Err    bool
    68  	}{
    69  		"basic": {
    70  			[]string{"bool"},
    71  			FieldReadResult{
    72  				Value:  true,
    73  				Exists: true,
    74  			},
    75  			testConfig(t, map[string]interface{}{
    76  				"bool": true,
    77  			}),
    78  			false,
    79  		},
    80  
    81  		"computed": {
    82  			[]string{"bool"},
    83  			FieldReadResult{
    84  				Exists:   true,
    85  				Computed: true,
    86  			},
    87  			testConfigInterpolate(t, map[string]interface{}{
    88  				"bool": "${var.foo}",
    89  			}, map[string]ast.Variable{
    90  				"var.foo": ast.Variable{
    91  					Value: config.UnknownVariableValue,
    92  					Type:  ast.TypeString,
    93  				},
    94  			}),
    95  			false,
    96  		},
    97  	}
    98  
    99  	for name, tc := range cases {
   100  		t.Run(name, func(t *testing.T) {
   101  			r := &ConfigFieldReader{
   102  				Schema: schema,
   103  				Config: tc.Config,
   104  			}
   105  			out, err := r.ReadField(tc.Addr)
   106  			if err != nil != tc.Err {
   107  				t.Fatalf("%s: err: %s", name, err)
   108  			}
   109  			if s, ok := out.Value.(*Set); ok {
   110  				// If it is a set, convert to a list so its more easily checked.
   111  				out.Value = s.List()
   112  			}
   113  			if !reflect.DeepEqual(tc.Result, out) {
   114  				t.Fatalf("%s: bad: %#v", name, out)
   115  			}
   116  		})
   117  	}
   118  }
   119  
   120  func TestConfigFieldReader_DefaultHandling(t *testing.T) {
   121  	schema := map[string]*Schema{
   122  		"strWithDefault": &Schema{
   123  			Type:    TypeString,
   124  			Default: "ImADefault",
   125  		},
   126  		"strWithDefaultFunc": &Schema{
   127  			Type: TypeString,
   128  			DefaultFunc: func() (interface{}, error) {
   129  				return "FuncDefault", nil
   130  			},
   131  		},
   132  	}
   133  
   134  	cases := map[string]struct {
   135  		Addr   []string
   136  		Result FieldReadResult
   137  		Config *terraform.ResourceConfig
   138  		Err    bool
   139  	}{
   140  		"gets default value when no config set": {
   141  			[]string{"strWithDefault"},
   142  			FieldReadResult{
   143  				Value:    "ImADefault",
   144  				Exists:   true,
   145  				Computed: false,
   146  			},
   147  			testConfig(t, map[string]interface{}{}),
   148  			false,
   149  		},
   150  		"config overrides default value": {
   151  			[]string{"strWithDefault"},
   152  			FieldReadResult{
   153  				Value:    "fromConfig",
   154  				Exists:   true,
   155  				Computed: false,
   156  			},
   157  			testConfig(t, map[string]interface{}{
   158  				"strWithDefault": "fromConfig",
   159  			}),
   160  			false,
   161  		},
   162  		"gets default from function when no config set": {
   163  			[]string{"strWithDefaultFunc"},
   164  			FieldReadResult{
   165  				Value:    "FuncDefault",
   166  				Exists:   true,
   167  				Computed: false,
   168  			},
   169  			testConfig(t, map[string]interface{}{}),
   170  			false,
   171  		},
   172  		"config overrides default function": {
   173  			[]string{"strWithDefaultFunc"},
   174  			FieldReadResult{
   175  				Value:    "fromConfig",
   176  				Exists:   true,
   177  				Computed: false,
   178  			},
   179  			testConfig(t, map[string]interface{}{
   180  				"strWithDefaultFunc": "fromConfig",
   181  			}),
   182  			false,
   183  		},
   184  	}
   185  
   186  	for name, tc := range cases {
   187  		r := &ConfigFieldReader{
   188  			Schema: schema,
   189  			Config: tc.Config,
   190  		}
   191  		out, err := r.ReadField(tc.Addr)
   192  		if err != nil != tc.Err {
   193  			t.Fatalf("%s: err: %s", name, err)
   194  		}
   195  		if s, ok := out.Value.(*Set); ok {
   196  			// If it is a set, convert to a list so its more easily checked.
   197  			out.Value = s.List()
   198  		}
   199  		if !reflect.DeepEqual(tc.Result, out) {
   200  			t.Fatalf("%s: bad: %#v", name, out)
   201  		}
   202  	}
   203  }
   204  
   205  func TestConfigFieldReader_ComputedMap(t *testing.T) {
   206  	schema := map[string]*Schema{
   207  		"map": &Schema{
   208  			Type:     TypeMap,
   209  			Computed: true,
   210  		},
   211  	}
   212  
   213  	cases := map[string]struct {
   214  		Addr   []string
   215  		Result FieldReadResult
   216  		Config *terraform.ResourceConfig
   217  		Err    bool
   218  	}{
   219  		"set, normal": {
   220  			[]string{"map"},
   221  			FieldReadResult{
   222  				Value: map[string]interface{}{
   223  					"foo": "bar",
   224  				},
   225  				Exists:   true,
   226  				Computed: false,
   227  			},
   228  			testConfig(t, map[string]interface{}{
   229  				"map": map[string]interface{}{
   230  					"foo": "bar",
   231  				},
   232  			}),
   233  			false,
   234  		},
   235  
   236  		"computed element": {
   237  			[]string{"map"},
   238  			FieldReadResult{
   239  				Exists:   true,
   240  				Computed: true,
   241  			},
   242  			testConfigInterpolate(t, map[string]interface{}{
   243  				"map": map[string]interface{}{
   244  					"foo": "${var.foo}",
   245  				},
   246  			}, map[string]ast.Variable{
   247  				"var.foo": ast.Variable{
   248  					Value: config.UnknownVariableValue,
   249  					Type:  ast.TypeString,
   250  				},
   251  			}),
   252  			false,
   253  		},
   254  
   255  		"native map": {
   256  			[]string{"map"},
   257  			FieldReadResult{
   258  				Value: map[string]interface{}{
   259  					"bar": "baz",
   260  					"baz": "bar",
   261  				},
   262  				Exists:   true,
   263  				Computed: false,
   264  			},
   265  			testConfigInterpolate(t, map[string]interface{}{
   266  				"map": "${var.foo}",
   267  			}, map[string]ast.Variable{
   268  				"var.foo": ast.Variable{
   269  					Type: ast.TypeMap,
   270  					Value: map[string]ast.Variable{
   271  						"bar": ast.Variable{
   272  							Type:  ast.TypeString,
   273  							Value: "baz",
   274  						},
   275  						"baz": ast.Variable{
   276  							Type:  ast.TypeString,
   277  							Value: "bar",
   278  						},
   279  					},
   280  				},
   281  			}),
   282  			false,
   283  		},
   284  	}
   285  
   286  	for name, tc := range cases {
   287  		r := &ConfigFieldReader{
   288  			Schema: schema,
   289  			Config: tc.Config,
   290  		}
   291  		out, err := r.ReadField(tc.Addr)
   292  		if err != nil != tc.Err {
   293  			t.Fatalf("%s: err: %s", name, err)
   294  		}
   295  		if s, ok := out.Value.(*Set); ok {
   296  			// If it is a set, convert to the raw map
   297  			out.Value = s.m
   298  			if len(s.m) == 0 {
   299  				out.Value = nil
   300  			}
   301  		}
   302  		if !reflect.DeepEqual(tc.Result, out) {
   303  			t.Fatalf("%s: bad: %#v", name, out)
   304  		}
   305  	}
   306  }
   307  
   308  func TestConfigFieldReader_ComputedSet(t *testing.T) {
   309  	schema := map[string]*Schema{
   310  		"strSet": &Schema{
   311  			Type: TypeSet,
   312  			Elem: &Schema{Type: TypeString},
   313  			Set:  HashString,
   314  		},
   315  	}
   316  
   317  	cases := map[string]struct {
   318  		Addr   []string
   319  		Result FieldReadResult
   320  		Config *terraform.ResourceConfig
   321  		Err    bool
   322  	}{
   323  		"set, normal": {
   324  			[]string{"strSet"},
   325  			FieldReadResult{
   326  				Value: map[string]interface{}{
   327  					"2356372769": "foo",
   328  				},
   329  				Exists:   true,
   330  				Computed: false,
   331  			},
   332  			testConfig(t, map[string]interface{}{
   333  				"strSet": []interface{}{"foo"},
   334  			}),
   335  			false,
   336  		},
   337  
   338  		"set, computed element": {
   339  			[]string{"strSet"},
   340  			FieldReadResult{
   341  				Value:    nil,
   342  				Exists:   true,
   343  				Computed: true,
   344  			},
   345  			testConfigInterpolate(t, map[string]interface{}{
   346  				"strSet": []interface{}{"${var.foo}"},
   347  			}, map[string]ast.Variable{
   348  				"var.foo": ast.Variable{
   349  					Value: config.UnknownVariableValue,
   350  					Type:  ast.TypeUnknown,
   351  				},
   352  			}),
   353  			false,
   354  		},
   355  
   356  		"set, computed element substring": {
   357  			[]string{"strSet"},
   358  			FieldReadResult{
   359  				Value:    nil,
   360  				Exists:   true,
   361  				Computed: true,
   362  			},
   363  			testConfigInterpolate(t, map[string]interface{}{
   364  				"strSet": []interface{}{"${var.foo}/32"},
   365  			}, map[string]ast.Variable{
   366  				"var.foo": ast.Variable{
   367  					Value: config.UnknownVariableValue,
   368  					Type:  ast.TypeUnknown,
   369  				},
   370  			}),
   371  			false,
   372  		},
   373  	}
   374  
   375  	for name, tc := range cases {
   376  		r := &ConfigFieldReader{
   377  			Schema: schema,
   378  			Config: tc.Config,
   379  		}
   380  		out, err := r.ReadField(tc.Addr)
   381  		if err != nil != tc.Err {
   382  			t.Fatalf("%s: err: %s", name, err)
   383  		}
   384  		if s, ok := out.Value.(*Set); ok {
   385  			// If it is a set, convert to the raw map
   386  			out.Value = s.m
   387  			if len(s.m) == 0 {
   388  				out.Value = nil
   389  			}
   390  		}
   391  		if !reflect.DeepEqual(tc.Result, out) {
   392  			t.Fatalf("%s: bad: %#v", name, out)
   393  		}
   394  	}
   395  }
   396  
   397  func TestConfigFieldReader_computedComplexSet(t *testing.T) {
   398  	hashfunc := func(v interface{}) int {
   399  		var buf bytes.Buffer
   400  		m := v.(map[string]interface{})
   401  		buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
   402  		buf.WriteString(fmt.Sprintf("%s-", m["vhd_uri"].(string)))
   403  		return hashcode.String(buf.String())
   404  	}
   405  
   406  	schema := map[string]*Schema{
   407  		"set": &Schema{
   408  			Type: TypeSet,
   409  			Elem: &Resource{
   410  				Schema: map[string]*Schema{
   411  					"name": {
   412  						Type:     TypeString,
   413  						Required: true,
   414  					},
   415  
   416  					"vhd_uri": {
   417  						Type:     TypeString,
   418  						Required: true,
   419  					},
   420  				},
   421  			},
   422  			Set: hashfunc,
   423  		},
   424  	}
   425  
   426  	cases := map[string]struct {
   427  		Addr   []string
   428  		Result FieldReadResult
   429  		Config *terraform.ResourceConfig
   430  		Err    bool
   431  	}{
   432  		"set, normal": {
   433  			[]string{"set"},
   434  			FieldReadResult{
   435  				Value: map[string]interface{}{
   436  					"532860136": map[string]interface{}{
   437  						"name":    "myosdisk1",
   438  						"vhd_uri": "bar",
   439  					},
   440  				},
   441  				Exists:   true,
   442  				Computed: false,
   443  			},
   444  			testConfig(t, map[string]interface{}{
   445  				"set": []interface{}{
   446  					map[string]interface{}{
   447  						"name":    "myosdisk1",
   448  						"vhd_uri": "bar",
   449  					},
   450  				},
   451  			}),
   452  			false,
   453  		},
   454  
   455  		"set, computed element": {
   456  			[]string{"set"},
   457  			FieldReadResult{
   458  				Value: map[string]interface{}{
   459  					"~3596295623": map[string]interface{}{
   460  						"name":    "myosdisk1",
   461  						"vhd_uri": "${var.foo}/bar",
   462  					},
   463  				},
   464  				Exists:   true,
   465  				Computed: false,
   466  			},
   467  			testConfigInterpolate(t, map[string]interface{}{
   468  				"set": []interface{}{
   469  					map[string]interface{}{
   470  						"name":    "myosdisk1",
   471  						"vhd_uri": "${var.foo}/bar",
   472  					},
   473  				},
   474  			}, map[string]ast.Variable{
   475  				"var.foo": ast.Variable{
   476  					Value: config.UnknownVariableValue,
   477  					Type:  ast.TypeUnknown,
   478  				},
   479  			}),
   480  			false,
   481  		},
   482  
   483  		"set, computed element single": {
   484  			[]string{"set", "~3596295623", "vhd_uri"},
   485  			FieldReadResult{
   486  				Value:    "${var.foo}/bar",
   487  				Exists:   true,
   488  				Computed: true,
   489  			},
   490  			testConfigInterpolate(t, map[string]interface{}{
   491  				"set": []interface{}{
   492  					map[string]interface{}{
   493  						"name":    "myosdisk1",
   494  						"vhd_uri": "${var.foo}/bar",
   495  					},
   496  				},
   497  			}, map[string]ast.Variable{
   498  				"var.foo": ast.Variable{
   499  					Value: config.UnknownVariableValue,
   500  					Type:  ast.TypeUnknown,
   501  				},
   502  			}),
   503  			false,
   504  		},
   505  	}
   506  
   507  	for name, tc := range cases {
   508  		r := &ConfigFieldReader{
   509  			Schema: schema,
   510  			Config: tc.Config,
   511  		}
   512  		out, err := r.ReadField(tc.Addr)
   513  		if err != nil != tc.Err {
   514  			t.Fatalf("%s: err: %s", name, err)
   515  		}
   516  		if s, ok := out.Value.(*Set); ok {
   517  			// If it is a set, convert to the raw map
   518  			out.Value = s.m
   519  			if len(s.m) == 0 {
   520  				out.Value = nil
   521  			}
   522  		}
   523  		if !reflect.DeepEqual(tc.Result, out) {
   524  			t.Fatalf("%s: bad: %#v", name, out)
   525  		}
   526  	}
   527  }
   528  
   529  func testConfig(
   530  	t *testing.T, raw map[string]interface{}) *terraform.ResourceConfig {
   531  	return testConfigInterpolate(t, raw, nil)
   532  }
   533  
   534  func testConfigInterpolate(
   535  	t *testing.T,
   536  	raw map[string]interface{},
   537  	vs map[string]ast.Variable) *terraform.ResourceConfig {
   538  
   539  	rc, err := config.NewRawConfig(raw)
   540  	if err != nil {
   541  		t.Fatalf("err: %s", err)
   542  	}
   543  	if len(vs) > 0 {
   544  		if err := rc.Interpolate(vs); err != nil {
   545  			t.Fatalf("err: %s", err)
   546  		}
   547  	}
   548  
   549  	return terraform.NewResourceConfig(rc)
   550  }