Skip to content

Commit 2cafaeb

Browse files
author
Arvind Thirumurugan
committed
crd-cleanup job
Signed-off-by: Arvind Thirumurugan <arvindth@microsoft.com>
1 parent b1eef70 commit 2cafaeb

14 files changed

Lines changed: 513 additions & 17 deletions

File tree

Makefile

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ HUB_AGENT_IMAGE_VERSION ?= $(TAG)
77
MEMBER_AGENT_IMAGE_VERSION ?= $(TAG)
88
REFRESH_TOKEN_IMAGE_VERSION ?= $(TAG)
99
CRD_INSTALLER_IMAGE_VERSION ?= $(TAG)
10+
CRD_CLEANUP_IMAGE_VERSION ?= $(TAG)
1011

1112
HUB_AGENT_IMAGE_NAME ?= hub-agent
1213
MEMBER_AGENT_IMAGE_NAME ?= member-agent
1314
REFRESH_TOKEN_IMAGE_NAME ?= refresh-token
1415
CRD_INSTALLER_IMAGE_NAME ?= crd-installer
16+
CRD_CLEANUP_IMAGE_NAME ?= crd-cleanup
1517
ARC_MEMBER_AGENT_HELMCHART_NAME = arc-member-cluster-agents-helm-chart
1618

1719
TARGET_OS ?= linux
@@ -256,6 +258,7 @@ build: generate fmt vet ## Build agent binaries
256258
go build -o bin/hubagent cmd/hubagent/main.go
257259
go build -o bin/memberagent cmd/memberagent/main.go
258260
go build -o bin/crdinstaller cmd/crdinstaller/main.go
261+
go build -o bin/crdcleanup cmd/crdcleanup/main.go
259262

260263
.PHONY: run-hubagent
261264
run-hubagent: manifests generate fmt vet ## Run hub-agent from your host
@@ -280,7 +283,7 @@ BUILDKIT_VERSION ?= v0.18.1
280283

281284
.PHONY: push
282285
push: ## Build and push all Docker images
283-
$(MAKE) OUTPUT_TYPE="type=registry" docker-build-hub-agent docker-build-member-agent docker-build-refresh-token docker-build-crd-installer
286+
$(MAKE) OUTPUT_TYPE="type=registry" docker-build-hub-agent docker-build-member-agent docker-build-refresh-token docker-build-crd-installer docker-build-crd-cleanup
284287

285288
# By default, docker buildx create will pull image moby/buildkit:buildx-stable-1 and hit the too many requests error
286289
#
@@ -360,6 +363,18 @@ docker-build-crd-installer: docker-buildx-builder
360363
--build-arg GOARCH=$(TARGET_ARCH) \
361364
--build-arg GOOS=${TARGET_OS} .
362365

366+
.PHONY: docker-build-crd-cleanup
367+
docker-build-crd-cleanup: docker-buildx-builder ## Build crd-cleanup image
368+
docker buildx build \
369+
--file docker/crd-cleanup.Dockerfile \
370+
--output=$(OUTPUT_TYPE) \
371+
--platform=$(TARGET_OS)/$(TARGET_ARCH) \
372+
--pull \
373+
--tag $(REGISTRY)/$(CRD_CLEANUP_IMAGE_NAME):$(CRD_CLEANUP_IMAGE_VERSION) \
374+
--progress=$(BUILDKIT_PROGRESS_TYPE) \
375+
--build-arg GOARCH=$(TARGET_ARCH) \
376+
--build-arg GOOS=${TARGET_OS} .
377+
363378
# Fleet Agents and Networking Agents are packaged and pushed to MCR for Arc Extension.
364379
.PHONY: helm-package-arc-member-cluster-agents
365380
helm-package-arc-member-cluster-agents:
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{{- if and .Values.crdCleanup.enabled .Values.enableV1Beta1APIs }}
2+
apiVersion: batch/v1
3+
kind: Job
4+
metadata:
5+
name: {{ include "hub-agent.fullname" . }}-crd-cleanup
6+
namespace: {{ .Values.namespace }}
7+
labels:
8+
{{- include "hub-agent.labels" . | nindent 4 }}
9+
annotations:
10+
# Run this job before helm deletes other resources
11+
"helm.sh/hook": pre-delete
12+
"helm.sh/hook-weight": "-5"
13+
"helm.sh/hook-delete-policy": hook-succeeded,hook-failed
14+
spec:
15+
ttlSecondsAfterFinished: 60
16+
activeDeadlineSeconds: 300
17+
backoffLimit: 2
18+
template:
19+
metadata:
20+
labels:
21+
{{- include "hub-agent.selectorLabels" . | nindent 8 }}
22+
spec:
23+
serviceAccountName: {{ include "hub-agent.fullname" . }}-sa
24+
restartPolicy: Never
25+
containers:
26+
- name: crd-cleanup
27+
image: "{{ .Values.crdCleanup.image.repository }}:{{ .Values.crdCleanup.image.tag }}"
28+
imagePullPolicy: {{ .Values.crdCleanup.image.pullPolicy }}
29+
args:
30+
- --mode=hub
31+
- --v={{ .Values.crdCleanup.logVerbosity }}
32+
resources:
33+
limits:
34+
cpu: 50m
35+
memory: 64Mi
36+
requests:
37+
cpu: 10m
38+
memory: 32Mi
39+
{{- end }}

