sigs.k8s.io/cluster-api@v1.6.3/controllers/remote/cluster_cache_reconciler_test.go (about)

     1  /*
     2  Copyright 2020 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 remote
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"testing"
    23  
    24  	. "github.com/onsi/gomega"
    25  	corev1 "k8s.io/api/core/v1"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	"k8s.io/client-go/kubernetes/scheme"
    28  	"sigs.k8s.io/controller-runtime/pkg/client"
    29  	"sigs.k8s.io/controller-runtime/pkg/controller"
    30  	"sigs.k8s.io/controller-runtime/pkg/manager"
    31  	metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
    32  
    33  	clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
    34  	"sigs.k8s.io/cluster-api/util"
    35  )
    36  
    37  func TestClusterCacheReconciler(t *testing.T) {
    38  	t.Run("When running the ClusterCacheReconciler", func(t *testing.T) {
    39  		var (
    40  			mgr        manager.Manager
    41  			mgrContext context.Context
    42  			mgrCancel  context.CancelFunc
    43  			cct        *ClusterCacheTracker
    44  			k8sClient  client.Client
    45  		)
    46  
    47  		// createAndWatchCluster creates a new cluster and ensures the clusterCacheTracker has a clusterAccessor for it
    48  		createAndWatchCluster := func(clusterName string, testNamespace *corev1.Namespace, g *WithT) {
    49  			t.Logf("Creating a cluster %q", clusterName)
    50  			testCluster := &clusterv1.Cluster{
    51  				ObjectMeta: metav1.ObjectMeta{
    52  					Name:      clusterName,
    53  					Namespace: testNamespace.GetName(),
    54  				},
    55  			}
    56  			g.Expect(k8sClient.Create(ctx, testCluster)).To(Succeed())
    57  
    58  			// Check the cluster can be fetched from the API server
    59  			testClusterKey := util.ObjectKey(testCluster)
    60  			g.Eventually(func() error {
    61  				return k8sClient.Get(ctx, testClusterKey, &clusterv1.Cluster{})
    62  			}, timeout).Should(Succeed())
    63  
    64  			t.Log("Creating a test cluster kubeconfig")
    65  			g.Expect(env.CreateKubeconfigSecret(ctx, testCluster)).To(Succeed())
    66  
    67  			// Check the secret can be fetched from the API server
    68  			secretKey := client.ObjectKey{Namespace: testNamespace.GetName(), Name: fmt.Sprintf("%s-kubeconfig", testCluster.GetName())}
    69  			g.Eventually(func() error {
    70  				return k8sClient.Get(ctx, secretKey, &corev1.Secret{})
    71  			}, timeout).Should(Succeed())
    72  
    73  			t.Log("Creating a clusterAccessor for the cluster")
    74  			_, err := cct.GetClient(ctx, testClusterKey)
    75  			g.Expect(err).ToNot(HaveOccurred())
    76  		}
    77  
    78  		setup := func(t *testing.T, g *WithT) *corev1.Namespace {
    79  			t.Helper()
    80  
    81  			t.Log("Setting up a new manager")
    82  			var err error
    83  			mgr, err = manager.New(env.Config, manager.Options{
    84  				Scheme: scheme.Scheme,
    85  				Metrics: metricsserver.Options{
    86  					BindAddress: "0",
    87  				},
    88  			})
    89  			g.Expect(err).ToNot(HaveOccurred())
    90  
    91  			t.Log("Setting up a ClusterCacheTracker")
    92  			cct, err = NewClusterCacheTracker(mgr, ClusterCacheTrackerOptions{})
    93  			g.Expect(err).ToNot(HaveOccurred())
    94  
    95  			t.Log("Creating the ClusterCacheReconciler")
    96  			r := &ClusterCacheReconciler{
    97  				Client:  mgr.GetClient(),
    98  				Tracker: cct,
    99  			}
   100  			g.Expect(r.SetupWithManager(ctx, mgr, controller.Options{})).To(Succeed())
   101  
   102  			t.Log("Starting the manager")
   103  			mgrContext, mgrCancel = context.WithCancel(ctx)
   104  			go func() {
   105  				g.Expect(mgr.Start(mgrContext)).To(Succeed())
   106  			}()
   107  			<-env.Manager.Elected()
   108  
   109  			k8sClient = mgr.GetClient()
   110  
   111  			t.Log("Creating a namespace for the test")
   112  			ns, err := env.CreateNamespace(ctx, "cluster-cache-test")
   113  			g.Expect(err).ToNot(HaveOccurred())
   114  
   115  			t.Log("Creating clusters to test with")
   116  			createAndWatchCluster("cluster-1", ns, g)
   117  			createAndWatchCluster("cluster-2", ns, g)
   118  			createAndWatchCluster("cluster-3", ns, g)
   119  
   120  			return ns
   121  		}
   122  
   123  		teardown := func(t *testing.T, g *WithT, ns *corev1.Namespace) {
   124  			t.Helper()
   125  
   126  			t.Log("Deleting any Secrets")
   127  			g.Expect(cleanupTestSecrets(ctx, k8sClient)).To(Succeed())
   128  			t.Log("Deleting any Clusters")
   129  			g.Expect(cleanupTestClusters(ctx, k8sClient)).To(Succeed())
   130  			t.Log("Deleting Namespace")
   131  			g.Expect(env.Delete(ctx, ns)).To(Succeed())
   132  			t.Log("Stopping the manager")
   133  			mgrCancel()
   134  		}
   135  
   136  		t.Run("should remove clusterAccessors when clusters are deleted", func(t *testing.T) {
   137  			g := NewWithT(t)
   138  			testNamespace := setup(t, g)
   139  			defer teardown(t, g, testNamespace)
   140  
   141  			for _, clusterName := range []string{"cluster-1", "cluster-2", "cluster-3"} {
   142  				t.Logf("Deleting cluster %q", clusterName)
   143  				obj := &clusterv1.Cluster{
   144  					ObjectMeta: metav1.ObjectMeta{
   145  						Namespace: testNamespace.Name,
   146  						Name:      clusterName,
   147  					},
   148  				}
   149  				g.Expect(k8sClient.Delete(ctx, obj)).To(Succeed())
   150  
   151  				t.Logf("Checking cluster %q's clusterAccessor is removed", clusterName)
   152  				g.Eventually(func() bool { return cct.clusterAccessorExists(util.ObjectKey(obj)) }, timeout).Should(BeFalse())
   153  			}
   154  		})
   155  	})
   156  }