Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 3 additions & 3 deletions helm/bundles/cortex-cinder/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ apiVersion: v2
name: cortex-cinder
description: A Helm chart deploying Cortex for Cinder.
type: application
version: 0.0.31
version: 0.0.32
appVersion: 0.1.0
dependencies:
# from: file://../../library/cortex-postgres
Expand All @@ -16,12 +16,12 @@ dependencies:
# from: file://../../library/cortex
- name: cortex
repository: oci://ghcr.io/cobaltcore-dev/cortex/charts
version: 0.0.18
version: 0.0.19
alias: cortex-knowledge-controllers
# from: file://../../library/cortex
- name: cortex
repository: oci://ghcr.io/cobaltcore-dev/cortex/charts
version: 0.0.18
version: 0.0.19
alias: cortex-scheduling-controllers

# Owner info adds a configmap to the kubernetes cluster with information on
Expand Down
4 changes: 2 additions & 2 deletions helm/bundles/cortex-crds/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ apiVersion: v2
name: cortex-crds
description: A Helm chart deploying Cortex CRDs.
type: application
version: 0.0.31
version: 0.0.32
appVersion: 0.1.0
dependencies:
# from: file://../../library/cortex
- name: cortex
repository: oci://ghcr.io/cobaltcore-dev/cortex/charts
version: 0.0.18
version: 0.0.19

# Owner info adds a configmap to the kubernetes cluster with information on
# the service owner. This makes it easier to find out who to contact in case
Expand Down
4 changes: 2 additions & 2 deletions helm/bundles/cortex-ironcore/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ apiVersion: v2
name: cortex-ironcore
description: A Helm chart deploying Cortex for IronCore.
type: application
version: 0.0.31
version: 0.0.32
appVersion: 0.1.0
dependencies:
# from: file://../../library/cortex
- name: cortex
repository: oci://ghcr.io/cobaltcore-dev/cortex/charts
version: 0.0.18
version: 0.0.19

# Owner info adds a configmap to the kubernetes cluster with information on
# the service owner. This makes it easier to find out who to contact in case
Expand Down
6 changes: 3 additions & 3 deletions helm/bundles/cortex-manila/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ apiVersion: v2
name: cortex-manila
description: A Helm chart deploying Cortex for Manila.
type: application
version: 0.0.31
version: 0.0.32
appVersion: 0.1.0
dependencies:
# from: file://../../library/cortex-postgres
Expand All @@ -16,12 +16,12 @@ dependencies:
# from: file://../../library/cortex
- name: cortex
repository: oci://ghcr.io/cobaltcore-dev/cortex/charts
version: 0.0.18
version: 0.0.19
alias: cortex-knowledge-controllers
# from: file://../../library/cortex
- name: cortex
repository: oci://ghcr.io/cobaltcore-dev/cortex/charts
version: 0.0.18
version: 0.0.19
alias: cortex-scheduling-controllers

# Owner info adds a configmap to the kubernetes cluster with information on
Expand Down
6 changes: 3 additions & 3 deletions helm/bundles/cortex-nova/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ apiVersion: v2
name: cortex-nova
description: A Helm chart deploying Cortex for Nova.
type: application
version: 0.0.31
version: 0.0.32
appVersion: 0.1.0
dependencies:
# from: file://../../library/cortex-postgres
Expand All @@ -16,12 +16,12 @@ dependencies:
# from: file://../../library/cortex
- name: cortex
repository: oci://ghcr.io/cobaltcore-dev/cortex/charts
version: 0.0.18
version: 0.0.19
alias: cortex-knowledge-controllers
# from: file://../../library/cortex
- name: cortex
repository: oci://ghcr.io/cobaltcore-dev/cortex/charts
version: 0.0.18
version: 0.0.19
alias: cortex-scheduling-controllers

# Owner info adds a configmap to the kubernetes cluster with information on
Expand Down
2 changes: 1 addition & 1 deletion helm/bundles/cortex-pods/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dependencies:
# from: file://../../library/cortex
- name: cortex
repository: oci://ghcr.io/cobaltcore-dev/cortex/charts
version: 0.0.18
version: 0.0.19

