k8s.io/kubernetes@v1.29.3/pkg/kubelet/secret/secret_manager_test.go (about) 1 /* 2 Copyright 2018 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 secret 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 getSecret(fakeClient clientset.Interface) manager.GetObjectFunc { 52 return func(namespace, name string, opts metav1.GetOptions) (runtime.Object, error) { 53 return fakeClient.CoreV1().Secrets(namespace).Get(context.TODO(), name, opts) 54 } 55 } 56 57 type envSecrets struct { 58 envVarNames []string 59 envFromNames []string 60 } 61 62 type secretsToAttach struct { 63 imagePullSecretNames []string 64 containerEnvSecrets []envSecrets 65 } 66 67 func podWithSecrets(ns, podName string, toAttach secretsToAttach) *v1.Pod { 68 pod := &v1.Pod{ 69 ObjectMeta: metav1.ObjectMeta{ 70 Namespace: ns, 71 Name: podName, 72 }, 73 Spec: v1.PodSpec{}, 74 } 75 for _, name := range toAttach.imagePullSecretNames { 76 pod.Spec.ImagePullSecrets = append( 77 pod.Spec.ImagePullSecrets, v1.LocalObjectReference{Name: name}) 78 } 79 for i, secrets := range toAttach.containerEnvSecrets { 80 container := v1.Container{ 81 Name: fmt.Sprintf("container-%d", i), 82 } 83 for _, name := range secrets.envFromNames { 84 envFrom := v1.EnvFromSource{ 85 SecretRef: &v1.SecretEnvSource{ 86 LocalObjectReference: v1.LocalObjectReference{ 87 Name: name, 88 }, 89 }, 90 } 91 container.EnvFrom = append(container.EnvFrom, envFrom) 92 } 93 94 for _, name := range secrets.envVarNames { 95 envSource := &v1.EnvVarSource{ 96 SecretKeyRef: &v1.SecretKeySelector{ 97 LocalObjectReference: v1.LocalObjectReference{ 98 Name: name, 99 }, 100 }, 101 } 102 container.Env = append(container.Env, v1.EnvVar{ValueFrom: envSource}) 103 } 104 pod.Spec.Containers = append(pod.Spec.Containers, container) 105 } 106 return pod 107 } 108 109 func TestCacheBasedSecretManager(t *testing.T) { 110 fakeClient := &fake.Clientset{} 111 store := manager.NewObjectStore(getSecret(fakeClient), clock.RealClock{}, noObjectTTL, 0) 112 manager := &secretManager{ 113 manager: manager.NewCacheBasedManager(store, getSecretNames), 114 } 115 116 // Create a pod with some secrets. 117 s1 := secretsToAttach{ 118 imagePullSecretNames: []string{"s1"}, 119 containerEnvSecrets: []envSecrets{ 120 {envVarNames: []string{"s1"}}, 121 {envVarNames: []string{"s2"}}, 122 {envFromNames: []string{"s20"}}, 123 }, 124 } 125 manager.RegisterPod(podWithSecrets("ns1", "name1", s1)) 126 // Update the pod with a different secrets. 127 s2 := secretsToAttach{ 128 imagePullSecretNames: []string{"s1"}, 129 containerEnvSecrets: []envSecrets{ 130 {envVarNames: []string{"s3"}}, 131 {envVarNames: []string{"s4"}}, 132 {envFromNames: []string{"s40"}}, 133 }, 134 } 135 manager.RegisterPod(podWithSecrets("ns1", "name1", s2)) 136 // Create another pod, but with same secrets in different namespace. 137 manager.RegisterPod(podWithSecrets("ns2", "name2", s2)) 138 // Create and delete a pod with some other secrets. 139 s3 := secretsToAttach{ 140 imagePullSecretNames: []string{"s5"}, 141 containerEnvSecrets: []envSecrets{ 142 {envVarNames: []string{"s6"}}, 143 {envFromNames: []string{"s60"}}, 144 }, 145 } 146 manager.RegisterPod(podWithSecrets("ns3", "name", s3)) 147 manager.UnregisterPod(podWithSecrets("ns3", "name", s3)) 148 149 // We should have only: s1, s3 and s4 secrets in namespaces: ns1 and ns2. 150 for _, ns := range []string{"ns1", "ns2", "ns3"} { 151 for _, secret := range []string{"s1", "s2", "s3", "s4", "s5", "s6", "s20", "s40", "s50"} { 152 shouldExist := 153 (secret == "s1" || secret == "s3" || secret == "s4" || secret == "s40") && (ns == "ns1" || ns == "ns2") 154 checkObject(t, store, ns, secret, shouldExist) 155 } 156 } 157 }