diff --git a/charts/service-gateway-presets/README.md b/charts/service-gateway-presets/README.md
index 9265e37cd..eb03a3bfb 100644
--- a/charts/service-gateway-presets/README.md
+++ b/charts/service-gateway-presets/README.md
@@ -110,6 +110,17 @@ The following table lists the configurable parameters of the `service-gateway-pr
| chart.sourceRef.kind | | HelmRepository |
| chart.sourceRef.name | | appscode-charts-oci |
| chart.sourceRef.namespace | | kubeops |
+| cleaner.enabled | | true |
+| cleaner.registry | | ghcr.io/appscode |
+| cleaner.repository | | kubectl-nonroot |
+| cleaner.tag | | "1.34" |
+| cleaner.pullPolicy | | IfNotPresent |
+| cleaner.securityContext.allowPrivilegeEscalation | | false |
+| cleaner.securityContext.privileged | | false |
+| cleaner.securityContext.readOnlyRootFilesystem | | true |
+| cleaner.securityContext.runAsNonRoot | | true |
+| cleaner.securityContext.runAsUser | | 65534 |
+| cleaner.securityContext.seccompProfile.type | | RuntimeDefault |
Specify each parameter using the `--set key=value[,key=value]` argument to `helm upgrade -i`. For example:
diff --git a/charts/service-gateway-presets/values.openapiv3_schema.yaml b/charts/service-gateway-presets/values.openapiv3_schema.yaml
index 53f02f7a2..fc798bfaa 100644
--- a/charts/service-gateway-presets/values.openapiv3_schema.yaml
+++ b/charts/service-gateway-presets/values.openapiv3_schema.yaml
@@ -30,6 +30,97 @@ properties:
- name
- sourceRef
type: object
+ cleaner:
+ properties:
+ enabled:
+ type: boolean
+ pullPolicy:
+ type: string
+ registry:
+ type: string
+ repository:
+ type: string
+ securityContext:
+ properties:
+ allowPrivilegeEscalation:
+ type: boolean
+ appArmorProfile:
+ properties:
+ localhostProfile:
+ type: string
+ type:
+ type: string
+ required:
+ - type
+ type: object
+ capabilities:
+ properties:
+ add:
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ drop:
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ privileged:
+ type: boolean
+ procMount:
+ type: string
+ readOnlyRootFilesystem:
+ type: boolean
+ runAsGroup:
+ format: int64
+ type: integer
+ runAsNonRoot:
+ type: boolean
+ runAsUser:
+ format: int64
+ type: integer
+ seLinuxOptions:
+ properties:
+ level:
+ type: string
+ role:
+ type: string
+ type:
+ type: string
+ user:
+ type: string
+ type: object
+ seccompProfile:
+ properties:
+ localhostProfile:
+ type: string
+ type:
+ type: string
+ required:
+ - type
+ type: object
+ windowsOptions:
+ properties:
+ gmsaCredentialSpec:
+ type: string
+ gmsaCredentialSpecName:
+ type: string
+ hostProcess:
+ type: boolean
+ runAsUserName:
+ type: string
+ type: object
+ type: object
+ tag:
+ type: string
+ required:
+ - enabled
+ - pullPolicy
+ - registry
+ - repository
+ - tag
+ type: object
cluster:
properties:
tls:
@@ -4693,6 +4784,7 @@ properties:
- name
type: object
required:
+- cleaner
- cluster
- clusterMetadata
- echoserver
diff --git a/charts/service-gateway-presets/values.yaml b/charts/service-gateway-presets/values.yaml
index 0abdf198c..2d7ec1b2b 100644
--- a/charts/service-gateway-presets/values.yaml
+++ b/charts/service-gateway-presets/values.yaml
@@ -151,3 +151,20 @@ chart:
kind: HelmRepository
name: appscode-charts-oci
namespace: kubeops
+
+cleaner:
+ enabled: true
+ registry: ghcr.io/appscode
+ repository: kubectl-nonroot
+ tag: "1.34"
+ pullPolicy: IfNotPresent
+ securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop: ["ALL"]
+ privileged: false
+ readOnlyRootFilesystem: true
+ runAsNonRoot: true
+ runAsUser: 65534
+ seccompProfile:
+ type: RuntimeDefault
\ No newline at end of file
diff --git a/charts/service-gateway/README.md b/charts/service-gateway/README.md
index 85979e994..3ebead715 100644
--- a/charts/service-gateway/README.md
+++ b/charts/service-gateway/README.md
@@ -104,6 +104,17 @@ The following table lists the configurable parameters of the `service-gateway` c
| echoserver.securityContext | | {"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"runAsNonRoot":true,"runAsUser":65534,"seccompProfile":{"type":"RuntimeDefault"}} |
| vaultServer.name | Vault server name that exist on cluster | "vault" |
| vaultServer.namespace | Vault server namespace that exist on cluster | "ace" |
+| cleaner.enabled | | true |
+| cleaner.registry | | ghcr.io/appscode |
+| cleaner.repository | | kubectl-nonroot |
+| cleaner.tag | | "1.34" |
+| cleaner.pullPolicy | | IfNotPresent |
+| cleaner.securityContext.allowPrivilegeEscalation | | false |
+| cleaner.securityContext.privileged | | false |
+| cleaner.securityContext.readOnlyRootFilesystem | | true |
+| cleaner.securityContext.runAsNonRoot | | true |
+| cleaner.securityContext.runAsUser | | 65534 |
+| cleaner.securityContext.seccompProfile.type | | RuntimeDefault |
Specify each parameter using the `--set key=value[,key=value]` argument to `helm upgrade -i`. For example:
diff --git a/charts/service-gateway/templates/cleaner/job.yaml b/charts/service-gateway/templates/cleaner/job.yaml
new file mode 100644
index 000000000..af3c73cbd
--- /dev/null
+++ b/charts/service-gateway/templates/cleaner/job.yaml
@@ -0,0 +1,34 @@
+{{- if .Values.cleaner.enabled -}}
+apiVersion: batch/v1
+kind: Job
+metadata:
+ name: {{ include "service-gateway.fullname" . }}-gwclass-cleaner
+ namespace: {{ .Release.Namespace }}
+ annotations:
+ "helm.sh/hook-weight": "0"
+ "helm.sh/hook": post-delete
+ "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
+spec:
+ backoffLimit: 3
+ template:
+ spec:
+ serviceAccountName: {{ include "service-gateway.fullname" . }}-gwclass-cleaner
+ automountServiceAccountToken: true
+ containers:
+ - name: kubectl
+ {{- if eq "true" ( include "distro.openshift" . ) }}
+ securityContext:
+ {{- toYaml (omit .Values.cleaner.securityContext "runAsUser" "runAsGroup" "fsGroup" "supplementalGroups") | nindent 12 }}
+ {{- else }}
+ securityContext:
+ {{- toYaml .Values.cleaner.securityContext | nindent 12 }}
+ {{- end }}
+ image: "{{ .Values.cleaner.registry }}/{{ .Values.cleaner.repository }}:{{ .Values.cleaner.tag }}"
+ imagePullPolicy: {{ .Values.cleaner.pullPolicy }}
+ command:
+ - /bin/sh
+ - -c
+ - |
+ kubectl patch gatewayclass {{ include "tenant.name" . }} --type=merge -p '{"metadata":{"finalizers":null}}' || true
+ restartPolicy: Never
+{{- end }}
diff --git a/charts/service-gateway/templates/cleaner/rbac.yaml b/charts/service-gateway/templates/cleaner/rbac.yaml
new file mode 100644
index 000000000..8fa54a61a
--- /dev/null
+++ b/charts/service-gateway/templates/cleaner/rbac.yaml
@@ -0,0 +1,34 @@
+{{- if .Values.cleaner.enabled -}}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: {{ include "service-gateway.fullname" . }}-gwclass-cleaner-{{ .Release.Namespace }}
+ annotations:
+ "helm.sh/hook-weight": "-4"
+ "helm.sh/hook": post-delete
+ "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
+rules:
+- apiGroups:
+ - gateway.networking.k8s.io
+ resources:
+ - gatewayclasses
+ verbs: ["get", "patch"]
+---
+
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: {{ include "service-gateway.fullname" . }}-gwclass-cleaner-{{ .Release.Namespace }}
+ annotations:
+ "helm.sh/hook-weight": "-4"
+ "helm.sh/hook": post-delete
+ "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: {{ include "service-gateway.fullname" . }}-gwclass-cleaner-{{ .Release.Namespace }}
+subjects:
+- kind: ServiceAccount
+ name: {{ include "service-gateway.fullname" . }}-gwclass-cleaner
+ namespace: {{ .Release.Namespace }}
+{{- end }}
diff --git a/charts/service-gateway/templates/cleaner/serviceaccount.yaml b/charts/service-gateway/templates/cleaner/serviceaccount.yaml
new file mode 100644
index 000000000..c300c25f1
--- /dev/null
+++ b/charts/service-gateway/templates/cleaner/serviceaccount.yaml
@@ -0,0 +1,11 @@
+{{- if .Values.cleaner.enabled -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "service-gateway.fullname" . }}-gwclass-cleaner
+ namespace: {{ .Release.Namespace }}
+ annotations:
+ "helm.sh/hook-weight": "-5"
+ "helm.sh/hook": post-delete
+ "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
+{{- end }}
diff --git a/charts/service-gateway/values.openapiv3_schema.yaml b/charts/service-gateway/values.openapiv3_schema.yaml
index eb885c60a..c8a5361eb 100644
--- a/charts/service-gateway/values.openapiv3_schema.yaml
+++ b/charts/service-gateway/values.openapiv3_schema.yaml
@@ -1,4 +1,95 @@
properties:
+ cleaner:
+ properties:
+ enabled:
+ type: boolean
+ pullPolicy:
+ type: string
+ registry:
+ type: string
+ repository:
+ type: string
+ securityContext:
+ properties:
+ allowPrivilegeEscalation:
+ type: boolean
+ appArmorProfile:
+ properties:
+ localhostProfile:
+ type: string
+ type:
+ type: string
+ required:
+ - type
+ type: object
+ capabilities:
+ properties:
+ add:
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ drop:
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ privileged:
+ type: boolean
+ procMount:
+ type: string
+ readOnlyRootFilesystem:
+ type: boolean
+ runAsGroup:
+ format: int64
+ type: integer
+ runAsNonRoot:
+ type: boolean
+ runAsUser:
+ format: int64
+ type: integer
+ seLinuxOptions:
+ properties:
+ level:
+ type: string
+ role:
+ type: string
+ type:
+ type: string
+ user:
+ type: string
+ type: object
+ seccompProfile:
+ properties:
+ localhostProfile:
+ type: string
+ type:
+ type: string
+ required:
+ - type
+ type: object
+ windowsOptions:
+ properties:
+ gmsaCredentialSpec:
+ type: string
+ gmsaCredentialSpecName:
+ type: string
+ hostProcess:
+ type: boolean
+ runAsUserName:
+ type: string
+ type: object
+ type: object
+ tag:
+ type: string
+ required:
+ - enabled
+ - pullPolicy
+ - registry
+ - repository
+ - tag
+ type: object
cluster:
properties:
tls:
@@ -4677,6 +4768,7 @@ properties:
- name
type: object
required:
+- cleaner
- cluster
- clusterMetadata
- echoserver
diff --git a/charts/service-gateway/values.yaml b/charts/service-gateway/values.yaml
index c5ee38167..8fcc7a07f 100644
--- a/charts/service-gateway/values.yaml
+++ b/charts/service-gateway/values.yaml
@@ -144,3 +144,23 @@ vaultServer:
name: "vault"
# Vault server namespace that exist on cluster
namespace: "ace"
+
+# Post-delete hook that strips the GatewayClass finalizer so the chart uninstalls cleanly.
+# Disabled by default. Enable when the envoy-gateway controller is deployed as a sub-chart
+# and shuts down before it can remove the finalizer.
+cleaner:
+ enabled: true
+ registry: ghcr.io/appscode
+ repository: kubectl-nonroot
+ tag: "1.34"
+ pullPolicy: IfNotPresent
+ securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop: ["ALL"]
+ privileged: false
+ readOnlyRootFilesystem: true
+ runAsNonRoot: true
+ runAsUser: 65534
+ seccompProfile:
+ type: RuntimeDefault
diff --git a/go.mod b/go.mod
index 5474caf19..6f4fe522e 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module go.bytebuilders.dev/installer
go 1.25.6
require (
- go.bytebuilders.dev/catalog v0.0.23
+ go.bytebuilders.dev/catalog v0.0.25-0.20260626115826-a5d44c24f104
go.bytebuilders.dev/resource-model v0.4.0
go.bytebuilders.dev/ui-wizards v0.35.0
go.openviz.dev/installer v0.0.0-20260619044110-702becd1dd97
diff --git a/go.sum b/go.sum
index 5db3830a5..5f8dd5975 100644
--- a/go.sum
+++ b/go.sum
@@ -211,8 +211,8 @@ github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
go.appscode.dev/alerts v0.2.1-0.20260516020454-00c8e56b1991 h1:juyyBSMLxf/D/py8QidUT0wZUIhisivkdeCIvwXvob8=
go.appscode.dev/alerts v0.2.1-0.20260516020454-00c8e56b1991/go.mod h1:oG1OnN2JTilTTqGAHv4CCoqnvT3u0J8c7YgNny0Rj7g=
-go.bytebuilders.dev/catalog v0.0.23 h1:C2QLyWa5e32WfhhJLvXgorPwQ1LvEVqT6Ox4GSY2Rf8=
-go.bytebuilders.dev/catalog v0.0.23/go.mod h1:o+3cekrGPUeG95FPtGfDMNiX0k4Lz0vK0Bc8b4F4S9U=
+go.bytebuilders.dev/catalog v0.0.25-0.20260626115826-a5d44c24f104 h1:DDdpXghpMjyJn6Alu9i3n5FJdQtYTmIXcFn/oJAULwA=
+go.bytebuilders.dev/catalog v0.0.25-0.20260626115826-a5d44c24f104/go.mod h1:zXAS4yNzCueduM3glK0JDuPuJd2MDvCx2PtauRtzT7I=
go.bytebuilders.dev/resource-model v0.4.0 h1:wDXg4SGYn3zNRuOj17gGo0qeSE//ytdzGPSxkHa8JvA=
go.bytebuilders.dev/resource-model v0.4.0/go.mod h1:wGndjj3y+Yjh7+e8Wjc6joqzZCC16WZfKNx9adAFVkw=
go.bytebuilders.dev/ui-wizards v0.35.0 h1:/JFbHqPFP/n57Igsg54ShFFENGcROiJHv+ENnE4nMqM=
diff --git a/vendor/go.bytebuilders.dev/catalog/api/gateway/v1alpha1/gatewayconfig_types.go b/vendor/go.bytebuilders.dev/catalog/api/gateway/v1alpha1/gatewayconfig_types.go
index f5d462aa6..4a4d88627 100644
--- a/vendor/go.bytebuilders.dev/catalog/api/gateway/v1alpha1/gatewayconfig_types.go
+++ b/vendor/go.bytebuilders.dev/catalog/api/gateway/v1alpha1/gatewayconfig_types.go
@@ -45,6 +45,17 @@ type GatewaySpec struct {
Echoserver EchoserverSpec `json:"echoserver"`
// +optional
VaultServer kmapi.ObjectReference `json:"vaultServer"`
+ Cleaner CleanerSpec `json:"cleaner"`
+}
+
+type CleanerSpec struct {
+ Enabled bool `json:"enabled"`
+ Registry string `json:"registry"`
+ Repository string `json:"repository"`
+ Tag string `json:"tag"`
+ PullPolicy core.PullPolicy `json:"pullPolicy"`
+ // +optional
+ SecurityContext *core.SecurityContext `json:"securityContext,omitempty"`
}
type GatewayValues struct {
diff --git a/vendor/go.bytebuilders.dev/catalog/api/gateway/v1alpha1/zz_generated.deepcopy.go b/vendor/go.bytebuilders.dev/catalog/api/gateway/v1alpha1/zz_generated.deepcopy.go
index 7905a2873..26be9f41f 100644
--- a/vendor/go.bytebuilders.dev/catalog/api/gateway/v1alpha1/zz_generated.deepcopy.go
+++ b/vendor/go.bytebuilders.dev/catalog/api/gateway/v1alpha1/zz_generated.deepcopy.go
@@ -43,6 +43,26 @@ func (in *AzureDNSAuth) DeepCopy() *AzureDNSAuth {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *CleanerSpec) DeepCopyInto(out *CleanerSpec) {
+ *out = *in
+ if in.SecurityContext != nil {
+ in, out := &in.SecurityContext, &out.SecurityContext
+ *out = new(v1.SecurityContext)
+ (*in).DeepCopyInto(*out)
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CleanerSpec.
+func (in *CleanerSpec) DeepCopy() *CleanerSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(CleanerSpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CloudDNSAuth) DeepCopyInto(out *CloudDNSAuth) {
*out = *in
@@ -469,6 +489,7 @@ func (in *GatewaySpec) DeepCopyInto(out *GatewaySpec) {
out.Cluster = in.Cluster
in.Echoserver.DeepCopyInto(&out.Echoserver)
out.VaultServer = in.VaultServer
+ in.Cleaner.DeepCopyInto(&out.Cleaner)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewaySpec.
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 98151e179..fd23ddfd7 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -317,7 +317,7 @@ github.com/zeebo/xxh3
## explicit; go 1.25
go.appscode.dev/alerts/apis/alerts
go.appscode.dev/alerts/apis/alerts/v1alpha1
-# go.bytebuilders.dev/catalog v0.0.23
+# go.bytebuilders.dev/catalog v0.0.25-0.20260626115826-a5d44c24f104
## explicit; go 1.25.6
go.bytebuilders.dev/catalog/api/gateway/v1alpha1
# go.bytebuilders.dev/resource-model v0.4.0