Skip to content

Commit f35de4a

Browse files
authored
Migrate to Cluster Inventory API v0.2.0 (#2361)
* Migrate to Cluster Inventory API v0.2.0 Signed-off-by: kahirokunn <okinakahiro@gmail.com> * Clarify required ClusterProfile API version in logs Signed-off-by: kahirokunn <okinakahiro@gmail.com> * Refresh cluster clients when proxy settings change Signed-off-by: kahirokunn <okinakahiro@gmail.com> --------- Signed-off-by: kahirokunn <okinakahiro@gmail.com>
1 parent 07e2d0f commit f35de4a

35 files changed

Lines changed: 1539 additions & 75 deletions

‎config/charts/knative-operator/values.yaml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ knative_operator:
2222
plugins: []
2323
# plugins:
2424
# - name: secretreader
25-
# image: registry.k8s.io/cluster-inventory-api/secretreader:v0.1.3
25+
# image: registry.k8s.io/cluster-inventory-api/secretreader:v0.2.0
2626
# mountPath: /access-plugins/secretreader
2727
# - name: kubeconfig-secretreader
28-
# image: registry.k8s.io/cluster-inventory-api/kubeconfig-secretreader:v0.1.3
28+
# image: registry.k8s.io/cluster-inventory-api/kubeconfig-secretreader:v0.2.0
2929
# mountPath: /access-plugins/kubeconfig-secretreader
3030
# Polling cadence for spoke deployment readiness.
3131
remoteDeploymentsPollInterval: 10s

‎docs/development/e2e-multicluster.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ KUBECONFIG="${SPOKE_HOST_KUBECONFIG}" kubectl get nodes
4040
## 2. Install the ClusterProfile CRD on the hub
4141

4242
```bash
43-
: "${CLUSTER_INVENTORY_CRD_URL:=https://raw.githubusercontent.com/kubernetes-sigs/cluster-inventory-api/v0.1.3/config/crd/bases/multicluster.x-k8s.io_clusterprofiles.yaml}"
43+
: "${CLUSTER_INVENTORY_CRD_URL:=https://raw.githubusercontent.com/kubernetes-sigs/cluster-inventory-api/v0.2.0/config/crd/bases/multicluster.x-k8s.io_clusterprofiles.yaml}"
4444
kubectl apply -f "${CLUSTER_INVENTORY_CRD_URL}"
4545
kubectl wait --for=condition=Established --timeout=60s \
4646
crd/clusterprofiles.multicluster.x-k8s.io

‎docs/multicluster.md‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ single hub cluster. Platform administrators keep the management CRs on the hub
77
and use `spec.clusterProfileRef` to choose the spoke cluster.
88

99
The hub needs network access to each spoke API server. Connection details are
10-
resolved through the Cluster Inventory API `v1alpha1` (`ClusterProfile`), so its
10+
resolved through the Cluster Inventory API `v1alpha2` (`ClusterProfile`), so its
1111
schema and access-provider integration may change between releases.
1212

1313
> Note: if direct connectivity is not available, reverse the direction with
@@ -16,7 +16,7 @@ schema and access-provider integration may change between releases.
1616
## Prerequisites
1717

1818
- **Kubernetes 1.35+** on the hub cluster (image volumes must be available).
19-
- The **Cluster Inventory API** CRD (`ClusterProfile`) installed on the hub.
19+
- The **Cluster Inventory API** CRD (`ClusterProfile`, `v1alpha2`) installed on the hub.
2020
- Network connectivity from the operator pod to each spoke API server.
2121

2222
## Usage
@@ -83,10 +83,10 @@ knative_operator:
8383
provideClusterInfo: true
8484
plugins:
8585
- name: secretreader
86-
image: registry.k8s.io/cluster-inventory-api/secretreader:v0.1.3
86+
image: registry.k8s.io/cluster-inventory-api/secretreader:v0.2.0
8787
mountPath: /access-plugins/secretreader
8888
- name: kubeconfig-secretreader
89-
image: registry.k8s.io/cluster-inventory-api/kubeconfig-secretreader:v0.1.3
89+
image: registry.k8s.io/cluster-inventory-api/kubeconfig-secretreader:v0.2.0
9090
mountPath: /access-plugins/kubeconfig-secretreader
9191
```
9292

‎go.mod‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ require (
2929
knative.dev/pkg v0.0.0-20261026113028-cfa0ac991c5a
3030
knative.dev/reconciler-test v0.0.0-20261026141430-d915e180051b
3131
knative.dev/serving v0.51.0
32-
sigs.k8s.io/cluster-inventory-api v0.1.3
32+
sigs.k8s.io/cluster-inventory-api v0.2.0
3333
sigs.k8s.io/controller-tools v0.20.1
3434
sigs.k8s.io/yaml v1.6.0
3535
)

‎go.sum‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1863,8 +1863,8 @@ rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
18631863
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2/go.mod h1:+qG7ISXqCDVVcyO8hLn12AKVYYUjM7ftlqsqmrhMZE0=
18641864
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 h1:hSfpvjjTQXQY2Fol2CS0QHMNs/WI1MOSGzCm1KhM5ec=
18651865
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
1866-
sigs.k8s.io/cluster-inventory-api v0.1.3 h1:E7GY85hOIIPdALNdTO9Cbs2PXqjotWq6afe/NTwgCJo=
1867-
sigs.k8s.io/cluster-inventory-api v0.1.3/go.mod h1:7J3M6srZ1I4snZR+p5zxgEBdXnia3tlHo5ODMHJpEUk=
1866+
sigs.k8s.io/cluster-inventory-api v0.2.0 h1:gGbfhTLP+RWo2wZSNJNItrhsUrgVhxRlZCDizir/kF4=
1867+
sigs.k8s.io/cluster-inventory-api v0.2.0/go.mod h1:7J3M6srZ1I4snZR+p5zxgEBdXnia3tlHo5ODMHJpEUk=
18681868
sigs.k8s.io/controller-runtime v0.15.3/go.mod h1:kp4jckA4vTx281S/0Yk2LFEEQe67mjg+ev/yknv47Ds=
18691869
sigs.k8s.io/controller-runtime v0.23.3 h1:VjB/vhoPoA9l1kEKZHBMnQF33tdCLQKJtydy4iqwZ80=
18701870
sigs.k8s.io/controller-runtime v0.23.3/go.mod h1:B6COOxKptp+YaUT5q4l6LqUJTRpizbgf9KSRNdQGns0=

‎pkg/reconciler/common/clusterprofile_informer.go‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import (
2727

2828
"knative.dev/pkg/logging"
2929

30-
clusterinventoryv1alpha1 "sigs.k8s.io/cluster-inventory-api/apis/v1alpha1"
30+
clusterinventoryv1alpha2 "sigs.k8s.io/cluster-inventory-api/apis/v1alpha2"
3131
)
3232

3333
const clusterProfileResyncPeriod = 10 * time.Minute
@@ -43,35 +43,35 @@ func (c *ClusterProvider) StartInformer(ctx context.Context) {
4343

4444
logger := logging.FromContext(ctx)
4545

46-
_, err := c.ciClient.ApisV1alpha1().ClusterProfiles("").List(ctx, metav1.ListOptions{Limit: 1})
46+
_, err := c.ciClient.ApisV1alpha2().ClusterProfiles("").List(ctx, metav1.ListOptions{Limit: 1})
4747
if err != nil {
48-
logger.Infof("ClusterProfile API not available (%v); multi-cluster informer disabled", err)
48+
logger.Infof("ClusterProfile API %s not available (%v); multi-cluster informer disabled", clusterinventoryv1alpha2.GroupVersion.String(), err)
4949
return
5050
}
5151

5252
lw := toolscache.ToListWatcherWithWatchListSemantics(&toolscache.ListWatch{
5353
ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) {
54-
return c.ciClient.ApisV1alpha1().ClusterProfiles("").List(c.controllerCtx, opts)
54+
return c.ciClient.ApisV1alpha2().ClusterProfiles("").List(c.controllerCtx, opts)
5555
},
5656
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
57-
return c.ciClient.ApisV1alpha1().ClusterProfiles("").Watch(c.controllerCtx, opts)
57+
return c.ciClient.ApisV1alpha2().ClusterProfiles("").Watch(c.controllerCtx, opts)
5858
},
5959
}, c.ciClient)
6060