charts/hub-agent/values.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ crdInstaller:
1919
tag: main
2020
logVerbosity: 2
2121

22+
# CRD cleanup job configuration.
23+
# This job cleans up CRDs when the helm chart is uninstalled.
24+
crdCleanup:
25+
enabled: false
26+
image:
27+
repository: ghcr.io/azure/fleet/crd-cleanup
28+
pullPolicy: Always
29+
tag: main
30+
logVerbosity: 2
31+
2232
logVerbosity: 5
2333

2434
enableWebhook: true
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{{- if and .Values.crdCleanup.enabled .Values.enableV1Beta1APIs }}
2+
apiVersion: batch/v1
3+
kind: Job
4+
metadata:
5+
name: {{ include "member-agent.fullname" . }}-crd-cleanup
6+
namespace: {{ .Values.namespace }}
7+
labels:
8+
{{- include "member-agent.labels" . | nindent 4 }}
9+
annotations:
10+
# Run this job before helm deletes other resources
11+
"helm.sh/hook": pre-delete
12+
"helm.sh/hook-weight": "-5"
13+
"helm.sh/hook-delete-policy": hook-succeeded,hook-failed
14+
spec:
15+
ttlSecondsAfterFinished: 60
16+
activeDeadlineSeconds: 300
17+
backoffLimit: 2
18+
template:
19+
metadata:
20+
labels:
21+
{{- include "member-agent.selectorLabels" . | nindent 8 }}
22+
spec:
23+
serviceAccountName: {{ include "member-agent.fullname" . }}-sa
24+
restartPolicy: Never
25+
containers:
26+
- name: crd-cleanup
27+
image: "{{ .Values.crdCleanup.image.repository }}:{{ .Values.crdCleanup.image.tag }}"
28+
imagePullPolicy: {{ .Values.crdCleanup.image.pullPolicy }}
29+
args:
30+
- --mode=member
31+
- --v={{ .Values.crdCleanup.logVerbosity }}
32+
resources:
33+
limits:
34+
cpu: 50m
35+
memory: 64Mi
36+
requests:
37+
cpu: 10m
38+
memory: 32Mi
39+
{{- end }}

charts/member-agent/values.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@ crdInstaller:
1414
tag: main
1515
logVerbosity: 2
1616

17+
# CRD cleanup job configuration.
18+
# This job cleans up CRDs when the helm chart is uninstalled.
19+
crdCleanup:
20+
enabled: false
21+
image:
22+
repository: ghcr.io/azure/fleet/crd-cleanup
23+
pullPolicy: Always
24+
tag: main
25+
logVerbosity: 2
26+
1727
logVerbosity: 5
1828

1929
refreshtoken:

