diff --git a/api/v1alpha4/index/cluster.go b/api/v1alpha4/index/cluster.go new file mode 100644 index 000000000000..fcd895300bc2 --- /dev/null +++ b/api/v1alpha4/index/cluster.go @@ -0,0 +1,55 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package index + +import ( + "context" + "fmt" + + "github.com/pkg/errors" + clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha4" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + // ClusterClassNameField is used by the Cluster controller to index Clusters by ClusterClass name. + ClusterClassNameField = "spec.topology.class" +) + +// ByClusterClassName adds the cluster class name index to the +// managers cache. +func ByClusterClassName(ctx context.Context, mgr ctrl.Manager) error { + if err := mgr.GetCache().IndexField(ctx, &clusterv1.Cluster{}, + ClusterClassNameField, + clusterByClassName, + ); err != nil { + return errors.Wrap(err, "error setting index field") + } + return nil +} + +func clusterByClassName(o client.Object) []string { + cluster, ok := o.(*clusterv1.Cluster) + if !ok { + panic(fmt.Sprintf("Expected Cluster but got a %T", o)) + } + if cluster.Spec.Topology != nil { + return []string{cluster.Spec.Topology.Class} + } + return nil +} diff --git a/api/v1alpha4/index/cluster_test.go b/api/v1alpha4/index/cluster_test.go new file mode 100644 index 000000000000..6976e4b1f0ba --- /dev/null +++ b/api/v1alpha4/index/cluster_test.go @@ -0,0 +1,58 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package index + +import ( + "testing" + + . "github.com/onsi/gomega" + clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha4" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func TestClusterByClassName(t *testing.T) { + testCases := []struct { + name string + object client.Object + expected []string + }{ + { + name: "when cluster has no Topology", + object: &clusterv1.Cluster{}, + expected: nil, + }, + { + name: "when cluster has a valid Topology", + object: &clusterv1.Cluster{ + Spec: clusterv1.ClusterSpec{ + Topology: &clusterv1.Topology{ + Class: "class1", + }, + }, + }, + expected: []string{"class1"}, + }, + } + + for _, test := range testCases { + t.Run(test.name, func(t *testing.T) { + g := NewWithT(t) + got := clusterByClassName(test.object) + g.Expect(got).To(Equal(test.expected)) + }) + } +} diff --git a/api/v1alpha4/index/index.go b/api/v1alpha4/index/index.go index 4a0df4375921..fdbed5663d27 100644 --- a/api/v1alpha4/index/index.go +++ b/api/v1alpha4/index/index.go @@ -20,6 +20,7 @@ package index import ( "context" + "sigs.k8s.io/cluster-api/feature" ctrl "sigs.k8s.io/controller-runtime" ) @@ -29,10 +30,15 @@ func AddDefaultIndexes(ctx context.Context, mgr ctrl.Manager) error { return err } - //nolint:revive if err := ByMachineProviderID(ctx, mgr); err != nil { return err } + if feature.Gates.Enabled(feature.ClusterTopology) { + if err := ByClusterClassName(ctx, mgr); err != nil { + return err + } + } + return nil }