From ce9090939dfb2177f27e4c211f9fa3c9bfae5d2b Mon Sep 17 00:00:00 2001 From: Giles Knap Date: Wed, 23 Apr 2025 13:15:26 +0000 Subject: [PATCH 1/4] Add initial ec deployment --- .devcontainer/devcontainer.json | 2 +- .../demo_configuration/p47/0.1.yaml | 37 +++++++++++++++++++ .../templates/apptainer_entrypoint | 1 - 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 src/deploy_tools/demo_configuration/p47/0.1.yaml diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 46a7e3d..ee851e8 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -29,7 +29,7 @@ }, "features": { // add in eternal history and other bash features - "ghcr.io/diamondlightsource/devcontainer-features/bash-config:1.0.0": {} + "ghcr.io/diamondlightsource/devcontainer-features/bash-config:1": {} }, // Create the config folder for the bash-config feature "initializeCommand": "mkdir -p ${localEnv:HOME}/.config/bash-config", diff --git a/src/deploy_tools/demo_configuration/p47/0.1.yaml b/src/deploy_tools/demo_configuration/p47/0.1.yaml new file mode 100644 index 0000000..7b5dffe --- /dev/null +++ b/src/deploy_tools/demo_configuration/p47/0.1.yaml @@ -0,0 +1,37 @@ +# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/release.json + +module: + # TODO we would need one of these per beamline so we should factor out + # the common features - the only unique things are the environment variables: + # EC_TARGET + # EC_SERVICES_REPO + name: p47 + version: "0.1" + description: ec command line tool for kubernetes IOCs + + env_vars: + - name: EC_CLI_BACKEND + value: ARGOCD + - name: EC_TARGET + value: p47-beamline/p47 + - name: EC_SERVICES_REPO + value: https://github.com/epics-containers/p47-services + - name: EC_LOG_URL + value: "https://graylog.diamond.ac.uk/search?rangetype=relative&fields=message%2Csource&width=1489&highlightMessage=&relative=172800&q=pod_name%3A{service_name}*" + + applications: + - app_type: apptainer + + container: + path: docker://ghcr.io/epics-containers/edge-containers-cli + version: "4.4.1b1" + + entrypoints: + - name: ec + command: ec + + global_options: + mounts: + # places to get argocd config from + - /dls/science/users/:/dls/science/users/ + - /scratch:/scratch diff --git a/src/deploy_tools/templates/apptainer_entrypoint b/src/deploy_tools/templates/apptainer_entrypoint index da9a834..eaba8ec 100644 --- a/src/deploy_tools/templates/apptainer_entrypoint +++ b/src/deploy_tools/templates/apptainer_entrypoint @@ -31,5 +31,4 @@ fi opts=${opts}" --env DISPLAY=${DISPLAY}" opts=${opts}" ${apptainer_args}" -set -x apptainer exec ${opts} ${sif_file} ${command} ${command_args} "${@}" From 30cc43df47010d5a7d24a63dd67d3134c8689fc6 Mon Sep 17 00:00:00 2001 From: Giles Knap Date: Wed, 23 Apr 2025 14:50:26 +0000 Subject: [PATCH 2/4] Add BinaryApp type and p47 module to demonstrate it --- .devcontainer/devcontainer.json | 6 ++- src/deploy_tools/app_builder.py | 30 +++++++++++ .../demo_configuration/p47/0.1.yaml | 10 ++++ .../demo_configuration/p47/dev.yaml | 47 +++++++++++++++++ src/deploy_tools/layout.py | 11 ++++ src/deploy_tools/models/binary_app.py | 17 +++++++ src/deploy_tools/models/module.py | 5 +- .../models/schemas/deployment.json | 51 ++++++++++++++++--- src/deploy_tools/models/schemas/module.json | 51 ++++++++++++++++--- src/deploy_tools/models/schemas/release.json | 51 ++++++++++++++++--- src/deploy_tools/module_builder.py | 2 + src/deploy_tools/templates/modulefile | 1 + 12 files changed, 256 insertions(+), 26 deletions(-) create mode 100644 src/deploy_tools/demo_configuration/p47/dev.yaml create mode 100644 src/deploy_tools/models/binary_app.py diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index ee851e8..12d2f01 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -42,7 +42,11 @@ "--device=/dev/fuse" ], "mounts": [ - "source=/dls_sw/,target=/dls_sw,type=bind,consistency=cached" + "source=/dls_sw/,target=/dls_sw,type=bind,consistency=cached", + // these two mounts allow us to pick up cache and config folders that have + // been symlinked out of the home directory + "source=/dls/science/users/,target=/dls/science/users,type=bind,consistency=cached", + "source=/scratch/,target=/scratch,type=bind,consistency=cached" ], // Mount the parent as /workspaces so we can pip install peers as editable "workspaceMount": "source=${localWorkspaceFolder}/..,target=/workspaces,type=bind", diff --git a/src/deploy_tools/app_builder.py b/src/deploy_tools/app_builder.py index 7e4dc41..513ab69 100644 --- a/src/deploy_tools/app_builder.py +++ b/src/deploy_tools/app_builder.py @@ -1,6 +1,10 @@ import uuid +from hashlib import sha256 from itertools import chain from pathlib import Path +from urllib.request import urlretrieve + +from deploy_tools.models.binary_app import BinaryApp from .apptainer import create_sif_file from .layout import ModuleBuildLayout @@ -27,6 +31,8 @@ def create_application_files(self, app: Application, module: Module): self._create_apptainer_files(app, module) case ShellApp(): self._create_shell_file(app, module) + case BinaryApp(): + self._create_binary_app(app, module) def _create_apptainer_files(self, app: ApptainerApp, module: Module) -> None: """Create apptainer entrypoints using a specified image and commands.""" @@ -96,3 +102,27 @@ def _create_shell_file(self, app: ShellApp, module: Module) -> None: executable=True, create_parents=True, ) + + def _create_binary_app(self, app: BinaryApp, module: Module) -> None: + """ + Download a URL, validate it against its sha256, make it executable + and add it to PATH + """ + binary_folder = self._build_layout.get_binary_files_folder( + module.name, module.version + ) + binary_path = binary_folder / app.name + binary_path.parent.mkdir(parents=True, exist_ok=True) + urlretrieve(app.url, binary_path) + + h = sha256() + with open(binary_path, "rb") as fh: + while True: + data = fh.read(4096) + if len(data) == 0: + break + h.update(data) + if h.hexdigest() != app.sha256: + raise RuntimeError(f"Downloaded Binary {app.url} digest failure") + + binary_path.chmod(0o555) diff --git a/src/deploy_tools/demo_configuration/p47/0.1.yaml b/src/deploy_tools/demo_configuration/p47/0.1.yaml index 7b5dffe..bbd39fe 100644 --- a/src/deploy_tools/demo_configuration/p47/0.1.yaml +++ b/src/deploy_tools/demo_configuration/p47/0.1.yaml @@ -35,3 +35,13 @@ module: # places to get argocd config from - /dls/science/users/:/dls/science/users/ - /scratch:/scratch + + - app_type: binary + name: argocd + url: https://github.com/argoproj/argo-cd/releases/download/v2.14.10/argocd-linux-amd64 + sha256: d1750274a336f0a090abf196a832cee14cb9f1c2fc3d20d80b0dbfeff83550fa + + - app_type: shell + name: ec-login + script: + - argocd login argocd.diamond.ac.uk --grpc-web --sso diff --git a/src/deploy_tools/demo_configuration/p47/dev.yaml b/src/deploy_tools/demo_configuration/p47/dev.yaml new file mode 100644 index 0000000..3fb5a09 --- /dev/null +++ b/src/deploy_tools/demo_configuration/p47/dev.yaml @@ -0,0 +1,47 @@ +# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/release.json + +module: + # TODO we would need one of these per beamline so we should factor out + # the common features - the only unique things are the environment variables: + # EC_TARGET + # EC_SERVICES_REPO + name: p47 + version: dev + description: ec command line tool for kubernetes IOCs + + env_vars: + - name: EC_CLI_BACKEND + value: ARGOCD + - name: EC_TARGET + value: p47-beamline/p47 + - name: EC_SERVICES_REPO + value: https://github.com/epics-containers/p47-services + - name: EC_LOG_URL + value: "https://graylog.diamond.ac.uk/search?rangetype=relative&fields=message%2Csource&width=1489&highlightMessage=&relative=172800&q=pod_name%3A{service_name}*" + + applications: + - app_type: apptainer + + container: + path: docker://ghcr.io/epics-containers/edge-containers-cli + version: "4.4.1b1" + + entrypoints: + - name: ec + command: ec + + global_options: + mounts: + # places to get argocd config from + - /dls/science/users/:/dls/science/users/ + - /scratch:/scratch + + - app_type: binary + name: argocd + url: https://github.com/argoproj/argo-cd/releases/download/v2.14.10/argocd-linux-amd64 + sha256: d1750274a336f0a090abf196a832cee14cb9f1c2fc3d20d80b0dbfeff83550fa + + - app_type: shell + name: ec-login + script: + - argocd login argocd.diamond.ac.uk --grpc-web --sso diff --git a/src/deploy_tools/layout.py b/src/deploy_tools/layout.py index 705c2b5..f3c1cc3 100644 --- a/src/deploy_tools/layout.py +++ b/src/deploy_tools/layout.py @@ -8,6 +8,7 @@ class ModuleAreaLayout: """ ENTRYPOINTS_FOLDER = "entrypoints" + BINARIES_FOLDER = "binaries" MODULE_SNAPSHOT_FILENAME = "module.yaml" MODULEFILE_FILENAME = "modulefile" @@ -21,6 +22,9 @@ def get_module_folder(self, name: str, version: str) -> Path: def get_entrypoints_folder(self, name: str, version: str) -> Path: return self.get_module_folder(name, version) / self.ENTRYPOINTS_FOLDER + def get_binaries_folder(self, name: str, version: str) -> Path: + return self.get_module_folder(name, version) / self.BINARIES_FOLDER + def get_modulefile(self, name: str, version: str) -> Path: return self.get_module_folder(name, version) / self.MODULEFILE_FILENAME @@ -37,10 +41,14 @@ class ModuleBuildLayout(ModuleAreaLayout): """ SIF_FILES_FOLDER = "sif_files" + BINARY_FILES_FOLDER = "binaries" def get_sif_files_folder(self, name: str, version: str) -> Path: return self.get_module_folder(name, version) / self.SIF_FILES_FOLDER + def get_binary_files_folder(self, name: str, version: str) -> Path: + return self.get_module_folder(name, version) / self.BINARY_FILES_FOLDER + @property def build_root(self): return self._root @@ -73,6 +81,9 @@ def get_module_folder(self, name: str, version: str) -> Path: def get_entrypoints_folder(self, name: str, version: str) -> Path: return self._modules_layout.get_entrypoints_folder(name, version) + def get_binaries_folder(self, name: str, version: str) -> Path: + return self._modules_layout.get_binaries_folder(name, version) + def get_modulefiles_root(self, from_deprecated: bool = False) -> Path: return ( self.deprecated_modulefiles_root diff --git a/src/deploy_tools/models/binary_app.py b/src/deploy_tools/models/binary_app.py new file mode 100644 index 0000000..d2bc0f4 --- /dev/null +++ b/src/deploy_tools/models/binary_app.py @@ -0,0 +1,17 @@ +from typing import Literal + +from .parent import ParentModel + + +class BinaryApp(ParentModel): + """ + Represents a standalone Binary application. + + This will fetch a standalone binary, validate its sha256 and add its + location to that path. + """ + + app_type: Literal["binary"] + name: str + url: str + sha256: str diff --git a/src/deploy_tools/models/module.py b/src/deploy_tools/models/module.py index eaa4acd..372abbe 100644 --- a/src/deploy_tools/models/module.py +++ b/src/deploy_tools/models/module.py @@ -4,10 +4,13 @@ from pydantic import Field from .apptainer_app import ApptainerApp +from .binary_app import BinaryApp from .parent import ParentModel from .shell_app import ShellApp -Application = Annotated[ApptainerApp | ShellApp, Field(..., discriminator="app_type")] +Application = Annotated[ + ApptainerApp | ShellApp | BinaryApp, Field(..., discriminator="app_type") +] DEVELOPMENT_VERSION = "dev" diff --git a/src/deploy_tools/models/schemas/deployment.json b/src/deploy_tools/models/schemas/deployment.json index 3ee93bc..57a7fa7 100644 --- a/src/deploy_tools/models/schemas/deployment.json +++ b/src/deploy_tools/models/schemas/deployment.json @@ -1,6 +1,6 @@ { "$defs": { - "Apptainer": { + "ApptainerApp": { "additionalProperties": false, "description": "Represents an Apptainer application or set of applications for a single image.\n\nThis uses Apptainer to deploy a portable image of the desired container. Several\nentrypoints can then be specified to allow for multiple commands run on the same\ncontainer image.", "properties": { @@ -33,7 +33,38 @@ "container", "entrypoints" ], - "title": "Apptainer", + "title": "ApptainerApp", + "type": "object" + }, + "BinaryApp": { + "additionalProperties": false, + "description": "Represents a standalone Binary application.\n\nThis will fetch a standalone binary, validate its sha256 and add its\nlocation to that path.", + "properties": { + "app_type": { + "const": "binary", + "title": "App Type", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "url": { + "title": "Url", + "type": "string" + }, + "sha256": { + "title": "Sha256", + "type": "string" + } + }, + "required": [ + "app_type", + "name", + "url", + "sha256" + ], + "title": "BinaryApp", "type": "object" }, "ContainerImage": { @@ -197,17 +228,21 @@ "items": { "discriminator": { "mapping": { - "apptainer": "#/$defs/Apptainer", - "shell": "#/$defs/Shell" + "apptainer": "#/$defs/ApptainerApp", + "binary": "#/$defs/BinaryApp", + "shell": "#/$defs/ShellApp" }, "propertyName": "app_type" }, "oneOf": [ { - "$ref": "#/$defs/Apptainer" + "$ref": "#/$defs/ApptainerApp" + }, + { + "$ref": "#/$defs/ShellApp" }, { - "$ref": "#/$defs/Shell" + "$ref": "#/$defs/BinaryApp" } ] }, @@ -281,7 +316,7 @@ }, "type": "object" }, - "Shell": { + "ShellApp": { "additionalProperties": false, "description": "Represents a Shell application.\n\nThis will run the code specified as a shell script. This currently uses Bash for\nimproved functionality while retaining high compatibility with various Linux\ndistributions.", "properties": { @@ -307,7 +342,7 @@ "name", "script" ], - "title": "Shell", + "title": "ShellApp", "type": "object" } }, diff --git a/src/deploy_tools/models/schemas/module.json b/src/deploy_tools/models/schemas/module.json index e7a877e..0b9060d 100644 --- a/src/deploy_tools/models/schemas/module.json +++ b/src/deploy_tools/models/schemas/module.json @@ -1,6 +1,6 @@ { "$defs": { - "Apptainer": { + "ApptainerApp": { "additionalProperties": false, "description": "Represents an Apptainer application or set of applications for a single image.\n\nThis uses Apptainer to deploy a portable image of the desired container. Several\nentrypoints can then be specified to allow for multiple commands run on the same\ncontainer image.", "properties": { @@ -33,7 +33,38 @@ "container", "entrypoints" ], - "title": "Apptainer", + "title": "ApptainerApp", + "type": "object" + }, + "BinaryApp": { + "additionalProperties": false, + "description": "Represents a standalone Binary application.\n\nThis will fetch a standalone binary, validate its sha256 and add its\nlocation to that path.", + "properties": { + "app_type": { + "const": "binary", + "title": "App Type", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "url": { + "title": "Url", + "type": "string" + }, + "sha256": { + "title": "Sha256", + "type": "string" + } + }, + "required": [ + "app_type", + "name", + "url", + "sha256" + ], + "title": "BinaryApp", "type": "object" }, "ContainerImage": { @@ -179,17 +210,21 @@ "items": { "discriminator": { "mapping": { - "apptainer": "#/$defs/Apptainer", - "shell": "#/$defs/Shell" + "apptainer": "#/$defs/ApptainerApp", + "binary": "#/$defs/BinaryApp", + "shell": "#/$defs/ShellApp" }, "propertyName": "app_type" }, "oneOf": [ { - "$ref": "#/$defs/Apptainer" + "$ref": "#/$defs/ApptainerApp" + }, + { + "$ref": "#/$defs/ShellApp" }, { - "$ref": "#/$defs/Shell" + "$ref": "#/$defs/BinaryApp" } ] }, @@ -232,7 +267,7 @@ "title": "ModuleDependency", "type": "object" }, - "Shell": { + "ShellApp": { "additionalProperties": false, "description": "Represents a Shell application.\n\nThis will run the code specified as a shell script. This currently uses Bash for\nimproved functionality while retaining high compatibility with various Linux\ndistributions.", "properties": { @@ -258,7 +293,7 @@ "name", "script" ], - "title": "Shell", + "title": "ShellApp", "type": "object" } }, diff --git a/src/deploy_tools/models/schemas/release.json b/src/deploy_tools/models/schemas/release.json index e7a877e..0b9060d 100644 --- a/src/deploy_tools/models/schemas/release.json +++ b/src/deploy_tools/models/schemas/release.json @@ -1,6 +1,6 @@ { "$defs": { - "Apptainer": { + "ApptainerApp": { "additionalProperties": false, "description": "Represents an Apptainer application or set of applications for a single image.\n\nThis uses Apptainer to deploy a portable image of the desired container. Several\nentrypoints can then be specified to allow for multiple commands run on the same\ncontainer image.", "properties": { @@ -33,7 +33,38 @@ "container", "entrypoints" ], - "title": "Apptainer", + "title": "ApptainerApp", + "type": "object" + }, + "BinaryApp": { + "additionalProperties": false, + "description": "Represents a standalone Binary application.\n\nThis will fetch a standalone binary, validate its sha256 and add its\nlocation to that path.", + "properties": { + "app_type": { + "const": "binary", + "title": "App Type", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "url": { + "title": "Url", + "type": "string" + }, + "sha256": { + "title": "Sha256", + "type": "string" + } + }, + "required": [ + "app_type", + "name", + "url", + "sha256" + ], + "title": "BinaryApp", "type": "object" }, "ContainerImage": { @@ -179,17 +210,21 @@ "items": { "discriminator": { "mapping": { - "apptainer": "#/$defs/Apptainer", - "shell": "#/$defs/Shell" + "apptainer": "#/$defs/ApptainerApp", + "binary": "#/$defs/BinaryApp", + "shell": "#/$defs/ShellApp" }, "propertyName": "app_type" }, "oneOf": [ { - "$ref": "#/$defs/Apptainer" + "$ref": "#/$defs/ApptainerApp" + }, + { + "$ref": "#/$defs/ShellApp" }, { - "$ref": "#/$defs/Shell" + "$ref": "#/$defs/BinaryApp" } ] }, @@ -232,7 +267,7 @@ "title": "ModuleDependency", "type": "object" }, - "Shell": { + "ShellApp": { "additionalProperties": false, "description": "Represents a Shell application.\n\nThis will run the code specified as a shell script. This currently uses Bash for\nimproved functionality while retaining high compatibility with various Linux\ndistributions.", "properties": { @@ -258,7 +293,7 @@ "name", "script" ], - "title": "Shell", + "title": "ShellApp", "type": "object" } }, diff --git a/src/deploy_tools/module_builder.py b/src/deploy_tools/module_builder.py index 7779b9b..c7ad228 100644 --- a/src/deploy_tools/module_builder.py +++ b/src/deploy_tools/module_builder.py @@ -27,6 +27,7 @@ def _create_modulefile(self, module: Module) -> None: entrypoints_folder = self._layout.get_entrypoints_folder( module.name, module.version ) + binaries_folder = self._layout.get_binaries_folder(module.name, module.version) description = module.description if description is None: @@ -38,6 +39,7 @@ def _create_modulefile(self, module: Module) -> None: "env_vars": module.env_vars, "dependencies": module.dependencies, "entrypoint_folder": entrypoints_folder, + "binaries_folder": binaries_folder, } built_modulefile = self._build_layout.get_modulefile( diff --git a/src/deploy_tools/templates/modulefile b/src/deploy_tools/templates/modulefile index 4ec3369..2cda133 100644 --- a/src/deploy_tools/templates/modulefile +++ b/src/deploy_tools/templates/modulefile @@ -17,3 +17,4 @@ module load {{ module.name }}/{{ module.version }} {% endfor %} prepend-path PATH "{{ entrypoint_folder }}" +prepend-path PATH "{{ binaries_folder }}" From 69fd31b85e612d642e5f6417b362ce3116b342ab Mon Sep 17 00:00:00 2001 From: Giles Knap Date: Wed, 23 Apr 2025 18:02:44 +0000 Subject: [PATCH 3/4] factor out common features for all beamlines --- .../edge-containers-cli/0.1.yaml | 44 +++++++++++++++++++ .../demo_configuration/p47/0.1.yaml | 39 +++------------- .../demo_configuration/p47/dev.yaml | 39 +++------------- 3 files changed, 56 insertions(+), 66 deletions(-) create mode 100644 src/deploy_tools/demo_configuration/edge-containers-cli/0.1.yaml diff --git a/src/deploy_tools/demo_configuration/edge-containers-cli/0.1.yaml b/src/deploy_tools/demo_configuration/edge-containers-cli/0.1.yaml new file mode 100644 index 0000000..6a49a51 --- /dev/null +++ b/src/deploy_tools/demo_configuration/edge-containers-cli/0.1.yaml @@ -0,0 +1,44 @@ +# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/release.json + +module: + name: edge-containers-cli + version: "0.1" + description: ec command line tool for kubernetes IOCs + + env_vars: + - name: EC_CLI_BACKEND + value: ARGOCD + - name: EC_LOG_URL + value: "https://graylog.diamond.ac.uk/search?rangetype=relative&fields=message%2Csource&width=1489&highlightMessage=&relative=172800&q=pod_name%3A{service_name}*" + # default configuration is for p47 for testing + - name: EC_TARGET + value: p47-beamline/p47 + - name: EC_SERVICES_REPO + value: https://github.com/epics-containers/p47-services + + applications: + - app_type: apptainer + + container: + path: docker://ghcr.io/epics-containers/edge-containers-cli + version: "4.4.1b1" + + entrypoints: + - name: ec + command: ec + + global_options: + mounts: + # places to get argocd config from + - /dls/science/users/:/dls/science/users/ + - /scratch:/scratch + + - app_type: binary + name: argocd + url: https://github.com/argoproj/argo-cd/releases/download/v2.14.10/argocd-linux-amd64 + sha256: d1750274a336f0a090abf196a832cee14cb9f1c2fc3d20d80b0dbfeff83550fa + + - app_type: shell + name: ec-login + script: + - argocd login argocd.diamond.ac.uk --grpc-web --sso diff --git a/src/deploy_tools/demo_configuration/p47/0.1.yaml b/src/deploy_tools/demo_configuration/p47/0.1.yaml index bbd39fe..2c2b25a 100644 --- a/src/deploy_tools/demo_configuration/p47/0.1.yaml +++ b/src/deploy_tools/demo_configuration/p47/0.1.yaml @@ -1,47 +1,20 @@ # yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/release.json module: - # TODO we would need one of these per beamline so we should factor out - # the common features - the only unique things are the environment variables: - # EC_TARGET - # EC_SERVICES_REPO name: p47 version: "0.1" description: ec command line tool for kubernetes IOCs env_vars: - - name: EC_CLI_BACKEND - value: ARGOCD - name: EC_TARGET value: p47-beamline/p47 - name: EC_SERVICES_REPO value: https://github.com/epics-containers/p47-services - - name: EC_LOG_URL - value: "https://graylog.diamond.ac.uk/search?rangetype=relative&fields=message%2Csource&width=1489&highlightMessage=&relative=172800&q=pod_name%3A{service_name}*" - applications: - - app_type: apptainer + dependencies: + - name: pollux + version: "local" + - name: edge-containers-cli + version: "0.1" - container: - path: docker://ghcr.io/epics-containers/edge-containers-cli - version: "4.4.1b1" - - entrypoints: - - name: ec - command: ec - - global_options: - mounts: - # places to get argocd config from - - /dls/science/users/:/dls/science/users/ - - /scratch:/scratch - - - app_type: binary - name: argocd - url: https://github.com/argoproj/argo-cd/releases/download/v2.14.10/argocd-linux-amd64 - sha256: d1750274a336f0a090abf196a832cee14cb9f1c2fc3d20d80b0dbfeff83550fa - - - app_type: shell - name: ec-login - script: - - argocd login argocd.diamond.ac.uk --grpc-web --sso + applications: [] diff --git a/src/deploy_tools/demo_configuration/p47/dev.yaml b/src/deploy_tools/demo_configuration/p47/dev.yaml index 3fb5a09..dd9150c 100644 --- a/src/deploy_tools/demo_configuration/p47/dev.yaml +++ b/src/deploy_tools/demo_configuration/p47/dev.yaml @@ -1,47 +1,20 @@ # yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/release.json module: - # TODO we would need one of these per beamline so we should factor out - # the common features - the only unique things are the environment variables: - # EC_TARGET - # EC_SERVICES_REPO name: p47 version: dev description: ec command line tool for kubernetes IOCs env_vars: - - name: EC_CLI_BACKEND - value: ARGOCD - name: EC_TARGET value: p47-beamline/p47 - name: EC_SERVICES_REPO value: https://github.com/epics-containers/p47-services - - name: EC_LOG_URL - value: "https://graylog.diamond.ac.uk/search?rangetype=relative&fields=message%2Csource&width=1489&highlightMessage=&relative=172800&q=pod_name%3A{service_name}*" - applications: - - app_type: apptainer + dependencies: + - name: pollux + version: "local" + - name: edge-containers-cli + version: "0.1" - container: - path: docker://ghcr.io/epics-containers/edge-containers-cli - version: "4.4.1b1" - - entrypoints: - - name: ec - command: ec - - global_options: - mounts: - # places to get argocd config from - - /dls/science/users/:/dls/science/users/ - - /scratch:/scratch - - - app_type: binary - name: argocd - url: https://github.com/argoproj/argo-cd/releases/download/v2.14.10/argocd-linux-amd64 - sha256: d1750274a336f0a090abf196a832cee14cb9f1c2fc3d20d80b0dbfeff83550fa - - - app_type: shell - name: ec-login - script: - - argocd login argocd.diamond.ac.uk --grpc-web --sso + applications: [] From 939af011268fa7fce48559736b8d8e11b4fad153 Mon Sep 17 00:00:00 2001 From: Giles Knap Date: Wed, 23 Apr 2025 19:51:17 +0000 Subject: [PATCH 4/4] add host_binaries feature and use it for edge-containers-cli --- .gitignore | 3 +++ src/deploy_tools/app_builder.py | 4 ++++ .../edge-containers-cli/0.1.yaml | 19 ++++++++++++++++-- .../demo_configuration/p47/dev.yaml | 20 ------------------- src/deploy_tools/models/apptainer_app.py | 1 + .../models/schemas/deployment.json | 14 +++++++++++-- src/deploy_tools/models/schemas/module.json | 14 +++++++++++-- src/deploy_tools/models/schemas/release.json | 14 +++++++++++-- .../templates/apptainer_entrypoint | 6 ++++++ 9 files changed, 67 insertions(+), 28 deletions(-) delete mode 100644 src/deploy_tools/demo_configuration/p47/dev.yaml diff --git a/.gitignore b/.gitignore index 5eda15c..c602ca4 100644 --- a/.gitignore +++ b/.gitignore @@ -72,3 +72,6 @@ lockfiles/ # Demo output path for vscode tasks demo-output + +# vscode workspaces are local only +*.code-workspace diff --git a/src/deploy_tools/app_builder.py b/src/deploy_tools/app_builder.py index 513ab69..feef710 100644 --- a/src/deploy_tools/app_builder.py +++ b/src/deploy_tools/app_builder.py @@ -50,6 +50,9 @@ def _create_apptainer_files(self, app: ApptainerApp, module: Module) -> None: entrypoint_file = entrypoints_folder / entrypoint.name mounts = ",".join(chain(global_options.mounts, options.mounts)).strip() + host_binaries = " ".join( + chain(global_options.host_binaries, options.host_binaries) + ).strip() apptainer_args = f"{global_options.apptainer_args} {options.apptainer_args}" apptainer_args = apptainer_args.strip() @@ -61,6 +64,7 @@ def _create_apptainer_files(self, app: ApptainerApp, module: Module) -> None: params = { "mounts": mounts, + "host_binaries": host_binaries, "apptainer_args": apptainer_args, "relative_sif_file": relative_sif_file, "command": command, diff --git a/src/deploy_tools/demo_configuration/edge-containers-cli/0.1.yaml b/src/deploy_tools/demo_configuration/edge-containers-cli/0.1.yaml index 6a49a51..4c0ccc4 100644 --- a/src/deploy_tools/demo_configuration/edge-containers-cli/0.1.yaml +++ b/src/deploy_tools/demo_configuration/edge-containers-cli/0.1.yaml @@ -21,17 +21,32 @@ module: container: path: docker://ghcr.io/epics-containers/edge-containers-cli - version: "4.4.1b1" + version: "4.4.1" entrypoints: - name: ec command: ec + # for debugging enter the container with bash shell + - name: ec-bash + command: bash global_options: mounts: - # places to get argocd config from + # places to get argocd and kubectl config from - /dls/science/users/:/dls/science/users/ - /scratch:/scratch + - /dls_sw/apps:/dls_sw/apps + host_binaries: + - argocd + # for future expansion and to demonstrate it can be done + # load in the remaining kubernetes tools + - kubectl + - helm + - kubelogin + - klogout + - kustomize + - kubeseal + - kubectl-oidc_login - app_type: binary name: argocd diff --git a/src/deploy_tools/demo_configuration/p47/dev.yaml b/src/deploy_tools/demo_configuration/p47/dev.yaml deleted file mode 100644 index dd9150c..0000000 --- a/src/deploy_tools/demo_configuration/p47/dev.yaml +++ /dev/null @@ -1,20 +0,0 @@ -# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/release.json - -module: - name: p47 - version: dev - description: ec command line tool for kubernetes IOCs - - env_vars: - - name: EC_TARGET - value: p47-beamline/p47 - - name: EC_SERVICES_REPO - value: https://github.com/epics-containers/p47-services - - dependencies: - - name: pollux - version: "local" - - name: edge-containers-cli - version: "0.1" - - applications: [] diff --git a/src/deploy_tools/models/apptainer_app.py b/src/deploy_tools/models/apptainer_app.py index 35c6bf2..ced0d5a 100644 --- a/src/deploy_tools/models/apptainer_app.py +++ b/src/deploy_tools/models/apptainer_app.py @@ -8,6 +8,7 @@ class EntrypointOptions(ParentModel): apptainer_args: str = "" command_args: str = "" mounts: Sequence[str] = [] + host_binaries: Sequence[str] = [] class Entrypoint(ParentModel): diff --git a/src/deploy_tools/models/schemas/deployment.json b/src/deploy_tools/models/schemas/deployment.json index 57a7fa7..0e82244 100644 --- a/src/deploy_tools/models/schemas/deployment.json +++ b/src/deploy_tools/models/schemas/deployment.json @@ -24,7 +24,8 @@ "default": { "apptainer_args": "", "command_args": "", - "mounts": [] + "mounts": [], + "host_binaries": [] } } }, @@ -129,7 +130,8 @@ "default": { "apptainer_args": "", "command_args": "", - "mounts": [] + "mounts": [], + "host_binaries": [] } } }, @@ -159,6 +161,14 @@ }, "title": "Mounts", "type": "array" + }, + "host_binaries": { + "default": [], + "items": { + "type": "string" + }, + "title": "Host Binaries", + "type": "array" } }, "title": "EntrypointOptions", diff --git a/src/deploy_tools/models/schemas/module.json b/src/deploy_tools/models/schemas/module.json index 0b9060d..e029d9e 100644 --- a/src/deploy_tools/models/schemas/module.json +++ b/src/deploy_tools/models/schemas/module.json @@ -24,7 +24,8 @@ "default": { "apptainer_args": "", "command_args": "", - "mounts": [] + "mounts": [], + "host_binaries": [] } } }, @@ -111,7 +112,8 @@ "default": { "apptainer_args": "", "command_args": "", - "mounts": [] + "mounts": [], + "host_binaries": [] } } }, @@ -141,6 +143,14 @@ }, "title": "Mounts", "type": "array" + }, + "host_binaries": { + "default": [], + "items": { + "type": "string" + }, + "title": "Host Binaries", + "type": "array" } }, "title": "EntrypointOptions", diff --git a/src/deploy_tools/models/schemas/release.json b/src/deploy_tools/models/schemas/release.json index 0b9060d..e029d9e 100644 --- a/src/deploy_tools/models/schemas/release.json +++ b/src/deploy_tools/models/schemas/release.json @@ -24,7 +24,8 @@ "default": { "apptainer_args": "", "command_args": "", - "mounts": [] + "mounts": [], + "host_binaries": [] } } }, @@ -111,7 +112,8 @@ "default": { "apptainer_args": "", "command_args": "", - "mounts": [] + "mounts": [], + "host_binaries": [] } } }, @@ -141,6 +143,14 @@ }, "title": "Mounts", "type": "array" + }, + "host_binaries": { + "default": [], + "items": { + "type": "string" + }, + "title": "Host Binaries", + "type": "array" } }, "title": "EntrypointOptions", diff --git a/src/deploy_tools/templates/apptainer_entrypoint b/src/deploy_tools/templates/apptainer_entrypoint index eaba8ec..92b015b 100644 --- a/src/deploy_tools/templates/apptainer_entrypoint +++ b/src/deploy_tools/templates/apptainer_entrypoint @@ -17,6 +17,12 @@ command="{{ command }}" # Options and arguments to pass to command command_args="{{ command_args }}" +# add mounts of host binaries into /usr/bin +for i in {{ host_binaries }}; do + binary=$(which $i) + mounts="${mounts},${binary}:/usr/bin/${i}" +done + # Raise an error if sif file does not exist if [[ ! -f ${sif_file} ]]; then echo "ERROR: sif file ${sif_file} does not exist" 1>&2