Skip to content

Commit f5f978d

Browse files
committed
add example on initializing workspaces
Signed-off-by: Karol Szwaj <[email protected]> On-behalf-of: @SAP [email protected]
1 parent 52e2a54 commit f5f978d

File tree

2 files changed

+170
-7
lines changed

2 files changed

+170
-7
lines changed

examples/apiexport/main.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ package main
1919
import (
2020
"context"
2121
"fmt"
22-
"net/http"
2322
"os"
2423

2524
"github.com/spf13/pflag"
@@ -139,9 +138,3 @@ func main() {
139138
os.Exit(1)
140139
}
141140
}
142-
143-
type RoundTripperFunc func(*http.Request) (*http.Response, error)
144-
145-
func (f RoundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) {
146-
return f(r)
147-
}
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
/*
2+
Copyright 2025 The KCP 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+
"fmt"
22+
"os"
23+
"slices"
24+
25+
"github.com/spf13/pflag"
26+
27+
apisv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/apis/v1alpha1"
28+
29+
corev1alpha1 "github.com/kcp-dev/kcp/sdk/apis/core/v1alpha1"
30+
"github.com/kcp-dev/kcp/sdk/apis/tenancy/initialization"
31+
tenancyv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/tenancy/v1alpha1"
32+
"github.com/kcp-dev/multicluster-provider/initializingworkspaces"
33+
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
34+
mcbuilder "sigs.k8s.io/multicluster-runtime/pkg/builder"
35+
mcmanager "sigs.k8s.io/multicluster-runtime/pkg/manager"
36+
mcreconcile "sigs.k8s.io/multicluster-runtime/pkg/reconcile"
37+
38+
corev1 "k8s.io/api/core/v1"
39+
"k8s.io/apimachinery/pkg/util/runtime"
40+
"k8s.io/client-go/kubernetes/scheme"
41+
"k8s.io/client-go/rest"
42+
ctrl "sigs.k8s.io/controller-runtime"
43+
"sigs.k8s.io/controller-runtime/pkg/log"
44+
"sigs.k8s.io/controller-runtime/pkg/log/zap"
45+
"sigs.k8s.io/controller-runtime/pkg/manager"
46+
"sigs.k8s.io/controller-runtime/pkg/manager/signals"
47+
"sigs.k8s.io/controller-runtime/pkg/reconcile"
48+
)
49+
50+
func init() {
51+
runtime.Must(corev1alpha1.AddToScheme(scheme.Scheme))
52+
runtime.Must(tenancyv1alpha1.AddToScheme(scheme.Scheme))
53+
runtime.Must(apisv1alpha1.AddToScheme(scheme.Scheme))
54+
}
55+
56+
func main() {
57+
initializerName := "initializer:example"
58+
log.SetLogger(zap.New(zap.UseDevMode(true)))
59+
60+
ctx := signals.SetupSignalHandler()
61+
entryLog := log.Log.WithName("entrypoint")
62+
63+
var (
64+
server string
65+
provider *initializingworkspaces.Provider
66+
)
67+
68+
pflag.StringVar(&server, "server", "", "Override for kubeconfig server URL")
69+
pflag.Parse()
70+
71+
cfg := ctrl.GetConfigOrDie()
72+
cfg = rest.CopyConfig(cfg)
73+
74+
if server != "" {
75+
cfg.Host = server
76+
}
77+
78+
// Setup a Manager, note that this not yet engages clusters, only makes them available.
79+
entryLog.Info("Setting up manager")
80+
opts := manager.Options{}
81+
82+
var err error
83+
provider, err = initializingworkspaces.New(cfg, initializingworkspaces.Options{})
84+
if err != nil {
85+
entryLog.Error(err, "unable to construct cluster provider")
86+
os.Exit(1)
87+
}
88+
89+
mgr, err := mcmanager.New(cfg, provider, opts)
90+
if err != nil {
91+
entryLog.Error(err, "unable to set up overall controller manager")
92+
os.Exit(1)
93+
}
94+
95+
if err := mcbuilder.ControllerManagedBy(mgr).
96+
Named("kcp-initializer-configmap-controller").
97+
For(&corev1.ConfigMap{}).
98+
Complete(mcreconcile.Func(
99+
func(ctx context.Context, req mcreconcile.Request) (ctrl.Result, error) {
100+
log := log.FromContext(ctx).WithValues("cluster", req.ClusterName)
101+
102+
cl, err := mgr.GetCluster(ctx, req.ClusterName)
103+
if err != nil {
104+
return reconcile.Result{}, fmt.Errorf("failed to get cluster: %w", err)
105+
}
106+
client := cl.GetClient()
107+
108+
lc := &corev1alpha1.LogicalCluster{}
109+
if err := client.Get(ctx, req.NamespacedName, lc); err != nil {
110+
return reconcile.Result{}, err
111+
}
112+
113+
// check if your initializer is still set on the logicalcluster
114+
if slices.Contains(lc.Status.Initializers, corev1alpha1.LogicalClusterInitializer(initializerName)) {
115+
116+
log.Info("Starting to initialize cluster")
117+
118+
s := &corev1.ConfigMap{
119+
ObjectMeta: ctrl.ObjectMeta{
120+
Name: "kcp-initializer-cm",
121+
Namespace: req.NamespacedName.Namespace,
122+
},
123+
Data: map[string]string{
124+
"test-data": "example-value",
125+
},
126+
}
127+
if err := client.Create(ctx, s); err != nil {
128+
return reconcile.Result{}, fmt.Errorf("failed to create configmap: %w", err)
129+
}
130+
log.Info("Created ConfigMap", "name", s.Name, "uuid", s.UID)
131+
// Remove the initializer from the logical cluster status
132+
// so that it won't be processed again.
133+
134+
initializerName := corev1alpha1.LogicalClusterInitializer(initializerName)
135+
if !slices.Contains(lc.Status.Initializers, initializerName) {
136+
log.Info("Initializer already absent, skipping patch")
137+
return reconcile.Result{}, nil
138+
}
139+
log.Info("Reconciling ConfigMap", "name", s.Name, "uuid", s.UID)
140+
141+
patch := ctrlclient.MergeFrom(lc.DeepCopy())
142+
lc.Status.Initializers = initialization.EnsureInitializerAbsent(initializerName, lc.Status.Initializers)
143+
if err := client.Status().Patch(ctx, lc, patch); err != nil {
144+
return reconcile.Result{}, err
145+
}
146+
log.Info("Removed initializer from LogicalCluster status", "name", lc.Name, "uuid", lc.UID)
147+
}
148+
return reconcile.Result{}, nil
149+
},
150+
)); err != nil {
151+
entryLog.Error(err, "failed to build controller")
152+
os.Exit(1)
153+
}
154+
155+
if provider != nil {
156+
entryLog.Info("Starting provider")
157+
go func() {
158+
if err := provider.Run(ctx, mgr); err != nil {
159+
entryLog.Error(err, "unable to run provider")
160+
os.Exit(1)
161+
}
162+
}()
163+
}
164+
165+
entryLog.Info("Starting manager")
166+
if err := mgr.Start(ctx); err != nil {
167+
entryLog.Error(err, "unable to run manager")
168+
os.Exit(1)
169+
}
170+
}

0 commit comments

Comments
 (0)