Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KSPACE-43: Adding common GetClusters func #372

Closed
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions pkg/cluster/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,24 @@ func GetCachedToolchainCluster(name string) (*CachedToolchainCluster, bool) {
return clusterCache.getCachedToolchainCluster(name, true)
}

// GetClustersFunc a func that returns all the clusters from the cache
type GetClustersFunc func(conditions ...Condition) []*CachedToolchainCluster

// Clusters the func to retrieve all the clusters
var Clusters GetClustersFunc = GetClusters

// GetClusters returns the kube clients for all the clusters from the cache of the clusters
func GetClusters(conditions ...Condition) []*CachedToolchainCluster {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one more thing, GetClusters is pretty generic and can be confusing. How about:

  • GetToolchainClusters
  • GetCachedToolchainClusters

so it's clear which clusters we are talking about

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is already a function named as GetCachedToolchainClusters , but to avoid confusion and for better understanding updating it to GetToolchainClustersCachedFunc

clusters := clusterCache.getCachedToolchainClusters(conditions...)
if len(clusters) == 0 {
if clusterCache.refreshCache != nil {
clusterCache.refreshCache()
}
clusters = clusterCache.getCachedToolchainClusters(conditions...)
}
return clusters
}

// GetHostClusterFunc a func that returns the Host cluster from the cache,
// along with a bool to indicate if there was a match or not
type GetHostClusterFunc func() (*CachedToolchainCluster, bool)
Comment on lines 124 to 126
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't forget to remove the GetHostCluster, GetMemberClusters, and the related functions and types - they shouldn't be used anymore.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I see that you wrote

Keeping the GetHostCluster() and GetMemberClusters() for now and delete them once their dependencies are removed in host, member, registration-service .

but let's delete it right away in this PR, so we are sure that we didn't miss any usage anywhere

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deleted it

Expand Down
129 changes: 27 additions & 102 deletions pkg/cluster/cache_whitebox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1"
"github.com/codeready-toolchain/toolchain-common/pkg/test"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
)

Expand Down Expand Up @@ -51,37 +50,6 @@ func TestGetCluster(t *testing.T) {
}
}

func TestHostCluster(t *testing.T) {
// given
defer resetClusterCache()
host := newTestCachedToolchainCluster(t, "host-cluster", ready)
clusterCache.addCachedToolchainCluster(host)

// when
returnedCachedCluster, ok := HostCluster()

// then
assert.True(t, ok)
assert.Equal(t, host, returnedCachedCluster)
}

func TestMemberClusters(t *testing.T) {
// given
defer resetClusterCache()
member1 := newTestCachedToolchainCluster(t, "member-cluster-1", ready)
clusterCache.addCachedToolchainCluster(member1)
member2 := newTestCachedToolchainCluster(t, "member-cluster-2", ready)
clusterCache.addCachedToolchainCluster(member2)

// when
returnedCachedClusters := MemberClusters()

// then
require.Len(t, returnedCachedClusters, 2)
assert.Contains(t, returnedCachedClusters, member1)
assert.Contains(t, returnedCachedClusters, member2)
}

func TestGetClusterWhenIsEmpty(t *testing.T) {
// given
resetClusterCache()
Expand All @@ -97,17 +65,17 @@ func TestGetClusterWhenIsEmpty(t *testing.T) {
}
}

