From db8606a79ae7c4f34121f257f9559c6bfff574df Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Tue, 19 May 2026 10:03:52 +0100 Subject: [PATCH 01/27] WIP --- .../Chart.yaml | 4 +- .../templates/deployment.yaml | 68 +++++++++ .../templates/service.yaml | 6 +- helm/hyperion-supervisor/values.yaml | 14 ++ helm/hyperion/templates/deployment.yaml | 136 ------------------ helm/hyperion/templates/ingress.yaml | 23 --- helm/hyperion/templates/zocalo-config.yaml | 39 ----- helm/hyperion/values.yaml | 35 ----- 8 files changed, 87 insertions(+), 238 deletions(-) rename helm/{hyperion => hyperion-supervisor}/Chart.yaml (54%) create mode 100644 helm/hyperion-supervisor/templates/deployment.yaml rename helm/{hyperion => hyperion-supervisor}/templates/service.yaml (75%) create mode 100644 helm/hyperion-supervisor/values.yaml delete mode 100644 helm/hyperion/templates/deployment.yaml delete mode 100644 helm/hyperion/templates/ingress.yaml delete mode 100644 helm/hyperion/templates/zocalo-config.yaml delete mode 100644 helm/hyperion/values.yaml diff --git a/helm/hyperion/Chart.yaml b/helm/hyperion-supervisor/Chart.yaml similarity index 54% rename from helm/hyperion/Chart.yaml rename to helm/hyperion-supervisor/Chart.yaml index cea620e9b7..a3539a626d 100644 --- a/helm/hyperion/Chart.yaml +++ b/helm/hyperion-supervisor/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 -name: hyperion -description: Hyperion server +name: hyperion-supervisor +description: Hyperion Supervisor type: application # version of the chart version: 0.0.1 diff --git a/helm/hyperion-supervisor/templates/deployment.yaml b/helm/hyperion-supervisor/templates/deployment.yaml new file mode 100644 index 0000000000..13ded82711 --- /dev/null +++ b/helm/hyperion-supervisor/templates/deployment.yaml @@ -0,0 +1,68 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: hyperion-supervisor-deployment +spec: + selector: + matchLabels: + app: hyperion-supervisor + replicas: 1 + template: + metadata: + labels: + app: hyperion-supervisor + spec: + volumes: + # Bind some source folders for easier debugging + - name: src + hostPath: + path: "{{ .Values.application.projectDir }}/src" + type: Directory + - name: tests + hostPath: + path: "{{ .Values.application.projectDir }}/tests" + type: Directory + - name: utility-scripts + hostPath: + path: "{{ .Values.application.projectDir }}/utility_scripts" + type: Directory + - name: dodal + hostPath: + path: "{{ .Values.dodal.projectDir | clean }}" + type: Directory + - name: logs + hostPath: + type: Directory + path: "{{ .Values.application.logDir }}" + containers: + - name: hyperion + image: {{ .Values.application.imageRepository}}/mx-bluesky:{{ .Values.application.appVersion }} + resources: + limits: + cpu: "1" + memory: "1Gi" + ports: + - name: hyperion-api + containerPort: {{ .Values.application.containerPort }} + protocol: TCP + env: + - name: LOG_DIR + value: /var/log/bluesky + - name: BEAMLINE + value: "{{ .Values.application.beamline }}" + readinessProbe: + exec: + command: [ "/app/hyperion/utility_scripts/docker/healthcheck.sh" ] + periodSeconds: 5 + volumeMounts: + - mountPath: "/app/hyperion/src" + name: src + - mountPath: "/app/hyperion/tests" + name: tests + - mountPath: "/app/hyperion/utility_scripts" + name: utility-scripts + - mountPath: "/app/dodal" + name: dodal + - mountPath: "/var/log/bluesky" + name: logs + hostNetwork: true diff --git a/helm/hyperion/templates/service.yaml b/helm/hyperion-supervisor/templates/service.yaml similarity index 75% rename from helm/hyperion/templates/service.yaml rename to helm/hyperion-supervisor/templates/service.yaml index ca11417892..5db81d381c 100644 --- a/helm/hyperion/templates/service.yaml +++ b/helm/hyperion-supervisor/templates/service.yaml @@ -1,7 +1,7 @@ apiVersion: v1 kind: Service metadata: - name: hyperion-svc + name: hyperion-supervisor-svc spec: {{- if .Values.application.dev }} type: LoadBalancer @@ -9,9 +9,9 @@ spec: type: ClusterIP {{- end }} ports: - - name: hyperion-api + - name: hyperion-supervisor-rest port: {{ .Values.application.servicePort }} protocol: TCP targetPort: {{ .Values.application.containerPort }} selector: - app: hyperion + app: hyperion-supervisor diff --git a/helm/hyperion-supervisor/values.yaml b/helm/hyperion-supervisor/values.yaml new file mode 100644 index 0000000000..acdfcdde55 --- /dev/null +++ b/helm/hyperion-supervisor/values.yaml @@ -0,0 +1,14 @@ +application: + containerPort: 5005 + servicePort: 80 + imageRepository: ghcr.io/diamondlightsource + beamline: i03 + dev: false + logDir: "/dls_sw/i03/logs/bluesky/hyperion-k8s" + # These should be overridden at install time + projectDir: SET_ON_INSTALL + appVersion: SET_ON_INSTALL +dodal: + projectDir: SET_ON_INSTALL +service: + type: NodePort diff --git a/helm/hyperion/templates/deployment.yaml b/helm/hyperion/templates/deployment.yaml deleted file mode 100644 index 41eb7ca251..0000000000 --- a/helm/hyperion/templates/deployment.yaml +++ /dev/null @@ -1,136 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: hyperion-deployment -spec: - selector: - matchLabels: - app: hyperion - replicas: 1 - template: - metadata: - labels: - app: hyperion - spec: - securityContext: - # gda2 - runAsUser: {{ .Values.application.runAsUser }} - runAsGroup: {{ .Values.application.runAsGroup }} - supplementalGroups: {{ .Values.application.supplementalGroups }} - volumes: - - name: dls-sw-bl - hostPath: - path: "/dls_sw/{{ .Values.application.beamline }}" - type: Directory - - name: dls-sw-dasc - hostPath: - path: "/dls_sw/dasc" - type: Directory - # Bind some source folders for easier debugging - - name: src - hostPath: - path: "{{ .Values.application.projectDir }}/src" - type: Directory - - name: tests - hostPath: - path: "{{ .Values.application.projectDir }}/tests" - type: Directory - - name: utility-scripts - hostPath: - path: "{{ .Values.application.projectDir }}/utility_scripts" - type: Directory - - name: dodal - hostPath: - path: "{{ .Values.dodal.projectDir | clean }}" - type: Directory - - name: logs - hostPath: - type: Directory - path: "{{ .Values.application.logDir }}" - - name: debuglogs - hostPath: - type: Directory - path: "{{ .Values.application.debugLogDir }}" - - name: data - hostPath: - type: Directory - path: "{{ .Values.application.dataDir }}" - - name: zocalo-config - configMap: - name: "{{ .Release.Name }}-zocalo-config" - - name: zocalo-secrets - projected: - defaultMode: 0444 - sources: - {{- if .Values.zocalo.secrets }} - {{- range .Values.zocalo.secrets }} - - secret: - name: {{ .secretName }} - {{- end -}} {{/* range */}} - {{- end -}} {{/* if */}} - - name: ispyb-secrets - secret: - type: secret - secretName: ispyb-hyperion-cfg - containers: - - name: hyperion - image: {{ .Values.application.imageRepository}}/mx-bluesky:{{ .Values.application.appVersion }} - resources: - limits: - cpu: "1" - memory: "1Gi" - ports: - - name: hyperion-api - containerPort: {{ .Values.application.containerPort }} - protocol: TCP - env: - - name: LOG_DIR - value: /var/log/bluesky - - name: DEBUG_LOG_DIR - value: /var/log/bluesky-debug - - name: BEAMLINE - value: "{{ .Values.application.beamline }}" - {{- if not .Values.application.dev }} - - name: ZOCALO_GO_USER - value: "gda2" - - name: ZOCALO_GO_HOSTNAME - value: "{{ .Values.application.beamline }}-control" - - name: ZOCALO_CONFIG - value: "/zocalo/config/configuration.yaml" - - name: ISPYB_CONFIG_PATH - value: "/ispyb/secrets/ispyb.cfg" - {{- end }} - readinessProbe: - exec: - command: [ "/app/hyperion/utility_scripts/docker/healthcheck.sh" ] - periodSeconds: 5 - volumeMounts: - - mountPath: "/dls_sw/{{ .Values.application.beamline }}" - name: dls-sw-bl - readOnly: true - mountPropagation: HostToContainer - - mountPath: "/dls_sw/dasc" - name: dls-sw-dasc - readOnly: true - mountPropagation: HostToContainer - - mountPath: "/app/hyperion/src" - name: src - - mountPath: "/app/hyperion/tests" - name: tests - - mountPath: "/app/hyperion/utility_scripts" - name: utility-scripts - - mountPath: "/app/dodal" - name: dodal - - mountPath: "/var/log/bluesky" - name: logs - - mountPath: "/var/log/bluesky-debug" - name: debuglogs - - mountPath: "/dls/{{ .Values.application.beamline }}/data" - name: data - - mountPath: "/zocalo/config" - name: zocalo-config - - mountPath: "/zocalo/secrets" - name: zocalo-secrets - - mountPath: "/ispyb/secrets" - name: ispyb-secrets - hostNetwork: true diff --git a/helm/hyperion/templates/ingress.yaml b/helm/hyperion/templates/ingress.yaml deleted file mode 100644 index 446cf4a9e1..0000000000 --- a/helm/hyperion/templates/ingress.yaml +++ /dev/null @@ -1,23 +0,0 @@ -{{- if not .Values.application.dev }} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: hyperion-ingress -spec: - ingressClassName: nginx - tls: - - hosts: - - {{ .Values.application.externalHostname }} - rules: - - host: {{ .Values.application.externalHostname }} - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: hyperion-svc # this must match the name of the service you want to target - port: - number: {{ .Values.application.containerPort }} - {{- end }} - diff --git a/helm/hyperion/templates/zocalo-config.yaml b/helm/hyperion/templates/zocalo-config.yaml deleted file mode 100644 index 3fd1af8a36..0000000000 --- a/helm/hyperion/templates/zocalo-config.yaml +++ /dev/null @@ -1,39 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: "{{ .Release.Name }}-zocalo-config" - namespace: "{{ .Release.Namespace }}" - labels: - app.kubernetes.io/name: zocalo-config - app.kubernetes.io/instance: "{{ .Release.Name }}-zocalo-config" - app.kubernetes.io/version: "{{ .Chart.Version }}" - app.kubernetes.io/part-of: hyperion -data: - configuration.yaml: |- - version: 1 - - graylog: - plugin: graylog - {{- .Values.zocalo.graylog | toYaml | nindent 6 }} - - {{- if .Values.zocalo.secrets }} - {{- range .Values.zocalo.secrets }} - {{ .name }}: "/zocalo/secrets/{{ .fileName }}" - {{- end -}} {{/* range */}} - {{- end -}} {{/* if */}} - - - default-transport: - plugin: transport - default: {{ .Values.zocalo.defaultTransport }} - - environments: - - bluesky: - plugins: - - default-transport - {{- if .Values.zocalo.secrets }} - {{- range .Values.zocalo.secrets }} - - {{ .name }} - {{- end -}} {{/* range */}} - {{- end -}} {{/* if */}} diff --git a/helm/hyperion/values.yaml b/helm/hyperion/values.yaml deleted file mode 100644 index 0cd408b5c9..0000000000 --- a/helm/hyperion/values.yaml +++ /dev/null @@ -1,35 +0,0 @@ -application: - containerPort: 5005 - servicePort: 80 - imageRepository: ghcr.io/diamondlightsource - # i03-hyperion user and group - runAsUser: 36101 - runAsGroup: 36101 - supplementalGroups: [] - beamline: i03 - dev: false - logDir: "/dls_sw/i03/logs/bluesky/hyperion-k8s" - debugLogDir: "/dls/tmp/i03/logs/bluesky-k8s" - dataDir: "/dls/i03/data" - # These should be overridden at install time - projectDir: SET_ON_INSTALL - appVersion: SET_ON_INSTALL - externalHostname: i03-hyperion.diamond.ac.uk -dodal: - projectDir: SET_ON_INSTALL -service: - type: NodePort - -zocalo: - defaultTransport: "PikaTransport" - graylog: - host: graylog-log-target.diamond.ac.uk - port: 12208 - protocol: UDP - secrets: - - name: rabbitmq - secretName: rmq-creds - fileName: rabbitmq-credentials.yml - - name: rabbitmq-api-reader - secretName: rmq-api-reader - fileName: rabbitmq-api-reader.yml From d0613c28980f35674c21ec82791de219b9bfb6b3 Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Tue, 19 May 2026 17:39:07 +0100 Subject: [PATCH 02/27] WIP --- .github/workflows/_container.yml | 4 +- Dockerfile.hyperion | 39 ++++++++------- .../explanations/containerised_mx_bluesky.rst | 6 ++- utility_scripts/build_docker_image.sh | 25 ++++++---- utility_scripts/docker/entrypoint.sh | 47 ++++++++----------- 5 files changed, 60 insertions(+), 61 deletions(-) diff --git a/.github/workflows/_container.yml b/.github/workflows/_container.yml index e8172726dc..596f92521d 100644 --- a/.github/workflows/_container.yml +++ b/.github/workflows/_container.yml @@ -48,10 +48,10 @@ jobs: images: | ghcr.io/${{ github.repository }} labels: | - org.opencontainers.image.title=mx-bluesky + org.opencontainers.image.title=hyperion org.opencontainers.image.description=Hyperion service for MX Unattended Data Collection annotations: | - org.opencontainers.image.title=mx-bluesky + org.opencontainers.image.title=hyperion org.opencontainers.image.description=Hyperion service for MX Unattended Data Collection tags: | type=ref,event=tag diff --git a/Dockerfile.hyperion b/Dockerfile.hyperion index 3f84127d9d..6e98d58db0 100644 --- a/Dockerfile.hyperion +++ b/Dockerfile.hyperion @@ -1,4 +1,6 @@ -FROM python:3.11 AS build +# This is the Dockerfile for building the image for hyperion-supervisor and hyperion-callbacks + +FROM python:3.12 AS build ARG DEBIAN_FRONTEND=noninteractive @@ -8,39 +10,36 @@ RUN apt update -y && \ apt upgrade -y && \ apt install -y libgl1 libglib2.0-0 -RUN pip install --no-cache-dir --no-compile setuptools_scm +# Install matching uv binaries for our python distro +COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ + +# Directory structure: +# /app/mx-bluesky +# /app/dodal # Copy the pyproject.toml and install dependencies for better caching when developing # & rerunning deployment scripts -COPY pyproject.toml /app/hyperion/ -WORKDIR "/app/hyperion" +WORKDIR "/app/mx-bluesky" +COPY pyproject.toml uv.lock ./ RUN mkdir -p src/mx_bluesky -# This enables us to cache the pip install without needing _version.py -# see https://setuptools-scm.readthedocs.io/en/latest/usage/ -RUN SETUPTOOLS_SCM_PRETEND_VERSION_FOR_MX_BLUESKY=1.0.0 pip install \ - --no-cache-dir --no-compile -e . - -# Check out and install dodal locally with no dependencies as this may be a different version to what -# is referred to in the setup.cfg, but we don't care as it will be overridden by bind mounts in the -# running container -RUN mkdir ../dodal && \ -git clone https://github.com/DiamondLightSource/dodal.git ../dodal && \ -pip install --no-cache-dir --no-compile --no-deps -e ../dodal - # # Everything above this line should be in the image cache unless pyproject.toml changes -# -ADD .git /app/hyperion/.git +ADD .git /app/mx-bluesky/.git + # Restore the repository at the current commit instead of copying, to exclude uncommitted changes # This is so that if you build a developer image from this dockerfile then _version.py will not # append the dirty workdir hash, which causes complications during deployments that mount from a clean folder. RUN git restore . +# This enables us to cache the pip install without needing _version.py +# see https://setuptools-scm.readthedocs.io/en/latest/usage/ +RUN uv sync --compile-bytecode --no-cache + # Regenerate _version.py with the correct version - this should run quickly since we already have our dependencies RUN rm src/mx_bluesky/_version.py -RUN pip install --no-cache-dir --no-compile --no-deps -e . +RUN uv pip install --no-cache-dir --no-compile --no-deps -e . -ENTRYPOINT ["/app/hyperion/utility_scripts/docker/entrypoint.sh"] +ENTRYPOINT ["/app/mx-bluesky/utility_scripts/docker/entrypoint.sh"] EXPOSE 5005 diff --git a/docs/developer/general/explanations/containerised_mx_bluesky.rst b/docs/developer/general/explanations/containerised_mx_bluesky.rst index 51bcf3d8b3..6f5074619f 100644 --- a/docs/developer/general/explanations/containerised_mx_bluesky.rst +++ b/docs/developer/general/explanations/containerised_mx_bluesky.rst @@ -3,12 +3,14 @@ Containerised mx-bluesky There are currently two images associated with this repository which are pushed on release: hyperion, and mx-bluesky-blueapi. -The Hyperion image exists because Hyperion was developed before BlueAPI was production-ready, and so doesn't use BlueAPI to schedule plans. This image is only really relevant for i03, and currently isn't used in production anywhere +The Hyperion image is the image that provides ``hyperion-supervisor`` and ``hyperion-callbacks``. These are launched as applications in their own right; ``hyperion-supervisor`` makes use of BlueAPI client but does not expose blueapi plans. ``hyperion-callbacks`` does not use BlueAPI. Which application is launched depends on the arguments passed to the ``entrypoint.sh`` launcher script on container startup. -The ``mx-bluesky-blueapi`` image exists as a minor extension of BlueAPI's image. BlueAPI's image contains the dependencies of BlueAPI, as well as the dependencies of BlueAPI, which includes dodal. When the BlueAPI service is launched, it will do a ``pip install --no deps`` of the plan repository. For MX, this means ``mx-bluesky`` gets installed without any of its dependencies. For this reason, we have created an ``mx-bluesky-blueapi`` image which installs these extra dependencies. +The ``mx-bluesky-blueapi`` image exists as a minor extension of BlueAPI's image. BlueAPI's image contains the dependencies of BlueAPI, as well as the dependencies of BlueAPI, which includes dodal. When the BlueAPI service is launched, it will do a ``pip install --no deps`` of the plan repository. For MX, this means ``mx-bluesky`` gets installed without any of its dependencies. For this reason, we have created an ``mx-bluesky-blueapi`` image which installs these extra dependencies. This image can be used with BlueAPI's original helmchart, the only change required in the ``values.yaml`` is:: image: repository: ghcr.io/diamondlightsource/mx-bluesky-blueapi tag: "{desired_version}" + +``hyperion-blueapi`` is launched as a standard ``mx-bluesky-blueapi`` image with configuration to load the hyperion plan and beamline modules. diff --git a/utility_scripts/build_docker_image.sh b/utility_scripts/build_docker_image.sh index 6854d10697..a4b97981b9 100755 --- a/utility_scripts/build_docker_image.sh +++ b/utility_scripts/build_docker_image.sh @@ -2,7 +2,8 @@ set -e # builds the docker image BUILD=1 -PUSH=1 +PUSH=0 +BUILD_UNCLEAN=0 PODMAN_FLAGS="" for option in "$@"; do case $option in @@ -10,22 +11,27 @@ for option in "$@"; do BUILD=0 shift ;; - --no-push) - PUSH=0 + --push) + PUSH=1 shift ;; --no-cache) PODMAN_FLAGS+=" --no-cache" shift ;; + --unclean) + BUILD_UNCLEAN=1 + shift + ;; --help|--info|--h) CMD=`basename $0` echo "$CMD [options]" echo "Builds and/or pushes the docker container image to the repository" echo " --help This help" echo " --no-build Do not build the image" - echo " --no-push Do not push the image" + echo " --push Push the image" echo " --no-cache Don't use the cache when building the image." + echo " --unclean Build with an unclean workspace" exit 0 ;; -*|--*) @@ -36,14 +42,15 @@ for option in "$@"; do done PROJECTDIR=`dirname $0`/.. -IMAGE=mx-bluesky +IMAGE=hyperion -if ! git diff --cached --quiet; then - echo "Cannot build image from unclean workspace" - exit 1 +if [[ $BUILD_UNCLEAN == 0 ]]; then + if ! git diff --cached --quiet; then + echo "Cannot build image from unclean workspace" + exit 1 + fi fi - if [[ $BUILD == 1 ]]; then echo "Building initial image" LATEST_TAG=$IMAGE:latest diff --git a/utility_scripts/docker/entrypoint.sh b/utility_scripts/docker/entrypoint.sh index 9fba523722..b0f826505e 100755 --- a/utility_scripts/docker/entrypoint.sh +++ b/utility_scripts/docker/entrypoint.sh @@ -1,15 +1,22 @@ #!/bin/bash # Entry point for the production docker image that launches the external callbacks # as well as the main server - +IN_DEV=false +CALLBACKS=false for option in "$@"; do case $option in --dev) IN_DEV=true + shift + ;; + --callbacks) + CALLBACKS=true + shift ;; --help|--info|--h) echo "Arguments:" echo " --dev start in development mode without external callbacks" + echo " --callbacks start hyperion callbacks, otherwise start hyperion-supervisor" exit 0 ;; -*|--*) @@ -19,38 +26,22 @@ for option in "$@"; do esac done -kill_active_apps () { - echo "Killing active instances of hyperion and hyperion-callbacks..." - pkill -e -f "python.*hyperion" - pkill -e -f "SCREEN.*hyperion" - echo "done." -} - RELATIVE_SCRIPT_DIR=$( dirname -- "$0"; ) cd ${RELATIVE_SCRIPT_DIR} echo "$(date) Logging to $LOG_DIR" mkdir -p $LOG_DIR start_log_path=$LOG_DIR/start_log.log -callback_start_log_path=$LOG_DIR/callback_start_log.log #Add future arguments here -declare -A h_and_cb_args=( ["IN_DEV"]="$IN_DEV" ) -declare -A h_and_cb_arg_strings=( ["IN_DEV"]="--dev" ) - -h_commands=() -cb_commands=() -for i in "${!h_and_cb_args[@]}" -do - if [ "${h_and_cb_args[$i]}" != false ]; then - h_commands+="${h_and_cb_arg_strings[$i]} "; - cb_commands+="${h_and_cb_arg_strings[$i]} "; - fi; -done - -trap kill_active_apps TERM - -hyperion-callbacks `echo $cb_commands;`>$callback_start_log_path 2>&1 & - -echo "$(date) Starting Hyperion..." -hyperion `echo $h_commands;`>$start_log_path 2>&1 +args="" +command="hyperion" +if [ $IN_DEV == true ]; then + args+="--dev " +fi +if [ $CALLBACKS == true ]; then + command="hyperion-callbacks" +fi + +echo "$(date) Starting $command..." +$command $args > $start_log_path 2>&1 From 9a6496a556c95ab0ecfedb4c3e80b90833a48623 Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Wed, 20 May 2026 11:53:40 +0100 Subject: [PATCH 03/27] Update entrypoint --- utility_scripts/docker/entrypoint.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/utility_scripts/docker/entrypoint.sh b/utility_scripts/docker/entrypoint.sh index b0f826505e..84c3872a93 100755 --- a/utility_scripts/docker/entrypoint.sh +++ b/utility_scripts/docker/entrypoint.sh @@ -13,10 +13,16 @@ for option in "$@"; do CALLBACKS=true shift ;; + --version) + . ./.venv/bin/activate + hyperion --version + exit $? + ;; --help|--info|--h) echo "Arguments:" echo " --dev start in development mode without external callbacks" echo " --callbacks start hyperion callbacks, otherwise start hyperion-supervisor" + echo " --version print the hyperion version and exit" exit 0 ;; -*|--*) @@ -29,6 +35,8 @@ done RELATIVE_SCRIPT_DIR=$( dirname -- "$0"; ) cd ${RELATIVE_SCRIPT_DIR} +. ./.venv/bin/activate + echo "$(date) Logging to $LOG_DIR" mkdir -p $LOG_DIR start_log_path=$LOG_DIR/start_log.log From 7c23fd4aa35383eb9a370b0bad214eabc35c0624 Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Thu, 21 May 2026 15:24:17 +0100 Subject: [PATCH 04/27] Changes to build docker image --- .dockerignore | 4 +- Dockerfile.hyperion | 43 ++++++++++---------- utility_scripts/build_docker_image.sh | 25 ++++++------ utility_scripts/docker/initialise_scratch.sh | 12 ++++++ utility_scripts/extract_version.sh | 5 +++ 5 files changed, 54 insertions(+), 35 deletions(-) create mode 100755 utility_scripts/docker/initialise_scratch.sh create mode 100755 utility_scripts/extract_version.sh diff --git a/.dockerignore b/.dockerignore index ba7a552e17..61ead4d8b4 100644 --- a/.dockerignore +++ b/.dockerignore @@ -5,8 +5,10 @@ .ruff_cache **/__pycache__/ +# _version.py updated when image is built +**/_version.py + # virtualenv stuff - this gets built by the docker script .venv activate - tmp diff --git a/Dockerfile.hyperion b/Dockerfile.hyperion index 6e98d58db0..a88b6a0b00 100644 --- a/Dockerfile.hyperion +++ b/Dockerfile.hyperion @@ -1,8 +1,16 @@ # This is the Dockerfile for building the image for hyperion-supervisor and hyperion-callbacks -FROM python:3.12 AS build +# The image will contain the directory structure: +# /app/mx-bluesky/.venv +# /app/mx-bluesky/.git +# /app/mx-bluesky/scripts +# but we don't include the source folder structure for mx-bluesky or dodal since these will be +# deployed in a separate volume by the initContainer for the scratch folder + +FROM python:3.12 AS base-image ARG DEBIAN_FRONTEND=noninteractive +ARG SETUPTOOLS_SCM_PRETEND_VERSION_FOR_MX_BLUESKY # Need: # libgl, libglib2.0 for python cv2 dependency @@ -13,32 +21,25 @@ RUN apt update -y && \ # Install matching uv binaries for our python distro COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ -# Directory structure: -# /app/mx-bluesky -# /app/dodal +ADD .git /app/mx-bluesky/.git +RUN mkdir -p /scratch && mkdir -p /app/scripts + +############################################################################# +FROM base-image as uv-staging # Copy the pyproject.toml and install dependencies for better caching when developing # & rerunning deployment scripts WORKDIR "/app/mx-bluesky" COPY pyproject.toml uv.lock ./ -RUN mkdir -p src/mx_bluesky - -# -# Everything above this line should be in the image cache unless pyproject.toml changes -ADD .git /app/mx-bluesky/.git - -# Restore the repository at the current commit instead of copying, to exclude uncommitted changes -# This is so that if you build a developer image from this dockerfile then _version.py will not -# append the dirty workdir hash, which causes complications during deployments that mount from a clean folder. -RUN git restore . +RUN mkdir -p src/mx_bluesky && \ + git restore . && \ + uv sync --compile-bytecode --no-cache --locked -# This enables us to cache the pip install without needing _version.py -# see https://setuptools-scm.readthedocs.io/en/latest/usage/ -RUN uv sync --compile-bytecode --no-cache - -# Regenerate _version.py with the correct version - this should run quickly since we already have our dependencies -RUN rm src/mx_bluesky/_version.py -RUN uv pip install --no-cache-dir --no-compile --no-deps -e . +############################################################################# +FROM base-image as build +WORKDIR "/app/mx-bluesky" +COPY --from=uv-staging /app/mx-bluesky/.venv /app/mx-bluesky/.venv +COPY utility_scripts/docker/initialise_scratch.sh /app/scripts/ ENTRYPOINT ["/app/mx-bluesky/utility_scripts/docker/entrypoint.sh"] diff --git a/utility_scripts/build_docker_image.sh b/utility_scripts/build_docker_image.sh index a4b97981b9..18e666fc87 100755 --- a/utility_scripts/build_docker_image.sh +++ b/utility_scripts/build_docker_image.sh @@ -1,6 +1,6 @@ #!/bin/bash set -e -# builds the docker image +# Script for building development docker images BUILD=1 PUSH=0 BUILD_UNCLEAN=0 @@ -26,7 +26,7 @@ for option in "$@"; do --help|--info|--h) CMD=`basename $0` echo "$CMD [options]" - echo "Builds and/or pushes the docker container image to the repository" + echo "Builds a development docker image and optionally pushes the docker container image to the repository" echo " --help This help" echo " --no-build Do not build the image" echo " --push Push the image" @@ -44,6 +44,12 @@ done PROJECTDIR=`dirname $0`/.. IMAGE=hyperion +function extract_version() { + LATEST_VERSION=$(git tag | sed -E -n 's/^v?([[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+)$/\1/p' | sort -V -r | head -1) + GIT_HASH=$(git rev-parse --short HEAD) + echo $LATEST_VERSION-g$GIT_HASH +} + if [[ $BUILD_UNCLEAN == 0 ]]; then if ! git diff --cached --quiet; then echo "Cannot build image from unclean workspace" @@ -53,23 +59,16 @@ fi if [[ $BUILD == 1 ]]; then echo "Building initial image" + IMAGE_VERSION=$(extract_version) + MX_BLUESKY_VERSION=${IMAGE_VERSION/-/+} LATEST_TAG=$IMAGE:latest TMPDIR=/tmp podman build \ $PODMAN_FLAGS \ + --build-arg SETUPTOOLS_SCM_PRETEND_VERSION_FOR_MX_BLUESKY=$MX_BLUESKY_VERSION \ -f $PROJECTDIR/Dockerfile.hyperion \ --tag $LATEST_TAG \ + --tag $IMAGE:$IMAGE_VERSION \ $PROJECTDIR - # Now extract the version from the built image and then rebuild with the label - IMAGE_VERSION=$(podman run --rm --entrypoint=hyperion $LATEST_TAG -c "--version" | \ - sed -e 's/[^a-zA-Z0-9 ._-]/_/g') - TAG=$IMAGE:$IMAGE_VERSION - echo "Labelling image with version $IMAGE_VERSION, tagging with tags $TAG $LATEST_TAG" - TMPDIR=/tmp podman build \ - -f $PROJECTDIR/Dockerfile.hyperion \ - --tag $TAG \ - --tag $LATEST_TAG \ - --label "version=$IMAGE_VERSION" \ - $PROJECTDIR fi if [[ $PUSH == 1 ]]; then diff --git a/utility_scripts/docker/initialise_scratch.sh b/utility_scripts/docker/initialise_scratch.sh new file mode 100755 index 0000000000..06de63a770 --- /dev/null +++ b/utility_scripts/docker/initialise_scratch.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# This script is run in the initContainer before the main hyperion pod is launched to initialise the scratch area +# if not already present +SCRATCH_ROOT=/scratch +APP_ROOT=/app + +if [ ! -d $SCRATCH_ROOT/mx-bluesky/.git ]; then + CURRENT_BRANCH=$(git --git-dir=$APP_ROOT/mx-bluesky/.git rev-parse --abbrev-ref HEAD) + git clone /app/mx-bluesky/.git $SCRATCH_ROOT/mx-bluesky + cd $SCRATCH_ROOT/mx-bluesky + git checkout $CURRENT_BRANCH +fi diff --git a/utility_scripts/extract_version.sh b/utility_scripts/extract_version.sh new file mode 100755 index 0000000000..e9dcb6716a --- /dev/null +++ b/utility_scripts/extract_version.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +LATEST_VERSION=$(git tag | sed -E -n 's/^v?([[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+)$/\1/p' | sort -V -r | head -1) +GIT_HASH=$(git rev-parse --short HEAD) +echo $LATEST_VERSION-g$GIT_HASH From 6f628396fc292d87cb84ddd1fe59e295a4238ddd Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Fri, 22 May 2026 17:19:10 +0100 Subject: [PATCH 05/27] Mostly working: * Hyperion supervisor/callback dockerfile * Hyperion supervisor helm chart * dev rabbitmq helm chart * updated development k8s deployment script --- Dockerfile.hyperion | 4 +- .../templates/configmap.yaml | 22 ++++ .../templates/deployment.yaml | 105 +++++++++-------- .../templates/volumes.yaml | 13 ++ helm/hyperion-supervisor/values.yaml | 23 ++-- helm/rabbitmq/Chart.yaml | 15 +++ helm/rabbitmq/README.md | 1 + helm/rabbitmq/values.yaml | 12 ++ utility_scripts/build_docker_image.sh | 10 +- .../deploy/deploy_hyperion_supervisor.sh | 4 + .../deploy/deploy_mx_bluesky_app_to_k8s.sh | 111 +++--------------- utility_scripts/docker/entrypoint.sh | 11 +- 12 files changed, 163 insertions(+), 168 deletions(-) create mode 100644 helm/hyperion-supervisor/templates/configmap.yaml create mode 100644 helm/hyperion-supervisor/templates/volumes.yaml create mode 100644 helm/rabbitmq/Chart.yaml create mode 100644 helm/rabbitmq/README.md create mode 100644 helm/rabbitmq/values.yaml create mode 100644 utility_scripts/deploy/deploy_hyperion_supervisor.sh diff --git a/Dockerfile.hyperion b/Dockerfile.hyperion index a88b6a0b00..901ff66097 100644 --- a/Dockerfile.hyperion +++ b/Dockerfile.hyperion @@ -41,6 +41,6 @@ WORKDIR "/app/mx-bluesky" COPY --from=uv-staging /app/mx-bluesky/.venv /app/mx-bluesky/.venv COPY utility_scripts/docker/initialise_scratch.sh /app/scripts/ -ENTRYPOINT ["/app/mx-bluesky/utility_scripts/docker/entrypoint.sh"] +ENTRYPOINT ["/scratch/mx-bluesky/utility_scripts/docker/entrypoint.sh"] -EXPOSE 5005 +EXPOSE 5006 diff --git a/helm/hyperion-supervisor/templates/configmap.yaml b/helm/hyperion-supervisor/templates/configmap.yaml new file mode 100644 index 0000000000..9f326f55a2 --- /dev/null +++ b/helm/hyperion-supervisor/templates/configmap.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: hyperion-supervisor-config +data: + supervisor_config.yaml: |- + # Configures the supervisor BlueAPI context to access the baton + env: + sources: + - kind: deviceManager + module: dodal.beamlines.{{ .Values.application.beamline }}_supervisor + logging: + graylog: + url: {{ .Values.graylog.url }} + enabled: true + client_config.yaml: |- + # Configuration for the BlueAPI client running in the hyperion supervisor + api: + url: {{ .Values.blueapi.url }} + stomp: + enabled: true + url: {{ .Values.stomp.url }} diff --git a/helm/hyperion-supervisor/templates/deployment.yaml b/helm/hyperion-supervisor/templates/deployment.yaml index 13ded82711..d88249069b 100644 --- a/helm/hyperion-supervisor/templates/deployment.yaml +++ b/helm/hyperion-supervisor/templates/deployment.yaml @@ -14,55 +14,58 @@ spec: spec: volumes: # Bind some source folders for easier debugging - - name: src - hostPath: - path: "{{ .Values.application.projectDir }}/src" - type: Directory - - name: tests - hostPath: - path: "{{ .Values.application.projectDir }}/tests" - type: Directory - - name: utility-scripts - hostPath: - path: "{{ .Values.application.projectDir }}/utility_scripts" - type: Directory - - name: dodal - hostPath: - path: "{{ .Values.dodal.projectDir | clean }}" - type: Directory - - name: logs - hostPath: - type: Directory - path: "{{ .Values.application.logDir }}" + - name: scratch + persistentVolumeClaim: + claimName: hyperion-supervisor-scratch-{{ .Values.application.imageVersion }} + - name: config + configMap: + name: hyperion-supervisor-config + initContainers: + - name: hyperion-init + image: {{ .Values.application.imageRepository}}/hyperion:{{ .Values.application.imageVersion }} + command: ['/app/scripts/initialise_scratch.sh'] + volumeMounts: + - name: scratch + mountPath: "/scratch" + {{- if .Values.application.dev }} + restartPolicy: Never + {{- end }} containers: - - name: hyperion - image: {{ .Values.application.imageRepository}}/mx-bluesky:{{ .Values.application.appVersion }} - resources: - limits: - cpu: "1" - memory: "1Gi" - ports: - - name: hyperion-api - containerPort: {{ .Values.application.containerPort }} - protocol: TCP - env: - - name: LOG_DIR - value: /var/log/bluesky - - name: BEAMLINE - value: "{{ .Values.application.beamline }}" - readinessProbe: - exec: - command: [ "/app/hyperion/utility_scripts/docker/healthcheck.sh" ] - periodSeconds: 5 - volumeMounts: - - mountPath: "/app/hyperion/src" - name: src - - mountPath: "/app/hyperion/tests" - name: tests - - mountPath: "/app/hyperion/utility_scripts" - name: utility-scripts - - mountPath: "/app/dodal" - name: dodal - - mountPath: "/var/log/bluesky" - name: logs - hostNetwork: true + - name: hyperion-supervisor + image: {{ .Values.application.imageRepository}}/hyperion:{{ .Values.application.imageVersion }} + command: ['/scratch/mx-bluesky/utility_scripts/docker/entrypoint.sh'] + {{- if .Values.application.dev }} + restartPolicy: Never + {{- end }} + args: + {{- if .Values.application.dev }} + - "--dev" + {{- end }} + resources: + limits: + cpu: "1" + memory: "1Gi" + ports: + - name: rest-api + containerPort: {{ .Values.application.containerPort }} + protocol: TCP + env: + - name: LOG_DIR + value: /var/log/bluesky + - name: DEBUG_LOG_DIR + value: /var/log/bluesky/debug + - name: BEAMLINE + value: "{{ .Values.application.beamline }}" + - name: CONFIG_SERVER_URL + value: "{{ .Values.configServer.url }}" + readinessProbe: + exec: + command: [ "/scratch/mx-bluesky/utility_scripts/docker/healthcheck.sh" ] + periodSeconds: 5 + volumeMounts: + - mountPath: "/scratch" + name: scratch + readOnly: true + - mountPath: "/etc/hyperion" + name: config + readOnly: true diff --git a/helm/hyperion-supervisor/templates/volumes.yaml b/helm/hyperion-supervisor/templates/volumes.yaml new file mode 100644 index 0000000000..5cd83135ef --- /dev/null +++ b/helm/hyperion-supervisor/templates/volumes.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: hyperion-supervisor-scratch-{{ .Values.application.imageVersion }} + annotations: + argocd.argoproj.io/sync-options: Prune=false,Delete=false + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.scratch.volumeSize }} diff --git a/helm/hyperion-supervisor/values.yaml b/helm/hyperion-supervisor/values.yaml index acdfcdde55..9306a1db7c 100644 --- a/helm/hyperion-supervisor/values.yaml +++ b/helm/hyperion-supervisor/values.yaml @@ -1,14 +1,19 @@ application: - containerPort: 5005 + containerPort: 5006 servicePort: 80 imageRepository: ghcr.io/diamondlightsource + imageName: hyperion + imageVersion: SET_ON_INSTALL beamline: i03 dev: false - logDir: "/dls_sw/i03/logs/bluesky/hyperion-k8s" - # These should be overridden at install time - projectDir: SET_ON_INSTALL - appVersion: SET_ON_INSTALL -dodal: - projectDir: SET_ON_INSTALL -service: - type: NodePort + logDir: "/var/logs/mx-bluesky" +scratch: + volumeSize: "2Gi" +configServer: + url: http://i03-daq-config-server.diamond.ac.uk +graylog: + url: "tcp://graylog-log-target.diamond.ac.uk:12232" +stomp: + url: tcp://localhost:61613 +blueapi: + url: http://my.blueapi.service:5005 diff --git a/helm/rabbitmq/Chart.yaml b/helm/rabbitmq/Chart.yaml new file mode 100644 index 0000000000..0ea3296092 --- /dev/null +++ b/helm/rabbitmq/Chart.yaml @@ -0,0 +1,15 @@ +apiVersion: v2 +name: mx-bluesky-rabbitmq-test +description: Rabbitmq server for use in testing environments + +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.0.1 + +dependencies: + - name: rabbitmq + version: 2.3.0 + repository: https://groundhog2k.github.io/helm-charts/ diff --git a/helm/rabbitmq/README.md b/helm/rabbitmq/README.md new file mode 100644 index 0000000000..96edb237ab --- /dev/null +++ b/helm/rabbitmq/README.md @@ -0,0 +1 @@ +This helmchart is provided for development testing purposes only diff --git a/helm/rabbitmq/values.yaml b/helm/rabbitmq/values.yaml new file mode 100644 index 0000000000..115e42607d --- /dev/null +++ b/helm/rabbitmq/values.yaml @@ -0,0 +1,12 @@ +rabbitmq: + plugins: + - rabbitmq_stomp + service: + extraPorts: + - name: stomp + protocol: TCP + containerPort: 61613 + port: 61613 + authentication: + erlangCookie: + value: DEFAULT_COOKIE diff --git a/utility_scripts/build_docker_image.sh b/utility_scripts/build_docker_image.sh index 18e666fc87..1e96747fe4 100755 --- a/utility_scripts/build_docker_image.sh +++ b/utility_scripts/build_docker_image.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -e +set -eo pipefail # Script for building development docker images BUILD=1 PUSH=0 @@ -61,7 +61,7 @@ if [[ $BUILD == 1 ]]; then echo "Building initial image" IMAGE_VERSION=$(extract_version) MX_BLUESKY_VERSION=${IMAGE_VERSION/-/+} - LATEST_TAG=$IMAGE:latest + LATEST_TAG=$IMAGE:dev TMPDIR=/tmp podman build \ $PODMAN_FLAGS \ --build-arg SETUPTOOLS_SCM_PRETEND_VERSION_FOR_MX_BLUESKY=$MX_BLUESKY_VERSION \ @@ -77,7 +77,7 @@ if [[ $PUSH == 1 ]]; then echo "Not logged in to ghcr.io" exit 1 fi - echo "Pushing to ghcr.io/$NAMESPACE/$IMAGE:latest ..." - podman push $IMAGE:latest docker://ghcr.io/$NAMESPACE/$IMAGE:latest - podman push $IMAGE:latest docker://ghcr.io/$NAMESPACE/$IMAGE:$IMAGE_VERSION + echo "Pushing to ghcr.io/$NAMESPACE/$IMAGE:dev ..." + podman push $IMAGE:dev docker://ghcr.io/$NAMESPACE/$IMAGE:dev + podman push $IMAGE:dev docker://ghcr.io/$NAMESPACE/$IMAGE:$IMAGE_VERSION fi diff --git a/utility_scripts/deploy/deploy_hyperion_supervisor.sh b/utility_scripts/deploy/deploy_hyperion_supervisor.sh new file mode 100644 index 0000000000..0d298e971f --- /dev/null +++ b/utility_scripts/deploy/deploy_hyperion_supervisor.sh @@ -0,0 +1,4 @@ +#!/bin/bash +PROJECTDIR=$(dirname $0)/../.. +helm package $PROJECTDIR/helm/hyperion-supervisor \ + --app-version diff --git a/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh b/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh index 59f70f8f2d..11fb76aa26 100755 --- a/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh +++ b/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh @@ -12,16 +12,12 @@ for option in "$@"; do DEV=true shift ;; - --checkout-to-prod) - CHECKOUT=true - shift - ;; --repository=*) REPOSITORY="${option#*=}" shift ;; - --appVersion=*) - APP_VERSION="${option#*=}" + --imageVersion=*) + IMAGE_VERSION="${option#*=}" shift ;; --no-login) @@ -32,10 +28,6 @@ for option in "$@"; do DRY_RUN=true shift ;; - --bind-dir=*) - BIND_DIR="${option#*=}" - shift - ;; --help|--info|--h) CMD=`basename $0` echo "$CMD [options] " @@ -48,21 +40,19 @@ the container, NOT the directory that you built the container image from. Arguments: release Name of the helmchart release - app_name Use either "hyperion" or "redis-to-murko" + app_name Use either "hyperion-supervisor" or "redis-to-murko" Options: --help This help - --appVersion=version Version of the image to fetch from the repository otherwise it is deduced + --imageVersion=version Version of the image to fetch from the repository otherwise it is deduced from the setuptools_scm. Must be in the format x.y.z -b, --beamline=BEAMLINE Overrides the BEAMLINE environment variable with the given beamline - --checkout-to-prod Checkout source folders to the production folder using deploy_mx_bluesky.py --dev Install to a development kubernetes cluster (assumes project checked out under /home) (default cluster is argus in user namespace) --dry-run Do everything but don't do the final deploy to k8s --no-login Do not attempt to log in to kubernetes instead use the current namespace and cluster --repository=REPOSITORY Override the repository to fetch the image from - --bind-dir=DIR Override the directory to bind to, default calculated from app version EOM exit 0 ;; @@ -91,8 +81,8 @@ if [[ -z $APP_NAME ]]; then echo "App name must be specified, currently supporting hyperion and redis-to-murko" exit 1 else - if [[ "$APP_NAME" != "hyperion" && "$APP_NAME" != "redis-to-murko" ]]; then - echo "Invalid app name specified. Please provide either 'hyperion' or 'redis-to-murko'." + if [[ "$APP_NAME" != "hyperion-supervisor" && "$APP_NAME" != "redis-to-murko" ]]; then + echo "Invalid app name specified. Please provide either 'hyperion-supervisor' or 'redis-to-murko'." exit 1 fi fi @@ -103,44 +93,6 @@ PROJECTDIR=$(readlink -e $(dirname $0)/../..) TOP_HELMCHART_DIR=${PROJECTDIR}/helm HELMCHART_DIR=${TOP_HELMCHART_DIR}/${APP_NAME} -if [[ -n $DEV ]]; then - if [[ -n $CHECKOUT ]]; then - echo "Cannot specify both --dev and --checkout-to-prod" - exit 1 - fi - CHECKED_OUT_VERSION=$(git describe --tag) -else - if [[ -z ${VIRTUAL_ENV#${PROJECTDIR}} ]]; then - echo "Virtual env not activated, activating" - . $PROJECTDIR/.venv/bin/activate - fi - - # First extract the version and location that will be deployed - DEPLOY_MX_BLUESKY="python $PROJECTDIR/utility_scripts/deploy/deploy_mx_bluesky.py" - MX_BLUESKY_BASE=$($DEPLOY_MX_BLUESKY --print-release-dir $BEAMLINE) - - if [[ -n $CHECKOUT ]]; then - if [[ -n $BIND_DIR ]]; then - echo "Cannot specify --bind-dir and --checkout-to-prod" - exit 1 - fi - echo "Running deploy_mx_bluesky.py to deploy to production folder..." - $DEPLOY_MX_BLUESKY --kubernetes $BEAMLINE - if [[ $? != 0 ]]; then - echo "Deployment failed, aborting." - exit 1 - fi - fi - - NEW_PROJECTDIR=$MX_BLUESKY_BASE/mx-bluesky - echo "Changing directory to $NEW_PROJECTDIR..." - cd $NEW_PROJECTDIR - PROJECTDIR=$NEW_PROJECTDIR - MX_BLUESKY_BASENAME=$(basename $MX_BLUESKY_BASE) - CHECKED_OUT_VERSION=${MX_BLUESKY_BASENAME#mx-bluesky_} -fi - - if [[ $LOGIN = true ]]; then if [[ -n $DEV ]]; then CLUSTER=argus @@ -151,67 +103,32 @@ if [[ $LOGIN = true ]]; then fi fi -ensure_version_py() { - # We require the _version.py to be created, this needs a minimal virtual environment - if [[ ! -d $PROJECTDIR/.venv ]]; then - echo "Creating _version.py" - echo "Virtual environment not found - creating" - module load python/3.11 && module load uv - uv venv $PROJECTDIR/.venv - source $PROJECTDIR/.venv/bin/activate - fi - uv pip install setuptools_scm -} - -app_version() { - . $PROJECTDIR/.venv/bin/activate - python -m setuptools_scm --force-write-version-files | sed -e 's/[^a-zA-Z0-9._-]/_/g' -} - if [[ -n $REPOSITORY ]]; then HELM_OPTIONS+="--set application.imageRepository=$REPOSITORY " fi -ensure_version_py -if [[ -z $APP_VERSION ]]; then - APP_VERSION=$(app_version) -fi - -echo "Checked out version that will be bind-mounted in $PROJECTDIR is $CHECKED_OUT_VERSION" echo "Container image version that will be pulled is $APP_VERSION" -if [[ $APP_VERSION != $CHECKED_OUT_VERSION ]]; then - echo "*****************************************************************" - echo "WARNING: Checked out version and container image versions differ!" - echo "*****************************************************************" -fi - +#application.runAsUser=$EUID,\ +#application.runAsGroup=$GID,\ +#application.supplementalGroups=[$SUPPLEMENTAL_GIDS],\ +#application.externalHostname=test-$APP_NAME.diamond.ac.uk " if [[ -n $DEV ]]; then GID=`id -g` SUPPLEMENTAL_GIDS=37904 HELM_OPTIONS+="--set \ application.dev=true,\ -application.runAsUser=$EUID,\ -application.runAsGroup=$GID,\ -application.supplementalGroups=[$SUPPLEMENTAL_GIDS],\ application.logDir=$PROJECTDIR/tmp,\ application.dataDir=$PROJECTDIR/tmp/data,\ -application.externalHostname=test-$APP_NAME.diamond.ac.uk " - mkdir -p $PROJECTDIR/tmp/data - DEPLOYMENT_DIR=$PROJECTDIR -else - DEPLOYMENT_DIR=/dls_sw/$BEAMLINE/software/bluesky/mx-bluesky_${APP_VERSION}/mx-bluesky -fi -if [[ -n $BIND_DIR ]]; then - DEPLOYMENT_DIR=$BIND_DIR +stomp.url=tcp://rabbitmq-test:61613 " fi -HELM_OPTIONS+="--set application.appVersion=v$APP_VERSION,\ -application.projectDir=$DEPLOYMENT_DIR,\ -dodal.projectDir=$DEPLOYMENT_DIR/../dodal " +HELM_OPTIONS+="--set application.imageVersion=$IMAGE_VERSION " module load helm +APP_VERSION=$IMAGE_VERSION + helm package $HELMCHART_DIR --app-version $APP_VERSION # Helm package generates a file suffixed with the chart version if [[ $LOGIN = true ]]; then diff --git a/utility_scripts/docker/entrypoint.sh b/utility_scripts/docker/entrypoint.sh index 84c3872a93..535604ed44 100755 --- a/utility_scripts/docker/entrypoint.sh +++ b/utility_scripts/docker/entrypoint.sh @@ -14,7 +14,7 @@ for option in "$@"; do shift ;; --version) - . ./.venv/bin/activate + . /app/mx-bluesky/.venv/bin/activate hyperion --version exit $? ;; @@ -35,11 +35,10 @@ done RELATIVE_SCRIPT_DIR=$( dirname -- "$0"; ) cd ${RELATIVE_SCRIPT_DIR} -. ./.venv/bin/activate +. /app/mx-bluesky/.venv/bin/activate echo "$(date) Logging to $LOG_DIR" mkdir -p $LOG_DIR -start_log_path=$LOG_DIR/start_log.log #Add future arguments here args="" @@ -47,9 +46,13 @@ command="hyperion" if [ $IN_DEV == true ]; then args+="--dev " fi +CONFIG_DIR=/etc/hyperion if [ $CALLBACKS == true ]; then command="hyperion-callbacks" + args+="--stomp-config $CONFIG_DIR/blueapi_callbacks.yml" +else + args+="--mode supervisor --client-config $CONFIG_DIR/client_config.yaml --supervisor-config $CONFIG_DIR/supervisor_config.yaml" fi echo "$(date) Starting $command..." -$command $args > $start_log_path 2>&1 +$command $args From 2d251fd03e79de8bebae6db121c8363d7a68ba26 Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Tue, 26 May 2026 10:09:36 +0100 Subject: [PATCH 06/27] Update initialise_scratch to pip install mx-bluesky --- helm/hyperion-supervisor/templates/deployment.yaml | 9 +++------ .../deploy/deploy_mx_bluesky_app_to_k8s.sh | 13 +++++++++++-- utility_scripts/docker/initialise_scratch.sh | 3 +++ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/helm/hyperion-supervisor/templates/deployment.yaml b/helm/hyperion-supervisor/templates/deployment.yaml index d88249069b..81243bb4a9 100644 --- a/helm/hyperion-supervisor/templates/deployment.yaml +++ b/helm/hyperion-supervisor/templates/deployment.yaml @@ -12,6 +12,9 @@ spec: labels: app: hyperion-supervisor spec: + {{- if .Values.application.dev }} + restartPolicy: Never + {{- end }} volumes: # Bind some source folders for easier debugging - name: scratch @@ -27,16 +30,10 @@ spec: volumeMounts: - name: scratch mountPath: "/scratch" - {{- if .Values.application.dev }} - restartPolicy: Never - {{- end }} containers: - name: hyperion-supervisor image: {{ .Values.application.imageRepository}}/hyperion:{{ .Values.application.imageVersion }} command: ['/scratch/mx-bluesky/utility_scripts/docker/entrypoint.sh'] - {{- if .Values.application.dev }} - restartPolicy: Never - {{- end }} args: {{- if .Values.application.dev }} - "--dev" diff --git a/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh b/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh index 11fb76aa26..7322327663 100755 --- a/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh +++ b/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh @@ -1,7 +1,7 @@ #!/bin/bash # Installs helm package to kubernetes LOGIN=true - +LINT=false for option in "$@"; do case $option in -b=*|--beamline=*) @@ -24,6 +24,10 @@ for option in "$@"; do LOGIN=false shift ;; + --lint) + LINT=true + shift + ;; --dry-run) DRY_RUN=true shift @@ -53,6 +57,7 @@ Options: --dry-run Do everything but don't do the final deploy to k8s --no-login Do not attempt to log in to kubernetes instead use the current namespace and cluster --repository=REPOSITORY Override the repository to fetch the image from + --lint Lint the helm chart EOM exit 0 ;; @@ -135,6 +140,10 @@ if [[ $LOGIN = true ]]; then module load $CLUSTER kubectl config set-context --current --namespace=$NAMESPACE fi -if [[ -z $DRY_RUN ]]; then +if [[ $LINT = true ]]; then + helm lint $HELMCHART_DIR $HELM_OPTIONS +elif [[ -z $DRY_RUN ]]; then helm upgrade --install $HELM_OPTIONS $RELEASE $APP_NAME-0.0.1.tgz +else + echo "helm upgrade --install $HELM_OPTIONS $RELEASE $APP_NAME-0.0.1.tgz" fi diff --git a/utility_scripts/docker/initialise_scratch.sh b/utility_scripts/docker/initialise_scratch.sh index 06de63a770..cd092671c5 100755 --- a/utility_scripts/docker/initialise_scratch.sh +++ b/utility_scripts/docker/initialise_scratch.sh @@ -9,4 +9,7 @@ if [ ! -d $SCRATCH_ROOT/mx-bluesky/.git ]; then git clone /app/mx-bluesky/.git $SCRATCH_ROOT/mx-bluesky cd $SCRATCH_ROOT/mx-bluesky git checkout $CURRENT_BRANCH + cd $APP_ROOT/mx-bluesky + . ./.venv/bin/activate + uv pip install -e $SCRATCH_ROOT/mx-bluesky fi From bb094f24f91c6361e61849327a05b1a05cc3f42f Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Tue, 26 May 2026 11:06:14 +0100 Subject: [PATCH 07/27] Additional debugging for initContainer --- helm/hyperion-supervisor/templates/deployment.yaml | 3 --- helm/rabbitmq/values.yaml | 12 ------------ .../deploy/deploy_mx_bluesky_app_to_k8s.sh | 9 +++++---- utility_scripts/docker/initialise_scratch.sh | 3 +++ 4 files changed, 8 insertions(+), 19 deletions(-) delete mode 100644 helm/rabbitmq/values.yaml diff --git a/helm/hyperion-supervisor/templates/deployment.yaml b/helm/hyperion-supervisor/templates/deployment.yaml index 81243bb4a9..8946f1c83a 100644 --- a/helm/hyperion-supervisor/templates/deployment.yaml +++ b/helm/hyperion-supervisor/templates/deployment.yaml @@ -12,9 +12,6 @@ spec: labels: app: hyperion-supervisor spec: - {{- if .Values.application.dev }} - restartPolicy: Never - {{- end }} volumes: # Bind some source folders for easier debugging - name: scratch diff --git a/helm/rabbitmq/values.yaml b/helm/rabbitmq/values.yaml deleted file mode 100644 index 115e42607d..0000000000 --- a/helm/rabbitmq/values.yaml +++ /dev/null @@ -1,12 +0,0 @@ -rabbitmq: - plugins: - - rabbitmq_stomp - service: - extraPorts: - - name: stomp - protocol: TCP - containerPort: 61613 - port: 61613 - authentication: - erlangCookie: - value: DEFAULT_COOKIE diff --git a/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh b/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh index 7322327663..593ce10f53 100755 --- a/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh +++ b/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh @@ -140,10 +140,11 @@ if [[ $LOGIN = true ]]; then module load $CLUSTER kubectl config set-context --current --namespace=$NAMESPACE fi +if [[ $DRY_RUN = true ]]; then + HELM_OPTIONS+="--dry-run=server --debug " +fi if [[ $LINT = true ]]; then - helm lint $HELMCHART_DIR $HELM_OPTIONS -elif [[ -z $DRY_RUN ]]; then - helm upgrade --install $HELM_OPTIONS $RELEASE $APP_NAME-0.0.1.tgz + helm lint $HELMCHART_DIR --strict --values $HELMCHART_DIR/values.yaml $HELM_OPTIONS else - echo "helm upgrade --install $HELM_OPTIONS $RELEASE $APP_NAME-0.0.1.tgz" + helm upgrade --install $HELM_OPTIONS $RELEASE $APP_NAME-0.0.1.tgz fi diff --git a/utility_scripts/docker/initialise_scratch.sh b/utility_scripts/docker/initialise_scratch.sh index cd092671c5..800b7e5fb4 100755 --- a/utility_scripts/docker/initialise_scratch.sh +++ b/utility_scripts/docker/initialise_scratch.sh @@ -8,6 +8,9 @@ if [ ! -d $SCRATCH_ROOT/mx-bluesky/.git ]; then CURRENT_BRANCH=$(git --git-dir=$APP_ROOT/mx-bluesky/.git rev-parse --abbrev-ref HEAD) git clone /app/mx-bluesky/.git $SCRATCH_ROOT/mx-bluesky cd $SCRATCH_ROOT/mx-bluesky + ls -la $APP_ROOT/mx-bluesky/.git + echo "Checking out $CURRENT_BRANCH... as $UID" + ls -la $SCRATCH_ROOT/mx-bluesky/.git git checkout $CURRENT_BRANCH cd $APP_ROOT/mx-bluesky . ./.venv/bin/activate From a196466ff30936ae51e21c2aa7c818f3d327d840 Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Tue, 26 May 2026 11:32:02 +0100 Subject: [PATCH 08/27] More debugging of initialise script --- utility_scripts/docker/initialise_scratch.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/utility_scripts/docker/initialise_scratch.sh b/utility_scripts/docker/initialise_scratch.sh index 800b7e5fb4..3ca3eb3860 100755 --- a/utility_scripts/docker/initialise_scratch.sh +++ b/utility_scripts/docker/initialise_scratch.sh @@ -16,3 +16,4 @@ if [ ! -d $SCRATCH_ROOT/mx-bluesky/.git ]; then . ./.venv/bin/activate uv pip install -e $SCRATCH_ROOT/mx-bluesky fi +sleep 600 From df563bbf830a185f14968b98f8e29220b0d8f31a Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Tue, 26 May 2026 13:03:07 +0100 Subject: [PATCH 09/27] Update dockerfile to add user, group creation --- Dockerfile.hyperion | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Dockerfile.hyperion b/Dockerfile.hyperion index 901ff66097..b6ce5a554b 100644 --- a/Dockerfile.hyperion +++ b/Dockerfile.hyperion @@ -24,6 +24,10 @@ COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ ADD .git /app/mx-bluesky/.git RUN mkdir -p /scratch && mkdir -p /app/scripts +# Create the hyperion user and group which will be needed in the deployment securityContext +RUN groupadd -r -g 1000 hyperion && \ + useradd -r -u 1000 -g hyperion hyperion + ############################################################################# FROM base-image as uv-staging @@ -33,7 +37,7 @@ WORKDIR "/app/mx-bluesky" COPY pyproject.toml uv.lock ./ RUN mkdir -p src/mx_bluesky && \ git restore . && \ - uv sync --compile-bytecode --no-cache --locked + uv sync --no-cache --locked ############################################################################# FROM base-image as build From 676c25ddb56d0ecf7cbc3049e5289a0272c4dd49 Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Tue, 26 May 2026 13:50:56 +0100 Subject: [PATCH 10/27] Change ownership of image directories --- Dockerfile.hyperion | 16 +++++++++++----- .../templates/deployment.yaml | 4 ++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Dockerfile.hyperion b/Dockerfile.hyperion index b6ce5a554b..0908170511 100644 --- a/Dockerfile.hyperion +++ b/Dockerfile.hyperion @@ -21,13 +21,14 @@ RUN apt update -y && \ # Install matching uv binaries for our python distro COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ -ADD .git /app/mx-bluesky/.git -RUN mkdir -p /scratch && mkdir -p /app/scripts - # Create the hyperion user and group which will be needed in the deployment securityContext RUN groupadd -r -g 1000 hyperion && \ useradd -r -u 1000 -g hyperion hyperion +ADD --chown=hyperion:hyperion .git /app/mx-bluesky/.git +RUN mkdir -p /app/scripts && \ + chown hyperion:hyperion /app/scripts + ############################################################################# FROM base-image as uv-staging @@ -41,9 +42,14 @@ RUN mkdir -p src/mx_bluesky && \ ############################################################################# FROM base-image as build + WORKDIR "/app/mx-bluesky" -COPY --from=uv-staging /app/mx-bluesky/.venv /app/mx-bluesky/.venv -COPY utility_scripts/docker/initialise_scratch.sh /app/scripts/ +RUN mkdir /scratch && \ + chown hyperion:hyperion /scratch + +USER hyperion:hyperion +COPY --chown=hyperion:hyperion --from=uv-staging /app/mx-bluesky/.venv /app/mx-bluesky/.venv +COPY --chown=hyperion:hyperion utility_scripts/docker/initialise_scratch.sh /app/scripts/ ENTRYPOINT ["/scratch/mx-bluesky/utility_scripts/docker/entrypoint.sh"] diff --git a/helm/hyperion-supervisor/templates/deployment.yaml b/helm/hyperion-supervisor/templates/deployment.yaml index 8946f1c83a..e73bb690b3 100644 --- a/helm/hyperion-supervisor/templates/deployment.yaml +++ b/helm/hyperion-supervisor/templates/deployment.yaml @@ -12,6 +12,10 @@ spec: labels: app: hyperion-supervisor spec: + securityContext: + fsGroup: 1000 + runAsGroup: 1000 + runAsUser: 1000 volumes: # Bind some source folders for easier debugging - name: scratch From f6a32fc13bf482b68b61ad185b742037a0cf0736 Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Tue, 26 May 2026 14:20:10 +0100 Subject: [PATCH 11/27] Tweak dockerfile for ownership --- Dockerfile.hyperion | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile.hyperion b/Dockerfile.hyperion index 0908170511..677228c51c 100644 --- a/Dockerfile.hyperion +++ b/Dockerfile.hyperion @@ -23,7 +23,7 @@ COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ # Create the hyperion user and group which will be needed in the deployment securityContext RUN groupadd -r -g 1000 hyperion && \ - useradd -r -u 1000 -g hyperion hyperion + useradd -r -u 1000 -g hyperion -d /app hyperion ADD --chown=hyperion:hyperion .git /app/mx-bluesky/.git RUN mkdir -p /app/scripts && \ @@ -37,6 +37,7 @@ FROM base-image as uv-staging WORKDIR "/app/mx-bluesky" COPY pyproject.toml uv.lock ./ RUN mkdir -p src/mx_bluesky && \ + git config --global --add safe.directory /app/mx-bluesky && \ git restore . && \ uv sync --no-cache --locked From 53d8fafaeb83a5f1c513645617cdc837dd5c400e Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Tue, 26 May 2026 14:33:10 +0100 Subject: [PATCH 12/27] Add dodal to the dockerfile --- Dockerfile.hyperion | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Dockerfile.hyperion b/Dockerfile.hyperion index 677228c51c..56b65ed0f2 100644 --- a/Dockerfile.hyperion +++ b/Dockerfile.hyperion @@ -3,6 +3,7 @@ # The image will contain the directory structure: # /app/mx-bluesky/.venv # /app/mx-bluesky/.git +# /app/dodal/.git # /app/mx-bluesky/scripts # but we don't include the source folder structure for mx-bluesky or dodal since these will be # deployed in a separate volume by the initContainer for the scratch folder @@ -49,6 +50,9 @@ RUN mkdir /scratch && \ chown hyperion:hyperion /scratch USER hyperion:hyperion + +RUN git clone --bare https://github.com/DiamondLightSource/dodal.git /app/dodal/.git + COPY --chown=hyperion:hyperion --from=uv-staging /app/mx-bluesky/.venv /app/mx-bluesky/.venv COPY --chown=hyperion:hyperion utility_scripts/docker/initialise_scratch.sh /app/scripts/ From 5d53b05bf9b6aa352df37d20192a9aee4404283b Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Tue, 26 May 2026 14:46:35 +0100 Subject: [PATCH 13/27] Update image, initialisation to check out dodal --- .../templates/deployment.yaml | 2 ++ helm/hyperion-supervisor/values.yaml | 2 ++ utility_scripts/docker/initialise_scratch.sh | 18 +++++++++++++----- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/helm/hyperion-supervisor/templates/deployment.yaml b/helm/hyperion-supervisor/templates/deployment.yaml index e73bb690b3..533dc4b00e 100644 --- a/helm/hyperion-supervisor/templates/deployment.yaml +++ b/helm/hyperion-supervisor/templates/deployment.yaml @@ -31,6 +31,8 @@ spec: volumeMounts: - name: scratch mountPath: "/scratch" + env: + - DODAL_BRANCH: {{ .Values.initContainer.dodalBranch }} containers: - name: hyperion-supervisor image: {{ .Values.application.imageRepository}}/hyperion:{{ .Values.application.imageVersion }} diff --git a/helm/hyperion-supervisor/values.yaml b/helm/hyperion-supervisor/values.yaml index 9306a1db7c..3a24c5ddc8 100644 --- a/helm/hyperion-supervisor/values.yaml +++ b/helm/hyperion-supervisor/values.yaml @@ -7,6 +7,8 @@ application: beamline: i03 dev: false logDir: "/var/logs/mx-bluesky" +initContainer: + dodalBranch: "main" scratch: volumeSize: "2Gi" configServer: diff --git a/utility_scripts/docker/initialise_scratch.sh b/utility_scripts/docker/initialise_scratch.sh index 3ca3eb3860..6f068632fa 100755 --- a/utility_scripts/docker/initialise_scratch.sh +++ b/utility_scripts/docker/initialise_scratch.sh @@ -4,16 +4,24 @@ SCRATCH_ROOT=/scratch APP_ROOT=/app +if [ ! -d $SCRATCH_ROOT/dodal/.git ]; then + git clone /app/dodal/.git $SCRATCH_ROOT/dodal + echo "Checking out dodal branch $DODAL_BRANCH" + git --git-dir=$SCRATCH_ROOT/dodal checkout $DODAL_BRANCH +fi + if [ ! -d $SCRATCH_ROOT/mx-bluesky/.git ]; then CURRENT_BRANCH=$(git --git-dir=$APP_ROOT/mx-bluesky/.git rev-parse --abbrev-ref HEAD) git clone /app/mx-bluesky/.git $SCRATCH_ROOT/mx-bluesky - cd $SCRATCH_ROOT/mx-bluesky ls -la $APP_ROOT/mx-bluesky/.git echo "Checking out $CURRENT_BRANCH... as $UID" ls -la $SCRATCH_ROOT/mx-bluesky/.git - git checkout $CURRENT_BRANCH - cd $APP_ROOT/mx-bluesky - . ./.venv/bin/activate - uv pip install -e $SCRATCH_ROOT/mx-bluesky + git --git-dir=$SCRATCH_ROOT/mx-bluesky checkout $CURRENT_BRANCH fi + +cd $APP_ROOT/mx-bluesky +. ./.venv/bin/activate +uv pip install -e $SCRATCH_ROOT/mx-bluesky +uv pip install -e $SCRATCH_ROOT/dodal + sleep 600 From 93cd674ea2e3d8f041614e255b897b57005aba38 Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Tue, 26 May 2026 14:55:31 +0100 Subject: [PATCH 14/27] fix git dir --- helm/hyperion-supervisor/templates/deployment.yaml | 3 ++- utility_scripts/docker/initialise_scratch.sh | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/helm/hyperion-supervisor/templates/deployment.yaml b/helm/hyperion-supervisor/templates/deployment.yaml index 533dc4b00e..26ad639abf 100644 --- a/helm/hyperion-supervisor/templates/deployment.yaml +++ b/helm/hyperion-supervisor/templates/deployment.yaml @@ -32,7 +32,8 @@ spec: - name: scratch mountPath: "/scratch" env: - - DODAL_BRANCH: {{ .Values.initContainer.dodalBranch }} + - name: DODAL_BRANCH + value: {{ .Values.initContainer.dodalBranch }} containers: - name: hyperion-supervisor image: {{ .Values.application.imageRepository}}/hyperion:{{ .Values.application.imageVersion }} diff --git a/utility_scripts/docker/initialise_scratch.sh b/utility_scripts/docker/initialise_scratch.sh index 6f068632fa..f1883b33b8 100755 --- a/utility_scripts/docker/initialise_scratch.sh +++ b/utility_scripts/docker/initialise_scratch.sh @@ -7,7 +7,7 @@ APP_ROOT=/app if [ ! -d $SCRATCH_ROOT/dodal/.git ]; then git clone /app/dodal/.git $SCRATCH_ROOT/dodal echo "Checking out dodal branch $DODAL_BRANCH" - git --git-dir=$SCRATCH_ROOT/dodal checkout $DODAL_BRANCH + git --git-dir=$SCRATCH_ROOT/dodal/.git checkout $DODAL_BRANCH fi if [ ! -d $SCRATCH_ROOT/mx-bluesky/.git ]; then @@ -16,7 +16,7 @@ if [ ! -d $SCRATCH_ROOT/mx-bluesky/.git ]; then ls -la $APP_ROOT/mx-bluesky/.git echo "Checking out $CURRENT_BRANCH... as $UID" ls -la $SCRATCH_ROOT/mx-bluesky/.git - git --git-dir=$SCRATCH_ROOT/mx-bluesky checkout $CURRENT_BRANCH + git --git-dir=$SCRATCH_ROOT/mx-bluesky/.git checkout $CURRENT_BRANCH fi cd $APP_ROOT/mx-bluesky From 4f700c8fb7f4db269d04cb0612ad0dee511e1e57 Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Tue, 26 May 2026 16:54:21 +0100 Subject: [PATCH 15/27] Fixes/more debugging of entrypoint script --- helm/hyperion-supervisor/templates/deployment.yaml | 9 ++++++--- helm/hyperion-supervisor/values.yaml | 8 ++++++++ utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh | 1 + utility_scripts/docker/entrypoint.sh | 8 +++++--- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/helm/hyperion-supervisor/templates/deployment.yaml b/helm/hyperion-supervisor/templates/deployment.yaml index 26ad639abf..858387984d 100644 --- a/helm/hyperion-supervisor/templates/deployment.yaml +++ b/helm/hyperion-supervisor/templates/deployment.yaml @@ -13,9 +13,9 @@ spec: app: hyperion-supervisor spec: securityContext: - fsGroup: 1000 - runAsGroup: 1000 - runAsUser: 1000 + fsGroup: {{ .Values.application.runAsGroup }} + runAsGroup: {{ .Values.application.runAsGroup }} + runAsUser: {{ .Values.application.runAsUser }} volumes: # Bind some source folders for easier debugging - name: scratch @@ -24,6 +24,7 @@ spec: - name: config configMap: name: hyperion-supervisor-config + {{- toYaml .Values.logging.volume | nindent 8 }} initContainers: - name: hyperion-init image: {{ .Values.application.imageRepository}}/hyperion:{{ .Values.application.imageVersion }} @@ -70,3 +71,5 @@ spec: - mountPath: "/etc/hyperion" name: config readOnly: true + - mountPath: "/var/log/bluesky" + name: logdir diff --git a/helm/hyperion-supervisor/values.yaml b/helm/hyperion-supervisor/values.yaml index 3a24c5ddc8..4e66facddd 100644 --- a/helm/hyperion-supervisor/values.yaml +++ b/helm/hyperion-supervisor/values.yaml @@ -7,6 +7,8 @@ application: beamline: i03 dev: false logDir: "/var/logs/mx-bluesky" + runAsUser: 1000 + runAsGroup: 1000 initContainer: dodalBranch: "main" scratch: @@ -19,3 +21,9 @@ stomp: url: tcp://localhost:61613 blueapi: url: http://my.blueapi.service:5005 +logging: + volume: + - name: logdir + emptyDir: {} +# hostPath: "/dls_sw/i03/logs/bluesky/hyperion-k8s" +# type: Directory diff --git a/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh b/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh index 593ce10f53..ccaff76ddc 100755 --- a/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh +++ b/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh @@ -144,6 +144,7 @@ if [[ $DRY_RUN = true ]]; then HELM_OPTIONS+="--dry-run=server --debug " fi if [[ $LINT = true ]]; then + helm template $RELEASE $HELMCHART_DIR $HELM_OPTIONS helm lint $HELMCHART_DIR --strict --values $HELMCHART_DIR/values.yaml $HELM_OPTIONS else helm upgrade --install $HELM_OPTIONS $RELEASE $APP_NAME-0.0.1.tgz diff --git a/utility_scripts/docker/entrypoint.sh b/utility_scripts/docker/entrypoint.sh index 535604ed44..ee73159516 100755 --- a/utility_scripts/docker/entrypoint.sh +++ b/utility_scripts/docker/entrypoint.sh @@ -3,6 +3,8 @@ # as well as the main server IN_DEV=false CALLBACKS=false +APP_DIR=/app/mx-bluesky + for option in "$@"; do case $option in --dev) @@ -32,10 +34,10 @@ for option in "$@"; do esac done -RELATIVE_SCRIPT_DIR=$( dirname -- "$0"; ) -cd ${RELATIVE_SCRIPT_DIR} -. /app/mx-bluesky/.venv/bin/activate +cd $APP_DIR +. .venv/bin/activate +uv pip list echo "$(date) Logging to $LOG_DIR" mkdir -p $LOG_DIR From 88ec648fef4637be23a9b39be1056a097d65a938 Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Tue, 26 May 2026 16:55:22 +0100 Subject: [PATCH 16/27] More debuggablility --- utility_scripts/docker/entrypoint.sh | 1 + utility_scripts/docker/initialise_scratch.sh | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/utility_scripts/docker/entrypoint.sh b/utility_scripts/docker/entrypoint.sh index ee73159516..9efcf76a94 100755 --- a/utility_scripts/docker/entrypoint.sh +++ b/utility_scripts/docker/entrypoint.sh @@ -58,3 +58,4 @@ fi echo "$(date) Starting $command..." $command $args +sleep 600 diff --git a/utility_scripts/docker/initialise_scratch.sh b/utility_scripts/docker/initialise_scratch.sh index f1883b33b8..45c02cc938 100755 --- a/utility_scripts/docker/initialise_scratch.sh +++ b/utility_scripts/docker/initialise_scratch.sh @@ -23,5 +23,3 @@ cd $APP_ROOT/mx-bluesky . ./.venv/bin/activate uv pip install -e $SCRATCH_ROOT/mx-bluesky uv pip install -e $SCRATCH_ROOT/dodal - -sleep 600 From 512983b76ad6047c3ea9f791741673b5705cfa46 Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Wed, 27 May 2026 09:57:47 +0100 Subject: [PATCH 17/27] Fix PYTHONPATH to import mx-bluesky, dodal --- helm/hyperion-supervisor/templates/deployment.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/helm/hyperion-supervisor/templates/deployment.yaml b/helm/hyperion-supervisor/templates/deployment.yaml index 858387984d..d89e262862 100644 --- a/helm/hyperion-supervisor/templates/deployment.yaml +++ b/helm/hyperion-supervisor/templates/deployment.yaml @@ -60,6 +60,8 @@ spec: value: "{{ .Values.application.beamline }}" - name: CONFIG_SERVER_URL value: "{{ .Values.configServer.url }}" + - name: PYTHONPATH + value: "/scratch/mx-bluesky/src:/scratch/dodal/src" readinessProbe: exec: command: [ "/scratch/mx-bluesky/utility_scripts/docker/healthcheck.sh" ] From cf219ed52c6fbf95ac437f3f5d4beda58203d198 Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Wed, 27 May 2026 10:06:12 +0100 Subject: [PATCH 18/27] Tidy the initContainer script --- utility_scripts/docker/initialise_scratch.sh | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/utility_scripts/docker/initialise_scratch.sh b/utility_scripts/docker/initialise_scratch.sh index 45c02cc938..e76e492635 100755 --- a/utility_scripts/docker/initialise_scratch.sh +++ b/utility_scripts/docker/initialise_scratch.sh @@ -1,6 +1,9 @@ #!/bin/bash # This script is run in the initContainer before the main hyperion pod is launched to initialise the scratch area -# if not already present +# if not already present. +# +# dodal and mx-bluesky are not installed with uv pip install since this requires the .venv to be writable +# instead they are added to PYTHONPATH in the container SCRATCH_ROOT=/scratch APP_ROOT=/app @@ -18,8 +21,3 @@ if [ ! -d $SCRATCH_ROOT/mx-bluesky/.git ]; then ls -la $SCRATCH_ROOT/mx-bluesky/.git git --git-dir=$SCRATCH_ROOT/mx-bluesky/.git checkout $CURRENT_BRANCH fi - -cd $APP_ROOT/mx-bluesky -. ./.venv/bin/activate -uv pip install -e $SCRATCH_ROOT/mx-bluesky -uv pip install -e $SCRATCH_ROOT/dodal From fef707485e90c160100925675936988413d8bf29 Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Wed, 27 May 2026 10:54:25 +0100 Subject: [PATCH 19/27] Convert to statefulset --- .../templates/{deployment.yaml => statefulset.yaml} | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) rename helm/hyperion-supervisor/templates/{deployment.yaml => statefulset.yaml} (92%) diff --git a/helm/hyperion-supervisor/templates/deployment.yaml b/helm/hyperion-supervisor/templates/statefulset.yaml similarity index 92% rename from helm/hyperion-supervisor/templates/deployment.yaml rename to helm/hyperion-supervisor/templates/statefulset.yaml index d89e262862..cb073cf653 100644 --- a/helm/hyperion-supervisor/templates/deployment.yaml +++ b/helm/hyperion-supervisor/templates/statefulset.yaml @@ -1,16 +1,17 @@ apiVersion: apps/v1 -kind: Deployment +kind: StatefulSet metadata: - name: hyperion-supervisor-deployment + name: hyperion-supervisor-statefulset spec: selector: matchLabels: - app: hyperion-supervisor + app.kubernetes.io/name: hyperion-supervisor replicas: 1 template: metadata: labels: - app: hyperion-supervisor + app.kubernetes.io/name: hyperion-supervisor + app.kubernetes.io/instance: {{ .Release.Name }} spec: securityContext: fsGroup: {{ .Values.application.runAsGroup }} From 14b7c8dfb757eb64bff128e02061ee62f817f875 Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Wed, 27 May 2026 11:17:06 +0100 Subject: [PATCH 20/27] Fix scratch initialisation --- utility_scripts/docker/initialise_scratch.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/utility_scripts/docker/initialise_scratch.sh b/utility_scripts/docker/initialise_scratch.sh index e76e492635..9b0cc218b4 100755 --- a/utility_scripts/docker/initialise_scratch.sh +++ b/utility_scripts/docker/initialise_scratch.sh @@ -1,9 +1,7 @@ #!/bin/bash # This script is run in the initContainer before the main hyperion pod is launched to initialise the scratch area # if not already present. -# -# dodal and mx-bluesky are not installed with uv pip install since this requires the .venv to be writable -# instead they are added to PYTHONPATH in the container + SCRATCH_ROOT=/scratch APP_ROOT=/app @@ -21,3 +19,10 @@ if [ ! -d $SCRATCH_ROOT/mx-bluesky/.git ]; then ls -la $SCRATCH_ROOT/mx-bluesky/.git git --git-dir=$SCRATCH_ROOT/mx-bluesky/.git checkout $CURRENT_BRANCH fi + +# dodal and mx-bluesky are installed with uv pip install however since the writable layer for the .venv is ephemeral +# they still need to be added to PYTHONPATH in the container +cd $APP_ROOT/mx-bluesky +. ./.venv/bin/activate +uv pip install -e $SCRATCH_ROOT/mx-bluesky +uv pip install -e $SCRATCH_ROOT/dodal From 1ef7a4c2bf6b9813ccabc6b92d63c7d084b19be9 Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Wed, 27 May 2026 12:30:43 +0100 Subject: [PATCH 21/27] Hyperion supervisor starts, revert statefulset back to deployment --- .../templates/configmap.yaml | 1 + .../{statefulset.yaml => deployment.yaml} | 17 ++++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) rename helm/hyperion-supervisor/templates/{statefulset.yaml => deployment.yaml} (88%) diff --git a/helm/hyperion-supervisor/templates/configmap.yaml b/helm/hyperion-supervisor/templates/configmap.yaml index 9f326f55a2..71a72518aa 100644 --- a/helm/hyperion-supervisor/templates/configmap.yaml +++ b/helm/hyperion-supervisor/templates/configmap.yaml @@ -9,6 +9,7 @@ data: sources: - kind: deviceManager module: dodal.beamlines.{{ .Values.application.beamline }}_supervisor + mock: {{ .Values.application.dev }} logging: graylog: url: {{ .Values.graylog.url }} diff --git a/helm/hyperion-supervisor/templates/statefulset.yaml b/helm/hyperion-supervisor/templates/deployment.yaml similarity index 88% rename from helm/hyperion-supervisor/templates/statefulset.yaml rename to helm/hyperion-supervisor/templates/deployment.yaml index cb073cf653..a76acbca8b 100644 --- a/helm/hyperion-supervisor/templates/statefulset.yaml +++ b/helm/hyperion-supervisor/templates/deployment.yaml @@ -1,17 +1,18 @@ apiVersion: apps/v1 -kind: StatefulSet +kind: Deployment metadata: - name: hyperion-supervisor-statefulset + name: hyperion-supervisor-deployment spec: selector: matchLabels: - app.kubernetes.io/name: hyperion-supervisor + app: hyperion-supervisor + strategy: + type: Recreate replicas: 1 template: metadata: labels: - app.kubernetes.io/name: hyperion-supervisor - app.kubernetes.io/instance: {{ .Release.Name }} + app: hyperion-supervisor spec: securityContext: fsGroup: {{ .Values.application.runAsGroup }} @@ -64,8 +65,10 @@ spec: - name: PYTHONPATH value: "/scratch/mx-bluesky/src:/scratch/dodal/src" readinessProbe: - exec: - command: [ "/scratch/mx-bluesky/utility_scripts/docker/healthcheck.sh" ] + httpGet: + path: "/status" + port: {{ .Values.application.containerPort }} + initialDelaySeconds: 30 periodSeconds: 5 volumeMounts: - mountPath: "/scratch" From c13f55a97502aacaf7e9cce05ca401ef3cafa53c Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Wed, 27 May 2026 15:35:35 +0100 Subject: [PATCH 22/27] Initial attempt at callbacks --- .../templates/deployment.yaml | 81 ---------- .../Chart.yaml | 4 +- .../templates/configmap.yaml | 10 ++ helm/hyperion/templates/deployment.yaml | 145 ++++++++++++++++++ .../templates/service.yaml | 4 +- .../templates/volumes.yaml | 0 helm/hyperion/templates/zocalo-config.yaml | 37 +++++ .../values.yaml | 33 +++- utility_scripts/docker/entrypoint.sh | 2 +- 9 files changed, 224 insertions(+), 92 deletions(-) delete mode 100644 helm/hyperion-supervisor/templates/deployment.yaml rename helm/{hyperion-supervisor => hyperion}/Chart.yaml (53%) rename helm/{hyperion-supervisor => hyperion}/templates/configmap.yaml (78%) create mode 100644 helm/hyperion/templates/deployment.yaml rename helm/{hyperion-supervisor => hyperion}/templates/service.yaml (72%) rename helm/{hyperion-supervisor => hyperion}/templates/volumes.yaml (100%) create mode 100644 helm/hyperion/templates/zocalo-config.yaml rename helm/{hyperion-supervisor => hyperion}/values.yaml (51%) diff --git a/helm/hyperion-supervisor/templates/deployment.yaml b/helm/hyperion-supervisor/templates/deployment.yaml deleted file mode 100644 index a76acbca8b..0000000000 --- a/helm/hyperion-supervisor/templates/deployment.yaml +++ /dev/null @@ -1,81 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: hyperion-supervisor-deployment -spec: - selector: - matchLabels: - app: hyperion-supervisor - strategy: - type: Recreate - replicas: 1 - template: - metadata: - labels: - app: hyperion-supervisor - spec: - securityContext: - fsGroup: {{ .Values.application.runAsGroup }} - runAsGroup: {{ .Values.application.runAsGroup }} - runAsUser: {{ .Values.application.runAsUser }} - volumes: - # Bind some source folders for easier debugging - - name: scratch - persistentVolumeClaim: - claimName: hyperion-supervisor-scratch-{{ .Values.application.imageVersion }} - - name: config - configMap: - name: hyperion-supervisor-config - {{- toYaml .Values.logging.volume | nindent 8 }} - initContainers: - - name: hyperion-init - image: {{ .Values.application.imageRepository}}/hyperion:{{ .Values.application.imageVersion }} - command: ['/app/scripts/initialise_scratch.sh'] - volumeMounts: - - name: scratch - mountPath: "/scratch" - env: - - name: DODAL_BRANCH - value: {{ .Values.initContainer.dodalBranch }} - containers: - - name: hyperion-supervisor - image: {{ .Values.application.imageRepository}}/hyperion:{{ .Values.application.imageVersion }} - command: ['/scratch/mx-bluesky/utility_scripts/docker/entrypoint.sh'] - args: - {{- if .Values.application.dev }} - - "--dev" - {{- end }} - resources: - limits: - cpu: "1" - memory: "1Gi" - ports: - - name: rest-api - containerPort: {{ .Values.application.containerPort }} - protocol: TCP - env: - - name: LOG_DIR - value: /var/log/bluesky - - name: DEBUG_LOG_DIR - value: /var/log/bluesky/debug - - name: BEAMLINE - value: "{{ .Values.application.beamline }}" - - name: CONFIG_SERVER_URL - value: "{{ .Values.configServer.url }}" - - name: PYTHONPATH - value: "/scratch/mx-bluesky/src:/scratch/dodal/src" - readinessProbe: - httpGet: - path: "/status" - port: {{ .Values.application.containerPort }} - initialDelaySeconds: 30 - periodSeconds: 5 - volumeMounts: - - mountPath: "/scratch" - name: scratch - readOnly: true - - mountPath: "/etc/hyperion" - name: config - readOnly: true - - mountPath: "/var/log/bluesky" - name: logdir diff --git a/helm/hyperion-supervisor/Chart.yaml b/helm/hyperion/Chart.yaml similarity index 53% rename from helm/hyperion-supervisor/Chart.yaml rename to helm/hyperion/Chart.yaml index a3539a626d..e786d03398 100644 --- a/helm/hyperion-supervisor/Chart.yaml +++ b/helm/hyperion/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 -name: hyperion-supervisor -description: Hyperion Supervisor +name: hyperion +description: Hyperion Supervisor and Callbacks type: application # version of the chart version: 0.0.1 diff --git a/helm/hyperion-supervisor/templates/configmap.yaml b/helm/hyperion/templates/configmap.yaml similarity index 78% rename from helm/hyperion-supervisor/templates/configmap.yaml rename to helm/hyperion/templates/configmap.yaml index 71a72518aa..def19432d4 100644 --- a/helm/hyperion-supervisor/templates/configmap.yaml +++ b/helm/hyperion/templates/configmap.yaml @@ -21,3 +21,13 @@ data: stomp: enabled: true url: {{ .Values.stomp.url }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: hyperion-callbacks-config +data: + blueapi_callbacks.yml: |- + stomp: + enabled: true + url: {{ .Values.stomp.url }} diff --git a/helm/hyperion/templates/deployment.yaml b/helm/hyperion/templates/deployment.yaml new file mode 100644 index 0000000000..54917b5bf3 --- /dev/null +++ b/helm/hyperion/templates/deployment.yaml @@ -0,0 +1,145 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: hyperion-deployment +spec: + selector: + matchLabels: + app: hyperion + strategy: + type: Recreate + replicas: 1 + template: + metadata: + labels: + app: hyperion + spec: + securityContext: + fsGroup: {{ .Values.supervisor.runAsGroup }} + runAsGroup: {{ .Values.supervisor.runAsGroup }} + runAsUser: {{ .Values.supervisor.runAsUser }} + volumes: + # Bind some source folders for easier debugging + - name: scratch + persistentVolumeClaim: + claimName: hyperion-supervisor-scratch-{{ .Values.application.imageVersion }} + - name: supervisor-config + configMap: + name: hyperion-supervisor-config + - name: callbacks-config + configMap: + name: hyperion-callbacks-config + {{- toYaml .Values.volumes.logging | nindent 8 }} + {{- toYaml .Values.volumes.data | nindent 8 }} + - name: expeye-secrets + secret: + secretName: ispyb-hyperion-cfg + - name: zocalo-config + configMap: + name: zocalo-config + defaultMode: 420 + - name: zocalo-secrets + secret: + secretName: rmq-creds + initContainers: + - name: hyperion-init + image: {{ .Values.application.imageRepository}}/hyperion:{{ .Values.application.imageVersion }} + command: ['/app/scripts/initialise_scratch.sh'] + volumeMounts: + - name: scratch + mountPath: "/scratch" + env: + - name: DODAL_BRANCH + value: {{ .Values.initContainer.dodalBranch }} + containers: + - name: hyperion-supervisor + image: {{ .Values.application.imageRepository}}/hyperion:{{ .Values.application.imageVersion }} + command: ['/scratch/mx-bluesky/utility_scripts/docker/entrypoint.sh'] + args: + {{- if .Values.application.dev }} + - "--dev" + {{- end }} + resources: + limits: + cpu: "1" + memory: "1Gi" + ports: + - name: rest-api + containerPort: {{ .Values.supervisor.containerPort }} + protocol: TCP + env: + - name: LOG_DIR + value: /var/log/bluesky + - name: DEBUG_LOG_DIR + value: /var/log/bluesky/debug + - name: BEAMLINE + value: "{{ .Values.application.beamline }}" + - name: CONFIG_SERVER_URL + value: "{{ .Values.configServer.url }}" + - name: PYTHONPATH + value: "/scratch/mx-bluesky/src:/scratch/dodal/src" + readinessProbe: + httpGet: + path: "/status" + port: {{ .Values.supervisor.containerPort }} + initialDelaySeconds: 30 + periodSeconds: 5 + volumeMounts: + - mountPath: "/scratch" + name: scratch + readOnly: true + - mountPath: "/etc/hyperion" + name: supervisor-config + readOnly: true + - mountPath: "/var/log/bluesky" + name: logdir + - name: hyperion-callbacks + image: {{ .Values.application.imageRepository}}/hyperion:{{ .Values.application.imageVersion }} + command: ['/scratch/mx-bluesky/utility_scripts/docker/entrypoint.sh'] + args: + - "--callbacks" + {{- if .Values.application.dev }} + - "--dev" + {{- end }} + securityContext: + fsGroup: {{ .Values.callbacks.runAsGroup }} + runAsGroup: {{ .Values.callbacks.runAsGroup }} + runAsUser: {{ .Values.callbacks.runAsUser }} + resources: + limits: + cpu: "1" + memory: "1Gi" + env: + - name: LOG_DIR + value: /var/log/bluesky + - name: DEBUG_LOG_DIR + value: /var/log/bluesky/debug + - name: BEAMLINE + value: "{{ .Values.application.beamline }}" + - name: CONFIG_SERVER_URL + value: "{{ .Values.configServer.url }}" + - name: PYTHONPATH + value: "/scratch/mx-bluesky/src:/scratch/dodal/src" + - name: ISPYB_CONFIG_PATH + value: "/etc/secrets/expeye/ispyb.cfg" +# readinessProbe: +# httpGet: +# path: "/status" +# port: {{ .Values.supervisor.containerPort }} +# initialDelaySeconds: 30 +# periodSeconds: 5 + volumeMounts: + - mountPath: "/scratch" + name: scratch + readOnly: true + - mountPath: "/etc/hyperion" + name: callbacks-config + readOnly: true + - mountPath: "/var/log/bluesky" + name: logdir + - mountPath: "/dls/{{ .Values.application.beamline }}/data" + name: data + - mountPath: "/etc/secrets/zocalo" + name: zocalo-secrets + - mountPath: "/etc/secrets/expeye" + name: expeye-secrets diff --git a/helm/hyperion-supervisor/templates/service.yaml b/helm/hyperion/templates/service.yaml similarity index 72% rename from helm/hyperion-supervisor/templates/service.yaml rename to helm/hyperion/templates/service.yaml index 5db81d381c..222f70e195 100644 --- a/helm/hyperion-supervisor/templates/service.yaml +++ b/helm/hyperion/templates/service.yaml @@ -10,8 +10,8 @@ spec: {{- end }} ports: - name: hyperion-supervisor-rest - port: {{ .Values.application.servicePort }} + port: {{ .Values.supervisor.servicePort }} protocol: TCP - targetPort: {{ .Values.application.containerPort }} + targetPort: {{ .Values.supervisor.containerPort }} selector: app: hyperion-supervisor diff --git a/helm/hyperion-supervisor/templates/volumes.yaml b/helm/hyperion/templates/volumes.yaml similarity index 100% rename from helm/hyperion-supervisor/templates/volumes.yaml rename to helm/hyperion/templates/volumes.yaml diff --git a/helm/hyperion/templates/zocalo-config.yaml b/helm/hyperion/templates/zocalo-config.yaml new file mode 100644 index 0000000000..0ce7498ad8 --- /dev/null +++ b/helm/hyperion/templates/zocalo-config.yaml @@ -0,0 +1,37 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: "zocalo-config" + namespace: "{{ .Release.Namespace }}" + labels: + app.kubernetes.io/name: zocalo-config + app.kubernetes.io/instance: "{{ .Release.Name }}-zocalo-config" + app.kubernetes.io/version: "{{ .Chart.Version }}" + app.kubernetes.io/part-of: hyperion +data: + configuration.yaml: |- + version: 1 + graylog: + plugin: graylog + {{- .Values.zocalo.graylog | toYaml | nindent 6 }} + {{- if .Values.zocalo.secrets }} + {{- range .Values.zocalo.secrets }} + {{ .name }}: "/etc/secrets/zocalo/{{ .fileName }}" + {{- end -}} {{/* range */}} + {{- end -}} {{/* if */}} + + + default-transport: + plugin: transport + default: {{ .Values.zocalo.defaultTransport }} + + environments: + + bluesky: + plugins: + - default-transport + {{- if .Values.zocalo.secrets }} + {{- range .Values.zocalo.secrets }} + - {{ .name }} + {{- end -}} {{/* range */}} + {{- end -}} {{/* if */}} diff --git a/helm/hyperion-supervisor/values.yaml b/helm/hyperion/values.yaml similarity index 51% rename from helm/hyperion-supervisor/values.yaml rename to helm/hyperion/values.yaml index 4e66facddd..be2bb301f7 100644 --- a/helm/hyperion-supervisor/values.yaml +++ b/helm/hyperion/values.yaml @@ -1,12 +1,16 @@ application: - containerPort: 5006 - servicePort: 80 imageRepository: ghcr.io/diamondlightsource imageName: hyperion imageVersion: SET_ON_INSTALL beamline: i03 dev: false logDir: "/var/logs/mx-bluesky" +supervisor: + servicePort: 80 + containerPort: 5006 + runAsUser: 1000 + runAsGroup: 1000 +callbacks: runAsUser: 1000 runAsGroup: 1000 initContainer: @@ -21,9 +25,26 @@ stomp: url: tcp://localhost:61613 blueapi: url: http://my.blueapi.service:5005 -logging: - volume: +volumes: + logging: - name: logdir emptyDir: {} -# hostPath: "/dls_sw/i03/logs/bluesky/hyperion-k8s" -# type: Directory +# hostPath: +# path: "/dls_sw/i03/logs/bluesky/hyperion-k8s" +# type: Directory + data: + - name: data + emptyDir: {} +# hostPath: +# type: Directory +# path: "/dls/i03/data" +zocalo: + defaultTransport: "PikaTransport" + graylog: + host: graylog-log-target.diamond.ac.uk + port: 12208 + protocol: UDP + secrets: + - name: rabbitmq + secretName: rmq-creds + fileName: rabbitmq-credentials.yml diff --git a/utility_scripts/docker/entrypoint.sh b/utility_scripts/docker/entrypoint.sh index 9efcf76a94..daf145262f 100755 --- a/utility_scripts/docker/entrypoint.sh +++ b/utility_scripts/docker/entrypoint.sh @@ -51,7 +51,7 @@ fi CONFIG_DIR=/etc/hyperion if [ $CALLBACKS == true ]; then command="hyperion-callbacks" - args+="--stomp-config $CONFIG_DIR/blueapi_callbacks.yml" + args+="--stomp-config $CONFIG_DIR/blueapi_callbacks.yaml" else args+="--mode supervisor --client-config $CONFIG_DIR/client_config.yaml --supervisor-config $CONFIG_DIR/supervisor_config.yaml" fi From 2181b555a85c37ee5586a1293f0c210aae0f23f7 Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Wed, 27 May 2026 16:55:25 +0100 Subject: [PATCH 23/27] More tweaks for callbacks, remove entrypoint script --- Dockerfile.hyperion | 8 +-- helm/hyperion/templates/deployment.yaml | 32 +++++++--- .../deploy/deploy_mx_bluesky_app_to_k8s.sh | 6 +- utility_scripts/docker/entrypoint.sh | 61 ------------------- 4 files changed, 29 insertions(+), 78 deletions(-) delete mode 100755 utility_scripts/docker/entrypoint.sh diff --git a/Dockerfile.hyperion b/Dockerfile.hyperion index 56b65ed0f2..2b2c4f4129 100644 --- a/Dockerfile.hyperion +++ b/Dockerfile.hyperion @@ -15,9 +15,9 @@ ARG SETUPTOOLS_SCM_PRETEND_VERSION_FOR_MX_BLUESKY # Need: # libgl, libglib2.0 for python cv2 dependency -RUN apt update -y && \ - apt upgrade -y && \ - apt install -y libgl1 libglib2.0-0 +RUN apt-get update -y && \ + apt-get upgrade -y && \ + apt-get install -y libgl1 libglib2.0-0 # Install matching uv binaries for our python distro COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ @@ -56,6 +56,4 @@ RUN git clone --bare https://github.com/DiamondLightSource/dodal.git /app/dodal/ COPY --chown=hyperion:hyperion --from=uv-staging /app/mx-bluesky/.venv /app/mx-bluesky/.venv COPY --chown=hyperion:hyperion utility_scripts/docker/initialise_scratch.sh /app/scripts/ -ENTRYPOINT ["/scratch/mx-bluesky/utility_scripts/docker/entrypoint.sh"] - EXPOSE 5006 diff --git a/helm/hyperion/templates/deployment.yaml b/helm/hyperion/templates/deployment.yaml index 54917b5bf3..819057375c 100644 --- a/helm/hyperion/templates/deployment.yaml +++ b/helm/hyperion/templates/deployment.yaml @@ -54,11 +54,17 @@ spec: containers: - name: hyperion-supervisor image: {{ .Values.application.imageRepository}}/hyperion:{{ .Values.application.imageVersion }} - command: ['/scratch/mx-bluesky/utility_scripts/docker/entrypoint.sh'] + command: ['/bin/bash', '-c'] args: - {{- if .Values.application.dev }} - - "--dev" - {{- end }} + - | + . /app/mx-bluesky/.venv/bin/activate + hyperion --mode supervisor \ + --client-config /etc/hyperion/client_config.yaml \ + --supervisor-config /etc/hyperion/supervisor_config.yaml + {{- if .Values.application.dev }} \ + --dev + sleep 600 + {{- end }} resources: limits: cpu: "1" @@ -95,12 +101,17 @@ spec: name: logdir - name: hyperion-callbacks image: {{ .Values.application.imageRepository}}/hyperion:{{ .Values.application.imageVersion }} - command: ['/scratch/mx-bluesky/utility_scripts/docker/entrypoint.sh'] + command: ['/bin/bash', '-c'] args: - - "--callbacks" - {{- if .Values.application.dev }} - - "--dev" - {{- end }} + - | + . /app/mx-bluesky/.venv/bin/activate + hyperion-callbacks \ + --watchdog-port {{ .Values.supervisor.containerPort }} \ + --stomp-config /etc/hyperion/blueapi_callbacks.yml + {{- if .Values.application.dev }} \ + --dev + sleep 600 + {{- end }} securityContext: fsGroup: {{ .Values.callbacks.runAsGroup }} runAsGroup: {{ .Values.callbacks.runAsGroup }} @@ -135,6 +146,9 @@ spec: - mountPath: "/etc/hyperion" name: callbacks-config readOnly: true + - mountPath: "/etc/zocalo" + name: zocalo-config + readOnly: true - mountPath: "/var/log/bluesky" name: logdir - mountPath: "/dls/{{ .Values.application.beamline }}/data" diff --git a/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh b/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh index ccaff76ddc..8a34955d99 100755 --- a/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh +++ b/utility_scripts/deploy/deploy_mx_bluesky_app_to_k8s.sh @@ -44,7 +44,7 @@ the container, NOT the directory that you built the container image from. Arguments: release Name of the helmchart release - app_name Use either "hyperion-supervisor" or "redis-to-murko" + app_name Use either "hyperion" or "redis-to-murko" Options: @@ -86,8 +86,8 @@ if [[ -z $APP_NAME ]]; then echo "App name must be specified, currently supporting hyperion and redis-to-murko" exit 1 else - if [[ "$APP_NAME" != "hyperion-supervisor" && "$APP_NAME" != "redis-to-murko" ]]; then - echo "Invalid app name specified. Please provide either 'hyperion-supervisor' or 'redis-to-murko'." + if [[ "$APP_NAME" != "hyperion" && "$APP_NAME" != "redis-to-murko" ]]; then + echo "Invalid app name specified. Please provide either 'hyperion' or 'redis-to-murko'." exit 1 fi fi diff --git a/utility_scripts/docker/entrypoint.sh b/utility_scripts/docker/entrypoint.sh deleted file mode 100755 index daf145262f..0000000000 --- a/utility_scripts/docker/entrypoint.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash -# Entry point for the production docker image that launches the external callbacks -# as well as the main server -IN_DEV=false -CALLBACKS=false -APP_DIR=/app/mx-bluesky - -for option in "$@"; do - case $option in - --dev) - IN_DEV=true - shift - ;; - --callbacks) - CALLBACKS=true - shift - ;; - --version) - . /app/mx-bluesky/.venv/bin/activate - hyperion --version - exit $? - ;; - --help|--info|--h) - echo "Arguments:" - echo " --dev start in development mode without external callbacks" - echo " --callbacks start hyperion callbacks, otherwise start hyperion-supervisor" - echo " --version print the hyperion version and exit" - exit 0 - ;; - -*|--*) - echo "Unknown option ${option}. Use --help for info on option usage." - exit 1 - ;; - esac -done - - -cd $APP_DIR -. .venv/bin/activate -uv pip list - -echo "$(date) Logging to $LOG_DIR" -mkdir -p $LOG_DIR - -#Add future arguments here -args="" -command="hyperion" -if [ $IN_DEV == true ]; then - args+="--dev " -fi -CONFIG_DIR=/etc/hyperion -if [ $CALLBACKS == true ]; then - command="hyperion-callbacks" - args+="--stomp-config $CONFIG_DIR/blueapi_callbacks.yaml" -else - args+="--mode supervisor --client-config $CONFIG_DIR/client_config.yaml --supervisor-config $CONFIG_DIR/supervisor_config.yaml" -fi - -echo "$(date) Starting $command..." -$command $args -sleep 600 From e09b3918ff2d41d3aab9abc3fce217483df2f5b1 Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Thu, 28 May 2026 13:47:54 +0100 Subject: [PATCH 24/27] Tidy up values, deployment files --- helm/hyperion/templates/deployment.yaml | 22 +++++++++++++++------- helm/hyperion/values.yaml | 2 ++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/helm/hyperion/templates/deployment.yaml b/helm/hyperion/templates/deployment.yaml index 819057375c..b0ddf12391 100644 --- a/helm/hyperion/templates/deployment.yaml +++ b/helm/hyperion/templates/deployment.yaml @@ -19,7 +19,6 @@ spec: runAsGroup: {{ .Values.supervisor.runAsGroup }} runAsUser: {{ .Values.supervisor.runAsUser }} volumes: - # Bind some source folders for easier debugging - name: scratch persistentVolumeClaim: claimName: hyperion-supervisor-scratch-{{ .Values.application.imageVersion }} @@ -133,12 +132,6 @@ spec: value: "/scratch/mx-bluesky/src:/scratch/dodal/src" - name: ISPYB_CONFIG_PATH value: "/etc/secrets/expeye/ispyb.cfg" -# readinessProbe: -# httpGet: -# path: "/status" -# port: {{ .Values.supervisor.containerPort }} -# initialDelaySeconds: 30 -# periodSeconds: 5 volumeMounts: - mountPath: "/scratch" name: scratch @@ -157,3 +150,18 @@ spec: name: zocalo-secrets - mountPath: "/etc/secrets/expeye" name: expeye-secrets + - name: hyperion-scratch + # container provided in order for vscode to attach to a writable scratch + image: {{ .Values.application.imageRepository}}/hyperion:{{ .Values.application.imageVersion }} + restartPolicy: Always + volumeMounts: + - mountPath: "/scratch" + name: scratch + resources: + limits: + cpu: "1" + memory: "1Gi" + command: ['/bin/bash', '-c'] + args: + - | + while true; do sleep 60; done diff --git a/helm/hyperion/values.yaml b/helm/hyperion/values.yaml index be2bb301f7..31d1aca02e 100644 --- a/helm/hyperion/values.yaml +++ b/helm/hyperion/values.yaml @@ -29,12 +29,14 @@ volumes: logging: - name: logdir emptyDir: {} +# In ixx-services, replace with path to relevant log folder, e.g. # hostPath: # path: "/dls_sw/i03/logs/bluesky/hyperion-k8s" # type: Directory data: - name: data emptyDir: {} +# In ixx-services, replace with path to relevant data folder, e.g. # hostPath: # type: Directory # path: "/dls/i03/data" From 5bfd86df1b9687d6534f036f826365dbda96c607 Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Thu, 28 May 2026 14:13:22 +0100 Subject: [PATCH 25/27] Remove temporary scripts that we don't need --- utility_scripts/deploy/deploy_hyperion_supervisor.sh | 4 ---- utility_scripts/extract_version.sh | 5 ----- 2 files changed, 9 deletions(-) delete mode 100644 utility_scripts/deploy/deploy_hyperion_supervisor.sh delete mode 100755 utility_scripts/extract_version.sh diff --git a/utility_scripts/deploy/deploy_hyperion_supervisor.sh b/utility_scripts/deploy/deploy_hyperion_supervisor.sh deleted file mode 100644 index 0d298e971f..0000000000 --- a/utility_scripts/deploy/deploy_hyperion_supervisor.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -PROJECTDIR=$(dirname $0)/../.. -helm package $PROJECTDIR/helm/hyperion-supervisor \ - --app-version diff --git a/utility_scripts/extract_version.sh b/utility_scripts/extract_version.sh deleted file mode 100755 index e9dcb6716a..0000000000 --- a/utility_scripts/extract_version.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -LATEST_VERSION=$(git tag | sed -E -n 's/^v?([[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+)$/\1/p' | sort -V -r | head -1) -GIT_HASH=$(git rev-parse --short HEAD) -echo $LATEST_VERSION-g$GIT_HASH From c24e057d636aa92ca816376750225eb1fe6303aa Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Thu, 28 May 2026 14:33:14 +0100 Subject: [PATCH 26/27] Add some docs on the hyperion container setup --- .../explanations/containerised_mx_bluesky.rst | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/developer/general/explanations/containerised_mx_bluesky.rst b/docs/developer/general/explanations/containerised_mx_bluesky.rst index 6f5074619f..850b260b16 100644 --- a/docs/developer/general/explanations/containerised_mx_bluesky.rst +++ b/docs/developer/general/explanations/containerised_mx_bluesky.rst @@ -3,7 +3,7 @@ Containerised mx-bluesky There are currently two images associated with this repository which are pushed on release: hyperion, and mx-bluesky-blueapi. -The Hyperion image is the image that provides ``hyperion-supervisor`` and ``hyperion-callbacks``. These are launched as applications in their own right; ``hyperion-supervisor`` makes use of BlueAPI client but does not expose blueapi plans. ``hyperion-callbacks`` does not use BlueAPI. Which application is launched depends on the arguments passed to the ``entrypoint.sh`` launcher script on container startup. +The Hyperion image is the image that provides ``hyperion-supervisor`` and ``hyperion-callbacks``. These are launched as applications in their own right; ``hyperion-supervisor`` makes use of BlueAPI client but does not expose blueapi plans. ``hyperion-callbacks`` does not use BlueAPI. Which application is launched depends on whether ``hyperion`` or ``hyperion-callbacks`` is specified in the container launch command. The ``mx-bluesky-blueapi`` image exists as a minor extension of BlueAPI's image. BlueAPI's image contains the dependencies of BlueAPI, as well as the dependencies of BlueAPI, which includes dodal. When the BlueAPI service is launched, it will do a ``pip install --no deps`` of the plan repository. For MX, this means ``mx-bluesky`` gets installed without any of its dependencies. For this reason, we have created an ``mx-bluesky-blueapi`` image which installs these extra dependencies. @@ -14,3 +14,21 @@ This image can be used with BlueAPI's original helmchart, the only change requir tag: "{desired_version}" ``hyperion-blueapi`` is launched as a standard ``mx-bluesky-blueapi`` image with configuration to load the hyperion plan and beamline modules. + +Notes on the hyperion k8s deployment +------------------------------------ + +The hyperion Kubernetes deployment consists of a singled pod in a deployment which has 4 containers: + +* ``hyperion-init``, an initContainer which runs before all other containers start. +* ``hyperion-supervisor`` which launches the supervisor +* ``hyperion-callbacks`` which launches the external callbacks +* ``hyperion-scratch`` which is present to enable hotfixes to be applied + +The base ``hyperion`` container image contains only ``mx-bluesky`` and ``dodal`` bare git repos, plus the python virtual environment which provides all other library dependencies. When a new release of ``hyperion`` is first deployed to the cluster, it creates an empty Persistent Volume Claim (PVC). + +``hyperion-init`` runs on pod startup and is responsible for checking out ``dodal`` and ``mx-bluesky`` to the persistent volume if they do not already exist. + +``hyperion-supervisor`` and ``hyperion-callbacks`` then mount the persistent volume read-only under ``/scratch``, and then run ``hyperion`` from this. + +``hyperion-scratch`` is a container that has the persistent volume mounted read-write, its only purpose is to wait for VSCode to attach to it so that you can edit the writable PVC; since ordinary ephemeral containers cannot mount PVCs directly. In this manner, hot fixes to the code can be applied either by editing in VSCode, or via the console; when the pod is restarted the changes will be retained. From 7d7907cceb0dda2bb85bb3fde436844f5c19c48a Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Thu, 28 May 2026 17:25:45 +0100 Subject: [PATCH 27/27] Update uv.lock --- uv.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uv.lock b/uv.lock index 79e05c7d68..a54d860057 100644 --- a/uv.lock +++ b/uv.lock @@ -810,8 +810,8 @@ wheels = [ [[package]] name = "dls-dodal" -version = "2.4.1.dev7+g50b24b2c3" -source = { git = "https://github.com/DiamondLightSource/dodal.git?rev=main#50b24b2c370e7214b97d25e03e4eaaf55517a7e1" } +version = "2.4.1.dev8+gbde3b691f" +source = { git = "https://github.com/DiamondLightSource/dodal.git?rev=main#bde3b691faff4afb4f3fd7540b6bd6fcbead2b45" } dependencies = [ { name = "aiofiles", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, { name = "aiohttp", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },