Skip to content

Commit 3d3c7c8

Browse files
embikvincepristttsivanape
committed
Add fleet example for multi-cluster support
On-behalf-of: SAP [email protected] Co-authored-by: Vince Prignano <[email protected]> Co-authored-by: Dr. Stefan Schimanski <[email protected]> Co-authored-by: Iván Álvarez <[email protected]> Signed-off-by: Marvin Beckers <[email protected]>
1 parent f25bda4 commit 3d3c7c8

File tree

5 files changed

+718
-0
lines changed

5 files changed

+718
-0
lines changed

examples/fleet/cluster.go

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
Copyright 2024 The Kubernetes 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 main
18+
19+
import (
20+
"k8s.io/apimachinery/pkg/types"
21+
"sigs.k8s.io/controller-runtime/pkg/reconcile"
22+
)
23+
24+
type clusterRequest struct {
25+
reconcile.Request
26+
ClusterName string
27+
}
28+
29+
// String returns the general purpose string representation.
30+
func (cr *clusterRequest) String() string {
31+
if cr.ClusterName == "" {
32+
return cr.NamespacedName.String()
33+
}
34+
return "cluster://" + cr.ClusterName + string(types.Separator) + cr.NamespacedName.String()
35+
}

examples/fleet/eventhandler.go

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
Copyright 2024 The Kubernetes 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 main
18+
19+
import (
20+
"context"
21+
"reflect"
22+
23+
"k8s.io/apimachinery/pkg/types"
24+
"k8s.io/client-go/util/workqueue"
25+
"sigs.k8s.io/controller-runtime/pkg/client"
26+
"sigs.k8s.io/controller-runtime/pkg/cluster"
27+
"sigs.k8s.io/controller-runtime/pkg/event"
28+
"sigs.k8s.io/controller-runtime/pkg/handler"
29+
"sigs.k8s.io/controller-runtime/pkg/reconcile"
30+
)
31+
32+
var _ handler.TypedDeepCopyableEventHandler[client.Object, clusterRequest] = &EnqueueClusterRequestForObject{}
33+
34+
type EnqueueClusterRequestForObject = TypedEnqueueClusterRequestForObject[client.Object]
35+
36+
type TypedEnqueueClusterRequestForObject[object client.Object] struct {
37+
clusterName string
38+
}
39+
40+
// Create implements EventHandler.
41+
func (e *TypedEnqueueClusterRequestForObject[T]) Create(ctx context.Context, evt event.TypedCreateEvent[T], q workqueue.TypedRateLimitingInterface[clusterRequest]) {
42+
if isNil(evt.Object) {
43+
return
44+
}
45+
46+
q.Add(clusterRequest{
47+
ClusterName: e.clusterName,
48+
Request: reconcile.Request{NamespacedName: types.NamespacedName{
49+
Name: evt.Object.GetName(),
50+
Namespace: evt.Object.GetNamespace(),
51+
}}})
52+
}
53+
54+
// Update implements EventHandler.
55+
func (e *TypedEnqueueClusterRequestForObject[T]) Update(ctx context.Context, evt event.TypedUpdateEvent[T], q workqueue.TypedRateLimitingInterface[clusterRequest]) {
56+
57+
switch {
58+
case !isNil(evt.ObjectNew):
59+
q.Add(clusterRequest{
60+
ClusterName: e.clusterName,
61+
Request: reconcile.Request{NamespacedName: types.NamespacedName{
62+
Name: evt.ObjectNew.GetName(),
63+
Namespace: evt.ObjectNew.GetNamespace(),
64+
}}})
65+
case !isNil(evt.ObjectOld):
66+
q.Add(clusterRequest{
67+
ClusterName: e.clusterName,
68+
Request: reconcile.Request{NamespacedName: types.NamespacedName{
69+
Name: evt.ObjectOld.GetName(),
70+
Namespace: evt.ObjectOld.GetNamespace(),
71+
}}})
72+
}
73+
}
74+
75+
// Delete implements EventHandler.
76+
func (e *TypedEnqueueClusterRequestForObject[T]) Delete(ctx context.Context, evt event.TypedDeleteEvent[T], q workqueue.TypedRateLimitingInterface[clusterRequest]) {
77+
if isNil(evt.Object) {
78+
return
79+
}
80+
81+
q.Add(clusterRequest{
82+
ClusterName: e.clusterName,
83+
Request: reconcile.Request{NamespacedName: types.NamespacedName{
84+
Name: evt.Object.GetName(),
85+
Namespace: evt.Object.GetNamespace(),
86+
}}})
87+
}
88+
89+
// Generic implements EventHandler.
90+
func (e *TypedEnqueueClusterRequestForObject[T]) Generic(ctx context.Context, evt event.TypedGenericEvent[T], q workqueue.TypedRateLimitingInterface[clusterRequest]) {
91+
if isNil(evt.Object) {
92+
return
93+
}
94+
95+
q.Add(clusterRequest{
96+
ClusterName: e.clusterName,
97+
Request: reconcile.Request{NamespacedName: types.NamespacedName{
98+
Name: evt.Object.GetName(),
99+
Namespace: evt.Object.GetNamespace(),
100+
}}})
101+
}
102+
103+
func (e *TypedEnqueueClusterRequestForObject[T]) DeepCopyFor(c cluster.Cluster) handler.TypedDeepCopyableEventHandler[T, clusterRequest] {
104+
if e == nil {
105+
return nil
106+
}
107+
108+
out := new(TypedEnqueueClusterRequestForObject[T])
109+
*out = *e
110+
out.clusterName = c.Name()
111+
112+
return out
113+
}
114+
115+
func isNil(arg any) bool {
116+
if v := reflect.ValueOf(arg); !v.IsValid() || ((v.Kind() == reflect.Ptr ||
117+
v.Kind() == reflect.Interface ||
118+
v.Kind() == reflect.Slice ||
119+
v.Kind() == reflect.Map ||
120+
v.Kind() == reflect.Chan ||
121+
v.Kind() == reflect.Func) && v.IsNil()) {
122+
return true
123+
}
124+
return false
125+
}

examples/fleet/go.mod

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
module sigs.k8s.io/controller-runtime/examples/fleet
2+
3+
go 1.23.2
4+
5+
replace sigs.k8s.io/controller-runtime => ../..
6+
7+
require (
8+
github.com/go-logr/logr v1.4.2
9+
k8s.io/api v0.32.0-beta.0
10+
k8s.io/apimachinery v0.32.0-beta.0
11+
k8s.io/client-go v0.32.0-beta.0
12+
sigs.k8s.io/controller-runtime v0.0.0-00010101000000-000000000000
13+
sigs.k8s.io/kind v0.24.0
14+
)
15+
16+
require (
17+
github.com/BurntSushi/toml v1.4.0 // indirect
18+
github.com/alessio/shellescape v1.4.2 // indirect
19+
github.com/beorn7/perks v1.0.1 // indirect
20+
github.com/cespare/xxhash/v2 v2.3.0 // indirect
21+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
22+
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
23+
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
24+
github.com/fsnotify/fsnotify v1.7.0 // indirect
25+
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
26+
github.com/go-logr/zapr v1.3.0 // indirect
27+
github.com/go-openapi/jsonpointer v0.21.0 // indirect
28+
github.com/go-openapi/jsonreference v0.20.2 // indirect
29+
github.com/go-openapi/swag v0.23.0 // indirect
30+
github.com/gogo/protobuf v1.3.2 // indirect
31+
github.com/golang/protobuf v1.5.4 // indirect
32+
github.com/google/gnostic-models v0.6.8 // indirect
33+
github.com/google/go-cmp v0.6.0 // indirect
34+
github.com/google/gofuzz v1.2.0 // indirect
35+
github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect
36+
github.com/google/uuid v1.6.0 // indirect
37+
github.com/inconshreveable/mousetrap v1.1.0 // indirect
38+
github.com/josharian/intern v1.0.0 // indirect
39+
github.com/json-iterator/go v1.1.12 // indirect
40+
github.com/mailru/easyjson v0.7.7 // indirect
41+
github.com/mattn/go-isatty v0.0.20 // indirect
42+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
43+
github.com/modern-go/reflect2 v1.0.2 // indirect
44+
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
45+
github.com/pelletier/go-toml v1.9.5 // indirect
46+
github.com/pkg/errors v0.9.1 // indirect
47+
github.com/prometheus/client_golang v1.19.1 // indirect
48+
github.com/prometheus/client_model v0.6.1 // indirect
49+
github.com/prometheus/common v0.55.0 // indirect
50+
github.com/prometheus/procfs v0.15.1 // indirect
51+
github.com/spf13/cobra v1.8.1 // indirect
52+
github.com/spf13/pflag v1.0.5 // indirect
53+
github.com/x448/float16 v0.8.4 // indirect
54+
go.uber.org/multierr v1.11.0 // indirect
55+
go.uber.org/zap v1.27.0 // indirect
56+
golang.org/x/net v0.30.0 // indirect
57+
golang.org/x/oauth2 v0.23.0 // indirect
58+
golang.org/x/sync v0.8.0 // indirect
59+
golang.org/x/sys v0.26.0 // indirect
60+
golang.org/x/term v0.25.0 // indirect
61+
golang.org/x/text v0.19.0 // indirect
62+
golang.org/x/time v0.7.0 // indirect
63+
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
64+
google.golang.org/protobuf v1.35.1 // indirect
65+
gopkg.in/inf.v0 v0.9.1 // indirect
66+
gopkg.in/yaml.v2 v2.4.0 // indirect
67+
gopkg.in/yaml.v3 v3.0.1 // indirect
68+
k8s.io/apiextensions-apiserver v0.32.0-beta.0 // indirect
69+
k8s.io/klog/v2 v2.130.1 // indirect
70+
k8s.io/kube-openapi v0.0.0-20240827152857-f7e401e7b4c2 // indirect
71+
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
72+
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
73+
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
74+
sigs.k8s.io/yaml v1.4.0 // indirect
75+
)

0 commit comments

Comments
 (0)