github.com/dhaiducek/policy-generator-plugin@v1.99.99/internal/patches_test.go (about)

     1  // Copyright Contributors to the Open Cluster Management project
     2  package internal
     3  
     4  import (
     5  	"fmt"
     6  	"strings"
     7  	"testing"
     8  
     9  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    10  )
    11  
    12  func createExConfigMap(name string) *map[string]interface{} {
    13  	return &map[string]interface{}{
    14  		"apiVersion": "v1",
    15  		"kind":       "ConfigMap",
    16  		"metadata": map[string]interface{}{
    17  			"name":      name,
    18  			"namespace": "default",
    19  		},
    20  		"data": map[string]string{
    21  			"game.properties": "enemies=goldfish",
    22  			"ui.properties":   "color.good=neon-green",
    23  		},
    24  	}
    25  }
    26  
    27  func TestValidate(t *testing.T) {
    28  	t.Parallel()
    29  
    30  	manifests := []map[string]interface{}{}
    31  	manifests = append(
    32  		manifests, *createExConfigMap("configmap1"), *createExConfigMap("configmap2"),
    33  	)
    34  	patches := []map[string]interface{}{
    35  		{
    36  			"apiVersion": "v1",
    37  			"kind":       "ConfigMap",
    38  			"metadata": map[string]interface{}{
    39  				"name":      "configmap2",
    40  				"namespace": "default",
    41  				"labels": map[string]string{
    42  					"chandler": "bing",
    43  				},
    44  			},
    45  		},
    46  	}
    47  
    48  	patcher := manifestPatcher{manifests: manifests, patches: patches}
    49  	err := patcher.Validate()
    50  
    51  	assertEqual(t, err, nil)
    52  }
    53  
    54  func TestValidateDefaults(t *testing.T) {
    55  	t.Parallel()
    56  
    57  	manifests := []map[string]interface{}{*createExConfigMap("configmap1")}
    58  	patches := []map[string]interface{}{
    59  		{
    60  			"metadata": map[string]interface{}{
    61  				"labels": map[string]string{
    62  					"chandler": "bing",
    63  				},
    64  			},
    65  		},
    66  	}
    67  
    68  	patcher := manifestPatcher{manifests: manifests, patches: patches}
    69  	err := patcher.Validate()
    70  
    71  	assertEqual(t, err, nil)
    72  }
    73  
    74  func TestValidateNoManifests(t *testing.T) {
    75  	t.Parallel()
    76  
    77  	patcher := manifestPatcher{
    78  		manifests: []map[string]interface{}{}, patches: []map[string]interface{}{},
    79  	}
    80  	err := patcher.Validate()
    81  
    82  	assertEqual(t, err.Error(), "there must be one or more manifests")
    83  }
    84  
    85  func TestValidateManifestMissingData(t *testing.T) {
    86  	t.Parallel()
    87  
    88  	tests := []struct{ missingFields []string }{
    89  		{missingFields: []string{"apiVersion"}},
    90  		{missingFields: []string{"kind"}},
    91  		{missingFields: []string{"metadata", "name"}},
    92  	}
    93  
    94  	for _, test := range tests {
    95  		test := test
    96  		name := fmt.Sprintf("manifest missing %s", strings.Join(test.missingFields, "."))
    97  
    98  		t.Run(
    99  			name,
   100  			func(t *testing.T) {
   101  				t.Parallel()
   102  				configmap := *createExConfigMap("configmap1")
   103  				err := unstructured.SetNestedField(configmap, "", test.missingFields...)
   104  				if err != nil {
   105  					t.Fatal(err.Error())
   106  				}
   107  				manifests := []map[string]interface{}{configmap}
   108  
   109  				patcher := manifestPatcher{manifests: manifests, patches: []map[string]interface{}{}}
   110  				err = patcher.Validate()
   111  
   112  				expected := fmt.Sprintf(
   113  					`all manifests must have the "%s" field set to a non-empty string`,
   114  					strings.Join(test.missingFields, "."),
   115  				)
   116  				assertEqual(t, err.Error(), expected)
   117  			},
   118  		)
   119  	}
   120  }
   121  
   122  func TestValidatePatchMissingData(t *testing.T) {
   123  	t.Parallel()
   124  
   125  	tests := []struct{ missingFields []string }{
   126  		{missingFields: []string{"apiVersion"}},
   127  		{missingFields: []string{"kind"}},
   128  		{missingFields: []string{"metadata", "name"}},
   129  	}
   130  
   131  	for _, test := range tests {
   132  		test := test
   133  		name := fmt.Sprintf("patch missing %s", strings.Join(test.missingFields, "."))
   134  
   135  		t.Run(
   136  			name,
   137  			func(t *testing.T) {
   138  				t.Parallel()
   139  
   140  				manifests := []map[string]interface{}{
   141  					*createExConfigMap("configmap1"), *createExConfigMap("configmap2"),
   142  				}
   143  
   144  				patch := map[string]interface{}{
   145  					"apiVersion": "v1",
   146  					"kind":       "ConfigMap",
   147  					"metadata": map[string]interface{}{
   148  						"name":      "configmap2",
   149  						"namespace": "default",
   150  						"labels": map[string]string{
   151  							"chandler": "bing",
   152  						},
   153  					},
   154  				}
   155  				err := unstructured.SetNestedField(patch, "", test.missingFields...)
   156  				if err != nil {
   157  					t.Fatal(err.Error())
   158  				}
   159  				patches := []map[string]interface{}{patch}
   160  
   161  				patcher := manifestPatcher{manifests: manifests, patches: patches}
   162  				err = patcher.Validate()
   163  
   164  				expected := fmt.Sprintf(
   165  					`patches must have the "%s" field set to a non-empty string when there is `+
   166  						"more than one manifest it can apply to",
   167  					strings.Join(test.missingFields, "."),
   168  				)
   169  				assertEqual(t, err.Error(), expected)
   170  			},
   171  		)
   172  	}
   173  }
   174  
   175  func TestValidatePatchInvalidSingleManifest(t *testing.T) {
   176  	t.Parallel()
   177  
   178  	tests := []struct{ invalidFields []string }{
   179  		{invalidFields: []string{"apiVersion"}},
   180  	}
   181  
   182  	for _, test := range tests {
   183  		test := test
   184  		name := fmt.Sprintf("patch invalid %s", strings.Join(test.invalidFields, "."))
   185  
   186  		t.Run(
   187  			name,
   188  			func(t *testing.T) {
   189  				t.Parallel()
   190  
   191  				manifests := []map[string]interface{}{*createExConfigMap("configmap1")}
   192  				patch := map[string]interface{}{
   193  					"apiVersion": "v1",
   194  					"kind":       "ConfigMap",
   195  					"metadata": map[string]interface{}{
   196  						"name":      "configmap2",
   197  						"namespace": "default",
   198  						"labels": map[string]string{
   199  							"chandler": "bing",
   200  						},
   201  					},
   202  				}
   203  				err := unstructured.SetNestedField(patch, true, test.invalidFields...)
   204  				if err != nil {
   205  					t.Fatal(err.Error())
   206  				}
   207  				patches := []map[string]interface{}{patch}
   208  
   209  				patcher := manifestPatcher{manifests: manifests, patches: patches}
   210  				err = patcher.Validate()
   211  
   212  				invalidFieldsStr := strings.Join(test.invalidFields, ".")
   213  				expected := fmt.Sprintf(
   214  					`failed to retrieve the "%s" field from the manifest of name `+
   215  						`"configmap1" and kind "ConfigMap": .%s accessor error: true is of the type `+
   216  						`bool, expected string`,
   217  					invalidFieldsStr,
   218  					invalidFieldsStr,
   219  				)
   220  				assertEqual(t, err.Error(), expected)
   221  			},
   222  		)
   223  	}
   224  }
   225  
   226  func TestApplyPatches(t *testing.T) {
   227  	t.Parallel()
   228  
   229  	manifests := []map[string]interface{}{}
   230  	manifests = append(
   231  		manifests, *createExConfigMap("configmap1"), *createExConfigMap("configmap2"),
   232  	)
   233  	patches := []map[string]interface{}{
   234  		{
   235  			"apiVersion": "v1",
   236  			"kind":       "ConfigMap",
   237  			"metadata": map[string]interface{}{
   238  				"name":      "configmap2",
   239  				"namespace": "default",
   240  				"labels": map[string]string{
   241  					"chandler": "bing",
   242  				},
   243  			},
   244  		},
   245  	}
   246  
   247  	patcher := manifestPatcher{manifests: manifests, patches: patches}
   248  	patchedManifests, err := patcher.ApplyPatches()
   249  
   250  	assertEqual(t, err, nil)
   251  
   252  	patchedManifest1 := patchedManifests[0]
   253  	_, found, _ := unstructured.NestedStringMap(patchedManifest1, "metadata", "labels")
   254  
   255  	assertEqual(t, found, false)
   256  
   257  	patchedManifest2 := patchedManifests[1]
   258  	labels, found, _ := unstructured.NestedStringMap(patchedManifest2, "metadata", "labels")
   259  
   260  	assertEqual(t, found, true)
   261  
   262  	expectedLabels := map[string]string{"chandler": "bing"}
   263  
   264  	assertReflectEqual(t, labels, expectedLabels)
   265  }
   266  
   267  func TestApplyPatchesInvalidPatch(t *testing.T) {
   268  	t.Parallel()
   269  
   270  	manifests := []map[string]interface{}{}
   271  	manifests = append(
   272  		manifests, *createExConfigMap("configmap1"), *createExConfigMap("configmap2"),
   273  	)
   274  	patches := []map[string]interface{}{
   275  		{
   276  			"apiVersion": "v1",
   277  			"kind":       "ToasterOven",
   278  			"metadata": map[string]interface{}{
   279  				"name":      "configmap2",
   280  				"namespace": "default",
   281  				"labels": map[string]string{
   282  					"chandler": "bing",
   283  				},
   284  			},
   285  		},
   286  	}
   287  
   288  	patcher := manifestPatcher{manifests: manifests, patches: patches}
   289  	_, err := patcher.ApplyPatches()
   290  
   291  	expected := "failed to apply the patch(es) to the manifest(s) using Kustomize: no matches " +
   292  		"for Id ToasterOven.v1.[noGrp]/configmap2.default; failed to find unique target for patch " +
   293  		"ToasterOven.v1.[noGrp]/configmap2.default"
   294  	assertEqual(t, err.Error(), expected)
   295  }