6161
_, informer := toolscache.NewInformerWithOptions(toolscache.InformerOptions{
6262
ListerWatcher: lw,
63-
ObjectType: &clusterinventoryv1alpha1.ClusterProfile{},
63+
ObjectType: &clusterinventoryv1alpha2.ClusterProfile{},
6464
ResyncPeriod: clusterProfileResyncPeriod,
6565
Handler: toolscache.ResourceEventHandlerFuncs{
6666
AddFunc: func(obj any) {
67-
cp, ok := obj.(*clusterinventoryv1alpha1.ClusterProfile)
67+
cp, ok := obj.(*clusterinventoryv1alpha2.ClusterProfile)
6868
if !ok {
6969
return
7070
}
7171
c.notifyListeners(cp.Namespace, cp.Name)
7272
},
7373
UpdateFunc: func(_, newObj any) {
74-
cp, ok := newObj.(*clusterinventoryv1alpha1.ClusterProfile)
74+
cp, ok := newObj.(*clusterinventoryv1alpha2.ClusterProfile)
7575
if !ok {
7676
return
7777
}
@@ -93,13 +93,13 @@ func (c *ClusterProvider) StartInformer(ctx context.Context) {
9393
}
9494

9595
func (c *ClusterProvider) handleDelete(obj any) {
96-
cp, ok := obj.(*clusterinventoryv1alpha1.ClusterProfile)
96+
cp, ok := obj.(*clusterinventoryv1alpha2.ClusterProfile)
9797
if !ok {
9898
tombstone, ok := obj.(toolscache.DeletedFinalStateUnknown)
9999
if !ok {
100100
return
101101
}
102-
cp, ok = tombstone.Obj.(*clusterinventoryv1alpha1.ClusterProfile)
102+
cp, ok = tombstone.Obj.(*clusterinventoryv1alpha2.ClusterProfile)
103103
if !ok {
104104
return
105105
}

‎pkg/reconciler/common/clusterprofile_informer_test.go‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ func TestStartInformerHandlers(t *testing.T) {
149149

150150
p.StartInformer(ctx)
151151

152-
if _, err := ci.ApisV1alpha1().ClusterProfiles("fleet").Create(ctx,
152+
if _, err := ci.ApisV1alpha2().ClusterProfiles("fleet").Create(ctx,
153153
readyClusterProfile("fleet", "worker"), metav1.CreateOptions{}); err != nil {
154154
t.Fatalf("Create ClusterProfile: %v", err)
155155
}
@@ -181,7 +181,7 @@ func TestStartInformerHandlers(t *testing.T) {
181181

182182
updated := existing.DeepCopy()
183183
updated.Labels = map[string]string{"changed": "yes"}
184-
if _, err := ci.ApisV1alpha1().ClusterProfiles("fleet").Update(ctx,
184+
if _, err := ci.ApisV1alpha2().ClusterProfiles("fleet").Update(ctx,
185185
updated, metav1.UpdateOptions{}); err != nil {
186186
t.Fatalf("Update ClusterProfile: %v", err)
187187
}
@@ -219,7 +219,7 @@ func TestStartInformerHandlers(t *testing.T) {
219219
waitForCount(t, &enqueued, 1, "initial Add event not delivered")
220220
before := enqueued.Load()
221221

222-
if err := ci.ApisV1alpha1().ClusterProfiles("fleet").Delete(ctx,
222+
if err := ci.ApisV1alpha2().ClusterProfiles("fleet").Delete(ctx,
223223
"worker", metav1.DeleteOptions{}); err != nil {
224224
t.Fatalf("Delete ClusterProfile: %v", err)
225225
}
@@ -321,7 +321,7 @@ func TestStartInformer_ContextCancel(t *testing.T) {
321321
<-settleCtx.Done()
322322
stableCount := enqueued.Load()
323323

324-
_, _ = ci.ApisV1alpha1().ClusterProfiles("fleet").Create(context.Background(),
324+
_, _ = ci.ApisV1alpha2().ClusterProfiles("fleet").Create(context.Background(),
325325
readyClusterProfile("fleet", "second"), metav1.CreateOptions{})
326326

327327
graceCtx, graceCancel := context.WithTimeout(context.Background(), 300*time.Millisecond)

‎pkg/reconciler/common/multicluster.go‎

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"errors"
2222
"fmt"
2323
"maps"
24+
"net/http"
2425
"reflect"
2526
"strings"
2627
"sync"
@@ -43,7 +44,7 @@ import (
4344
"knative.dev/operator/pkg/apis/operator/base"
4445
"knative.dev/pkg/logging"
4546

46-
clusterinventoryv1alpha1 "sigs.k8s.io/cluster-inventory-api/apis/v1alpha1"
47+
clusterinventoryv1alpha2 "sigs.k8s.io/cluster-inventory-api/apis/v1alpha2"
4748
clusterinventoryclient "sigs.k8s.io/cluster-inventory-api/client/clientset/versioned"
4849
"sigs.k8s.io/cluster-inventory-api/pkg/access"
4950
)
@@ -71,12 +72,13 @@ var (
7172

7273
// ClusterProfileAccess builds a rest.Config from a ClusterProfile.
7374
type ClusterProfileAccess interface {
74-
BuildConfigFromCP(cp *clusterinventoryv1alpha1.ClusterProfile) (*rest.Config, error)
75+
BuildConfigFromCP(cp *clusterinventoryv1alpha2.ClusterProfile) (*rest.Config, error)
7576
}
7677

7778
type NoOpClusterProfileAccess struct{}
7879

79-
func (NoOpClusterProfileAccess) BuildConfigFromCP(*clusterinventoryv1alpha1.ClusterProfile) (*rest.Config, error) {
80+
// BuildConfigFromCP returns an error because multi-cluster support is disabled.
81+
func (NoOpClusterProfileAccess) BuildConfigFromCP(*clusterinventoryv1alpha2.ClusterProfile) (*rest.Config, error) {
8082
return nil, errMulticlusterDisabled
8183
}
8284

@@ -242,7 +244,7 @@ func (c *ClusterProvider) Refresh(ctx context.Context, namespace, name string) (
242244
func (c *ClusterProvider) doRefresh(ctx context.Context, key, namespace, name string) (string, error) {
243245
logger := logging.FromContext(ctx)
244246

245-
cp, err := c.ciClient.ApisV1alpha1().ClusterProfiles(namespace).Get(
247+
cp, err := c.ciClient.ApisV1alpha2().ClusterProfiles(namespace).Get(
246248
ctx, name, metav1.GetOptions{})
247249
if err != nil {
248250
c.Remove(key)
@@ -395,22 +397,39 @@ func (c *ClusterProvider) GetOrRefresh(ctx context.Context, namespace, name stri
395397
return c.Get(ctx, key)
396398
}
397399

398-
// configEqual reports whether two rest.Configs have equivalent credentials.
400+
// configEqual reports whether two rest.Configs have equivalent connection settings.
399401
func configEqual(a, b *rest.Config) bool {
400402
return a.Host == b.Host &&
403+
a.DisableCompression == b.DisableCompression &&
401404
reflect.DeepEqual(a.TLSClientConfig, b.TLSClientConfig) &&
402405
reflect.DeepEqual(a.ExecProvider, b.ExecProvider) &&
403406
a.BearerToken == b.BearerToken &&
404407
a.BearerTokenFile == b.BearerTokenFile &&
405408
a.Username == b.Username &&
406409
a.Password == b.Password &&
407410
reflect.DeepEqual(a.AuthProvider, b.AuthProvider) &&
408-
reflect.DeepEqual(a.Impersonate, b.Impersonate)
411+
reflect.DeepEqual(a.Impersonate, b.Impersonate) &&
412+
proxyEqual(a, b)
409413
}
410414

411-
func isClusterProfileReady(cp *clusterinventoryv1alpha1.ClusterProfile) bool {
415+
// proxyEqual reports whether two rest.Configs resolve the same proxy for a.Host.
416+
// A nil Proxy uses environment settings; a non-nil Proxy can disable proxying.
417+
func proxyEqual(a, b *rest.Config) bool {
418+
if a.Proxy == nil || b.Proxy == nil {
419+
return a.Proxy == nil && b.Proxy == nil
420+
}
421+
req, err := http.NewRequest(http.MethodGet, a.Host, nil)
422+
if err != nil {
423+
return false
424+
}
425+
urlA, errA := a.Proxy(req)
426+
urlB, errB := b.Proxy(req)
427+
return errA == nil && errB == nil && reflect.DeepEqual(urlA, urlB)
428+
}
429+
430+
func isClusterProfileReady(cp *clusterinventoryv1alpha2.ClusterProfile) bool {
412431
cond := apimeta.FindStatusCondition(cp.Status.Conditions,
413-
clusterinventoryv1alpha1.ClusterConditionControlPlaneHealthy)
432+
clusterinventoryv1alpha2.ClusterConditionControlPlaneHealthy)
414433
if cond == nil {
415434
return false
416435
}

0 commit comments

Comments
 (0)