github.com/banzaicloud/operator-tools@v0.28.10/pkg/resources/overlay_test.go (about)

     1  // Copyright © 2020 Banzai Cloud
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package resources
    16  
    17  import (
    18  	"testing"
    19  
    20  	"github.com/go-test/deep"
    21  	"github.com/stretchr/testify/assert"
    22  	v1 "k8s.io/api/core/v1"
    23  	v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
    24  	"k8s.io/apimachinery/pkg/runtime"
    25  	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
    26  
    27  	"github.com/banzaicloud/operator-tools/pkg/types"
    28  	"github.com/banzaicloud/operator-tools/pkg/utils"
    29  )
    30  
    31  func TestPatchYAMLModifier(t *testing.T) {
    32  	objectName := "test-object"
    33  	testNamespace := "test-ns"
    34  
    35  	baseObject := &v1.Service{
    36  		TypeMeta: v12.TypeMeta{
    37  			Kind:       "Service",
    38  			APIVersion: "v1",
    39  		},
    40  		ObjectMeta: v12.ObjectMeta{
    41  			Name:      objectName,
    42  			Namespace: testNamespace,
    43  		},
    44  		Spec: v1.ServiceSpec{
    45  			LoadBalancerIP: "1.2.3.4",
    46  			Ports: []v1.ServicePort{
    47  				{
    48  					Port: 123,
    49  					Name: "port1",
    50  				},
    51  				{
    52  					Port: 456,
    53  					Name: "port-to-delete",
    54  				},
    55  			},
    56  		},
    57  	}
    58  
    59  	baseWantObject := &v1.Service{
    60  		TypeMeta: v12.TypeMeta{
    61  			Kind:       "Service",
    62  			APIVersion: "v1",
    63  		},
    64  		ObjectMeta: v12.ObjectMeta{
    65  			Name:      objectName,
    66  			Namespace: testNamespace,
    67  		},
    68  		Spec: v1.ServiceSpec{
    69  			LoadBalancerIP: "5.6.7.8",
    70  			Ports: []v1.ServicePort{
    71  				{
    72  					Port: 123,
    73  					Name: "port2",
    74  				},
    75  			},
    76  		},
    77  	}
    78  
    79  	parser := NewObjectParser(clientgoscheme.Scheme)
    80  	tests := map[string]struct {
    81  		overlay           K8SResourceOverlay
    82  		object            runtime.Object
    83  		want              runtime.Object
    84  		assertErr         func(error)
    85  		assertModifierErr func(error)
    86  	}{
    87  		"matching patching": {
    88  			overlay: K8SResourceOverlay{
    89  				ObjectKey: types.ObjectKey{
    90  					Name:      objectName,
    91  					Namespace: testNamespace,
    92  				},
    93  				Patches: []K8SResourceOverlayPatch{
    94  					{
    95  						Type:  ReplaceOverlayPatchType,
    96  						Path:  utils.StringPointer("/spec/loadBalancerIP"),
    97  						Value: utils.StringPointer("5.6.7.8"),
    98  					},
    99  					{
   100  						Type:  ReplaceOverlayPatchType,
   101  						Path:  utils.StringPointer("/spec/ports/0/name"),
   102  						Value: utils.StringPointer("port2"),
   103  					},
   104  					{
   105  						Type: DeleteOverlayPatchType,
   106  						Path: utils.StringPointer("/spec/ports/1"),
   107  					},
   108  				},
   109  			},
   110  			object: baseObject,
   111  			want:   baseWantObject,
   112  		},
   113  		"matching wo objectkey patching": {
   114  			overlay: K8SResourceOverlay{
   115  				Patches: []K8SResourceOverlayPatch{
   116  					{
   117  						Type:  ReplaceOverlayPatchType,
   118  						Path:  utils.StringPointer("/spec/loadBalancerIP"),
   119  						Value: utils.StringPointer("5.6.7.8"),
   120  					},
   121  					{
   122  						Type:  ReplaceOverlayPatchType,
   123  						Path:  utils.StringPointer("/spec/ports/0/name"),
   124  						Value: utils.StringPointer("port2"),
   125  					},
   126  					{
   127  						Type: DeleteOverlayPatchType,
   128  						Path: utils.StringPointer("/spec/ports/1"),
   129  					},
   130  				},
   131  			},
   132  			object: baseObject,
   133  			want:   baseWantObject,
   134  		},
   135  		"matching wo objectkey namespace patching": {
   136  			overlay: K8SResourceOverlay{
   137  				ObjectKey: types.ObjectKey{
   138  					Name: objectName,
   139  				},
   140  				Patches: []K8SResourceOverlayPatch{
   141  					{
   142  						Type:  ReplaceOverlayPatchType,
   143  						Path:  utils.StringPointer("/spec/loadBalancerIP"),
   144  						Value: utils.StringPointer("5.6.7.8"),
   145  					},
   146  					{
   147  						Type:  ReplaceOverlayPatchType,
   148  						Path:  utils.StringPointer("/spec/ports/0/name"),
   149  						Value: utils.StringPointer("port2"),
   150  					},
   151  					{
   152  						Type: DeleteOverlayPatchType,
   153  						Path: utils.StringPointer("/spec/ports/1"),
   154  					},
   155  				},
   156  			},
   157  			object: baseObject,
   158  			want:   baseWantObject,
   159  		},
   160  		"matching wo objectkey name patching": {
   161  			overlay: K8SResourceOverlay{
   162  				ObjectKey: types.ObjectKey{
   163  					Namespace: testNamespace,
   164  				},
   165  				Patches: []K8SResourceOverlayPatch{
   166  					{
   167  						Type:  ReplaceOverlayPatchType,
   168  						Path:  utils.StringPointer("/spec/loadBalancerIP"),
   169  						Value: utils.StringPointer("5.6.7.8"),
   170  					},
   171  					{
   172  						Type:  ReplaceOverlayPatchType,
   173  						Path:  utils.StringPointer("/spec/ports/0/name"),
   174  						Value: utils.StringPointer("port2"),
   175  					},
   176  					{
   177  						Type: DeleteOverlayPatchType,
   178  						Path: utils.StringPointer("/spec/ports/1"),
   179  					},
   180  				},
   181  			},
   182  			object: baseObject,
   183  			want:   baseWantObject,
   184  		},
   185  	}
   186  	for name, tt := range tests {
   187  		t.Run(name, func(t *testing.T) {
   188  			got, err := PatchYAMLModifier(tt.overlay, parser)
   189  			if tt.assertErr != nil {
   190  				tt.assertErr(err)
   191  			} else {
   192  				assert.NoError(t, err)
   193  			}
   194  			patched, err := got(tt.object)
   195  			if tt.assertModifierErr != nil {
   196  				tt.assertModifierErr(err)
   197  			} else {
   198  				assert.NoError(t, err)
   199  			}
   200  			if diff := deep.Equal(patched, tt.want); diff != nil {
   201  				t.Error(diff)
   202  			}
   203  		})
   204  	}
   205  }