# Owner info adds a configmap to the kubernetes cluster with information on
# the service owner. This makes it easier to find out who to contact in case
Expand Down
4 changes: 2 additions & 2 deletions helm/library/cortex/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: v2
name: cortex
description: A Helm chart to distribute cortex.
type: application
version: 0.0.18
appVersion: "sha-35848cf3"
version: 0.0.19
appVersion: "sha-4811cd43"
icon: "https://example.com/icon.png"
dependencies: []
11 changes: 9 additions & 2 deletions pkg/multicluster/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,8 @@ func (c *Client) IndexField(ctx context.Context, obj client.Object, list client.
if err != nil {
return err
}
if err := c.ClusterForResource(gvkObj).
objCluster := c.ClusterForResource(gvkObj)
if err := objCluster.
GetCache().
IndexField(ctx, obj, field, extractValue); err != nil {
return err
Expand All @@ -353,7 +354,13 @@ func (c *Client) IndexField(ctx context.Context, obj client.Object, list client.
if err != nil {
return err
}
if err := c.ClusterForResource(gvkList).
objListCluster := c.ClusterForResource(gvkList)
// If the object and list map to the same cluster, we have already indexed
// the field above and re-defining the index will lead to an indexer conflict.
if objCluster == objListCluster {
return nil
}
if err := objListCluster.
GetCache().
IndexField(ctx, obj, field, extractValue); err != nil {
return err
Expand Down
100 changes: 100 additions & 0 deletions pkg/multicluster/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ func newFakeCluster(scheme *runtime.Scheme, objs ...client.Object) *fakeCluster
}
}

//nolint:unparam
func newFakeClusterWithCache(scheme *runtime.Scheme, fakeCache *fakeCache, objs ...client.Object) *fakeCluster {
return &fakeCluster{
fakeClient: fake.NewClientBuilder().WithScheme(scheme).WithObjects(objs...).Build(),
Expand Down Expand Up @@ -1559,3 +1560,102 @@ func TestClient_IndexField_WithRemoteClusters(t *testing.T) {
t.Errorf("expected 0 IndexField calls on home cluster, got %d", len(homeCalls))
}
}

// TestClient_IndexField_SameClusterSkipsSecondIndex tests that when object and list map to
// the same cluster, IndexField is only called once to avoid re-defining the index (which would error).
func TestClient_IndexField_SameClusterSkipsSecondIndex(t *testing.T) {
scheme := newTestScheme(t)

// Use the same cache/cluster for both object and list GVKs
remoteCache := &fakeCache{}
remoteCluster := newFakeClusterWithCache(scheme, remoteCache)

homeCache := &fakeCache{}
homeCluster := newFakeClusterWithCache(scheme, homeCache)

objGVK := schema.GroupVersionKind{
Group: "",
Version: "v1",
Kind: "ConfigMap",
}
listGVK := schema.GroupVersionKind{
Group: "",
Version: "v1",
Kind: "ConfigMapList",
}

// Both object and list GVKs point to the SAME remote cluster instance
c := &Client{
HomeCluster: homeCluster,
HomeScheme: scheme,
remoteClusters: map[schema.GroupVersionKind]cluster.Cluster{
objGVK: remoteCluster,
listGVK: remoteCluster, // Same cluster instance
},
}

ctx := context.Background()

obj := &corev1.ConfigMap{}
list := &corev1.ConfigMapList{}
field := "metadata.name"
extractValue := func(obj client.Object) []string {
return []string{obj.GetName()}
}

err := c.IndexField(ctx, obj, list, field, extractValue)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

// Key assertion: IndexField should only be called ONCE because both object
// and list resolve to the same cluster. Calling it twice would cause an error
// from re-defining the same index.
remoteCalls := remoteCache.getIndexFieldCalls()
if len(remoteCalls) != 1 {
t.Errorf("expected 1 IndexField call (skipping duplicate for same cluster), got %d", len(remoteCalls))
}

// Home cluster should not be called at all
homeCalls := homeCache.getIndexFieldCalls()
if len(homeCalls) != 0 {
t.Errorf("expected 0 IndexField calls on home cluster, got %d", len(homeCalls))
}
}

// TestClient_IndexField_HomeClusterSkipsSecondIndex tests that when both object and list
// use the home cluster (no remote clusters configured), IndexField is only called once.
func TestClient_IndexField_HomeClusterSkipsSecondIndex(t *testing.T) {
scheme := newTestScheme(t)

homeCache := &fakeCache{}
homeCluster := newFakeClusterWithCache(scheme, homeCache)

// No remote clusters configured - both object and list will use home cluster
c := &Client{
HomeCluster: homeCluster,
HomeScheme: scheme,
}

ctx := context.Background()

obj := &corev1.ConfigMap{}
list := &corev1.ConfigMapList{}
field := "metadata.name"
extractValue := func(obj client.Object) []string {
return []string{obj.GetName()}
}

err := c.IndexField(ctx, obj, list, field, extractValue)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

// Key assertion: IndexField should only be called ONCE because both object
// and list resolve to the same home cluster. Calling it twice would cause
// an error from re-defining the same index.
homeCalls := homeCache.getIndexFieldCalls()
if len(homeCalls) != 1 {
t.Errorf("expected 1 IndexField call (skipping duplicate for same home cluster), got %d", len(homeCalls))
}
}