Skip to content

Commit 46f1ac5

Browse files
committed
✨ Add hook server into same container as operator
Add hook server into same container as operator Adding the hook server into the same container as CSO Signed-off-by: janiskemper <[email protected]>
1 parent f15f28a commit 46f1ac5

File tree

3,953 files changed

+1282
-1445179
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

3,953 files changed

+1282
-1445179
lines changed

Tiltfile

Lines changed: 4 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ settings = {
1818
"kind-cso",
1919
],
2020
"local_mode": False,
21-
"runtime_sdk": True,
2221
"deploy_cert_manager": True,
2322
"preload_images_for_kind": True,
2423
"kind_cluster_name": "cso",
@@ -110,12 +109,6 @@ def fixup_yaml_empty_arrays(yaml_str):
110109
yaml_str = yaml_str.replace("conditions: null", "conditions: []")
111110
return yaml_str.replace("storedVersions: null", "storedVersions: []")
112111

113-
tilt_dockerfile_header_runtime = """
114-
FROM docker.io/library/alpine:3.18.0
115-
WORKDIR /
116-
COPY extension/.tiltbuild/manager .
117-
"""
118-
119112
## This should have the same versions as the Dockerfile
120113
if settings.get("local_mode"):
121114
tilt_dockerfile_header_cso = """
@@ -218,53 +211,11 @@ def deploy_cso():
218211
labels = ["CSO"],
219212
)
220213

221-
def deploy_runtime_extension():
222-
yaml = str(kustomizesub("./extension/config/default"))
223-
224-
local_resource(
225-
name = "runtime-components",
226-
cmd = ["sh", "-ec", sed_cmd, yaml, "|", envsubst_cmd],
227-
labels = ["runtime"],
228-
)
229-
230-
local_resource(
231-
"runtime-manager",
232-
cmd = 'cd extension; mkdir -p .tiltbuild;CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags \'-extldflags "-static"\' -o .tiltbuild/manager main.go',
233-
deps = ["extension/handlers", "extension/main.go"],
234-
labels = ["runtime"],
235-
)
236-
237-
entrypoint = ["/manager"]
238-
extra_args = settings.get("extra_args")
239-
if extra_args:
240-
entrypoint.extend(extra_args)
241-
242-
docker_build_with_restart(
243-
ref = "ghcr.io/sovereigncloudstack/runtime-sdk-staging",
244-
context = ".",
245-
dockerfile_contents = tilt_dockerfile_header_runtime,
246-
entrypoint = entrypoint,
247-
live_update = [
248-
sync("extension/.tiltbuild/manager", "/manager"),
249-
# sync(".release", "/tmp/cluster-stacks"),
250-
],
251-
ignore = ["templates"],
252-
)
214+
def deploy_capd():
215+
yaml = './capd.yaml'
216+
cmd = "kubectl apply -f capd.yaml"
217+
local(cmd, quiet = True)
253218

254-
k8s_yaml(blob(yaml))
255-
k8s_resource(workload = "test-runtime-sdk", labels = ["runtime"])
256-
k8s_resource(
257-
objects = [
258-
"runtimesdk:namespace",
259-
# "test-runtime-sdk:deployment",
260-
"test-runtime-sdk-sa:serviceaccount",
261-
"test-runtime-sdk-role:clusterrole",
262-
"test-runtime-sdk-role-rolebinding:clusterrolebinding",
263-
"runtime-sdk-selfsigned-issuer:issuer",
264-
],
265-
new_name = "runtime-misc",
266-
labels = ["runtime"],
267-
)
268219

269220
def clusterstack():
270221
k8s_resource(objects = ["clusterstack:clusterstack"], new_name = "clusterstack", labels = ["CLUSTERSTACK"])
@@ -333,9 +284,6 @@ deploy_cso()
333284

334285
clusterstack()
335286

336-
if settings.get("runtime_sdk"):
337-
deploy_runtime_extension()
338-
339287
waitforsystem()
340288

341289
prepare_environment()

cmd/main.go

Lines changed: 94 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626

2727
//+kubebuilder:scaffold:imports
2828
csov1alpha1 "github.com/SovereignCloudStack/cluster-stack-operator/api/v1alpha1"
29+
"github.com/SovereignCloudStack/cluster-stack-operator/extension/handlers"
2930
"github.com/SovereignCloudStack/cluster-stack-operator/internal/controller"
3031
"github.com/SovereignCloudStack/cluster-stack-operator/pkg/assetsclient"
3132
"github.com/SovereignCloudStack/cluster-stack-operator/pkg/assetsclient/fake"
@@ -39,6 +40,10 @@ import (
3940
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
4041
_ "k8s.io/client-go/plugin/pkg/client/auth"
4142
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
43+
"sigs.k8s.io/cluster-api/controllers/remote"
44+
runtimecatalog "sigs.k8s.io/cluster-api/exp/runtime/catalog"
45+
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
46+
"sigs.k8s.io/cluster-api/exp/runtime/server"
4247
dockerv1beta1 "sigs.k8s.io/cluster-api/test/infrastructure/docker/api/v1beta1"
4348
"sigs.k8s.io/cluster-api/util/record"
4449
ctrl "sigs.k8s.io/controller-runtime"
@@ -51,9 +56,15 @@ import (
5156
var (
5257
scheme = runtime.NewScheme()
5358
setupLog = ctrl.Log.WithName("setup")
59+
60+
// catalog contains all information about RuntimeHooks.
61+
catalog = runtimecatalog.New()
5462
)
5563

5664
func init() {
65+
// Adds to the catalog all the RuntimeHooks defined in cluster API.
66+
_ = runtimehooksv1.AddToCatalog(catalog)
67+
5768
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
5869
utilruntime.Must(csov1alpha1.AddToScheme(scheme))
5970
utilruntime.Must(dockerv1beta1.AddToScheme(scheme))
@@ -76,6 +87,8 @@ var (
7687
localMode bool
7788
qps float64
7889
burst int
90+
hookPort int
91+
hookCertDir string
7992
)
8093

8194
func main() {
@@ -93,7 +106,8 @@ func main() {
93106
flag.BoolVar(&localMode, "local", false, "Enable local mode where no release assets will be downloaded from a remote Git repository. Useful for implementing cluster stacks.")
94107
flag.Float64Var(&qps, "qps", 50, "Enable custom query per second for kubernetes API server")
95108
flag.IntVar(&burst, "burst", 100, "Enable custom burst defines how many queries the API server will accept before enforcing the limit established by qps")
96-
109+
flag.IntVar(&hookPort, "hook-port", 9442, "hook server port")
110+
flag.StringVar(&hookCertDir, "hook-cert-dir", "/tmp/k8s-hook-server/serving-certs/", "hook cert dir, only used when hook-port is specified.")
97111
flag.Parse()
98112

99113
ctrl.SetLogger(utillog.GetDefaultLogger(logLevel))
@@ -151,7 +165,6 @@ func main() {
151165
}
152166

153167
var wg sync.WaitGroup
154-
wg.Add(1)
155168

156169
if err = (&controller.ClusterStackReconciler{
157170
Client: mgr.GetClient(),
@@ -207,14 +220,88 @@ func main() {
207220
os.Exit(1)
208221
}
209222

210-
setupLog.Info("starting manager", "version", csoversion.Get().String())
211-
if err := mgr.Start(ctx); err != nil {
212-
setupLog.Error(err, "problem running manager")
223+
// Create a http server for serving runtime extensions
224+
hookServer, err := server.New(server.Options{
225+
Catalog: catalog,
226+
Port: hookPort,
227+
CertDir: hookCertDir,
228+
})
229+
if err != nil {
230+
setupLog.Error(err, "error creating webhook server")
231+
os.Exit(1)
232+
}
233+
234+
// Lifecycle Hooks
235+
// Gets a client to access the Kubernetes cluster where this RuntimeExtension will be deployed to;
236+
// this is a requirement specific of the lifecycle hooks implementation for Cluster APIs E2E tests.
237+
restConfig.UserAgent = remote.DefaultClusterAPIUserAgent("cluster-stack-operator-extension-manager")
238+
239+
// Create the ExtensionHandlers for the lifecycle hooks
240+
lifecycleExtensionHandlers := handlers.NewExtensionHandlers(mgr.GetClient(), scheme)
241+
242+
setupLog.Info("Add extension handlers")
243+
if err := hookServer.AddExtensionHandler(server.ExtensionHandler{
244+
Hook: runtimehooksv1.BeforeClusterUpgrade,
245+
Name: "before-cluster-upgrade",
246+
HandlerFunc: lifecycleExtensionHandlers.DoBeforeClusterUpgrade,
247+
}); err != nil {
248+
setupLog.Error(err, "error adding handler")
249+
os.Exit(1)
250+
}
251+
252+
if err := hookServer.AddExtensionHandler(server.ExtensionHandler{
253+
Hook: runtimehooksv1.AfterClusterUpgrade,
254+
Name: "after-cluster-upgrade",
255+
HandlerFunc: lifecycleExtensionHandlers.DoAfterClusterUpgrade,
256+
}); err != nil {
257+
setupLog.Error(err, "error adding handler")
213258
os.Exit(1)
214259
}
215260

216-
wg.Done()
217-
// Wait for all target cluster managers to gracefully shut down.
261+
if err := hookServer.AddExtensionHandler(server.ExtensionHandler{
262+
Hook: runtimehooksv1.AfterControlPlaneInitialized,
263+
Name: "after-control-plane-initialized",
264+
HandlerFunc: lifecycleExtensionHandlers.DoAfterControlPlaneInitialized,
265+
}); err != nil {
266+
setupLog.Error(err, "error adding handler")
267+
os.Exit(1)
268+
}
269+
270+
errChan := make(chan error, 1)
271+
272+
wg.Add(1)
273+
274+
go func() {
275+
setupLog.Info("starting manager", "version", csoversion.Get().String())
276+
if err := mgr.Start(ctx); err != nil {
277+
setupLog.Error(err, "problem running manager")
278+
errChan <- err
279+
}
280+
wg.Done()
281+
}()
282+
283+
wg.Add(1)
284+
285+
go func() {
286+
setupLog.Info("starting hook server")
287+
if err := hookServer.Start(ctx); err != nil {
288+
setupLog.Error(err, "problem running hook server")
289+
errChan <- err
290+
}
291+
wg.Done()
292+
}()
293+
294+
go func() {
295+
select {
296+
case err := <-errChan:
297+
setupLog.Error(err, "Received error")
298+
os.Exit(1)
299+
case <-ctx.Done():
300+
setupLog.Info("shutting down")
301+
}
302+
}()
303+
304+
// wait for all processes to shut down
218305
wg.Wait()
219306
}
220307

config/certmanager/certificate.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,20 @@ spec:
2626
subject:
2727
organizations:
2828
- k8s-sig-cluster-lifecycle
29+
---
30+
apiVersion: cert-manager.io/v1
31+
kind: Certificate
32+
metadata:
33+
name: hook-server-serving-cert # this name should match the one appeared in kustomizeconfig.yaml
34+
namespace: system
35+
spec:
36+
dnsNames:
37+
- $(HOOK_SERVER_SERVICE_NAME).$(HOOK_SERVER_SERVICE_NAMESPACE).svc
38+
- $(HOOK_SERVER_SERVICE_NAME).$(HOOK_SERVER_SERVICE_NAMESPACE).svc.cluster.local
39+
issuerRef:
40+
kind: Issuer
41+
name: selfsigned-issuer
42+
secretName: cso-hook-server-server-cert # this secret will not be prefixed, since it's not managed by kustomize
43+
subject:
44+
organizations:
45+
- k8s-sig-cluster-lifecycle

config/default/kustomization.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ resources:
1010
- ../rbac
1111
- ../manager
1212
- ../webhook
13+
- ../hookserver
1314
- ../certmanager
1415

1516
patchesStrategicMerge:
1617
- manager_config_patch.yaml
1718
- manager_webhook_patch.yaml
19+
- manager_hookserver_patch.yaml
1820
- webhookcainjection_patch.yaml
1921
- manager_pull_policy.yaml
2022
vars:
@@ -26,21 +28,47 @@ vars:
2628
name: serving-cert # this name should match the one in certificate.yaml
2729
fieldref:
2830
fieldpath: metadata.namespace
31+
- name: HOOK_SERVER_CERTIFICATE_NAMESPACE # namespace of the certificate CR
32+
objref:
33+
kind: Certificate
34+
group: cert-manager.io
35+
version: v1
36+
name: hook-server-serving-cert # this name should match the one in certificate.yaml
37+
fieldref:
38+
fieldpath: metadata.namespace
2939
- name: CERTIFICATE_NAME
3040
objref:
3141
kind: Certificate
3242
group: cert-manager.io
3343
version: v1
3444
name: serving-cert # this name should match the one in certificate.yaml
45+
- name: HOOK_SERVER_CERTIFICATE_NAME
46+
objref:
47+
kind: Certificate
48+
group: cert-manager.io
49+
version: v1
50+
name: hook-server-serving-cert # this name should match the one in certificate.yaml
3551
- name: SERVICE_NAMESPACE # namespace of the service
3652
objref:
3753
kind: Service
3854
version: v1
3955
name: webhook-service
4056
fieldref:
4157
fieldpath: metadata.namespace
58+
- name: HOOK_SERVER_SERVICE_NAMESPACE # namespace of the service
59+
objref:
60+
kind: Service
61+
version: v1
62+
name: hook-server-svc
63+
fieldref:
64+
fieldpath: metadata.namespace
4265
- name: SERVICE_NAME
4366
objref:
4467
kind: Service
4568
version: v1
4669
name: webhook-service
70+
- name: HOOK_SERVER_SERVICE_NAME
71+
objref:
72+
kind: Service
73+
version: v1
74+
name: hook-server-svc
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: controller-manager
5+
namespace: system
6+
spec:
7+
template:
8+
spec:
9+
containers:
10+
- name: manager
11+
ports:
12+
- containerPort: 9442
13+
name: hook-server-svc
14+
protocol: TCP
15+
volumeMounts:
16+
- mountPath: /tmp/k8s-hook-server/serving-certs
17+
name: hook-server-cert
18+
readOnly: true
19+
volumes:
20+
- name: hook-server-cert
21+
secret:
22+
defaultMode: 420
23+
secretName: cso-hook-server-server-cert
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: runtime.cluster.x-k8s.io/v1alpha1
2+
kind: ExtensionConfig
3+
metadata:
4+
annotations:
5+
runtime.cluster.x-k8s.io/inject-ca-from-secret: $(HOOK_SERVER_CERTIFICATE_NAMESPACE)/$(HOOK_SERVER_CERTIFICATE_NAME)
6+
name: hook-server-extensionconfig
7+
spec:
8+
clientConfig:
9+
service:
10+
name: hook-server-svc
11+
namespace: system # Note: this assumes the test extension get deployed in the default namespace defined in its own runtime-extensions-components.yaml
12+
port: 443
13+
namespaceSelector: {}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
resources:
2+
- service.yaml
3+
- extensionconfig.yaml
4+
5+
configurations:
6+
- kustomizeconfig.yaml
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# the following config is for teaching kustomize where to look at when substituting vars.
2+
# It requires kustomize v2.1.0 or newer to work properly.
3+
nameReference:
4+
- kind: Service
5+
version: v1
6+
fieldSpecs:
7+
- kind: ExtensionConfig
8+
group: runtime.cluster.x-k8s.io
9+
path: spec/clientConfig/service/name
10+
11+
namespace:
12+
- kind: ExtensionConfig
13+
group: runtime.cluster.x-k8s.io
14+
path: spec/clientConfig/service/namespace
15+
create: true
16+
17+
varReference:
18+
- path: metadata/annotations

0 commit comments

Comments
 (0)