github.com/opentofu/opentofu@v1.7.1/internal/tofu/upgrade_resource_state_test.go (about) 1 // Copyright (c) The OpenTofu Authors 2 // SPDX-License-Identifier: MPL-2.0 3 // Copyright (c) 2023 HashiCorp, Inc. 4 // SPDX-License-Identifier: MPL-2.0 5 6 package tofu 7 8 import ( 9 "reflect" 10 "testing" 11 12 "github.com/zclconf/go-cty/cty" 13 ) 14 15 func TestStripRemovedStateAttributes(t *testing.T) { 16 cases := []struct { 17 name string 18 state map[string]interface{} 19 expect map[string]interface{} 20 ty cty.Type 21 modified bool 22 }{ 23 { 24 "removed string", 25 map[string]interface{}{ 26 "a": "ok", 27 "b": "gone", 28 }, 29 map[string]interface{}{ 30 "a": "ok", 31 }, 32 cty.Object(map[string]cty.Type{ 33 "a": cty.String, 34 }), 35 true, 36 }, 37 { 38 "removed null", 39 map[string]interface{}{ 40 "a": "ok", 41 "b": nil, 42 }, 43 map[string]interface{}{ 44 "a": "ok", 45 }, 46 cty.Object(map[string]cty.Type{ 47 "a": cty.String, 48 }), 49 true, 50 }, 51 { 52 "removed nested string", 53 map[string]interface{}{ 54 "a": "ok", 55 "b": map[string]interface{}{ 56 "a": "ok", 57 "b": "removed", 58 }, 59 }, 60 map[string]interface{}{ 61 "a": "ok", 62 "b": map[string]interface{}{ 63 "a": "ok", 64 }, 65 }, 66 cty.Object(map[string]cty.Type{ 67 "a": cty.String, 68 "b": cty.Object(map[string]cty.Type{ 69 "a": cty.String, 70 }), 71 }), 72 true, 73 }, 74 { 75 "removed nested list", 76 map[string]interface{}{ 77 "a": "ok", 78 "b": map[string]interface{}{ 79 "a": "ok", 80 "b": []interface{}{"removed"}, 81 }, 82 }, 83 map[string]interface{}{ 84 "a": "ok", 85 "b": map[string]interface{}{ 86 "a": "ok", 87 }, 88 }, 89 cty.Object(map[string]cty.Type{ 90 "a": cty.String, 91 "b": cty.Object(map[string]cty.Type{ 92 "a": cty.String, 93 }), 94 }), 95 true, 96 }, 97 { 98 "removed keys in set of objs", 99 map[string]interface{}{ 100 "a": "ok", 101 "b": map[string]interface{}{ 102 "a": "ok", 103 "set": []interface{}{ 104 map[string]interface{}{ 105 "x": "ok", 106 "y": "removed", 107 }, 108 map[string]interface{}{ 109 "x": "ok", 110 "y": "removed", 111 }, 112 }, 113 }, 114 }, 115 map[string]interface{}{ 116 "a": "ok", 117 "b": map[string]interface{}{ 118 "a": "ok", 119 "set": []interface{}{ 120 map[string]interface{}{ 121 "x": "ok", 122 }, 123 map[string]interface{}{ 124 "x": "ok", 125 }, 126 }, 127 }, 128 }, 129 cty.Object(map[string]cty.Type{ 130 "a": cty.String, 131 "b": cty.Object(map[string]cty.Type{ 132 "a": cty.String, 133 "set": cty.Set(cty.Object(map[string]cty.Type{ 134 "x": cty.String, 135 })), 136 }), 137 }), 138 true, 139 }, 140 } 141 142 for _, tc := range cases { 143 t.Run(tc.name, func(t *testing.T) { 144 modified := removeRemovedAttrs(tc.state, tc.ty) 145 if !reflect.DeepEqual(tc.state, tc.expect) { 146 t.Fatalf("expected: %#v\n got: %#v\n", tc.expect, tc.state) 147 } 148 if modified != tc.modified { 149 t.Fatal("incorrect return value") 150 } 151 }) 152 } 153 }