func TestGetClustersByType(t *testing.T) {
func TestGetClusters(t *testing.T) {

t.Run("get member clusters", func(t *testing.T) {
t.Run("get clusters", func(t *testing.T) {

t.Run("not found", func(t *testing.T) {
// given
defer resetClusterCache()
// no members
// no clusters

//when
clusters := GetMemberClusters()
clusters := GetClusters()

//then
assert.Empty(t, clusters)
Expand All @@ -116,111 +84,68 @@ func TestGetClustersByType(t *testing.T) {
t.Run("all clusters", func(t *testing.T) {
// given
defer resetClusterCache()
host := newTestCachedToolchainCluster(t, "cluster-host", ready)
clusterCache.addCachedToolchainCluster(host)
member1 := newTestCachedToolchainCluster(t, "cluster-1", ready)
clusterCache.addCachedToolchainCluster(member1)
member2 := newTestCachedToolchainCluster(t, "cluster-2", ready)
clusterCache.addCachedToolchainCluster(member2)

//when
clusters := GetMemberClusters()
clusters := GetClusters()

//then
assert.Len(t, clusters, 2)
assert.Len(t, clusters, 3)
assert.Contains(t, clusters, member1)
assert.Contains(t, clusters, member2)
assert.Contains(t, clusters, host)
})

t.Run("found after refreshing the cache", func(t *testing.T) {
// given
defer resetClusterCache()
member := newTestCachedToolchainCluster(t, "member", ready)
clustertest := newTestCachedToolchainCluster(t, "clustertotest", ready)
called := false
clusterCache.refreshCache = func() {
called = true
clusterCache.addCachedToolchainCluster(member)
clusterCache.addCachedToolchainCluster(clustertest)
}

//when
clusters := GetMemberClusters()
clusters := GetClusters()

//then
assert.Len(t, clusters, 1)
assert.Contains(t, clusters, member)
assert.Contains(t, clusters, clustertest)
assert.True(t, called)
})

})
t.Run("get clusters filtered by readiness and capacity", func(t *testing.T) {
defer resetClusterCache()

t.Run("get member clusters filtered by readiness and capacity", func(t *testing.T) {
defer resetClusterCache()
host := newTestCachedToolchainCluster(t, "cluster-host", ready)
clusterCache.addCachedToolchainCluster(host)
member1 := newTestCachedToolchainCluster(t, "cluster-1", ready)
clusterCache.addCachedToolchainCluster(member1)
member2 := newTestCachedToolchainCluster(t, "cluster-2", ready)
clusterCache.addCachedToolchainCluster(member2)
// noise
member3 := newTestCachedToolchainCluster(t, "cluster-3", notReady)
clusterCache.addCachedToolchainCluster(member3)

// noise
host := newTestCachedToolchainCluster(t, "cluster-host", ready)
clusterCache.addCachedToolchainCluster(host)
member1 := newTestCachedToolchainCluster(t, "cluster-1", ready)
clusterCache.addCachedToolchainCluster(member1)
member2 := newTestCachedToolchainCluster(t, "cluster-2", ready)
clusterCache.addCachedToolchainCluster(member2)
member3 := newTestCachedToolchainCluster(t, "cluster-3", notReady)
clusterCache.addCachedToolchainCluster(member3)

t.Run("get only ready member clusters", func(t *testing.T) {
//when
clusters := GetMemberClusters(Ready)
clusters := GetClusters(Ready)

//then
assert.Len(t, clusters, 3)
assert.Contains(t, clusters, member1)
assert.Contains(t, clusters, member2)
})
})

t.Run("get host cluster", func(t *testing.T) {

t.Run("not found", func(t *testing.T) {
// given
defer resetClusterCache()
// no host

//when
_, ok := GetHostCluster()
assert.Contains(t, clusters, host)

//then
assert.False(t, ok)
})
t.Run("found", func(t *testing.T) {
// given
defer resetClusterCache()
host := newTestCachedToolchainCluster(t, "cluster-host", ready)
clusterCache.addCachedToolchainCluster(host)

//when
cluster, ok := GetHostCluster()

//then
assert.True(t, ok)
assert.Equal(t, host, cluster)
})

t.Run("found after refreshing the cache", func(t *testing.T) {
// given
defer resetClusterCache()
host := newTestCachedToolchainCluster(t, "cluster-host", ready)
called := false
clusterCache.refreshCache = func() {
called = true
clusterCache.addCachedToolchainCluster(host)
}

//when
cluster, ok := GetHostCluster()

//then
assert.True(t, ok)
assert.Equal(t, host, cluster)
assert.True(t, called)
})
})

}

func TestGetClusterUsingDifferentKey(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions pkg/cluster/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,9 @@ func IsReady(clusterStatus *toolchainv1alpha1.ToolchainClusterStatus) bool {
return false
}

func ListToolchainClusterConfigs(cl client.Client, namespace string, timeout time.Duration) ([]*Config, error) {
func ListToolchainClusterConfigs(ctx context.Context, cl client.Client, namespace string, timeout time.Duration) ([]*Config, error) {
toolchainClusters := &toolchainv1alpha1.ToolchainClusterList{}
if err := cl.List(context.TODO(), toolchainClusters, client.InNamespace(namespace)); err != nil {
if err := cl.List(ctx, toolchainClusters, client.InNamespace(namespace)); err != nil {
return nil, err
}
var configs []*Config
Expand Down
10 changes: 5 additions & 5 deletions pkg/cluster/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func TestListToolchainClusterConfigs(t *testing.T) {

t.Run("list members", func(t *testing.T) {
// when
clusterConfigs, err := cluster.ListToolchainClusterConfigs(cl, m1.Namespace, time.Second)
clusterConfigs, err := cluster.ListToolchainClusterConfigs(context.TODO(), cl, m1.Namespace, time.Second)

// then
require.NoError(t, err)
Expand All @@ -105,7 +105,7 @@ func TestListToolchainClusterConfigs(t *testing.T) {
t.Run("list host", func(t *testing.T) {
// when

clusterConfigs, err := cluster.ListToolchainClusterConfigs(cl, host.Namespace, time.Second)
clusterConfigs, err := cluster.ListToolchainClusterConfigs(context.TODO(), cl, host.Namespace, time.Second)

// then
require.NoError(t, err)
Expand All @@ -124,7 +124,7 @@ func TestListToolchainClusterConfigs(t *testing.T) {
cl := test.NewFakeClient(t, host, noise, secNoise)

// when
clusterConfigs, err := cluster.ListToolchainClusterConfigs(cl, m1.Namespace, time.Second)
clusterConfigs, err := cluster.ListToolchainClusterConfigs(context.TODO(), cl, m1.Namespace, time.Second)

// then
require.NoError(t, err)
Expand All @@ -139,7 +139,7 @@ func TestListToolchainClusterConfigs(t *testing.T) {
}

// when
clusterConfigs, err := cluster.ListToolchainClusterConfigs(cl, m1.Namespace, time.Second)
clusterConfigs, err := cluster.ListToolchainClusterConfigs(context.TODO(), cl, m1.Namespace, time.Second)

// then
require.Error(t, err)
Expand All @@ -154,7 +154,7 @@ func TestListToolchainClusterConfigs(t *testing.T) {
}

// when
clusterConfigs, err := cluster.ListToolchainClusterConfigs(cl, m1.Namespace, time.Second)
clusterConfigs, err := cluster.ListToolchainClusterConfigs(context.TODO(), cl, m1.Namespace, time.Second)

// then
require.Error(t, err)
Expand Down
12 changes: 7 additions & 5 deletions pkg/status/toolchaincluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,20 @@ const (

// ToolchainClusterAttributes required attributes for obtaining ToolchainCluster status
type ToolchainClusterAttributes struct {
GetClusterFunc func() (*cluster.CachedToolchainCluster, bool)
Period time.Duration
Timeout time.Duration
GetClustersFunc cluster.GetClustersFunc
Copy link
Contributor

@MatousJobanek MatousJobanek Mar 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the purpose and the usage of the ToolchainClusterAttributes type and GetToolchainClusterConditions function doesn't match with the cluster.GetClustersFunc - this is intended to be used for one ToolchainCluster, but for many. I saw that you used

toolchainCluster := toolchainClusters[0]

to get the first one, but you never know if you are supposed to use the first one, second, or third.
I would rather either keep the

GetClusterFunc func() (*cluster.CachedToolchainCluster, bool)

in the same format is it was before and let the caller to pass the ToolchainCluster - something like this:

	attributes := status.ToolchainClusterAttributes{
		GetClusterFunc: func() (*cluster.CachedToolchainCluster, bool) {
			clusters := cluster.GetClustersFunc()
			if len(clusters) != 0 {
				return clusters[0], true
			}
			return nil, false
		},

or just change the field so it doesn't take a func but rather a *cluster.CachedToolchainCluster directly

Period time.Duration
Timeout time.Duration
}

// GetToolchainClusterConditions uses the provided ToolchainCluster attributes to determine status conditions
func GetToolchainClusterConditions(logger logr.Logger, attrs ToolchainClusterAttributes) []toolchainv1alpha1.Condition {
// look up cluster connection status
toolchainCluster, ok := attrs.GetClusterFunc()
if !ok {
toolchainClusters := attrs.GetClustersFunc()

if len(toolchainClusters) != 1 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

originally, there was:

if !ok {

which is not then same as

if len(toolchainClusters) != 1 {

when there can be 0...n results 🙃

return []toolchainv1alpha1.Condition{*NewComponentErrorCondition(toolchainv1alpha1.ToolchainStatusClusterConnectionNotFoundReason, ErrMsgClusterConnectionNotFound)}
}
toolchainCluster := toolchainClusters[0]

// check conditions of cluster connection
if !cluster.IsReady(toolchainCluster.ClusterStatus) {
Expand Down
Loading
Loading