k8s.io/apiserver@v0.31.1/pkg/admission/plugin/webhook/mutating/dispatcher_test.go (about)

     1  /*
     2  Copyright 2019 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 mutating
    18  
    19  import (
    20  	"encoding/json"
    21  	"reflect"
    22  	"testing"
    23  
    24  	"github.com/stretchr/testify/assert"
    25  	jsonpatch "gopkg.in/evanphx/json-patch.v4"
    26  )
    27  
    28  func TestMutationAnnotationValue(t *testing.T) {
    29  	tcs := []struct {
    30  		config   string
    31  		webhook  string
    32  		mutated  bool
    33  		expected string
    34  	}{
    35  		{
    36  			config:   "test-config",
    37  			webhook:  "test-webhook",
    38  			mutated:  true,
    39  			expected: `{"configuration":"test-config","webhook":"test-webhook","mutated":true}`,
    40  		},
    41  		{
    42  			config:   "test-config",
    43  			webhook:  "test-webhook",
    44  			mutated:  false,
    45  			expected: `{"configuration":"test-config","webhook":"test-webhook","mutated":false}`,
    46  		},
    47  	}
    48  
    49  	for _, tc := range tcs {
    50  		actual, err := mutationAnnotationValue(tc.config, tc.webhook, tc.mutated)
    51  		assert.NoError(t, err, "unexpected error")
    52  		if actual != tc.expected {
    53  			t.Errorf("composed mutation annotation value doesn't match, want: %s, got: %s", tc.expected, actual)
    54  		}
    55  	}
    56  }
    57  
    58  func TestJSONPatchAnnotationValue(t *testing.T) {
    59  	tcs := []struct {
    60  		name     string
    61  		config   string
    62  		webhook  string
    63  		patch    []byte
    64  		expected string
    65  	}{
    66  		{
    67  			name:     "valid patch annotation",
    68  			config:   "test-config",
    69  			webhook:  "test-webhook",
    70  			patch:    []byte(`[{"op": "add", "path": "/metadata/labels/a", "value": "true"}]`),
    71  			expected: `{"configuration":"test-config","webhook":"test-webhook","patch":[{"op":"add","path":"/metadata/labels/a","value":"true"}],"patchType":"JSONPatch"}`,
    72  		},
    73  		{
    74  			name:     "empty configuration",
    75  			config:   "",
    76  			webhook:  "test-webhook",
    77  			patch:    []byte(`[{"op": "add", "path": "/metadata/labels/a", "value": "true"}]`),
    78  			expected: `{"configuration":"","webhook":"test-webhook","patch":[{"op":"add","path":"/metadata/labels/a","value":"true"}],"patchType":"JSONPatch"}`,
    79  		},
    80  		{
    81  			name:     "empty webhook",
    82  			config:   "test-config",
    83  			webhook:  "",
    84  			patch:    []byte(`[{"op": "add", "path": "/metadata/labels/a", "value": "true"}]`),
    85  			expected: `{"configuration":"test-config","webhook":"","patch":[{"op":"add","path":"/metadata/labels/a","value":"true"}],"patchType":"JSONPatch"}`,
    86  		},
    87  		{
    88  			name:     "valid JSON patch empty operation",
    89  			config:   "test-config",
    90  			webhook:  "test-webhook",
    91  			patch:    []byte("[{}]"),
    92  			expected: `{"configuration":"test-config","webhook":"test-webhook","patch":[{}],"patchType":"JSONPatch"}`,
    93  		},
    94  		{
    95  			name:     "empty slice patch",
    96  			config:   "test-config",
    97  			webhook:  "test-webhook",
    98  			patch:    []byte("[]"),
    99  			expected: `{"configuration":"test-config","webhook":"test-webhook","patch":[],"patchType":"JSONPatch"}`,
   100  		},
   101  	}
   102  
   103  	for _, tc := range tcs {
   104  		t.Run(tc.name, func(t *testing.T) {
   105  			jsonPatch, err := jsonpatch.DecodePatch(tc.patch)
   106  			assert.NoError(t, err, "unexpected error decode patch")
   107  			actual, err := jsonPatchAnnotationValue(tc.config, tc.webhook, jsonPatch)
   108  			assert.NoError(t, err, "unexpected error getting json patch annotation")
   109  			if actual != tc.expected {
   110  				t.Errorf("composed patch annotation value doesn't match, want: %s, got: %s", tc.expected, actual)
   111  			}
   112  
   113  			var p map[string]interface{}
   114  			if err := json.Unmarshal([]byte(actual), &p); err != nil {
   115  				t.Errorf("unexpected error unmarshaling patch annotation: %v", err)
   116  			}
   117  			if p["configuration"] != tc.config {
   118  				t.Errorf("unmarshaled configuration doesn't match, want: %s, got: %v", tc.config, p["configuration"])
   119  			}
   120  			if p["webhook"] != tc.webhook {
   121  				t.Errorf("unmarshaled webhook doesn't match, want: %s, got: %v", tc.webhook, p["webhook"])
   122  			}
   123  			var expectedPatch interface{}
   124  			err = json.Unmarshal(tc.patch, &expectedPatch)
   125  			if err != nil {
   126  				t.Errorf("unexpected error unmarshaling patch: %v, %v", tc.patch, err)
   127  			}
   128  			if !reflect.DeepEqual(expectedPatch, p["patch"]) {
   129  				t.Errorf("unmarshaled patch doesn't match, want: %v, got: %v", expectedPatch, p["patch"])
   130  			}
   131  		})
   132  	}
   133  }