github.com/Hashicorp/terraform@v0.11.12-beta1/helper/schema/field_reader_diff_test.go (about)

     1  package schema
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  
     7  	"github.com/hashicorp/terraform/terraform"
     8  )
     9  
    10  func TestDiffFieldReader_impl(t *testing.T) {
    11  	var _ FieldReader = new(DiffFieldReader)
    12  }
    13  
    14  func TestDiffFieldReader_NestedSetUpdate(t *testing.T) {
    15  	hashFn := func(a interface{}) int {
    16  		m := a.(map[string]interface{})
    17  		return m["val"].(int)
    18  	}
    19  
    20  	schema := map[string]*Schema{
    21  		"list_of_sets_1": &Schema{
    22  			Type: TypeList,
    23  			Elem: &Resource{
    24  				Schema: map[string]*Schema{
    25  					"nested_set": &Schema{
    26  						Type: TypeSet,
    27  						Elem: &Resource{
    28  							Schema: map[string]*Schema{
    29  								"val": &Schema{
    30  									Type: TypeInt,
    31  								},
    32  							},
    33  						},
    34  						Set: hashFn,
    35  					},
    36  				},
    37  			},
    38  		},
    39  		"list_of_sets_2": &Schema{
    40  			Type: TypeList,
    41  			Elem: &Resource{
    42  				Schema: map[string]*Schema{
    43  					"nested_set": &Schema{
    44  						Type: TypeSet,
    45  						Elem: &Resource{
    46  							Schema: map[string]*Schema{
    47  								"val": &Schema{
    48  									Type: TypeInt,
    49  								},
    50  							},
    51  						},
    52  						Set: hashFn,
    53  					},
    54  				},
    55  			},
    56  		},
    57  	}
    58  
    59  	r := &DiffFieldReader{
    60  		Schema: schema,
    61  		Diff: &terraform.InstanceDiff{
    62  			Attributes: map[string]*terraform.ResourceAttrDiff{
    63  				"list_of_sets_1.0.nested_set.1.val": &terraform.ResourceAttrDiff{
    64  					Old:        "1",
    65  					New:        "0",
    66  					NewRemoved: true,
    67  				},
    68  				"list_of_sets_1.0.nested_set.2.val": &terraform.ResourceAttrDiff{
    69  					New: "2",
    70  				},
    71  			},
    72  		},
    73  	}
    74  
    75  	r.Source = &MultiLevelFieldReader{
    76  		Readers: map[string]FieldReader{
    77  			"diff": r,
    78  			"set":  &MapFieldReader{Schema: schema},
    79  			"state": &MapFieldReader{
    80  				Map: &BasicMapReader{
    81  					"list_of_sets_1.#":                  "1",
    82  					"list_of_sets_1.0.nested_set.#":     "1",
    83  					"list_of_sets_1.0.nested_set.1.val": "1",
    84  					"list_of_sets_2.#":                  "1",
    85  					"list_of_sets_2.0.nested_set.#":     "1",
    86  					"list_of_sets_2.0.nested_set.1.val": "1",
    87  				},
    88  				Schema: schema,
    89  			},
    90  		},
    91  		Levels: []string{"state", "config"},
    92  	}
    93  
    94  	out, err := r.ReadField([]string{"list_of_sets_2"})
    95  	if err != nil {
    96  		t.Fatalf("err: %v", err)
    97  	}
    98  
    99  	s := &Set{F: hashFn}
   100  	s.Add(map[string]interface{}{"val": 1})
   101  	expected := s.List()
   102  
   103  	l := out.Value.([]interface{})
   104  	i := l[0].(map[string]interface{})
   105  	actual := i["nested_set"].(*Set).List()
   106  
   107  	if !reflect.DeepEqual(expected, actual) {
   108  		t.Fatalf("bad: NestedSetUpdate\n\nexpected: %#v\n\ngot: %#v\n\n", expected, actual)
   109  	}
   110  }
   111  
   112  // https://github.com/hashicorp/terraform/issues/914
   113  func TestDiffFieldReader_MapHandling(t *testing.T) {
   114  	schema := map[string]*Schema{
   115  		"tags": &Schema{
   116  			Type: TypeMap,
   117  		},
   118  	}
   119  	r := &DiffFieldReader{
   120  		Schema: schema,
   121  		Diff: &terraform.InstanceDiff{
   122  			Attributes: map[string]*terraform.ResourceAttrDiff{
   123  				"tags.%": &terraform.ResourceAttrDiff{
   124  					Old: "1",
   125  					New: "2",
   126  				},
   127  				"tags.baz": &terraform.ResourceAttrDiff{
   128  					Old: "",
   129  					New: "qux",
   130  				},
   131  			},
   132  		},
   133  		Source: &MapFieldReader{
   134  			Schema: schema,
   135  			Map: BasicMapReader(map[string]string{
   136  				"tags.%":   "1",
   137  				"tags.foo": "bar",
   138  			}),
   139  		},
   140  	}
   141  
   142  	result, err := r.ReadField([]string{"tags"})
   143  	if err != nil {
   144  		t.Fatalf("ReadField failed: %#v", err)
   145  	}
   146  
   147  	expected := map[string]interface{}{
   148  		"foo": "bar",
   149  		"baz": "qux",
   150  	}
   151  
   152  	if !reflect.DeepEqual(expected, result.Value) {
   153  		t.Fatalf("bad: DiffHandling\n\nexpected: %#v\n\ngot: %#v\n\n", expected, result.Value)
   154  	}
   155  }
   156  
   157  func TestDiffFieldReader_extra(t *testing.T) {
   158  	schema := map[string]*Schema{
   159  		"stringComputed": &Schema{Type: TypeString},
   160  
   161  		"listMap": &Schema{
   162  			Type: TypeList,
   163  			Elem: &Schema{
   164  				Type: TypeMap,
   165  			},
   166  		},
   167  
   168  		"mapRemove": &Schema{Type: TypeMap},
   169  
   170  		"setChange": &Schema{
   171  			Type:     TypeSet,
   172  			Optional: true,
   173  			Elem: &Resource{
   174  				Schema: map[string]*Schema{
   175  					"index": &Schema{
   176  						Type:     TypeInt,
   177  						Required: true,
   178  					},
   179  
   180  					"value": &Schema{
   181  						Type:     TypeString,
   182  						Required: true,
   183  					},
   184  				},
   185  			},
   186  			Set: func(a interface{}) int {
   187  				m := a.(map[string]interface{})
   188  				return m["index"].(int)
   189  			},
   190  		},
   191  
   192  		"setEmpty": &Schema{
   193  			Type:     TypeSet,
   194  			Optional: true,
   195  			Elem: &Resource{
   196  				Schema: map[string]*Schema{
   197  					"index": &Schema{
   198  						Type:     TypeInt,
   199  						Required: true,
   200  					},
   201  
   202  					"value": &Schema{
   203  						Type:     TypeString,
   204  						Required: true,
   205  					},
   206  				},
   207  			},
   208  			Set: func(a interface{}) int {
   209  				m := a.(map[string]interface{})
   210  				return m["index"].(int)
   211  			},
   212  		},
   213  	}
   214  
   215  	r := &DiffFieldReader{
   216  		Schema: schema,
   217  		Diff: &terraform.InstanceDiff{
   218  			Attributes: map[string]*terraform.ResourceAttrDiff{
   219  				"stringComputed": &terraform.ResourceAttrDiff{
   220  					Old:         "foo",
   221  					New:         "bar",
   222  					NewComputed: true,
   223  				},
   224  
   225  				"listMap.0.bar": &terraform.ResourceAttrDiff{
   226  					NewRemoved: true,
   227  				},
   228  
   229  				"mapRemove.bar": &terraform.ResourceAttrDiff{
   230  					NewRemoved: true,
   231  				},
   232  
   233  				"setChange.10.value": &terraform.ResourceAttrDiff{
   234  					Old: "50",
   235  					New: "80",
   236  				},
   237  
   238  				"setEmpty.#": &terraform.ResourceAttrDiff{
   239  					Old: "2",
   240  					New: "0",
   241  				},
   242  			},
   243  		},
   244  
   245  		Source: &MapFieldReader{
   246  			Schema: schema,
   247  			Map: BasicMapReader(map[string]string{
   248  				"listMap.#":     "2",
   249  				"listMap.0.foo": "bar",
   250  				"listMap.0.bar": "baz",
   251  				"listMap.1.baz": "baz",
   252  
   253  				"mapRemove.foo": "bar",
   254  				"mapRemove.bar": "bar",
   255  
   256  				"setChange.#":        "1",
   257  				"setChange.10.index": "10",
   258  				"setChange.10.value": "50",
   259  
   260  				"setEmpty.#":        "2",
   261  				"setEmpty.10.index": "10",
   262  				"setEmpty.10.value": "50",
   263  				"setEmpty.20.index": "20",
   264  				"setEmpty.20.value": "50",
   265  			}),
   266  		},
   267  	}
   268  
   269  	cases := map[string]struct {
   270  		Addr   []string
   271  		Result FieldReadResult
   272  		Err    bool
   273  	}{
   274  		"stringComputed": {
   275  			[]string{"stringComputed"},
   276  			FieldReadResult{
   277  				Value:    "",
   278  				Exists:   true,
   279  				Computed: true,
   280  			},
   281  			false,
   282  		},
   283  
   284  		"listMapRemoval": {
   285  			[]string{"listMap"},
   286  			FieldReadResult{
   287  				Value: []interface{}{
   288  					map[string]interface{}{
   289  						"foo": "bar",
   290  					},
   291  					map[string]interface{}{
   292  						"baz": "baz",
   293  					},
   294  				},
   295  				Exists: true,
   296  			},
   297  			false,
   298  		},
   299  
   300  		"mapRemove": {
   301  			[]string{"mapRemove"},
   302  			FieldReadResult{
   303  				Value: map[string]interface{}{
   304  					"foo": "bar",
   305  				},
   306  				Exists:   true,
   307  				Computed: false,
   308  			},
   309  			false,
   310  		},
   311  
   312  		"setChange": {
   313  			[]string{"setChange"},
   314  			FieldReadResult{
   315  				Value: []interface{}{
   316  					map[string]interface{}{
   317  						"index": 10,
   318  						"value": "80",
   319  					},
   320  				},
   321  				Exists: true,
   322  			},
   323  			false,
   324  		},
   325  
   326  		"setEmpty": {
   327  			[]string{"setEmpty"},
   328  			FieldReadResult{
   329  				Value:  []interface{}{},
   330  				Exists: true,
   331  			},
   332  			false,
   333  		},
   334  	}
   335  
   336  	for name, tc := range cases {
   337  		out, err := r.ReadField(tc.Addr)
   338  		if err != nil != tc.Err {
   339  			t.Fatalf("%s: err: %s", name, err)
   340  		}
   341  		if s, ok := out.Value.(*Set); ok {
   342  			// If it is a set, convert to a list so its more easily checked.
   343  			out.Value = s.List()
   344  		}
   345  		if !reflect.DeepEqual(tc.Result, out) {
   346  			t.Fatalf("%s: bad: %#v", name, out)
   347  		}
   348  	}
   349  }
   350  
   351  func TestDiffFieldReader(t *testing.T) {
   352  	testFieldReader(t, func(s map[string]*Schema) FieldReader {
   353  		return &DiffFieldReader{
   354  			Schema: s,
   355  			Diff: &terraform.InstanceDiff{
   356  				Attributes: map[string]*terraform.ResourceAttrDiff{
   357  					"bool": &terraform.ResourceAttrDiff{
   358  						Old: "",
   359  						New: "true",
   360  					},
   361  
   362  					"int": &terraform.ResourceAttrDiff{
   363  						Old: "",
   364  						New: "42",
   365  					},
   366  
   367  					"float": &terraform.ResourceAttrDiff{
   368  						Old: "",
   369  						New: "3.1415",
   370  					},
   371  
   372  					"string": &terraform.ResourceAttrDiff{
   373  						Old: "",
   374  						New: "string",
   375  					},
   376  
   377  					"stringComputed": &terraform.ResourceAttrDiff{
   378  						Old:         "foo",
   379  						New:         "bar",
   380  						NewComputed: true,
   381  					},
   382  
   383  					"list.#": &terraform.ResourceAttrDiff{
   384  						Old: "0",
   385  						New: "2",
   386  					},
   387  
   388  					"list.0": &terraform.ResourceAttrDiff{
   389  						Old: "",
   390  						New: "foo",
   391  					},
   392  
   393  					"list.1": &terraform.ResourceAttrDiff{
   394  						Old: "",
   395  						New: "bar",
   396  					},
   397  
   398  					"listInt.#": &terraform.ResourceAttrDiff{
   399  						Old: "0",
   400  						New: "2",
   401  					},
   402  
   403  					"listInt.0": &terraform.ResourceAttrDiff{
   404  						Old: "",
   405  						New: "21",
   406  					},
   407  
   408  					"listInt.1": &terraform.ResourceAttrDiff{
   409  						Old: "",
   410  						New: "42",
   411  					},
   412  
   413  					"map.foo": &terraform.ResourceAttrDiff{
   414  						Old: "",
   415  						New: "bar",
   416  					},
   417  
   418  					"map.bar": &terraform.ResourceAttrDiff{
   419  						Old: "",
   420  						New: "baz",
   421  					},
   422  
   423  					"mapInt.%": &terraform.ResourceAttrDiff{
   424  						Old: "",
   425  						New: "2",
   426  					},
   427  					"mapInt.one": &terraform.ResourceAttrDiff{
   428  						Old: "",
   429  						New: "1",
   430  					},
   431  					"mapInt.two": &terraform.ResourceAttrDiff{
   432  						Old: "",
   433  						New: "2",
   434  					},
   435  
   436  					"mapIntNestedSchema.%": &terraform.ResourceAttrDiff{
   437  						Old: "",
   438  						New: "2",
   439  					},
   440  					"mapIntNestedSchema.one": &terraform.ResourceAttrDiff{
   441  						Old: "",
   442  						New: "1",
   443  					},
   444  					"mapIntNestedSchema.two": &terraform.ResourceAttrDiff{
   445  						Old: "",
   446  						New: "2",
   447  					},
   448  
   449  					"mapFloat.%": &terraform.ResourceAttrDiff{
   450  						Old: "",
   451  						New: "1",
   452  					},
   453  					"mapFloat.oneDotTwo": &terraform.ResourceAttrDiff{
   454  						Old: "",
   455  						New: "1.2",
   456  					},
   457  
   458  					"mapBool.%": &terraform.ResourceAttrDiff{
   459  						Old: "",
   460  						New: "2",
   461  					},
   462  					"mapBool.True": &terraform.ResourceAttrDiff{
   463  						Old: "",
   464  						New: "true",
   465  					},
   466  					"mapBool.False": &terraform.ResourceAttrDiff{
   467  						Old: "",
   468  						New: "false",
   469  					},
   470  
   471  					"set.#": &terraform.ResourceAttrDiff{
   472  						Old: "0",
   473  						New: "2",
   474  					},
   475  
   476  					"set.10": &terraform.ResourceAttrDiff{
   477  						Old: "",
   478  						New: "10",
   479  					},
   480  
   481  					"set.50": &terraform.ResourceAttrDiff{
   482  						Old: "",
   483  						New: "50",
   484  					},
   485  
   486  					"setDeep.#": &terraform.ResourceAttrDiff{
   487  						Old: "0",
   488  						New: "2",
   489  					},
   490  
   491  					"setDeep.10.index": &terraform.ResourceAttrDiff{
   492  						Old: "",
   493  						New: "10",
   494  					},
   495  
   496  					"setDeep.10.value": &terraform.ResourceAttrDiff{
   497  						Old: "",
   498  						New: "foo",
   499  					},
   500  
   501  					"setDeep.50.index": &terraform.ResourceAttrDiff{
   502  						Old: "",
   503  						New: "50",
   504  					},
   505  
   506  					"setDeep.50.value": &terraform.ResourceAttrDiff{
   507  						Old: "",
   508  						New: "bar",
   509  					},
   510  				},
   511  			},
   512  
   513  			Source: &MapFieldReader{
   514  				Schema: s,
   515  				Map: BasicMapReader(map[string]string{
   516  					"listMap.#":     "2",
   517  					"listMap.0.foo": "bar",
   518  					"listMap.0.bar": "baz",
   519  					"listMap.1.baz": "baz",
   520  				}),
   521  			},
   522  		}
   523  	})
   524  }