kubeform.dev/terraform-backend-sdk@v0.0.0-20220310143633-45f07fe731c5/terraform/reduce_plan_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/hashicorp/hcl/v2"
     7  	"github.com/hashicorp/hcl/v2/hclsyntax"
     8  	"github.com/zclconf/go-cty/cty"
     9  )
    10  
    11  func TestProcessIgnoreChangesIndividual(t *testing.T) {
    12  	tests := map[string]struct {
    13  		Old, New cty.Value
    14  		Ignore   []string
    15  		Want     cty.Value
    16  	}{
    17  		"string": {
    18  			cty.ObjectVal(map[string]cty.Value{
    19  				"a": cty.StringVal("a value"),
    20  				"b": cty.StringVal("b value"),
    21  			}),
    22  			cty.ObjectVal(map[string]cty.Value{
    23  				"a": cty.StringVal("new a value"),
    24  				"b": cty.StringVal("new b value"),
    25  			}),
    26  			[]string{"a"},
    27  			cty.ObjectVal(map[string]cty.Value{
    28  				"a": cty.StringVal("a value"),
    29  				"b": cty.StringVal("new b value"),
    30  			}),
    31  		},
    32  		"changed type": {
    33  			cty.ObjectVal(map[string]cty.Value{
    34  				"a": cty.StringVal("a value"),
    35  				"b": cty.StringVal("b value"),
    36  			}),
    37  			cty.ObjectVal(map[string]cty.Value{
    38  				"a": cty.NumberIntVal(1),
    39  				"b": cty.StringVal("new b value"),
    40  			}),
    41  			[]string{"a"},
    42  			cty.ObjectVal(map[string]cty.Value{
    43  				"a": cty.StringVal("a value"),
    44  				"b": cty.StringVal("new b value"),
    45  			}),
    46  		},
    47  		"list": {
    48  			cty.ObjectVal(map[string]cty.Value{
    49  				"a": cty.ListVal([]cty.Value{
    50  					cty.StringVal("a0 value"),
    51  					cty.StringVal("a1 value"),
    52  				}),
    53  				"b": cty.StringVal("b value"),
    54  			}),
    55  			cty.ObjectVal(map[string]cty.Value{
    56  				"a": cty.ListVal([]cty.Value{
    57  					cty.StringVal("new a0 value"),
    58  					cty.StringVal("new a1 value"),
    59  				}),
    60  				"b": cty.StringVal("new b value"),
    61  			}),
    62  			[]string{"a"},
    63  			cty.ObjectVal(map[string]cty.Value{
    64  				"a": cty.ListVal([]cty.Value{
    65  					cty.StringVal("a0 value"),
    66  					cty.StringVal("a1 value"),
    67  				}),
    68  				"b": cty.StringVal("new b value"),
    69  			}),
    70  		},
    71  		"list_index": {
    72  			cty.ObjectVal(map[string]cty.Value{
    73  				"a": cty.ListVal([]cty.Value{
    74  					cty.StringVal("a0 value"),
    75  					cty.StringVal("a1 value"),
    76  				}),
    77  				"b": cty.StringVal("b value"),
    78  			}),
    79  			cty.ObjectVal(map[string]cty.Value{
    80  				"a": cty.ListVal([]cty.Value{
    81  					cty.StringVal("new a0 value"),
    82  					cty.StringVal("new a1 value"),
    83  				}),
    84  				"b": cty.StringVal("new b value"),
    85  			}),
    86  			[]string{"a[1]"},
    87  			cty.ObjectVal(map[string]cty.Value{
    88  				"a": cty.ListVal([]cty.Value{
    89  					cty.StringVal("new a0 value"),
    90  					cty.StringVal("a1 value"),
    91  				}),
    92  				"b": cty.StringVal("new b value"),
    93  			}),
    94  		},
    95  		"map": {
    96  			cty.ObjectVal(map[string]cty.Value{
    97  				"a": cty.MapVal(map[string]cty.Value{
    98  					"a0": cty.StringVal("a0 value"),
    99  					"a1": cty.StringVal("a1 value"),
   100  				}),
   101  				"b": cty.StringVal("b value"),
   102  			}),
   103  			cty.ObjectVal(map[string]cty.Value{
   104  				"a": cty.MapVal(map[string]cty.Value{
   105  					"a0": cty.StringVal("new a0 value"),
   106  					"a1": cty.UnknownVal(cty.String),
   107  				}),
   108  				"b": cty.StringVal("b value"),
   109  			}),
   110  			[]string{`a`},
   111  			cty.ObjectVal(map[string]cty.Value{
   112  				"a": cty.MapVal(map[string]cty.Value{
   113  					"a0": cty.StringVal("a0 value"),
   114  					"a1": cty.StringVal("a1 value"),
   115  				}),
   116  				"b": cty.StringVal("b value"),
   117  			}),
   118  		},
   119  		"map_index": {
   120  			cty.ObjectVal(map[string]cty.Value{
   121  				"a": cty.MapVal(map[string]cty.Value{
   122  					"a0": cty.StringVal("a0 value"),
   123  					"a1": cty.StringVal("a1 value"),
   124  				}),
   125  				"b": cty.StringVal("b value"),
   126  			}),
   127  			cty.ObjectVal(map[string]cty.Value{
   128  				"a": cty.MapVal(map[string]cty.Value{
   129  					"a0": cty.StringVal("new a0 value"),
   130  					"a1": cty.StringVal("new a1 value"),
   131  				}),
   132  				"b": cty.StringVal("b value"),
   133  			}),
   134  			[]string{`a["a1"]`},
   135  			cty.ObjectVal(map[string]cty.Value{
   136  				"a": cty.MapVal(map[string]cty.Value{
   137  					"a0": cty.StringVal("new a0 value"),
   138  					"a1": cty.StringVal("a1 value"),
   139  				}),
   140  				"b": cty.StringVal("b value"),
   141  			}),
   142  		},
   143  		"map_index_no_config": {
   144  			cty.ObjectVal(map[string]cty.Value{
   145  				"a": cty.MapVal(map[string]cty.Value{
   146  					"a0": cty.StringVal("a0 value"),
   147  					"a1": cty.StringVal("a1 value"),
   148  				}),
   149  				"b": cty.StringVal("b value"),
   150  			}),
   151  			cty.ObjectVal(map[string]cty.Value{
   152  				"a": cty.NullVal(cty.Map(cty.String)),
   153  				"b": cty.StringVal("b value"),
   154  			}),
   155  			[]string{`a["a1"]`},
   156  			cty.ObjectVal(map[string]cty.Value{
   157  				"a": cty.MapVal(map[string]cty.Value{
   158  					"a1": cty.StringVal("a1 value"),
   159  				}),
   160  				"b": cty.StringVal("b value"),
   161  			}),
   162  		},
   163  		"map_index_unknown_value": {
   164  			cty.ObjectVal(map[string]cty.Value{
   165  				"a": cty.MapVal(map[string]cty.Value{
   166  					"a0": cty.StringVal("a0 value"),
   167  					"a1": cty.StringVal("a1 value"),
   168  				}),
   169  				"b": cty.StringVal("b value"),
   170  			}),
   171  			cty.ObjectVal(map[string]cty.Value{
   172  				"a": cty.MapVal(map[string]cty.Value{
   173  					"a0": cty.StringVal("a0 value"),
   174  					"a1": cty.UnknownVal(cty.String),
   175  				}),
   176  				"b": cty.StringVal("b value"),
   177  			}),
   178  			[]string{`a["a1"]`},
   179  			cty.ObjectVal(map[string]cty.Value{
   180  				"a": cty.MapVal(map[string]cty.Value{
   181  					"a0": cty.StringVal("a0 value"),
   182  					"a1": cty.StringVal("a1 value"),
   183  				}),
   184  				"b": cty.StringVal("b value"),
   185  			}),
   186  		},
   187  		"map_index_multiple_keys": {
   188  			cty.ObjectVal(map[string]cty.Value{
   189  				"a": cty.MapVal(map[string]cty.Value{
   190  					"a0": cty.StringVal("a0 value"),
   191  					"a1": cty.StringVal("a1 value"),
   192  					"a2": cty.StringVal("a2 value"),
   193  					"a3": cty.StringVal("a3 value"),
   194  				}),
   195  				"b": cty.StringVal("b value"),
   196  			}),
   197  			cty.ObjectVal(map[string]cty.Value{
   198  				"a": cty.NullVal(cty.Map(cty.String)),
   199  				"b": cty.StringVal("new b value"),
   200  			}),
   201  			[]string{`a["a1"]`, `a["a2"]`, `a["a3"]`, `b`},
   202  			cty.ObjectVal(map[string]cty.Value{
   203  				"a": cty.MapVal(map[string]cty.Value{
   204  					"a1": cty.StringVal("a1 value"),
   205  					"a2": cty.StringVal("a2 value"),
   206  					"a3": cty.StringVal("a3 value"),
   207  				}),
   208  				"b": cty.StringVal("b value"),
   209  			}),
   210  		},
   211  		"map_index_redundant": {
   212  			cty.ObjectVal(map[string]cty.Value{
   213  				"a": cty.MapVal(map[string]cty.Value{
   214  					"a0": cty.StringVal("a0 value"),
   215  					"a1": cty.StringVal("a1 value"),
   216  					"a2": cty.StringVal("a2 value"),
   217  				}),
   218  				"b": cty.StringVal("b value"),
   219  			}),
   220  			cty.ObjectVal(map[string]cty.Value{
   221  				"a": cty.NullVal(cty.Map(cty.String)),
   222  				"b": cty.StringVal("new b value"),
   223  			}),
   224  			[]string{`a["a1"]`, `a`, `b`},
   225  			cty.ObjectVal(map[string]cty.Value{
   226  				"a": cty.MapVal(map[string]cty.Value{
   227  					"a0": cty.StringVal("a0 value"),
   228  					"a1": cty.StringVal("a1 value"),
   229  					"a2": cty.StringVal("a2 value"),
   230  				}),
   231  				"b": cty.StringVal("b value"),
   232  			}),
   233  		},
   234  		"missing_map_index": {
   235  			cty.ObjectVal(map[string]cty.Value{
   236  				"a": cty.MapVal(map[string]cty.Value{
   237  					"a0": cty.StringVal("a0 value"),
   238  					"a1": cty.StringVal("a1 value"),
   239  				}),
   240  				"b": cty.StringVal("b value"),
   241  			}),
   242  			cty.ObjectVal(map[string]cty.Value{
   243  				"a": cty.MapValEmpty(cty.String),
   244  				"b": cty.StringVal("b value"),
   245  			}),
   246  			[]string{`a["a1"]`},
   247  			cty.ObjectVal(map[string]cty.Value{
   248  				"a": cty.MapVal(map[string]cty.Value{
   249  					"a1": cty.StringVal("a1 value"),
   250  				}),
   251  				"b": cty.StringVal("b value"),
   252  			}),
   253  		},
   254  		"missing_map_index_empty": {
   255  			cty.ObjectVal(map[string]cty.Value{
   256  				"a": cty.MapValEmpty(cty.String),
   257  			}),
   258  			cty.ObjectVal(map[string]cty.Value{
   259  				"a": cty.MapVal(map[string]cty.Value{
   260  					"a": cty.StringVal("a0 value"),
   261  				}),
   262  			}),
   263  			[]string{`a["a"]`},
   264  			cty.ObjectVal(map[string]cty.Value{
   265  				"a": cty.MapValEmpty(cty.String),
   266  			}),
   267  		},
   268  		"missing_map_index_to_object": {
   269  			cty.ObjectVal(map[string]cty.Value{
   270  				"a": cty.MapVal(map[string]cty.Value{
   271  					"a": cty.ObjectVal(map[string]cty.Value{
   272  						"a": cty.StringVal("aa0"),
   273  						"b": cty.StringVal("ab0"),
   274  					}),
   275  					"b": cty.ObjectVal(map[string]cty.Value{
   276  						"a": cty.StringVal("ba0"),
   277  						"b": cty.StringVal("bb0"),
   278  					}),
   279  				}),
   280  			}),
   281  			cty.ObjectVal(map[string]cty.Value{
   282  				"a": cty.MapValEmpty(
   283  					cty.Object(map[string]cty.Type{
   284  						"a": cty.String,
   285  						"b": cty.String,
   286  					}),
   287  				),
   288  			}),
   289  			// we expect the config to be used here, as the ignore changes was
   290  			// `a["a"].b`, but the change was larger than that removing
   291  			// `a["a"]` entirely.
   292  			[]string{`a["a"].b`},
   293  			cty.ObjectVal(map[string]cty.Value{
   294  				"a": cty.MapValEmpty(
   295  					cty.Object(map[string]cty.Type{
   296  						"a": cty.String,
   297  						"b": cty.String,
   298  					}),
   299  				),
   300  			}),
   301  		},
   302  		"missing_prior_map_index": {
   303  			cty.ObjectVal(map[string]cty.Value{
   304  				"a": cty.MapVal(map[string]cty.Value{
   305  					"a0": cty.StringVal("a0 value"),
   306  				}),
   307  				"b": cty.StringVal("b value"),
   308  			}),
   309  			cty.ObjectVal(map[string]cty.Value{
   310  				"a": cty.MapVal(map[string]cty.Value{
   311  					"a0": cty.StringVal("a0 value"),
   312  					"a1": cty.StringVal("new a1 value"),
   313  				}),
   314  				"b": cty.StringVal("b value"),
   315  			}),
   316  			[]string{`a["a1"]`},
   317  			cty.ObjectVal(map[string]cty.Value{
   318  				"a": cty.MapVal(map[string]cty.Value{
   319  					"a0": cty.StringVal("a0 value"),
   320  				}),
   321  				"b": cty.StringVal("b value"),
   322  			}),
   323  		},
   324  		"object attribute": {
   325  			cty.ObjectVal(map[string]cty.Value{
   326  				"a": cty.ObjectVal(map[string]cty.Value{
   327  					"foo": cty.StringVal("a.foo value"),
   328  					"bar": cty.StringVal("a.bar value"),
   329  				}),
   330  				"b": cty.StringVal("b value"),
   331  			}),
   332  			cty.ObjectVal(map[string]cty.Value{
   333  				"a": cty.ObjectVal(map[string]cty.Value{
   334  					"foo": cty.StringVal("new a.foo value"),
   335  					"bar": cty.StringVal("new a.bar value"),
   336  				}),
   337  				"b": cty.StringVal("new b value"),
   338  			}),
   339  			[]string{"a.bar"},
   340  			cty.ObjectVal(map[string]cty.Value{
   341  				"a": cty.ObjectVal(map[string]cty.Value{
   342  					"foo": cty.StringVal("new a.foo value"),
   343  					"bar": cty.StringVal("a.bar value"),
   344  				}),
   345  				"b": cty.StringVal("new b value"),
   346  			}),
   347  		},
   348  		"unknown_object_attribute": {
   349  			cty.ObjectVal(map[string]cty.Value{
   350  				"a": cty.ObjectVal(map[string]cty.Value{
   351  					"foo": cty.StringVal("a.foo value"),
   352  					"bar": cty.StringVal("a.bar value"),
   353  				}),
   354  				"b": cty.StringVal("b value"),
   355  			}),
   356  			cty.ObjectVal(map[string]cty.Value{
   357  				"a": cty.ObjectVal(map[string]cty.Value{
   358  					"foo": cty.StringVal("new a.foo value"),
   359  					"bar": cty.UnknownVal(cty.String),
   360  				}),
   361  				"b": cty.StringVal("new b value"),
   362  			}),
   363  			[]string{"a.bar"},
   364  			cty.ObjectVal(map[string]cty.Value{
   365  				"a": cty.ObjectVal(map[string]cty.Value{
   366  					"foo": cty.StringVal("new a.foo value"),
   367  					"bar": cty.StringVal("a.bar value"),
   368  				}),
   369  				"b": cty.StringVal("new b value"),
   370  			}),
   371  		},
   372  	}
   373  
   374  	for name, test := range tests {
   375  		t.Run(name, func(t *testing.T) {
   376  			ignore := make([]hcl.Traversal, len(test.Ignore))
   377  			for i, ignoreStr := range test.Ignore {
   378  				trav, diags := hclsyntax.ParseTraversalAbs([]byte(ignoreStr), "", hcl.Pos{Line: 1, Column: 1})
   379  				if diags.HasErrors() {
   380  					t.Fatalf("failed to parse %q: %s", ignoreStr, diags.Error())
   381  				}
   382  				ignore[i] = trav
   383  			}
   384  
   385  			ret, diags := processIgnoreChangesIndividual(test.Old, test.New, traversalsToPaths(ignore))
   386  			if diags.HasErrors() {
   387  				t.Fatal(diags.Err())
   388  			}
   389  
   390  			if got, want := ret, test.Want; !want.RawEquals(got) {
   391  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, want)
   392  			}
   393  		})
   394  	}
   395  }