refactor: move ioc logic from ansible to the gitea runner
The ioc install/start/restart logic moves out of the ansible playbooks and the 'agebd ioc ...' cli into scripts run by the gitea runner: - ioc-install.sh / ioc-restart.sh run on the runner itself - ioc-start.sh triggers the shellbox commands over ssh - ioc-for-services.sh runs an action for one or all services They read the deployed ioc files from /sls instead of cloning the repo on the target host, so a service has to be deployed before its ioc can be installed. The deploy script therefore also takes over the environment suffix renaming of the subs/parameters files that ansible used to do, and the workflow steps are ordered deploy -> install. The commented-out ioc placeholders in the add-new-service workflow are filled in, and a manually triggered 'Ioc' workflow replaces the removed cli commands. With this, nothing uses ansible anymore, so the ansible dir, the cli ioc commands and the ansible dependencies are removed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJTevZiSsHepW2xnJGQY49
This commit is contained in:
co-authored by
Claude Opus 5
parent
720e260b3e
commit
430f99baa1
@@ -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 <service-name> <dev|prod>
|
||||
init_service_env() {
|
||||
local SERVICE_NAME=$1
|
||||
AGEBD_ENV=$2
|
||||
|
||||
if [ -z "${SERVICE_NAME}" ] || [ -z "${AGEBD_ENV}" ]; then
|
||||
echo "Usage: $0 <service-name> <dev|prod>" >&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}
|
||||
}
|
||||
@@ -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> <dev|prod>
|
||||
|
||||
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}"
|
||||
|
||||
Executable
+27
@@ -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 <install|start|restart> <service-name|all> <dev|prod>
|
||||
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
|
||||
Executable
+37
@@ -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 <service-name> <dev|prod>
|
||||
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
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
# Restarts the ioc of a service.
|
||||
#
|
||||
# Usage: ./.gitea/scripts/ioc-restart.sh <service-name> <dev|prod>
|
||||
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}"
|
||||
Executable
+23
@@ -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 <service-name> <dev|prod>
|
||||
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 <<REMOTE
|
||||
set -e
|
||||
sudo shellbox status
|
||||
sudo shellbox reload
|
||||
sudo shellbox status
|
||||
sudo shellbox start ${IOC_PORT}
|
||||
REMOTE
|
||||
@@ -9,7 +9,7 @@ env:
|
||||
UV_CACHE_DIR: /var/cache/uv
|
||||
UV_LINK_MODE: hardlink
|
||||
|
||||
# TODO: when to deploy to prod? Manual (i.e. cli command)?
|
||||
# TODO: when to deploy to prod? Manual (i.e. the 'Ioc' workflow)?
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: hla-dev
|
||||
@@ -31,19 +31,31 @@ jobs:
|
||||
SERVICE_NAME="${BRANCH#feature/add-service-}"
|
||||
echo "service_name_lower=$SERVICE_NAME" >> $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"
|
||||
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -1,3 +0,0 @@
|
||||
collections:
|
||||
- name: ansible.posix
|
||||
version: 1.6.0
|
||||
@@ -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:
|
||||
@@ -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:
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 }}"
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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) }}"
|
||||
@@ -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",
|
||||
|
||||
@@ -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))
|
||||
@@ -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"
|
||||
|
||||
-112
@@ -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}"],
|
||||
)
|
||||
@@ -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__":
|
||||
|
||||
Generated
-147
@@ -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"
|
||||
|
||||
@@ -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=<service dir name>" \
|
||||
-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
|
||||
```
|
||||
@@ -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/<env>/` and the `ioc ...` commands
|
||||
|
||||
## Setup
|
||||
|
||||
|
||||
@@ -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 <service-name> <dev|prod>`
|
||||
- `.gitea/scripts/ioc-start.sh <service-name> <dev|prod>` (shellbox, over `ssh`)
|
||||
- `.gitea/scripts/ioc-restart.sh <service-name> <dev|prod>`
|
||||
|
||||
The scripts operate on the deployed IOC files in
|
||||
`/sls/bd/hla/<env>/services/<service-name>/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.
|
||||
|
||||
Reference in New Issue
Block a user