cmd/crdcleanup/main.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
Copyright (c) Microsoft Corporation.
3+
Licensed under the MIT license.
4+
*/
5+
6+
// Package main contains the CRD cleanup job for KubeFleet.
7+
// This job cleans up all CRDs that were installed by the CRD installer
8+
// when the Fleet agents are uninstalled via Helm pre-delete hook.
9+
package main
10+
11+
import (
12+
"context"
13+
"flag"
14+
"os"
15+
16+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
17+
"k8s.io/apimachinery/pkg/labels"
18+
"k8s.io/apimachinery/pkg/runtime"
19+
"k8s.io/klog/v2"
20+
ctrl "sigs.k8s.io/controller-runtime"
21+
"sigs.k8s.io/controller-runtime/pkg/client"
22+
23+
"go.goms.io/fleet/cmd/crdinstaller/utils"
24+
)
25+
26+
var mode = flag.String("mode", "", "Mode to run in: 'hub' or 'member' (required)")
27+
28+
func main() {
29+
klog.InitFlags(nil)
30+
flag.Parse()
31+
32+
// Validate required flags.
33+
if *mode != "hub" && *mode != "member" {
34+
klog.Fatal("--mode flag must be either 'hub' or 'member'")
35+
}
36+
37+
klog.Infof("Starting CRD cleanup job in %s mode", *mode)
38+
39+
// Print all flags for debugging.
40+
flag.VisitAll(func(f *flag.Flag) {
41+
klog.V(2).InfoS("flag:", "name", f.Name, "value", f.Value)
42+
})
43+
44+
// Get Kubernetes config using controller-runtime.
45+
config := ctrl.GetConfigOrDie()
46+
47+
// Create a scheme that knows about CRD types.
48+
scheme := runtime.NewScheme()
49+
if err := apiextensionsv1.AddToScheme(scheme); err != nil {
50+
klog.Fatalf("Failed to add apiextensions scheme: %v", err)
51+
}
52+
53+
k8sClient, err := client.New(config, client.Options{
54+
Scheme: scheme,
55+
})
56+
if err != nil {
57+
klog.Fatalf("Failed to create Kubernetes client: %v", err)
58+
}
59+
60+
// Create context for cleanup operations.
61+
ctx := context.Background()
62+
63+
// Perform cleanup.
64+
if err := cleanupCRDs(ctx, k8sClient, *mode); err != nil {
65+
klog.Errorf("Failed to cleanup CRDs: %v", err)
66+
os.Exit(1)
67+
}
68+
69+
klog.Info("CRD cleanup completed successfully")
70+
}
71+
72+
// cleanupCRDs deletes all CRDs that were installed by the CRD installer for the given mode.
73+
// It uses the mode label to identify which CRDs to delete.
74+
func cleanupCRDs(ctx context.Context, k8sClient client.Client, mode string) error {
75+
// List all CRDs with both the managed label and the matching mode label.
76+
crdList := &apiextensionsv1.CustomResourceDefinitionList{}
77+
labelSelector := labels.SelectorFromSet(labels.Set{
78+
utils.CRDInstallerLabelKey: "true",
79+
utils.CRDInstallerModeLabel: mode,
80+
})
81+
82+
if err := k8sClient.List(ctx, crdList, &client.ListOptions{
83+
LabelSelector: labelSelector,
84+
}); err != nil {
85+
return err
86+
}
87+
88+
klog.Infof("Found %d CRDs to cleanup for mode %s", len(crdList.Items), mode)
89+
90+
// Delete all matching CRDs.
91+
var deletedCount int
92+
for i := range crdList.Items {
93+
crd := &crdList.Items[i]
94+
95+
klog.Infof("Deleting CRD: %s", crd.Name)
96+
if err := k8sClient.Delete(ctx, crd); err != nil {
97+
klog.Errorf("Failed to delete CRD %s: %v", crd.Name, err)
98+
// Continue with other CRDs even if one fails.
99+
continue
100+
}
101+
deletedCount++
102+
klog.Infof("Successfully deleted CRD: %s", crd.Name)
103+
}
104+
105+
klog.Infof("Cleanup complete: deleted %d CRDs", deletedCount)
106+
return nil
107+
}

0 commit comments

Comments
 (0)