github.com/richardbowden/terraform@v0.6.12-0.20160901200758-30ea22c25211/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  func TestConfigFieldReader_DefaultHandling(t *testing.T) {
    53  	schema := map[string]*Schema{
    54  		"strWithDefault": &Schema{
    55  			Type:    TypeString,
    56  			Default: "ImADefault",
    57  		},
    58  		"strWithDefaultFunc": &Schema{
    59  			Type: TypeString,
    60  			DefaultFunc: func() (interface{}, error) {
    61  				return "FuncDefault", nil
    62  			},
    63  		},
    64  	}
    65  
    66  	cases := map[string]struct {
    67  		Addr   []string
    68  		Result FieldReadResult
    69  		Config *terraform.ResourceConfig
    70  		Err    bool
    71  	}{
    72  		"gets default value when no config set": {
    73  			[]string{"strWithDefault"},
    74  			FieldReadResult{
    75  				Value:    "ImADefault",
    76  				Exists:   true,
    77  				Computed: false,
    78  			},
    79  			testConfig(t, map[string]interface{}{}),
    80  			false,
    81  		},
    82  		"config overrides default value": {
    83  			[]string{"strWithDefault"},
    84  			FieldReadResult{
    85  				Value:    "fromConfig",
    86  				Exists:   true,
    87  				Computed: false,
    88  			},
    89  			testConfig(t, map[string]interface{}{
    90  				"strWithDefault": "fromConfig",
    91  			}),
    92  			false,
    93  		},
    94  		"gets default from function when no config set": {
    95  			[]string{"strWithDefaultFunc"},
    96  			FieldReadResult{
    97  				Value:    "FuncDefault",
    98  				Exists:   true,
    99  				Computed: false,
   100  			},
   101  			testConfig(t, map[string]interface{}{}),
   102  			false,
   103  		},
   104  		"config overrides default function": {
   105  			[]string{"strWithDefaultFunc"},
   106  			FieldReadResult{
   107  				Value:    "fromConfig",
   108  				Exists:   true,
   109  				Computed: false,
   110  			},
   111  			testConfig(t, map[string]interface{}{
   112  				"strWithDefaultFunc": "fromConfig",
   113  			}),
   114  			false,
   115  		},
   116  	}
   117  
   118  	for name, tc := range cases {
   119  		r := &ConfigFieldReader{
   120  			Schema: schema,
   121  			Config: tc.Config,
   122  		}
   123  		out, err := r.ReadField(tc.Addr)
   124  		if err != nil != tc.Err {
   125  			t.Fatalf("%s: err: %s", name, err)
   126  		}
   127  		if s, ok := out.Value.(*Set); ok {
   128  			// If it is a set, convert to a list so its more easily checked.
   129  			out.Value = s.List()
   130  		}
   131  		if !reflect.DeepEqual(tc.Result, out) {
   132  			t.Fatalf("%s: bad: %#v", name, out)
   133  		}
   134  	}
   135  }
   136  
   137  func TestConfigFieldReader_ComputedMap(t *testing.T) {
   138  	schema := map[string]*Schema{
   139  		"map": &Schema{
   140  			Type:     TypeMap,
   141  			Computed: true,
   142  		},
   143  	}
   144  
   145  	cases := map[string]struct {
   146  		Addr   []string
   147  		Result FieldReadResult
   148  		Config *terraform.ResourceConfig
   149  		Err    bool
   150  	}{
   151  		"set, normal": {
   152  			[]string{"map"},
   153  			FieldReadResult{
   154  				Value: map[string]interface{}{
   155  					"foo": "bar",
   156  				},
   157  				Exists:   true,
   158  				Computed: false,
   159  			},
   160  			testConfig(t, map[string]interface{}{
   161  				"map": map[string]interface{}{
   162  					"foo": "bar",
   163  				},
   164  			}),
   165  			false,
   166  		},
   167  
   168  		"computed element": {
   169  			[]string{"map"},
   170  			FieldReadResult{
   171  				Exists:   true,
   172  				Computed: true,
   173  			},
   174  			testConfigInterpolate(t, map[string]interface{}{
   175  				"map": map[string]interface{}{
   176  					"foo": "${var.foo}",
   177  				},
   178  			}, map[string]ast.Variable{
   179  				"var.foo": ast.Variable{
   180  					Value: config.UnknownVariableValue,
   181  					Type:  ast.TypeString,
   182  				},
   183  			}),
   184  			false,
   185  		},
   186  
   187  		"native map": {
   188  			[]string{"map"},
   189  			FieldReadResult{
   190  				Value: map[string]interface{}{
   191  					"bar": "baz",
   192  					"baz": "bar",
   193  				},
   194  				Exists:   true,
   195  				Computed: false,
   196  			},
   197  			testConfigInterpolate(t, map[string]interface{}{
   198  				"map": "${var.foo}",
   199  			}, map[string]ast.Variable{
   200  				"var.foo": ast.Variable{
   201  					Type: ast.TypeMap,
   202  					Value: map[string]ast.Variable{
   203  						"bar": ast.Variable{
   204  							Type:  ast.TypeString,
   205  							Value: "baz",
   206  						},
   207  						"baz": ast.Variable{
   208  							Type:  ast.TypeString,
   209  							Value: "bar",
   210  						},
   211  					},
   212  				},
   213  			}),
   214  			false,
   215  		},
   216  	}
   217  
   218  	for name, tc := range cases {
   219  		r := &ConfigFieldReader{
   220  			Schema: schema,
   221  			Config: tc.Config,
   222  		}
   223  		out, err := r.ReadField(tc.Addr)
   224  		if err != nil != tc.Err {
   225  			t.Fatalf("%s: err: %s", name, err)
   226  		}
   227  		if s, ok := out.Value.(*Set); ok {
   228  			// If it is a set, convert to the raw map
   229  			out.Value = s.m
   230  			if len(s.m) == 0 {
   231  				out.Value = nil
   232  			}
   233  		}
   234  		if !reflect.DeepEqual(tc.Result, out) {
   235  			t.Fatalf("%s: bad: %#v", name, out)
   236  		}
   237  	}
   238  }
   239  
   240  func TestConfigFieldReader_ComputedSet(t *testing.T) {
   241  	schema := map[string]*Schema{
   242  		"strSet": &Schema{
   243  			Type: TypeSet,
   244  			Elem: &Schema{Type: TypeString},
   245  			Set:  HashString,
   246  		},
   247  	}
   248  
   249  	cases := map[string]struct {
   250  		Addr   []string
   251  		Result FieldReadResult
   252  		Config *terraform.ResourceConfig
   253  		Err    bool
   254  	}{
   255  		"set, normal": {
   256  			[]string{"strSet"},
   257  			FieldReadResult{
   258  				Value: map[string]interface{}{
   259  					"2356372769": "foo",
   260  				},
   261  				Exists:   true,
   262  				Computed: false,
   263  			},
   264  			testConfig(t, map[string]interface{}{
   265  				"strSet": []interface{}{"foo"},
   266  			}),
   267  			false,
   268  		},
   269  
   270  		"set, computed element": {
   271  			[]string{"strSet"},
   272  			FieldReadResult{
   273  				Value:    nil,
   274  				Exists:   true,
   275  				Computed: true,
   276  			},
   277  			testConfigInterpolate(t, map[string]interface{}{
   278  				"strSet": []interface{}{"${var.foo}"},
   279  			}, map[string]ast.Variable{
   280  				"var.foo": ast.Variable{
   281  					Value: config.UnknownVariableValue,
   282  					Type:  ast.TypeString,
   283  				},
   284  			}),
   285  			false,
   286  		},
   287  
   288  		"set, computed element substring": {
   289  			[]string{"strSet"},
   290  			FieldReadResult{
   291  				Value:    nil,
   292  				Exists:   true,
   293  				Computed: true,
   294  			},
   295  			testConfigInterpolate(t, map[string]interface{}{
   296  				"strSet": []interface{}{"${var.foo}/32"},
   297  			}, map[string]ast.Variable{
   298  				"var.foo": ast.Variable{
   299  					Value: config.UnknownVariableValue,
   300  					Type:  ast.TypeString,
   301  				},
   302  			}),
   303  			false,
   304  		},
   305  	}
   306  
   307  	for name, tc := range cases {
   308  		r := &ConfigFieldReader{
   309  			Schema: schema,
   310  			Config: tc.Config,
   311  		}
   312  		out, err := r.ReadField(tc.Addr)
   313  		if err != nil != tc.Err {
   314  			t.Fatalf("%s: err: %s", name, err)
   315  		}
   316  		if s, ok := out.Value.(*Set); ok {
   317  			// If it is a set, convert to the raw map
   318  			out.Value = s.m
   319  			if len(s.m) == 0 {
   320  				out.Value = nil
   321  			}
   322  		}
   323  		if !reflect.DeepEqual(tc.Result, out) {
   324  			t.Fatalf("%s: bad: %#v", name, out)
   325  		}
   326  	}
   327  }
   328  
   329  func testConfig(
   330  	t *testing.T, raw map[string]interface{}) *terraform.ResourceConfig {
   331  	return testConfigInterpolate(t, raw, nil)
   332  }
   333  
   334  func testConfigInterpolate(
   335  	t *testing.T,
   336  	raw map[string]interface{},
   337  	vs map[string]ast.Variable) *terraform.ResourceConfig {
   338  
   339  	rc, err := config.NewRawConfig(raw)
   340  	if err != nil {
   341  		t.Fatalf("err: %s", err)
   342  	}
   343  	if len(vs) > 0 {
   344  		if err := rc.Interpolate(vs); err != nil {
   345  			t.Fatalf("err: %s", err)
   346  		}
   347  	}
   348  
   349  	return terraform.NewResourceConfig(rc)
   350  }