istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/kube/inject/watcher_test.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package inject 16 17 import ( 18 "context" 19 "fmt" 20 "sync" 21 "testing" 22 "time" 23 24 . "github.com/onsi/gomega" 25 v1 "k8s.io/api/core/v1" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 28 "istio.io/istio/pkg/kube" 29 "istio.io/istio/pkg/test" 30 ) 31 32 const ( 33 namespace string = "istio-system" 34 cmName string = "istio-sidecar-injector" 35 configKey string = "config" 36 valuesKey string = "values" 37 ) 38 39 func makeConfigMap(resourceVersion string, data map[string]string) *v1.ConfigMap { 40 return &v1.ConfigMap{ 41 ObjectMeta: metav1.ObjectMeta{ 42 Namespace: namespace, 43 Name: cmName, 44 ResourceVersion: resourceVersion, 45 }, 46 Data: data, 47 } 48 } 49 50 func TestNewConfigMapWatcher(t *testing.T) { 51 configYaml := "policy: enabled" 52 c, err := UnmarshalConfig([]byte(configYaml)) 53 if err != nil { 54 t.Fatal(err) 55 } 56 valuesConfig := "sidecarInjectorWebhook: {}" 57 58 cm := makeConfigMap("1", map[string]string{ 59 configKey: configYaml, 60 valuesKey: valuesConfig, 61 }) 62 badCM := makeConfigMap("2", map[string]string{ 63 configKey: configYaml, 64 }) 65 badCM2 := makeConfigMap("3", map[string]string{ 66 valuesKey: valuesConfig, 67 }) 68 badCM3 := makeConfigMap("4", map[string]string{ 69 configKey: "bad yaml", 70 valuesKey: valuesConfig, 71 }) 72 73 var mu sync.Mutex 74 var newConfig *Config 75 var newValues string 76 77 client := kube.NewFakeClient() 78 w := NewConfigMapWatcher(client, namespace, cmName, configKey, valuesKey) 79 w.SetHandler(func(config *Config, values string) error { 80 mu.Lock() 81 defer mu.Unlock() 82 newConfig = config 83 newValues = values 84 return nil 85 }) 86 stop := test.NewStop(t) 87 go w.Run(stop) 88 controller := w.(*configMapWatcher).c 89 client.RunAndWait(stop) 90 kube.WaitForCacheSync("test", stop, controller.HasSynced) 91 92 cms := client.Kube().CoreV1().ConfigMaps(namespace) 93 steps := []struct { 94 added *v1.ConfigMap 95 updated *v1.ConfigMap 96 deleted *v1.ConfigMap 97 }{ 98 {added: cm}, 99 100 // Handle misconfiguration errors. 101 {updated: badCM}, 102 {updated: cm}, 103 {updated: badCM2}, 104 {updated: badCM}, 105 {updated: cm}, 106 {updated: badCM3}, 107 {updated: cm}, 108 109 // Handle deletion. 110 {deleted: cm}, 111 {added: cm}, 112 } 113 114 for i, step := range steps { 115 t.Run(fmt.Sprintf("[%v]", i), func(t *testing.T) { 116 g := NewWithT(t) 117 118 switch { 119 case step.added != nil: 120 _, err := cms.Create(context.TODO(), step.added, metav1.CreateOptions{}) 121 g.Expect(err).Should(BeNil()) 122 case step.updated != nil: 123 _, err := cms.Update(context.TODO(), step.updated, metav1.UpdateOptions{}) 124 g.Expect(err).Should(BeNil()) 125 case step.deleted != nil: 126 g.Expect(cms.Delete(context.TODO(), step.deleted.Name, metav1.DeleteOptions{})). 127 Should(Succeed()) 128 } 129 130 g.Eventually(func() *Config { 131 mu.Lock() 132 defer mu.Unlock() 133 return newConfig 134 }, time.Second).Should(Equal(&c)) 135 g.Eventually(func() string { 136 mu.Lock() 137 defer mu.Unlock() 138 return newValues 139 }, time.Second).Should(Equal(valuesConfig)) 140 }) 141 } 142 }