Skip to content

Commit 8faa1b2

Browse files
qiujian16gnana997
andauthored
✨ Added support for about-api for cluster properties (#1006)
* Added support for about-api for cluster properties Signed-off-by: gnana997 <[email protected]> * refactored failing registration test cases Signed-off-by: gnana997 <[email protected]> * Added new fake classes and test cases Signed-off-by: gnana997 <[email protected]> * Refactored test cases and vendors Signed-off-by: gnana997 <[email protected]> * updated the open-cluster api package and updated cluster property Signed-off-by: gnana997 <[email protected]> * Refactored the pr with just registration details and crds Signed-off-by: gnana997 <[email protected]> * Fix fake client Signed-off-by: Jian Qiu <[email protected]> * Add integration test for clusterproperty Signed-off-by: Jian Qiu <[email protected]> --------- Signed-off-by: gnana997 <[email protected]> Signed-off-by: Jian Qiu <[email protected]> Co-authored-by: gnana997 <[email protected]>
1 parent 5bcfeca commit 8faa1b2

39 files changed

+2410
-40
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ require (
3939
open-cluster-management.io/addon-framework v0.12.1-0.20250407131028-9d436ffc2da7
4040
open-cluster-management.io/api v0.16.2-0.20250529024642-922ceaca4e66
4141
open-cluster-management.io/sdk-go v0.16.1-0.20250428032116-875454003818
42+
sigs.k8s.io/about-api v0.0.0-20250131010323-518069c31c03
4243
sigs.k8s.io/cluster-inventory-api v0.0.0-20240730014211-ef0154379848
4344
sigs.k8s.io/controller-runtime v0.20.2
4445
sigs.k8s.io/kube-storage-version-migrator v0.0.6-0.20230721195810-5c8923c5ff96

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,8 @@ open-cluster-management.io/api v0.16.2-0.20250529024642-922ceaca4e66 h1:al0mUH6t
491491
open-cluster-management.io/api v0.16.2-0.20250529024642-922ceaca4e66/go.mod h1:/OeqXycNBZQoe3WG6ghuWsMgsKGuMZrK8ZpsU6gWL0Y=
492492
open-cluster-management.io/sdk-go v0.16.1-0.20250428032116-875454003818 h1:b7HpdTpKPzLEoJ5UtrXCed1PjxaKOxEboJ+kG6FZudI=
493493
open-cluster-management.io/sdk-go v0.16.1-0.20250428032116-875454003818/go.mod h1:n89YVVoi5zm3KVpOyVMmTdD4rGOVSsykUtu7Ol3do3M=
494+
sigs.k8s.io/about-api v0.0.0-20250131010323-518069c31c03 h1:1ShFiMjGQOR/8jTBkmZrk1gORxnvMwm1nOy2/DbHg4U=
495+
sigs.k8s.io/about-api v0.0.0-20250131010323-518069c31c03/go.mod h1:F1pT4mK53U6F16/zuaPSYpBaR7x5Kjym6aKJJC0/DHU=
494496
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 h1:CPT0ExVicCzcpeN4baWEV2ko2Z/AsiZgEdwgcfwLgMo=
495497
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
496498
sigs.k8s.io/cluster-inventory-api v0.0.0-20240730014211-ef0154379848 h1:WYPi2PdQyZwZkHG648v2jQl6deyCgyjJ0fkLYgUJ618=
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
apiVersion: apiextensions.k8s.io/v1
2+
kind: CustomResourceDefinition
3+
metadata:
4+
annotations:
5+
api-approved.kubernetes.io: "https://github.com/kubernetes/enhancements/pull/3084"
6+
name: clusterproperties.about.k8s.io
7+
spec:
8+
group: about.k8s.io
9+
names:
10+
kind: ClusterProperty
11+
listKind: ClusterPropertyList
12+
plural: clusterproperties
13+
singular: clusterproperty
14+
scope: Cluster
15+
versions:
16+
- additionalPrinterColumns:
17+
- jsonPath: .spec.value
18+
name: value
19+
type: string
20+
- jsonPath: .metadata.creationTimestamp
21+
name: age
22+
type: date
23+
name: v1alpha1
24+
schema:
25+
openAPIV3Schema:
26+
description: ClusterProperty is the Schema for the clusterproperties API
27+
properties:
28+
apiVersion:
29+
description: |-
30+
APIVersion defines the versioned schema of this representation of an object.
31+
Servers should convert recognized schemas to the latest internal value, and
32+
may reject unrecognized values.
33+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
34+
type: string
35+
kind:
36+
description: |-
37+
Kind is a string value representing the REST resource this object represents.
38+
Servers may infer this from the endpoint the client submits requests to.
39+
Cannot be updated.
40+
In CamelCase.
41+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
42+
type: string
43+
metadata:
44+
type: object
45+
spec:
46+
description: ClusterPropertySpec defines the desired state of ClusterProperty
47+
properties:
48+
value:
49+
description: ClusterProperty value
50+
minLength: 1
51+
type: string
52+
required:
53+
- value
54+
type: object
55+
status:
56+
description: ClusterPropertyStatus defines the observed state of ClusterProperty
57+
type: object
58+
type: object
59+
served: true
60+
storage: true
61+
subresources:
62+
status: {}

pkg/registration/spoke/managedcluster/claim_reconcile.go

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"k8s.io/apimachinery/pkg/labels"
1212
"k8s.io/apimachinery/pkg/selection"
1313
"k8s.io/apimachinery/pkg/util/sets"
14+
aboutv1alpha1listers "sigs.k8s.io/about-api/pkg/generated/listers/apis/v1alpha1"
1415

1516
clusterv1alpha1listers "open-cluster-management.io/api/client/cluster/listers/cluster/v1alpha1"
1617
clusterv1 "open-cluster-management.io/api/cluster/v1"
@@ -25,14 +26,12 @@ const labelCustomizedOnly = "open-cluster-management.io/spoke-only"
2526
type claimReconcile struct {
2627
recorder events.Recorder
2728
claimLister clusterv1alpha1listers.ClusterClaimLister
29+
aboutLister aboutv1alpha1listers.ClusterPropertyLister
2830
maxCustomClusterClaims int
2931
reservedClusterClaimSuffixes []string
3032
}
3133

3234
func (r *claimReconcile) reconcile(ctx context.Context, cluster *clusterv1.ManagedCluster) (*clusterv1.ManagedCluster, reconcileState, error) {
33-
if !features.SpokeMutableFeatureGate.Enabled(ocmfeature.ClusterClaim) {
34-
return cluster, reconcileContinue, nil
35-
}
3635
// current managed cluster has not joined the hub yet, do nothing.
3736
if !meta.IsStatusConditionTrue(cluster.Status.Conditions, clusterv1.ManagedClusterConditionJoined) {
3837
r.recorder.Eventf("ManagedClusterIsNotAccepted", "Managed cluster %q does not join the hub yet", cluster.Name)
@@ -46,31 +45,61 @@ func (r *claimReconcile) reconcile(ctx context.Context, cluster *clusterv1.Manag
4645
// exposeClaims saves cluster claims fetched on managed cluster into status of the
4746
// managed cluster on hub. Some of the customized claims might not be exposed once
4847
// the total number of the claims exceeds the value of `cluster-claims-max`.
49-
func (r *claimReconcile) exposeClaims(ctx context.Context, cluster *clusterv1.ManagedCluster) error {
48+
func (r *claimReconcile) exposeClaims(_ context.Context, cluster *clusterv1.ManagedCluster) error {
5049
var reservedClaims, customClaims []clusterv1.ManagedClusterClaim
50+
var clusterClaims []*clusterv1alpha1.ClusterClaim
51+
claimsMap := map[string]clusterv1.ManagedClusterClaim{}
5152

5253
// clusterClaim with label `open-cluster-management.io/spoke-only` will not be synced to managedCluster.Status at hub.
53-
requirement, _ := labels.NewRequirement(labelCustomizedOnly, selection.DoesNotExist, []string{})
54-
selector := labels.NewSelector().Add(*requirement)
55-
clusterClaims, err := r.claimLister.List(selector)
54+
requirement, err := labels.NewRequirement(labelCustomizedOnly, selection.DoesNotExist, []string{})
5655
if err != nil {
57-
return fmt.Errorf("unable to list cluster claims: %w", err)
56+
return err
57+
}
58+
selector := labels.NewSelector().Add(*requirement)
59+
60+
if features.SpokeMutableFeatureGate.Enabled(ocmfeature.ClusterProperty) {
61+
clusterProperties, err := r.aboutLister.List(selector)
62+
if err != nil {
63+
return fmt.Errorf("unable to list cluster properties: %w", err)
64+
}
65+
66+
for _, property := range clusterProperties {
67+
claimsMap[property.Name] = clusterv1.ManagedClusterClaim{
68+
Name: property.Name,
69+
Value: property.Spec.Value,
70+
}
71+
}
72+
}
73+
74+
if features.SpokeMutableFeatureGate.Enabled(ocmfeature.ClusterClaim) {
75+
clusterClaims, err = r.claimLister.List(selector)
76+
if err != nil {
77+
return fmt.Errorf("unable to list cluster claims: %w", err)
78+
}
79+
80+
for _, claim := range clusterClaims {
81+
// if the claim has the same name with the property, ignore it.
82+
if _, ok := claimsMap[claim.Name]; !ok {
83+
claimsMap[claim.Name] = clusterv1.ManagedClusterClaim{
84+
Name: claim.Name,
85+
Value: claim.Spec.Value,
86+
}
87+
}
88+
}
5889
}
5990

6091
// check if the cluster claim is one of the reserved claims or has a reserved suffix.
6192
// if so, it will be treated as a reserved claim and will always be exposed.
6293
reservedClaimNames := sets.New(clusterv1alpha1.ReservedClusterClaimNames[:]...)
6394
reservedClaimSuffixes := sets.New(r.reservedClusterClaimSuffixes...)
64-
for _, clusterClaim := range clusterClaims {
65-
managedClusterClaim := clusterv1.ManagedClusterClaim{
66-
Name: clusterClaim.Name,
67-
Value: clusterClaim.Spec.Value,
68-
}
6995

96+
for _, managedClusterClaim := range claimsMap {
7097
if matchReservedClaims(reservedClaimNames, reservedClaimSuffixes, managedClusterClaim) {
7198
reservedClaims = append(reservedClaims, managedClusterClaim)
99+
// reservedClaimNames.Insert(managedClusterClaim.Name)
72100
continue
73101
}
102+
74103
customClaims = append(customClaims, managedClusterClaim)
75104
}
76105

0 commit comments

Comments
 (0)