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  }