k8s.io/kubernetes@v1.29.3/pkg/kubelet/configmap/configmap_manager_test.go (about) 1 /* 2 Copyright 2017 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 configmap 18 19 import ( 20 "context" 21 "fmt" 22 "strings" 23 "testing" 24 "time" 25 26 "k8s.io/api/core/v1" 27 28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 "k8s.io/apimachinery/pkg/runtime" 30 31 clientset "k8s.io/client-go/kubernetes" 32 "k8s.io/client-go/kubernetes/fake" 33 "k8s.io/kubernetes/pkg/kubelet/util/manager" 34 "k8s.io/utils/clock" 35 ) 36 37 func checkObject(t *testing.T, store manager.Store, ns, name string, shouldExist bool) { 38 _, err := store.Get(ns, name) 39 if shouldExist && err != nil { 40 t.Errorf("unexpected actions: %#v", err) 41 } 42 if !shouldExist && (err == nil || !strings.Contains(err.Error(), fmt.Sprintf("object %q/%q not registered", ns, name))) { 43 t.Errorf("unexpected actions: %#v", err) 44 } 45 } 46 47 func noObjectTTL() (time.Duration, bool) { 48 return time.Duration(0), false 49 } 50 51 func getConfigMap(fakeClient clientset.Interface) manager.GetObjectFunc { 52 return func(namespace, name string, opts metav1.GetOptions) (runtime.Object, error) { 53 return fakeClient.CoreV1().ConfigMaps(namespace).Get(context.TODO(), name, opts) 54 } 55 } 56 57 type envConfigMaps struct { 58 envVarNames []string 59 envFromNames []string 60 } 61 62 type configMapsToAttach struct { 63 containerEnvConfigMaps []envConfigMaps 64 volumes []string 65 } 66 67 func podWithConfigMaps(ns, podName string, toAttach configMapsToAttach) *v1.Pod { 68 pod := &v1.Pod{ 69 ObjectMeta: metav1.ObjectMeta{ 70 Namespace: ns, 71 Name: podName, 72 }, 73 Spec: v1.PodSpec{}, 74 } 75 for i, configMaps := range toAttach.containerEnvConfigMaps { 76 container := v1.Container{ 77 Name: fmt.Sprintf("container-%d", i), 78 } 79 for _, name := range configMaps.envFromNames { 80 envFrom := v1.EnvFromSource{ 81 ConfigMapRef: &v1.ConfigMapEnvSource{ 82 LocalObjectReference: v1.LocalObjectReference{ 83 Name: name, 84 }, 85 }, 86 } 87 container.EnvFrom = append(container.EnvFrom, envFrom) 88 } 89 90 for _, name := range configMaps.envVarNames { 91 envSource := &v1.EnvVarSource{ 92 ConfigMapKeyRef: &v1.ConfigMapKeySelector{ 93 LocalObjectReference: v1.LocalObjectReference{ 94 Name: name, 95 }, 96 }, 97 } 98 container.Env = append(container.Env, v1.EnvVar{ValueFrom: envSource}) 99 } 100 pod.Spec.Containers = append(pod.Spec.Containers, container) 101 } 102 for _, configMap := range toAttach.volumes { 103 volume := &v1.ConfigMapVolumeSource{ 104 LocalObjectReference: v1.LocalObjectReference{Name: configMap}, 105 } 106 pod.Spec.Volumes = append(pod.Spec.Volumes, v1.Volume{ 107 Name: configMap, 108 VolumeSource: v1.VolumeSource{ 109 ConfigMap: volume, 110 }, 111 }) 112 } 113 return pod 114 } 115 116 func TestCacheBasedConfigMapManager(t *testing.T) { 117 fakeClient := &fake.Clientset{} 118 store := manager.NewObjectStore(getConfigMap(fakeClient), clock.RealClock{}, noObjectTTL, 0) 119 manager := &configMapManager{ 120 manager: manager.NewCacheBasedManager(store, getConfigMapNames), 121 } 122 123 // Create a pod with some configMaps. 124 s1 := configMapsToAttach{ 125 containerEnvConfigMaps: []envConfigMaps{ 126 {envVarNames: []string{"s1"}}, 127 {envFromNames: []string{"s20"}}, 128 }, 129 volumes: []string{"s2"}, 130 } 131 manager.RegisterPod(podWithConfigMaps("ns1", "name1", s1)) 132 manager.RegisterPod(podWithConfigMaps("ns2", "name2", s1)) 133 // Update the pod with a different configMaps. 134 s2 := configMapsToAttach{ 135 containerEnvConfigMaps: []envConfigMaps{ 136 {envVarNames: []string{"s3"}}, 137 {envVarNames: []string{"s4"}}, 138 {envFromNames: []string{"s40"}}, 139 }, 140 } 141 // Create another pod, but with same configMaps in different namespace. 142 manager.RegisterPod(podWithConfigMaps("ns2", "name2", s2)) 143 // Create and delete a pod with some other configMaps. 144 s3 := configMapsToAttach{ 145 containerEnvConfigMaps: []envConfigMaps{ 146 {envVarNames: []string{"s6"}}, 147 {envFromNames: []string{"s60"}}, 148 }, 149 } 150 manager.RegisterPod(podWithConfigMaps("ns3", "name", s3)) 151 manager.UnregisterPod(podWithConfigMaps("ns3", "name", s3)) 152 153 existingMaps := map[string][]string{ 154 "ns1": {"s1", "s2", "s20"}, 155 "ns2": {"s3", "s4", "s40"}, 156 } 157 shouldExist := func(ns, configMap string) bool { 158 if cmaps, ok := existingMaps[ns]; ok { 159 for _, cm := range cmaps { 160 if cm == configMap { 161 return true 162 } 163 } 164 } 165 return false 166 } 167 168 for _, ns := range []string{"ns1", "ns2", "ns3"} { 169 for _, configMap := range []string{"s1", "s2", "s3", "s4", "s5", "s6", "s20", "s40", "s50"} { 170 checkObject(t, store, ns, configMap, shouldExist(ns, configMap)) 171 } 172 } 173 }