1
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
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
134 s2 := configMapsToAttach{
135 containerEnvConfigMaps: []envConfigMaps{
136 {envVarNames: []string{"s3"}},
137 {envVarNames: []string{"s4"}},
138 {envFromNames: []string{"s40"}},
139 },
140 }
141
142 manager.RegisterPod(podWithConfigMaps("ns2", "name2", s2))
143
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 }
174
View as plain text