istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/serviceregistry/kube/controller/multicluster_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 controller 16 17 import ( 18 "context" 19 "testing" 20 "time" 21 22 v1 "k8s.io/api/core/v1" 23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 "k8s.io/client-go/rest" 25 26 meshconfig "istio.io/api/mesh/v1alpha1" 27 "istio.io/istio/pilot/pkg/features" 28 "istio.io/istio/pilot/pkg/keycertbundle" 29 "istio.io/istio/pilot/pkg/server" 30 "istio.io/istio/pilot/pkg/serviceregistry/aggregate" 31 "istio.io/istio/pkg/cluster" 32 "istio.io/istio/pkg/config/mesh" 33 "istio.io/istio/pkg/kube" 34 "istio.io/istio/pkg/kube/multicluster" 35 "istio.io/istio/pkg/test" 36 "istio.io/istio/pkg/test/util/assert" 37 "istio.io/istio/pkg/test/util/retry" 38 ) 39 40 const ( 41 testSecretNameSpace = "istio-system" 42 DomainSuffix = "fake_domain" 43 ) 44 45 func newMockserviceController() *aggregate.Controller { 46 return aggregate.NewController(aggregate.Options{}) 47 } 48 49 func createMultiClusterSecret(k8s kube.Client, sname, cname string) error { 50 data := map[string][]byte{} 51 secret := v1.Secret{ 52 ObjectMeta: metav1.ObjectMeta{ 53 Name: sname, 54 Namespace: testSecretNameSpace, 55 Labels: map[string]string{ 56 multicluster.MultiClusterSecretLabel: "true", 57 }, 58 }, 59 Data: map[string][]byte{}, 60 } 61 62 data[cname] = []byte("Test") 63 secret.Data = data 64 _, err := k8s.Kube().CoreV1().Secrets(testSecretNameSpace).Create(context.TODO(), &secret, metav1.CreateOptions{}) 65 return err 66 } 67 68 func deleteMultiClusterSecret(k8s kube.Client, sname string) error { 69 var immediate int64 70 71 return k8s.Kube().CoreV1().Secrets(testSecretNameSpace).Delete( 72 context.TODO(), 73 sname, metav1.DeleteOptions{GracePeriodSeconds: &immediate}) 74 } 75 76 func verifyControllers(t *testing.T, m *Multicluster, expectedControllerCount int, timeoutName string) { 77 t.Helper() 78 assert.EventuallyEqual(t, func() int { 79 return len(m.component.All()) 80 }, expectedControllerCount, retry.Message(timeoutName), retry.Delay(time.Millisecond*10), retry.Timeout(time.Second*5)) 81 } 82 83 func initController(client kube.CLIClient, ns string, stop <-chan struct{}) *multicluster.Controller { 84 sc := multicluster.NewController(client, ns, "cluster-1", mesh.NewFixedWatcher(nil)) 85 sc.ClientBuilder = func(kubeConfig []byte, c cluster.ID, configOverrides ...func(*rest.Config)) (kube.Client, error) { 86 return kube.NewFakeClient(), nil 87 } 88 client.RunAndWait(stop) 89 return sc 90 } 91 92 func Test_KubeSecretController(t *testing.T) { 93 mockserviceController := newMockserviceController() 94 clientset := kube.NewFakeClient() 95 stop := test.NewStop(t) 96 s := server.New() 97 mcc := initController(clientset, testSecretNameSpace, stop) 98 mc := NewMulticluster("pilot-abc-123", clientset.Kube(), testSecretNameSpace, Options{ 99 ClusterID: "cluster-1", 100 DomainSuffix: DomainSuffix, 101 MeshWatcher: mesh.NewFixedWatcher(&meshconfig.MeshConfig{}), 102 MeshServiceController: mockserviceController, 103 }, nil, nil, nil, "default", false, nil, s, mcc) 104 assert.NoError(t, mcc.Run(stop)) 105 go mockserviceController.Run(stop) 106 clientset.RunAndWait(stop) 107 kube.WaitForCacheSync("test", stop, mcc.HasSynced) 108 _ = s.Start(stop) 109 110 verifyControllers(t, mc, 1, "create local controller") 111 112 // Create the multicluster secret. Sleep to allow created remote 113 // controller to start and callback add function to be called. 114 err := createMultiClusterSecret(clientset, "test-secret-1", "test-remote-cluster-1") 115 if err != nil { 116 t.Fatalf("Unexpected error on secret create: %v", err) 117 } 118 119 // Test - Verify that the remote controller has been added. 120 verifyControllers(t, mc, 2, "create remote controller") 121 122 // Delete the mulicluster secret. 123 err = deleteMultiClusterSecret(clientset, "test-secret-1") 124 if err != nil { 125 t.Fatalf("Unexpected error on secret delete: %v", err) 126 } 127 128 // Test - Verify that the remote controller has been removed. 129 verifyControllers(t, mc, 1, "delete remote controller") 130 } 131 132 func Test_KubeSecretController_ExternalIstiod_MultipleClusters(t *testing.T) { 133 test.SetForTest(t, &features.ExternalIstiod, true) 134 test.SetForTest(t, &features.InjectionWebhookConfigName, "") 135 mockserviceController := newMockserviceController() 136 clientset := kube.NewFakeClient() 137 stop := test.NewStop(t) 138 s := server.New() 139 certWatcher := keycertbundle.NewWatcher() 140 mcc := initController(clientset, testSecretNameSpace, stop) 141 mc := NewMulticluster("pilot-abc-123", clientset.Kube(), testSecretNameSpace, Options{ 142 ClusterID: "cluster-1", 143 DomainSuffix: DomainSuffix, 144 MeshWatcher: mesh.NewFixedWatcher(&meshconfig.MeshConfig{}), 145 MeshServiceController: mockserviceController, 146 }, nil, nil, certWatcher, "default", false, nil, s, mcc) 147 assert.NoError(t, mcc.Run(stop)) 148 go mockserviceController.Run(stop) 149 clientset.RunAndWait(stop) 150 kube.WaitForCacheSync("test", stop, mcc.HasSynced) 151 _ = s.Start(stop) 152 153 // the multicluster controller will register the local cluster 154 verifyControllers(t, mc, 1, "registered local cluster controller") 155 156 // Create the multicluster secret. Sleep to allow created remote 157 // controller to start and callback add function to be called. 158 err := createMultiClusterSecret(clientset, "test-secret-1", "test-remote-cluster-1") 159 if err != nil { 160 t.Fatalf("Unexpected error on secret create: %v", err) 161 } 162 163 // Test - Verify that the remote controller has been added. 164 verifyControllers(t, mc, 2, "create remote controller 1") 165 166 // Create second multicluster secret. Sleep to allow created remote 167 // controller to start and callback add function to be called. 168 err = createMultiClusterSecret(clientset, "test-secret-2", "test-remote-cluster-2") 169 if err != nil { 170 t.Fatalf("Unexpected error on secret create: %v", err) 171 } 172 173 // Test - Verify that the remote controller has been added. 174 verifyControllers(t, mc, 3, "create remote controller 2") 175 176 // Delete the first mulicluster secret. 177 err = deleteMultiClusterSecret(clientset, "test-secret-1") 178 if err != nil { 179 t.Fatalf("Unexpected error on secret delete: %v", err) 180 } 181 182 // Test - Verify that the remote controller has been removed. 183 verifyControllers(t, mc, 2, "delete remote controller 1") 184 185 // Delete the second mulicluster secret. 186 err = deleteMultiClusterSecret(clientset, "test-secret-2") 187 if err != nil { 188 t.Fatalf("Unexpected error on secret delete: %v", err) 189 } 190 191 // Test - Verify that the remote controller has been removed. 192 verifyControllers(t, mc, 1, "delete remote controller 2") 193 }