sigs.k8s.io/cluster-api@v1.7.1/internal/controllers/topology/cluster/structuredmerge/drop_diff_test.go (about) 1 /* 2 Copyright 2022 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package structuredmerge 18 19 import ( 20 "testing" 21 22 . "github.com/onsi/gomega" 23 24 "sigs.k8s.io/cluster-api/internal/contract" 25 "sigs.k8s.io/cluster-api/internal/util/ssa" 26 ) 27 28 func Test_dropDiffForNotAllowedPaths(t *testing.T) { 29 tests := []struct { 30 name string 31 ctx *dropDiffInput 32 wantModified map[string]interface{} 33 }{ 34 { 35 name: "Sets not allowed paths to original value if defined", 36 ctx: &dropDiffInput{ 37 path: contract.Path{}, 38 original: map[string]interface{}{ 39 "metadata": map[string]interface{}{ 40 "name": "foo", 41 }, 42 "status": map[string]interface{}{ 43 "foo": "123", 44 }, 45 }, 46 modified: map[string]interface{}{ 47 "metadata": map[string]interface{}{ 48 "name": "foo-changed", 49 "labels": map[string]interface{}{ 50 "foo": "123", 51 }, 52 "annotations": map[string]interface{}{ 53 "foo": "123", 54 }, 55 }, 56 "spec": map[string]interface{}{ 57 "foo": "123", 58 }, 59 "status": map[string]interface{}{ 60 "foo": "123-changed", 61 }, 62 }, 63 shouldDropDiffFunc: ssa.IsPathNotAllowed( 64 []contract.Path{ // NOTE: we are dropping everything not in this list (IsPathNotAllowed) 65 {"metadata", "labels"}, 66 {"metadata", "annotations"}, 67 {"spec"}, 68 }, 69 ), 70 }, 71 wantModified: map[string]interface{}{ 72 "metadata": map[string]interface{}{ 73 "name": "foo", // metadata.name aligned to original 74 "labels": map[string]interface{}{ 75 "foo": "123", 76 }, 77 "annotations": map[string]interface{}{ 78 "foo": "123", 79 }, 80 }, 81 "spec": map[string]interface{}{ 82 "foo": "123", 83 }, 84 "status": map[string]interface{}{ // status aligned to original 85 "foo": "123", 86 }, 87 }, 88 }, 89 { 90 name: "Drops not allowed paths if they do not exist in original", 91 ctx: &dropDiffInput{ 92 path: contract.Path{}, 93 original: map[string]interface{}{ 94 // Original doesn't have values for not allowed paths. 95 }, 96 modified: map[string]interface{}{ 97 "metadata": map[string]interface{}{ 98 "name": "foo", 99 "labels": map[string]interface{}{ 100 "foo": "123", 101 }, 102 "annotations": map[string]interface{}{ 103 "foo": "123", 104 }, 105 }, 106 "spec": map[string]interface{}{ 107 "foo": "123", 108 }, 109 "status": map[string]interface{}{ 110 "foo": "123", 111 }, 112 }, 113 shouldDropDiffFunc: ssa.IsPathNotAllowed( 114 []contract.Path{ // NOTE: we are dropping everything not in this list (IsPathNotAllowed) 115 {"metadata", "labels"}, 116 {"metadata", "annotations"}, 117 {"spec"}, 118 }, 119 ), 120 }, 121 wantModified: map[string]interface{}{ 122 "metadata": map[string]interface{}{ 123 // metadata.name dropped 124 "labels": map[string]interface{}{ 125 "foo": "123", 126 }, 127 "annotations": map[string]interface{}{ 128 "foo": "123", 129 }, 130 }, 131 "spec": map[string]interface{}{ 132 "foo": "123", 133 }, 134 // status dropped 135 }, 136 }, 137 { 138 name: "Cleanup empty maps", 139 ctx: &dropDiffInput{ 140 path: contract.Path{}, 141 original: map[string]interface{}{ 142 // Original doesn't have values for not allowed paths. 143 }, 144 modified: map[string]interface{}{ 145 "spec": map[string]interface{}{ 146 "foo": "123", 147 }, 148 }, 149 shouldDropDiffFunc: ssa.IsPathNotAllowed( 150 []contract.Path{}, // NOTE: we are dropping everything not in this list (IsPathNotAllowed) 151 ), 152 }, 153 wantModified: map[string]interface{}{ 154 // we are dropping spec.foo and then spec given that it is an empty map 155 }, 156 }, 157 } 158 for _, tt := range tests { 159 t.Run(tt.name, func(t *testing.T) { 160 g := NewWithT(t) 161 162 dropDiff(tt.ctx) 163 164 g.Expect(tt.ctx.modified).To(BeComparableTo(tt.wantModified)) 165 }) 166 } 167 } 168 169 func Test_dropDiffForIgnoredPaths(t *testing.T) { 170 tests := []struct { 171 name string 172 ctx *dropDiffInput 173 wantModified map[string]interface{} 174 }{ 175 { 176 name: "Sets ignored paths to original value if defined", 177 ctx: &dropDiffInput{ 178 path: contract.Path{}, 179 original: map[string]interface{}{ 180 "spec": map[string]interface{}{ 181 "foo": "bar", 182 "controlPlaneEndpoint": map[string]interface{}{ 183 "host": "foo", 184 "port": "123", 185 }, 186 }, 187 }, 188 modified: map[string]interface{}{ 189 "spec": map[string]interface{}{ 190 "foo": "bar", 191 "controlPlaneEndpoint": map[string]interface{}{ 192 "host": "foo-changed", 193 "port": "123-changed", 194 }, 195 }, 196 }, 197 shouldDropDiffFunc: ssa.IsPathIgnored( 198 []contract.Path{ 199 {"spec", "controlPlaneEndpoint"}, 200 }, 201 ), 202 }, 203 wantModified: map[string]interface{}{ 204 "spec": map[string]interface{}{ 205 "foo": "bar", 206 "controlPlaneEndpoint": map[string]interface{}{ // spec.controlPlaneEndpoint aligned to original 207 "host": "foo", 208 "port": "123", 209 }, 210 }, 211 }, 212 }, 213 { 214 name: "Drops ignore paths if they do not exist in original", 215 ctx: &dropDiffInput{ 216 path: contract.Path{}, 217 original: map[string]interface{}{ 218 // Original doesn't have values for ignore paths. 219 }, 220 modified: map[string]interface{}{ 221 "spec": map[string]interface{}{ 222 "foo": "bar", 223 "controlPlaneEndpoint": map[string]interface{}{ 224 "host": "foo-changed", 225 "port": "123-changed", 226 }, 227 }, 228 }, 229 shouldDropDiffFunc: ssa.IsPathIgnored( 230 []contract.Path{ 231 {"spec", "controlPlaneEndpoint"}, 232 }, 233 ), 234 }, 235 wantModified: map[string]interface{}{ 236 "spec": map[string]interface{}{ 237 "foo": "bar", 238 // spec.controlPlaneEndpoint dropped 239 }, 240 }, 241 }, 242 { 243 name: "Cleanup empty maps", 244 ctx: &dropDiffInput{ 245 path: contract.Path{}, 246 original: map[string]interface{}{ 247 // Original doesn't have values for not allowed paths. 248 }, 249 modified: map[string]interface{}{ 250 "spec": map[string]interface{}{ 251 "foo": "123", 252 }, 253 }, 254 shouldDropDiffFunc: ssa.IsPathIgnored( 255 []contract.Path{ 256 {"spec", "foo"}, 257 }, 258 ), 259 }, 260 wantModified: map[string]interface{}{ 261 // we are dropping spec.foo and then spec given that it is an empty map 262 }, 263 }, 264 } 265 for _, tt := range tests { 266 t.Run(tt.name, func(t *testing.T) { 267 g := NewWithT(t) 268 269 dropDiff(tt.ctx) 270 271 g.Expect(tt.ctx.modified).To(BeComparableTo(tt.wantModified)) 272 }) 273 } 274 }