Skip to content

Commit d6ee8f5

Browse files
authored
Upgrage multicluster-runtime and providers frameworks (#425)
1 parent e96e779 commit d6ee8f5

37 files changed

Lines changed: 419 additions & 305 deletions

backend/config.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ import (
2222
"net/url"
2323
"strings"
2424

25-
apisv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/apis/v1alpha1"
26-
apisv1alpha2 "github.com/kcp-dev/kcp/sdk/apis/apis/v1alpha2"
2725
"github.com/kcp-dev/multicluster-provider/apiexport"
26+
apisv1alpha1 "github.com/kcp-dev/sdk/apis/apis/v1alpha1"
27+
apisv1alpha2 "github.com/kcp-dev/sdk/apis/apis/v1alpha2"
2828
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2929
"k8s.io/apimachinery/pkg/runtime"
3030
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
@@ -39,6 +39,7 @@ import (
3939

4040
kuberesources "github.com/kube-bind/kube-bind/backend/kubernetes/resources"
4141
"github.com/kube-bind/kube-bind/backend/options"
42+
kcpprovider "github.com/kube-bind/kube-bind/backend/provider/kcp"
4243
kubebindv1alpha1 "github.com/kube-bind/kube-bind/sdk/apis/kubebind/v1alpha1"
4344
kubebindv1alpha2 "github.com/kube-bind/kube-bind/sdk/apis/kubebind/v1alpha2"
4445
)
@@ -70,10 +71,6 @@ func NewConfig(options *options.CompletedOptions) (*Config, error) {
7071
config.ClientConfig = rest.CopyConfig(config.ClientConfig)
7172
config.ClientConfig = rest.AddUserAgent(config.ClientConfig, "kube-bind-backend")
7273

73-
if options.ServerURL != "" {
74-
config.ClientConfig.Host = options.ServerURL
75-
}
76-
7774
// Set up controller-runtime manager
7875
scheme := runtime.NewScheme()
7976
if err := clientgoscheme.AddToScheme(scheme); err != nil {
@@ -93,13 +90,16 @@ func NewConfig(options *options.CompletedOptions) (*Config, error) {
9390

9491
switch options.Provider {
9592
case "kcp":
93+
if options.ProviderKcp == nil {
94+
return nil, fmt.Errorf("kcp provider options must be provided when provider is kcp")
95+
}
9696
if err := apisv1alpha1.AddToScheme(scheme); err != nil {
9797
return nil, fmt.Errorf("error adding apis scheme: %w", err)
9898
}
9999
if err := apisv1alpha2.AddToScheme(scheme); err != nil {
100100
return nil, fmt.Errorf("error adding apis scheme: %w", err)
101101
}
102-
provider, err := apiexport.New(config.ClientConfig, apiexport.Options{
102+
provider, err := kcpprovider.New(config.ClientConfig, options.ProviderKcp.APIExportEndpointSliceName, apiexport.Options{
103103
Scheme: scheme,
104104
})
105105
if err != nil {

backend/oidc/oidc_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import (
2323
"strings"
2424
"testing"
2525

26-
"github.com/kcp-dev/kcp/sdk/testing/third_party/library-go/crypto"
26+
"github.com/kcp-dev/sdk/testing/third_party/library-go/crypto"
2727
"github.com/xrstf/mockoidc"
2828
)
2929

backend/options/options.go

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"k8s.io/component-base/logs"
2828
logsv1 "k8s.io/component-base/logs/api/v1"
2929

30+
providerkcp "github.com/kube-bind/kube-bind/backend/provider/kcp/options"
3031
kubebindv1alpha2 "github.com/kube-bind/kube-bind/sdk/apis/kubebind/v1alpha2"
3132
)
3233

@@ -36,14 +37,15 @@ type Options struct {
3637
Cookie *Cookie
3738
Serve *Serve
3839

40+
ProviderKcp *providerkcp.Options
41+
3942
ExtraOptions
4043
}
4144

4245
type ExtraOptions struct {
4346
KubeConfig string
4447

45-
Provider string
46-
ServerURL string
48+
Provider string
4749

4850
NamespacePrefix string
4951
PrettyName string
@@ -73,6 +75,9 @@ type completedOptions struct {
7375
Cookie *Cookie
7476
Serve *Serve
7577

78+
// Provider specific options
79+
ProviderKcp *providerkcp.CompletedOptions
80+
7681
ExtraOptions
7782
}
7883

@@ -85,23 +90,24 @@ func NewOptions() *Options {
8590
logs := logs.NewOptions()
8691
logs.Verbosity = logsv1.VerbosityLevel(2)
8792

88-
return &Options{
89-
Logs: logs,
90-
OIDC: NewOIDC(),
91-
Cookie: NewCookie(),
92-
Serve: NewServe(),
93+
opts := &Options{
94+
Logs: logs,
95+
OIDC: NewOIDC(),
96+
Cookie: NewCookie(),
97+
Serve: NewServe(),
98+
ProviderKcp: providerkcp.NewOptions(),
9399

94100
ExtraOptions: ExtraOptions{
95101
Provider: "kubernetes",
96102
NamespacePrefix: "cluster",
97103
PrettyName: "Backend",
98104
ConsumerScope: string(kubebindv1alpha2.NamespacedScope),
99105
ClusterScopedIsolation: string(kubebindv1alpha2.IsolationPrefixed),
100-
ServerURL: "",
101106
SchemaSource: CustomResourceDefinitionSource.String(),
102107
Frontend: "embedded", // Not used, but indicates to use embedded frontend using SPA.
103108
},
104109
}
110+
return opts
105111
}
106112

107113
var providerAliases = map[string]string{
@@ -135,6 +141,7 @@ func (options *Options) AddFlags(fs *pflag.FlagSet) {
135141
options.OIDC.AddFlags(fs)
136142
options.Cookie.AddFlags(fs)
137143
options.Serve.AddFlags(fs)
144+
options.ProviderKcp.AddFlags(fs)
138145

139146
fs.StringVar(&options.KubeConfig, "kubeconfig", options.KubeConfig, "path to a kubeconfig. Only required if out-of-cluster")
140147
fs.StringVar(&options.NamespacePrefix, "namespace-prefix", options.NamespacePrefix, "The prefix to use for cluster namespaces")
@@ -160,8 +167,6 @@ func (options *Options) AddFlags(fs *pflag.FlagSet) {
160167
values),
161168
)
162169

163-
fs.StringVar(&options.ServerURL, "server-url", options.ServerURL, "The URL of the backend server. If not specified, it will be derived from the kubeconfig or service account's hosts.")
164-
165170
fs.StringVar(&options.TestingAutoSelect, "testing-auto-select", options.TestingAutoSelect, "<resource>.<group> that is automatically selected on th bind screen for testing")
166171
fs.MarkHidden("testing-auto-select") //nolint:errcheck
167172
}
@@ -209,15 +214,24 @@ func (options *Options) Complete() (*CompletedOptions, error) {
209214
}
210215
options.ExternalCA = ca
211216
}
212-
return &CompletedOptions{
217+
co := &CompletedOptions{
213218
completedOptions: &completedOptions{
214219
Logs: options.Logs,
215220
OIDC: options.OIDC,
216221
Cookie: options.Cookie,
217222
Serve: options.Serve,
218223
ExtraOptions: options.ExtraOptions,
219224
},
220-
}, nil
225+
}
226+
227+
if options.Provider == "kcp" {
228+
opts, err := options.ProviderKcp.Complete()
229+
if err != nil {
230+
return nil, err
231+
}
232+
co.completedOptions.ProviderKcp = opts
233+
}
234+
return co, nil
221235
}
222236

223237
func (options *CompletedOptions) Validate() error {
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
Copyright 2025 The Kube Bind Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package options
18+
19+
import (
20+
"github.com/spf13/pflag"
21+
)
22+
23+
type Options struct {
24+
ExtraOptions
25+
}
26+
27+
type ExtraOptions struct {
28+
APIExportEndpointSliceName string
29+
}
30+
31+
type completedOptions struct {
32+
ExtraOptions
33+
}
34+
35+
type CompletedOptions struct {
36+
*completedOptions
37+
}
38+
39+
func NewOptions() *Options {
40+
return &Options{
41+
ExtraOptions: ExtraOptions{
42+
APIExportEndpointSliceName: "kube-bind.io",
43+
},
44+
}
45+
}
46+
47+
func (options *Options) AddFlags(fs *pflag.FlagSet) {
48+
fs.StringVar(&options.ExtraOptions.APIExportEndpointSliceName, "apiexport-endpoint-slice-name", options.ExtraOptions.APIExportEndpointSliceName, "name of the APIExport EndpointSlice to watch")
49+
}
50+
51+
func (options *Options) Complete() (*CompletedOptions, error) {
52+
return &CompletedOptions{
53+
completedOptions: &completedOptions{
54+
ExtraOptions: options.ExtraOptions,
55+
},
56+
}, nil
57+
}
58+
59+
func (options *CompletedOptions) Validate() error {
60+
return nil
61+
}

backend/provider/kcp/provider.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
Copyright 2025 The Kube Bind Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package kcp
18+
19+
import (
20+
"context"
21+
22+
provider "github.com/kcp-dev/multicluster-provider/apiexport"
23+
"k8s.io/client-go/rest"
24+
"sigs.k8s.io/controller-runtime/pkg/client"
25+
"sigs.k8s.io/controller-runtime/pkg/cluster"
26+
"sigs.k8s.io/multicluster-runtime/pkg/multicluster"
27+
)
28+
29+
var _ multicluster.Provider = &Provider{}
30+
var _ multicluster.ProviderRunnable = &Provider{}
31+
32+
// Provider is a [sigs.k8s.io/multicluster-runtime/pkg/multicluster.Provider] that represents each [logical cluster]
33+
// (in the kcp sense) exposed via a APIExport virtual workspace as a cluster in the [sigs.k8s.io/multicluster-runtime] sense.
34+
//
35+
// Core functionality is delegated to the apiexport.Provider, this wrapper just adds best effort path-awareness index to it via hooks.
36+
//
37+
// [logical cluster]: https://docs.kcp.io/kcp/latest/concepts/terminology/#logical-cluster
38+
type Provider struct {
39+
*provider.Provider
40+
}
41+
42+
// New is simple provider wrapper for kcp.
43+
func New(cfg *rest.Config, endpointSliceName string, options provider.Options) (*Provider, error) {
44+
p, err := provider.New(cfg, endpointSliceName, options)
45+
if err != nil {
46+
return nil, err
47+
}
48+
49+
return &Provider{
50+
Provider: p,
51+
}, nil
52+
}
53+
54+
// Get returns the cluster with the given name as a cluster.Cluster.
55+
func (p *Provider) Get(ctx context.Context, clusterName string) (cluster.Cluster, error) {
56+
return p.Provider.Get(ctx, clusterName)
57+
}
58+
59+
// IndexField adds an indexer to the clusters managed by this provider.
60+
func (p *Provider) IndexField(ctx context.Context, obj client.Object, field string, extractValue client.IndexerFunc) error {
61+
return p.Provider.IndexField(ctx, obj, field, extractValue)
62+
}
63+
64+
// Start starts the provider and blocks.
65+
func (p *Provider) Start(ctx context.Context, aware multicluster.Aware) error {
66+
return p.Provider.Start(ctx, &awareWrapper{Aware: aware})
67+
}
68+
69+
// awareWrapper wraps a multicluster.Aware to create kube-bind Cluster objects
70+
// so we could bootstrap RBAC for them.
71+
type awareWrapper struct {
72+
multicluster.Aware
73+
}
74+
75+
func (a *awareWrapper) Engage(ctx context.Context, name string, cluster cluster.Cluster) error {
76+
// TODO: Add cluster seeding here in the follow-up PRS.
77+
return a.Aware.Engage(ctx, name, cluster)
78+
}

backend/provider/provider.go

Lines changed: 0 additions & 17 deletions
This file was deleted.

cli/go.mod

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ require (
1919
github.com/spf13/pflag v1.0.9
2020
github.com/stretchr/testify v1.11.1
2121
helm.sh/helm/v3 v3.19.0
22-
k8s.io/api v0.34.0
23-
k8s.io/apiextensions-apiserver v0.34.0
24-
k8s.io/apimachinery v0.34.0
22+
k8s.io/api v0.34.2
23+
k8s.io/apiextensions-apiserver v0.34.2
24+
k8s.io/apimachinery v0.34.2
2525
k8s.io/cli-runtime v0.34.0
26-
k8s.io/client-go v0.34.0
27-
k8s.io/component-base v0.34.0
26+
k8s.io/client-go v0.34.2
27+
k8s.io/component-base v0.34.2
2828
k8s.io/klog/v2 v2.130.1
2929
sigs.k8s.io/kind v0.30.0
3030
sigs.k8s.io/yaml v1.6.0
@@ -148,7 +148,7 @@ require (
148148
gopkg.in/inf.v0 v0.9.1 // indirect
149149
gopkg.in/yaml.v3 v3.0.1 // indirect
150150
gotest.tools/v3 v3.5.2 // indirect
151-
k8s.io/apiserver v0.34.0 // indirect
151+
k8s.io/apiserver v0.34.2 // indirect
152152
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect
153153
k8s.io/kubectl v0.34.0 // indirect
154154
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect

cli/go.sum

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -444,20 +444,20 @@ gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
444444
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
445445
helm.sh/helm/v3 v3.19.0 h1:krVyCGa8fa/wzTZgqw0DUiXuRT5BPdeqE/sQXujQ22k=
446446
helm.sh/helm/v3 v3.19.0/go.mod h1:Lk/SfzN0w3a3C3o+TdAKrLwJ0wcZ//t1/SDXAvfgDdc=
447-
k8s.io/api v0.34.0 h1:L+JtP2wDbEYPUeNGbeSa/5GwFtIA662EmT2YSLOkAVE=
448-
k8s.io/api v0.34.0/go.mod h1:YzgkIzOOlhl9uwWCZNqpw6RJy9L2FK4dlJeayUoydug=
449-
k8s.io/apiextensions-apiserver v0.34.0 h1:B3hiB32jV7BcyKcMU5fDaDxk882YrJ1KU+ZSkA9Qxoc=
450-
k8s.io/apiextensions-apiserver v0.34.0/go.mod h1:hLI4GxE1BDBy9adJKxUxCEHBGZtGfIg98Q+JmTD7+g0=
451-
k8s.io/apimachinery v0.34.0 h1:eR1WO5fo0HyoQZt1wdISpFDffnWOvFLOOeJ7MgIv4z0=
452-
k8s.io/apimachinery v0.34.0/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=
453-
k8s.io/apiserver v0.34.0 h1:Z51fw1iGMqN7uJ1kEaynf2Aec1Y774PqU+FVWCFV3Jg=
454-
k8s.io/apiserver v0.34.0/go.mod h1:52ti5YhxAvewmmpVRqlASvaqxt0gKJxvCeW7ZrwgazQ=
447+
k8s.io/api v0.34.2 h1:fsSUNZhV+bnL6Aqrp6O7lMTy6o5x2C4XLjnh//8SLYY=
448+
k8s.io/api v0.34.2/go.mod h1:MMBPaWlED2a8w4RSeanD76f7opUoypY8TFYkSM+3XHw=
449+
k8s.io/apiextensions-apiserver v0.34.2 h1:WStKftnGeoKP4AZRz/BaAAEJvYp4mlZGN0UCv+uvsqo=
450+
k8s.io/apiextensions-apiserver v0.34.2/go.mod h1:398CJrsgXF1wytdaanynDpJ67zG4Xq7yj91GrmYN2SE=
451+
k8s.io/apimachinery v0.34.2 h1:zQ12Uk3eMHPxrsbUJgNF8bTauTVR2WgqJsTmwTE/NW4=
452+
k8s.io/apimachinery v0.34.2/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=
453+
k8s.io/apiserver v0.34.2 h1:2/yu8suwkmES7IzwlehAovo8dDE07cFRC7KMDb1+MAE=
454+
k8s.io/apiserver v0.34.2/go.mod h1:gqJQy2yDOB50R3JUReHSFr+cwJnL8G1dzTA0YLEqAPI=
455455
k8s.io/cli-runtime v0.34.0 h1:N2/rUlJg6TMEBgtQ3SDRJwa8XyKUizwjlOknT1mB2Cw=
456456
k8s.io/cli-runtime v0.34.0/go.mod h1:t/skRecS73Piv+J+FmWIQA2N2/rDjdYSQzEE67LUUs8=
457-
k8s.io/client-go v0.34.0 h1:YoWv5r7bsBfb0Hs2jh8SOvFbKzzxyNo0nSb0zC19KZo=
458-
k8s.io/client-go v0.34.0/go.mod h1:ozgMnEKXkRjeMvBZdV1AijMHLTh3pbACPvK7zFR+QQY=
459-
k8s.io/component-base v0.34.0 h1:bS8Ua3zlJzapklsB1dZgjEJuJEeHjj8yTu1gxE2zQX8=
460-
k8s.io/component-base v0.34.0/go.mod h1:RSCqUdvIjjrEm81epPcjQ/DS+49fADvGSCkIP3IC6vg=
457+
k8s.io/client-go v0.34.2 h1:Co6XiknN+uUZqiddlfAjT68184/37PS4QAzYvQvDR8M=
458+
k8s.io/client-go v0.34.2/go.mod h1:2VYDl1XXJsdcAxw7BenFslRQX28Dxz91U9MWKjX97fE=
459+
k8s.io/component-base v0.34.2 h1:HQRqK9x2sSAsd8+R4xxRirlTjowsg6fWCPwWYeSvogQ=
460+
k8s.io/component-base v0.34.2/go.mod h1:9xw2FHJavUHBFpiGkZoKuYZ5pdtLKe97DEByaA+hHbM=
461461
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
462462
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
463463
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA=

0 commit comments

Comments
 (0)