diff --git a/.gitea/scripts/common.sh b/.gitea/scripts/common.sh new file mode 100644 index 0000000..d681b86 --- /dev/null +++ b/.gitea/scripts/common.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# Shared helpers for the scripts run by the gitea runner. +# Source it as: source "$(dirname "$0")/common.sh" + +# Overridable so the scripts can be exercised outside of the runner +HLA_ROOT=${HLA_ROOT:-/sls/bd/hla} + +# Sets the naming and path variables used by the deploy and ioc scripts. +# Usage: init_service_env +init_service_env() { + local SERVICE_NAME=$1 + AGEBD_ENV=$2 + + if [ -z "${SERVICE_NAME}" ] || [ -z "${AGEBD_ENV}" ]; then + echo "Usage: $0 " >&2 + exit 1 + fi + + if [ "${AGEBD_ENV}" = "dev" ]; then + AGEBD_ENV_SUFFIX_UPPER="-DEV" + AGEBD_ENV_SUFFIX_LOWER="-dev" + elif [ "${AGEBD_ENV}" = "prod" ]; then + AGEBD_ENV_SUFFIX_UPPER="" + AGEBD_ENV_SUFFIX_LOWER="" + else + echo "Unknown environment '${AGEBD_ENV}', expected 'dev' or 'prod'" >&2 + exit 1 + fi + + SERVICE_NAME_LOWER=$(echo "${SERVICE_NAME}" | tr '[:upper:]' '[:lower:]') + SERVICE_NAME_UPPER=$(echo "${SERVICE_NAME}" | tr '[:lower:]' '[:upper:]') + + SERVICE_DIR=${HLA_ROOT}/${AGEBD_ENV}/services/${SERVICE_NAME_LOWER}/current + IOC_DIR=${SERVICE_DIR}/ioc + IOC_NAME=AGEBD-CPCL-${SERVICE_NAME_UPPER}${AGEBD_ENV_SUFFIX_UPPER} + # Host running shellbox, i.e. the host the ioc itself runs on + IOC_HOST=sls-vserv-bd-01${AGEBD_ENV_SUFFIX_LOWER} +} diff --git a/.gitea/scripts/deploy-and-restart-service.sh b/.gitea/scripts/deploy-and-restart-service.sh index 142b509..081f510 100755 --- a/.gitea/scripts/deploy-and-restart-service.sh +++ b/.gitea/scripts/deploy-and-restart-service.sh @@ -1,28 +1,19 @@ #!/bin/bash +# Deploys a service to /sls and (re)starts its systemd unit. +# +# Usage: ./.gitea/scripts/deploy-and-restart-service.sh -SERVICE_NAME=$1 -AGEBD_ENV=$2 +source "$(dirname "$0")/common.sh" +init_service_env "${1:-}" "${2:-}" echo "==========================================" -echo "Deploying service: $SERVICE_NAME (${AGEBD_ENV})" +echo "Deploying service: $SERVICE_NAME_LOWER (${AGEBD_ENV})" echo "==========================================" -SERVICE_NAME_LOWER=$(echo "$SERVICE_NAME" | tr '[:upper:]' '[:lower:]') -SERVICE_NAME_UPPER=$(echo "$SERVICE_NAME" | tr '[:lower:]' '[:upper:]') -SERVICE_DIR=/sls/bd/hla/${AGEBD_ENV}/services/${SERVICE_NAME_LOWER}/current SYSTEMD_UNIT_NAME=AGEBD-SERVICE-${SERVICE_NAME_UPPER}.service SYSTEMD_UNIT_FILE_PATH=${SERVICE_DIR}/systemd/${SYSTEMD_UNIT_NAME} -IOC_DIR=${SERVICE_DIR}/ioc IOC_PORT=$(uv run --directory scripts ci/get_ioc_port.py ${SERVICE_NAME_LOWER}) -if [ "${AGEBD_ENV}" = "dev" ]; then - AGEBD_ENV_SUFFIX_UPPER="-DEV" - AGEBD_ENV_SUFFIX_LOWER="-dev" -else - AGEBD_ENV_SUFFIX_UPPER="" - AGEBD_ENV_SUFFIX_LOWER="" -fi - # TODO: see https://gitea.psi.ch/sls/hla_framework_bd/issues/50 # rm -rf "${SERVICE_DIR}" # mkdir -p ${SERVICE_DIR} @@ -43,6 +34,19 @@ sed -i "s/{{ *agebd_env_suffix_upper* }}/${AGEBD_ENV_SUFFIX_UPPER}/g" "${IOC_DIR sed -i "s/{{ *agebd_env_suffix_lower* }}/${AGEBD_ENV_SUFFIX_LOWER}/g" "${IOC_DIR}/"* sed -i "s/{{ *ioc_port* }}/${IOC_PORT}/g" "${IOC_DIR}/"* +### RENAMING +### The ioc files carry the environment suffix in their name, e.g. in dev +### AGEBD-CPCL-NTURNS_main.subs -> AGEBD-CPCL-NTURNS-DEV_main.subs +### (rsync --delete restores the original names on every deploy, so this runs every time) +if [ -n "${AGEBD_ENV_SUFFIX_UPPER}" ]; then + for FILE_SUFFIX in "_main.subs" "_parameters.yaml"; do + ORIG_FILE=${IOC_DIR}/AGEBD-CPCL-${SERVICE_NAME_UPPER}${FILE_SUFFIX} + if [ -f "${ORIG_FILE}" ]; then + mv "${ORIG_FILE}" "${IOC_DIR}/AGEBD-CPCL-${SERVICE_NAME_UPPER}${AGEBD_ENV_SUFFIX_UPPER}${FILE_SUFFIX}" + fi + done +fi + ### SYSTEMD if [ -f "${SYSTEMD_UNIT_FILE_PATH}" ]; then sed -i "s/{{ *agebd_env* }}/${AGEBD_ENV}/g" "${SYSTEMD_UNIT_FILE_PATH}" diff --git a/.gitea/scripts/ioc-for-services.sh b/.gitea/scripts/ioc-for-services.sh new file mode 100755 index 0000000..c6f651b --- /dev/null +++ b/.gitea/scripts/ioc-for-services.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Runs an ioc action for a single service or for all services. +# +# Usage: ./.gitea/scripts/ioc-for-services.sh +set -euo pipefail + +IOC_ACTION=${1:-} +SERVICE=${2:-} +AGEBD_ENV=${3:-} + +SCRIPT_DIR=$(dirname "$0") +IOC_SCRIPT=${SCRIPT_DIR}/ioc-${IOC_ACTION}.sh + +if [ ! -f "${IOC_SCRIPT}" ]; then + echo "Unknown ioc action '${IOC_ACTION}', expected 'install', 'start' or 'restart'" >&2 + exit 1 +fi + +if [ "${SERVICE}" = "all" ]; then + SERVICES=$(ls -d services/*/ | xargs -n1 basename) +else + SERVICES=${SERVICE} +fi + +for SERVICE_NAME in ${SERVICES}; do + "${IOC_SCRIPT}" "${SERVICE_NAME}" "${AGEBD_ENV}" +done diff --git a/.gitea/scripts/ioc-install.sh b/.gitea/scripts/ioc-install.sh new file mode 100755 index 0000000..01a68d8 --- /dev/null +++ b/.gitea/scripts/ioc-install.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# Installs the ioc of a service from its deployed ioc dir on /sls. +# Requires the service to have been deployed first (deploy-and-restart-service.sh), +# which is what puts the substituted and environment-renamed ioc files in place. +# +# Usage: ./.gitea/scripts/ioc-install.sh +set -euo pipefail + +source "$(dirname "$0")/common.sh" +init_service_env "${1:-}" "${2:-}" + +echo "==========================================" +echo "Installing ioc: ${IOC_NAME} (${AGEBD_ENV})" +echo "==========================================" + +if [ ! -d "${IOC_DIR}" ]; then + echo "Ioc dir '${IOC_DIR}' not found, deploy the service first" >&2 + exit 1 +fi + +STDERR_FILE=$(mktemp) +trap 'rm -f "${STDERR_FILE}"' EXIT + +set +e +(cd "${IOC_DIR}" && ioc install -V --facility sls --ioc "${IOC_NAME}" --clean) 2>"${STDERR_FILE}" +INSTALL_RC=$? +set -e + +cat "${STDERR_FILE}" >&2 + +# 'ioc install ...' returns exit code 0 even on failure, so its stderr is +# inspected for error keywords to force a pipeline failure. +# Note: -a because some responses of the 'ioc ...' cli are non-utf8. +if [ ${INSTALL_RC} -ne 0 ] || grep -qa -e "\[error\]" -e "Unable to write" "${STDERR_FILE}"; then + echo "Failed to install ioc ${IOC_NAME}" >&2 + exit 1 +fi diff --git a/.gitea/scripts/ioc-restart.sh b/.gitea/scripts/ioc-restart.sh new file mode 100755 index 0000000..f573356 --- /dev/null +++ b/.gitea/scripts/ioc-restart.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# Restarts the ioc of a service. +# +# Usage: ./.gitea/scripts/ioc-restart.sh +set -euo pipefail + +source "$(dirname "$0")/common.sh" +init_service_env "${1:-}" "${2:-}" + +echo "==========================================" +echo "Restarting ioc: ${IOC_NAME} (${AGEBD_ENV})" +echo "==========================================" + +cd "${IOC_DIR}" +ioc restart "${IOC_NAME}" diff --git a/.gitea/scripts/ioc-start.sh b/.gitea/scripts/ioc-start.sh new file mode 100755 index 0000000..8b187cf --- /dev/null +++ b/.gitea/scripts/ioc-start.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Starts the ioc of a service through shellbox on the ioc host. +# Needed once after the initial install of a new ioc. +# +# Usage: ./.gitea/scripts/ioc-start.sh +set -euo pipefail + +source "$(dirname "$0")/common.sh" +init_service_env "${1:-}" "${2:-}" + +IOC_PORT=$(uv run --directory scripts ci/get_ioc_port.py "${SERVICE_NAME_LOWER}") + +echo "==========================================" +echo "Starting ioc: ${IOC_NAME} on ${IOC_HOST}:${IOC_PORT}" +echo "==========================================" + +ssh -o BatchMode=yes "${IOC_HOST}" bash -s <> $GITHUB_OUTPUT - # - name: Install Master IOC - - # - name: Restart Master IOC - + # The ioc steps read the deployed ioc files on /sls, so the service + # has to be deployed before its ioc is installed. - name: Deploy and Restart Master Service run: | ./.gitea/scripts/deploy-and-restart-service.sh "master" "dev" - # - name: Install New IOC + - name: Install Master IOC + run: | + ./.gitea/scripts/ioc-install.sh "master" "dev" - # - name: Start New IOC + - name: Restart Master IOC + run: | + ./.gitea/scripts/ioc-restart.sh "master" "dev" - name: Deploy and Restart New Service run: | SERVICE_NAME=${{ steps.parse_branch.outputs.service_name_lower }} ./.gitea/scripts/deploy-and-restart-service.sh "${SERVICE_NAME}" "dev" + + - name: Install New IOC + run: | + SERVICE_NAME=${{ steps.parse_branch.outputs.service_name_lower }} + ./.gitea/scripts/ioc-install.sh "${SERVICE_NAME}" "dev" + + - name: Start New IOC + run: | + SERVICE_NAME=${{ steps.parse_branch.outputs.service_name_lower }} + ./.gitea/scripts/ioc-start.sh "${SERVICE_NAME}" "dev" diff --git a/.gitea/workflows/ioc.yml b/.gitea/workflows/ioc.yml new file mode 100644 index 0000000..e3594a6 --- /dev/null +++ b/.gitea/workflows/ioc.yml @@ -0,0 +1,56 @@ +name: Ioc + +# Manually install / start / restart iocs, i.e. what the 'agebd ioc ...' cli +# commands used to do. The ioc files are read from the deployed dir on /sls, +# so the service has to be deployed (see the 'Deploy' workflow) beforehand. +on: + workflow_dispatch: + inputs: + action: + description: 'What to do with the ioc(s)' + type: choice + required: true + default: 'install' + options: + - install + - restart + - start + service: + description: "Service name in lower case, or 'all' for every service" + type: string + required: true + agebd_env: + description: 'Environment' + type: choice + required: true + default: 'dev' + options: + - dev + - prod + +env: + UV_CACHE_DIR: /var/cache/uv + UV_LINK_MODE: hardlink + +jobs: + ioc-dev: + if: ${{ inputs.agebd_env == 'dev' }} + runs-on: hla-dev + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Run ioc ${{ inputs.action }} + run: | + ./.gitea/scripts/ioc-for-services.sh "${{ inputs.action }}" "${{ inputs.service }}" "dev" + + ioc-prod: + if: ${{ inputs.agebd_env == 'prod' }} + runs-on: hla-prod + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Run ioc ${{ inputs.action }} + run: | + ./.gitea/scripts/ioc-for-services.sh "${{ inputs.action }}" "${{ inputs.service }}" "prod" diff --git a/ansible/ansible.cfg b/ansible/ansible.cfg deleted file mode 100644 index 758081a..0000000 --- a/ansible/ansible.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[defaults] -remote_tmp = /tmp/ansible-$USER - -# some responses of 'ioc ...' cli are non-utf8 -module_strict_utf8_response = False - -# ./ refers to dir in which this file is located -collections_path = ./installed-collections diff --git a/ansible/collections/requirements.yml b/ansible/collections/requirements.yml deleted file mode 100644 index 6b3fb4c..0000000 --- a/ansible/collections/requirements.yml +++ /dev/null @@ -1,3 +0,0 @@ -collections: - - name: ansible.posix - version: 1.6.0 \ No newline at end of file diff --git a/ansible/inventories/dev/hosts.yml b/ansible/inventories/dev/hosts.yml deleted file mode 100644 index 3ac0e24..0000000 --- a/ansible/inventories/dev/hosts.yml +++ /dev/null @@ -1,19 +0,0 @@ -all: - vars: - agebd_env: "dev" - env_suffix_upper: "-DEV" - env_suffix_lower: "-dev" - - children: - lc: - hosts: - sls-lc: - ansible_remote_tmp: /tmp/.ansible_${ansible_user}_tmp - vserv: - hosts: - sls-vserv-bd-01-dev: - ansible_ssh_pipelining: true - ansible_ssh_common_args: '-o ForwardAgent=yes' - vserv-hla: - hosts: - sls-vserv-bd-hla01-dev: diff --git a/ansible/inventories/prod/hosts.yml b/ansible/inventories/prod/hosts.yml deleted file mode 100644 index 20ea709..0000000 --- a/ansible/inventories/prod/hosts.yml +++ /dev/null @@ -1,18 +0,0 @@ -all: - vars: - agebd_env: "prod" - env_suffix_upper: "" - env_suffix_lower: "" - - children: - lc: - hosts: - sls-lca: - ansible_remote_tmp: /tmp/.ansible_${ansible_user}_tmp - vserv: - hosts: - sls-vserv-bd-01: - ansible_ssh_pipelining: true - vserv-hla: - hosts: - sls-vserv-bd-hla01: diff --git a/ansible/playbooks/add-new-service.yml b/ansible/playbooks/add-new-service.yml deleted file mode 100644 index a2bfbd0..0000000 --- a/ansible/playbooks/add-new-service.yml +++ /dev/null @@ -1,42 +0,0 @@ ---- -- name: Add a new service - hosts: vserv-hla - connection: local - gather_facts: true # Gather once here, available to all included tasks! - - vars: - repo_root: "{{ playbook_dir }}/../.." - - tasks: - # - name: Install Master IOC - # vars: - # preferred_service_name_lower: master - # branch_name: "feature/add-service-{{ service_name_lower }}" - # import_tasks: ../tasks/ioc/ioc-install.yml - - # - name: Restart Master IOC - # vars: - # preferred_service_name_lower: master - # branch_name: "feature/add-service-{{ service_name_lower }}" - # import_tasks: ../tasks/ioc/ioc-restart.yml - - - name: Deploy and Restart Master Service - vars: - preferred_service_name_lower: master - branch_name: "feature/add-service-{{ service_name_lower }}" - import_tasks: ../tasks/service/service-deploy-and-restart.yml - - # - name: Install New IOC - # vars: - # branch_name: "feature/add-service-{{ service_name_lower }}" - # import_tasks: ../tasks/ioc/ioc-install.yml - - # - name: Start New IOC - # vars: - # branch_name: "feature/add-service-{{ service_name_lower }}" - # import_tasks: ../tasks/ioc/ioc-start.yml - - - name: Deploy and Restart New Service - vars: - branch_name: "feature/add-service-{{ service_name_lower }}" - import_tasks: ../tasks/service/service-deploy-and-restart.yml diff --git a/ansible/playbooks/deploy-and-restart-modified-services.yml b/ansible/playbooks/deploy-and-restart-modified-services.yml deleted file mode 100644 index cb47314..0000000 --- a/ansible/playbooks/deploy-and-restart-modified-services.yml +++ /dev/null @@ -1,24 +0,0 @@ ---- -- name: Deploy and Restart Modified Services - hosts: vserv-hla - connection: local - - vars: - # Passed from the Gitea workflow, e.g., "master playground" - changed_services_raw: "" - agebd_env: "dev" - repo_root: "{{ playbook_dir }}/../.." - - tasks: - # Fail early if no services were modified - - name: Check if there are services to deploy - ansible.builtin.meta: end_play - when: changed_services_raw | trim == "" - - # Main Loop: loop through the list of modified service names - - name: Deploy and Restart Modified Services - include_tasks: ../tasks/service/service-deploy-and-restart.yml - loop: "{{ changed_services_raw.split() }}" - loop_control: - loop_var: service_name_lower - extended: yes diff --git a/ansible/playbooks/ioc-install.yml b/ansible/playbooks/ioc-install.yml deleted file mode 100644 index f337812..0000000 --- a/ansible/playbooks/ioc-install.yml +++ /dev/null @@ -1,11 +0,0 @@ ---- -- name: Install an IOC - hosts: lc - gather_facts: false - - vars: - workspace_dir: "/tmp/hla_framework_bd" - - tasks: - - name: Run ioc install tasks - ansible.builtin.import_tasks: ../tasks/ioc/ioc-install.yml diff --git a/ansible/playbooks/ioc-restart.yml b/ansible/playbooks/ioc-restart.yml deleted file mode 100644 index a36728e..0000000 --- a/ansible/playbooks/ioc-restart.yml +++ /dev/null @@ -1,11 +0,0 @@ ---- -- name: Restart an IOC - hosts: lc - gather_facts: false - - vars: - workspace_dir: "/tmp/hla_framework_bd" - - tasks: - - name: Run ioc restart tasks - ansible.builtin.include_tasks: ../tasks/ioc/ioc-restart.yml diff --git a/ansible/playbooks/ioc-start.yml b/ansible/playbooks/ioc-start.yml deleted file mode 100644 index 02a6386..0000000 --- a/ansible/playbooks/ioc-start.yml +++ /dev/null @@ -1,14 +0,0 @@ -# TODO: ansible seems to be very slow on this machine -# each step takes quite a while (e.g. cloning repo, which -# is significantly faster on other machines). ---- -- name: Start an IOC - hosts: vserv - gather_facts: false - - vars: - workspace_dir: "/tmp/hla_framework_bd" - - tasks: - - name: Run ioc start tasks - ansible.builtin.import_tasks: ../tasks/ioc/ioc-start.yml diff --git a/ansible/tasks/ioc/ioc-install.yml b/ansible/tasks/ioc/ioc-install.yml deleted file mode 100644 index 225c2c7..0000000 --- a/ansible/tasks/ioc/ioc-install.yml +++ /dev/null @@ -1,63 +0,0 @@ ---- -- name: Init service name - ansible.builtin.import_tasks: ../utils/init-service-name.yml - -- name: Clone repo - ansible.builtin.import_tasks: ../utils/clone-repo.yml - -- name: Get and set ioc_port - ansible.builtin.import_tasks: ../utils/get-ioc-port.yml - -- name: "[{{ target_service_name_lower }}] Establish environment naming conventions" - ansible.builtin.set_fact: - service_name_upper: "{{ target_service_name_lower | upper }}" - -- name: "[{{ target_service_name_lower }}] Define file paths" - ansible.builtin.set_fact: - ioc_base_dir: "{{ workspace_dir }}/services/{{ target_service_name_lower }}/current/ioc" - orig_subs_name: "AGEBD-CPCL-{{ service_name_upper }}_main.subs" - target_subs_name: "AGEBD-CPCL-{{ service_name_upper }}{{ env_suffix_upper }}_main.subs" - orig_params_name: "AGEBD-CPCL-{{ service_name_upper }}_parameters.yaml" - target_params_name: "AGEBD-CPCL-{{ service_name_upper }}{{ env_suffix_upper }}_parameters.yaml" - -# Rename the subs file if we are in DEV -- name: "[{{ target_service_name_lower }}] Rename substitution file for environment" - ansible.builtin.command: - cmd: "mv {{ ioc_base_dir }}/{{ orig_subs_name }} {{ ioc_base_dir }}/{{ target_subs_name }}" - removes: "{{ ioc_base_dir }}/{{ orig_subs_name }}" # Only runs if the original file exists - -# Rename the paramters file if we are in DEV -- name: "[{{ target_service_name_lower }}] Rename parameters file for environment" - ansible.builtin.command: - cmd: "mv {{ ioc_base_dir }}/{{ orig_params_name }} {{ ioc_base_dir }}/{{ target_params_name }}" - removes: "{{ ioc_base_dir }}/{{ orig_params_name }}" # Only runs if the original file exists - -# Replace {{ agebd_env_suffix_upper }} inside the newly renamed subs file -- name: "[{{ target_service_name_lower }}] Substitute environment tokens inside subs file" - ansible.builtin.replace: - path: "{{ ioc_base_dir }}/{{ target_subs_name }}" - regexp: '\{\{\s*agebd_env_suffix_upper\s*\}\}' - replace: "{{ env_suffix_upper }}" - -# Replace {{ agebd_env_suffix_lower }} and {{ ioc_port }} inside the newly renamed params file -- name: "[{{ target_service_name_lower }}] Substitute environment token inside params file" - ansible.builtin.replace: - path: "{{ ioc_base_dir }}/{{ target_params_name }}" - regexp: "{{ item.regexp }}" - replace: "{{ item.replace | string }}" - with_items: - - { regexp: '\{\{\s*agebd_env_suffix_lower\s*\}\}', replace: "{{ env_suffix_lower }}" } - - { regexp: '\{\{\s*ioc_port\s*\}\}', replace: "{{ ioc_port }}" } - -- name: "[{{ target_service_name_lower }}] Run ioc install" - ansible.builtin.shell: - cmd: "ioc install -V --facility sls --ioc AGEBD-CPCL-{{ service_name_upper }}{{ env_suffix_upper }} --clean" - chdir: "{{ ioc_base_dir }}" - changed_when: true - register: ioc_install_result - # Force a pipeline failure if the command output contains error keywords - # (ioc install ... returns exit code 0 even on failure...) - failed_when: > - ioc_install_result.rc != 0 or - "[error]" in ioc_install_result.stderr or - "Unable to write" in ioc_install_result.stderr diff --git a/ansible/tasks/ioc/ioc-restart.yml b/ansible/tasks/ioc/ioc-restart.yml deleted file mode 100644 index ad637ac..0000000 --- a/ansible/tasks/ioc/ioc-restart.yml +++ /dev/null @@ -1,20 +0,0 @@ ---- -- name: Init service name - ansible.builtin.import_tasks: ../utils/init-service-name.yml - -- name: Clone repo - ansible.builtin.import_tasks: ../utils/clone-repo.yml - -- name: "[{{ target_service_name_lower }}] Establish environment naming conventions" - ansible.builtin.set_fact: - service_name_upper: "{{ target_service_name_lower | upper }}" - -- name: "[{{ target_service_name_lower }}] Define file paths" - ansible.builtin.set_fact: - ioc_base_dir: "{{ workspace_dir }}/services/{{ target_service_name_lower }}/current/ioc" - -- name: "[{{ target_service_name_lower }}] Restart IOC" - ansible.builtin.shell: - cmd: "ioc restart AGEBD-CPCL-{{ service_name_upper }}{{ env_suffix_upper }}" - chdir: "{{ ioc_base_dir }}" - changed_when: true diff --git a/ansible/tasks/ioc/ioc-start.yml b/ansible/tasks/ioc/ioc-start.yml deleted file mode 100644 index 28d3e64..0000000 --- a/ansible/tasks/ioc/ioc-start.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -- name: Init service name - ansible.builtin.import_tasks: ../utils/init-service-name.yml - -- name: Clone repo - ansible.builtin.import_tasks: ../utils/clone-repo.yml - -- name: Get and set ioc_port - ansible.builtin.import_tasks: ../utils/get-ioc-port.yml - -- name: "[{{ ioc_port }}] Start IOC" - ansible.builtin.shell: | - sudo shellbox status - sudo shellbox reload - sudo shellbox status - sudo shellbox start {{ ioc_port }} - changed_when: true diff --git a/ansible/tasks/service/service-deploy-and-restart.yml b/ansible/tasks/service/service-deploy-and-restart.yml deleted file mode 100644 index 0d38c27..0000000 --- a/ansible/tasks/service/service-deploy-and-restart.yml +++ /dev/null @@ -1,53 +0,0 @@ ---- -- name: Initialize service name - ansible.builtin.set_fact: - # Uses preferred_service_name_lower if defined in vars, otherwise falls back to the CLI extra-vars - target_service_name_lower: "{{ preferred_service_name_lower | default(service_name_lower) }}" - -- name: "[{{ target_service_name_lower }}] Define service specific paths and names" - ansible.builtin.set_fact: - svc_current_dir: "/sls/bd/hla/{{ agebd_env }}/services/{{ target_service_name_lower }}/current" - service_unit_name: "AGEBD-SERVICE-{{ target_service_name_lower | upper }}.service" - -- name: "[{{ target_service_name_lower }}] Ensure target directory structure exists" - ansible.builtin.file: - path: "{{ svc_current_dir }}" - state: directory - # ansible.builtin.shell: | - # mkdir -p "{{ svc_current_dir }}" - -# TODO: make sure this is what we want (essentially wipes existing dest dir). Does it remove .venv? -- name: "[{{ target_service_name_lower }}] Sync service deployment files" - ansible.posix.synchronize: - src: "{{ repo_root }}/services/{{ target_service_name_lower }}/current/" - dest: "{{ svc_current_dir }}/" - delete: yes # This removes stale files on the target that no longer exist locally - recursive: yes - -- name: "[{{ target_service_name_lower }}] Substitute environment variable inline" - ansible.builtin.replace: - path: "{{ svc_current_dir }}/systemd/{{ service_unit_name }}" - regexp: '\{\{\s*agebd_env\s*\}\}' - replace: "{{ agebd_env }}" - - # systemctl --user link --force "./{{ service_unit_name }}" -- name: "[{{ target_service_name_lower }}] Symlink systemd unit file (Absolute Path)" - ansible.builtin.file: - src: "{{ svc_current_dir }}/systemd/{{ service_unit_name }}" - dest: "~/.config/systemd/user/{{ service_unit_name }}" - state: link - force: yes # This overwrites the broken/existing symlink cleanly without error - - # export XDG_RUNTIME_DIR=/run/user/$(id -u) - # systemctl --user daemon-reload - # systemctl --user enable "{{ service_unit_name }}" - # systemctl --user restart "{{ service_unit_name }}" -- name: "[{{ target_service_name_lower }}] Enable and Restart Systemd Service" - ansible.builtin.systemd_service: - name: "{{ service_unit_name }}" - scope: user - daemon_reload: yes - enabled: yes - state: restarted - environment: - XDG_RUNTIME_DIR: "/run/user/{{ ansible_user_uid }}" diff --git a/ansible/tasks/utils/clone-repo.yml b/ansible/tasks/utils/clone-repo.yml deleted file mode 100644 index 3c782bb..0000000 --- a/ansible/tasks/utils/clone-repo.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -- name: Clone this repository - ansible.builtin.git: - repo: "git@gitea.psi.ch:sls/hla_framework_bd.git" - dest: "{{ workspace_dir }}" - accept_hostkey: true - version: "{{ branch_name }}" - force: true diff --git a/ansible/tasks/utils/get-ioc-port.yml b/ansible/tasks/utils/get-ioc-port.yml deleted file mode 100644 index 2f18c69..0000000 --- a/ansible/tasks/utils/get-ioc-port.yml +++ /dev/null @@ -1,18 +0,0 @@ ---- -- name: Read the service registry file - ansible.builtin.slurp: - src: "{{ workspace_dir }}/config/services_registry.yml" - register: remote_registry_file - -- name: Parse the service registry YAML content into a fact - ansible.builtin.set_fact: - services_registry: "{{ remote_registry_file.content | b64decode | from_yaml }}" - -- name: Extract the port from the services registry and save it as a persistent fact - ansible.builtin.set_fact: - ioc_port: "{{ services_registry.services | selectattr('name', 'equalto', target_service_name_lower) | map(attribute='ioc_port') | first | default(none) }}" - -- name: Fail if the service or port wasn't found in the registry - ansible.builtin.fail: - msg: "Service '{{ target_service_name_lower }}' not found in services registry or port not set" - when: ioc_port | trim == "" or ioc_port is none diff --git a/ansible/tasks/utils/init-service-name.yml b/ansible/tasks/utils/init-service-name.yml deleted file mode 100644 index 46ad173..0000000 --- a/ansible/tasks/utils/init-service-name.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -- name: Initialize service name - ansible.builtin.set_fact: - # Uses preferred_service_name_lower if defined in vars, otherwise falls back to the CLI extra-vars - target_service_name_lower: "{{ preferred_service_name_lower | default(service_name_lower) }}" diff --git a/cli/pyproject.toml b/cli/pyproject.toml index 0fa047f..e7728cf 100644 --- a/cli/pyproject.toml +++ b/cli/pyproject.toml @@ -9,8 +9,6 @@ authors = [ dependencies = [ "agebd", - "ansible>=8.7.0", - "ansible-runner>=2.4.3", "copier>=9.10.3", "pydantic>=2.13.4", "pydantic-settings>=2.14.2", diff --git a/cli/src/core/ansible.py b/cli/src/core/ansible.py deleted file mode 100644 index 445dca5..0000000 --- a/cli/src/core/ansible.py +++ /dev/null @@ -1,40 +0,0 @@ -import os -import sys - -import ansible_runner -import typer - -from agebd.utils import get_git_root -from core.enums import IOC_ENV - -ioc = typer.Typer(no_args_is_help=True) - -REPO_ROOT = get_git_root(__file__) - - -def run_playbook(playbook: str, env: IOC_ENV, vars: list[str]): - env_str = str(env) - if env_str not in ["dev", "prod"]: - raise ValueError("env must be 'dev' or 'prod'") - - current_env = os.environ.copy() - current_env["ANSIBLE_CONFIG"] = f"{REPO_ROOT}/ansible/ansible.cfg" - - extra_vars = [f"--extra-vars={var}" for var in vars] - out, err, rc = ansible_runner.run_command( - executable_cmd=f"ansible-playbook", - cmdline_args=[ - playbook, - "-i", - f"{REPO_ROOT}/ansible/inventories/{env_str}/hosts.yml", - *extra_vars, - "-v", - ], - envvars=current_env, - input_fd=sys.stdin, - output_fd=sys.stdout, - error_fd=sys.stderr, - ) - print("rc: {}".format(rc)) - print("out: {}".format(out)) - print("err: {}".format(err)) diff --git a/cli/src/core/enums.py b/cli/src/core/enums.py index fc6dae1..2379c23 100644 --- a/cli/src/core/enums.py +++ b/cli/src/core/enums.py @@ -6,14 +6,6 @@ class ServiceStatus(str, Enum): DISABLED = "disabled" -class IOC_ENV(str, Enum): - PROD = "prod" - DEV = "dev" - - def __str__(self) -> str: - return self.value - - class GuiOption(str, Enum): NEW = "new" EXISTING = "existing" diff --git a/cli/src/ioc.py b/cli/src/ioc.py deleted file mode 100644 index d0cd20c..0000000 --- a/cli/src/ioc.py +++ /dev/null @@ -1,112 +0,0 @@ -import typer - -from agebd.utils import get_git_root -from config.paths import Paths -from core.ansible import run_playbook -from core.enums import IOC_ENV -from models import ServiceRegistry - -ioc = typer.Typer(no_args_is_help=True) - -REPO_ROOT = get_git_root(__file__) - -ANSIBLE_PLAYBOOKS_DIR = REPO_ROOT / "ansible" / "playbooks" -IOC_PLAYBOOK_INSTALL = ANSIBLE_PLAYBOOKS_DIR / "ioc-install.yml" -IOC_PLAYBOOK_RESTART = ANSIBLE_PLAYBOOKS_DIR / "ioc-restart.yml" -IOC_PLAYBOOK_START = ANSIBLE_PLAYBOOKS_DIR / "ioc-start.yml" - -SERVICE_NAME_HELP = "Service name in lower case" - - -def _resolve_branch_name(branch_name: str | None, service_name_lower: str) -> str: - return branch_name or f"feature/add-service-{service_name_lower}" - - -def _get_registry_services(): - paths = Paths() - registry = ServiceRegistry.read_from_file(paths.service_registry_file) - return registry.get_services() - - -@ioc.command(no_args_is_help=True) -def install( - env: IOC_ENV = typer.Option(..., "--env"), - service_name_lower: str = typer.Option(..., "--service-name", "-s", help=SERVICE_NAME_HELP), - branch_name: str | None = typer.Option( - None, "--branch-name", "-b", help="Default is 'feature/add-service-{service-name}'" - ), -): - branch_name = _resolve_branch_name(branch_name, service_name_lower) - run_playbook( - playbook=str(IOC_PLAYBOOK_INSTALL), - env=env, - vars=[f"branch_name={branch_name}", f"service_name_lower={service_name_lower}"], - ) - - -@ioc.command(no_args_is_help=True) -def install_all( - env: IOC_ENV = typer.Option(..., "--env"), -): - for service in _get_registry_services(): - run_playbook( - playbook=str(IOC_PLAYBOOK_INSTALL), - env=env, - vars=["branch_name=main", f"service_name_lower={service.name_lower}"], - ) - - -@ioc.command(no_args_is_help=True) -def start( - env: IOC_ENV = typer.Option(..., "--env"), - service_name_lower: str = typer.Option(..., "--service-name", "-s", help=SERVICE_NAME_HELP), - branch_name: str | None = typer.Option( - None, "--branch-name", "-b", help="Default is 'feature/add-service-{service-name}'" - ), -): - branch_name = _resolve_branch_name(branch_name, service_name_lower) - run_playbook( - playbook=str(IOC_PLAYBOOK_START), - env=env, - vars=[f"service_name_lower={service_name_lower}", f"branch_name={branch_name}"], - ) - - -@ioc.command() -def start_all( - env: IOC_ENV = typer.Option(..., "--env"), -): - for service in _get_registry_services(): - run_playbook( - playbook=str(IOC_PLAYBOOK_START), - env=env, - vars=[f"service_name_lower={service.name_lower}"], - ) - - -@ioc.command(no_args_is_help=True) -def restart( - env: IOC_ENV = typer.Option(..., "--env"), - service_name_lower: str = typer.Option(..., "--service-name", "-s", help=SERVICE_NAME_HELP), - branch_name: str | None = typer.Option( - None, "--branch-name", "-b", help="Default is 'feature/add-service-{service-name}'" - ), -): - branch_name = _resolve_branch_name(branch_name, service_name_lower) - run_playbook( - playbook=str(IOC_PLAYBOOK_RESTART), - env=env, - vars=[f"branch_name={branch_name}", f"service_name_lower={service_name_lower}"], - ) - - -@ioc.command(no_args_is_help=True) -def restart_all( - env: IOC_ENV = typer.Option(..., "--env"), -): - for service in _get_registry_services(): - run_playbook( - playbook=str(IOC_PLAYBOOK_RESTART), - env=env, - vars=["branch_name=main", f"service_name_lower={service.name_lower}"], - ) diff --git a/cli/src/main.py b/cli/src/main.py index a23e705..7a5c16e 100644 --- a/cli/src/main.py +++ b/cli/src/main.py @@ -2,7 +2,6 @@ import logging import typer -import ioc import service logger = logging.getLogger(__name__) @@ -10,7 +9,6 @@ logger = logging.getLogger(__name__) cli = typer.Typer(no_args_is_help=True, add_completion=False) cli.add_typer(service.service, name="service") -cli.add_typer(ioc.ioc, name="ioc") if __name__ == "__main__": diff --git a/cli/uv.lock b/cli/uv.lock index d56b4cc..568ebd0 100644 --- a/cli/uv.lock +++ b/cli/uv.lock @@ -37,8 +37,6 @@ version = "0.1.0" source = { editable = "." } dependencies = [ { name = "agebd" }, - { name = "ansible" }, - { name = "ansible-runner" }, { name = "copier" }, { name = "pydantic" }, { name = "pydantic-settings" }, @@ -60,8 +58,6 @@ dev = [ [package.metadata] requires-dist = [ { name = "agebd", editable = "../packages/agebd" }, - { name = "ansible", specifier = ">=8.7.0" }, - { name = "ansible-runner", specifier = ">=2.4.3" }, { name = "copier", specifier = ">=9.10.3" }, { name = "pydantic", specifier = ">=2.13.4" }, { name = "pydantic-settings", specifier = ">=2.14.2" }, @@ -98,49 +94,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, ] -[[package]] -name = "ansible" -version = "10.7.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "ansible-core" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/d4/64/29fdff6fe7682342adb54802c1cd90b2272d382e1743089af88f90a1d986/ansible-10.7.0.tar.gz", hash = "sha256:59d29e3de1080e740dfa974517d455217601b16d16880314d9be26145c68dc22", size = 41256974, upload-time = "2024-12-03T18:04:25.794Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f3/95/cb8944902a2cdd94b1e19ff73695548679a388b9c473dc63c8dc64ffea3a/ansible-10.7.0-py3-none-any.whl", hash = "sha256:0089f08e047ceb70edd011be009f5c6273add613fbe491e9697c0556c989d8ea", size = 51576038, upload-time = "2024-12-03T18:04:20.065Z" }, -] - -[[package]] -name = "ansible-core" -version = "2.17.14" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cryptography" }, - { name = "jinja2" }, - { name = "packaging" }, - { name = "pyyaml" }, - { name = "resolvelib" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ff/80/2925a0564f6f99a8002c3be3885b83c3a1dc5f57ebf00163f528889865f5/ansible_core-2.17.14.tar.gz", hash = "sha256:7c17fee39f8c29d70e3282a7e9c10bd70d5cd4fd13ddffc5dcaa52adbd142ff8", size = 3119687, upload-time = "2025-09-08T18:28:03.158Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/86/29/d694562f1a875b50aa74f691521fe493704f79cf1938cd58f28f7e2327d2/ansible_core-2.17.14-py3-none-any.whl", hash = "sha256:34a49582a57c2f2af17ede2cefd3b3602a2d55d22089f3928570d52030cafa35", size = 2189656, upload-time = "2025-09-08T18:28:00.375Z" }, -] - -[[package]] -name = "ansible-runner" -version = "2.4.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "packaging" }, - { name = "pexpect" }, - { name = "python-daemon" }, - { name = "pyyaml" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/68/4f/62222b42b52cc771db51ccc77ffac19cc5f0196ff61de7c93585845a819b/ansible_runner-2.4.3.tar.gz", hash = "sha256:5f3025529bb968fdc3b627457dd8d418dbf9d53bc73735d50e69c28544d53031", size = 154148, upload-time = "2026-03-16T18:42:14.861Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e3/89/fa7f81db6134caa455c9351373ee934b5fdeed212eb939d6c42d80d683d7/ansible_runner-2.4.3-py3-none-any.whl", hash = "sha256:cdac6daa151a50084ffda710e769db23fa975fc0507796191d7708831b286e37", size = 80257, upload-time = "2026-03-16T18:42:13.72Z" }, -] - [[package]] name = "asttokens" version = "3.0.2" @@ -150,29 +103,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d4/2b/04b8a15f3a1c77bc79ddf5c73875327f34b4fa75982df2b76e45e402d364/asttokens-3.0.2-py3-none-any.whl", hash = "sha256:9da13157f5b28becde0bd374fc677dcd3c290614264eff096f167c469cd9f933", size = 28702, upload-time = "2026-07-12T03:31:47.542Z" }, ] -[[package]] -name = "cffi" -version = "2.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pycparser", marker = "implementation_name != 'PyPy'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/57/5f/ff100cae70ebe9d8df1c01a00e510e45d9adb5c1fdda84791b199141de97/cffi-2.1.0.tar.gz", hash = "sha256:efc1cdd798b1aaf39b4610bba7aad28c9bea9b910f25c784ccf9ec1fa719d1f9", size = 531036, upload-time = "2026-07-06T21:34:30.382Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c0/e9/6d7724983b3d5a0908dbf74f64038ade77c18646ff6636ec7894fd392ce1/cffi-2.1.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:b65f590ef2a44640f9a05dbb548a429b4ade77913ce683ac8b1480777658a6c0", size = 183837, upload-time = "2026-07-06T21:32:09.655Z" }, - { url = "https://files.pythonhosted.org/packages/69/aa/24580a278de21fd7322635556334d9b535f1cbc00b0a3919447cdf464c65/cffi-2.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:164bff1657b2a74f0b6d54e11c9b375bc97b931f2ca9c43fcf875838da1570dd", size = 184226, upload-time = "2026-07-06T21:32:11.196Z" }, - { url = "https://files.pythonhosted.org/packages/88/a9/02cae418ec4beb282ace11958d9d4737793439d561fadc7e6d56f2e2b354/cffi-2.1.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:c941bb58d5a6e1c3892d86e42927ed6c180302f07e6d395d08c416e594b98b46", size = 211107, upload-time = "2026-07-06T21:32:12.328Z" }, - { url = "https://files.pythonhosted.org/packages/3b/30/c806937ed5e4c2c7ac30d9d6b76b5dc57ff8b75d83800d9bb11a8253cf2a/cffi-2.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a016194dbe13d14ee9556e734b772d8d67b947092b268d757fd4290e3ba2dfc2", size = 218733, upload-time = "2026-07-06T21:32:13.67Z" }, - { url = "https://files.pythonhosted.org/packages/f9/cf/398272b8bbfd58aa314fda5a7f1cdbb26d1d78ae324a11211521315dd1f0/cffi-2.1.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:03e9810d18c646077e501f661b682fbf5dee4676048527ca3cffe66faa9960dd", size = 205543, upload-time = "2026-07-06T21:32:15.148Z" }, - { url = "https://files.pythonhosted.org/packages/45/ca/f91641185cdd90c36d317a9dc7f85e88ef8682d8b300977baff5e23c35d8/cffi-2.1.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:19c54ac121cad98450b4896fa9a43ee0180d57bc4bc911a33db6cab1efab6cd3", size = 205460, upload-time = "2026-07-06T21:32:16.479Z" }, - { url = "https://files.pythonhosted.org/packages/38/66/04781a77b411f0bb5b234d62c1814754ab75ebe455ccff1b08e8d7aae98f/cffi-2.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d433a51f1870e43a13b6732f92aaf540ff77c2015097c78556f75a2d6c030e0", size = 218760, upload-time = "2026-07-06T21:32:17.98Z" }, - { url = "https://files.pythonhosted.org/packages/d0/9a/bb1d5ed9c3fcae158e9f6391bf309c95d98c2ac37ed56573228471d0af5e/cffi-2.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3d7f118b5adbfdfead90c25822690b02bc8074fba949bb7858bec4ebd55adb43", size = 221230, upload-time = "2026-07-06T21:32:19.407Z" }, - { url = "https://files.pythonhosted.org/packages/41/aa/3c1409cdd26094efacd1c36c66e0a6eb9d4296e4fd4f9901b8b2042f4323/cffi-2.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c5f5df567f6eb216de69be06ce55c8b714090fae02b18a3b40da8163b8c5fa9c", size = 213524, upload-time = "2026-07-06T21:32:20.828Z" }, - { url = "https://files.pythonhosted.org/packages/fa/75/74dfb7c3fc6ebbd408038476bd4c1d7e925c62614e7b9c534ecc34218288/cffi-2.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:11b3fb55f4f8ad92274ed26705f65d8f91457de71f5380061eb6d125a768fecd", size = 220341, upload-time = "2026-07-06T21:32:21.9Z" }, - { url = "https://files.pythonhosted.org/packages/70/b6/9003c33a3e7d2c1306f5962e646457dcfe5a8cd8fce6bbe02d7af25db783/cffi-2.1.0-cp310-cp310-win32.whl", hash = "sha256:9d72af0cf10a76a600a9690078fe31c63b9588c8e86bf9fd353f713c84b5db0f", size = 174578, upload-time = "2026-07-06T21:32:23.073Z" }, - { url = "https://files.pythonhosted.org/packages/8a/26/710688310447531c7a22f857c7f79d9855ec18b03e04494ced723fb37e2f/cffi-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb62edb5bb52cca65fab91a63afa7561607120d26090a7e8fda6fb9f064726da", size = 185071, upload-time = "2026-07-06T21:32:24.671Z" }, -] - [[package]] name = "colorama" version = "0.4.6" @@ -207,44 +137,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/22/2c/68dec88ee26f96af2d4d8ee9d8567313a0826f4fd6bc5ae4527be670d354/copier-9.17.0-py3-none-any.whl", hash = "sha256:fe4e7b59faf4c0e1386eccbb79c6797e6df33ca20d5de49a8372571d8669f2ad", size = 65954, upload-time = "2026-07-13T14:33:03.301Z" }, ] -[[package]] -name = "cryptography" -version = "49.0.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/1f/99/d1c90d6041656cc6ee229dc99cd67fd0cd5aec3c5f7d72fffc27cc750054/cryptography-49.0.0.tar.gz", hash = "sha256:f89660a348f4f78a92366240a61404e337586ef7f5909a2fef59ca88ef505493", size = 854345, upload-time = "2026-06-12T20:02:30.512Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9b/22/adf66990e63584a68dfb50c24f48a125c07b1699899381c8151e63ed458c/cryptography-49.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:966fe0e9c67490071f14c0d2b1cb2dfb3023c5ce39457343931415f08382f2db", size = 4032100, upload-time = "2026-06-12T20:02:32.143Z" }, - { url = "https://files.pythonhosted.org/packages/09/41/3797cfaf69cae04a13ee78ebd83f0678d9c02b4779d21ce24445326f1a69/cryptography-49.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:36d1709f992593689b45bda411498d62c6e365f2ca00b84657d4dadd24de16db", size = 4692978, upload-time = "2026-06-12T20:01:21.305Z" }, - { url = "https://files.pythonhosted.org/packages/e6/8b/43011f7ebe515a8aa20d61f290a326cd890c2e738e16e59eaff8d9c3a412/cryptography-49.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0e959b578856a3924bc0cbb710fc12c387b9412a951389f3ca61704a9e25f325", size = 4716422, upload-time = "2026-06-12T20:01:48.566Z" }, - { url = "https://files.pythonhosted.org/packages/4a/91/01ce7303a4579e6d3a6abef01bd322848e9ea7a219adcabc5048b9033571/cryptography-49.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:53ecee2e23f7169b6117e99fc8a944e5e50f79e69758a83b52a00cb98ab2b2d2", size = 4700503, upload-time = "2026-06-12T20:02:47.091Z" }, - { url = "https://files.pythonhosted.org/packages/62/99/a2c95cf8293f07491e9e27c20cc4dcd18176d944e674679adeb1d0173fd6/cryptography-49.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:2eda353d8a27bcbcaa4cbed18994a74ab4d19a2ca897db188ea269ab9b71419b", size = 5309779, upload-time = "2026-06-12T20:02:08.987Z" }, - { url = "https://files.pythonhosted.org/packages/20/2c/0622f20ff02b2ef32558733443805dc82fd4c275be01b2d19d14676f3a1b/cryptography-49.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2afe9051da7ae7bd5905da5a949280c7d2bb75682e188f650a9d0f2756b834c6", size = 4749683, upload-time = "2026-06-12T20:02:03.335Z" }, - { url = "https://files.pythonhosted.org/packages/a3/5b/c5246635d5fd3b64e0d45ae10e99fd32fe9676a79915ccfe5a61ba9af1a5/cryptography-49.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:0b82e28ee398a386f0807bba7884d30f25218855690f45115831bcce5d90822c", size = 4337874, upload-time = "2026-06-12T20:02:54.323Z" }, - { url = "https://files.pythonhosted.org/packages/6d/88/05563c7fe2e914e87d1a536d06fe83e66b4e1d95cb593e05aea375531da8/cryptography-49.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:ccac2bfebc306b862133e3bb71f3f6ee8bb525240089b2d952e4144b3a6d5da7", size = 4700283, upload-time = "2026-06-12T20:01:34.822Z" }, - { url = "https://files.pythonhosted.org/packages/c4/b6/d7696e4e890d6ae1469935164c9e5215c557671cb78d6e3f458ccceaa632/cryptography-49.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:d0527ce944105f257f605a827d6ebead966c752038b6e8656abb9c5edee6fc68", size = 5265844, upload-time = "2026-06-12T20:01:24.09Z" }, - { url = "https://files.pythonhosted.org/packages/a9/3c/f3ad17eecc1a57b0ba236dc01f90e783c51f4a2f35f64777cc4f47a184b2/cryptography-49.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:cbc77da8c523d5abd028635ba850a6966fcee2c82e2bf65a41d1d8afe0f98be9", size = 4749290, upload-time = "2026-06-12T20:01:30.848Z" }, - { url = "https://files.pythonhosted.org/packages/4f/01/339573cf1023163a400b0b5d16f6d507de413b9f60be6fd1b77feeaf6737/cryptography-49.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b87e65d263b3e5d3bb92a57e2a6638e2f31110fa7aa890c7b2dbba42248d0a3f", size = 4834612, upload-time = "2026-06-12T20:01:29.246Z" }, - { url = "https://files.pythonhosted.org/packages/71/fd/577302e213a1be9468f92d1afef66fcf1ef83d516819d9992ca547f592bd/cryptography-49.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:66ec79c3904820572d7e987abdf304281f141d37ad9a489b8e97066e7b9b6459", size = 4980804, upload-time = "2026-06-12T20:01:42.853Z" }, - { url = "https://files.pythonhosted.org/packages/1f/09/f42b1d190c5ba75f72062a387f8030d1d75f6ab035788f1d9c4b01de6525/cryptography-49.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:e5dfc1e64de5677cec922ffa8da89c546d0415bf6efdf081842e5d44c84e1f0e", size = 3810026, upload-time = "2026-06-12T20:02:39.262Z" }, - { url = "https://files.pythonhosted.org/packages/19/2a/5bb823f5bedcf80718cea7fbc95ec5515cca3769633c4b01a32be7f30e7c/cryptography-49.0.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ec5e529fb80935c94fe7b729f9972b50e351a0e6b50aa294fd5cabb109fcc29a", size = 4025947, upload-time = "2026-06-12T20:01:25.745Z" }, - { url = "https://files.pythonhosted.org/packages/3d/df/40577043ca124e17012f408ddddaeb213b856336ac82ddb3bc915f39e29f/cryptography-49.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f78ff2c9ed8dc2d036b0f4d640e22522213d047c1b14e61205a7e55c80a494d4", size = 4692429, upload-time = "2026-06-12T20:01:53.628Z" }, - { url = "https://files.pythonhosted.org/packages/2c/99/2d13299eb3dd27b02dcfaafcc91d6b5cb3329f7cbd6d8f51921acd566c1a/cryptography-49.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:35b151772baff2c74cba7fa290ceaff4c3b11c0c881eb93eb5dbc05a7cfbba18", size = 4700968, upload-time = "2026-06-12T20:02:45.383Z" }, - { url = "https://files.pythonhosted.org/packages/a5/4d/9c0cd02f95e2602dd5e563da149ee0830abef3537be8b34dc56281ebe27a/cryptography-49.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0f21641cf4b30fca7aee061ced0ec7ad7b073518088b7c9969a297c0ae796c69", size = 4697758, upload-time = "2026-06-12T20:01:41.13Z" }, - { url = "https://files.pythonhosted.org/packages/24/01/186c825898477d77e2324d5360fefe622ff1d8d1963ec0554e2cada8ec77/cryptography-49.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:9e82dcc8e56052715fb18b2429e3bca4823b1629136a2084fc45a9a5cecb9b64", size = 5298863, upload-time = "2026-06-12T20:02:24.579Z" }, - { url = "https://files.pythonhosted.org/packages/b8/7b/62cbbab75d0659865bf0273790031544a0b16c8072d258f9428dcd8190dc/cryptography-49.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6f2debedf9ca60cf1d5bd466475638af5130f89965605cd818484d19987d3a21", size = 4735983, upload-time = "2026-06-12T20:01:50.14Z" }, - { url = "https://files.pythonhosted.org/packages/6c/72/3e798c064bc39e471008075d0f9bc9daf77a80879c092e4a8e170c585ed4/cryptography-49.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:8c25ceb16df5b9435f3f6a9829204985b0e0cbee3b48aacd432c7d2c850b44d9", size = 4334173, upload-time = "2026-06-12T20:01:44.743Z" }, - { url = "https://files.pythonhosted.org/packages/f0/ee/6fca21d1ac73e06f8bef71940abfd4d2f6472b4bca284d770f32bd4086f6/cryptography-49.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:28d8b15e6275f12c8a207dc309dfa957903c927d08d0cc937ee3f63f200693cc", size = 4697298, upload-time = "2026-06-12T20:02:20.918Z" }, - { url = "https://files.pythonhosted.org/packages/67/d0/a5fcd3515f0bae49a7b6d0413cc1bdccdcc1fc0047037a0d480642cdc5d6/cryptography-49.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:6fc361c34fb6aac015ce19435876635e5c6d21db31998b0920f675f131e043b8", size = 5254338, upload-time = "2026-06-12T20:02:22.737Z" }, - { url = "https://files.pythonhosted.org/packages/a0/84/84fe36f19caf857d61cb7fc9c63035a47ffabd84ea12d1d393148efa3615/cryptography-49.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:2400ef9c9e2299a25614eb1dea3db54a69b1349efd043bfac9c67630d136df36", size = 4735650, upload-time = "2026-06-12T20:02:41.389Z" }, - { url = "https://files.pythonhosted.org/packages/6c/a0/db537264e234f7273a73ec020873d6d6b39dfd8a53db78b550ca8320440e/cryptography-49.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:67e1d20ad9ef3a563c59ef22e7a8a0b8210bd26604369ea4a30a7c66aefe504e", size = 4834820, upload-time = "2026-06-12T20:01:51.847Z" }, - { url = "https://files.pythonhosted.org/packages/93/77/8df9eb486495979bccecd1062e2eaf435250e84437040295b57d09048b0b/cryptography-49.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:42b0684e0e40cf26122427802486f6d93aea593612603a94fbf260c7eb1e9c1b", size = 4967968, upload-time = "2026-06-12T20:02:12.524Z" }, - { url = "https://files.pythonhosted.org/packages/c2/e6/f60198ea8d9dfa15fff9ed4ca02ce362f6eadd9ba757dcc50634c4257b63/cryptography-49.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:026ac7423e6fa66872d3bf889be5974507da3944f866f704fa200eadacd00001", size = 3785547, upload-time = "2026-06-12T20:02:26.847Z" }, -] - [[package]] name = "decorator" version = "5.3.1" @@ -406,15 +298,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl", hash = "sha256:e1082f5564917649c76fed239117820610516ec10f87735d0338688800a55b34", size = 18975, upload-time = "2022-06-30T14:08:49.571Z" }, ] -[[package]] -name = "lockfile" -version = "0.12.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/17/47/72cb04a58a35ec495f96984dddb48232b551aafb95bde614605b754fe6f7/lockfile-0.12.2.tar.gz", hash = "sha256:6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799", size = 20874, upload-time = "2015-11-25T18:29:58.279Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c8/22/9460e311f340cb62d26a38c419b1381b8593b0bb6b5d1f056938b086d362/lockfile-0.12.2-py2.py3-none-any.whl", hash = "sha256:6c3cb24f344923d30b2785d5ad75182c8ea7ac1b6171b08657258ec7429d50fa", size = 13564, upload-time = "2015-11-25T18:29:51.462Z" }, -] - [[package]] name = "markdown-it-py" version = "4.2.0" @@ -597,15 +480,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" }, ] -[[package]] -name = "pycparser" -version = "3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, -] - [[package]] name = "pydantic" version = "2.13.4" @@ -748,18 +622,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl", hash = "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d", size = 10095, upload-time = "2025-09-16T16:37:25.734Z" }, ] -[[package]] -name = "python-daemon" -version = "3.1.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "lockfile" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/3d/37/4f10e37bdabc058a32989da2daf29e57dc59dbc5395497f3d36d5f5e2694/python_daemon-3.1.2.tar.gz", hash = "sha256:f7b04335adc473de877f5117e26d5f1142f4c9f7cd765408f0877757be5afbf4", size = 71576, upload-time = "2024-12-03T08:41:07.843Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/45/3c/b88167e2d6785c0e781ee5d498b07472aeb9b6765da3b19e7cc9e0813841/python_daemon-3.1.2-py3-none-any.whl", hash = "sha256:b906833cef63502994ad48e2eab213259ed9bb18d54fa8774dcba2ff7864cec6", size = 30872, upload-time = "2024-12-03T08:41:03.322Z" }, -] - [[package]] name = "python-dotenv" version = "1.2.2" @@ -798,15 +660,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl", hash = "sha256:a51af13f345f1cdea62347589fbb6df3b290306ab8930713bfae4d475a7d4a59", size = 36753, upload-time = "2025-08-28T19:00:19.56Z" }, ] -[[package]] -name = "resolvelib" -version = "1.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ce/10/f699366ce577423cbc3df3280063099054c23df70856465080798c6ebad6/resolvelib-1.0.1.tar.gz", hash = "sha256:04ce76cbd63fded2078ce224785da6ecd42b9564b1390793f64ddecbe997b309", size = 21065, upload-time = "2023-03-09T05:10:38.292Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/fc/e9ccf0521607bcd244aa0b3fbd574f71b65e9ce6a112c83af988bbbe2e23/resolvelib-1.0.1-py2.py3-none-any.whl", hash = "sha256:d2da45d1a8dfee81bdd591647783e340ef3bcb104b54c383f70d422ef5cc7dbf", size = 17194, upload-time = "2023-03-09T05:10:36.214Z" }, -] - [[package]] name = "rich" version = "15.0.0" diff --git a/docs/developer/ansible.md b/docs/developer/ansible.md deleted file mode 100644 index 28d55c1..0000000 --- a/docs/developer/ansible.md +++ /dev/null @@ -1,36 +0,0 @@ -# Ansible - -## Running a playbook manually - -Set vars on command line: - -``` -ansible-playbook ansible/playbooks/add-new-service.yml \ - -i ansible/hosts.yml \ - --extra-vars="repo_root=${{ github.workspace }} agebd_env=dev service_name_lower=" \ - -v -``` - -### Install an IOC -``` -ansible-playbook ansible/playbooks/ioc-install.yml \ - -i ansible/hosts.yml \ - --extra-vars="agebd_env=dev branch_name=feature/add-service-playground service_name_lower=playground ioc_port=50003" \ - -v -``` - -### Start an IOC -``` -ansible-playbook ansible/playbooks/ioc-start.yml \ - -i ansible/hosts.yml \ - --extra-vars="service_name_lower=playground ioc_port=50003" \ - -v -``` - -### Restart an IOC -``` -ansible-playbook ansible/playbooks/ioc-restart.yml \ - -i ansible/hosts.yml \ - --extra-vars="agebd_env=dev branch_name=feature/add-service-playground service_name_lower=playground" \ - -v -``` diff --git a/docs/developer/cicd_runner.md b/docs/developer/cicd_runner.md index 1efa972..3aa8da0 100644 --- a/docs/developer/cicd_runner.md +++ b/docs/developer/cicd_runner.md @@ -3,9 +3,11 @@ ## Hosts - `sls-vserv-bd-01(-dev)` - - Runs shellbox commands (and `ioc install ...`?) + - Runs the shellbox commands, which the runner triggers over `ssh` + (see `.gitea/scripts/ioc-start.sh`) - `sls-vserv-bd-hla01(-dev)` - - Runs everything else + - Runs the runner itself, and therefore everything else: the deployments + to `/sls/bd/hla//` and the `ioc ...` commands ## Setup diff --git a/docs/developer/ioc/ioc.md b/docs/developer/ioc/ioc.md index 96b1d08..c4eef02 100644 --- a/docs/developer/ioc/ioc.md +++ b/docs/developer/ioc/ioc.md @@ -1,6 +1,8 @@ # IOC -The following instructions explain the basics of starting and managing IOCs on the IOC host. +The following instructions explain the basics of starting and managing IOCs on the IOC host. +They describe the manual steps. In practice the CI/CD runner does this for you, see +[Automation](#automation) below. - TODO: some iocs not associated to a service, where to put? - TODO: need to dev/prod template them too @@ -92,3 +94,20 @@ sudo shellbox start 50045 # start ioc sudo shellbox log 50045 -f # log file (tail) exit # exit ssh ``` + + +## Automation + +Installing, starting and restarting IOCs is done by the gitea runner, not by hand: + +- `.gitea/scripts/ioc-install.sh ` +- `.gitea/scripts/ioc-start.sh ` (shellbox, over `ssh`) +- `.gitea/scripts/ioc-restart.sh ` + +The scripts operate on the deployed IOC files in +`/sls/bd/hla//services//current/ioc`, so a service has to be deployed +before its IOC can be installed. + +They run automatically when a new service is added (`.gitea/workflows/add-new-service.yml`), +and can be triggered manually for any service (or `all` services) through the `Ioc` workflow +(`.gitea/workflows/ioc.yml`) in the gitea Actions tab.