From fb338992d5424c6b265902b5dfca876d533dd730 Mon Sep 17 00:00:00 2001 From: Alex J Date: Thu, 9 Apr 2026 09:24:30 +0100 Subject: [PATCH 1/6] chore: making new branch (#1478) merging personal branch to a new branch. --- helm/blueapi/Chart.yaml | 2 +- helm/blueapi/templates/configmap.yaml | 27 ++++++- helm/blueapi/templates/cronjob.yaml | 72 +++++++++++++++++++ .../blueapi/templates/tests/test-cronjob.yaml | 19 +++++ 4 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 helm/blueapi/templates/cronjob.yaml create mode 100644 helm/blueapi/templates/tests/test-cronjob.yaml diff --git a/helm/blueapi/Chart.yaml b/helm/blueapi/Chart.yaml index 08097921fb..385f69f9d1 100644 --- a/helm/blueapi/Chart.yaml +++ b/helm/blueapi/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number is incremented by the release process. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 +version: 1.13.0 # This is the version number of the application being deployed. This version number is incremented by the release process. # Versions are not expected to follow Semantic Versioning. They should reflect the version the application is using. diff --git a/helm/blueapi/templates/configmap.yaml b/helm/blueapi/templates/configmap.yaml index aa813e6485..15cfbc4d67 100644 --- a/helm/blueapi/templates/configmap.yaml +++ b/helm/blueapi/templates/configmap.yaml @@ -31,6 +31,31 @@ data: init_config.yaml: |- scratch: {{- toYaml .Values.worker.scratch | nindent 6 }} + +--- {{- end }} ---- +apiVersion: v1 +kind: ConfigMap +metadata: + name : {{include "blueapi.fullname" . }}-pvc-stamper-script +data: + time-stamper.sh: | + #!/bin/sh + # Get PVCs belonging to this blueapi release + ALL_PVC=$(kubectl get pvc -n {{ .Release.Namespace }} \ + -o jsonpath='{.items[*].metadata.name}' | tr ' ' '\n' | \ + grep "^{{ .Release.Name }}-scratch-") + # Get all PVCs currently mounted by running pods + MOUNTED_PVCS=$(kubectl get pods -n {{ .Release.Namespace }} \ + -o=jsonpath='{.items[*].spec.volumes[*].persistentVolumeClaim.claimName}' | tr ' ' '\n' | sort -u) + NOW=$(date +%s) + #loop through all the pvcs annotating ones thare are mounted or lack a last-used stamp + for pvc in $ALL_PVC; do + ANNOTATION=$(kubectl get pvc "$pvc" -n {{ .Release.Namespace }} -o=jsonpath='{.metadata.annotations.last-used}') + if [ -z "$ANNOTATION" ]; then + kubectl annotate --overwrite pvc "$pvc" -n {{ .Release.Namespace }} last-used="$NOW" + elif echo "$MOUNTED_PVCS" | grep -qx "$pvc"; then + kubectl annotate --overwrite pvc "$pvc" -n {{ .Release.Namespace }} last-used="$NOW" + fi + done diff --git a/helm/blueapi/templates/cronjob.yaml b/helm/blueapi/templates/cronjob.yaml new file mode 100644 index 0000000000..0860467d73 --- /dev/null +++ b/helm/blueapi/templates/cronjob.yaml @@ -0,0 +1,72 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "blueapi.fullname" . }}-last-used-stamper + namespace: {{ .Release.Namespace }} +automountServiceAccountToken: true +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "blueapi.fullname" . }}-last-used-stamper + namespace: {{ .Release.Namespace }} +rules: +- apiGroups: [""] + resources: ["pods", "persistentvolumeclaims"] + verbs: ["get", "list", "patch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "blueapi.fullname" . }}-last-used-stamper + namespace: {{ .Release.Namespace }} +subjects: +- kind: ServiceAccount + name: {{ include "blueapi.fullname" . }}-last-used-stamper + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: {{ include "blueapi.fullname" . }}-last-used-stamper + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: {{ include "blueapi.fullname" . }}-last-used-stamper + namespace: {{ .Release.Namespace }} +spec: + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 1 + schedule: "*/5 * * * *" + + jobTemplate: + spec: + # amount of attempts of labeling a pvc + backoffLimit: 0 + # job stops after 60 secounds + activeDeadlineSeconds: 60 + template: + spec: + serviceAccountName: {{ include "blueapi.fullname" . }}-last-used-stamper + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 12 }} + {{- end }} + + volumes: + - name : {{include "blueapi.fullname" . }}-pvc-stamper-script + configMap: + name: {{include "blueapi.fullname" . }}-pvc-stamper-script + defaultMode: 0555 + + + containers: + - name: last-used-stamper + volumeMounts: + - name: {{include "blueapi.fullname" . }}-pvc-stamper-script + mountPath: /scripts + image: bitnami/kubectl:latest + imagePullPolicy: IfNotPresent + command: ["/scripts/time-stamper.sh"] + restartPolicy: OnFailure diff --git a/helm/blueapi/templates/tests/test-cronjob.yaml b/helm/blueapi/templates/tests/test-cronjob.yaml new file mode 100644 index 0000000000..52df70cba5 --- /dev/null +++ b/helm/blueapi/templates/tests/test-cronjob.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Pod +metadata: + name: {{ include "blueapi.fullname" . }}-last-used-stamper + annotations: + "helm.sh/hook": test +spec: + serviceAccountName: {{ include "blueapi.fullname" . }}-last-used-stamper + containers: + - name: test + image: bitnami/kubectl:1.34.5 + command: ["/bin/sh", "-c"] + args: + - | + # Get a pod belonging to this release and annotate it, then verify + kubectl annotate --overwrite pod "$HOSTNAME" -n "{{ .Release.Namespace }}" last-used="$(date +%s)" + kubectl get pod "$HOSTNAME" -n "{{ .Release.Namespace }}" \ + -o jsonpath='{.metadata.annotations.last-used}' | grep -q . + restartPolicy: Never From 079426b5bd44bf20f3c77a8320df4ca0b960bf1b Mon Sep 17 00:00:00 2001 From: Alex J Date: Thu, 9 Apr 2026 09:35:18 +0100 Subject: [PATCH 2/6] Add conditional cronjob and increase backoff limit --- helm/blueapi/templates/cronjob.yaml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/helm/blueapi/templates/cronjob.yaml b/helm/blueapi/templates/cronjob.yaml index 0860467d73..52f5849414 100644 --- a/helm/blueapi/templates/cronjob.yaml +++ b/helm/blueapi/templates/cronjob.yaml @@ -1,3 +1,4 @@ +{{- if .Values.timeStampCron.enabled }} apiVersion: v1 kind: ServiceAccount metadata: @@ -43,7 +44,7 @@ spec: jobTemplate: spec: # amount of attempts of labeling a pvc - backoffLimit: 0 + backoffLimit: 3 # job stops after 60 secounds activeDeadlineSeconds: 60 template: @@ -63,6 +64,11 @@ spec: containers: - name: last-used-stamper + env: + - name: RELEASE_NAME + value: {{ .Release.Name }} + - name: RELEASE_NAMESPACE + value: {{ .Release.Namespace }} volumeMounts: - name: {{include "blueapi.fullname" . }}-pvc-stamper-script mountPath: /scripts @@ -70,3 +76,4 @@ spec: imagePullPolicy: IfNotPresent command: ["/scripts/time-stamper.sh"] restartPolicy: OnFailure +{{- end }} From 33726a6cbcfb055d55cb293ef9a418764b4747b3 Mon Sep 17 00:00:00 2001 From: Alex J Date: Thu, 9 Apr 2026 09:35:42 +0100 Subject: [PATCH 3/6] Refactor time-stamper.sh script inclusion in ConfigMap --- helm/blueapi/templates/configmap.yaml | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/helm/blueapi/templates/configmap.yaml b/helm/blueapi/templates/configmap.yaml index 15cfbc4d67..2c834bb31a 100644 --- a/helm/blueapi/templates/configmap.yaml +++ b/helm/blueapi/templates/configmap.yaml @@ -35,27 +35,14 @@ data: --- {{- end }} +--- +{{- if .Values.timeStampCron.enabled }} apiVersion: v1 kind: ConfigMap metadata: name : {{include "blueapi.fullname" . }}-pvc-stamper-script data: - time-stamper.sh: | - #!/bin/sh - # Get PVCs belonging to this blueapi release - ALL_PVC=$(kubectl get pvc -n {{ .Release.Namespace }} \ - -o jsonpath='{.items[*].metadata.name}' | tr ' ' '\n' | \ - grep "^{{ .Release.Name }}-scratch-") - # Get all PVCs currently mounted by running pods - MOUNTED_PVCS=$(kubectl get pods -n {{ .Release.Namespace }} \ - -o=jsonpath='{.items[*].spec.volumes[*].persistentVolumeClaim.claimName}' | tr ' ' '\n' | sort -u) - NOW=$(date +%s) - #loop through all the pvcs annotating ones thare are mounted or lack a last-used stamp - for pvc in $ALL_PVC; do - ANNOTATION=$(kubectl get pvc "$pvc" -n {{ .Release.Namespace }} -o=jsonpath='{.metadata.annotations.last-used}') - if [ -z "$ANNOTATION" ]; then - kubectl annotate --overwrite pvc "$pvc" -n {{ .Release.Namespace }} last-used="$NOW" - elif echo "$MOUNTED_PVCS" | grep -qx "$pvc"; then - kubectl annotate --overwrite pvc "$pvc" -n {{ .Release.Namespace }} last-used="$NOW" - fi - done + {{- $files := .Files }} + time-stamper.sh: |- +{{ $files.Get "files/scripts/time-stamper.sh" | indent 4 }} +{{- end }} From a88fa5dad36f1ee6e15d6fa93661adf38c552138 Mon Sep 17 00:00:00 2001 From: Alex J Date: Thu, 9 Apr 2026 10:56:23 +0100 Subject: [PATCH 4/6] Time stamper cron (#1479) --- helm/blueapi/README.md | 1 + helm/blueapi/files/scripts/time-stamper.sh | 20 ++++++++++++++++++++ helm/blueapi/values.schema.json | 8 ++++++++ helm/blueapi/values.yaml | 3 +++ 4 files changed, 32 insertions(+) create mode 100644 helm/blueapi/files/scripts/time-stamper.sh diff --git a/helm/blueapi/README.md b/helm/blueapi/README.md index 3862290fb8..41ccb8827b 100644 --- a/helm/blueapi/README.md +++ b/helm/blueapi/README.md @@ -44,6 +44,7 @@ A Helm chart deploying a worker pod that runs Bluesky plans | serviceAccount.create | bool | `false` | | | serviceAccount.name | string | `""` | | | startupProbe | object | `{"failureThreshold":5,"httpGet":{"path":"/healthz","port":"http"},"periodSeconds":10}` | A more lenient livenessProbe to allow the service to start fully. This is automatically disabled when in debug mode. | +| timeStampCron.enabled | bool | `true` | | | tolerations | list | `[]` | May be required to run on specific nodes (e.g. the control machine) | | tracing | object | `{"fastapi":{"excludedURLs":"/healthz"},"otlp":{"enabled":false,"protocol":"http/protobuf","server":{"host":"http://opentelemetry-collector.tracing","port":4318}}}` | Exclude health probe requests from tracing by default to prevent spamming | | volumeMounts | list | `[{"mountPath":"/config","name":"worker-config","readOnly":true}]` | Additional volumeMounts on the output StatefulSet definition. Define how volumes are mounted to the container referenced by using the same name. | diff --git a/helm/blueapi/files/scripts/time-stamper.sh b/helm/blueapi/files/scripts/time-stamper.sh new file mode 100644 index 0000000000..027e879fd2 --- /dev/null +++ b/helm/blueapi/files/scripts/time-stamper.sh @@ -0,0 +1,20 @@ +#!/bin/sh +# Get PVCs belonging to this blueapi release +ALL_PVC=$(kubectl get pvc -n $RELEASE_NAMESPACE \ + -o jsonpath='{.items[*].metadata.name}' | tr ' ' '\n' | \ + grep "^$RELEASE_NAME-scratch-") +# Get all PVCs currently mounted by running pods +MOUNTED_PVCS=$(kubectl get pods -n $RELEASE_NAMESPACE \ + -o=jsonpath='{.items[*].spec.volumes[*].persistentVolumeClaim.claimName}' | tr ' ' '\n' | sort -u) +NOW=$(date +%s) +#loop through all the pvcs annotating ones thare are mounted or lack a last-used stamp +for pvc in $ALL_PVC; do + # Checks if Annotation for last-used is empty + ANNOTATION=$(kubectl get pvc "$pvc" -n $RELEASE_NAMESPACE -o=jsonpath='{.metadata.annotations.last-used}') + # -z checks if ANNOTATION is empty, if its empty or mounted to updates last-used else it ignores it + if [ -z "$ANNOTATION" ]; then + kubectl annotate --overwrite pvc "$pvc" -n $RELEASE_NAMESPACE last-used="$NOW" + elif echo "$MOUNTED_PVCS" | grep -qx "$pvc"; then + kubectl annotate --overwrite pvc "$pvc" -n $RELEASE_NAMESPACE last-used="$NOW" + fi +done diff --git a/helm/blueapi/values.schema.json b/helm/blueapi/values.schema.json index 3159f6713e..5bd7d0735d 100644 --- a/helm/blueapi/values.schema.json +++ b/helm/blueapi/values.schema.json @@ -292,6 +292,14 @@ } } }, + "timeStampCron": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + } + }, "tolerations": { "description": "May be required to run on specific nodes (e.g. the control machine)", "type": "array" diff --git a/helm/blueapi/values.yaml b/helm/blueapi/values.yaml index 876b37a989..9634d08596 100644 --- a/helm/blueapi/values.yaml +++ b/helm/blueapi/values.yaml @@ -224,6 +224,9 @@ initContainer: # -- Size of persistent volume size: "1Gi" +timeStampCron: + enabled: true + debug: # -- If enabled, runs debugpy, allowing port-forwarding to expose port 5678 or attached vscode instance enabled: false From 6bbaf6dc94ad831d67ccdda523e8d2c768ef447a Mon Sep 17 00:00:00 2001 From: Alex J Date: Thu, 9 Apr 2026 10:57:34 +0100 Subject: [PATCH 5/6] Change chart version from 1.13.0 to 0.1.0 --- helm/blueapi/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm/blueapi/Chart.yaml b/helm/blueapi/Chart.yaml index 385f69f9d1..08097921fb 100644 --- a/helm/blueapi/Chart.yaml +++ b/helm/blueapi/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number is incremented by the release process. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 1.13.0 +version: 0.1.0 # This is the version number of the application being deployed. This version number is incremented by the release process. # Versions are not expected to follow Semantic Versioning. They should reflect the version the application is using. From 09cc9c2ad24c4fc65543e91d7c44da1f13a56149 Mon Sep 17 00:00:00 2001 From: alexj9837 Date: Thu, 9 Apr 2026 14:32:05 +0000 Subject: [PATCH 6/6] removing not fit for purpose test --- .../blueapi/templates/tests/test-cronjob.yaml | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 helm/blueapi/templates/tests/test-cronjob.yaml diff --git a/helm/blueapi/templates/tests/test-cronjob.yaml b/helm/blueapi/templates/tests/test-cronjob.yaml deleted file mode 100644 index 52df70cba5..0000000000 --- a/helm/blueapi/templates/tests/test-cronjob.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: {{ include "blueapi.fullname" . }}-last-used-stamper - annotations: - "helm.sh/hook": test -spec: - serviceAccountName: {{ include "blueapi.fullname" . }}-last-used-stamper - containers: - - name: test - image: bitnami/kubectl:1.34.5 - command: ["/bin/sh", "-c"] - args: - - | - # Get a pod belonging to this release and annotate it, then verify - kubectl annotate --overwrite pod "$HOSTNAME" -n "{{ .Release.Namespace }}" last-used="$(date +%s)" - kubectl get pod "$HOSTNAME" -n "{{ .Release.Namespace }}" \ - -o jsonpath='{.metadata.annotations.last-used}' | grep -q . - restartPolicy: Never