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  }