k8s.io/kubernetes@v1.29.3/pkg/controlplane/controller/legacytokentracking/controller_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 legacytokentracking 18 19 import ( 20 "testing" 21 "time" 22 23 "github.com/google/go-cmp/cmp" 24 "golang.org/x/time/rate" 25 26 corev1 "k8s.io/api/core/v1" 27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 "k8s.io/apimachinery/pkg/runtime" 29 "k8s.io/apimachinery/pkg/runtime/schema" 30 "k8s.io/client-go/kubernetes/fake" 31 core "k8s.io/client-go/testing" 32 testingclock "k8s.io/utils/clock/testing" 33 ) 34 35 const throttlePeriod = 30 * time.Second 36 37 func TestSyncConfigMap(t *testing.T) { 38 now := time.Now().UTC() 39 tests := []struct { 40 name string 41 nextCreateAt []time.Time 42 clientObjects []runtime.Object 43 existingConfigMap *corev1.ConfigMap 44 45 expectedErr error 46 expectedActions []core.Action 47 }{ 48 { 49 name: "create configmap [no cache, no live object]", 50 clientObjects: []runtime.Object{}, 51 expectedActions: []core.Action{ 52 core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "configmaps"}, metav1.NamespaceSystem, &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: ConfigMapName}, Data: map[string]string{ConfigMapDataKey: now.Format(dateFormat)}}), 53 }, 54 }, 55 { 56 name: "create configmap should ignore AlreadyExists error [no cache, live object exists]", 57 clientObjects: []runtime.Object{ 58 &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: ConfigMapName}, Data: map[string]string{ConfigMapDataKey: now.Format(dateFormat)}}, 59 }, 60 expectedActions: []core.Action{ 61 core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "configmaps"}, metav1.NamespaceSystem, &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: ConfigMapName}, Data: map[string]string{ConfigMapDataKey: now.Format(dateFormat)}}), 62 }, 63 }, 64 { 65 name: "create configmap throttled [no cache, no live object]", 66 nextCreateAt: []time.Time{now.Add(throttlePeriod - 2*time.Second), now.Add(throttlePeriod - time.Second)}, 67 clientObjects: []runtime.Object{}, 68 expectedActions: []core.Action{ 69 core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "configmaps"}, metav1.NamespaceSystem, &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: ConfigMapName}, Data: map[string]string{ConfigMapDataKey: now.Format(dateFormat)}}), 70 }, 71 }, 72 { 73 name: "create configmap after throttle period [no cache, no live object]", 74 nextCreateAt: []time.Time{now.Add(throttlePeriod - 2*time.Second), now.Add(throttlePeriod - time.Second), now.Add(throttlePeriod + time.Second)}, 75 clientObjects: []runtime.Object{}, 76 expectedActions: []core.Action{ 77 core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "configmaps"}, metav1.NamespaceSystem, &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: ConfigMapName}, Data: map[string]string{ConfigMapDataKey: now.Format(dateFormat)}}), 78 core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "configmaps"}, metav1.NamespaceSystem, &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: ConfigMapName}, Data: map[string]string{ConfigMapDataKey: now.Add(throttlePeriod + time.Second).Format(dateFormat)}}), 79 }, 80 }, 81 { 82 name: "skip update configmap [cache with expected date format exists, live object exists]", 83 clientObjects: []runtime.Object{ 84 &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: ConfigMapName}, Data: map[string]string{ConfigMapDataKey: now.Format(dateFormat)}}, 85 }, 86 existingConfigMap: &corev1.ConfigMap{ 87 ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: ConfigMapName}, 88 Data: map[string]string{ConfigMapDataKey: now.Format(dateFormat)}, 89 }, 90 expectedActions: []core.Action{}, 91 }, 92 { 93 name: "update configmap [cache with unexpected date format, live object exists]", 94 clientObjects: []runtime.Object{ 95 &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: ConfigMapName}, Data: map[string]string{ConfigMapDataKey: now.Format(time.RFC3339)}}, 96 }, 97 existingConfigMap: &corev1.ConfigMap{ 98 ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: ConfigMapName}, 99 Data: map[string]string{ConfigMapDataKey: now.Format(time.RFC3339)}, 100 }, 101 expectedActions: []core.Action{ 102 core.NewUpdateAction(schema.GroupVersionResource{Version: "v1", Resource: "configmaps"}, metav1.NamespaceSystem, &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: ConfigMapName}, Data: map[string]string{ConfigMapDataKey: now.Format(dateFormat)}}), 103 }, 104 }, 105 { 106 name: "update configmap with no data", 107 clientObjects: []runtime.Object{ 108 &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: ConfigMapName}, Data: nil}, 109 }, 110 existingConfigMap: &corev1.ConfigMap{ 111 ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: ConfigMapName}, 112 Data: nil, 113 }, 114 expectedActions: []core.Action{ 115 core.NewUpdateAction(schema.GroupVersionResource{Version: "v1", Resource: "configmaps"}, metav1.NamespaceSystem, &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: ConfigMapName}, Data: map[string]string{ConfigMapDataKey: now.Format(dateFormat)}}), 116 }, 117 }, 118 { 119 name: "update configmap should ignore NotFound error [cache with unexpected date format, no live object]", 120 existingConfigMap: &corev1.ConfigMap{ 121 ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: ConfigMapName}, 122 Data: map[string]string{ConfigMapDataKey: "BAD_TIMESTAMP"}, 123 }, 124 expectedActions: []core.Action{ 125 core.NewUpdateAction(schema.GroupVersionResource{Version: "v1", Resource: "configmaps"}, metav1.NamespaceSystem, &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: ConfigMapName}, Data: map[string]string{ConfigMapDataKey: now.Format(dateFormat)}}), 126 }, 127 }, 128 } 129 for _, test := range tests { 130 t.Run(test.name, func(t *testing.T) { 131 client := fake.NewSimpleClientset(test.clientObjects...) 132 limiter := rate.NewLimiter(rate.Every(throttlePeriod), 1) 133 controller := newController(client, testingclock.NewFakeClock(now), limiter) 134 if test.existingConfigMap != nil { 135 controller.configMapCache.Add(test.existingConfigMap) 136 } 137 138 if err := controller.syncConfigMap(); err != nil { 139 t.Errorf("Failed to sync ConfigMap, err: %v", err) 140 } 141 142 for _, createAt := range test.nextCreateAt { 143 // delete the existing configmap to trigger second create 144 controller.configMapCache.Delete(&corev1.ConfigMap{ 145 ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: ConfigMapName}, 146 }) 147 controller.clock.(*testingclock.FakeClock).SetTime(createAt) 148 if err := controller.syncConfigMap(); err != nil { 149 t.Errorf("Failed to sync ConfigMap, err: %v", err) 150 } 151 } 152 153 if diff := cmp.Diff(test.expectedActions, client.Actions()); diff != "" { 154 t.Errorf("Unexpected diff (-want +got):\n%s", diff) 155 } 156 }) 157 } 158 }