Skip to content

Commit a4b8f92

Browse files
authored
Merge pull request #29 from vdice/feat/marketplace-uninstall
feat(marketplace): pre-delete resource check and post-delete complete uninstall
2 parents 793a4f6 + 1178c01 commit a4b8f92

File tree

3 files changed

+280
-2
lines changed

3 files changed

+280
-2
lines changed

.github/workflows/marketplace-smoke-test.yaml

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ on:
66
pull_request:
77
branches: ["main"]
88

9+
env:
10+
# This version should match the (forked) version of the spin-operator sub-chart
11+
SPIN_OPERATOR_VERSION: v0.3.0
12+
913
jobs:
1014
helm-install-smoke-test:
1115
runs-on: ubuntu-22.04
@@ -31,13 +35,13 @@ jobs:
3135
3236
- name: run spin app
3337
run: |
34-
kubectl apply -f https://raw.githubusercontent.com/spinkube/spin-operator/main/config/samples/simple.yaml
38+
kubectl apply -f https://raw.githubusercontent.com/spinkube/spin-operator/${{ env.SPIN_OPERATOR_VERSION }}/config/samples/simple.yaml
3539
kubectl rollout status deployment simple-spinapp --timeout 90s
3640
kubectl get pods -A
3741
kubectl port-forward svc/simple-spinapp 8083:80 &
3842
timeout 15s bash -c 'until curl -f -vvv http://localhost:8083/hello; do sleep 2; done'
3943
40-
- name: debug
44+
- name: debug install
4145
if: failure()
4246
run: |
4347
kubectl get pods -A
@@ -51,3 +55,46 @@ jobs:
5155
5256
- name: Verify curl
5357
run: curl localhost:8083/hello
58+
59+
- name: helm delete spinkube
60+
run: |
61+
if helm delete spinkube --timeout 1m --namespace spinkube; then
62+
echo "A Spin App remains on the cluster; the helm release should not have uninstalled successfully."
63+
exit 1
64+
fi
65+
66+
kubectl logs -n spinkube -l job-name=spinkube-pre-delete | \
67+
grep -q "There are 1 SpinApps still existing on the cluster; aborting helm release deletion."
68+
69+
- name: Ensure Spin app still reachable
70+
run: curl localhost:8083/hello
71+
72+
- name: Ensure SpinKube resources still exist
73+
run: |
74+
kubectl get po -n spinkube -o name | grep -q spin-operator
75+
kubectl get po -n spinkube -o name | grep -q kwasm-operator
76+
kubectl get po -n spinkube -o name | grep -q cert-manager
77+
kubectl get crd -o name | grep -q spinapp
78+
kubectl get crd -o name | grep -q cert-manager
79+
80+
- name: Delete Spin App
81+
run: kubectl delete spinapp simple-spinapp
82+
83+
- name: helm delete spinkube
84+
run: helm delete spinkube --timeout 1m --namespace spinkube
85+
86+
- name: Verify all resources are deleted
87+
run: |
88+
timeout 15s bash -c 'until ! kubectl get crd -o name | grep -q cert-manager; do sleep 2; done'
89+
timeout 15s bash -c 'until ! kubectl get crd -o name | grep -q spinapp; do sleep 2; done'
90+
timeout 15s bash -c 'until ! kubectl get ns -o name | grep -q spinkube; do sleep 2; done'
91+
92+
- name: debug uninstall
93+
if: failure()
94+
run: |
95+
kubectl get pods -A
96+
kubectl get crd -A
97+
kubectl get ns -A
98+
kubectl describe pods -A
99+
kubectl describe crd -A
100+
kubectl describe ns -A
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
apiVersion: batch/v1
2+
kind: Job
3+
metadata:
4+
name: "{{ .Release.Name }}-post-delete"
5+
labels:
6+
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
7+
app.kubernetes.io/instance: {{ .Release.Name | quote }}
8+
app.kubernetes.io/version: {{ .Chart.AppVersion }}
9+
helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
10+
annotations:
11+
"helm.sh/hook": post-delete
12+
"helm.sh/hook-weight": "3"
13+
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
14+
spec:
15+
template:
16+
metadata:
17+
name: "{{ .Release.Name }}"
18+
labels:
19+
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
20+
app.kubernetes.io/instance: {{ .Release.Name | quote }}
21+
helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
22+
spec:
23+
restartPolicy: Never
24+
serviceAccountName: {{ .Release.Name }}-post-delete
25+
containers:
26+
- name: post-delete-job
27+
image: {{ printf "%s/%s:%s" .Values.global.azure.images.kubectl.registry .Values.global.azure.images.kubectl.image .Values.global.azure.images.kubectl.tag }}
28+
imagePullPolicy: IfNotPresent
29+
env:
30+
- name: RELEASE_NAMESPACE
31+
value: {{ .Release.Namespace }}
32+
command: ["/bin/sh", "-c"]
33+
args:
34+
- |-
35+
# Delete spin-operator CRDs
36+
kubectl delete customresourcedefinition.apiextensions.k8s.io/spinapps.core.spinoperator.dev
37+
kubectl delete customresourcedefinition.apiextensions.k8s.io/spinappexecutors.core.spinoperator.dev
38+
39+
# Delete cert-manager CRDs
40+
kubectl delete customresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io
41+
kubectl delete customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io
42+
kubectl delete customresourcedefinition.apiextensions.k8s.io/challenges.acme.cert-manager.io
43+
kubectl delete customresourcedefinition.apiextensions.k8s.io/clusterissuers.cert-manager.io
44+
kubectl delete customresourcedefinition.apiextensions.k8s.io/issuers.cert-manager.io
45+
kubectl delete customresourcedefinition.apiextensions.k8s.io/orders.acme.cert-manager.io
46+
47+
# Delete the namespace
48+
# Note: Helm won't delete the release namespace resource when deleting a release.
49+
kubectl delete ns "${RELEASE_NAMESPACE}"
50+
---
51+
apiVersion: v1
52+
kind: ServiceAccount
53+
metadata:
54+
name: {{ .Release.Name }}-post-delete
55+
labels:
56+
app.kubernetes.io/component: rbac
57+
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
58+
app.kubernetes.io/instance: {{ .Release.Name | quote }}
59+
app.kubernetes.io/version: {{ .Chart.AppVersion }}
60+
helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
61+
annotations:
62+
"helm.sh/hook": post-delete
63+
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
64+
"helm.sh/hook-weight": "1"
65+
---
66+
apiVersion: rbac.authorization.k8s.io/v1
67+
kind: ClusterRole
68+
metadata:
69+
name: {{ .Release.Name }}-post-delete-role
70+
labels:
71+
app.kubernetes.io/component: rbac
72+
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
73+
app.kubernetes.io/instance: {{ .Release.Name | quote }}
74+
app.kubernetes.io/version: {{ .Chart.AppVersion }}
75+
helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
76+
annotations:
77+
"helm.sh/hook": post-delete
78+
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
79+
"helm.sh/hook-weight": "1"
80+
rules:
81+
- apiGroups:
82+
- apiextensions.k8s.io
83+
resources:
84+
- customresourcedefinitions
85+
verbs:
86+
- list
87+
- delete
88+
- apiGroups:
89+
- ""
90+
resources:
91+
- namespaces
92+
verbs:
93+
- list
94+
- delete
95+
---
96+
apiVersion: rbac.authorization.k8s.io/v1
97+
kind: ClusterRoleBinding
98+
metadata:
99+
name: '{{ .Release.Name }}-post-delete-rolebinding'
100+
labels:
101+
app.kubernetes.io/component: rbac
102+
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
103+
app.kubernetes.io/instance: {{ .Release.Name | quote }}
104+
app.kubernetes.io/version: {{ .Chart.AppVersion }}
105+
helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
106+
annotations:
107+
"helm.sh/hook": post-delete
108+
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
109+
"helm.sh/hook-weight": "2"
110+
roleRef:
111+
apiGroup: rbac.authorization.k8s.io
112+
kind: ClusterRole
113+
name: '{{ .Release.Name }}-post-delete-role'
114+
subjects:
115+
- kind: ServiceAccount
116+
name: '{{ .Release.Name }}-post-delete'
117+
namespace: '{{ .Release.Namespace }}'
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
apiVersion: batch/v1
2+
kind: Job
3+
metadata:
4+
name: "{{ .Release.Name }}-pre-delete"
5+
labels:
6+
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
7+
app.kubernetes.io/instance: {{ .Release.Name | quote }}
8+
app.kubernetes.io/version: {{ .Chart.AppVersion }}
9+
helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
10+
annotations:
11+
"helm.sh/hook": pre-delete
12+
"helm.sh/hook-weight": "3"
13+
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
14+
spec:
15+
template:
16+
metadata:
17+
name: "{{ .Release.Name }}"
18+
labels:
19+
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
20+
app.kubernetes.io/instance: {{ .Release.Name | quote }}
21+
helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
22+
spec:
23+
restartPolicy: Never
24+
serviceAccountName: {{ .Release.Name }}-pre-delete
25+
containers:
26+
- name: pre-delete-job
27+
image: {{ printf "%s/%s:%s" .Values.global.azure.images.kubectl.registry .Values.global.azure.images.kubectl.image .Values.global.azure.images.kubectl.tag }}
28+
imagePullPolicy: IfNotPresent
29+
command: ["/bin/bash", "-c"]
30+
args:
31+
- |-
32+
# Prevent deletion if one or more SpinApps still exist on the cluster
33+
spinapp_count="$(kubectl get spinapps.core.spinoperator.dev --all-namespaces -o name | wc -l)"
34+
if [[ $spinapp_count -gt 0 ]]; then
35+
echo "There are $spinapp_count SpinApps still existing on the cluster; aborting helm release deletion."
36+
echo "Remove these resources before attempting to delete the helm release."
37+
exit 1
38+
fi
39+
40+
# Prevent deletion if one or more SpinAppExecutors still exist on the cluster
41+
# (Not counting the containerd-shim-spin SpinAppExecutor installed as part of the post-install job)
42+
spinappexecutor_count="$(kubectl get spinappexecutors.core.spinoperator.dev --all-namespaces -o name | grep -v containerd-shim-spin | wc -l)"
43+
if [[ $spinappexecutor_count -gt 0 ]]; then
44+
echo "There are $spinappexecutor_count SpinAppExecutors still existing on the cluster; aborting helm release deletion."
45+
echo "Remove these resources before attempting to delete the helm release."
46+
exit 1
47+
fi
48+
49+
# Delete the containerd-shim-spin SpinAppExecutor installed as part of the post-install-job
50+
kubectl delete --namespace default spinappexecutors.core.spinoperator.dev containerd-shim-spin
51+
---
52+
apiVersion: v1
53+
kind: ServiceAccount
54+
metadata:
55+
name: {{ .Release.Name }}-pre-delete
56+
labels:
57+
app.kubernetes.io/component: rbac
58+
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
59+
app.kubernetes.io/instance: {{ .Release.Name | quote }}
60+
app.kubernetes.io/version: {{ .Chart.AppVersion }}
61+
helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
62+
annotations:
63+
"helm.sh/hook": pre-delete
64+
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
65+
"helm.sh/hook-weight": "1"
66+
---
67+
apiVersion: rbac.authorization.k8s.io/v1
68+
kind: ClusterRole
69+
metadata:
70+
name: {{ .Release.Name }}-pre-delete-role
71+
labels:
72+
app.kubernetes.io/component: rbac
73+
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
74+
app.kubernetes.io/instance: {{ .Release.Name | quote }}
75+
app.kubernetes.io/version: {{ .Chart.AppVersion }}
76+
helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
77+
annotations:
78+
"helm.sh/hook": pre-delete
79+
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
80+
"helm.sh/hook-weight": "1"
81+
rules:
82+
- apiGroups:
83+
- core.spinoperator.dev
84+
resources:
85+
- spinapps
86+
- spinappexecutors
87+
verbs:
88+
- get
89+
- list
90+
- watch
91+
- delete
92+
---
93+
apiVersion: rbac.authorization.k8s.io/v1
94+
kind: ClusterRoleBinding
95+
metadata:
96+
name: '{{ .Release.Name }}-pre-delete-rolebinding'
97+
labels:
98+
app.kubernetes.io/component: rbac
99+
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
100+
app.kubernetes.io/instance: {{ .Release.Name | quote }}
101+
app.kubernetes.io/version: {{ .Chart.AppVersion }}
102+
helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
103+
annotations:
104+
"helm.sh/hook": pre-delete
105+
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
106+
"helm.sh/hook-weight": "2"
107+
roleRef:
108+
apiGroup: rbac.authorization.k8s.io
109+
kind: ClusterRole
110+
name: '{{ .Release.Name }}-pre-delete-role'
111+
subjects:
112+
- kind: ServiceAccount
113+
name: '{{ .Release.Name }}-pre-delete'
114+
namespace: '{{ .Release.Namespace }}'

0 commit comments

Comments
 (0)