Skip to content

Commit

Permalink
KSPACE-20: drop the distinction between host & member ToolchainCluste…
Browse files Browse the repository at this point in the history
…rs (#359)
  • Loading branch information
fbm3307 authored Mar 13, 2024
1 parent 05f8dfb commit 5cafefa
Show file tree
Hide file tree
Showing 10 changed files with 226 additions and 337 deletions.
25 changes: 12 additions & 13 deletions controllers/toolchaincluster/healthchecker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
func TestClusterHealthChecks(t *testing.T) {
// given
defer gock.Off()
tcNs := "test-namespace"
gock.New("http://cluster.com").
Get("healthz").
Persist().
Expand All @@ -35,9 +36,9 @@ func TestClusterHealthChecks(t *testing.T) {
Reply(404)

t.Run("ToolchainCluster.status doesn't contain any conditions", func(t *testing.T) {
unstable, sec := newToolchainCluster("unstable", "http://unstable.com", toolchainv1alpha1.ToolchainClusterStatus{})
notFound, _ := newToolchainCluster("not-found", "http://not-found.com", toolchainv1alpha1.ToolchainClusterStatus{})
stable, _ := newToolchainCluster("stable", "http://cluster.com", toolchainv1alpha1.ToolchainClusterStatus{})
unstable, sec := newToolchainCluster("unstable", tcNs, "http://unstable.com", toolchainv1alpha1.ToolchainClusterStatus{})
notFound, _ := newToolchainCluster("not-found", tcNs, "http://not-found.com", toolchainv1alpha1.ToolchainClusterStatus{})
stable, _ := newToolchainCluster("stable", tcNs, "http://cluster.com", toolchainv1alpha1.ToolchainClusterStatus{})

cl := test.NewFakeClient(t, unstable, notFound, stable, sec)
reset := setupCachedClusters(t, cl, unstable, notFound, stable)
Expand All @@ -53,10 +54,9 @@ func TestClusterHealthChecks(t *testing.T) {
})

t.Run("ToolchainCluster.status already contains conditions", func(t *testing.T) {
unstable, sec := newToolchainCluster("unstable", "http://unstable.com", withStatus(healthy()))
notFound, _ := newToolchainCluster("not-found", "http://not-found.com", withStatus(notOffline(), unhealthy()))
stable, _ := newToolchainCluster("stable", "http://cluster.com", withStatus(offline()))

unstable, sec := newToolchainCluster("unstable", tcNs, "http://unstable.com", withStatus(healthy()))
notFound, _ := newToolchainCluster("not-found", tcNs, "http://not-found.com", withStatus(notOffline(), unhealthy()))
stable, _ := newToolchainCluster("stable", tcNs, "http://cluster.com", withStatus(offline()))
cl := test.NewFakeClient(t, unstable, notFound, stable, sec)
resetCache := setupCachedClusters(t, cl, unstable, notFound, stable)
defer resetCache()
Expand All @@ -71,8 +71,7 @@ func TestClusterHealthChecks(t *testing.T) {
})

t.Run("if no zones nor region is retrieved, then keep the current", func(t *testing.T) {
stable, sec := newToolchainCluster("stable", "http://cluster.com", withStatus(offline()))

stable, sec := newToolchainCluster("stable", tcNs, "http://cluster.com", withStatus(offline()))
cl := test.NewFakeClient(t, stable, sec)
resetCache := setupCachedClusters(t, cl, stable)
defer resetCache()
Expand All @@ -85,7 +84,7 @@ func TestClusterHealthChecks(t *testing.T) {
})

t.Run("if the connection cannot be established at beginning, then it should be offline", func(t *testing.T) {
stable, sec := newToolchainCluster("failing", "http://failing.com", toolchainv1alpha1.ToolchainClusterStatus{})
stable, sec := newToolchainCluster("failing", tcNs, "http://failing.com", toolchainv1alpha1.ToolchainClusterStatus{})

cl := test.NewFakeClient(t, stable, sec)

Expand All @@ -98,7 +97,7 @@ func TestClusterHealthChecks(t *testing.T) {
}

func setupCachedClusters(t *testing.T, cl *test.FakeClient, clusters ...*toolchainv1alpha1.ToolchainCluster) func() {
service := cluster.NewToolchainClusterServiceWithClient(cl, logf.Log, "test-namespace", 0, func(config *rest.Config, options client.Options) (client.Client, error) {
service := cluster.NewToolchainClusterServiceWithClient(cl, logf.Log, test.MemberOperatorNs, 0, func(config *rest.Config, options client.Options) (client.Client, error) {
// make sure that insecure is false to make Gock mocking working properly
config.Insecure = false
return client.New(config, options)
Expand All @@ -123,8 +122,8 @@ func withStatus(conditions ...toolchainv1alpha1.ToolchainClusterCondition) toolc
}
}

func newToolchainCluster(name, apiEndpoint string, status toolchainv1alpha1.ToolchainClusterStatus) (*toolchainv1alpha1.ToolchainCluster, *corev1.Secret) {
toolchainCluster, secret := test.NewToolchainClusterWithEndpoint(name, "secret", apiEndpoint, status, map[string]string{})
func newToolchainCluster(name, tcNs string, apiEndpoint string, status toolchainv1alpha1.ToolchainClusterStatus) (*toolchainv1alpha1.ToolchainCluster, *corev1.Secret) {
toolchainCluster, secret := test.NewToolchainClusterWithEndpoint(name, tcNs, "secret", apiEndpoint, status, map[string]string{"namespace": "test-namespace"})
return toolchainCluster, secret
}

Expand Down
28 changes: 0 additions & 28 deletions controllers/toolchaincluster/toolchaincluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,33 +61,5 @@ func (r *Reconciler) Reconcile(ctx context.Context, request ctrl.Request) (ctrl.
return reconcile.Result{}, err
}

// add toolchaincluster role label if not present
reqLogger.Info("adding cluster role label based on type")
if err := r.addToolchainClusterRoleLabelFromType(ctx, toolchainCluster); err != nil {
return reconcile.Result{}, err
}

return reconcile.Result{}, r.clusterCacheService.AddOrUpdateToolchainCluster(toolchainCluster)
}

func (r *Reconciler) addToolchainClusterRoleLabelFromType(ctx context.Context, toolchainCluster *toolchainv1alpha1.ToolchainCluster) error {
logger := log.FromContext(ctx)

if clusterType, found := toolchainCluster.Labels[cluster.LabelType]; !found {
logger.Info("cluster `type` label not found, unable to add toolchain cluster role label from type")
return nil
} else if clusterType != string(cluster.Member) {
logger.Info("cluster `type` is not member, skipping cluster role label setting")
return nil
}
clusterRoleLabel := cluster.RoleLabel(cluster.Tenant)
if _, exists := toolchainCluster.Labels[clusterRoleLabel]; !exists {
logger.Info("setting cluster role label for toolchaincluster", clusterRoleLabel, toolchainCluster.Name)
// We use only the label key, the value can remain empty.
toolchainCluster.Labels[clusterRoleLabel] = ""
if err := r.client.Update(ctx, toolchainCluster); err != nil {
return err
}
}
return nil
}
34 changes: 11 additions & 23 deletions pkg/cluster/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ type Config struct {
// APIEndpoint is the API endpoint of the corresponding ToolchainCluster. This can be a hostname,
// hostname:port, IP or IP:port.
APIEndpoint string
// Type is a type of the cluster (either host or member)
Type Type
// OperatorNamespace is a name of a namespace (in the cluster) the operator is running in
OperatorNamespace string
// OwnerClusterName keeps the name of the cluster the ToolchainCluster resource is created in
Expand Down Expand Up @@ -81,23 +79,21 @@ var Ready Condition = func(cluster *CachedToolchainCluster) bool {
return IsReady(cluster.ClusterStatus)
}

func (c *toolchainClusterClients) getCachedToolchainClustersByType(clusterType Type, conditions ...Condition) []*CachedToolchainCluster {
func (c *toolchainClusterClients) getCachedToolchainClusters(conditions ...Condition) []*CachedToolchainCluster {
c.RLock()
defer c.RUnlock()
return Filter(clusterType, c.clusters, conditions...)
return Filter(c.clusters, conditions...)
}
func Filter(clusterType Type, clusters map[string]*CachedToolchainCluster, conditions ...Condition) []*CachedToolchainCluster {
func Filter(clusters map[string]*CachedToolchainCluster, conditions ...Condition) []*CachedToolchainCluster {
filteredClusters := make([]*CachedToolchainCluster, 0, len(clusters))
clusters:
for _, cluster := range clusters {
if cluster.Type == clusterType {
for _, match := range conditions {
if !match(cluster) {
continue clusters
}
for _, match := range conditions {
if !match(cluster) {
continue clusters
}
filteredClusters = append(filteredClusters, cluster)
}
filteredClusters = append(filteredClusters, cluster)
}
return filteredClusters
}
Expand All @@ -117,12 +113,12 @@ var HostCluster GetHostClusterFunc = GetHostCluster
// GetHostCluster returns the kube client for the host cluster from the cache of the clusters
// and info if such a client exists
func GetHostCluster() (*CachedToolchainCluster, bool) {
clusters := clusterCache.getCachedToolchainClustersByType(Host)
clusters := clusterCache.getCachedToolchainClusters()
if len(clusters) == 0 {
if clusterCache.refreshCache != nil {
clusterCache.refreshCache()
}
clusters = clusterCache.getCachedToolchainClustersByType(Host)
clusters = clusterCache.getCachedToolchainClusters()
if len(clusters) == 0 {
return nil, false
}
Expand All @@ -138,24 +134,16 @@ var MemberClusters GetMemberClustersFunc = GetMemberClusters

// GetMemberClusters returns the kube clients for the host clusters from the cache of the clusters
func GetMemberClusters(conditions ...Condition) []*CachedToolchainCluster {
clusters := clusterCache.getCachedToolchainClustersByType(Member, conditions...)
clusters := clusterCache.getCachedToolchainClusters(conditions...)
if len(clusters) == 0 {
if clusterCache.refreshCache != nil {
clusterCache.refreshCache()
}
clusters = clusterCache.getCachedToolchainClustersByType(Member, conditions...)
clusters = clusterCache.getCachedToolchainClusters(conditions...)
}
return clusters
}

// Type is a cluster type (either host or member)
type Type string

const (
Member Type = "member"
Host Type = "host"
)

// Role defines the role of the cluster.
// Each type of cluster can have multiple roles (tenant for specific APIs, user workloads, others ... )
type Role string
Expand Down
Loading

0 comments on commit 5cafefa

Please sign in to comment.