From cfd3ecad6cfe6198830e4d3aa1cbf2fe422975fc Mon Sep 17 00:00:00 2001 From: Benjamin Labrecque Date: Thu, 20 Aug 2026 11:26:49 +0200 Subject: [PATCH 1/4] refactor: centralize deploy-time substitutions (steps 1-2) Deploy-time placeholders were spread across four independent implementations: sed in the Gitea deploy script, ansible.builtin.replace in two playbooks, a hardcoded suffix in bin/sls_hla_launch_gui.sh, and another in agebd/pv.py. Each defined its own values, so nothing kept them in sync and a missed substitution failed silently. Step 1 -- one source of truth: * config/environments.yml declares every deploy-time token, its value per environment, and where tokens are allowed to live. An environment that is missing a token, or defines an undeclared one, is a load-time error. * agebd.subs loads it and renders. Rendering is a strict regex over declared token names rather than a template engine: the rendered files are EPICS db/substitution files and Qt XML, and an unknown token must raise rather than survive into the output. * scripts/ci/check_subs.py enforces the contract in CI: tokens in a rendered path are declared, declared tokens only appear where they are rendered or generated, and no pre-migration delimiters survive. Step 2 -- separate the two substitution stages by delimiter: * Creation-time (copier, once per new service) keeps {{ token }}. Deploy-time (every deploy, per environment) becomes @@token@@. * This drops the {{ '{{ token }}' }} escaping from templates/, which existed only because one Jinja pass had to emit syntax for a second. * Angle brackets were tried first and rejected: << >> is not well-formed XML, and cli parses qt/*.ui with ElementTree. * The existing sed and ansible consumers are repointed at the new delimiters so this stays behaviour-preserving. Routing them through agebd.subs is step 3. Also fixes, as a side effect of having one implementation: * The sed pattern '{{ *agebd_env_suffix_upper* }}' quantified 'r' rather than the space, so it only matched one exact spacing. * agebd.subs.read_ioc_port compares service names case-insensitively; ansible/tasks/utils/get-ioc-port.yml still compares CamelCase registry names against a lowercase input and never matches. qt/*.ui is declared as a render path but nothing renders it yet -- the Qt deploy step is still a plain rsync. Wiring that up is step 4. Co-Authored-By: Claude Opus 5 --- .gitea/scripts/deploy-and-restart-service.sh | 11 +- .gitea/workflows/add-new-service.yml | 6 + ansible/tasks/ioc/ioc-install.yml | 10 +- .../service/service-deploy-and-restart.yml | 2 +- cli/src/models/master_ioc_subs.py | 2 +- .../expected_output/qt/A_BD_ServiceManager.ui | 24 +- .../qt/A_BD_TestService99-X00.ui | 8 +- .../current/ioc/AGEBD-CPCL-MASTER_main.subs | 4 +- .../AGEBD-CPCL-TESTSERVICE99-X00_main.subs | 2 +- ...EBD-CPCL-TESTSERVICE99-X00_parameters.yaml | 4 +- .../AGEBD-SERVICE-TESTSERVICE99-X00.service | 4 +- .../test_repo_root/qt/A_BD_ServiceManager.ui | 24 +- .../current/ioc/AGEBD-CPCL-MASTER_main.subs | 2 +- cli/uv.lock | 2 + config/environments.yml | 79 ++++ packages/agebd/pyproject.toml | 1 + packages/agebd/src/agebd/subs.py | 370 ++++++++++++++++++ packages/agebd/tests/test_subs.py | 217 ++++++++++ packages/agebd/uv.lock | 19 + qt/A_BD_DBPM3Curr.ui | 30 +- qt/A_BD_FeedBackOverview.ui | 2 +- qt/A_BD_InjectionGuard.ui | 22 +- qt/A_BD_InjectionGuard_inc.ui | 12 +- qt/A_BD_Master.ui | 8 +- qt/A_BD_NTurns.ui | 28 +- qt/A_BD_OrbitBump.ui | 2 +- qt/A_BD_OrbitBump_ExpertBackUp.ui | 14 +- qt/A_BD_OrbitBump_Expert_inc.ui | 40 +- qt/A_BD_OrbitBump_Operator_inc.ui | 8 +- qt/A_BD_PostMortemLog.ui | 48 +-- qt/A_BD_Scrubbing.ui | 84 ++-- qt/A_BD_ServiceManager.ui | 24 +- qt/A_BD_ServiceManager_inc.ui | 22 +- qt/A_BD_TauBPM.ui | 18 +- qt/A_BD_TauPCT.ui | 18 +- qt/A_BD_Timing.ui | 106 ++--- qt/A_BD_TopUpTool.ui | 52 +-- qt/A_BD_Tune.ui | 50 +-- qt/A_BD_TuneBump.ui | 176 ++++----- scripts/ci/check_subs.py | 131 +++++++ scripts/tests/test_check_subs.py | 73 ++++ scripts/uv.lock | 2 + services/dbpm3curr/current/app/uv.lock | 19 + .../ioc/AGEBD-CPCL-DBPM3CURR_main.subs | 2 +- .../ioc/AGEBD-CPCL-DBPM3CURR_parameters.yaml | 4 +- .../systemd/AGEBD-SERVICE-DBPM3CURR.service | 4 +- services/injectionguard/current/app/uv.lock | 19 + .../ioc/AGEBD-CPCL-INJECTIONGUARD_main.subs | 48 +-- .../AGEBD-CPCL-INJECTIONGUARD_parameters.yaml | 4 +- .../AGEBD-SERVICE-INJECTIONGUARD.service | 4 +- services/master/current/app/uv.lock | 2 + .../current/ioc/AGEBD-CPCL-MASTER_main.subs | 58 +-- .../ioc/AGEBD-CPCL-MASTER_parameters.yaml | 4 +- .../systemd/AGEBD-SERVICE-MASTER.service | 4 +- services/nturns/current/app/uv.lock | 19 + .../current/ioc/AGEBD-CPCL-NTURNS_main.subs | 2 +- .../ioc/AGEBD-CPCL-NTURNS_parameters.yaml | 4 +- .../systemd/AGEBD-SERVICE-NTURNS.service | 4 +- .../ioc/AGEBD-CPCL-ORBITBUMP_main.subs | 92 ++--- .../ioc/AGEBD-CPCL-ORBITBUMP_parameters.yaml | 4 +- .../current/ioc/AGEBD-CPCL-PARAMS_main.subs | 2 +- .../ioc/AGEBD-CPCL-PARAMS_parameters.yaml | 4 +- services/plots/current/app/uv.lock | 19 + .../current/ioc/AGEBD-CPCL-PLOTS_main.subs | 98 ++--- .../ioc/AGEBD-CPCL-PLOTS_parameters.yaml | 4 +- .../systemd/AGEBD-SERVICE-PLOTS.service | 4 +- services/postmortemlog/current/app/uv.lock | 19 + .../ioc/AGEBD-CPCL-POSTMORTEMLOG_main.subs | 226 +++++------ .../AGEBD-CPCL-POSTMORTEMLOG_parameters.yaml | 4 +- .../AGEBD-SERVICE-POSTMORTEMLOG.service | 4 +- services/scrubbing/current/app/uv.lock | 19 + .../ioc/AGEBD-CPCL-SCRUBBING_main.subs | 2 +- .../ioc/AGEBD-CPCL-SCRUBBING_parameters.yaml | 4 +- .../systemd/AGEBD-SERVICE-SCRUBBING.service | 4 +- services/shifttool/current/app/uv.lock | 19 + .../ioc/AGEBD-CPCL-SHIFTTOOL_main.subs | 2 +- .../ioc/AGEBD-CPCL-SHIFTTOOL_parameters.yaml | 4 +- .../systemd/AGEBD-SERVICE-SHIFTTOOL.service | 4 +- services/taubpm/current/app/uv.lock | 19 + .../current/ioc/AGEBD-CPCL-TAUBPM_main.subs | 2 +- .../ioc/AGEBD-CPCL-TAUBPM_parameters.yaml | 4 +- .../systemd/AGEBD-SERVICE-TAUBPM.service | 4 +- services/taupct/current/app/uv.lock | 19 + .../current/ioc/AGEBD-CPCL-TAUPCT_main.subs | 2 +- .../ioc/AGEBD-CPCL-TAUPCT_parameters.yaml | 4 +- .../systemd/AGEBD-SERVICE-TAUPCT.service | 4 +- services/timing/current/app/uv.lock | 19 + .../current/ioc/AGEBD-CPCL-TIMING_main.subs | 2 +- .../ioc/AGEBD-CPCL-TIMING_parameters.yaml | 4 +- .../systemd/AGEBD-SERVICE-TIMING.service | 4 +- services/topuptool/current/app/uv.lock | 19 + .../ioc/AGEBD-CPCL-TOPUPTOOL_main.subs | 2 +- .../ioc/AGEBD-CPCL-TOPUPTOOL_parameters.yaml | 4 +- .../systemd/AGEBD-SERVICE-TOPUPTOOL.service | 4 +- services/tune/current/app/uv.lock | 19 + .../current/ioc/AGEBD-CPCL-TUNE_main.subs | 2 +- .../ioc/AGEBD-CPCL-TUNE_parameters.yaml | 4 +- .../systemd/AGEBD-SERVICE-TUNE.service | 4 +- services/tunebump/current/app/uv.lock | 19 + .../current/ioc/AGEBD-CPCL-TUNEBUMP_main.subs | 2 +- .../ioc/AGEBD-CPCL-TUNEBUMP_parameters.yaml | 4 +- .../systemd/AGEBD-SERVICE-TUNEBUMP.service | 4 +- services/tunefbx/current/app/uv.lock | 19 + .../current/ioc/AGEBD-CPCL-TUNEFBX_main.subs | 2 +- .../ioc/AGEBD-CPCL-TUNEFBX_parameters.yaml | 4 +- .../systemd/AGEBD-SERVICE-TUNEFBX.service | 4 +- services/tunefby/current/app/uv.lock | 19 + .../current/ioc/AGEBD-CPCL-TUNEFBY_main.subs | 2 +- .../ioc/AGEBD-CPCL-TUNEFBY_parameters.yaml | 4 +- .../systemd/AGEBD-SERVICE-TUNEFBY.service | 4 +- templates/qt/A_BD_{{ui_filename}}.ui.jinja | 8 +- ...PCL-{{service_name_upper}}_main.subs.jinja | 2 +- ...service_name_upper}}_parameters.yaml.jinja | 4 +- ...RVICE-{{service_name_upper}}.service.jinja | 4 +- 114 files changed, 1970 insertions(+), 780 deletions(-) create mode 100644 config/environments.yml create mode 100644 packages/agebd/src/agebd/subs.py create mode 100644 packages/agebd/tests/test_subs.py create mode 100644 scripts/ci/check_subs.py create mode 100644 scripts/tests/test_check_subs.py diff --git a/.gitea/scripts/deploy-and-restart-service.sh b/.gitea/scripts/deploy-and-restart-service.sh index 142b509..ccbbb8f 100755 --- a/.gitea/scripts/deploy-and-restart-service.sh +++ b/.gitea/scripts/deploy-and-restart-service.sh @@ -38,14 +38,17 @@ rsync -avz --delete \ ./services/${SERVICE_NAME_LOWER}/current/* ${SERVICE_DIR}/ ### SUBSTITUTIONS +# Deploy-time tokens are '@@token@@'. Their values are declared in +# config/environments.yml -- keep the two in sync until this is replaced by a +# call to agebd.subs (see the refactor plan, step 3). ### IOC -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}/"* +sed -i "s/@@[[:space:]]*agebd_env_suffix_upper[[:space:]]*@@/${AGEBD_ENV_SUFFIX_UPPER}/g" "${IOC_DIR}/"* +sed -i "s/@@[[:space:]]*agebd_env_suffix_lower[[:space:]]*@@/${AGEBD_ENV_SUFFIX_LOWER}/g" "${IOC_DIR}/"* +sed -i "s/@@[[:space:]]*ioc_port[[:space:]]*@@/${IOC_PORT}/g" "${IOC_DIR}/"* ### SYSTEMD if [ -f "${SYSTEMD_UNIT_FILE_PATH}" ]; then - sed -i "s/{{ *agebd_env* }}/${AGEBD_ENV}/g" "${SYSTEMD_UNIT_FILE_PATH}" + sed -i "s/@@[[:space:]]*agebd_env[[:space:]]*@@/${AGEBD_ENV}/g" "${SYSTEMD_UNIT_FILE_PATH}" fi diff --git a/.gitea/workflows/add-new-service.yml b/.gitea/workflows/add-new-service.yml index 0d465d6..2a2aea7 100644 --- a/.gitea/workflows/add-new-service.yml +++ b/.gitea/workflows/add-new-service.yml @@ -23,6 +23,12 @@ jobs: echo $UV_CACHE_DIR uv run --directory cli pytest + # Includes check_subs: every @@token@@ the new service brought in must be + # declared in config/environments.yml and live in a rendered path. + - name: Run scripts tests + run: | + uv run --directory scripts pytest + - name: Parse Service Directory Name id: parse_branch # Uses bash shell parameter elimination to strip 'feature/add-service-' from the front diff --git a/ansible/tasks/ioc/ioc-install.yml b/ansible/tasks/ioc/ioc-install.yml index 225c2c7..d807ee4 100644 --- a/ansible/tasks/ioc/ioc-install.yml +++ b/ansible/tasks/ioc/ioc-install.yml @@ -32,22 +32,22 @@ 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 +# Replace the @@agebd_env_suffix_upper@@ token 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*\}\}' + 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 +# Replace the @@agebd_env_suffix_lower@@ and @@ioc_port@@ tokens 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 }}" } + - { 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: diff --git a/ansible/tasks/service/service-deploy-and-restart.yml b/ansible/tasks/service/service-deploy-and-restart.yml index 0d38c27..2380c7c 100644 --- a/ansible/tasks/service/service-deploy-and-restart.yml +++ b/ansible/tasks/service/service-deploy-and-restart.yml @@ -27,7 +27,7 @@ - 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*\}\}' + regexp: '@@\s*agebd_env\s*@@' replace: "{{ agebd_env }}" # systemctl --user link --force "./{{ service_unit_name }}" diff --git a/cli/src/models/master_ioc_subs.py b/cli/src/models/master_ioc_subs.py index 80d1c82..6b6d67e 100644 --- a/cli/src/models/master_ioc_subs.py +++ b/cli/src/models/master_ioc_subs.py @@ -24,7 +24,7 @@ class MasterIocSubs(BaseModel): Parses the configuration text and appends a new row before the closing bracket. """ quoted_service = f'"{service_name}"' - new_row = f' {{ "{{{{ agebd_env_suffix_upper }}}}", {quoted_service:<22} , "{starton}", "{autooff}" }}' + new_row = f' {{ "@@agebd_env_suffix_upper@@", {quoted_service:<22} , "{starton}", "{autooff}" }}' # Use regex to find the last closing curly brace of the configuration block # This targets the line that contains only a lone closing brace, optional spaces, and maybe a comma/semicolon. diff --git a/cli/tests/fixtures/expected_output/qt/A_BD_ServiceManager.ui b/cli/tests/fixtures/expected_output/qt/A_BD_ServiceManager.ui index 389a057..4260a44 100644 --- a/cli/tests/fixtures/expected_output/qt/A_BD_ServiceManager.ui +++ b/cli/tests/fixtures/expected_output/qt/A_BD_ServiceManager.ui @@ -71,7 +71,7 @@ caLabel[statusTip="Operation"]{ A - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-GUIRELOAD + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-GUIRELOAD caCalc::TriggerZeroToOne @@ -106,7 +106,7 @@ caLabel[statusTip="Operation"]{ !A - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-ONOFF @@ -586,7 +586,7 @@ caLabel[statusTip="Operation"]{ false - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-ALIVE + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-ALIVE caLed::Alarm @@ -602,7 +602,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-STARTTIME + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-STARTTIME caLineEdit::Default @@ -624,7 +624,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-STATUS + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-STATUS caLineEdit::Default @@ -646,7 +646,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-VERSION + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-VERSION caLineEdit::Default @@ -668,7 +668,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-ONOFF caChoice::Column @@ -717,7 +717,7 @@ caLabel[statusTip="Operation"]{ false - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-ONOFF-RB + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-ONOFF-RB caLed::Alarm @@ -763,7 +763,7 @@ caLabel[statusTip="Operation"]{ false - AGEBD-CPCL-MASTER{{ agebd_env_suffix_upper }}:STATUS + AGEBD-CPCL-MASTER@@agebd_env_suffix_upper@@:STATUS caLed::Alarm @@ -1040,7 +1040,7 @@ caLabel[statusTip="Operation"]{ EPushButton::None - AGEBD-MASTER{{ agebd_env_suffix_upper }}:MASTER-LOGS-REQ + AGEBD-MASTER@@agebd_env_suffix_upper@@:MASTER-LOGS-REQ Logs @@ -1106,7 +1106,7 @@ caLabel[statusTip="Operation"]{ false - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-GUIRELOAD + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-GUIRELOAD Reload @@ -1172,7 +1172,7 @@ caLabel[statusTip="Operation"]{ EPushButton::None - AGEBD-CPCL-MASTER{{ agebd_env_suffix_upper }}:RESTART + AGEBD-CPCL-MASTER@@agebd_env_suffix_upper@@:RESTART ↺ diff --git a/cli/tests/fixtures/expected_output/qt/A_BD_TestService99-X00.ui b/cli/tests/fixtures/expected_output/qt/A_BD_TestService99-X00.ui index 3e964b9..b0cf93b 100644 --- a/cli/tests/fixtures/expected_output/qt/A_BD_TestService99-X00.ui +++ b/cli/tests/fixtures/expected_output/qt/A_BD_TestService99-X00.ui @@ -30,7 +30,7 @@ 0 - AGEBD-TESTSERVICE99-X00{{ agebd_env_suffix_upper }}:AO + AGEBD-TESTSERVICE99-X00@@agebd_env_suffix_upper@@:AO 9.000000000000000 @@ -49,10 +49,10 @@ - Toggle AGEBD-ALH{{ agebd_env_suffix_upper }}:TESTSERVICE99-X00-ONOFF + Toggle AGEBD-ALH@@agebd_env_suffix_upper@@:TESTSERVICE99-X00-ONOFF - AGEBD-ALH{{ agebd_env_suffix_upper }}:TESTSERVICE99-X00-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:TESTSERVICE99-X00-ONOFF @@ -70,7 +70,7 @@ - Value of AGEBD-TESTSERVICE99-X00{{ agebd_env_suffix_upper }}:AO + Value of AGEBD-TESTSERVICE99-X00@@agebd_env_suffix_upper@@:AO diff --git a/cli/tests/fixtures/expected_output/services/master/current/ioc/AGEBD-CPCL-MASTER_main.subs b/cli/tests/fixtures/expected_output/services/master/current/ioc/AGEBD-CPCL-MASTER_main.subs index cebcb97..a1754e8 100644 --- a/cli/tests/fixtures/expected_output/services/master/current/ioc/AGEBD-CPCL-MASTER_main.subs +++ b/cli/tests/fixtures/expected_output/services/master/current/ioc/AGEBD-CPCL-MASTER_main.subs @@ -1,5 +1,5 @@ file MASTER.template { pattern { SUFFIX SERVICE STARTON AUTOOFF } - { "{{ agebd_env_suffix_upper }}", "MASTER" , "0", "30" } - { "{{ agebd_env_suffix_upper }}", "TESTSERVICE99-X00" , "0", "0" } + { "@@agebd_env_suffix_upper@@", "MASTER" , "0", "30" } + { "@@agebd_env_suffix_upper@@", "TESTSERVICE99-X00" , "0", "0" } } diff --git a/cli/tests/fixtures/expected_output/services/testservice99-x00/current/ioc/AGEBD-CPCL-TESTSERVICE99-X00_main.subs b/cli/tests/fixtures/expected_output/services/testservice99-x00/current/ioc/AGEBD-CPCL-TESTSERVICE99-X00_main.subs index ba42592..70d11d8 100644 --- a/cli/tests/fixtures/expected_output/services/testservice99-x00/current/ioc/AGEBD-CPCL-TESTSERVICE99-X00_main.subs +++ b/cli/tests/fixtures/expected_output/services/testservice99-x00/current/ioc/AGEBD-CPCL-TESTSERVICE99-X00_main.subs @@ -1,4 +1,4 @@ file TESTSERVICE99-X00.template { pattern { DEVICE } - { AGEBD-TESTSERVICE99-X00{{ agebd_env_suffix_upper }} } + { AGEBD-TESTSERVICE99-X00@@agebd_env_suffix_upper@@ } } diff --git a/cli/tests/fixtures/expected_output/services/testservice99-x00/current/ioc/AGEBD-CPCL-TESTSERVICE99-X00_parameters.yaml b/cli/tests/fixtures/expected_output/services/testservice99-x00/current/ioc/AGEBD-CPCL-TESTSERVICE99-X00_parameters.yaml index c179f0d..24aa364 100644 --- a/cli/tests/fixtures/expected_output/services/testservice99-x00/current/ioc/AGEBD-CPCL-TESTSERVICE99-X00_parameters.yaml +++ b/cli/tests/fixtures/expected_output/services/testservice99-x00/current/ioc/AGEBD-CPCL-TESTSERVICE99-X00_parameters.yaml @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ agebd_env_suffix_lower }} -ioc_port: {{ ioc_port }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/cli/tests/fixtures/expected_output/services/testservice99-x00/current/systemd/AGEBD-SERVICE-TESTSERVICE99-X00.service b/cli/tests/fixtures/expected_output/services/testservice99-x00/current/systemd/AGEBD-SERVICE-TESTSERVICE99-X00.service index 496c48b..436985e 100644 --- a/cli/tests/fixtures/expected_output/services/testservice99-x00/current/systemd/AGEBD-SERVICE-TESTSERVICE99-X00.service +++ b/cli/tests/fixtures/expected_output/services/testservice99-x00/current/systemd/AGEBD-SERVICE-TESTSERVICE99-X00.service @@ -3,9 +3,9 @@ Description=AGEBD-SERVICE-TESTSERVICE99-X00 After=network.target [Service] -Environment=AGEBD_ENV={{ agebd_env }} +Environment=AGEBD_ENV=@@agebd_env@@ Environment=PYTHONUNBUFFERED=1 -ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh TESTSERVICE99-X00 +ExecStart=/sls/bd/hla/@@agebd_env@@/bin/start_service.sh TESTSERVICE99-X00 Restart=no [Install] diff --git a/cli/tests/fixtures/test_repo_root/qt/A_BD_ServiceManager.ui b/cli/tests/fixtures/test_repo_root/qt/A_BD_ServiceManager.ui index c1b6561..d2c3936 100644 --- a/cli/tests/fixtures/test_repo_root/qt/A_BD_ServiceManager.ui +++ b/cli/tests/fixtures/test_repo_root/qt/A_BD_ServiceManager.ui @@ -71,7 +71,7 @@ caLabel[statusTip="Operation"]{ A - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-GUIRELOAD + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-GUIRELOAD caCalc::TriggerZeroToOne @@ -106,7 +106,7 @@ caLabel[statusTip="Operation"]{ !A - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-ONOFF @@ -586,7 +586,7 @@ caLabel[statusTip="Operation"]{ false - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-ALIVE + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-ALIVE caLed::Alarm @@ -602,7 +602,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-STARTTIME + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-STARTTIME caLineEdit::Default @@ -624,7 +624,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-STATUS + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-STATUS caLineEdit::Default @@ -646,7 +646,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-VERSION + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-VERSION caLineEdit::Default @@ -668,7 +668,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-ONOFF caChoice::Column @@ -717,7 +717,7 @@ caLabel[statusTip="Operation"]{ false - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-ONOFF-RB + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-ONOFF-RB caLed::Alarm @@ -763,7 +763,7 @@ caLabel[statusTip="Operation"]{ false - AGEBD-CPCL-MASTER{{ agebd_env_suffix_upper }}:STATUS + AGEBD-CPCL-MASTER@@agebd_env_suffix_upper@@:STATUS caLed::Alarm @@ -1040,7 +1040,7 @@ caLabel[statusTip="Operation"]{ EPushButton::None - AGEBD-MASTER{{ agebd_env_suffix_upper }}:MASTER-LOGS-REQ + AGEBD-MASTER@@agebd_env_suffix_upper@@:MASTER-LOGS-REQ Logs @@ -1106,7 +1106,7 @@ caLabel[statusTip="Operation"]{ false - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-GUIRELOAD + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-GUIRELOAD Reload @@ -1172,7 +1172,7 @@ caLabel[statusTip="Operation"]{ EPushButton::None - AGEBD-CPCL-MASTER{{ agebd_env_suffix_upper }}:RESTART + AGEBD-CPCL-MASTER@@agebd_env_suffix_upper@@:RESTART ↺ diff --git a/cli/tests/fixtures/test_repo_root/services/master/current/ioc/AGEBD-CPCL-MASTER_main.subs b/cli/tests/fixtures/test_repo_root/services/master/current/ioc/AGEBD-CPCL-MASTER_main.subs index 6ccd171..6e28017 100644 --- a/cli/tests/fixtures/test_repo_root/services/master/current/ioc/AGEBD-CPCL-MASTER_main.subs +++ b/cli/tests/fixtures/test_repo_root/services/master/current/ioc/AGEBD-CPCL-MASTER_main.subs @@ -1,4 +1,4 @@ file MASTER.template { pattern { SUFFIX SERVICE STARTON AUTOOFF } - { "{{ agebd_env_suffix_upper }}", "MASTER" , "0", "30" } + { "@@agebd_env_suffix_upper@@", "MASTER" , "0", "30" } } diff --git a/cli/uv.lock b/cli/uv.lock index d56b4cc..29a62ec 100644 --- a/cli/uv.lock +++ b/cli/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "gitpython" }, { name = "h5py" }, { name = "pyepics" }, + { name = "pyyaml" }, { name = "typer" }, ] @@ -18,6 +19,7 @@ requires-dist = [ { name = "gitpython", specifier = ">=3.1.50" }, { name = "h5py", specifier = ">=3.16.0" }, { name = "pyepics", specifier = ">=3.5.10" }, + { name = "pyyaml", specifier = ">=6.0.3" }, { name = "typer", specifier = ">=0.23.2" }, ] diff --git a/config/environments.yml b/config/environments.yml new file mode 100644 index 0000000..bf3707a --- /dev/null +++ b/config/environments.yml @@ -0,0 +1,79 @@ +# Single source of truth for every deploy-time substitution in this repo. +# +# There are two substitution stages, and they use different delimiters on +# purpose: +# +# {{ token }} creation-time. Resolved once by copier when a new service is +# created (cli/src/core/service_creator.py). Never survives +# into a committed file. +# +# @@token@@ deploy-time. Resolved on every deploy, per environment, by +# agebd.subs. Lives in committed files. +# +# This file declares the deploy-time stage only. scripts/ci/check_subs.py +# enforces that every @@token@@ in the repo is declared here, and that it +# only appears in a path that actually gets rendered. +# +# 'local' is deliberately absent: it is a runtime mode for tests without EPICS +# access (see agebd.enums.AGEBD_ENV), not a deploy target. + +environments: + prod: + agebd_env: prod + agebd_env_suffix_upper: "" + agebd_env_suffix_lower: "" + dev: + agebd_env: dev + agebd_env_suffix_upper: "-DEV" + agebd_env_suffix_lower: "-dev" + +# Every deploy-time token. Each environment above must define exactly the +# tokens with source 'environment' -- adding one here without adding it to +# every environment is a load-time error. +tokens: + agebd_env: + source: environment + description: >- + Deployment environment name. Used in deploy paths and systemd units, + e.g. /sls/bd/hla/dev/bin/start_service.sh. + agebd_env_suffix_upper: + source: environment + description: >- + Uppercase suffix appended to EPICS device names, e.g. AGEBD-TUNE-DEV. + Used in IOC substitution files and Qt UI files. + agebd_env_suffix_lower: + source: environment + description: >- + Lowercase suffix appended to host names, e.g. sls-vserv-bd-01-dev. + Used in IOC parameter files. + ioc_port: + source: registry + description: >- + IOC port for the service being deployed, read from + config/services_registry.yml. + +# Where deploy-time tokens are allowed to live, as repo-root-relative globs. +locations: + # Rendered at deploy time by agebd.subs. A token here is resolved. + render: + - services/*/current/ioc + - services/*/current/systemd + - qt + # Carry deploy-time tokens verbatim, because the copy they produce lands in + # a render path. A token here is NOT resolved in place. + passthrough: + - templates + - cli/tests/fixtures + # The substitution machinery itself: code that renders, generates or + # documents tokens. Naming a token here is expected; nothing is resolved. + # These paths use {{ }} as their own template language (Ansible, copier), so + # the leftover-delimiter check does not apply to them. + references: + - ansible/tasks/* + - .gitea/scripts + - cli/src/models + - packages/agebd/src/agebd + - packages/agebd/tests + - scripts/ci + - scripts/tests + - config diff --git a/packages/agebd/pyproject.toml b/packages/agebd/pyproject.toml index 20a1b46..384fcf3 100644 --- a/packages/agebd/pyproject.toml +++ b/packages/agebd/pyproject.toml @@ -9,6 +9,7 @@ dependencies = [ "pyepics>=3.5.10", "typer>=0.23.2", "gitpython>=3.1.50", + "pyyaml>=6.0.3", ] # Dev dependencies diff --git a/packages/agebd/src/agebd/subs.py b/packages/agebd/src/agebd/subs.py new file mode 100644 index 0000000..dd4b1e1 --- /dev/null +++ b/packages/agebd/src/agebd/subs.py @@ -0,0 +1,370 @@ +""" +Single source of truth for deploy-time substitutions. + +Committed files carry deploy-time placeholders written as ``@@token@@``. +This module is the only place that knows what those tokens resolve to. + +There are two substitution stages in this repo, and they use different +delimiters on purpose: + + ``{{ token }}`` creation-time. Resolved once by copier when a new + service is created (cli/src/core/service_creator.py). + Never survives into a committed file. + + ``@@token@@`` deploy-time. Resolved on every deploy, per environment, + by this module. Lives in committed files. + +Token values come from two sources, both declared in config/environments.yml: + + environment the per-environment table in config/environments.yml + registry config/services_registry.yml, per service + +Rendering is a strict regex substitution rather than a template engine. The +rendered files are EPICS database/substitution files and Qt XML, which are +full of braces and other characters a template engine would try to interpret; +and a regex over declared token names gives an exact "unknown token in this +file" error instead of silently leaving the placeholder in place -- which is +the failure mode of the sed calls this module replaces. +""" + +import os +import re +from dataclasses import dataclass, field +from fnmatch import fnmatch +from pathlib import Path +from typing import Iterable, Iterator, Optional, Union + +import yaml + +from agebd.utils import get_git_root + +CONFIG_DIR_ENV_VAR = "AGEBD_CONFIG_DIR" +ENVIRONMENTS_FILENAME = "environments.yml" +SERVICES_REGISTRY_FILENAME = "services_registry.yml" + +ENVIRONMENT_SOURCE = "environment" +REGISTRY_SOURCE = "registry" + +#: Deploy-time placeholder, e.g. ``@@agebd_env@@`` or ``@@agebd_env@@``. +TOKEN_PATTERN = re.compile(r"@@\s*([a-z][a-z0-9_]*)\s*@@") + +#: The pre-migration deploy-time delimiters. Kept here so that the CI lint can +#: spot files that were missed by the switch to ``@@token@@``. +LEGACY_TOKEN_PATTERN = re.compile(r"\{\{\s*([a-z][a-z0-9_]*)\s*\}\}") + + +class SubstitutionError(Exception): + """Base class for every error raised by this module.""" + + +class UnknownTokenError(SubstitutionError): + """A ``@@token@@`` was found that is not declared in environments.yml.""" + + +def resolve_config_dir(config_dir: Optional[Union[str, Path]] = None) -> Path: + """ + Locate the directory holding environments.yml. + + Explicit argument wins, then $AGEBD_CONFIG_DIR, then the config directory + of the surrounding git checkout. The env var is what deployed hosts use: + the deployed tree is not a git checkout. + """ + if config_dir is not None: + return Path(config_dir) + + from_env = os.environ.get(CONFIG_DIR_ENV_VAR) + if from_env: + return Path(from_env) + + try: + return get_git_root(__file__) / "config" + except Exception as e: + raise SubstitutionError( + "Could not locate the config directory: agebd is not installed inside a git " + f"checkout. Set ${CONFIG_DIR_ENV_VAR} to the directory holding " + f"{ENVIRONMENTS_FILENAME}." + ) from e + + +@dataclass(frozen=True) +class TokenSpec: + name: str + source: str + description: str = "" + + +@dataclass +class SubstitutionsConfig: + """The parsed contents of config/environments.yml.""" + + config_dir: Path + environments: dict + tokens: dict + render_paths: tuple = () + passthrough_paths: tuple = () + reference_paths: tuple = () + + @property + def environments_file(self) -> Path: + return self.config_dir / ENVIRONMENTS_FILENAME + + @property + def services_registry_file(self) -> Path: + return self.config_dir / SERVICES_REGISTRY_FILENAME + + @classmethod + def load(cls, config_dir: Optional[Union[str, Path]] = None) -> "SubstitutionsConfig": + resolved_dir = resolve_config_dir(config_dir) + path = resolved_dir / ENVIRONMENTS_FILENAME + if not path.is_file(): + raise SubstitutionError(f"No {ENVIRONMENTS_FILENAME} found at: {path}") + + with open(path) as f: + raw = yaml.safe_load(f) or {} + + tokens = { + name: TokenSpec( + name=name, + source=spec["source"], + description=spec.get("description", ""), + ) + for name, spec in (raw.get("tokens") or {}).items() + } + locations = raw.get("locations") or {} + + config = cls( + config_dir=resolved_dir, + environments=raw.get("environments") or {}, + tokens=tokens, + render_paths=tuple(locations.get("render") or ()), + passthrough_paths=tuple(locations.get("passthrough") or ()), + reference_paths=tuple(locations.get("references") or ()), + ) + config.assert_valid() + return config + + def assert_valid(self) -> None: + """ + Every environment must define exactly the tokens sourced from the + environment table -- no more, no less. This is what stops a new token + from being added for dev but forgotten for prod. + """ + if not self.environments: + raise SubstitutionError(f"No environments declared in {self.environments_file}") + + for name, spec in self.tokens.items(): + if spec.source not in (ENVIRONMENT_SOURCE, REGISTRY_SOURCE): + raise SubstitutionError( + f"Token '{name}' in {self.environments_file} has unknown source " + f"'{spec.source}'. Expected '{ENVIRONMENT_SOURCE}' or '{REGISTRY_SOURCE}'." + ) + + expected = self.environment_token_names() + for env_name, values in self.environments.items(): + declared = set(values) + missing = expected - declared + unexpected = declared - expected + if missing: + raise SubstitutionError( + f"Environment '{env_name}' in {self.environments_file} is missing " + f"token(s): {', '.join(sorted(missing))}" + ) + if unexpected: + raise SubstitutionError( + f"Environment '{env_name}' in {self.environments_file} defines " + f"token(s) that are not declared under 'tokens': " + f"{', '.join(sorted(unexpected))}" + ) + + def environment_token_names(self) -> set: + return {n for n, spec in self.tokens.items() if spec.source == ENVIRONMENT_SOURCE} + + def registry_token_names(self) -> set: + return {n for n, spec in self.tokens.items() if spec.source == REGISTRY_SOURCE} + + def assert_environment_exists(self, env: str) -> dict: + try: + return self.environments[env] + except KeyError: + known = ", ".join(sorted(self.environments)) + raise SubstitutionError( + f"Unknown environment '{env}'. Declared in {self.environments_file}: {known}" + ) from None + + def expand_render_paths(self, repo_root: Union[str, Path]) -> list: + """ + Resolve the 'render' globs against a checkout, keeping only what exists. + """ + root = Path(repo_root) + found = [] + for pattern in self.render_paths: + found.extend(sorted(p for p in root.glob(pattern) if p.is_dir())) + return found + + def is_render_path(self, rel_path: Union[str, Path]) -> bool: + return _is_under_any(Path(rel_path), self.render_paths) + + def is_passthrough_path(self, rel_path: Union[str, Path]) -> bool: + return _is_under_any(Path(rel_path), self.passthrough_paths) + + def is_reference_path(self, rel_path: Union[str, Path]) -> bool: + """ + True for the substitution machinery itself -- code that renders, + generates or documents tokens rather than carrying them. + """ + return _is_under_any(Path(rel_path), self.reference_paths) + + +@dataclass +class Substitutions: + """ + Resolved deploy-time token values for one environment, and optionally for + one service. + """ + + values: dict = field(default_factory=dict) + config: Optional[SubstitutionsConfig] = None + + @classmethod + def for_env(cls, env: str, config_dir: Optional[Union[str, Path]] = None) -> "Substitutions": + """ + Tokens that depend only on the environment. Rendering a file that also + needs a registry token (``ioc_port``) with this will raise -- use + :meth:`for_service`. + """ + config = SubstitutionsConfig.load(config_dir) + return cls(values=dict(config.assert_environment_exists(str(env))), config=config) + + @classmethod + def for_service( + cls, env: str, service_name: str, config_dir: Optional[Union[str, Path]] = None + ) -> "Substitutions": + """ + Every deploy-time token, for one service in one environment. + """ + subs = cls.for_env(env, config_dir=config_dir) + assert subs.config is not None + if "ioc_port" in subs.config.registry_token_names(): + subs.values["ioc_port"] = str( + read_ioc_port(subs.config.services_registry_file, service_name) + ) + return subs + + def __getitem__(self, token: str) -> str: + try: + return self.values[token] + except KeyError: + raise UnknownTokenError(self._unknown_token_message(token)) from None + + def __contains__(self, token: str) -> bool: + return token in self.values + + def render_text(self, text: str, origin: Optional[Union[str, Path]] = None) -> str: + """ + Replace every ``@@token@@`` in ``text``. Raises on an undeclared or + misspelled token rather than leaving it in the output. + """ + + def replace(match: "re.Match") -> str: + token = match.group(1) + if token not in self.values: + raise UnknownTokenError(self._unknown_token_message(token, origin=origin)) + return self.values[token] + + return TOKEN_PATTERN.sub(replace, text) + + def render_file(self, path: Union[str, Path]) -> bool: + """ + Render one file in place. Returns True if the file changed. + """ + path = Path(path) + original = path.read_text() + rendered = self.render_text(original, origin=path) + if rendered == original: + return False + path.write_text(rendered) + return True + + def render_tree(self, root: Union[str, Path]) -> list: + """ + Render every text file under ``root`` in place. Returns the files that + changed. + """ + return [path for path in iter_text_files(root) if self.render_file(path)] + + def _unknown_token_message(self, token: str, origin: Optional[Union[str, Path]] = None) -> str: + where = f" in {origin}" if origin else "" + known = ", ".join(sorted(self.values)) or "(none)" + declared_in = self.config.environments_file if self.config else ENVIRONMENTS_FILENAME + return ( + f"Unknown deploy-time token '@@{token}@@'{where}. " + f"Declare it in {declared_in}, or fix the spelling. " + f"Available here: {known}." + ) + + +def read_ioc_port(registry_file: Union[str, Path], service_name: str) -> int: + """ + Look up a service's IOC port in the services registry. + + Registry names are CamelCase; callers pass whatever casing they have, so + the comparison is case-insensitive. + """ + with open(registry_file) as f: + registry = yaml.safe_load(f) or {} + + wanted = service_name.lower() + for entry in registry.get("services") or []: + if str(entry.get("name", "")).lower() == wanted: + return entry["ioc_port"] + + raise SubstitutionError(f"Service '{service_name}' not found in {registry_file}") + + +def find_tokens(text: str) -> set: + """Every deploy-time token name appearing in ``text``.""" + return set(TOKEN_PATTERN.findall(text)) + + +def find_legacy_tokens(text: str) -> set: + """Every pre-migration ``{{ token }}`` name appearing in ``text``.""" + return set(LEGACY_TOKEN_PATTERN.findall(text)) + + +SKIPPED_DIRS = frozenset( + {".git", ".venv", ".pixi", ".cache", ".pytest_cache", ".ruff_cache", "__pycache__"} +) + + +def iter_text_files(root: Union[str, Path]) -> Iterator[Path]: + """ + Yield readable text files under ``root``, skipping build/cache directories + and anything that is not valid UTF-8. + """ + for path in sorted(Path(root).rglob("*")): + if not path.is_file(): + continue + if SKIPPED_DIRS.intersection(path.parts): + continue + try: + path.read_text() + except (UnicodeDecodeError, OSError): + continue + yield path + + +def _is_under_any(rel_path: Path, patterns: Iterable) -> bool: + """ + True if ``rel_path`` itself, or any of its parent directories, matches one + of the repo-root-relative directory globs in ``patterns``. + """ + candidates = [rel_path] + [p for p in rel_path.parents if str(p) != "."] + for pattern in patterns: + pattern_parts = Path(pattern).parts + for candidate in candidates: + parts = candidate.parts + if len(parts) == len(pattern_parts) and all( + fnmatch(part, pat) for part, pat in zip(parts, pattern_parts) + ): + return True + return False diff --git a/packages/agebd/tests/test_subs.py b/packages/agebd/tests/test_subs.py new file mode 100644 index 0000000..f909544 --- /dev/null +++ b/packages/agebd/tests/test_subs.py @@ -0,0 +1,217 @@ +import pytest +import yaml + +from agebd.subs import ( + SubstitutionError, + Substitutions, + SubstitutionsConfig, + UnknownTokenError, + find_legacy_tokens, + find_tokens, + read_ioc_port, +) + +ENVIRONMENTS = { + "environments": { + "prod": { + "agebd_env": "prod", + "agebd_env_suffix_upper": "", + "agebd_env_suffix_lower": "", + }, + "dev": { + "agebd_env": "dev", + "agebd_env_suffix_upper": "-DEV", + "agebd_env_suffix_lower": "-dev", + }, + }, + "tokens": { + "agebd_env": {"source": "environment", "description": "env name"}, + "agebd_env_suffix_upper": {"source": "environment", "description": "upper suffix"}, + "agebd_env_suffix_lower": {"source": "environment", "description": "lower suffix"}, + "ioc_port": {"source": "registry", "description": "ioc port"}, + }, + "locations": { + "render": ["services/*/current/ioc", "qt"], + "passthrough": ["templates"], + }, +} + +REGISTRY = { + "next_available_ioc_port": 50002, + "services": [ + {"name": "Master", "ioc_port": 50000, "status": "active"}, + {"name": "TauBPM", "ioc_port": 50001, "status": "active"}, + ], +} + + +@pytest.fixture +def config_dir(tmp_path): + (tmp_path / "environments.yml").write_text(yaml.safe_dump(ENVIRONMENTS)) + (tmp_path / "services_registry.yml").write_text(yaml.safe_dump(REGISTRY)) + return tmp_path + + +def write_environments(config_dir, environments): + (config_dir / "environments.yml").write_text(yaml.safe_dump(environments)) + + +def test_for_env_resolves_environment_tokens(config_dir): + subs = Substitutions.for_env("dev", config_dir=config_dir) + + assert subs["agebd_env"] == "dev" + assert subs["agebd_env_suffix_upper"] == "-DEV" + assert subs["agebd_env_suffix_lower"] == "-dev" + + +def test_prod_suffixes_are_empty(config_dir): + subs = Substitutions.for_env("prod", config_dir=config_dir) + + assert subs.render_text("AGEBD-TUNE@@agebd_env_suffix_upper@@:AO") == "AGEBD-TUNE:AO" + + +def test_for_service_adds_ioc_port(config_dir): + subs = Substitutions.for_service("dev", "taubpm", config_dir=config_dir) + + assert subs["ioc_port"] == "50001" + + +def test_render_text_substitutes_every_occurrence(config_dir): + subs = Substitutions.for_env("dev", config_dir=config_dir) + + text = "AGEBD-ALH@@agebd_env_suffix_upper@@:X\nsls-vserv-bd-01@@agebd_env_suffix_lower@@\n" + + assert subs.render_text(text) == "AGEBD-ALH-DEV:X\nsls-vserv-bd-01-dev\n" + + +def test_render_text_raises_on_misspelled_token(config_dir): + subs = Substitutions.for_env("dev", config_dir=config_dir) + + with pytest.raises(UnknownTokenError, match="agebd_env_sufix_upper"): + subs.render_text("AGEBD-TUNE@@agebd_env_sufix_upper@@:AO", origin="TUNE.subs") + + +def test_render_text_raises_when_registry_token_is_not_loaded(config_dir): + """for_env() has no ioc_port, so a parameters file must fail loudly.""" + subs = Substitutions.for_env("dev", config_dir=config_dir) + + with pytest.raises(UnknownTokenError, match="ioc_port"): + subs.render_text("ioc_port: @@ioc_port@@") + + +def test_render_file_reports_whether_it_changed(config_dir, tmp_path): + subs = Substitutions.for_env("dev", config_dir=config_dir) + path = tmp_path / "AGEBD-CPCL-TUNE_main.subs" + path.write_text("{ AGEBD-TUNE@@agebd_env_suffix_upper@@ }\n") + + assert subs.render_file(path) is True + assert path.read_text() == "{ AGEBD-TUNE-DEV }\n" + assert subs.render_file(path) is False + + +def test_render_tree_skips_cache_directories(config_dir, tmp_path): + subs = Substitutions.for_env("dev", config_dir=config_dir) + (tmp_path / "ioc").mkdir() + (tmp_path / "ioc" / "a.subs").write_text("AGEBD-A@@agebd_env_suffix_upper@@") + (tmp_path / "__pycache__").mkdir() + (tmp_path / "__pycache__" / "b.subs").write_text("AGEBD-B@@agebd_env_suffix_upper@@") + + changed = subs.render_tree(tmp_path) + + assert [p.name for p in changed] == ["a.subs"] + assert (tmp_path / "__pycache__" / "b.subs").read_text().endswith("@@agebd_env_suffix_upper@@") + + +def test_replacement_value_is_literal(config_dir): + """A value containing regex backreference syntax must not be interpreted.""" + environments = yaml.safe_load(yaml.safe_dump(ENVIRONMENTS)) + environments["environments"]["dev"]["agebd_env_suffix_upper"] = r"-\1DEV" + write_environments(config_dir, environments) + + subs = Substitutions.for_env("dev", config_dir=config_dir) + + assert subs.render_text("AGEBD-A@@agebd_env_suffix_upper@@") == r"AGEBD-A-\1DEV" + + +def test_unknown_environment_lists_the_known_ones(config_dir): + with pytest.raises(SubstitutionError, match="dev, prod"): + Substitutions.for_env("staging", config_dir=config_dir) + + +def test_token_missing_from_one_environment_is_a_load_error(config_dir): + environments = yaml.safe_load(yaml.safe_dump(ENVIRONMENTS)) + del environments["environments"]["prod"]["agebd_env_suffix_lower"] + write_environments(config_dir, environments) + + with pytest.raises(SubstitutionError, match="missing token"): + SubstitutionsConfig.load(config_dir) + + +def test_undeclared_token_in_an_environment_is_a_load_error(config_dir): + environments = yaml.safe_load(yaml.safe_dump(ENVIRONMENTS)) + environments["environments"]["dev"]["agebd_env_suffix_mixed"] = "-Dev" + write_environments(config_dir, environments) + + with pytest.raises(SubstitutionError, match="not declared"): + SubstitutionsConfig.load(config_dir) + + +def test_unknown_token_source_is_a_load_error(config_dir): + environments = yaml.safe_load(yaml.safe_dump(ENVIRONMENTS)) + environments["tokens"]["ioc_port"]["source"] = "somewhere" + write_environments(config_dir, environments) + + with pytest.raises(SubstitutionError, match="unknown source"): + SubstitutionsConfig.load(config_dir) + + +def test_read_ioc_port_is_case_insensitive(config_dir): + registry_file = config_dir / "services_registry.yml" + + assert read_ioc_port(registry_file, "taubpm") == 50001 + assert read_ioc_port(registry_file, "TauBPM") == 50001 + assert read_ioc_port(registry_file, "TAUBPM") == 50001 + + +def test_read_ioc_port_raises_for_unknown_service(config_dir): + with pytest.raises(SubstitutionError, match="Nope"): + read_ioc_port(config_dir / "services_registry.yml", "Nope") + + +def test_path_classification(config_dir): + config = SubstitutionsConfig.load(config_dir) + + assert config.is_render_path("services/tune/current/ioc/TUNE.template") + assert config.is_render_path("qt/A_BD_Tune.ui") + assert config.is_passthrough_path("templates/service/x/current/ioc/a.jinja") + assert not config.is_render_path("services/tune/current/app/src/main.py") + assert not config.is_passthrough_path("services/tune/current/app/src/main.py") + + +def test_expand_render_paths(config_dir, tmp_path): + config = SubstitutionsConfig.load(config_dir) + repo = tmp_path / "repo" + (repo / "services" / "tune" / "current" / "ioc").mkdir(parents=True) + (repo / "services" / "tune" / "current" / "app").mkdir(parents=True) + (repo / "qt").mkdir() + + expanded = {p.relative_to(repo).as_posix() for p in config.expand_render_paths(repo)} + + assert expanded == {"services/tune/current/ioc", "qt"} + + +def test_find_tokens_ignores_non_token_angle_brackets(): + assert find_tokens("@@b@@ and @@agebd_env@@") == {"b", "agebd_env"} + assert find_tokens("user@@example.com") == set() + assert find_tokens("@@ NotAToken @@") == set() + + +def test_find_legacy_tokens_returns_both_stages(): + """ + It cannot tell the two stages apart on syntax alone -- callers intersect + the result with the declared deploy-time tokens. + """ + assert find_legacy_tokens("{{ agebd_env_suffix_upper }} {{service_name_upper}}") == { + "agebd_env_suffix_upper", + "service_name_upper", + } diff --git a/packages/agebd/uv.lock b/packages/agebd/uv.lock index 1f758ce..11ec0f8 100644 --- a/packages/agebd/uv.lock +++ b/packages/agebd/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "gitpython" }, { name = "h5py" }, { name = "pyepics" }, + { name = "pyyaml" }, { name = "typer" }, ] @@ -28,6 +29,7 @@ requires-dist = [ { name = "gitpython", specifier = ">=3.1.50" }, { name = "h5py", specifier = ">=3.16.0" }, { name = "pyepics", specifier = ">=3.5.10" }, + { name = "pyyaml", specifier = ">=6.0.3" }, { name = "typer", specifier = ">=0.23.2" }, ] @@ -532,6 +534,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756, upload-time = "2024-08-14T10:15:33.187Z" }, ] +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, +] + [[package]] name = "readme-renderer" version = "45.0" diff --git a/qt/A_BD_DBPM3Curr.ui b/qt/A_BD_DBPM3Curr.ui index 288be53..5cc52db 100644 --- a/qt/A_BD_DBPM3Curr.ui +++ b/qt/A_BD_DBPM3Curr.ui @@ -43,7 +43,7 @@ A - AGEBD-ALH{{ agebd_env_suffix_upper }}:DBPM3CURR-GUIRELOAD + AGEBD-ALH@@agebd_env_suffix_upper@@:DBPM3CURR-GUIRELOAD caCalc::TriggerZeroToOne @@ -185,7 +185,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-DBPM3CURR{{ agebd_env_suffix_upper }}:CHARGE-AVG + AGEBD-DBPM3CURR@@agebd_env_suffix_upper@@:CHARGE-AVG @@ -245,7 +245,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-DBPM3CURR{{ agebd_env_suffix_upper }}:CURRENT-AVG + AGEBD-DBPM3CURR@@agebd_env_suffix_upper@@:CURRENT-AVG @@ -305,7 +305,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-DBPM3CURR{{ agebd_env_suffix_upper }}:ACCUMULATED-BEAM-DOSE + AGEBD-DBPM3CURR@@agebd_env_suffix_upper@@:ACCUMULATED-BEAM-DOSE @@ -521,7 +521,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-DBPM3CURR{{ agebd_env_suffix_upper }}:CURRENT-AVG.EGU + AGEBD-DBPM3CURR@@agebd_env_suffix_upper@@:CURRENT-AVG.EGU @@ -581,7 +581,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-DBPM3CURR{{ agebd_env_suffix_upper }}:CHARGE-AVG.EGU + AGEBD-DBPM3CURR@@agebd_env_suffix_upper@@:CHARGE-AVG.EGU @@ -641,7 +641,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-DBPM3CURR{{ agebd_env_suffix_upper }}:ACCUMULATED-BEAM-DOSE.EGU + AGEBD-DBPM3CURR@@agebd_env_suffix_upper@@:ACCUMULATED-BEAM-DOSE.EGU @@ -755,7 +755,7 @@ - AGEBD-ALH{{ agebd_env_suffix_upper }}:DBPM3CURR-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:DBPM3CURR-ONOFF caChoice::Column @@ -796,7 +796,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-DBPM3CURR{{ agebd_env_suffix_upper }}:CALIBRATION-DBPM3-2-PCT-NEW + AGEBD-DBPM3CURR@@agebd_env_suffix_upper@@:CALIBRATION-DBPM3-2-PCT-NEW @@ -853,7 +853,7 @@ Calculate New Calibration Factor - AGEBD-DBPM3CURR{{ agebd_env_suffix_upper }}:CONTROL-RECALIBRATE + AGEBD-DBPM3CURR@@agebd_env_suffix_upper@@:CONTROL-RECALIBRATE Calculate New Calibration Factor @@ -872,7 +872,7 @@ - AGEBD-DBPM3CURR{{ agebd_env_suffix_upper }}:CONTROL-RECALIBRATE-NPTS + AGEBD-DBPM3CURR@@agebd_env_suffix_upper@@:CONTROL-RECALIBRATE-NPTS 0 @@ -894,7 +894,7 @@ Apply New Calibration Factor - AGEBD-DBPM3CURR{{ agebd_env_suffix_upper }}:CONTROL-RECALIBRATE-APPLY + AGEBD-DBPM3CURR@@agebd_env_suffix_upper@@:CONTROL-RECALIBRATE-APPLY Apply New Calibration Factor @@ -922,7 +922,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-DBPM3CURR{{ agebd_env_suffix_upper }}:CALIBRATION-DBPM3-2-PCT + AGEBD-DBPM3CURR@@agebd_env_suffix_upper@@:CALIBRATION-DBPM3-2-PCT @@ -1118,7 +1118,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-DBPM3CURR{{ agebd_env_suffix_upper }}:ACCUMULATED-BEAM-DOSE-PCT + AGEBD-DBPM3CURR@@agebd_env_suffix_upper@@:ACCUMULATED-BEAM-DOSE-PCT @@ -1194,7 +1194,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-DBPM3CURR{{ agebd_env_suffix_upper }}:ACCUMULATED-BEAM-DOSE-PCT.EGU + AGEBD-DBPM3CURR@@agebd_env_suffix_upper@@:ACCUMULATED-BEAM-DOSE-PCT.EGU diff --git a/qt/A_BD_FeedBackOverview.ui b/qt/A_BD_FeedBackOverview.ui index afac466..d58b54a 100644 --- a/qt/A_BD_FeedBackOverview.ui +++ b/qt/A_BD_FeedBackOverview.ui @@ -106,7 +106,7 @@ caLabel[statusTip="Operation"]{ - name=Orbit Feedback,alive=ARSGE-CECL-FOFB1:FOFB-OPERATE,panelcmd=A_DI_FOFB_CECL_USER.ui;name=Hor. Tune Feedback,onoff=AGEBD-ALH{{ agebd_env_suffix_upper }}:TUNEFBX-ONOFF,alive=AGEBD-ALH{{ agebd_env_suffix_upper }}:TUNEFBX-ALIVE,panelcmd=A_BD_TuneBump.ui;name=Ver. Tune Feedback,onoff=AGEBD-ALH{{ agebd_env_suffix_upper }}:TUNEFBY-ONOFF,alive=AGEBD-ALH{{ agebd_env_suffix_upper }}:TUNEFBY-ALIVE,panelcmd=A_BD_TuneBump.ui + name=Orbit Feedback,alive=ARSGE-CECL-FOFB1:FOFB-OPERATE,panelcmd=A_DI_FOFB_CECL_USER.ui;name=Hor. Tune Feedback,onoff=AGEBD-ALH@@agebd_env_suffix_upper@@:TUNEFBX-ONOFF,alive=AGEBD-ALH@@agebd_env_suffix_upper@@:TUNEFBX-ALIVE,panelcmd=A_BD_TuneBump.ui;name=Ver. Tune Feedback,onoff=AGEBD-ALH@@agebd_env_suffix_upper@@:TUNEFBY-ONOFF,alive=AGEBD-ALH@@agebd_env_suffix_upper@@:TUNEFBY-ALIVE,panelcmd=A_BD_TuneBump.ui A_BD_FeedBackOverview_inc.ui diff --git a/qt/A_BD_InjectionGuard.ui b/qt/A_BD_InjectionGuard.ui index 4393d06..7328d5e 100644 --- a/qt/A_BD_InjectionGuard.ui +++ b/qt/A_BD_InjectionGuard.ui @@ -66,7 +66,7 @@ caLabel[statusTip="Operation"]{ A - AGEBD-ALH{{ agebd_env_suffix_upper }}:INJECTIONGUARD-GUIRELOAD + AGEBD-ALH@@agebd_env_suffix_upper@@:INJECTIONGUARD-GUIRELOAD caCalc::TriggerZeroToOne @@ -89,7 +89,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }}:CONTROL-MODE + AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@:CONTROL-MODE @@ -125,7 +125,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }}:CHECK-SUM + AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@:CHECK-SUM caLineEdit::Alarm_Default @@ -405,7 +405,7 @@ caLabel[statusTip="Operation"]{ 30 - AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }}:STATUS-SECRET-MASTER + AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@:STATUS-SECRET-MASTER caLed::Alarm @@ -547,7 +547,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignCenter - AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }}:CHECK-SUM-OP + AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@:CHECK-SUM-OP caLineEdit::Alarm_Default @@ -617,7 +617,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignCenter - AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }}:CHECK-SUM-MD + AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@:CHECK-SUM-MD caLineEdit::Alarm_Default @@ -696,7 +696,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignCenter - AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }}:CHECK-SUM-LATCH + AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@:CHECK-SUM-LATCH caLineEdit::Alarm_Default @@ -724,7 +724,7 @@ caLabel[statusTip="Operation"]{ false - AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }}:RESET-LATCHES + AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@:RESET-LATCHES Reset @@ -771,7 +771,7 @@ caLabel[statusTip="Operation"]{ Qt::ScrollBarAsNeeded - AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }}:LOG + AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@:LOG caMultiLineString::None @@ -790,7 +790,7 @@ caLabel[statusTip="Operation"]{ Clear Logs - AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }}:LOG-CLEAR + AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@:LOG-CLEAR Clear Logs @@ -819,7 +819,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }}:LOG-PAUSE + AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@:LOG-PAUSE diff --git a/qt/A_BD_InjectionGuard_inc.ui b/qt/A_BD_InjectionGuard_inc.ui index 12b4b31..f81722a 100644 --- a/qt/A_BD_InjectionGuard_inc.ui +++ b/qt/A_BD_InjectionGuard_inc.ui @@ -30,7 +30,7 @@ - AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }}:CONTROL-BRIDGE-CHECK-$(checknr) + AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@:CONTROL-BRIDGE-CHECK-$(checknr) @@ -62,7 +62,7 @@ false - AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }}:CHECK-$(checknr) + AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@:CHECK-$(checknr) caLed::Alarm @@ -81,7 +81,7 @@ false - AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }}:CHECK-$(checknr)-MD + AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@:CHECK-$(checknr)-MD caLed::Alarm @@ -110,7 +110,7 @@ true - AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }}:CHECK-$(checknr).DESC + AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@:CHECK-$(checknr).DESC @@ -170,7 +170,7 @@ false - AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }}:CHECK-$(checknr)-LATCH + AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@:CHECK-$(checknr)-LATCH caLed::Alarm @@ -199,7 +199,7 @@ 20 - AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }}:CONTROL-BRIDGE-CHECK-$(checknr) + AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@:CONTROL-BRIDGE-CHECK-$(checknr) caLed::Alarm diff --git a/qt/A_BD_Master.ui b/qt/A_BD_Master.ui index 96b5a3c..229928e 100644 --- a/qt/A_BD_Master.ui +++ b/qt/A_BD_Master.ui @@ -43,7 +43,7 @@ A - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-GUIRELOAD + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-GUIRELOAD caCalc::TriggerZeroToOne @@ -62,7 +62,7 @@ Clear Logs - AGEBD-MASTER{{ agebd_env_suffix_upper }}:LOG-CLEAR + AGEBD-MASTER@@agebd_env_suffix_upper@@:LOG-CLEAR Clear Logs @@ -94,7 +94,7 @@ Get Systemd Status for each Service - AGEBD-MASTER{{ agebd_env_suffix_upper }}:GET-SYSTEMD-STATUS + AGEBD-MASTER@@agebd_env_suffix_upper@@:GET-SYSTEMD-STATUS Get Systemd Status for each Service @@ -151,7 +151,7 @@ true - AGEBD-MASTER{{ agebd_env_suffix_upper }}:LOG + AGEBD-MASTER@@agebd_env_suffix_upper@@:LOG caLineEdit::User diff --git a/qt/A_BD_NTurns.ui b/qt/A_BD_NTurns.ui index 0921764..dc4479a 100644 --- a/qt/A_BD_NTurns.ui +++ b/qt/A_BD_NTurns.ui @@ -24,7 +24,7 @@ - AGEBD-ALH{{ agebd_env_suffix_upper }}:NTURNS-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:NTURNS-ONOFF caChoice::Column @@ -62,7 +62,7 @@ A - AGEBD-ALH{{ agebd_env_suffix_upper }}:NTURNS-GUIRELOAD + AGEBD-ALH@@agebd_env_suffix_upper@@:NTURNS-GUIRELOAD caCalc::TriggerZeroToOne @@ -202,7 +202,7 @@ - AGEBD-NTURNS{{ agebd_env_suffix_upper }}:CONTROL-80-NPOINTS + AGEBD-NTURNS@@agebd_env_suffix_upper@@:CONTROL-80-NPOINTS caLineEdit::User @@ -218,7 +218,7 @@ - AGEBD-NTURNS{{ agebd_env_suffix_upper }}:CONTROL-80-MINHEIGHT + AGEBD-NTURNS@@agebd_env_suffix_upper@@:CONTROL-80-MINHEIGHT @@ -231,7 +231,7 @@ - AGEBD-NTURNS{{ agebd_env_suffix_upper }}:CONTROL-80-MINSEP + AGEBD-NTURNS@@agebd_env_suffix_upper@@:CONTROL-80-MINSEP @@ -292,7 +292,7 @@ - AGEBD-NTURNS{{ agebd_env_suffix_upper }}:CONTROL-2K-MINSEP + AGEBD-NTURNS@@agebd_env_suffix_upper@@:CONTROL-2K-MINSEP @@ -305,7 +305,7 @@ - AGEBD-NTURNS{{ agebd_env_suffix_upper }}:CONTROL-2K-MINHEIGHT + AGEBD-NTURNS@@agebd_env_suffix_upper@@:CONTROL-2K-MINHEIGHT @@ -318,7 +318,7 @@ - AGEBD-NTURNS{{ agebd_env_suffix_upper }}:CONTROL-2K-NPOINTS + AGEBD-NTURNS@@agebd_env_suffix_upper@@:CONTROL-2K-NPOINTS caLineEdit::User @@ -388,7 +388,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-NTURNS{{ agebd_env_suffix_upper }}:STAGE0-Q-80TURNS + AGEBD-NTURNS@@agebd_env_suffix_upper@@:STAGE0-Q-80TURNS @@ -448,7 +448,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-NTURNS{{ agebd_env_suffix_upper }}:STAGE0-Q-2KTURNS + AGEBD-NTURNS@@agebd_env_suffix_upper@@:STAGE0-Q-2KTURNS @@ -526,7 +526,7 @@ - AGEBD-NTURNS{{ agebd_env_suffix_upper }}:BPM-WF-ENUMERATE;AGEBD-NTURNS{{ agebd_env_suffix_upper }}:STAGE0-Q-80TURNS-WF + AGEBD-NTURNS@@agebd_env_suffix_upper@@:BPM-WF-ENUMERATE;AGEBD-NTURNS@@agebd_env_suffix_upper@@:STAGE0-Q-80TURNS-WF caCartesianPlot::Lines @@ -542,7 +542,7 @@ - AGEBD-NTURNS{{ agebd_env_suffix_upper }}:BPM-WF-ENUMERATE;AGEBD-NTURNS{{ agebd_env_suffix_upper }}:STAGE0-Q-80TURNS-PEAKS + AGEBD-NTURNS@@agebd_env_suffix_upper@@:BPM-WF-ENUMERATE;AGEBD-NTURNS@@agebd_env_suffix_upper@@:STAGE0-Q-80TURNS-PEAKS caCartesianPlot::Sticks @@ -582,7 +582,7 @@ - AGEBD-NTURNS{{ agebd_env_suffix_upper }}:BPM-WF-ENUMERATE;AGEBD-NTURNS{{ agebd_env_suffix_upper }}:STAGE0-Q-2KTURNS-WF + AGEBD-NTURNS@@agebd_env_suffix_upper@@:BPM-WF-ENUMERATE;AGEBD-NTURNS@@agebd_env_suffix_upper@@:STAGE0-Q-2KTURNS-WF caCartesianPlot::Lines @@ -598,7 +598,7 @@ - AGEBD-NTURNS{{ agebd_env_suffix_upper }}:BPM-WF-ENUMERATE;AGEBD-NTURNS{{ agebd_env_suffix_upper }}:STAGE0-Q-80TURNS-PEAKS; + AGEBD-NTURNS@@agebd_env_suffix_upper@@:BPM-WF-ENUMERATE;AGEBD-NTURNS@@agebd_env_suffix_upper@@:STAGE0-Q-80TURNS-PEAKS; caCartesianPlot::Sticks diff --git a/qt/A_BD_OrbitBump.ui b/qt/A_BD_OrbitBump.ui index 64c3c4e..2a17f88 100644 --- a/qt/A_BD_OrbitBump.ui +++ b/qt/A_BD_OrbitBump.ui @@ -328,7 +328,7 @@ A - AGEBD-ALH{{ agebd_env_suffix_upper }}:ORBITBUMP-GUIRELOAD + AGEBD-ALH@@agebd_env_suffix_upper@@:ORBITBUMP-GUIRELOAD caCalc::TriggerZeroToOne diff --git a/qt/A_BD_OrbitBump_ExpertBackUp.ui b/qt/A_BD_OrbitBump_ExpertBackUp.ui index 18fac9c..3b52e13 100644 --- a/qt/A_BD_OrbitBump_ExpertBackUp.ui +++ b/qt/A_BD_OrbitBump_ExpertBackUp.ui @@ -31,7 +31,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:BEAMLINE-BEND + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:BEAMLINE-BEND @@ -51,7 +51,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:BEAMLINE-ID + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:BEAMLINE-ID @@ -64,7 +64,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:BEAMLINECALC + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:BEAMLINECALC caLineEdit::Default @@ -86,7 +86,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:BEAMLINETYPE-BEND + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:BEAMLINETYPE-BEND caLineEdit::Default @@ -108,7 +108,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:BEAMLINETYPE + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:BEAMLINETYPE caLineEdit::Default @@ -130,7 +130,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:BEAMLINETYPE-ID + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:BEAMLINETYPE-ID caLineEdit::Default @@ -152,7 +152,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:BEAMLINE + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:BEAMLINE caLineEdit::Default diff --git a/qt/A_BD_OrbitBump_Expert_inc.ui b/qt/A_BD_OrbitBump_Expert_inc.ui index 1d0a058..105d90e 100644 --- a/qt/A_BD_OrbitBump_Expert_inc.ui +++ b/qt/A_BD_OrbitBump_Expert_inc.ui @@ -24,7 +24,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-DELTAX-BPM1 + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-DELTAX-BPM1 @@ -37,7 +37,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-DELTAY-BPM1 + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-DELTAY-BPM1 @@ -50,7 +50,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-DELTAX-BPM2 + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-DELTAX-BPM2 @@ -63,7 +63,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-DELTAY-BPM2 + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-DELTAY-BPM2 @@ -82,7 +82,7 @@ 0 - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-OFFSET-X + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-OFFSET-X caSpinbox::Alarm @@ -116,7 +116,7 @@ 0 - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-OFFSET-XP + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-OFFSET-XP caSpinbox::Alarm @@ -150,7 +150,7 @@ 0 - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-OFFSET-YP + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-OFFSET-YP caSpinbox::Alarm @@ -184,7 +184,7 @@ 0 - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-OFFSET-Y + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-OFFSET-Y caSpinbox::Alarm @@ -212,7 +212,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-DELTAX-BPM4 + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-DELTAX-BPM4 @@ -225,7 +225,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-DELTAY-BPM3 + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-DELTAY-BPM3 @@ -238,7 +238,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-DELTAY-BPM4 + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-DELTAY-BPM4 @@ -251,7 +251,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-DELTAX-BPM3 + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-DELTAX-BPM3 @@ -264,7 +264,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-BPM1 + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-BPM1 @@ -277,7 +277,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-BPM2 + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-BPM2 @@ -290,7 +290,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-BPM3 + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-BPM3 @@ -303,7 +303,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-BPM4 + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-BPM4 @@ -475,7 +475,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-OFFSET-X-TOTAL + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-OFFSET-X-TOTAL caLineEdit::Alarm_Default @@ -497,7 +497,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-OFFSET-Y-TOTAL + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-OFFSET-Y-TOTAL caLineEdit::Alarm_Default @@ -516,7 +516,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-OFFSET-YP-TOTAL + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-OFFSET-YP-TOTAL caLineEdit::Alarm_Default @@ -535,7 +535,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-OFFSET-XP-TOTAL + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-OFFSET-XP-TOTAL caLineEdit::Alarm_Default diff --git a/qt/A_BD_OrbitBump_Operator_inc.ui b/qt/A_BD_OrbitBump_Operator_inc.ui index 3d59a56..8c18013 100644 --- a/qt/A_BD_OrbitBump_Operator_inc.ui +++ b/qt/A_BD_OrbitBump_Operator_inc.ui @@ -37,7 +37,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-OFFSET-X-TOTAL + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-OFFSET-X-TOTAL caLineEdit::Alarm_Default @@ -59,7 +59,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-OFFSET-XP-TOTAL + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-OFFSET-XP-TOTAL caLineEdit::Alarm_Default @@ -78,7 +78,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-OFFSET-Y-TOTAL + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-OFFSET-Y-TOTAL caLineEdit::Alarm_Default @@ -97,7 +97,7 @@ - AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }}:$(sourcepoint)-OFFSET-YP-TOTAL + AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@:$(sourcepoint)-OFFSET-YP-TOTAL caLineEdit::Alarm_Default diff --git a/qt/A_BD_PostMortemLog.ui b/qt/A_BD_PostMortemLog.ui index bf7f8f7..658cfab 100644 --- a/qt/A_BD_PostMortemLog.ui +++ b/qt/A_BD_PostMortemLog.ui @@ -52,7 +52,7 @@ A - AGEBD-ALH{{ agebd_env_suffix_upper }}:POSTMORTEMLOG-GUIRELOAD + AGEBD-ALH@@agebd_env_suffix_upper@@:POSTMORTEMLOG-GUIRELOAD caCalc::TriggerZeroToOne @@ -74,7 +74,7 @@ true - AGEBD-MASTER{{ agebd_env_suffix_upper }}:LOG + AGEBD-MASTER@@agebd_env_suffix_upper@@:LOG @@ -106,7 +106,7 @@ Horizontal Tune (nominal: Qx = 39.37) - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-QX + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-QX @@ -179,7 +179,7 @@ Vertival Tune (nominal: Qy = 15.22) - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-QY + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-QY @@ -252,7 +252,7 @@ Vertival Beam Size (nominal: Sig_y = 10) - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-X01DD-SIGY + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-X01DD-SIGY @@ -262,7 +262,7 @@ - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-X08DB-SIGY + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-X08DB-SIGY caCartesianPlot::Lines @@ -332,7 +332,7 @@ Horizontal Beam Size (nominal: Sig_x = 9) - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-X01DD-SIGX + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-X01DD-SIGX @@ -342,7 +342,7 @@ - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-X08DB-SIGX + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-X08DB-SIGX caCartesianPlot::Lines @@ -412,7 +412,7 @@ Stored Beam Current - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-CURRPCT + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-CURRPCT @@ -422,7 +422,7 @@ - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-CURRBPM + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-CURRBPM caCartesianPlot::Lines @@ -492,7 +492,7 @@ Beam Lifetime - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TAUBPM + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TAUBPM caCartesianPlot::FatDots @@ -505,7 +505,7 @@ - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TAUPCT + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TAUPCT caCartesianPlot::FatDots @@ -580,7 +580,7 @@ Vertival Beam Size (nominal: Sig_y = 10) - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-X01DD-SIGY-LAST + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-X01DD-SIGY-LAST @@ -590,7 +590,7 @@ - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-X08DB-SIGY-LAST + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-X08DB-SIGY-LAST caCartesianPlot::Lines @@ -660,7 +660,7 @@ Stored Beam Current - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-CURRPCT-LAST + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-CURRPCT-LAST @@ -670,7 +670,7 @@ - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-CURRBPM-LAST + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-CURRBPM-LAST caCartesianPlot::Lines @@ -740,7 +740,7 @@ Horizontal Tune (nominal: Qx = 39.37) - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-QX-LAST + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-QX-LAST @@ -813,7 +813,7 @@ Horizontal Beam Size (nominal: Sig_x = 9) - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-X01DD-SIGX-LAST + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-X01DD-SIGX-LAST @@ -823,7 +823,7 @@ - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-X08DB-SIGX-LAST + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-X08DB-SIGX-LAST caCartesianPlot::Lines @@ -893,7 +893,7 @@ Vertival Tune (nominal: Qy = 15.22) - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-QY-LAST + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-QY-LAST @@ -966,7 +966,7 @@ Beam Lifetime - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TAUBPM-LAST + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TAUBPM-LAST caCartesianPlot::FatDots @@ -979,7 +979,7 @@ - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TIME;AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:BUFFER-TAUPCT-LAST + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TIME;AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:BUFFER-TAUPCT-LAST caCartesianPlot::FatDots @@ -1072,7 +1072,7 @@ Update Logs - AGEBD-MASTER{{ agebd_env_suffix_upper }}:POSTMORTEMLOG-LOGS-REQ + AGEBD-MASTER@@agebd_env_suffix_upper@@:POSTMORTEMLOG-LOGS-REQ Update Logs @@ -1104,7 +1104,7 @@ Test Trigger Post Mortem - AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }}:TEST + AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@:TEST Test Trigger Post Mortem diff --git a/qt/A_BD_Scrubbing.ui b/qt/A_BD_Scrubbing.ui index 0c96232..0deae26 100644 --- a/qt/A_BD_Scrubbing.ui +++ b/qt/A_BD_Scrubbing.ui @@ -24,7 +24,7 @@ - AGEBD-ALH{{ agebd_env_suffix_upper }}:SCRUBBING-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:SCRUBBING-ONOFF caChoice::Column @@ -59,7 +59,7 @@ - ARIVA-VMAVE:PRESS-MAX;ARIVA-VMAVE-FE:PRESS-MAX;ARIVA-VMAVE-ALL:PRESS-MAX;AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-VACUUM-MAX-PLOT;AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-VACUUM-MIN-PLOT;AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-VACUUM-DYN-PLOT + ARIVA-VMAVE:PRESS-MAX;ARIVA-VMAVE-FE:PRESS-MAX;ARIVA-VMAVE-ALL:PRESS-MAX;AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:CONTROL-VACUUM-MAX-PLOT;AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:CONTROL-VACUUM-MIN-PLOT;AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:CONTROL-VACUUM-DYN-PLOT caStripPlot::Second @@ -411,7 +411,7 @@ A - AGEBD-ALH{{ agebd_env_suffix_upper }}:SCRUBBING-GUIRELOAD + AGEBD-ALH@@agebd_env_suffix_upper@@:SCRUBBING-GUIRELOAD caCalc::TriggerOneToZero @@ -427,7 +427,7 @@ - AGEBD-ALH{{ agebd_env_suffix_upper }}:SCRUBBING-INFO + AGEBD-ALH@@agebd_env_suffix_upper@@:SCRUBBING-INFO caLineEdit::Alarm_Default @@ -449,7 +449,7 @@ - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:TOPUP-DELTAT + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:TOPUP-DELTAT caLineEdit::Default @@ -474,7 +474,7 @@ - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:TOPUP-TAU + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:TOPUP-TAU caLineEdit::Default @@ -568,7 +568,7 @@ - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:TOPUP-DELTAI + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:TOPUP-DELTAI caLineEdit::Default @@ -1913,7 +1913,7 @@ 22 - AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }}:STATUS-SECRET-MASTER + AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@:STATUS-SECRET-MASTER caLed::Alarm @@ -2937,7 +2937,7 @@ AGETI-CVME-MASTER-TMA:Evt-LI-Gun-EVRCount-I 0 - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:WARMUPCYCLES-BOIN-SP.VAL + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:WARMUPCYCLES-BOIN-SP.VAL caSpinbox::User @@ -2962,7 +2962,7 @@ AGETI-CVME-MASTER-TMA:Evt-LI-Gun-EVRCount-I 0 - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:WARMUPCYCLES-BOMB-SP.VAL + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:WARMUPCYCLES-BOMB-SP.VAL caSpinbox::User @@ -2987,7 +2987,7 @@ AGETI-CVME-MASTER-TMA:Evt-LI-Gun-EVRCount-I 0 - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:WARMUPCYCLES-BOME-SP.VAL + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:WARMUPCYCLES-BOME-SP.VAL caSpinbox::User @@ -3012,7 +3012,7 @@ AGETI-CVME-MASTER-TMA:Evt-LI-Gun-EVRCount-I 0 - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:WARMUPCYCLES-BOEX-SP.VAL + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:WARMUPCYCLES-BOEX-SP.VAL caSpinbox::User @@ -3037,7 +3037,7 @@ AGETI-CVME-MASTER-TMA:Evt-LI-Gun-EVRCount-I 0 - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:WARMUPCYCLES-SRIN-SP.VAL + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:WARMUPCYCLES-SRIN-SP.VAL caSpinbox::User @@ -3099,7 +3099,7 @@ Setpoint true - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:WARMUPCYCLES-BOMB-RB.VAL + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:WARMUPCYCLES-BOMB-RB.VAL @@ -3141,7 +3141,7 @@ Setpoint true - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:WARMUPCYCLES-BOIN-RB.VAL + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:WARMUPCYCLES-BOIN-RB.VAL @@ -3183,7 +3183,7 @@ Setpoint true - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:WARMUPCYCLES-BOME-RB.VAL + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:WARMUPCYCLES-BOME-RB.VAL @@ -3225,7 +3225,7 @@ Setpoint true - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:WARMUPCYCLES-SRIN-RB.VAL + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:WARMUPCYCLES-SRIN-RB.VAL @@ -3267,7 +3267,7 @@ Setpoint true - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:WARMUPCYCLES-BOEX-RB.VAL + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:WARMUPCYCLES-BOEX-RB.VAL @@ -3394,7 +3394,7 @@ Remaining - ;AGEBD-TIMING{{ agebd_env_suffix_upper }}:TARGET-BUCKET + ;AGEBD-TIMING@@agebd_env_suffix_upper@@:TARGET-BUCKET caCartesianPlot::Sticks @@ -3491,7 +3491,7 @@ Remaining - AGEBD-TIMING{{ agebd_env_suffix_upper }}:GO + AGEBD-TIMING@@agebd_env_suffix_upper@@:GO @@ -3535,7 +3535,7 @@ Remaining - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FILLPATTERN-string.VAL + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FILLPATTERN-string.VAL 0 @@ -3567,7 +3567,7 @@ Remaining - AGEBD-TIMING{{ agebd_env_suffix_upper }}:FPFB-MODE + AGEBD-TIMING@@agebd_env_suffix_upper@@:FPFB-MODE @@ -3591,7 +3591,7 @@ Remaining EPushButton::WidthAndHeight - AGEBD-TIMING{{ agebd_env_suffix_upper }}:ZERO-TARGET-BUCKET + AGEBD-TIMING@@agebd_env_suffix_upper@@:ZERO-TARGET-BUCKET Reset @@ -3639,7 +3639,7 @@ Remaining true - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CURRENT-THRESHOLD + AGEBD-TIMING@@agebd_env_suffix_upper@@:CURRENT-THRESHOLD caSpinbox::User @@ -3690,7 +3690,7 @@ Remaining 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:FPFB-NTH + AGEBD-TIMING@@agebd_env_suffix_upper@@:FPFB-NTH caSpinbox::User @@ -3754,7 +3754,7 @@ Remaining 1 - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-CURRENT-MIN + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:CONTROL-CURRENT-MIN caSpinbox::User @@ -3779,7 +3779,7 @@ Remaining 1 - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-CURRENT-MAX + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:CONTROL-CURRENT-MAX caSpinbox::User @@ -3850,7 +3850,7 @@ Remaining 1 - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-VACUUM-MIN + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:CONTROL-VACUUM-MIN caSpinbox::User @@ -3921,7 +3921,7 @@ Remaining 1 - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-VACUUM-MAX + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:CONTROL-VACUUM-MAX caSpinbox::User @@ -3969,7 +3969,7 @@ Remaining 0 - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-TIME-MAX + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:CONTROL-TIME-MAX caSpinbox::User @@ -3994,7 +3994,7 @@ Remaining 0 - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-TIME-MIN + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:CONTROL-TIME-MIN caSpinbox::User @@ -4058,7 +4058,7 @@ Remaining 0 - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-GUNGRID-FPFB + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:CONTROL-GUNGRID-FPFB caSpinbox::User @@ -4083,7 +4083,7 @@ Remaining 0 - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-GUNGRID-ACCUM + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:CONTROL-GUNGRID-ACCUM caSpinbox::User @@ -4171,7 +4171,7 @@ Remaining - ARS07-DPCT-0000:CURR;AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-CURRENT-MAX;AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-CURRENT-MIN + ARS07-DPCT-0000:CURR;AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:CONTROL-CURRENT-MAX;AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:CONTROL-CURRENT-MIN caStripPlot::Second @@ -4398,7 +4398,7 @@ Remaining Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - AGEBD-PARAMS{{ agebd_env_suffix_upper }}:LIFETIME + AGEBD-PARAMS@@agebd_env_suffix_upper@@:LIFETIME @@ -4448,7 +4448,7 @@ Remaining - AGEBD-PARAMS{{ agebd_env_suffix_upper }}:TRANSMISSION + AGEBD-PARAMS@@agebd_env_suffix_upper@@:TRANSMISSION @@ -4521,7 +4521,7 @@ Remaining -AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-VACUUM-DYN-FRAC +AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:CONTROL-VACUUM-DYN-FRAC caSpinbox::User @@ -4559,7 +4559,7 @@ AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-VACUUM-DYN-FRAC - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-SCRUB + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:CONTROL-SCRUB @@ -4611,7 +4611,7 @@ AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-VACUUM-DYN-FRAC A>3 - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-SCRUB + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:CONTROL-SCRUB @@ -4674,7 +4674,7 @@ AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-VACUUM-DYN-FRAC 0 - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:MBFBY-GAIN-SP.VAL + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:MBFBY-GAIN-SP.VAL caSpinbox::User @@ -4776,7 +4776,7 @@ AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-VACUUM-DYN-FRAC 0 - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:MBFBX-GAIN-SP.VAL + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:MBFBX-GAIN-SP.VAL caSpinbox::User @@ -5062,7 +5062,7 @@ ARSGE-MBFBT-AMP-02:SET-ON-OFF A<4 & A>0 - AGEBD-SCRUBBING{{ agebd_env_suffix_upper }}:CONTROL-SCRUB + AGEBD-SCRUBBING@@agebd_env_suffix_upper@@:CONTROL-SCRUB diff --git a/qt/A_BD_ServiceManager.ui b/qt/A_BD_ServiceManager.ui index 850dca3..3539295 100644 --- a/qt/A_BD_ServiceManager.ui +++ b/qt/A_BD_ServiceManager.ui @@ -71,7 +71,7 @@ caLabel[statusTip="Operation"]{ A - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-GUIRELOAD + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-GUIRELOAD caCalc::TriggerZeroToOne @@ -106,7 +106,7 @@ caLabel[statusTip="Operation"]{ !A - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-ONOFF @@ -586,7 +586,7 @@ caLabel[statusTip="Operation"]{ false - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-ALIVE + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-ALIVE caLed::Alarm @@ -602,7 +602,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-STARTTIME + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-STARTTIME caLineEdit::Default @@ -624,7 +624,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-STATUS + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-STATUS caLineEdit::Default @@ -646,7 +646,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-VERSION + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-VERSION caLineEdit::Default @@ -668,7 +668,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-ONOFF caChoice::Column @@ -717,7 +717,7 @@ caLabel[statusTip="Operation"]{ false - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-ONOFF-RB + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-ONOFF-RB caLed::Alarm @@ -763,7 +763,7 @@ caLabel[statusTip="Operation"]{ false - AGEBD-CPCL-MASTER{{ agebd_env_suffix_upper }}:STATUS + AGEBD-CPCL-MASTER@@agebd_env_suffix_upper@@:STATUS caLed::Alarm @@ -1040,7 +1040,7 @@ caLabel[statusTip="Operation"]{ EPushButton::None - AGEBD-MASTER{{ agebd_env_suffix_upper }}:MASTER-LOGS-REQ + AGEBD-MASTER@@agebd_env_suffix_upper@@:MASTER-LOGS-REQ Logs @@ -1106,7 +1106,7 @@ caLabel[statusTip="Operation"]{ false - AGEBD-ALH{{ agebd_env_suffix_upper }}:MASTER-GUIRELOAD + AGEBD-ALH@@agebd_env_suffix_upper@@:MASTER-GUIRELOAD Reload @@ -1172,7 +1172,7 @@ caLabel[statusTip="Operation"]{ EPushButton::None - AGEBD-CPCL-MASTER{{ agebd_env_suffix_upper }}:RESTART + AGEBD-CPCL-MASTER@@agebd_env_suffix_upper@@:RESTART ↺ diff --git a/qt/A_BD_ServiceManager_inc.ui b/qt/A_BD_ServiceManager_inc.ui index 4f030fb..056c07c 100644 --- a/qt/A_BD_ServiceManager_inc.ui +++ b/qt/A_BD_ServiceManager_inc.ui @@ -162,7 +162,7 @@ - AGEBD-ALH{{ agebd_env_suffix_upper }}:$(service)-STATUS + AGEBD-ALH@@agebd_env_suffix_upper@@:$(service)-STATUS caLineEdit::Default @@ -195,7 +195,7 @@ EPushButton::None - AGEBD-MASTER{{ agebd_env_suffix_upper }}:$(service)-RESTART-REQ + AGEBD-MASTER@@agebd_env_suffix_upper@@:$(service)-RESTART-REQ Restart @@ -227,7 +227,7 @@ - AGEBD-ALH{{ agebd_env_suffix_upper }}:$(service)-VERSION + AGEBD-ALH@@agebd_env_suffix_upper@@:$(service)-VERSION caLineEdit::Default @@ -249,7 +249,7 @@ - AGEBD-ALH{{ agebd_env_suffix_upper }}:$(service)-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:$(service)-ONOFF caChoice::Column @@ -268,7 +268,7 @@ - AGEBD-ALH{{ agebd_env_suffix_upper }}:$(service)-STARTTIME + AGEBD-ALH@@agebd_env_suffix_upper@@:$(service)-STARTTIME caLineEdit::Default @@ -320,7 +320,7 @@ false - AGEBD-ALH{{ agebd_env_suffix_upper }}:$(service)-ALIVE + AGEBD-ALH@@agebd_env_suffix_upper@@:$(service)-ALIVE caLed::Alarm @@ -347,7 +347,7 @@ EPushButton::None - AGEBD-MASTER{{ agebd_env_suffix_upper }}:$(service)-LOGS-REQ + AGEBD-MASTER@@agebd_env_suffix_upper@@:$(service)-LOGS-REQ Logs @@ -409,7 +409,7 @@ false - AGEBD-ALH{{ agebd_env_suffix_upper }}:$(service)-ONOFF-RB + AGEBD-ALH@@agebd_env_suffix_upper@@:$(service)-ONOFF-RB caLed::Alarm @@ -536,7 +536,7 @@ EPushButton::None - AGEBD-MASTER{{ agebd_env_suffix_upper }}:$(service)-START-REQ + AGEBD-MASTER@@agebd_env_suffix_upper@@:$(service)-START-REQ Start @@ -579,7 +579,7 @@ EPushButton::None - AGEBD-MASTER{{ agebd_env_suffix_upper }}:$(service)-ABORT-REQ + AGEBD-MASTER@@agebd_env_suffix_upper@@:$(service)-ABORT-REQ KILL @@ -686,7 +686,7 @@ - AGEBD-ALH{{ agebd_env_suffix_upper }}:$(service)-GUIRELOAD + AGEBD-ALH@@agebd_env_suffix_upper@@:$(service)-GUIRELOAD Reload diff --git a/qt/A_BD_TauBPM.ui b/qt/A_BD_TauBPM.ui index 9460e95..c063922 100644 --- a/qt/A_BD_TauBPM.ui +++ b/qt/A_BD_TauBPM.ui @@ -78,7 +78,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TAUBPM{{ agebd_env_suffix_upper }}:TAU + AGEBD-TAUBPM@@agebd_env_suffix_upper@@:TAU @@ -138,7 +138,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TAUBPM{{ agebd_env_suffix_upper }}:TAU-ERR + AGEBD-TAUBPM@@agebd_env_suffix_upper@@:TAU-ERR @@ -214,7 +214,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TAUBPM{{ agebd_env_suffix_upper }}:INJRATE + AGEBD-TAUBPM@@agebd_env_suffix_upper@@:INJRATE @@ -274,7 +274,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TAUBPM{{ agebd_env_suffix_upper }}:INJRATE-ERR + AGEBD-TAUBPM@@agebd_env_suffix_upper@@:INJRATE-ERR @@ -363,7 +363,7 @@ A - AGEBD-ALH{{ agebd_env_suffix_upper }}:LIFETIME-GUIRELOAD + AGEBD-ALH@@agebd_env_suffix_upper@@:LIFETIME-GUIRELOAD caCalc::TriggerZeroToOne @@ -395,7 +395,7 @@ - AGEBD-TAUBPM{{ agebd_env_suffix_upper }}:CONTROL-NSAMPLES-FIT-TAU + AGEBD-TAUBPM@@agebd_env_suffix_upper@@:CONTROL-NSAMPLES-FIT-TAU caLineEdit::User @@ -411,7 +411,7 @@ - AGEBD-TAUBPM{{ agebd_env_suffix_upper }}:CONTROL-MIN-CURR + AGEBD-TAUBPM@@agebd_env_suffix_upper@@:CONTROL-MIN-CURR 12 @@ -430,7 +430,7 @@ - AGEBD-ALH{{ agebd_env_suffix_upper }}:TAUBPM-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:TAUBPM-ONOFF caChoice::Column @@ -465,7 +465,7 @@ - AGEBD-TAUBPM{{ agebd_env_suffix_upper }}:CONTROL-NSAMPLES-FIT-ROC + AGEBD-TAUBPM@@agebd_env_suffix_upper@@:CONTROL-NSAMPLES-FIT-ROC caLineEdit::User diff --git a/qt/A_BD_TauPCT.ui b/qt/A_BD_TauPCT.ui index 31c3115..7f79c7d 100644 --- a/qt/A_BD_TauPCT.ui +++ b/qt/A_BD_TauPCT.ui @@ -78,7 +78,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TAUPCT{{ agebd_env_suffix_upper }}:TAU + AGEBD-TAUPCT@@agebd_env_suffix_upper@@:TAU @@ -138,7 +138,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TAUPCT{{ agebd_env_suffix_upper }}:TAU-ERR + AGEBD-TAUPCT@@agebd_env_suffix_upper@@:TAU-ERR @@ -214,7 +214,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TAUPCT{{ agebd_env_suffix_upper }}:INJRATE + AGEBD-TAUPCT@@agebd_env_suffix_upper@@:INJRATE @@ -274,7 +274,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TAUPCT{{ agebd_env_suffix_upper }}:INJRATE-ERR + AGEBD-TAUPCT@@agebd_env_suffix_upper@@:INJRATE-ERR @@ -363,7 +363,7 @@ A - AGEBD-ALH{{ agebd_env_suffix_upper }}:TAUPCT-GUIRELOAD + AGEBD-ALH@@agebd_env_suffix_upper@@:TAUPCT-GUIRELOAD caCalc::TriggerZeroToOne @@ -395,7 +395,7 @@ - AGEBD-TAUPCT{{ agebd_env_suffix_upper }}:CONTROL-NSAMPLES-FIT-TAU + AGEBD-TAUPCT@@agebd_env_suffix_upper@@:CONTROL-NSAMPLES-FIT-TAU caLineEdit::User @@ -411,7 +411,7 @@ - AGEBD-TAUPCT{{ agebd_env_suffix_upper }}:CONTROL-MIN-CURR + AGEBD-TAUPCT@@agebd_env_suffix_upper@@:CONTROL-MIN-CURR 12 @@ -430,7 +430,7 @@ - AGEBD-ALH{{ agebd_env_suffix_upper }}:TAUPCT-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:TAUPCT-ONOFF caChoice::Column @@ -449,7 +449,7 @@ - AGEBD-TAUPCT{{ agebd_env_suffix_upper }}:CONTROL-NSAMPLES-FIT-ROC + AGEBD-TAUPCT@@agebd_env_suffix_upper@@:CONTROL-NSAMPLES-FIT-ROC caLineEdit::User diff --git a/qt/A_BD_Timing.ui b/qt/A_BD_Timing.ui index 3b78166..b18ff40 100644 --- a/qt/A_BD_Timing.ui +++ b/qt/A_BD_Timing.ui @@ -46,7 +46,7 @@ A - AGEBD-ALH{{ agebd_env_suffix_upper }}:TIMING-GUIRELOAD + AGEBD-ALH@@agebd_env_suffix_upper@@:TIMING-GUIRELOAD caCalc::TriggerZeroToOne @@ -154,7 +154,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-GUN + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-GUN caSpinbox::User @@ -185,7 +185,7 @@ 3 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-lirf-llemast + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-lirf-llemast caSpinbox::User @@ -240,7 +240,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-BOINKI + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-BOINKI caSpinbox::User @@ -295,7 +295,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-BOINSE + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-BOINSE caSpinbox::User @@ -326,7 +326,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-BOEXKI + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-BOEXKI caSpinbox::User @@ -384,7 +384,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-BOEXSE + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-BOEXSE caSpinbox::User @@ -442,7 +442,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-SRINSE + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-SRINSE caSpinbox::User @@ -548,7 +548,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-BTRICT + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-BTRICT caSpinbox::User @@ -798,7 +798,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-lirf-klystr2 + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-lirf-klystr2 caSpinbox::User @@ -829,7 +829,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-lirf-3GHzScp + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-lirf-3GHzScp caSpinbox::User @@ -860,7 +860,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-lirf-500-PBU + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-lirf-500-PBU caSpinbox::User @@ -891,7 +891,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-lirf-Kly1PMU + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-lirf-Kly1PMU caSpinbox::User @@ -922,7 +922,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-lirf-klystr1 + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-lirf-klystr1 caSpinbox::User @@ -953,7 +953,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-lirf-preamp1 + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-lirf-preamp1 caSpinbox::User @@ -984,7 +984,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-lirf-3GHzQdm + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-lirf-3GHzQdm caSpinbox::User @@ -1015,7 +1015,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-lirf-preamp2 + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-lirf-preamp2 caSpinbox::User @@ -1046,7 +1046,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-lirf-Kly2PMU + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-lirf-Kly2PMU caSpinbox::User @@ -1173,7 +1173,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-SRINK1 + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-SRINK1 caSpinbox::User @@ -1207,7 +1207,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-SRINK2 + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-SRINK2 caSpinbox::User @@ -1241,7 +1241,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-SRINK3 + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-SRINK3 caSpinbox::User @@ -1275,7 +1275,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-SRINK4 + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-SRINK4 caSpinbox::User @@ -1333,7 +1333,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-lindi-ictone + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-lindi-ictone caSpinbox::User @@ -1364,7 +1364,7 @@ 0 - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-ZERO-DELAY-lindi-icts23 + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-ZERO-DELAY-lindi-icts23 caSpinbox::User @@ -3472,7 +3472,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-GUN + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-GUN @@ -3497,7 +3497,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-lirf-llemast + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-lirf-llemast @@ -3522,7 +3522,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-BOINKI + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-BOINKI @@ -3547,7 +3547,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-BOINSE + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-BOINSE @@ -3572,7 +3572,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-BOEXKI + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-BOEXKI @@ -3597,7 +3597,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-BOEXSE + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-BOEXSE @@ -3622,7 +3622,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-BTRICT + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-BTRICT @@ -3647,7 +3647,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-SRINSE + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-SRINSE @@ -3672,7 +3672,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-SRINK4 + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-SRINK4 @@ -3697,7 +3697,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-lirf-preamp1 + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-lirf-preamp1 @@ -3722,7 +3722,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-lirf-3GHzQdm + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-lirf-3GHzQdm @@ -3747,7 +3747,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-lirf-500-PBU + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-lirf-500-PBU @@ -3772,7 +3772,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-lirf-preamp2 + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-lirf-preamp2 @@ -3797,7 +3797,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-lirf-klystr2 + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-lirf-klystr2 @@ -3822,7 +3822,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-lirf-3GHzScp + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-lirf-3GHzScp @@ -3847,7 +3847,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-lirf-Kly1PMU + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-lirf-Kly1PMU @@ -3872,7 +3872,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-lirf-klystr1 + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-lirf-klystr1 @@ -3897,7 +3897,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-lirf-Kly2PMU + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-lirf-Kly2PMU @@ -3922,7 +3922,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-lindi-ictone + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-lindi-ictone @@ -3947,7 +3947,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-lindi-icts23 + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-lindi-icts23 @@ -3972,7 +3972,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-SRINK3 + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-SRINK3 @@ -3997,7 +3997,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-SRINK2 + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-SRINK2 @@ -4022,7 +4022,7 @@ false - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FLW-BCKT-SRINK1 + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FLW-BCKT-SRINK1 catogglebutton_3 @@ -4089,7 +4089,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TIMING{{ agebd_env_suffix_upper }}:SETALL-DELAY + AGEBD-TIMING@@agebd_env_suffix_upper@@:SETALL-DELAY @@ -4149,7 +4149,7 @@ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TIMING{{ agebd_env_suffix_upper }}:SETALL-ERROR + AGEBD-TIMING@@agebd_env_suffix_upper@@:SETALL-ERROR @@ -4230,7 +4230,7 @@ - AGEBD-TIMING{{ agebd_env_suffix_upper }}:CONTROL-FILLPATTERN-string.VAL + AGEBD-TIMING@@agebd_env_suffix_upper@@:CONTROL-FILLPATTERN-string.VAL 0 @@ -4266,7 +4266,7 @@ EPushButton::WidthAndHeight - AGEBD-TIMING{{ agebd_env_suffix_upper }}:ZERO-TARGET-BUCKET + AGEBD-TIMING@@agebd_env_suffix_upper@@:ZERO-TARGET-BUCKET Reset @@ -4426,7 +4426,7 @@ !A - AGEBD-ALH{{ agebd_env_suffix_upper }}:TIMING-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:TIMING-ONOFF @@ -4470,7 +4470,7 @@ - AGEBD-ALH{{ agebd_env_suffix_upper }}:TIMING-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:TIMING-ONOFF 0 diff --git a/qt/A_BD_TopUpTool.ui b/qt/A_BD_TopUpTool.ui index cb126f5..83e7b85 100644 --- a/qt/A_BD_TopUpTool.ui +++ b/qt/A_BD_TopUpTool.ui @@ -24,7 +24,7 @@ - AGEBD-ALH{{ agebd_env_suffix_upper }}:TOPUPTOOL-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:TOPUPTOOL-ONOFF caChoice::Column @@ -209,7 +209,7 @@ 0 - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:CONTROL-GUNGRID-MAX + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:CONTROL-GUNGRID-MAX caSpinbox::User @@ -273,7 +273,7 @@ A - AGEBD-ALH{{ agebd_env_suffix_upper }}:SCRUBBING-GUIRELOAD + AGEBD-ALH@@agebd_env_suffix_upper@@:SCRUBBING-GUIRELOAD caCalc::TriggerOneToZero @@ -289,7 +289,7 @@ - AGEBD-ALH{{ agebd_env_suffix_upper }}:SCRUBBING-INFO + AGEBD-ALH@@agebd_env_suffix_upper@@:SCRUBBING-INFO caLineEdit::Alarm_Default @@ -311,7 +311,7 @@ - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:TOPUP-DELTAT + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:TOPUP-DELTAT caLineEdit::Default @@ -336,7 +336,7 @@ - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:TOPUP-TAU + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:TOPUP-TAU caLineEdit::Default @@ -430,7 +430,7 @@ - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:TOPUP-DELTAI + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:TOPUP-DELTAI caLineEdit::Default @@ -1989,7 +1989,7 @@ 22 - AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }}:STATUS-SECRET-MASTER + AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@:STATUS-SECRET-MASTER caLed::Alarm @@ -2286,7 +2286,7 @@ AGETI-CVME-MASTER-TMA:Evt-SR-Inj-EVRCount-I 1 - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:CONTROL-CURRENT-MAX + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:CONTROL-CURRENT-MAX caSpinbox::User @@ -2744,7 +2744,7 @@ AGETI-CVME-MASTER-TMA:Evt-14.VALA 1 - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:CONTROL-CURRENT-MAX + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:CONTROL-CURRENT-MAX caSpinbox::User @@ -2769,7 +2769,7 @@ AGETI-CVME-MASTER-TMA:Evt-14.VALA 1 - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:CONTROL-CURRENT-MAX + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:CONTROL-CURRENT-MAX caSpinbox::User @@ -2794,7 +2794,7 @@ AGETI-CVME-MASTER-TMA:Evt-14.VALA 1 - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:CONTROL-CURRENT-MAX + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:CONTROL-CURRENT-MAX caSpinbox::User @@ -2819,7 +2819,7 @@ AGETI-CVME-MASTER-TMA:Evt-14.VALA 1 - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:CONTROL-CURRENT-MAX + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:CONTROL-CURRENT-MAX caSpinbox::User @@ -2844,7 +2844,7 @@ AGETI-CVME-MASTER-TMA:Evt-14.VALA 1 - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:CONTROL-CURRENT-MAX + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:CONTROL-CURRENT-MAX caSpinbox::User @@ -2869,7 +2869,7 @@ AGETI-CVME-MASTER-TMA:Evt-14.VALA 1 - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:CONTROL-CURRENT-MAX + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:CONTROL-CURRENT-MAX caSpinbox::User @@ -2894,7 +2894,7 @@ AGETI-CVME-MASTER-TMA:Evt-14.VALA 1 - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:CONTROL-CURRENT-MAX + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:CONTROL-CURRENT-MAX caSpinbox::User @@ -3050,7 +3050,7 @@ AGETI-CVME-MASTER-TMA:Evt-14.VALA 1 - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:CONTROL-CURRENT-MAX + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:CONTROL-CURRENT-MAX caSpinbox::User @@ -3121,7 +3121,7 @@ AGETI-CVME-MASTER-TMA:Evt-14.VALA 1 - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:CONTROL-TIME-FREQ + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:CONTROL-TIME-FREQ caSpinbox::User @@ -3169,7 +3169,7 @@ AGETI-CVME-MASTER-TMA:Evt-14.VALA 1 - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:CONTROL-CURRENT-MIN + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:CONTROL-CURRENT-MIN caSpinbox::User @@ -3194,7 +3194,7 @@ AGETI-CVME-MASTER-TMA:Evt-14.VALA 1 - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:CONTROL-VAC-MAX + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:CONTROL-VAC-MAX caSpinbox::User @@ -3219,7 +3219,7 @@ AGETI-CVME-MASTER-TMA:Evt-14.VALA 1 - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:CONTROL-VAC-MIN + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:CONTROL-VAC-MIN caSpinbox::User @@ -3262,7 +3262,7 @@ AGETI-CVME-MASTER-TMA:Evt-14.VALA - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:TOPUP-DELTAT + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:TOPUP-DELTAT caLineEdit::Default @@ -3287,7 +3287,7 @@ AGETI-CVME-MASTER-TMA:Evt-14.VALA - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:TOPUP-DELTAI + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:TOPUP-DELTAI caLineEdit::Default @@ -3312,7 +3312,7 @@ AGETI-CVME-MASTER-TMA:Evt-14.VALA - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:TOPUP-TAU + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:TOPUP-TAU caLineEdit::Default @@ -3337,7 +3337,7 @@ AGETI-CVME-MASTER-TMA:Evt-14.VALA - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:TOPUP-DELTAI + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:TOPUP-DELTAI caLineEdit::Default @@ -3431,7 +3431,7 @@ AGETI-CVME-MASTER-TMA:Evt-14.VALA - AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }}:TOPUP-DELTAT + AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@:TOPUP-DELTAT caLineEdit::Default diff --git a/qt/A_BD_Tune.ui b/qt/A_BD_Tune.ui index d6b6403..733714b 100644 --- a/qt/A_BD_Tune.ui +++ b/qt/A_BD_Tune.ui @@ -55,7 +55,7 @@ x [mm] - AGEBD-TUNE{{ agebd_env_suffix_upper }}:OSCILLATION-SAMPLE-ALL;AGEBD-TUNE{{ agebd_env_suffix_upper }}:OSCILLATION-X-ALL + AGEBD-TUNE@@agebd_env_suffix_upper@@:OSCILLATION-SAMPLE-ALL;AGEBD-TUNE@@agebd_env_suffix_upper@@:OSCILLATION-X-ALL caCartesianPlot::NoSymbol @@ -102,7 +102,7 @@ y [mm] - AGEBD-TUNE{{ agebd_env_suffix_upper }}:OSCILLATION-SAMPLE-ALL;AGEBD-TUNE{{ agebd_env_suffix_upper }}:OSCILLATION-Y-ALL + AGEBD-TUNE@@agebd_env_suffix_upper@@:OSCILLATION-SAMPLE-ALL;AGEBD-TUNE@@agebd_env_suffix_upper@@:OSCILLATION-Y-ALL caCartesianPlot::NoSymbol @@ -151,7 +151,7 @@ Amplitude - AGEBD-TUNE{{ agebd_env_suffix_upper }}:SPEC-SAMPLE-ALL;AGEBD-TUNE{{ agebd_env_suffix_upper }}:HORIZONTAL-SPEC-ALL + AGEBD-TUNE@@agebd_env_suffix_upper@@:SPEC-SAMPLE-ALL;AGEBD-TUNE@@agebd_env_suffix_upper@@:HORIZONTAL-SPEC-ALL caCartesianPlot::NoSymbol @@ -198,7 +198,7 @@ Amplitude - AGEBD-TUNE{{ agebd_env_suffix_upper }}:SPEC-SAMPLE-ALL;AGEBD-TUNE{{ agebd_env_suffix_upper }}:VERTICAL-SPEC-ALL + AGEBD-TUNE@@agebd_env_suffix_upper@@:SPEC-SAMPLE-ALL;AGEBD-TUNE@@agebd_env_suffix_upper@@:VERTICAL-SPEC-ALL caCartesianPlot::NoSymbol @@ -283,7 +283,7 @@ false - AGEBD-ALH{{ agebd_env_suffix_upper }}:TUNE-ALIVE + AGEBD-ALH@@agebd_env_suffix_upper@@:TUNE-ALIVE caLed::Alarm @@ -323,7 +323,7 @@ false - AGEBD-ALH{{ agebd_env_suffix_upper }}:TUNE-ONOFF-RB + AGEBD-ALH@@agebd_env_suffix_upper@@:TUNE-ONOFF-RB caLed::Alarm @@ -358,7 +358,7 @@ measurement true - AGEBD-ALH{{ agebd_env_suffix_upper }}:TUNE-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:TUNE-ONOFF @@ -405,7 +405,7 @@ measurement - AGEBD-TUNE{{ agebd_env_suffix_upper }}:MEAS-TIME + AGEBD-TUNE@@agebd_env_suffix_upper@@:MEAS-TIME @@ -433,7 +433,7 @@ measurement - AGEBD-TUNE{{ agebd_env_suffix_upper }}:VERTICAL-PEAK1-FREQ + AGEBD-TUNE@@agebd_env_suffix_upper@@:VERTICAL-PEAK1-FREQ 4 @@ -467,7 +467,7 @@ measurement - AGEBD-TUNE{{ agebd_env_suffix_upper }}:HORIZONTAL-PEAK1-FREQ + AGEBD-TUNE@@agebd_env_suffix_upper@@:HORIZONTAL-PEAK1-FREQ 4 @@ -516,7 +516,7 @@ measurement - AGEBD-TUNE{{ agebd_env_suffix_upper }}:Q1_NAFF + AGEBD-TUNE@@agebd_env_suffix_upper@@:Q1_NAFF 4 @@ -538,7 +538,7 @@ measurement - AGEBD-TUNE{{ agebd_env_suffix_upper }}:Q2_NAFF + AGEBD-TUNE@@agebd_env_suffix_upper@@:Q2_NAFF 4 @@ -612,7 +612,7 @@ measurement false - AGEBD-TUNE{{ agebd_env_suffix_upper }}:SVD-CLEAN + AGEBD-TUNE@@agebd_env_suffix_upper@@:SVD-CLEAN @@ -631,7 +631,7 @@ measurement 0 - AGEBD-TUNE{{ agebd_env_suffix_upper }}:SVD-CLEAN-Neigenvalues + AGEBD-TUNE@@agebd_env_suffix_upper@@:SVD-CLEAN-Neigenvalues false @@ -705,7 +705,7 @@ values 2 - AGEBD-TUNE{{ agebd_env_suffix_upper }}:CONTROL-ROI-Yi + AGEBD-TUNE@@agebd_env_suffix_upper@@:CONTROL-ROI-Yi caSpinbox::User @@ -756,7 +756,7 @@ values 0.000000000000000 - AGEBD-TUNE{{ agebd_env_suffix_upper }}:CONTROL-ROI-Xf + AGEBD-TUNE@@agebd_env_suffix_upper@@:CONTROL-ROI-Xf caSpinbox::User @@ -789,7 +789,7 @@ values 2 - AGEBD-TUNE{{ agebd_env_suffix_upper }}:CONTROL-ROI-Xi + AGEBD-TUNE@@agebd_env_suffix_upper@@:CONTROL-ROI-Xi caSpinbox::User @@ -870,7 +870,7 @@ values 0.000000000000000 - AGEBD-TUNE{{ agebd_env_suffix_upper }}:CONTROL-ROI-Yf + AGEBD-TUNE@@agebd_env_suffix_upper@@:CONTROL-ROI-Yf caSpinbox::User @@ -934,7 +934,7 @@ values false - AGEBD-TUNE{{ agebd_env_suffix_upper }}:CONTROL-TbTLastIndex + AGEBD-TUNE@@agebd_env_suffix_upper@@:CONTROL-TbTLastIndex caSpinbox::User @@ -994,7 +994,7 @@ values false - AGEBD-TUNE{{ agebd_env_suffix_upper }}:CONTROL-TbTFirstIndex + AGEBD-TUNE@@agebd_env_suffix_upper@@:CONTROL-TbTFirstIndex false @@ -1045,7 +1045,7 @@ values true - AGEBD-TUNE{{ agebd_env_suffix_upper }}:CONTROL-NAveraging + AGEBD-TUNE@@agebd_env_suffix_upper@@:CONTROL-NAveraging caNumeric::Channel @@ -1096,7 +1096,7 @@ values true - AGEBD-TUNE{{ agebd_env_suffix_upper }}:CONTROL-NAFF + AGEBD-TUNE@@agebd_env_suffix_upper@@:CONTROL-NAFF @@ -1130,7 +1130,7 @@ harmonics true - AGEBD-TUNE{{ agebd_env_suffix_upper }}:NAFF-HARMONICS + AGEBD-TUNE@@agebd_env_suffix_upper@@:NAFF-HARMONICS caNumeric::Channel @@ -1185,7 +1185,7 @@ ARS07-DBPM-0840 - AGEBD-TUNE{{ agebd_env_suffix_upper }}:BPM-SELECT-SINGLE + AGEBD-TUNE@@agebd_env_suffix_upper@@:BPM-SELECT-SINGLE @@ -1873,7 +1873,7 @@ ARS07-DBPM-0840 false - AGEBD-TUNE{{ agebd_env_suffix_upper }}:SINGLE-BPM + AGEBD-TUNE@@agebd_env_suffix_upper@@:SINGLE-BPM diff --git a/qt/A_BD_TuneBump.ui b/qt/A_BD_TuneBump.ui index 55eff01..9ed1d2c 100644 --- a/qt/A_BD_TuneBump.ui +++ b/qt/A_BD_TuneBump.ui @@ -81,7 +81,7 @@ caLabel[statusTip="Operation"]{ A - AGEBD-ALH{{ agebd_env_suffix_upper }}:TUNEBUMP-GUIRELOAD + AGEBD-ALH@@agebd_env_suffix_upper@@:TUNEBUMP-GUIRELOAD caCalc::TriggerZeroToOne @@ -103,7 +103,7 @@ caLabel[statusTip="Operation"]{ false - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QX-STEPDOWN + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QX-STEPDOWN << @@ -141,7 +141,7 @@ caLabel[statusTip="Operation"]{ 4 - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QX-STEPSIZE + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QX-STEPSIZE caSpinbox::User @@ -175,7 +175,7 @@ caLabel[statusTip="Operation"]{ 4 - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QY-STEPSIZE + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QY-STEPSIZE caSpinbox::User @@ -232,7 +232,7 @@ caLabel[statusTip="Operation"]{ false - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QY-STEPDOWN + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QY-STEPDOWN << @@ -330,7 +330,7 @@ caLabel[statusTip="Operation"]{ false - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QY-STEPUP + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QY-STEPUP >> @@ -368,7 +368,7 @@ caLabel[statusTip="Operation"]{ false - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QX-STEPUP + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QX-STEPUP >> @@ -457,7 +457,7 @@ caLabel[statusTip="Operation"]{ Vertical Tune (nominal: Qy = 15.22) - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:NORM-QY-FREQ;AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:NORM-QY-AMP + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:NORM-QY-FREQ;AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:NORM-QY-AMP @@ -467,7 +467,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QY-PEAKS-FREQ;AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QY-PEAKS + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QY-PEAKS-FREQ;AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QY-PEAKS caCartesianPlot::Sticks @@ -518,7 +518,7 @@ caLabel[statusTip="Operation"]{ Synchrotron Tune (nominal: 0.0027) - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:NORM-QZ-FREQ;AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:NORM-QZ-AMP + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:NORM-QZ-FREQ;AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:NORM-QZ-AMP @@ -528,7 +528,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QZ-PEAKS-FREQ;AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QZ-PEAKS + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QZ-PEAKS-FREQ;AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QZ-PEAKS caCartesianPlot::Sticks @@ -579,7 +579,7 @@ caLabel[statusTip="Operation"]{ Horizontal Tune (nominal: Qx = 39.37) - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:NORM-QX-FREQ;AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:NORM-QX-AMP + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:NORM-QX-FREQ;AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:NORM-QX-AMP @@ -589,7 +589,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QX-PEAKS-FREQ;AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QX-PEAKS + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QX-PEAKS-FREQ;AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QX-PEAKS caCartesianPlot::Sticks @@ -657,7 +657,7 @@ caLabel[statusTip="Operation"]{ Tune Z - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:SPEC-FREQ-qZ;AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:SPEC-Z + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:SPEC-FREQ-qZ;AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:SPEC-Z @@ -702,7 +702,7 @@ caLabel[statusTip="Operation"]{ Tune Y - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:SPEC-FREQ-qY;AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:SPEC-Y + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:SPEC-FREQ-qY;AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:SPEC-Y @@ -747,7 +747,7 @@ caLabel[statusTip="Operation"]{ Tune X - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:SPEC-FREQ-qX;AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:SPEC-X + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:SPEC-FREQ-qX;AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:SPEC-X @@ -809,7 +809,7 @@ caLabel[statusTip="Operation"]{ Vertical TbT data - ;AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:SIGN-Y + ;AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:SIGN-Y @@ -857,7 +857,7 @@ caLabel[statusTip="Operation"]{ Longitudinal Stage 1 Data - ;AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:SIGN-Z + ;AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:SIGN-Z @@ -905,7 +905,7 @@ caLabel[statusTip="Operation"]{ Horizontal TbT data - ;AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:SIGN-X + ;AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:SIGN-X @@ -1329,7 +1329,7 @@ caLabel[statusTip="Operation"]{ 2 - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QX-ULIM + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QX-ULIM caSpinbox::User @@ -1360,7 +1360,7 @@ caLabel[statusTip="Operation"]{ 2 - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QX-LLIM + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QX-LLIM caSpinbox::User @@ -1391,7 +1391,7 @@ caLabel[statusTip="Operation"]{ 2 - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QY-ULIM + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QY-ULIM caSpinbox::User @@ -1459,7 +1459,7 @@ caLabel[statusTip="Operation"]{ 2 - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QY-LLIM + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QY-LLIM caSpinbox::User @@ -1758,7 +1758,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:SIGN-Y.INP + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:SIGN-Y.INP @@ -1818,7 +1818,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:SIGN-X.INP + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:SIGN-X.INP @@ -1878,7 +1878,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:SIGN-Z.INP + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:SIGN-Z.INP @@ -2021,7 +2021,7 @@ caLabel[statusTip="Operation"]{ 3 - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:CONTROL-KP + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:CONTROL-KP caSpinbox::User @@ -2193,7 +2193,7 @@ caLabel[statusTip="Operation"]{ 3 - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:CONTROL-KI + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:CONTROL-KI caSpinbox::User @@ -2224,7 +2224,7 @@ caLabel[statusTip="Operation"]{ 3 - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:CONTROL-KD + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:CONTROL-KD caSpinbox::User @@ -2255,7 +2255,7 @@ caLabel[statusTip="Operation"]{ 2 - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:CONTROL-QX + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:CONTROL-QX caSpinbox::User @@ -2323,7 +2323,7 @@ caLabel[statusTip="Operation"]{ 2 - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:CONTROL-QXMAX + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:CONTROL-QXMAX caSpinbox::User @@ -2391,7 +2391,7 @@ caLabel[statusTip="Operation"]{ 2 - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:CONTROL-QXMIN + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:CONTROL-QXMIN caSpinbox::User @@ -2496,7 +2496,7 @@ caLabel[statusTip="Operation"]{ 1 - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:CONTROL-MIN-CURR + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:CONTROL-MIN-CURR caSpinbox::User @@ -2567,7 +2567,7 @@ caLabel[statusTip="Operation"]{ true - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:CONTROL-QX-OKRNG + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:CONTROL-QX-OKRNG caSpinbox::User @@ -2598,7 +2598,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:DELTAQ + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:DELTAQ @@ -2705,7 +2705,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:QSTEPS + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:QSTEPS caStripPlot::Second @@ -2866,7 +2866,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-ALH{{ agebd_env_suffix_upper }}:TUNEFBX-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:TUNEFBX-ONOFF caChoice::Column @@ -2885,7 +2885,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:CHECK1 + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:CHECK1 @@ -2911,7 +2911,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:CHECK2 + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:CHECK2 @@ -2974,7 +2974,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:CHECK5 + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:CHECK5 @@ -3000,7 +3000,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:CHECK8 + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:CHECK8 @@ -3063,7 +3063,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:CHECK3 + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:CHECK3 @@ -3126,7 +3126,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:CHECK6 + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:CHECK6 @@ -3152,7 +3152,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:CHECK4 + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:CHECK4 @@ -3215,7 +3215,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:CHECK7 + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:CHECK7 @@ -3321,7 +3321,7 @@ caLabel[statusTip="Operation"]{ true - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:CHECKALL + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:CHECKALL @@ -3501,7 +3501,7 @@ caLabel[statusTip="Operation"]{ 3 - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:DELTAQ-ULIM + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:DELTAQ-ULIM caSpinbox::User @@ -3532,7 +3532,7 @@ caLabel[statusTip="Operation"]{ 3 - AGEBD-TUNEFBX{{ agebd_env_suffix_upper }}:DELTAQ-LLIM + AGEBD-TUNEFBX@@agebd_env_suffix_upper@@:DELTAQ-LLIM caSpinbox::User @@ -3635,7 +3635,7 @@ caLabel[statusTip="Operation"]{ 2 - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:CONTROL-QY + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:CONTROL-QY caSpinbox::User @@ -3706,7 +3706,7 @@ caLabel[statusTip="Operation"]{ true - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:CONTROL-QY-OKRNG + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:CONTROL-QY-OKRNG caSpinbox::User @@ -3774,7 +3774,7 @@ caLabel[statusTip="Operation"]{ 3 - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:CONTROL-KI + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:CONTROL-KI caSpinbox::User @@ -3873,7 +3873,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:CHECK4 + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:CHECK4 @@ -3905,7 +3905,7 @@ caLabel[statusTip="Operation"]{ 3 - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:CONTROL-KP + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:CONTROL-KP caSpinbox::User @@ -3936,7 +3936,7 @@ caLabel[statusTip="Operation"]{ 2 - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:CONTROL-QYMAX + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:CONTROL-QYMAX caSpinbox::User @@ -4078,7 +4078,7 @@ caLabel[statusTip="Operation"]{ 3 - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:CONTROL-KD + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:CONTROL-KD caSpinbox::User @@ -4103,7 +4103,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:CHECK3 + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:CHECK3 @@ -4283,7 +4283,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:DELTAQ + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:DELTAQ @@ -4386,7 +4386,7 @@ caLabel[statusTip="Operation"]{ true - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:CHECKALL + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:CHECKALL @@ -4412,7 +4412,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:CHECK5 + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:CHECK5 @@ -4438,7 +4438,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:CHECK2 + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:CHECK2 @@ -4507,7 +4507,7 @@ caLabel[statusTip="Operation"]{ 2 - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:CONTROL-QYMIN + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:CONTROL-QYMIN caSpinbox::User @@ -4532,7 +4532,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:CHECK1 + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:CHECK1 @@ -4595,7 +4595,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-ALH{{ agebd_env_suffix_upper }}:TUNEFBY-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:TUNEFBY-ONOFF caChoice::Column @@ -4614,7 +4614,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:CHECK6 + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:CHECK6 @@ -4656,7 +4656,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:QSTEPS + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:QSTEPS caStripPlot::Second @@ -4897,7 +4897,7 @@ caLabel[statusTip="Operation"]{ 1 - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:CONTROL-MIN-CURR + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:CONTROL-MIN-CURR caSpinbox::User @@ -4959,7 +4959,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:CHECK7 + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:CHECK7 @@ -4985,7 +4985,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:CHECK8 + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:CHECK8 @@ -5091,7 +5091,7 @@ caLabel[statusTip="Operation"]{ 3 - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:DELTAQ-ULIM + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:DELTAQ-ULIM caSpinbox::User @@ -5122,7 +5122,7 @@ caLabel[statusTip="Operation"]{ 3 - AGEBD-TUNEFBY{{ agebd_env_suffix_upper }}:DELTAQ-LLIM + AGEBD-TUNEFBY@@agebd_env_suffix_upper@@:DELTAQ-LLIM caSpinbox::User @@ -5189,7 +5189,7 @@ caLabel[statusTip="Operation"]{ - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:WRITE2MAG + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:WRITE2MAG @@ -5241,7 +5241,7 @@ caLabel[statusTip="Operation"]{ Qt::ScrollBarAsNeeded - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:CHANGELOG + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:CHANGELOG caMultiLineString::None @@ -5277,7 +5277,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QX + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QX @@ -5359,7 +5359,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QY + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QY @@ -5472,7 +5472,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QX-SB1 + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QX-SB1 @@ -5532,7 +5532,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QX-SB1-DIFF + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QX-SB1-DIFF @@ -5629,7 +5629,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QX-SB2 + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QX-SB2 @@ -5689,7 +5689,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QX-SB2-DIFF + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QX-SB2-DIFF @@ -5860,7 +5860,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QY-SB1 + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QY-SB1 @@ -6031,7 +6031,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QY-SB2 + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QY-SB2 @@ -6091,7 +6091,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QY-SB1-DIFF + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QY-SB1-DIFF @@ -6151,7 +6151,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QY-SB2-DIFF + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QY-SB2-DIFF @@ -6223,7 +6223,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QX-FREQ + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QX-FREQ @@ -6311,7 +6311,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QY-FREQ + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QY-FREQ @@ -6423,7 +6423,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QZ + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QZ @@ -6508,7 +6508,7 @@ caLabel[statusTip="Operation"]{ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }}:QZ-FREQ + AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@:QZ-FREQ @@ -6603,7 +6603,7 @@ caLabel[statusTip="Operation"]{ A - AGEBD-ALH{{ agebd_env_suffix_upper }}:TUNEFBX-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:TUNEFBX-ONOFF @@ -6641,7 +6641,7 @@ caLabel[statusTip="Operation"]{ A - AGEBD-ALH{{ agebd_env_suffix_upper }}:TUNEFBY-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:TUNEFBY-ONOFF calabel_3 diff --git a/scripts/ci/check_subs.py b/scripts/ci/check_subs.py new file mode 100644 index 0000000..f341d9a --- /dev/null +++ b/scripts/ci/check_subs.py @@ -0,0 +1,131 @@ +""" +Guard the deploy-time substitution contract. + +Every ``@@token@@`` in this repo must be declared in config/environments.yml, +and must live somewhere that actually gets rendered. Three things are checked: + + 1. Tokens inside a render path are declared. + Catches typos, which would otherwise ship the literal placeholder. + + 2. Declared tokens only appear in a render, passthrough or reference path. + Catches a placeholder added to a file nobody renders -- exactly the + regression that put a suffix token into qt/*.ui while the Qt deploy + step was a plain rsync. + + 3. No pre-migration ``{{ token }}`` form of a deploy-time token survives, + in the paths that carry tokens. Catches files missed by the switch to + the ``@@token@@`` delimiters. Reference paths are exempt: Ansible and + copier own ``{{ }}`` in their own files, and some of their variables + share a name with our tokens. + +Files tracked by git plus new, non-ignored files are scanned, so build and +cache directories are skipped for free. +""" + +import sys + +import git +from agebd.subs import ( + SubstitutionsConfig, + find_legacy_tokens, + find_tokens, +) +from agebd.utils import get_git_root + +REPO_ROOT = get_git_root(__file__) + + +def iter_tracked_text_files(repo_root=REPO_ROOT): + """ + Yield (relative_path, contents) for every UTF-8 decodable file that is + tracked, or new and not gitignored. New files are included so that a bad + token is reported before it is committed rather than after. + """ + repo = git.Repo(repo_root) + listing = repo.git.ls_files("--cached", "--others", "--exclude-standard") + for rel_path in sorted(set(listing.splitlines())): + path = repo_root / rel_path + if not path.is_file(): + continue + try: + yield rel_path, path.read_text() + except (UnicodeDecodeError, OSError): + continue + + +def check_declared(config, rel_path, contents): + """1. Tokens inside a render path must be declared.""" + if not config.is_render_path(rel_path): + return [] + + return [ + f"{rel_path}: '@@{token}@@' is not declared under 'tokens' in " + f"{config.environments_file.name}" + for token in sorted(find_tokens(contents)) + if token not in config.tokens + ] + + +def carries_tokens(config, rel_path): + """ + True for paths whose files carry deploy-time tokens as data: they are + either rendered, or copied into something that is. + """ + return config.is_render_path(rel_path) or config.is_passthrough_path(rel_path) + + +def check_location(config, rel_path, contents): + """2. Declared tokens must sit in a render, passthrough or reference path.""" + if carries_tokens(config, rel_path) or config.is_reference_path(rel_path): + return [] + + return [ + f"{rel_path}: '@@{token}@@' is in a path that is never rendered. In " + f"{config.environments_file.name}, add the path to 'locations.render' if it " + f"should be substituted at deploy time, or to 'locations.references' if it is " + f"part of the substitution machinery. Otherwise remove the token." + for token in sorted(find_tokens(contents) & set(config.tokens)) + ] + + +def check_no_legacy_delimiters(config, rel_path, contents): + """ + 3. No deploy-time token may still use the creation-time delimiters, in the + paths that carry tokens. Elsewhere {{ }} belongs to whichever tool owns + the file. + """ + if not carries_tokens(config, rel_path): + return [] + + return [ + f"{rel_path}: '{{{{ {token} }}}}' uses the creation-time delimiters for a " + f"deploy-time token. Write it as '@@{token}@@'." + for token in sorted(find_legacy_tokens(contents) & set(config.tokens)) + ] + + +CHECKS = (check_declared, check_location, check_no_legacy_delimiters) + + +def check_subs(repo_root=REPO_ROOT): + """ + Raise AssertionError listing every violation, or return silently. + """ + config = SubstitutionsConfig.load(repo_root / "config") + + errors = [] + for rel_path, contents in iter_tracked_text_files(repo_root): + for check in CHECKS: + errors.extend(check(config, rel_path, contents)) + + if errors: + raise AssertionError("Deploy-time substitution problems found:\n\n " + "\n ".join(errors)) + + +if __name__ == "__main__": + try: + check_subs() + except AssertionError as e: + print(e, file=sys.stderr) + sys.exit(1) + print("All deploy-time tokens are declared and live in a rendered path.") diff --git a/scripts/tests/test_check_subs.py b/scripts/tests/test_check_subs.py new file mode 100644 index 0000000..e7e53af --- /dev/null +++ b/scripts/tests/test_check_subs.py @@ -0,0 +1,73 @@ +import pytest +from agebd.subs import SubstitutionsConfig +from agebd.utils import get_git_root + +from ci.check_subs import ( + check_declared, + check_location, + check_no_legacy_delimiters, + check_subs, +) + +REPO_ROOT = get_git_root(__file__) + + +@pytest.fixture +def config(): + return SubstitutionsConfig.load(REPO_ROOT / "config") + + +def test_repo_satisfies_the_substitution_contract(): + check_subs() + + +def test_undeclared_token_in_a_render_path_is_reported(config): + errors = check_declared(config, "qt/A_BD_Tune.ui", "AGEBD-TUNE@@agebd_env_sufix_upper@@:AO") + + assert len(errors) == 1 + assert "agebd_env_sufix_upper" in errors[0] + + +def test_declared_token_in_a_render_path_is_accepted(config): + assert check_declared(config, "qt/A_BD_Tune.ui", "@@agebd_env_suffix_upper@@") == [] + + +def test_token_outside_a_rendered_path_is_reported(config): + errors = check_location(config, "bin/start_service.sh", "SUFFIX=@@agebd_env_suffix_upper@@") + + assert len(errors) == 1 + assert "never rendered" in errors[0] + + +def test_token_in_a_render_path_is_accepted(config): + assert check_location(config, "qt/A_BD_Tune.ui", "@@agebd_env_suffix_upper@@") == [] + + +def test_token_in_a_passthrough_path_is_accepted(config): + assert ( + check_location( + config, + "templates/service/{{service_name_lower}}/current/ioc/x.jinja", + "@@agebd_env_suffix_upper@@", + ) + == [] + ) + + +def test_legacy_delimiters_are_reported(config): + errors = check_no_legacy_delimiters( + config, "qt/A_BD_Tune.ui", "AGEBD-TUNE{{ agebd_env_suffix_upper }}:AO" + ) + + assert len(errors) == 1 + assert "@@agebd_env_suffix_upper@@" in errors[0] + + +def test_creation_time_tokens_are_left_alone(config): + """{{ service_name_upper }} is copier's, not ours.""" + assert ( + check_no_legacy_delimiters( + config, "templates/service/x/current/ioc/y.jinja", "{{ service_name_upper }}" + ) + == [] + ) diff --git a/scripts/uv.lock b/scripts/uv.lock index 4fb18c2..0f9df6b 100644 --- a/scripts/uv.lock +++ b/scripts/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "gitpython" }, { name = "h5py" }, { name = "pyepics" }, + { name = "pyyaml" }, { name = "typer" }, ] @@ -18,6 +19,7 @@ requires-dist = [ { name = "gitpython", specifier = ">=3.1.50" }, { name = "h5py", specifier = ">=3.16.0" }, { name = "pyepics", specifier = ">=3.5.10" }, + { name = "pyyaml", specifier = ">=6.0.3" }, { name = "typer", specifier = ">=0.23.2" }, ] diff --git a/services/dbpm3curr/current/app/uv.lock b/services/dbpm3curr/current/app/uv.lock index d44abe9..c2d1df4 100644 --- a/services/dbpm3curr/current/app/uv.lock +++ b/services/dbpm3curr/current/app/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "gitpython" }, { name = "h5py" }, { name = "pyepics" }, + { name = "pyyaml" }, { name = "typer" }, ] @@ -18,6 +19,7 @@ requires-dist = [ { name = "gitpython", specifier = ">=3.1.50" }, { name = "h5py", specifier = ">=3.16.0" }, { name = "pyepics", specifier = ">=3.5.10" }, + { name = "pyyaml", specifier = ">=6.0.3" }, { name = "typer", specifier = ">=0.23.2" }, ] @@ -284,6 +286,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, ] +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, +] + [[package]] name = "rich" version = "15.0.0" diff --git a/services/dbpm3curr/current/ioc/AGEBD-CPCL-DBPM3CURR_main.subs b/services/dbpm3curr/current/ioc/AGEBD-CPCL-DBPM3CURR_main.subs index 9bd8726..0c8c4c7 100644 --- a/services/dbpm3curr/current/ioc/AGEBD-CPCL-DBPM3CURR_main.subs +++ b/services/dbpm3curr/current/ioc/AGEBD-CPCL-DBPM3CURR_main.subs @@ -1,4 +1,4 @@ file DBPM3CURR.template { pattern { DEVICE } - { AGEBD-DBPM3CURR{{ agebd_env_suffix_upper }} } + { AGEBD-DBPM3CURR@@agebd_env_suffix_upper@@ } } diff --git a/services/dbpm3curr/current/ioc/AGEBD-CPCL-DBPM3CURR_parameters.yaml b/services/dbpm3curr/current/ioc/AGEBD-CPCL-DBPM3CURR_parameters.yaml index c179f0d..24aa364 100644 --- a/services/dbpm3curr/current/ioc/AGEBD-CPCL-DBPM3CURR_parameters.yaml +++ b/services/dbpm3curr/current/ioc/AGEBD-CPCL-DBPM3CURR_parameters.yaml @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ agebd_env_suffix_lower }} -ioc_port: {{ ioc_port }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/services/dbpm3curr/current/systemd/AGEBD-SERVICE-DBPM3CURR.service b/services/dbpm3curr/current/systemd/AGEBD-SERVICE-DBPM3CURR.service index dc46bb9..800fe42 100644 --- a/services/dbpm3curr/current/systemd/AGEBD-SERVICE-DBPM3CURR.service +++ b/services/dbpm3curr/current/systemd/AGEBD-SERVICE-DBPM3CURR.service @@ -3,9 +3,9 @@ Description=AGEBD-SERVICE-DBPM3CURR After=network.target [Service] -Environment=AGEBD_ENV={{ agebd_env }} +Environment=AGEBD_ENV=@@agebd_env@@ Environment=PYTHONUNBUFFERED=1 -ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh DBPM3CURR +ExecStart=/sls/bd/hla/@@agebd_env@@/bin/start_service.sh DBPM3CURR Restart=no [Install] diff --git a/services/injectionguard/current/app/uv.lock b/services/injectionguard/current/app/uv.lock index dc5c6b5..67f7f0c 100644 --- a/services/injectionguard/current/app/uv.lock +++ b/services/injectionguard/current/app/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "gitpython" }, { name = "h5py" }, { name = "pyepics" }, + { name = "pyyaml" }, { name = "typer" }, ] @@ -18,6 +19,7 @@ requires-dist = [ { name = "gitpython", specifier = ">=3.1.50" }, { name = "h5py", specifier = ">=3.16.0" }, { name = "pyepics", specifier = ">=3.5.10" }, + { name = "pyyaml", specifier = ">=6.0.3" }, { name = "typer", specifier = ">=0.23.2" }, ] @@ -284,6 +286,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, ] +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, +] + [[package]] name = "rich" version = "15.0.0" diff --git a/services/injectionguard/current/ioc/AGEBD-CPCL-INJECTIONGUARD_main.subs b/services/injectionguard/current/ioc/AGEBD-CPCL-INJECTIONGUARD_main.subs index 28c92a4..ff29124 100644 --- a/services/injectionguard/current/ioc/AGEBD-CPCL-INJECTIONGUARD_main.subs +++ b/services/injectionguard/current/ioc/AGEBD-CPCL-INJECTIONGUARD_main.subs @@ -1,31 +1,31 @@ file INJECTIONGUARD_individual.template { pattern { DEVICE } - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} } + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ } } file INJECTIONGUARD_automated.template { pattern { DEVICE NR Latch Description } - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 01 1 "Beam Dump Kicker"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 02 1 "Dump Valve"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 03 1 "MIS"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 04 1 "VCS"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 05 1 "Linac KV/BB/BY"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 06 1 "RF Linac"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 07 1 "RF Booster"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 08 1 "RF Ring"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 09 1 "Magnets Pulsed"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 10 1 "Magnets Booster"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 11 1 "Magnets Corrector"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 12 1 "Magnets Ring"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 13 1 "Current Limit"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 14 1 "IDs Ready"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 15 1 "Single Bunch Charge"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 16 1 "Injection Quality"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 17 1 "Dump Quality"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 18 1 "Lifetime"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 19 1 "Tune"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 20 0 "Pingers"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 21 1 "Vacuum Pressure"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 22 1 "Orbit Deviation"} - { AGEBD-INJECTIONGUARD{{ agebd_env_suffix_upper }} 23 1 "Beam Dump Controller"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 01 1 "Beam Dump Kicker"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 02 1 "Dump Valve"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 03 1 "MIS"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 04 1 "VCS"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 05 1 "Linac KV/BB/BY"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 06 1 "RF Linac"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 07 1 "RF Booster"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 08 1 "RF Ring"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 09 1 "Magnets Pulsed"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 10 1 "Magnets Booster"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 11 1 "Magnets Corrector"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 12 1 "Magnets Ring"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 13 1 "Current Limit"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 14 1 "IDs Ready"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 15 1 "Single Bunch Charge"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 16 1 "Injection Quality"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 17 1 "Dump Quality"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 18 1 "Lifetime"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 19 1 "Tune"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 20 0 "Pingers"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 21 1 "Vacuum Pressure"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 22 1 "Orbit Deviation"} + { AGEBD-INJECTIONGUARD@@agebd_env_suffix_upper@@ 23 1 "Beam Dump Controller"} } diff --git a/services/injectionguard/current/ioc/AGEBD-CPCL-INJECTIONGUARD_parameters.yaml b/services/injectionguard/current/ioc/AGEBD-CPCL-INJECTIONGUARD_parameters.yaml index c179f0d..24aa364 100644 --- a/services/injectionguard/current/ioc/AGEBD-CPCL-INJECTIONGUARD_parameters.yaml +++ b/services/injectionguard/current/ioc/AGEBD-CPCL-INJECTIONGUARD_parameters.yaml @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ agebd_env_suffix_lower }} -ioc_port: {{ ioc_port }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/services/injectionguard/current/systemd/AGEBD-SERVICE-INJECTIONGUARD.service b/services/injectionguard/current/systemd/AGEBD-SERVICE-INJECTIONGUARD.service index 64f6675..007f32a 100644 --- a/services/injectionguard/current/systemd/AGEBD-SERVICE-INJECTIONGUARD.service +++ b/services/injectionguard/current/systemd/AGEBD-SERVICE-INJECTIONGUARD.service @@ -3,9 +3,9 @@ Description=AGEBD-SERVICE-INJECTIONGUARD After=network.target [Service] -Environment=AGEBD_ENV={{ agebd_env }} +Environment=AGEBD_ENV=@@agebd_env@@ Environment=PYTHONUNBUFFERED=1 -ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh INJECTIONGUARD +ExecStart=/sls/bd/hla/@@agebd_env@@/bin/start_service.sh INJECTIONGUARD Restart=no [Install] diff --git a/services/master/current/app/uv.lock b/services/master/current/app/uv.lock index 7118582..9bd84ca 100644 --- a/services/master/current/app/uv.lock +++ b/services/master/current/app/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "gitpython" }, { name = "h5py" }, { name = "pyepics" }, + { name = "pyyaml" }, { name = "typer" }, ] @@ -18,6 +19,7 @@ requires-dist = [ { name = "gitpython", specifier = ">=3.1.50" }, { name = "h5py", specifier = ">=3.16.0" }, { name = "pyepics", specifier = ">=3.5.10" }, + { name = "pyyaml", specifier = ">=6.0.3" }, { name = "typer", specifier = ">=0.23.2" }, ] diff --git a/services/master/current/ioc/AGEBD-CPCL-MASTER_main.subs b/services/master/current/ioc/AGEBD-CPCL-MASTER_main.subs index 6fa7099..7c80682 100644 --- a/services/master/current/ioc/AGEBD-CPCL-MASTER_main.subs +++ b/services/master/current/ioc/AGEBD-CPCL-MASTER_main.subs @@ -1,32 +1,32 @@ file MASTER.template { pattern { SUFFIX SERVICE STARTON AUTOOFF } - { "{{ agebd_env_suffix_upper }}", "MASTER" , "0", "30" } - { "{{ agebd_env_suffix_upper }}", "NTURNS" , "0", "0" } - { "{{ agebd_env_suffix_upper }}", "DBPM3CURR" , "1", "0" } - { "{{ agebd_env_suffix_upper }}", "TAUBPM" , "1", "0" } - { "{{ agebd_env_suffix_upper }}", "TAUPCT" , "1", "0" } - { "{{ agebd_env_suffix_upper }}", "SCRUBBING" , "1", "0" } - { "{{ agebd_env_suffix_upper }}", "TIMING" , "0", "0" } - { "{{ agebd_env_suffix_upper }}", "TUNE" , "1", "0" } - { "{{ agebd_env_suffix_upper }}", "INJECTIONGUARD" , "1", "0" } - { "{{ agebd_env_suffix_upper }}", "POSTMORTEMLOG" , "1", "0" } - { "{{ agebd_env_suffix_upper }}", "TUNEBUMP" , "1", "0" } - { "{{ agebd_env_suffix_upper }}", "PLOTS" , "0", "0" } - { "{{ agebd_env_suffix_upper }}", "ORBITBUMP" , "0", "0" } - { "{{ agebd_env_suffix_upper }}", "TOPUPTOOL" , "0", "0" } - { "{{ agebd_env_suffix_upper }}", "SHIFTTOOL" , "1", "0" } - { "{{ agebd_env_suffix_upper }}", "BEAMTRANSFERCHECKS" , "0", "0" } - { "{{ agebd_env_suffix_upper }}", "TUNEFBX" , "0", "0" } - { "{{ agebd_env_suffix_upper }}", "TUNEFBY" , "0", "0" } - { "{{ agebd_env_suffix_upper }}", "OPTICSFF-X02S" , "0", "0" } # I-TOMCAT - { "{{ agebd_env_suffix_upper }}", "OPTICSFF-X03M" , "0", "0" } # ADRESS - { "{{ agebd_env_suffix_upper }}", "OPTICSFF-X04S" , "0", "0" } # ADDAMS - { "{{ agebd_env_suffix_upper }}", "OPTICSFF-X05L" , "0", "0" } # QUEST - { "{{ agebd_env_suffix_upper }}", "OPTICSFF-X06S" , "0", "0" } # PXI - { "{{ agebd_env_suffix_upper }}", "OPTICSFF-X07M" , "0", "0" } # PHOENIX/XTREME - { "{{ agebd_env_suffix_upper }}", "OPTICSFF-X08S" , "0", "0" } # MicroXAS - { "{{ agebd_env_suffix_upper }}", "OPTICSFF-X09L" , "0", "0" } # OPERA - { "{{ agebd_env_suffix_upper }}", "OPTICSFF-X10S" , "0", "0" } # PXII - { "{{ agebd_env_suffix_upper }}", "OPTICSFF-X11M" , "0", "0" } # SIM - { "{{ agebd_env_suffix_upper }}", "OPTICSFF-X12S" , "0", "0" } # cSAXS + { "@@agebd_env_suffix_upper@@", "MASTER" , "0", "30" } + { "@@agebd_env_suffix_upper@@", "NTURNS" , "0", "0" } + { "@@agebd_env_suffix_upper@@", "DBPM3CURR" , "1", "0" } + { "@@agebd_env_suffix_upper@@", "TAUBPM" , "1", "0" } + { "@@agebd_env_suffix_upper@@", "TAUPCT" , "1", "0" } + { "@@agebd_env_suffix_upper@@", "SCRUBBING" , "1", "0" } + { "@@agebd_env_suffix_upper@@", "TIMING" , "0", "0" } + { "@@agebd_env_suffix_upper@@", "TUNE" , "1", "0" } + { "@@agebd_env_suffix_upper@@", "INJECTIONGUARD" , "1", "0" } + { "@@agebd_env_suffix_upper@@", "POSTMORTEMLOG" , "1", "0" } + { "@@agebd_env_suffix_upper@@", "TUNEBUMP" , "1", "0" } + { "@@agebd_env_suffix_upper@@", "PLOTS" , "0", "0" } + { "@@agebd_env_suffix_upper@@", "ORBITBUMP" , "0", "0" } + { "@@agebd_env_suffix_upper@@", "TOPUPTOOL" , "0", "0" } + { "@@agebd_env_suffix_upper@@", "SHIFTTOOL" , "1", "0" } + { "@@agebd_env_suffix_upper@@", "BEAMTRANSFERCHECKS" , "0", "0" } + { "@@agebd_env_suffix_upper@@", "TUNEFBX" , "0", "0" } + { "@@agebd_env_suffix_upper@@", "TUNEFBY" , "0", "0" } + { "@@agebd_env_suffix_upper@@", "OPTICSFF-X02S" , "0", "0" } # I-TOMCAT + { "@@agebd_env_suffix_upper@@", "OPTICSFF-X03M" , "0", "0" } # ADRESS + { "@@agebd_env_suffix_upper@@", "OPTICSFF-X04S" , "0", "0" } # ADDAMS + { "@@agebd_env_suffix_upper@@", "OPTICSFF-X05L" , "0", "0" } # QUEST + { "@@agebd_env_suffix_upper@@", "OPTICSFF-X06S" , "0", "0" } # PXI + { "@@agebd_env_suffix_upper@@", "OPTICSFF-X07M" , "0", "0" } # PHOENIX/XTREME + { "@@agebd_env_suffix_upper@@", "OPTICSFF-X08S" , "0", "0" } # MicroXAS + { "@@agebd_env_suffix_upper@@", "OPTICSFF-X09L" , "0", "0" } # OPERA + { "@@agebd_env_suffix_upper@@", "OPTICSFF-X10S" , "0", "0" } # PXII + { "@@agebd_env_suffix_upper@@", "OPTICSFF-X11M" , "0", "0" } # SIM + { "@@agebd_env_suffix_upper@@", "OPTICSFF-X12S" , "0", "0" } # cSAXS } diff --git a/services/master/current/ioc/AGEBD-CPCL-MASTER_parameters.yaml b/services/master/current/ioc/AGEBD-CPCL-MASTER_parameters.yaml index c179f0d..24aa364 100644 --- a/services/master/current/ioc/AGEBD-CPCL-MASTER_parameters.yaml +++ b/services/master/current/ioc/AGEBD-CPCL-MASTER_parameters.yaml @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ agebd_env_suffix_lower }} -ioc_port: {{ ioc_port }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/services/master/current/systemd/AGEBD-SERVICE-MASTER.service b/services/master/current/systemd/AGEBD-SERVICE-MASTER.service index aea7b97..490eefe 100644 --- a/services/master/current/systemd/AGEBD-SERVICE-MASTER.service +++ b/services/master/current/systemd/AGEBD-SERVICE-MASTER.service @@ -3,9 +3,9 @@ Description=AGEBD-SERVICE-MASTER After=network.target [Service] -Environment=AGEBD_ENV={{ agebd_env }} +Environment=AGEBD_ENV=@@agebd_env@@ Environment=PYTHONUNBUFFERED=1 -ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh MASTER +ExecStart=/sls/bd/hla/@@agebd_env@@/bin/start_service.sh MASTER Restart=no [Install] diff --git a/services/nturns/current/app/uv.lock b/services/nturns/current/app/uv.lock index 1f79ca4..46026f6 100644 --- a/services/nturns/current/app/uv.lock +++ b/services/nturns/current/app/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "gitpython" }, { name = "h5py" }, { name = "pyepics" }, + { name = "pyyaml" }, { name = "typer" }, ] @@ -18,6 +19,7 @@ requires-dist = [ { name = "gitpython", specifier = ">=3.1.50" }, { name = "h5py", specifier = ">=3.16.0" }, { name = "pyepics", specifier = ">=3.5.10" }, + { name = "pyyaml", specifier = ">=6.0.3" }, { name = "typer", specifier = ">=0.23.2" }, ] @@ -286,6 +288,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, ] +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, +] + [[package]] name = "rich" version = "15.0.0" diff --git a/services/nturns/current/ioc/AGEBD-CPCL-NTURNS_main.subs b/services/nturns/current/ioc/AGEBD-CPCL-NTURNS_main.subs index 8a6d076..708f2e9 100644 --- a/services/nturns/current/ioc/AGEBD-CPCL-NTURNS_main.subs +++ b/services/nturns/current/ioc/AGEBD-CPCL-NTURNS_main.subs @@ -1,4 +1,4 @@ file NTURNS.template { pattern { DEVICE } - { AGEBD-NTURNS{{ agebd_env_suffix_upper }} } + { AGEBD-NTURNS@@agebd_env_suffix_upper@@ } } diff --git a/services/nturns/current/ioc/AGEBD-CPCL-NTURNS_parameters.yaml b/services/nturns/current/ioc/AGEBD-CPCL-NTURNS_parameters.yaml index c179f0d..24aa364 100644 --- a/services/nturns/current/ioc/AGEBD-CPCL-NTURNS_parameters.yaml +++ b/services/nturns/current/ioc/AGEBD-CPCL-NTURNS_parameters.yaml @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ agebd_env_suffix_lower }} -ioc_port: {{ ioc_port }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/services/nturns/current/systemd/AGEBD-SERVICE-NTURNS.service b/services/nturns/current/systemd/AGEBD-SERVICE-NTURNS.service index 93bc014..cf91666 100644 --- a/services/nturns/current/systemd/AGEBD-SERVICE-NTURNS.service +++ b/services/nturns/current/systemd/AGEBD-SERVICE-NTURNS.service @@ -3,9 +3,9 @@ Description=AGEBD-SERVICE-NTURNS After=network.target [Service] -Environment=AGEBD_ENV={{ agebd_env }} +Environment=AGEBD_ENV=@@agebd_env@@ Environment=PYTHONUNBUFFERED=1 -ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh NTURNS +ExecStart=/sls/bd/hla/@@agebd_env@@/bin/start_service.sh NTURNS Restart=no [Install] diff --git a/services/orbitbump/current/ioc/AGEBD-CPCL-ORBITBUMP_main.subs b/services/orbitbump/current/ioc/AGEBD-CPCL-ORBITBUMP_main.subs index 710b532..286591d 100644 --- a/services/orbitbump/current/ioc/AGEBD-CPCL-ORBITBUMP_main.subs +++ b/services/orbitbump/current/ioc/AGEBD-CPCL-ORBITBUMP_main.subs @@ -2,31 +2,31 @@ file ORBITBUMP_machine.template { pattern {DEVICE sourcepoint beamline LOX HIX X LOXP HIXP XP LOY HIY Y LOYP HIYP YP BPM1 C1xx C1xpx C1yy C1ypy BPM2 C2xx C2xpx C2yy C2ypy BPM3 C3xx C3xpx C3yy C3ypy BPM4 C4xx C4xpx C4yy C4ypy} # Diagnostic dipole beamlines - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X01DD NEMO -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS01-DBPM-1080 -0.0009920 -0.0006308 -0.0001141 0.0001109 ARS01-DBPM-1460 0.9742755 -0.1432472 0.9455447 -0.0865934 ARS01-DBPM-1900 0.9277200 1.0454287 0.1445141 1.5920941 ARS01-DBPM-2410 -0.0809412 -0.0384293 0.0058229 0.1036650} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X08DB DISCO -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS08-DBPM-1900 -0.2500389 -0.0365053 0.0001023 0.0000595 ARS08-DBPM-2410 1.2775662 -0.9246414 0.5814965 -0.4999301 ARS08-DBPM-2910 0.6885552 0.9211364 0.4873898 1.7550023 ARS08-DBPM-4220 -0.2391394 -0.0169593 0.0309046 0.1234665} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X10DG X11HEAT -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS10-DBPM-4720 -0.0187 -0.0188 0 0 ARS10-DBPM-5250 1.6016 -1.2108 0.5496 -0.5376 ARS10-DBPM-5880 0.7075 1.0654 1.1093 1.9515 ARS11-DBPM-0850 0.0026 0.0044 0.0166 0.0304} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X01DD NEMO -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS01-DBPM-1080 -0.0009920 -0.0006308 -0.0001141 0.0001109 ARS01-DBPM-1460 0.9742755 -0.1432472 0.9455447 -0.0865934 ARS01-DBPM-1900 0.9277200 1.0454287 0.1445141 1.5920941 ARS01-DBPM-2410 -0.0809412 -0.0384293 0.0058229 0.1036650} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X08DB DISCO -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS08-DBPM-1900 -0.2500389 -0.0365053 0.0001023 0.0000595 ARS08-DBPM-2410 1.2775662 -0.9246414 0.5814965 -0.4999301 ARS08-DBPM-2910 0.6885552 0.9211364 0.4873898 1.7550023 ARS08-DBPM-4220 -0.2391394 -0.0169593 0.0309046 0.1234665} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X10DG X11HEAT -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS10-DBPM-4720 -0.0187 -0.0188 0 0 ARS10-DBPM-5250 1.6016 -1.2108 0.5496 -0.5376 ARS10-DBPM-5880 0.7075 1.0654 1.1093 1.9515 ARS11-DBPM-0850 0.0026 0.0044 0.0166 0.0304} # User dipole beamlines - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X01DA DEBYE -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS01-DBPM-2410 -0.2169694 -0.0006291 0.0001170 0.0000325 ARS01-DBPM-2910 1.2765938 -0.9208697 0.5792863 -0.5011470 ARS01-DBPM-4220 0.6866207 0.9198858 0.4842977 1.7595080 ARS01-DBPM-4720 -0.1924402 0.0258918 0.0307458 0.1239361} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X02DA S-TOMCAT -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS02-DBPM-2410 -0.2089937 0.0072435 0.0001169 0.0000325 ARS02-DBPM-2910 1.2772588 -0.9200089 0.5792866 -0.5011606 ARS02-DBPM-4220 0.6864959 0.9194778 0.4843170 1.7595616 ARS02-DBPM-4720 -0.1833930 0.0352770 0.0307471 0.1239392} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X03DA PEARL -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS03-DBPM-2410 -0.2016647 0.0152728 0.0001171 0.0000326 ARS03-DBPM-2910 1.2831552 -0.9190247 0.5819894 -0.5004911 ARS03-DBPM-4220 0.6905553 0.9206615 0.4875028 1.7552635 ARS03-DBPM-4720 -0.1749243 0.0438144 0.0309089 0.1234182} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X04DB VUV -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS04-DBPM-1900 -0.1917962 0.0214714 0.0001022 0.0000595 ARS04-DBPM-2410 1.2842031 -0.9179380 0.5814999 -0.5000284 ARS04-DBPM-2910 0.6887599 0.9211626 0.4874732 1.7553295 ARS04-DBPM-4220 -0.1710439 0.0514609 0.0309080 0.1234788} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X05DA Optics -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS05-DBPM-2410 -0.2740176 -0.0571105 0.0001170 0.0000321 ARS05-DBPM-2910 1.2732647 -0.9287209 0.5819890 -0.5003730 ARS05-DBPM-4220 0.6913367 0.9213802 0.4873370 1.7548006 ARS05-DBPM-4720 -0.2592981 -0.0408063 0.0308988 0.1233928} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X06DA PXIII -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS06-DBPM-2410 -0.2675305 -0.0508248 0.0001170 0.0000321 ARS06-DBPM-2910 1.2749858 -0.9266845 0.5818007 -0.5004548 ARS06-DBPM-4220 0.6916389 0.9218001 0.4871613 1.7552275 ARS06-DBPM-4720 -0.2517260 -0.0332473 0.0308895 0.1234316} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X07DB nanoXAS -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS07-DBPM-1900 -0.2563387 -0.0425222 0.0001023 0.0000596 ARS07-DBPM-2410 1.2761628 -0.9263027 0.5814954 -0.4999177 ARS07-DBPM-2910 0.6888233 0.9216262 0.4873810 1.7549631 ARS07-DBPM-4220 -0.2469055 -0.0248794 0.0309043 0.1234651} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X07DA PolLux -300 300 0 -150 150 0 -300 300 0 -250 250 0 ARS07-DBPM-2410 -0.2606076 -0.0450539 0.0001170 0.0000326 ARS07-DBPM-2910 1.2750718 -0.9205684 0.5819899 -0.4976199 ARS07-DBPM-4220 0.6915728 0.9246379 0.4873668 1.7572153 ARS07-DBPM-4720 -0.2433555 -0.0254434 0.0309006 0.1235450} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X10DA SuperXAS -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS10-DBPM-2410 -0.2392400 -0.0226765 0.0001170 0.0000321 ARS10-DBPM-2910 1.2780895 -0.9235140 0.5818007 -0.5005005 ARS10-DBPM-4220 0.6911875 0.9212713 0.4872251 1.7554059 ARS10-DBPM-4720 -0.2190626 -0.0004438 0.0308933 0.1234413} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X01DA DEBYE -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS01-DBPM-2410 -0.2169694 -0.0006291 0.0001170 0.0000325 ARS01-DBPM-2910 1.2765938 -0.9208697 0.5792863 -0.5011470 ARS01-DBPM-4220 0.6866207 0.9198858 0.4842977 1.7595080 ARS01-DBPM-4720 -0.1924402 0.0258918 0.0307458 0.1239361} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X02DA S-TOMCAT -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS02-DBPM-2410 -0.2089937 0.0072435 0.0001169 0.0000325 ARS02-DBPM-2910 1.2772588 -0.9200089 0.5792866 -0.5011606 ARS02-DBPM-4220 0.6864959 0.9194778 0.4843170 1.7595616 ARS02-DBPM-4720 -0.1833930 0.0352770 0.0307471 0.1239392} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X03DA PEARL -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS03-DBPM-2410 -0.2016647 0.0152728 0.0001171 0.0000326 ARS03-DBPM-2910 1.2831552 -0.9190247 0.5819894 -0.5004911 ARS03-DBPM-4220 0.6905553 0.9206615 0.4875028 1.7552635 ARS03-DBPM-4720 -0.1749243 0.0438144 0.0309089 0.1234182} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X04DB VUV -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS04-DBPM-1900 -0.1917962 0.0214714 0.0001022 0.0000595 ARS04-DBPM-2410 1.2842031 -0.9179380 0.5814999 -0.5000284 ARS04-DBPM-2910 0.6887599 0.9211626 0.4874732 1.7553295 ARS04-DBPM-4220 -0.1710439 0.0514609 0.0309080 0.1234788} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X05DA Optics -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS05-DBPM-2410 -0.2740176 -0.0571105 0.0001170 0.0000321 ARS05-DBPM-2910 1.2732647 -0.9287209 0.5819890 -0.5003730 ARS05-DBPM-4220 0.6913367 0.9213802 0.4873370 1.7548006 ARS05-DBPM-4720 -0.2592981 -0.0408063 0.0308988 0.1233928} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X06DA PXIII -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS06-DBPM-2410 -0.2675305 -0.0508248 0.0001170 0.0000321 ARS06-DBPM-2910 1.2749858 -0.9266845 0.5818007 -0.5004548 ARS06-DBPM-4220 0.6916389 0.9218001 0.4871613 1.7552275 ARS06-DBPM-4720 -0.2517260 -0.0332473 0.0308895 0.1234316} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X07DB nanoXAS -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS07-DBPM-1900 -0.2563387 -0.0425222 0.0001023 0.0000596 ARS07-DBPM-2410 1.2761628 -0.9263027 0.5814954 -0.4999177 ARS07-DBPM-2910 0.6888233 0.9216262 0.4873810 1.7549631 ARS07-DBPM-4220 -0.2469055 -0.0248794 0.0309043 0.1234651} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X07DA PolLux -300 300 0 -150 150 0 -300 300 0 -250 250 0 ARS07-DBPM-2410 -0.2606076 -0.0450539 0.0001170 0.0000326 ARS07-DBPM-2910 1.2750718 -0.9205684 0.5819899 -0.4976199 ARS07-DBPM-4220 0.6915728 0.9246379 0.4873668 1.7572153 ARS07-DBPM-4720 -0.2433555 -0.0254434 0.0309006 0.1235450} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X10DA SuperXAS -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS10-DBPM-2410 -0.2392400 -0.0226765 0.0001170 0.0000321 ARS10-DBPM-2910 1.2780895 -0.9235140 0.5818007 -0.5005005 ARS10-DBPM-4220 0.6911875 0.9212713 0.4872251 1.7554059 ARS10-DBPM-4720 -0.2190626 -0.0004438 0.0308933 0.1234413} # ID beamlines - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X02SA I-TOMCAT -500 500 0 -150 150 0 -500 500 0 -150 150 0 ARS01-DBPM-5250 -0.0161762 0.0645315 -0.0000522 0.0002217 ARS01-DBPM-5880 1.3057217 -3.1586368 0.7340909 -1.7908669 ARS02-DBPM-1080 1.1637103 2.7703664 0.8405251 2.0415012 ARS02-DBPM-1460 0.0473369 0.1176477 0.0354851 0.0914118} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X03MA ADRESS -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS02-DBPM-5250 -0.0056074 0.0805576 -0.0000533 0.0001427 ARS02-DBPM-5880 1.2522257 -3.5240592 0.7649336 -2.1576328 ARS03-DBPM-0810 1.1134798 3.0406278 0.8874945 2.4488073 ARS03-DBPM-1080 0.0367597 0.0902093 0.0491615 0.1421129} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X04SA ADDAMS -500 500 0 -150 150 0 -500 500 0 -150 150 0 ARS03-DBPM-5250 0.0006041 0.0811354 -0.0000524 0.0002222 ARS03-DBPM-5880 1.3048037 -3.1594991 0.7340820 -1.7909262 ARS04-DBPM-1080 1.1649402 2.7718322 0.8405182 2.0415768 ARS04-DBPM-1460 0.0441826 0.1145073 0.0354841 0.0914133} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X05LA QUEST -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS04-DBPM-5880 0.0008866 0.0002252 -0.0001045 0.0002529 ARS05-DBPM-0410 0.8976150 -2.8499257 1.0112790 -2.8592349 ARS05-DBPM-1080 1.0880889 5.0183256 0.9137175 4.2390359 ARS05-DBPM-1460 0.0421489 0.1947713 0.0433357 0.2067705} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X06SA PXI -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS05-DBPM-5250 -0.0776973 0.0030268 -0.0000523 0.0002212 ARS05-DBPM-5880 1.3044906 -3.1590695 0.7341239 -1.7906420 ARS06-DBPM-1080 1.1642809 2.7699897 0.8405515 2.0412179 ARS06-DBPM-1460 0.0604868 0.1306028 0.0354886 0.0914055} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X07MA Phoenix/XTreme -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS06-DBPM-5250 -0.0684380 0.0189547 -0.0000531 0.0001447 ARS06-DBPM-5880 1.2508776 -3.5845660 0.7649630 -2.1939024 ARS07-DBPM-0810 1.1137188 2.9863773 0.8875136 2.4060190 ARS07-DBPM-1080 0.0093629 0.0606390 0.0491634 0.1397441} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X08SA micro-XAS -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS07-DBPM-5250 -0.0624701 0.0181621 -0.0000523 0.0002216 ARS07-DBPM-5880 1.3039931 -3.1597229 0.7341156 -1.7906968 ARS08-DBPM-1080 1.1652753 2.7714013 0.8405450 2.0412871 ARS08-DBPM-1460 0.0575855 0.1278140 0.0354876 0.0914065} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X09LA PEARL/XIL-II -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS08-DBPM-5880 0.0011254 0.0009724 -0.0000942 0.0002317 ARS09-DBPM-0570 0.8843735 -2.4344684 1.1263977 -3.0082085 ARS09-DBPM-1080 1.0591734 3.0395499 0.9413643 2.7184391 ARS09-DBPM-1460 0.0394021 0.1139547 0.0465775 0.1402264} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X10SA PXII -500 500 0 -150 150 0 -500 500 0 -150 150 0 ARS09-DBPM-5250 -0.0473875 0.0333454 -0.0000523 0.0002213 ARS09-DBPM-5880 1.3047178 -3.1592507 0.7341077 -1.7907518 ARS10-DBPM-1080 1.1639981 2.7701547 0.8405387 2.0413565 ARS10-DBPM-1460 0.0540084 0.1242161 0.0354869 0.0914087} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X11MA SIM -500 500 0 -150 150 0 -500 500 0 -150 150 0 ARS10-DBPM-5250 -0.0383667 0.0514782 -0.0000499 0.0001646 ARS10-DBPM-5880 1.2526899 -3.7342542 0.7640638 -2.2804441 ARS11-DBPM-0850 1.1168967 3.1441871 0.8845808 2.5170397 ARS11-DBPM-1080 0.0219427 0.0928506 0.0546028 0.1626088} - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X12SA cSAXS -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS11-DBPM-5250 -0.0326376 0.0479239 -0.0000524 0.0002219 ARS11-DBPM-5880 1.3047910 -3.1591765 0.7340995 -1.7908066 ARS12-DBPM-1080 1.1653151 2.7718178 0.8405322 2.0414257 ARS12-DBPM-1460 0.0513287 0.1216036 0.0354860 0.0914097} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X02SA I-TOMCAT -500 500 0 -150 150 0 -500 500 0 -150 150 0 ARS01-DBPM-5250 -0.0161762 0.0645315 -0.0000522 0.0002217 ARS01-DBPM-5880 1.3057217 -3.1586368 0.7340909 -1.7908669 ARS02-DBPM-1080 1.1637103 2.7703664 0.8405251 2.0415012 ARS02-DBPM-1460 0.0473369 0.1176477 0.0354851 0.0914118} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X03MA ADRESS -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS02-DBPM-5250 -0.0056074 0.0805576 -0.0000533 0.0001427 ARS02-DBPM-5880 1.2522257 -3.5240592 0.7649336 -2.1576328 ARS03-DBPM-0810 1.1134798 3.0406278 0.8874945 2.4488073 ARS03-DBPM-1080 0.0367597 0.0902093 0.0491615 0.1421129} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X04SA ADDAMS -500 500 0 -150 150 0 -500 500 0 -150 150 0 ARS03-DBPM-5250 0.0006041 0.0811354 -0.0000524 0.0002222 ARS03-DBPM-5880 1.3048037 -3.1594991 0.7340820 -1.7909262 ARS04-DBPM-1080 1.1649402 2.7718322 0.8405182 2.0415768 ARS04-DBPM-1460 0.0441826 0.1145073 0.0354841 0.0914133} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X05LA QUEST -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS04-DBPM-5880 0.0008866 0.0002252 -0.0001045 0.0002529 ARS05-DBPM-0410 0.8976150 -2.8499257 1.0112790 -2.8592349 ARS05-DBPM-1080 1.0880889 5.0183256 0.9137175 4.2390359 ARS05-DBPM-1460 0.0421489 0.1947713 0.0433357 0.2067705} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X06SA PXI -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS05-DBPM-5250 -0.0776973 0.0030268 -0.0000523 0.0002212 ARS05-DBPM-5880 1.3044906 -3.1590695 0.7341239 -1.7906420 ARS06-DBPM-1080 1.1642809 2.7699897 0.8405515 2.0412179 ARS06-DBPM-1460 0.0604868 0.1306028 0.0354886 0.0914055} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X07MA Phoenix/XTreme -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS06-DBPM-5250 -0.0684380 0.0189547 -0.0000531 0.0001447 ARS06-DBPM-5880 1.2508776 -3.5845660 0.7649630 -2.1939024 ARS07-DBPM-0810 1.1137188 2.9863773 0.8875136 2.4060190 ARS07-DBPM-1080 0.0093629 0.0606390 0.0491634 0.1397441} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X08SA micro-XAS -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS07-DBPM-5250 -0.0624701 0.0181621 -0.0000523 0.0002216 ARS07-DBPM-5880 1.3039931 -3.1597229 0.7341156 -1.7906968 ARS08-DBPM-1080 1.1652753 2.7714013 0.8405450 2.0412871 ARS08-DBPM-1460 0.0575855 0.1278140 0.0354876 0.0914065} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X09LA PEARL/XIL-II -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS08-DBPM-5880 0.0011254 0.0009724 -0.0000942 0.0002317 ARS09-DBPM-0570 0.8843735 -2.4344684 1.1263977 -3.0082085 ARS09-DBPM-1080 1.0591734 3.0395499 0.9413643 2.7184391 ARS09-DBPM-1460 0.0394021 0.1139547 0.0465775 0.1402264} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X10SA PXII -500 500 0 -150 150 0 -500 500 0 -150 150 0 ARS09-DBPM-5250 -0.0473875 0.0333454 -0.0000523 0.0002213 ARS09-DBPM-5880 1.3047178 -3.1592507 0.7341077 -1.7907518 ARS10-DBPM-1080 1.1639981 2.7701547 0.8405387 2.0413565 ARS10-DBPM-1460 0.0540084 0.1242161 0.0354869 0.0914087} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X11MA SIM -500 500 0 -150 150 0 -500 500 0 -150 150 0 ARS10-DBPM-5250 -0.0383667 0.0514782 -0.0000499 0.0001646 ARS10-DBPM-5880 1.2526899 -3.7342542 0.7640638 -2.2804441 ARS11-DBPM-0850 1.1168967 3.1441871 0.8845808 2.5170397 ARS11-DBPM-1080 0.0219427 0.0928506 0.0546028 0.1626088} + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X12SA cSAXS -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS11-DBPM-5250 -0.0326376 0.0479239 -0.0000524 0.0002219 ARS11-DBPM-5880 1.3047910 -3.1591765 0.7340995 -1.7908066 ARS12-DBPM-1080 1.1653151 2.7718178 0.8405322 2.0414257 ARS12-DBPM-1460 0.0513287 0.1216036 0.0354860 0.0914097} } @@ -34,29 +34,29 @@ file ORBITBUMP_beamline.template { pattern {DEVICE sourcepoint beamline DRVL DRVH X XP Y YP } # Diagnostic dipole beamlines - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X01DD NEMO -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X08DB DISCO -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X10DG X11HEAT -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X01DD NEMO -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X08DB DISCO -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X10DG X11HEAT -10 10 0 0 0 0 } # User dipole beamlines - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X01DA DEBYE -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X02DA S-TOMCAT -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X03DA PEARL -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X04DB VUV -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X05DA Optics -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X06DA PXIII -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X07DB nanoXAS -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X07DA PolLux -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X10DA SuperXAS -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X01DA DEBYE -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X02DA S-TOMCAT -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X03DA PEARL -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X04DB VUV -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X05DA Optics -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X06DA PXIII -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X07DB nanoXAS -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X07DA PolLux -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X10DA SuperXAS -10 10 0 0 0 0 } # ID beamlines - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X02SA I-TOMCAT -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X03MA ADRESS -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X04SA ADDAMS -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X05LA QUEST -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X06SA PXI -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X07MA Phoenix/XTreme -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X08SA micro-XAS -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X09LA PEARL/XIL-II -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X10SA PXII -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X11MA SIM -10 10 0 0 0 0 } - {AGEBD-ORBITBUMP{{ agebd_env_suffix_upper }} X12SA cSAXS -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X02SA I-TOMCAT -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X03MA ADRESS -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X04SA ADDAMS -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X05LA QUEST -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X06SA PXI -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X07MA Phoenix/XTreme -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X08SA micro-XAS -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X09LA PEARL/XIL-II -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X10SA PXII -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X11MA SIM -10 10 0 0 0 0 } + {AGEBD-ORBITBUMP@@agebd_env_suffix_upper@@ X12SA cSAXS -10 10 0 0 0 0 } } diff --git a/services/orbitbump/current/ioc/AGEBD-CPCL-ORBITBUMP_parameters.yaml b/services/orbitbump/current/ioc/AGEBD-CPCL-ORBITBUMP_parameters.yaml index c179f0d..24aa364 100644 --- a/services/orbitbump/current/ioc/AGEBD-CPCL-ORBITBUMP_parameters.yaml +++ b/services/orbitbump/current/ioc/AGEBD-CPCL-ORBITBUMP_parameters.yaml @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ agebd_env_suffix_lower }} -ioc_port: {{ ioc_port }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/services/params/current/ioc/AGEBD-CPCL-PARAMS_main.subs b/services/params/current/ioc/AGEBD-CPCL-PARAMS_main.subs index 17d70e3..6eec21d 100644 --- a/services/params/current/ioc/AGEBD-CPCL-PARAMS_main.subs +++ b/services/params/current/ioc/AGEBD-CPCL-PARAMS_main.subs @@ -1,4 +1,4 @@ file PARAMS.template { pattern { DEVICE } - { AGEBD-PARAMS{{ agebd_env_suffix_upper }} } + { AGEBD-PARAMS@@agebd_env_suffix_upper@@ } } diff --git a/services/params/current/ioc/AGEBD-CPCL-PARAMS_parameters.yaml b/services/params/current/ioc/AGEBD-CPCL-PARAMS_parameters.yaml index c179f0d..24aa364 100644 --- a/services/params/current/ioc/AGEBD-CPCL-PARAMS_parameters.yaml +++ b/services/params/current/ioc/AGEBD-CPCL-PARAMS_parameters.yaml @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ agebd_env_suffix_lower }} -ioc_port: {{ ioc_port }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/services/plots/current/app/uv.lock b/services/plots/current/app/uv.lock index b02d9a2..1c4bad6 100644 --- a/services/plots/current/app/uv.lock +++ b/services/plots/current/app/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "gitpython" }, { name = "h5py" }, { name = "pyepics" }, + { name = "pyyaml" }, { name = "typer" }, ] @@ -18,6 +19,7 @@ requires-dist = [ { name = "gitpython", specifier = ">=3.1.50" }, { name = "h5py", specifier = ">=3.16.0" }, { name = "pyepics", specifier = ">=3.5.10" }, + { name = "pyyaml", specifier = ">=6.0.3" }, { name = "typer", specifier = ">=0.23.2" }, ] @@ -510,6 +512,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, ] +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, +] + [[package]] name = "requests" version = "2.34.2" diff --git a/services/plots/current/ioc/AGEBD-CPCL-PLOTS_main.subs b/services/plots/current/ioc/AGEBD-CPCL-PLOTS_main.subs index 17e7b9d..2e9deb5 100644 --- a/services/plots/current/ioc/AGEBD-CPCL-PLOTS_main.subs +++ b/services/plots/current/ioc/AGEBD-CPCL-PLOTS_main.subs @@ -1,64 +1,64 @@ file PLOTS_timeaxis.template { pattern { DEVICE } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }} } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@ } } file PLOTS_9h.template { pattern { DEVICE, NAME, INP } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, CURRENT, AGEBD-PARAMS:CURRENT } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, CURRENT-BPM, AGEBD-DBPM3CURR:CURRENT-AVG } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, CURRENT-PCT, ARS07-DPCT-0000:CURR } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, INJECTION-RATE, AGEBD-PARAMS:INJECTION-RATE } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, TRANSMISSION, AGEBD-PARAMS:TRANSMISSION } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, LIFETIME, AGEBD-PARAMS:LIFETIME } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, MAVAC-AVG, ARIVA-VMAVE:PRESS-AVE } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, MAVAC-MAX, ARIVA-VMAVE:PRESS-MAX } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, FEVAC-AVG, ARIVA-VMAVE-FE:PRESS-AVE } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, FEVAC-MAX, ARIVA-VMAVE-FE:PRESS-MAX } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, ABRTL-DDRM-0670, ABRTL-DDRM-0670:FET1_BIAS_DOSE} - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, ABRTL-DDRM-0950, ABRTL-DDRM-0950:FET1_DOSE} - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, X05LA-DDRM-0330, X05LA-DDRM-0330:FET1_BIAS_DOSE} - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, X05LA-DDRM-0650, X05LA-DDRM-0650:FET1_BIAS_DOSE} - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, X09LA-DDRM-0330, X09LA-DDRM-0330:FET1_BIAS_DOSE} - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, X09LA-DDRM-0790, X09LA-DDRM-0790:FET1_BIAS_DOSE} - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, ARS01-DDRM-0375, ARS01-DDRM-0375:FET1_DOSE} - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, ARS01-DDRM-1530, ARS01-DDRM-1530:FET1_BIAS_DOSE} - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, ARS05-DDRM-1530, ARS05-DDRM-1530:FET1_BIAS_DOSE} - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, ARS05-DDRM-3500, ARS05-DDRM-3500:FET1_BIAS_DOSE} - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, ARS09-DDRM-1530, ARS09-DDRM-1530:FET1_BIAS_DOSE} - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, ARS09-DDRM-3500, ARS09-DDRM-3500:FET2_BIAS_DOSE} - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, ARS12-DDRM-1530, ARS12-DDRM-1530:FET1_BIAS_DOSE} - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, ARS12-DDRM-3500, ARS12-DDRM-3500:FET1_BIAS_DOSE} - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, ARS12-DDRM-4400, ARS12-DDRM-4400:FET1_BIAS_DOSE} - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, ARS12-DDRM-5480, ARS12-DDRM-5480:FET1_BIAS_DOSE} - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, X02SA-UIND-GAP, AGEOP-STATUS:X02SA-UIND-GAP} # Soft Blue #A0C4FF - # { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, X03MA-UIND-GAP, AGEOP-STATUS:X03MA-UIND-GAP} # Warm Orange #FFD6A5 - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, X04SA-UIND-GAP, AGEOP-STATUS:X04SA-UIND-GAP} # Light Green #CAFFBF - # { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, X05LA-UIND-GAP, AGEOP-STATUS:X05LA-UIND-GAP} # Coral Red #FFADAD - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, X06SA-UIND-GAP, AGEOP-STATUS:X06SA-UIND-GAP} # Lavender #CDB4DB - # { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, X07MA-UIND-GAP, AGEOP-STATUS:X07MA-UIND-GAP} # Desert Tan #DDB892 - # { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, X08SA-UIND-GAP, AGEOP-STATUS:X08SA-UIND-GAP} # Peach Pink #FFB5A7 - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, X09LB-UIND-GAP, AGEOP-STATUS:X09LB-UIND-GAP} # Aqua Blue #9BF6FF - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, X10SA-UIND-GAP, AGEOP-STATUS:X10SA-UIND-GAP} # Pale Yellow #FDFFB6 - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, X11MA-UIND2-GAP, AGEOP-STATUS:X11MA-UIND2-GAP} # Periwinkle #BDB2FF - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, X12SA-UIND-GAP, AGEOP-STATUS:X12SA-UIND-GAP} # Mint Green #B0F2C2 + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, CURRENT, AGEBD-PARAMS:CURRENT } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, CURRENT-BPM, AGEBD-DBPM3CURR:CURRENT-AVG } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, CURRENT-PCT, ARS07-DPCT-0000:CURR } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, INJECTION-RATE, AGEBD-PARAMS:INJECTION-RATE } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, TRANSMISSION, AGEBD-PARAMS:TRANSMISSION } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, LIFETIME, AGEBD-PARAMS:LIFETIME } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, MAVAC-AVG, ARIVA-VMAVE:PRESS-AVE } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, MAVAC-MAX, ARIVA-VMAVE:PRESS-MAX } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, FEVAC-AVG, ARIVA-VMAVE-FE:PRESS-AVE } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, FEVAC-MAX, ARIVA-VMAVE-FE:PRESS-MAX } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, ABRTL-DDRM-0670, ABRTL-DDRM-0670:FET1_BIAS_DOSE} + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, ABRTL-DDRM-0950, ABRTL-DDRM-0950:FET1_DOSE} + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, X05LA-DDRM-0330, X05LA-DDRM-0330:FET1_BIAS_DOSE} + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, X05LA-DDRM-0650, X05LA-DDRM-0650:FET1_BIAS_DOSE} + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, X09LA-DDRM-0330, X09LA-DDRM-0330:FET1_BIAS_DOSE} + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, X09LA-DDRM-0790, X09LA-DDRM-0790:FET1_BIAS_DOSE} + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, ARS01-DDRM-0375, ARS01-DDRM-0375:FET1_DOSE} + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, ARS01-DDRM-1530, ARS01-DDRM-1530:FET1_BIAS_DOSE} + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, ARS05-DDRM-1530, ARS05-DDRM-1530:FET1_BIAS_DOSE} + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, ARS05-DDRM-3500, ARS05-DDRM-3500:FET1_BIAS_DOSE} + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, ARS09-DDRM-1530, ARS09-DDRM-1530:FET1_BIAS_DOSE} + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, ARS09-DDRM-3500, ARS09-DDRM-3500:FET2_BIAS_DOSE} + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, ARS12-DDRM-1530, ARS12-DDRM-1530:FET1_BIAS_DOSE} + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, ARS12-DDRM-3500, ARS12-DDRM-3500:FET1_BIAS_DOSE} + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, ARS12-DDRM-4400, ARS12-DDRM-4400:FET1_BIAS_DOSE} + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, ARS12-DDRM-5480, ARS12-DDRM-5480:FET1_BIAS_DOSE} + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, X02SA-UIND-GAP, AGEOP-STATUS:X02SA-UIND-GAP} # Soft Blue #A0C4FF + # { AGEBD-PLOTS@@agebd_env_suffix_upper@@, X03MA-UIND-GAP, AGEOP-STATUS:X03MA-UIND-GAP} # Warm Orange #FFD6A5 + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, X04SA-UIND-GAP, AGEOP-STATUS:X04SA-UIND-GAP} # Light Green #CAFFBF + # { AGEBD-PLOTS@@agebd_env_suffix_upper@@, X05LA-UIND-GAP, AGEOP-STATUS:X05LA-UIND-GAP} # Coral Red #FFADAD + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, X06SA-UIND-GAP, AGEOP-STATUS:X06SA-UIND-GAP} # Lavender #CDB4DB + # { AGEBD-PLOTS@@agebd_env_suffix_upper@@, X07MA-UIND-GAP, AGEOP-STATUS:X07MA-UIND-GAP} # Desert Tan #DDB892 + # { AGEBD-PLOTS@@agebd_env_suffix_upper@@, X08SA-UIND-GAP, AGEOP-STATUS:X08SA-UIND-GAP} # Peach Pink #FFB5A7 + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, X09LB-UIND-GAP, AGEOP-STATUS:X09LB-UIND-GAP} # Aqua Blue #9BF6FF + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, X10SA-UIND-GAP, AGEOP-STATUS:X10SA-UIND-GAP} # Pale Yellow #FDFFB6 + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, X11MA-UIND2-GAP, AGEOP-STATUS:X11MA-UIND2-GAP} # Periwinkle #BDB2FF + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, X12SA-UIND-GAP, AGEOP-STATUS:X12SA-UIND-GAP} # Mint Green #B0F2C2 } file PLOTS_week.template { pattern { DEVICE, NAME, INP } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, CURRENT-BPM, AGEBD-DBPM3CURR:CURRENT-AVG } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, CURRENT-PCT, ARS07-DPCT-0000:CURR } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, TAU-BPM, AGEBD-TAUBPM:TAU } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, TAU-PCT, AGEBD-TAUPCT:TAU } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, TAU-TOPUP, AGEBD-SCRUBBING:TOPUP-TAU } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, INJRATE-BPM, AGEBD-TAUBPM:INJRATE } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, INJRATE-PCT, AGEBD-TAUPCT:INJRATE } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, MAVAC-AVG, ARIVA-VMAVE:PRESS-AVE } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, MAVAC-MAX, ARIVA-VMAVE:PRESS-MAX } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, FEVAC-AVG, ARIVA-VMAVE-FE:PRESS-AVE } - { AGEBD-PLOTS{{ agebd_env_suffix_upper }}, FEVAC-MAX, ARIVA-VMAVE-FE:PRESS-MAX } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, CURRENT-BPM, AGEBD-DBPM3CURR:CURRENT-AVG } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, CURRENT-PCT, ARS07-DPCT-0000:CURR } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, TAU-BPM, AGEBD-TAUBPM:TAU } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, TAU-PCT, AGEBD-TAUPCT:TAU } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, TAU-TOPUP, AGEBD-SCRUBBING:TOPUP-TAU } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, INJRATE-BPM, AGEBD-TAUBPM:INJRATE } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, INJRATE-PCT, AGEBD-TAUPCT:INJRATE } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, MAVAC-AVG, ARIVA-VMAVE:PRESS-AVE } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, MAVAC-MAX, ARIVA-VMAVE:PRESS-MAX } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, FEVAC-AVG, ARIVA-VMAVE-FE:PRESS-AVE } + { AGEBD-PLOTS@@agebd_env_suffix_upper@@, FEVAC-MAX, ARIVA-VMAVE-FE:PRESS-MAX } } diff --git a/services/plots/current/ioc/AGEBD-CPCL-PLOTS_parameters.yaml b/services/plots/current/ioc/AGEBD-CPCL-PLOTS_parameters.yaml index c179f0d..24aa364 100644 --- a/services/plots/current/ioc/AGEBD-CPCL-PLOTS_parameters.yaml +++ b/services/plots/current/ioc/AGEBD-CPCL-PLOTS_parameters.yaml @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ agebd_env_suffix_lower }} -ioc_port: {{ ioc_port }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/services/plots/current/systemd/AGEBD-SERVICE-PLOTS.service b/services/plots/current/systemd/AGEBD-SERVICE-PLOTS.service index 98888ed..9f4739c 100644 --- a/services/plots/current/systemd/AGEBD-SERVICE-PLOTS.service +++ b/services/plots/current/systemd/AGEBD-SERVICE-PLOTS.service @@ -3,9 +3,9 @@ Description=AGEBD-SERVICE-PLOTS After=network.target [Service] -Environment=AGEBD_ENV={{ agebd_env }} +Environment=AGEBD_ENV=@@agebd_env@@ Environment=PYTHONUNBUFFERED=1 -ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh PLOTS +ExecStart=/sls/bd/hla/@@agebd_env@@/bin/start_service.sh PLOTS Restart=no [Install] diff --git a/services/postmortemlog/current/app/uv.lock b/services/postmortemlog/current/app/uv.lock index d036cb1..4550566 100644 --- a/services/postmortemlog/current/app/uv.lock +++ b/services/postmortemlog/current/app/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "gitpython" }, { name = "h5py" }, { name = "pyepics" }, + { name = "pyyaml" }, { name = "typer" }, ] @@ -18,6 +19,7 @@ requires-dist = [ { name = "gitpython", specifier = ">=3.1.50" }, { name = "h5py", specifier = ">=3.16.0" }, { name = "pyepics", specifier = ">=3.5.10" }, + { name = "pyyaml", specifier = ">=6.0.3" }, { name = "typer", specifier = ">=0.23.2" }, ] @@ -506,6 +508,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, ] +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, +] + [[package]] name = "requests" version = "2.34.2" diff --git a/services/postmortemlog/current/ioc/AGEBD-CPCL-POSTMORTEMLOG_main.subs b/services/postmortemlog/current/ioc/AGEBD-CPCL-POSTMORTEMLOG_main.subs index c424cf8..1b79c63 100644 --- a/services/postmortemlog/current/ioc/AGEBD-CPCL-POSTMORTEMLOG_main.subs +++ b/services/postmortemlog/current/ioc/AGEBD-CPCL-POSTMORTEMLOG_main.subs @@ -1,129 +1,129 @@ file POSTMORTEMLOG.template { pattern { DEVICE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ } } file POSTMORTEMLOG_15min10Hz.template { pattern { DEVICE NAME INP} # ---------- BEAM CURRENT -------------- - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} CURRBPM AGEBD-DBPM3CURR:CURRENT-AVG } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} CURRPCT ARS07-DPCT-0000:CURR } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ CURRBPM AGEBD-DBPM3CURR:CURRENT-AVG } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ CURRPCT ARS07-DPCT-0000:CURR } # ---------- BEAM LIFETIME -------------- - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} TAUBPM AGEBD-TAUBPM:TAU } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} TAUPCT AGEBD-TAUPCT:TAU } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ TAUBPM AGEBD-TAUBPM:TAU } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ TAUPCT AGEBD-TAUPCT:TAU } # ---------- TUNES -------------- - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} QX AGEBD-TUNEBUMP:QX } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} QY AGEBD-TUNEBUMP:QY } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} QZ AGEBD-TUNEBUMP:QZ } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ QX AGEBD-TUNEBUMP:QX } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ QY AGEBD-TUNEBUMP:QY } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ QZ AGEBD-TUNEBUMP:QZ } # ---------- LOSSES -------------- - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS01-DDRM-0375 ARS01-DDRM-0375:FET1_DOSE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ABRTL-DDRM-0670 ABRTL-DDRM-0670:FET1_BIAS_DOSE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ABRTL-DDRM-0950 ABRTL-DDRM-0950:FET1_DOSE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS01-DDRM-1530 ARS01-DDRM-1530:FET1_BIAS_DOSE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} X05LA-DDRM-0330 X05LA-DDRM-0330:FET1_BIAS_DOSE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS05-DDRM-1530 ARS05-DDRM-1530:FET1_BIAS_DOSE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS05-DDRM-3500 ARS05-DDRM-3500:FET1_BIAS_DOSE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} X09LA-DDRM-0330 X09LA-DDRM-0330:FET1_BIAS_DOSE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS09-DDRM-1530 ARS09-DDRM-1530:FET1_BIAS_DOSE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS09-DDRM-3500 ARS09-DDRM-3500:FET2_BIAS_DOSE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS12-DDRM-1530 ARS12-DDRM-1530:FET1_BIAS_DOSE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS12-DDRM-3500 ARS12-DDRM-3500:FET2_BIAS_DOSE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS12-DDRM-4400 ARS12-DDRM-4400:FET2_BIAS_DOSE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS12-DDRM-5480 ARS12-DDRM-5480:FET1_BIAS_DOSE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS01-DDRM-0375 ARS01-DDRM-0375:FET1_DOSE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ABRTL-DDRM-0670 ABRTL-DDRM-0670:FET1_BIAS_DOSE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ABRTL-DDRM-0950 ABRTL-DDRM-0950:FET1_DOSE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS01-DDRM-1530 ARS01-DDRM-1530:FET1_BIAS_DOSE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ X05LA-DDRM-0330 X05LA-DDRM-0330:FET1_BIAS_DOSE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS05-DDRM-1530 ARS05-DDRM-1530:FET1_BIAS_DOSE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS05-DDRM-3500 ARS05-DDRM-3500:FET1_BIAS_DOSE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ X09LA-DDRM-0330 X09LA-DDRM-0330:FET1_BIAS_DOSE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS09-DDRM-1530 ARS09-DDRM-1530:FET1_BIAS_DOSE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS09-DDRM-3500 ARS09-DDRM-3500:FET2_BIAS_DOSE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS12-DDRM-1530 ARS12-DDRM-1530:FET1_BIAS_DOSE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS12-DDRM-3500 ARS12-DDRM-3500:FET2_BIAS_DOSE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS12-DDRM-4400 ARS12-DDRM-4400:FET2_BIAS_DOSE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS12-DDRM-5480 ARS12-DDRM-5480:FET1_BIAS_DOSE } # ---------- RF -------------- - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} MASTERFREQ-SET AGERF-MO01:FREQ-SET } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} MASTERFREQ-GET AGERF-MO01:FREQ-GET } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} RFPOW-0140-INP ARS05-RCAV-0140:CO1i-POWER-MAX } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} RFPOW-0060-INP ARS05-RCAV-0060:CO1i-POWER-MAX } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} RFPOW-0230-INP ARS05-RCAV-0230:CO1i-POWER-MAX } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} RFPOW-0310-INP ARS05-RCAV-0310:CO1i-POWER-MAX } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} RFPOW-0060-REF ARS05-RCAV-0060:CO1r-POWER-MAX } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} RFPOW-0140-REF ARS05-RCAV-0140:CO1r-POWER-MAX } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} RFPOW-0230-REF ARS05-RCAV-0230:CO1r-POWER-MAX } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} RFPOW-0310-REF ARS05-RCAV-0310:CO1r-POWER-MAX } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ MASTERFREQ-SET AGERF-MO01:FREQ-SET } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ MASTERFREQ-GET AGERF-MO01:FREQ-GET } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ RFPOW-0140-INP ARS05-RCAV-0140:CO1i-POWER-MAX } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ RFPOW-0060-INP ARS05-RCAV-0060:CO1i-POWER-MAX } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ RFPOW-0230-INP ARS05-RCAV-0230:CO1i-POWER-MAX } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ RFPOW-0310-INP ARS05-RCAV-0310:CO1i-POWER-MAX } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ RFPOW-0060-REF ARS05-RCAV-0060:CO1r-POWER-MAX } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ RFPOW-0140-REF ARS05-RCAV-0140:CO1r-POWER-MAX } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ RFPOW-0230-REF ARS05-RCAV-0230:CO1r-POWER-MAX } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ RFPOW-0310-REF ARS05-RCAV-0310:CO1r-POWER-MAX } # ---------- BEAM SIZE -------------- - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} X01DD-SIGX X01DD-FE-CAM1:SIG-X } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} X01DD-SIGY X01DD-FE-CAM1:SIG-Y } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} X08DB-SIGX X08DB-FE-CAM1:SIG-X } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} X08DB-SIGY X08DB-FE-CAM1:SIG-Y } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ X01DD-SIGX X01DD-FE-CAM1:SIG-X } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ X01DD-SIGY X01DD-FE-CAM1:SIG-Y } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ X08DB-SIGX X08DB-FE-CAM1:SIG-X } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ X08DB-SIGY X08DB-FE-CAM1:SIG-Y } # ---------- VACUUM -------------- - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} VACMAX ARIVA-VMAVE:PRESS-MAX } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} VACMAXFE ARIVA-VMAVE-FE:PRESS-MAX } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS01-VMCC-0110 ARS01-VMCC-0110:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS01-VMCC-0210 ARS01-VMCC-0210:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS01-VMCC-0225 ARS01-VMCC-0225:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS01-VMCC-0310 ARS01-VMCC-0310:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS01-VMCC-1550 ARS01-VMCC-1550:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS01-VMCC-3510 ARS01-VMCC-3510:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS01-VMCC-5460 ARS01-VMCC-5460:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS02-VMCC-0110 ARS02-VMCC-0110:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS02-VMCC-0210 ARS02-VMCC-0210:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS02-VMCC-0310 ARS02-VMCC-0310:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS02-VMCC-1550 ARS02-VMCC-1550:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS02-VMCC-3510 ARS02-VMCC-3510:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS02-VMCC-5460 ARS02-VMCC-5460:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS03-VMCC-0110 ARS03-VMCC-0110:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS03-VMCC-0320 ARS03-VMCC-0320:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS03-VMCC-1550 ARS03-VMCC-1550:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS03-VMCC-3510 ARS03-VMCC-3510:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS03-VMCC-5460 ARS03-VMCC-5460:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS04-VMCC-0110 ARS04-VMCC-0110:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS04-VMCC-1550 ARS04-VMCC-1550:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS04-VMCC-3510 ARS04-VMCC-3510:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS04-VMCC-5460 ARS04-VMCC-5460:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS05-VMCC-0110 ARS05-VMCC-0110:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS05-VMCC-0115 ARS05-VMCC-0115:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS05-VMCC-0210 ARS05-VMCC-0210:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS05-VMCC-0215 ARS05-VMCC-0215:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS05-VMCC-0310 ARS05-VMCC-0310:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS05-VMCC-0315 ARS05-VMCC-0315:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS05-VMCC-0410 ARS05-VMCC-0410:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS05-VMCC-0415 ARS05-VMCC-0415:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS05-VMCC-0510 ARS05-VMCC-0510:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS05-VMCC-0520 ARS05-VMCC-0520:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS05-VMCC-0530 ARS05-VMCC-0530:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS05-VMCC-0810 ARS05-VMCC-0810:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS05-VMCC-1550 ARS05-VMCC-1550:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS05-VMCC-3510 ARS05-VMCC-3510:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS05-VMCC-5460 ARS05-VMCC-5460:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS06-VMCC-0110 ARS06-VMCC-0110:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS06-VMCC-1550 ARS06-VMCC-1550:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS06-VMCC-3510 ARS06-VMCC-3510:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS06-VMCC-5460 ARS06-VMCC-5460:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS07-VMCC-0010 ARS07-VMCC-0010:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS07-VMCC-0120 ARS07-VMCC-0120:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS07-VMCC-0210 ARS07-VMCC-0210:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS07-VMCC-1550 ARS07-VMCC-1550:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS07-VMCC-3510 ARS07-VMCC-3510:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS07-VMCC-5460 ARS07-VMCC-5460:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS08-VMCC-0110 ARS08-VMCC-0110:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS08-VMCC-1550 ARS08-VMCC-1550:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS08-VMCC-3510 ARS08-VMCC-3510:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS08-VMCC-5460 ARS08-VMCC-5460:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS09-VMCC-0110 ARS09-VMCC-0110:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS09-VMCC-0120 ARS09-VMCC-0120:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS09-VMCC-0410 ARS09-VMCC-0410:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS09-VMCC-0510 ARS09-VMCC-0510:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS09-VMCC-0810 ARS09-VMCC-0810:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS09-VMCC-1550 ARS09-VMCC-1550:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS09-VMCC-3510 ARS09-VMCC-3510:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS09-VMCC-5460 ARS09-VMCC-5460:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS10-VMCC-0110 ARS10-VMCC-0110:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS10-VMCC-1550 ARS10-VMCC-1550:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS10-VMCC-3510 ARS10-VMCC-3510:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS10-VMCC-5460 ARS10-VMCC-5460:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS11-VMCC-0110 ARS11-VMCC-0110:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS11-VMCC-0210 ARS11-VMCC-0210:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS11-VMCC-0310 ARS11-VMCC-0310:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS11-VMCC-0410 ARS11-VMCC-0410:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS11-VMCC-0510 ARS11-VMCC-0510:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS11-VMCC-1550 ARS11-VMCC-1550:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS11-VMCC-3510 ARS11-VMCC-3510:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS11-VMCC-5460 ARS11-VMCC-5460:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS12-VMCC-0110 ARS12-VMCC-0110:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS12-VMCC-1550 ARS12-VMCC-1550:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS12-VMCC-3510 ARS12-VMCC-3510:PRESSURE } - { AGEBD-POSTMORTEMLOG{{ agebd_env_suffix_upper }} ARS12-VMCC-5460 ARS12-VMCC-5460:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ VACMAX ARIVA-VMAVE:PRESS-MAX } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ VACMAXFE ARIVA-VMAVE-FE:PRESS-MAX } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS01-VMCC-0110 ARS01-VMCC-0110:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS01-VMCC-0210 ARS01-VMCC-0210:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS01-VMCC-0225 ARS01-VMCC-0225:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS01-VMCC-0310 ARS01-VMCC-0310:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS01-VMCC-1550 ARS01-VMCC-1550:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS01-VMCC-3510 ARS01-VMCC-3510:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS01-VMCC-5460 ARS01-VMCC-5460:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS02-VMCC-0110 ARS02-VMCC-0110:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS02-VMCC-0210 ARS02-VMCC-0210:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS02-VMCC-0310 ARS02-VMCC-0310:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS02-VMCC-1550 ARS02-VMCC-1550:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS02-VMCC-3510 ARS02-VMCC-3510:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS02-VMCC-5460 ARS02-VMCC-5460:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS03-VMCC-0110 ARS03-VMCC-0110:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS03-VMCC-0320 ARS03-VMCC-0320:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS03-VMCC-1550 ARS03-VMCC-1550:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS03-VMCC-3510 ARS03-VMCC-3510:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS03-VMCC-5460 ARS03-VMCC-5460:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS04-VMCC-0110 ARS04-VMCC-0110:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS04-VMCC-1550 ARS04-VMCC-1550:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS04-VMCC-3510 ARS04-VMCC-3510:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS04-VMCC-5460 ARS04-VMCC-5460:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS05-VMCC-0110 ARS05-VMCC-0110:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS05-VMCC-0115 ARS05-VMCC-0115:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS05-VMCC-0210 ARS05-VMCC-0210:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS05-VMCC-0215 ARS05-VMCC-0215:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS05-VMCC-0310 ARS05-VMCC-0310:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS05-VMCC-0315 ARS05-VMCC-0315:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS05-VMCC-0410 ARS05-VMCC-0410:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS05-VMCC-0415 ARS05-VMCC-0415:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS05-VMCC-0510 ARS05-VMCC-0510:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS05-VMCC-0520 ARS05-VMCC-0520:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS05-VMCC-0530 ARS05-VMCC-0530:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS05-VMCC-0810 ARS05-VMCC-0810:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS05-VMCC-1550 ARS05-VMCC-1550:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS05-VMCC-3510 ARS05-VMCC-3510:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS05-VMCC-5460 ARS05-VMCC-5460:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS06-VMCC-0110 ARS06-VMCC-0110:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS06-VMCC-1550 ARS06-VMCC-1550:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS06-VMCC-3510 ARS06-VMCC-3510:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS06-VMCC-5460 ARS06-VMCC-5460:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS07-VMCC-0010 ARS07-VMCC-0010:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS07-VMCC-0120 ARS07-VMCC-0120:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS07-VMCC-0210 ARS07-VMCC-0210:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS07-VMCC-1550 ARS07-VMCC-1550:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS07-VMCC-3510 ARS07-VMCC-3510:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS07-VMCC-5460 ARS07-VMCC-5460:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS08-VMCC-0110 ARS08-VMCC-0110:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS08-VMCC-1550 ARS08-VMCC-1550:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS08-VMCC-3510 ARS08-VMCC-3510:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS08-VMCC-5460 ARS08-VMCC-5460:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS09-VMCC-0110 ARS09-VMCC-0110:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS09-VMCC-0120 ARS09-VMCC-0120:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS09-VMCC-0410 ARS09-VMCC-0410:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS09-VMCC-0510 ARS09-VMCC-0510:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS09-VMCC-0810 ARS09-VMCC-0810:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS09-VMCC-1550 ARS09-VMCC-1550:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS09-VMCC-3510 ARS09-VMCC-3510:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS09-VMCC-5460 ARS09-VMCC-5460:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS10-VMCC-0110 ARS10-VMCC-0110:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS10-VMCC-1550 ARS10-VMCC-1550:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS10-VMCC-3510 ARS10-VMCC-3510:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS10-VMCC-5460 ARS10-VMCC-5460:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS11-VMCC-0110 ARS11-VMCC-0110:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS11-VMCC-0210 ARS11-VMCC-0210:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS11-VMCC-0310 ARS11-VMCC-0310:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS11-VMCC-0410 ARS11-VMCC-0410:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS11-VMCC-0510 ARS11-VMCC-0510:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS11-VMCC-1550 ARS11-VMCC-1550:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS11-VMCC-3510 ARS11-VMCC-3510:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS11-VMCC-5460 ARS11-VMCC-5460:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS12-VMCC-0110 ARS12-VMCC-0110:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS12-VMCC-1550 ARS12-VMCC-1550:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS12-VMCC-3510 ARS12-VMCC-3510:PRESSURE } + { AGEBD-POSTMORTEMLOG@@agebd_env_suffix_upper@@ ARS12-VMCC-5460 ARS12-VMCC-5460:PRESSURE } } diff --git a/services/postmortemlog/current/ioc/AGEBD-CPCL-POSTMORTEMLOG_parameters.yaml b/services/postmortemlog/current/ioc/AGEBD-CPCL-POSTMORTEMLOG_parameters.yaml index c179f0d..24aa364 100644 --- a/services/postmortemlog/current/ioc/AGEBD-CPCL-POSTMORTEMLOG_parameters.yaml +++ b/services/postmortemlog/current/ioc/AGEBD-CPCL-POSTMORTEMLOG_parameters.yaml @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ agebd_env_suffix_lower }} -ioc_port: {{ ioc_port }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/services/postmortemlog/current/systemd/AGEBD-SERVICE-POSTMORTEMLOG.service b/services/postmortemlog/current/systemd/AGEBD-SERVICE-POSTMORTEMLOG.service index 0c9bef2..3812a83 100644 --- a/services/postmortemlog/current/systemd/AGEBD-SERVICE-POSTMORTEMLOG.service +++ b/services/postmortemlog/current/systemd/AGEBD-SERVICE-POSTMORTEMLOG.service @@ -3,9 +3,9 @@ Description=AGEBD-SERVICE-POSTMORTEMLOG After=network.target [Service] -Environment=AGEBD_ENV={{ agebd_env }} +Environment=AGEBD_ENV=@@agebd_env@@ Environment=PYTHONUNBUFFERED=1 -ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh POSTMORTEMLOG +ExecStart=/sls/bd/hla/@@agebd_env@@/bin/start_service.sh POSTMORTEMLOG Restart=no [Install] diff --git a/services/scrubbing/current/app/uv.lock b/services/scrubbing/current/app/uv.lock index c4e3018..3a93903 100644 --- a/services/scrubbing/current/app/uv.lock +++ b/services/scrubbing/current/app/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "gitpython" }, { name = "h5py" }, { name = "pyepics" }, + { name = "pyyaml" }, { name = "typer" }, ] @@ -18,6 +19,7 @@ requires-dist = [ { name = "gitpython", specifier = ">=3.1.50" }, { name = "h5py", specifier = ">=3.16.0" }, { name = "pyepics", specifier = ">=3.5.10" }, + { name = "pyyaml", specifier = ">=6.0.3" }, { name = "typer", specifier = ">=0.23.2" }, ] @@ -284,6 +286,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, ] +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, +] + [[package]] name = "rich" version = "15.0.0" diff --git a/services/scrubbing/current/ioc/AGEBD-CPCL-SCRUBBING_main.subs b/services/scrubbing/current/ioc/AGEBD-CPCL-SCRUBBING_main.subs index 7c4b66f..d9be150 100644 --- a/services/scrubbing/current/ioc/AGEBD-CPCL-SCRUBBING_main.subs +++ b/services/scrubbing/current/ioc/AGEBD-CPCL-SCRUBBING_main.subs @@ -1,4 +1,4 @@ file SCRUBBING.template { pattern { DEVICE } - { AGEBD-SCRUBBING{{ agebd_env_suffix_upper }} } + { AGEBD-SCRUBBING@@agebd_env_suffix_upper@@ } } diff --git a/services/scrubbing/current/ioc/AGEBD-CPCL-SCRUBBING_parameters.yaml b/services/scrubbing/current/ioc/AGEBD-CPCL-SCRUBBING_parameters.yaml index c179f0d..24aa364 100644 --- a/services/scrubbing/current/ioc/AGEBD-CPCL-SCRUBBING_parameters.yaml +++ b/services/scrubbing/current/ioc/AGEBD-CPCL-SCRUBBING_parameters.yaml @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ agebd_env_suffix_lower }} -ioc_port: {{ ioc_port }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/services/scrubbing/current/systemd/AGEBD-SERVICE-SCRUBBING.service b/services/scrubbing/current/systemd/AGEBD-SERVICE-SCRUBBING.service index 479b986..22183fc 100644 --- a/services/scrubbing/current/systemd/AGEBD-SERVICE-SCRUBBING.service +++ b/services/scrubbing/current/systemd/AGEBD-SERVICE-SCRUBBING.service @@ -3,9 +3,9 @@ Description=AGEBD-SERVICE-SCRUBBING After=network.target [Service] -Environment=AGEBD_ENV={{ agebd_env }} +Environment=AGEBD_ENV=@@agebd_env@@ Environment=PYTHONUNBUFFERED=1 -ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh SCRUBBING +ExecStart=/sls/bd/hla/@@agebd_env@@/bin/start_service.sh SCRUBBING Restart=no [Install] diff --git a/services/shifttool/current/app/uv.lock b/services/shifttool/current/app/uv.lock index f89a870..ee3e89e 100644 --- a/services/shifttool/current/app/uv.lock +++ b/services/shifttool/current/app/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "gitpython" }, { name = "h5py" }, { name = "pyepics" }, + { name = "pyyaml" }, { name = "typer" }, ] @@ -18,6 +19,7 @@ requires-dist = [ { name = "gitpython", specifier = ">=3.1.50" }, { name = "h5py", specifier = ">=3.16.0" }, { name = "pyepics", specifier = ">=3.5.10" }, + { name = "pyyaml", specifier = ">=6.0.3" }, { name = "typer", specifier = ">=0.23.2" }, ] @@ -373,6 +375,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, ] +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, +] + [[package]] name = "requests" version = "2.34.2" diff --git a/services/shifttool/current/ioc/AGEBD-CPCL-SHIFTTOOL_main.subs b/services/shifttool/current/ioc/AGEBD-CPCL-SHIFTTOOL_main.subs index 1e54004..4b4c10e 100644 --- a/services/shifttool/current/ioc/AGEBD-CPCL-SHIFTTOOL_main.subs +++ b/services/shifttool/current/ioc/AGEBD-CPCL-SHIFTTOOL_main.subs @@ -1,4 +1,4 @@ file SHIFTTOOL.template { pattern { DEVICE } - { AGEBD-SHIFTTOOL{{ agebd_env_suffix_upper }} } + { AGEBD-SHIFTTOOL@@agebd_env_suffix_upper@@ } } diff --git a/services/shifttool/current/ioc/AGEBD-CPCL-SHIFTTOOL_parameters.yaml b/services/shifttool/current/ioc/AGEBD-CPCL-SHIFTTOOL_parameters.yaml index c179f0d..24aa364 100644 --- a/services/shifttool/current/ioc/AGEBD-CPCL-SHIFTTOOL_parameters.yaml +++ b/services/shifttool/current/ioc/AGEBD-CPCL-SHIFTTOOL_parameters.yaml @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ agebd_env_suffix_lower }} -ioc_port: {{ ioc_port }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/services/shifttool/current/systemd/AGEBD-SERVICE-SHIFTTOOL.service b/services/shifttool/current/systemd/AGEBD-SERVICE-SHIFTTOOL.service index e1e1a1c..95dfb42 100644 --- a/services/shifttool/current/systemd/AGEBD-SERVICE-SHIFTTOOL.service +++ b/services/shifttool/current/systemd/AGEBD-SERVICE-SHIFTTOOL.service @@ -3,9 +3,9 @@ Description=AGEBD-SERVICE-SHIFTTOOL After=network.target [Service] -Environment=AGEBD_ENV={{ agebd_env }} +Environment=AGEBD_ENV=@@agebd_env@@ Environment=PYTHONUNBUFFERED=1 -ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh SHIFTTOOL +ExecStart=/sls/bd/hla/@@agebd_env@@/bin/start_service.sh SHIFTTOOL Restart=no [Install] diff --git a/services/taubpm/current/app/uv.lock b/services/taubpm/current/app/uv.lock index ab2369d..6180982 100644 --- a/services/taubpm/current/app/uv.lock +++ b/services/taubpm/current/app/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "gitpython" }, { name = "h5py" }, { name = "pyepics" }, + { name = "pyyaml" }, { name = "typer" }, ] @@ -18,6 +19,7 @@ requires-dist = [ { name = "gitpython", specifier = ">=3.1.50" }, { name = "h5py", specifier = ">=3.16.0" }, { name = "pyepics", specifier = ">=3.5.10" }, + { name = "pyyaml", specifier = ">=6.0.3" }, { name = "typer", specifier = ">=0.23.2" }, ] @@ -284,6 +286,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, ] +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, +] + [[package]] name = "rich" version = "15.0.0" diff --git a/services/taubpm/current/ioc/AGEBD-CPCL-TAUBPM_main.subs b/services/taubpm/current/ioc/AGEBD-CPCL-TAUBPM_main.subs index bef2d58..24d8543 100644 --- a/services/taubpm/current/ioc/AGEBD-CPCL-TAUBPM_main.subs +++ b/services/taubpm/current/ioc/AGEBD-CPCL-TAUBPM_main.subs @@ -1,4 +1,4 @@ file TAUBPM.template { pattern { DEVICE } - { AGEBD-TAUBPM{{ agebd_env_suffix_upper }} } + { AGEBD-TAUBPM@@agebd_env_suffix_upper@@ } } diff --git a/services/taubpm/current/ioc/AGEBD-CPCL-TAUBPM_parameters.yaml b/services/taubpm/current/ioc/AGEBD-CPCL-TAUBPM_parameters.yaml index c179f0d..24aa364 100644 --- a/services/taubpm/current/ioc/AGEBD-CPCL-TAUBPM_parameters.yaml +++ b/services/taubpm/current/ioc/AGEBD-CPCL-TAUBPM_parameters.yaml @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ agebd_env_suffix_lower }} -ioc_port: {{ ioc_port }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/services/taubpm/current/systemd/AGEBD-SERVICE-TAUBPM.service b/services/taubpm/current/systemd/AGEBD-SERVICE-TAUBPM.service index 7a2c19d..59e5dae 100644 --- a/services/taubpm/current/systemd/AGEBD-SERVICE-TAUBPM.service +++ b/services/taubpm/current/systemd/AGEBD-SERVICE-TAUBPM.service @@ -3,9 +3,9 @@ Description=AGEBD-SERVICE-TAUBPM After=network.target [Service] -Environment=AGEBD_ENV={{ agebd_env }} +Environment=AGEBD_ENV=@@agebd_env@@ Environment=PYTHONUNBUFFERED=1 -ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh TAUBPM +ExecStart=/sls/bd/hla/@@agebd_env@@/bin/start_service.sh TAUBPM Restart=no [Install] diff --git a/services/taupct/current/app/uv.lock b/services/taupct/current/app/uv.lock index 939300c..2d56d1e 100644 --- a/services/taupct/current/app/uv.lock +++ b/services/taupct/current/app/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "gitpython" }, { name = "h5py" }, { name = "pyepics" }, + { name = "pyyaml" }, { name = "typer" }, ] @@ -18,6 +19,7 @@ requires-dist = [ { name = "gitpython", specifier = ">=3.1.50" }, { name = "h5py", specifier = ">=3.16.0" }, { name = "pyepics", specifier = ">=3.5.10" }, + { name = "pyyaml", specifier = ">=6.0.3" }, { name = "typer", specifier = ">=0.23.2" }, ] @@ -284,6 +286,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, ] +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, +] + [[package]] name = "rich" version = "15.0.0" diff --git a/services/taupct/current/ioc/AGEBD-CPCL-TAUPCT_main.subs b/services/taupct/current/ioc/AGEBD-CPCL-TAUPCT_main.subs index efe7adc..f902cd6 100644 --- a/services/taupct/current/ioc/AGEBD-CPCL-TAUPCT_main.subs +++ b/services/taupct/current/ioc/AGEBD-CPCL-TAUPCT_main.subs @@ -1,4 +1,4 @@ file TAUPCT.template { pattern { DEVICE } - { AGEBD-TAUPCT{{ agebd_env_suffix_upper }} } + { AGEBD-TAUPCT@@agebd_env_suffix_upper@@ } } diff --git a/services/taupct/current/ioc/AGEBD-CPCL-TAUPCT_parameters.yaml b/services/taupct/current/ioc/AGEBD-CPCL-TAUPCT_parameters.yaml index c179f0d..24aa364 100644 --- a/services/taupct/current/ioc/AGEBD-CPCL-TAUPCT_parameters.yaml +++ b/services/taupct/current/ioc/AGEBD-CPCL-TAUPCT_parameters.yaml @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ agebd_env_suffix_lower }} -ioc_port: {{ ioc_port }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/services/taupct/current/systemd/AGEBD-SERVICE-TAUPCT.service b/services/taupct/current/systemd/AGEBD-SERVICE-TAUPCT.service index 8632a60..8695bb4 100644 --- a/services/taupct/current/systemd/AGEBD-SERVICE-TAUPCT.service +++ b/services/taupct/current/systemd/AGEBD-SERVICE-TAUPCT.service @@ -3,9 +3,9 @@ Description=AGEBD-SERVICE-TAUPCT After=network.target [Service] -Environment=AGEBD_ENV={{ agebd_env }} +Environment=AGEBD_ENV=@@agebd_env@@ Environment=PYTHONUNBUFFERED=1 -ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh TAUPCT +ExecStart=/sls/bd/hla/@@agebd_env@@/bin/start_service.sh TAUPCT Restart=no [Install] diff --git a/services/timing/current/app/uv.lock b/services/timing/current/app/uv.lock index 24e45d2..94c899e 100644 --- a/services/timing/current/app/uv.lock +++ b/services/timing/current/app/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "gitpython" }, { name = "h5py" }, { name = "pyepics" }, + { name = "pyyaml" }, { name = "typer" }, ] @@ -18,6 +19,7 @@ requires-dist = [ { name = "gitpython", specifier = ">=3.1.50" }, { name = "h5py", specifier = ">=3.16.0" }, { name = "pyepics", specifier = ">=3.5.10" }, + { name = "pyyaml", specifier = ">=6.0.3" }, { name = "typer", specifier = ">=0.23.2" }, ] @@ -284,6 +286,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, ] +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, +] + [[package]] name = "rich" version = "15.0.0" diff --git a/services/timing/current/ioc/AGEBD-CPCL-TIMING_main.subs b/services/timing/current/ioc/AGEBD-CPCL-TIMING_main.subs index 768d0f2..9837aba 100644 --- a/services/timing/current/ioc/AGEBD-CPCL-TIMING_main.subs +++ b/services/timing/current/ioc/AGEBD-CPCL-TIMING_main.subs @@ -1,4 +1,4 @@ file TIMING.template { pattern { DEVICE } - { AGEBD-TIMING{{ agebd_env_suffix_upper }} } + { AGEBD-TIMING@@agebd_env_suffix_upper@@ } } diff --git a/services/timing/current/ioc/AGEBD-CPCL-TIMING_parameters.yaml b/services/timing/current/ioc/AGEBD-CPCL-TIMING_parameters.yaml index c179f0d..24aa364 100644 --- a/services/timing/current/ioc/AGEBD-CPCL-TIMING_parameters.yaml +++ b/services/timing/current/ioc/AGEBD-CPCL-TIMING_parameters.yaml @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ agebd_env_suffix_lower }} -ioc_port: {{ ioc_port }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/services/timing/current/systemd/AGEBD-SERVICE-TIMING.service b/services/timing/current/systemd/AGEBD-SERVICE-TIMING.service index 37d3228..7650e5c 100644 --- a/services/timing/current/systemd/AGEBD-SERVICE-TIMING.service +++ b/services/timing/current/systemd/AGEBD-SERVICE-TIMING.service @@ -3,9 +3,9 @@ Description=AGEBD-SERVICE-TIMING After=network.target [Service] -Environment=AGEBD_ENV={{ agebd_env }} +Environment=AGEBD_ENV=@@agebd_env@@ Environment=PYTHONUNBUFFERED=1 -ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh TIMING +ExecStart=/sls/bd/hla/@@agebd_env@@/bin/start_service.sh TIMING Restart=no [Install] diff --git a/services/topuptool/current/app/uv.lock b/services/topuptool/current/app/uv.lock index a1e962a..137728b 100644 --- a/services/topuptool/current/app/uv.lock +++ b/services/topuptool/current/app/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "gitpython" }, { name = "h5py" }, { name = "pyepics" }, + { name = "pyyaml" }, { name = "typer" }, ] @@ -18,6 +19,7 @@ requires-dist = [ { name = "gitpython", specifier = ">=3.1.50" }, { name = "h5py", specifier = ">=3.16.0" }, { name = "pyepics", specifier = ">=3.5.10" }, + { name = "pyyaml", specifier = ">=6.0.3" }, { name = "typer", specifier = ">=0.23.2" }, ] @@ -284,6 +286,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, ] +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, +] + [[package]] name = "rich" version = "15.0.0" diff --git a/services/topuptool/current/ioc/AGEBD-CPCL-TOPUPTOOL_main.subs b/services/topuptool/current/ioc/AGEBD-CPCL-TOPUPTOOL_main.subs index 99c70ee..5edf85b 100644 --- a/services/topuptool/current/ioc/AGEBD-CPCL-TOPUPTOOL_main.subs +++ b/services/topuptool/current/ioc/AGEBD-CPCL-TOPUPTOOL_main.subs @@ -1,4 +1,4 @@ file TOPUPTOOL.template { pattern { DEVICE } - { AGEBD-TOPUPTOOL{{ agebd_env_suffix_upper }} } + { AGEBD-TOPUPTOOL@@agebd_env_suffix_upper@@ } } diff --git a/services/topuptool/current/ioc/AGEBD-CPCL-TOPUPTOOL_parameters.yaml b/services/topuptool/current/ioc/AGEBD-CPCL-TOPUPTOOL_parameters.yaml index c179f0d..24aa364 100644 --- a/services/topuptool/current/ioc/AGEBD-CPCL-TOPUPTOOL_parameters.yaml +++ b/services/topuptool/current/ioc/AGEBD-CPCL-TOPUPTOOL_parameters.yaml @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ agebd_env_suffix_lower }} -ioc_port: {{ ioc_port }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/services/topuptool/current/systemd/AGEBD-SERVICE-TOPUPTOOL.service b/services/topuptool/current/systemd/AGEBD-SERVICE-TOPUPTOOL.service index f322fb2..612e53f 100644 --- a/services/topuptool/current/systemd/AGEBD-SERVICE-TOPUPTOOL.service +++ b/services/topuptool/current/systemd/AGEBD-SERVICE-TOPUPTOOL.service @@ -3,9 +3,9 @@ Description=AGEBD-SERVICE-TOPUPTOOL After=network.target [Service] -Environment=AGEBD_ENV={{ agebd_env }} +Environment=AGEBD_ENV=@@agebd_env@@ Environment=PYTHONUNBUFFERED=1 -ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh TOPUPTOOL +ExecStart=/sls/bd/hla/@@agebd_env@@/bin/start_service.sh TOPUPTOOL Restart=no [Install] diff --git a/services/tune/current/app/uv.lock b/services/tune/current/app/uv.lock index e7452fe..effe985 100644 --- a/services/tune/current/app/uv.lock +++ b/services/tune/current/app/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "gitpython" }, { name = "h5py" }, { name = "pyepics" }, + { name = "pyyaml" }, { name = "typer" }, ] @@ -18,6 +19,7 @@ requires-dist = [ { name = "gitpython", specifier = ">=3.1.50" }, { name = "h5py", specifier = ">=3.16.0" }, { name = "pyepics", specifier = ">=3.5.10" }, + { name = "pyyaml", specifier = ">=6.0.3" }, { name = "typer", specifier = ">=0.23.2" }, ] @@ -382,6 +384,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/dd/96da98f892250475bdf2328112d7468abdd4acc7b902b6af23f4ed958ea0/pytz-2026.2-py2.py3-none-any.whl", hash = "sha256:04156e608bee23d3792fd45c94ae47fae1036688e75032eea2e3bf0323d1f126", size = 510141, upload-time = "2026-05-04T01:35:27.408Z" }, ] +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, +] + [[package]] name = "rich" version = "15.0.0" diff --git a/services/tune/current/ioc/AGEBD-CPCL-TUNE_main.subs b/services/tune/current/ioc/AGEBD-CPCL-TUNE_main.subs index 45ad64a..64f89f8 100644 --- a/services/tune/current/ioc/AGEBD-CPCL-TUNE_main.subs +++ b/services/tune/current/ioc/AGEBD-CPCL-TUNE_main.subs @@ -1,4 +1,4 @@ file TUNE.template { pattern { DEVICE } - { AGEBD-TUNE{{ agebd_env_suffix_upper }} } + { AGEBD-TUNE@@agebd_env_suffix_upper@@ } } diff --git a/services/tune/current/ioc/AGEBD-CPCL-TUNE_parameters.yaml b/services/tune/current/ioc/AGEBD-CPCL-TUNE_parameters.yaml index c179f0d..24aa364 100644 --- a/services/tune/current/ioc/AGEBD-CPCL-TUNE_parameters.yaml +++ b/services/tune/current/ioc/AGEBD-CPCL-TUNE_parameters.yaml @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ agebd_env_suffix_lower }} -ioc_port: {{ ioc_port }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/services/tune/current/systemd/AGEBD-SERVICE-TUNE.service b/services/tune/current/systemd/AGEBD-SERVICE-TUNE.service index a2ef74f..e3d8433 100644 --- a/services/tune/current/systemd/AGEBD-SERVICE-TUNE.service +++ b/services/tune/current/systemd/AGEBD-SERVICE-TUNE.service @@ -3,9 +3,9 @@ Description=AGEBD-SERVICE-TUNE After=network.target [Service] -Environment=AGEBD_ENV={{ agebd_env }} +Environment=AGEBD_ENV=@@agebd_env@@ Environment=PYTHONUNBUFFERED=1 -ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh TUNE +ExecStart=/sls/bd/hla/@@agebd_env@@/bin/start_service.sh TUNE Restart=no [Install] diff --git a/services/tunebump/current/app/uv.lock b/services/tunebump/current/app/uv.lock index fa7fbfc..30017a1 100644 --- a/services/tunebump/current/app/uv.lock +++ b/services/tunebump/current/app/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "gitpython" }, { name = "h5py" }, { name = "pyepics" }, + { name = "pyyaml" }, { name = "typer" }, ] @@ -18,6 +19,7 @@ requires-dist = [ { name = "gitpython", specifier = ">=3.1.50" }, { name = "h5py", specifier = ">=3.16.0" }, { name = "pyepics", specifier = ">=3.5.10" }, + { name = "pyyaml", specifier = ">=6.0.3" }, { name = "typer", specifier = ">=0.23.2" }, ] @@ -288,6 +290,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, ] +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, +] + [[package]] name = "rich" version = "15.0.0" diff --git a/services/tunebump/current/ioc/AGEBD-CPCL-TUNEBUMP_main.subs b/services/tunebump/current/ioc/AGEBD-CPCL-TUNEBUMP_main.subs index eda0773..1b568b7 100644 --- a/services/tunebump/current/ioc/AGEBD-CPCL-TUNEBUMP_main.subs +++ b/services/tunebump/current/ioc/AGEBD-CPCL-TUNEBUMP_main.subs @@ -1,4 +1,4 @@ file TUNEBUMP.template { pattern { DEVICE } - { AGEBD-TUNEBUMP{{ agebd_env_suffix_upper }} } + { AGEBD-TUNEBUMP@@agebd_env_suffix_upper@@ } } diff --git a/services/tunebump/current/ioc/AGEBD-CPCL-TUNEBUMP_parameters.yaml b/services/tunebump/current/ioc/AGEBD-CPCL-TUNEBUMP_parameters.yaml index c179f0d..24aa364 100644 --- a/services/tunebump/current/ioc/AGEBD-CPCL-TUNEBUMP_parameters.yaml +++ b/services/tunebump/current/ioc/AGEBD-CPCL-TUNEBUMP_parameters.yaml @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ agebd_env_suffix_lower }} -ioc_port: {{ ioc_port }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/services/tunebump/current/systemd/AGEBD-SERVICE-TUNEBUMP.service b/services/tunebump/current/systemd/AGEBD-SERVICE-TUNEBUMP.service index 1c9313b..623ae62 100644 --- a/services/tunebump/current/systemd/AGEBD-SERVICE-TUNEBUMP.service +++ b/services/tunebump/current/systemd/AGEBD-SERVICE-TUNEBUMP.service @@ -3,9 +3,9 @@ Description=AGEBD-SERVICE-TUNEBUMP After=network.target [Service] -Environment=AGEBD_ENV={{ agebd_env }} +Environment=AGEBD_ENV=@@agebd_env@@ Environment=PYTHONUNBUFFERED=1 -ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh TUNEBUMP +ExecStart=/sls/bd/hla/@@agebd_env@@/bin/start_service.sh TUNEBUMP Restart=no [Install] diff --git a/services/tunefbx/current/app/uv.lock b/services/tunefbx/current/app/uv.lock index 46b65ea..b06290c 100644 --- a/services/tunefbx/current/app/uv.lock +++ b/services/tunefbx/current/app/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "gitpython" }, { name = "h5py" }, { name = "pyepics" }, + { name = "pyyaml" }, { name = "typer" }, ] @@ -18,6 +19,7 @@ requires-dist = [ { name = "gitpython", specifier = ">=3.1.50" }, { name = "h5py", specifier = ">=3.16.0" }, { name = "pyepics", specifier = ">=3.5.10" }, + { name = "pyyaml", specifier = ">=6.0.3" }, { name = "typer", specifier = ">=0.23.2" }, ] @@ -284,6 +286,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, ] +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, +] + [[package]] name = "rich" version = "15.0.0" diff --git a/services/tunefbx/current/ioc/AGEBD-CPCL-TUNEFBX_main.subs b/services/tunefbx/current/ioc/AGEBD-CPCL-TUNEFBX_main.subs index 4ce5b49..91e35d9 100644 --- a/services/tunefbx/current/ioc/AGEBD-CPCL-TUNEFBX_main.subs +++ b/services/tunefbx/current/ioc/AGEBD-CPCL-TUNEFBX_main.subs @@ -1,4 +1,4 @@ file TUNEFBX.template { pattern { DEVICE } - { AGEBD-TUNEFBX{{ agebd_env_suffix_upper }} } + { AGEBD-TUNEFBX@@agebd_env_suffix_upper@@ } } diff --git a/services/tunefbx/current/ioc/AGEBD-CPCL-TUNEFBX_parameters.yaml b/services/tunefbx/current/ioc/AGEBD-CPCL-TUNEFBX_parameters.yaml index c179f0d..24aa364 100644 --- a/services/tunefbx/current/ioc/AGEBD-CPCL-TUNEFBX_parameters.yaml +++ b/services/tunefbx/current/ioc/AGEBD-CPCL-TUNEFBX_parameters.yaml @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ agebd_env_suffix_lower }} -ioc_port: {{ ioc_port }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/services/tunefbx/current/systemd/AGEBD-SERVICE-TUNEFBX.service b/services/tunefbx/current/systemd/AGEBD-SERVICE-TUNEFBX.service index 85688a0..ce93033 100644 --- a/services/tunefbx/current/systemd/AGEBD-SERVICE-TUNEFBX.service +++ b/services/tunefbx/current/systemd/AGEBD-SERVICE-TUNEFBX.service @@ -3,9 +3,9 @@ Description=AGEBD-SERVICE-TUNEFBX After=network.target [Service] -Environment=AGEBD_ENV={{ agebd_env }} +Environment=AGEBD_ENV=@@agebd_env@@ Environment=PYTHONUNBUFFERED=1 -ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh TUNEFBX +ExecStart=/sls/bd/hla/@@agebd_env@@/bin/start_service.sh TUNEFBX Restart=no [Install] diff --git a/services/tunefby/current/app/uv.lock b/services/tunefby/current/app/uv.lock index ae9bbd5..9639669 100644 --- a/services/tunefby/current/app/uv.lock +++ b/services/tunefby/current/app/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "gitpython" }, { name = "h5py" }, { name = "pyepics" }, + { name = "pyyaml" }, { name = "typer" }, ] @@ -18,6 +19,7 @@ requires-dist = [ { name = "gitpython", specifier = ">=3.1.50" }, { name = "h5py", specifier = ">=3.16.0" }, { name = "pyepics", specifier = ">=3.5.10" }, + { name = "pyyaml", specifier = ">=6.0.3" }, { name = "typer", specifier = ">=0.23.2" }, ] @@ -284,6 +286,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, ] +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, +] + [[package]] name = "rich" version = "15.0.0" diff --git a/services/tunefby/current/ioc/AGEBD-CPCL-TUNEFBY_main.subs b/services/tunefby/current/ioc/AGEBD-CPCL-TUNEFBY_main.subs index 759a18d..9b64018 100644 --- a/services/tunefby/current/ioc/AGEBD-CPCL-TUNEFBY_main.subs +++ b/services/tunefby/current/ioc/AGEBD-CPCL-TUNEFBY_main.subs @@ -1,4 +1,4 @@ file TUNEFBY.template { pattern { DEVICE } - { AGEBD-TUNEFBY{{ agebd_env_suffix_upper }} } + { AGEBD-TUNEFBY@@agebd_env_suffix_upper@@ } } diff --git a/services/tunefby/current/ioc/AGEBD-CPCL-TUNEFBY_parameters.yaml b/services/tunefby/current/ioc/AGEBD-CPCL-TUNEFBY_parameters.yaml index c179f0d..24aa364 100644 --- a/services/tunefby/current/ioc/AGEBD-CPCL-TUNEFBY_parameters.yaml +++ b/services/tunefby/current/ioc/AGEBD-CPCL-TUNEFBY_parameters.yaml @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ agebd_env_suffix_lower }} -ioc_port: {{ ioc_port }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/services/tunefby/current/systemd/AGEBD-SERVICE-TUNEFBY.service b/services/tunefby/current/systemd/AGEBD-SERVICE-TUNEFBY.service index c2f2d0e..828b784 100644 --- a/services/tunefby/current/systemd/AGEBD-SERVICE-TUNEFBY.service +++ b/services/tunefby/current/systemd/AGEBD-SERVICE-TUNEFBY.service @@ -3,9 +3,9 @@ Description=AGEBD-SERVICE-TUNEFBY After=network.target [Service] -Environment=AGEBD_ENV={{ agebd_env }} +Environment=AGEBD_ENV=@@agebd_env@@ Environment=PYTHONUNBUFFERED=1 -ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh TUNEFBY +ExecStart=/sls/bd/hla/@@agebd_env@@/bin/start_service.sh TUNEFBY Restart=no [Install] diff --git a/templates/qt/A_BD_{{ui_filename}}.ui.jinja b/templates/qt/A_BD_{{ui_filename}}.ui.jinja index 307ae6d..1e372dc 100644 --- a/templates/qt/A_BD_{{ui_filename}}.ui.jinja +++ b/templates/qt/A_BD_{{ui_filename}}.ui.jinja @@ -30,7 +30,7 @@ 0 - AGEBD-{{ service_name_upper }}{{ '{{ agebd_env_suffix_upper }}' }}:AO + AGEBD-{{ service_name_upper }}@@agebd_env_suffix_upper@@:AO 9.000000000000000 @@ -49,10 +49,10 @@ - Toggle AGEBD-ALH{{ '{{ agebd_env_suffix_upper }}' }}:{{ service_name_upper }}-ONOFF + Toggle AGEBD-ALH@@agebd_env_suffix_upper@@:{{ service_name_upper }}-ONOFF - AGEBD-ALH{{ '{{ agebd_env_suffix_upper }}' }}:{{ service_name_upper }}-ONOFF + AGEBD-ALH@@agebd_env_suffix_upper@@:{{ service_name_upper }}-ONOFF @@ -70,7 +70,7 @@ - Value of AGEBD-{{ service_name_upper }}{{ '{{ agebd_env_suffix_upper }}' }}:AO + Value of AGEBD-{{ service_name_upper }}@@agebd_env_suffix_upper@@:AO diff --git a/templates/service/{{service_name_lower}}/current/ioc/AGEBD-CPCL-{{service_name_upper}}_main.subs.jinja b/templates/service/{{service_name_lower}}/current/ioc/AGEBD-CPCL-{{service_name_upper}}_main.subs.jinja index 78f2f06..a209fa1 100644 --- a/templates/service/{{service_name_lower}}/current/ioc/AGEBD-CPCL-{{service_name_upper}}_main.subs.jinja +++ b/templates/service/{{service_name_lower}}/current/ioc/AGEBD-CPCL-{{service_name_upper}}_main.subs.jinja @@ -1,4 +1,4 @@ file {{ service_name_upper }}.template { pattern { DEVICE } - { AGEBD-{{ service_name_upper }}{{ '{{ agebd_env_suffix_upper }}' }} } + { AGEBD-{{ service_name_upper }}@@agebd_env_suffix_upper@@ } } diff --git a/templates/service/{{service_name_lower}}/current/ioc/AGEBD-CPCL-{{service_name_upper}}_parameters.yaml.jinja b/templates/service/{{service_name_lower}}/current/ioc/AGEBD-CPCL-{{service_name_upper}}_parameters.yaml.jinja index 8748d7c..24aa364 100644 --- a/templates/service/{{service_name_lower}}/current/ioc/AGEBD-CPCL-{{service_name_upper}}_parameters.yaml.jinja +++ b/templates/service/{{service_name_lower}}/current/ioc/AGEBD-CPCL-{{service_name_upper}}_parameters.yaml.jinja @@ -1,6 +1,6 @@ cpu_architecture: x86_64 epics_version: 7.0.8 -ioc_host: sls-vserv-bd-01{{ '{{ agebd_env_suffix_lower }}' }} -ioc_port: {{ '{{ ioc_port }}' }} +ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@ +ioc_port: @@ioc_port@@ os: RHEL8 os_id: rhel diff --git a/templates/service/{{service_name_lower}}/current/systemd/AGEBD-SERVICE-{{service_name_upper}}.service.jinja b/templates/service/{{service_name_lower}}/current/systemd/AGEBD-SERVICE-{{service_name_upper}}.service.jinja index 61b1e48..2bdaf79 100644 --- a/templates/service/{{service_name_lower}}/current/systemd/AGEBD-SERVICE-{{service_name_upper}}.service.jinja +++ b/templates/service/{{service_name_lower}}/current/systemd/AGEBD-SERVICE-{{service_name_upper}}.service.jinja @@ -3,9 +3,9 @@ Description=AGEBD-SERVICE-{{ service_name_upper }} After=network.target [Service] -Environment=AGEBD_ENV={{ '{{ agebd_env }}' }} +Environment=AGEBD_ENV=@@agebd_env@@ Environment=PYTHONUNBUFFERED=1 -ExecStart=/sls/bd/hla/{{'{{ agebd_env }}'}}/bin/start_service.sh {{ service_name_upper }} +ExecStart=/sls/bd/hla/@@agebd_env@@/bin/start_service.sh {{ service_name_upper }} Restart=no [Install] -- 2.54.0 From 5e4246508b55577a16251d23e6c27883cf569784 Mon Sep 17 00:00:00 2001 From: Benjamin Labrecque Date: Thu, 20 Aug 2026 12:04:57 +0200 Subject: [PATCH 2/4] refactor: route deploy consumers through the central config (step 3) Both deploy paths now take their token values from config/environments.yml instead of defining their own copies. CI / shell path: * scripts/ci/render_subs.py renders deployed files via agebd.subs. * deploy-and-restart-service.sh drops its dev/prod if-else and its four sed calls for one render_subs.py invocation, and aborts the deploy if rendering fails rather than restarting a service whose files still contain placeholders. Ansible path: * ansible/tasks/utils/load-substitutions.yml reads the central config on the controller and exposes the token table for this environment. * ioc-install and service-deploy-and-restart now loop over that table instead of listing tokens inline, so a new token needs no ansible edit. * env_suffix_upper/lower are gone from both inventories. The inventory says which environment it is; the central config says what that environment means. The facts are renamed to agebd_env_suffix_upper / _lower to match the token names, removing a rename trap. Ansible keeps using ansible.builtin.replace rather than calling agebd.subs, because ioc-install runs on hosts with no uv or Python environment for this repo. Only the mechanism differs now; the values and the token list are shared. Verified: both playbook paths run locally against dev and prod and produce the expected output, an undeclared environment fails loudly in both paths, and a misspelled token exits non-zero instead of shipping the placeholder. Not addressed here, still step 5: ansible/tasks/utils/get-ioc-port.yml matches CamelCase registry names against a lowercase input and returns nothing, so the ansible ioc-install path cannot resolve a port. This is pre-existing and unchanged by this commit. Co-Authored-By: Claude Opus 5 --- .gitea/scripts/deploy-and-restart-service.sh | 29 ++---- ansible/inventories/dev/hosts.yml | 4 +- ansible/inventories/prod/hosts.yml | 4 +- ansible/playbooks/ioc-install.yml | 2 + ansible/playbooks/ioc-restart.yml | 2 + ansible/playbooks/ioc-start.yml | 2 + ansible/tasks/ioc/ioc-install.yml | 37 ++++---- ansible/tasks/ioc/ioc-restart.yml | 5 +- .../service/service-deploy-and-restart.yml | 14 ++- ansible/tasks/utils/load-substitutions.yml | 32 +++++++ scripts/ci/render_subs.py | 71 ++++++++++++++ scripts/tests/test_render_subs.py | 93 +++++++++++++++++++ 12 files changed, 250 insertions(+), 45 deletions(-) create mode 100644 ansible/tasks/utils/load-substitutions.yml create mode 100644 scripts/ci/render_subs.py create mode 100644 scripts/tests/test_render_subs.py diff --git a/.gitea/scripts/deploy-and-restart-service.sh b/.gitea/scripts/deploy-and-restart-service.sh index ccbbb8f..95834c3 100755 --- a/.gitea/scripts/deploy-and-restart-service.sh +++ b/.gitea/scripts/deploy-and-restart-service.sh @@ -13,15 +13,6 @@ 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}" @@ -38,17 +29,15 @@ rsync -avz --delete \ ./services/${SERVICE_NAME_LOWER}/current/* ${SERVICE_DIR}/ ### SUBSTITUTIONS -# Deploy-time tokens are '@@token@@'. Their values are declared in -# config/environments.yml -- keep the two in sync until this is replaced by a -# call to agebd.subs (see the refactor plan, step 3). -### IOC -sed -i "s/@@[[:space:]]*agebd_env_suffix_upper[[:space:]]*@@/${AGEBD_ENV_SUFFIX_UPPER}/g" "${IOC_DIR}/"* -sed -i "s/@@[[:space:]]*agebd_env_suffix_lower[[:space:]]*@@/${AGEBD_ENV_SUFFIX_LOWER}/g" "${IOC_DIR}/"* -sed -i "s/@@[[:space:]]*ioc_port[[:space:]]*@@/${IOC_PORT}/g" "${IOC_DIR}/"* - -### SYSTEMD -if [ -f "${SYSTEMD_UNIT_FILE_PATH}" ]; then - sed -i "s/@@[[:space:]]*agebd_env[[:space:]]*@@/${AGEBD_ENV}/g" "${SYSTEMD_UNIT_FILE_PATH}" +# Every @@token@@ is resolved from config/environments.yml and +# config/services_registry.yml. An unknown or misspelled token aborts the +# deploy instead of leaving the placeholder in a file the IOC will read. +if ! uv run --directory scripts ci/render_subs.py \ + --env "${AGEBD_ENV}" \ + --service "${SERVICE_NAME_LOWER}" \ + "${IOC_DIR}" "${SERVICE_DIR}/systemd"; then + echo "Substitution failed -- aborting deploy of ${SERVICE_NAME}" >&2 + exit 1 fi diff --git a/ansible/inventories/dev/hosts.yml b/ansible/inventories/dev/hosts.yml index 3ac0e24..fe426e5 100644 --- a/ansible/inventories/dev/hosts.yml +++ b/ansible/inventories/dev/hosts.yml @@ -1,8 +1,8 @@ all: vars: + # Suffix values for this environment live in config/environments.yml -- + # do not reintroduce them here. agebd_env: "dev" - env_suffix_upper: "-DEV" - env_suffix_lower: "-dev" children: lc: diff --git a/ansible/inventories/prod/hosts.yml b/ansible/inventories/prod/hosts.yml index 20ea709..ec25a8e 100644 --- a/ansible/inventories/prod/hosts.yml +++ b/ansible/inventories/prod/hosts.yml @@ -1,8 +1,8 @@ all: vars: + # Suffix values for this environment live in config/environments.yml -- + # do not reintroduce them here. agebd_env: "prod" - env_suffix_upper: "" - env_suffix_lower: "" children: lc: diff --git a/ansible/playbooks/ioc-install.yml b/ansible/playbooks/ioc-install.yml index f337812..c78d698 100644 --- a/ansible/playbooks/ioc-install.yml +++ b/ansible/playbooks/ioc-install.yml @@ -5,6 +5,8 @@ vars: workspace_dir: "/tmp/hla_framework_bd" + # Controller-side checkout, where config/environments.yml is read from + repo_root: "{{ playbook_dir }}/../.." tasks: - name: Run ioc install tasks diff --git a/ansible/playbooks/ioc-restart.yml b/ansible/playbooks/ioc-restart.yml index a36728e..7c54986 100644 --- a/ansible/playbooks/ioc-restart.yml +++ b/ansible/playbooks/ioc-restart.yml @@ -5,6 +5,8 @@ vars: workspace_dir: "/tmp/hla_framework_bd" + # Controller-side checkout, where config/environments.yml is read from + repo_root: "{{ playbook_dir }}/../.." tasks: - name: Run ioc restart tasks diff --git a/ansible/playbooks/ioc-start.yml b/ansible/playbooks/ioc-start.yml index 02a6386..b50b4bc 100644 --- a/ansible/playbooks/ioc-start.yml +++ b/ansible/playbooks/ioc-start.yml @@ -8,6 +8,8 @@ vars: workspace_dir: "/tmp/hla_framework_bd" + # Controller-side checkout, where config/environments.yml is read from + repo_root: "{{ playbook_dir }}/../.." tasks: - name: Run ioc start tasks diff --git a/ansible/tasks/ioc/ioc-install.yml b/ansible/tasks/ioc/ioc-install.yml index d807ee4..d991c1c 100644 --- a/ansible/tasks/ioc/ioc-install.yml +++ b/ansible/tasks/ioc/ioc-install.yml @@ -8,6 +8,9 @@ - name: Get and set ioc_port ansible.builtin.import_tasks: ../utils/get-ioc-port.yml +- name: Load deploy-time substitutions + ansible.builtin.import_tasks: ../utils/load-substitutions.yml + - name: "[{{ target_service_name_lower }}] Establish environment naming conventions" ansible.builtin.set_fact: service_name_upper: "{{ target_service_name_lower | upper }}" @@ -16,9 +19,9 @@ 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" + target_subs_name: "AGEBD-CPCL-{{ service_name_upper }}{{ agebd_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" + target_params_name: "AGEBD-CPCL-{{ service_name_upper }}{{ agebd_env_suffix_upper }}_parameters.yaml" # Rename the subs file if we are in DEV - name: "[{{ target_service_name_lower }}] Rename substitution file for environment" @@ -32,26 +35,26 @@ 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 the @@agebd_env_suffix_upper@@ token 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 }}" +# Every @@token@@ is resolved from the central token table -- the token list +# is not repeated here, so a new token needs no change to this file. +- name: "[{{ target_service_name_lower }}] Collect deploy-time token values" + ansible.builtin.set_fact: + deploy_tokens: "{{ env_tokens | combine({'ioc_port': ioc_port}) }}" -# Replace the @@agebd_env_suffix_lower@@ and @@ioc_port@@ tokens inside the newly renamed params file -- name: "[{{ target_service_name_lower }}] Substitute environment token inside params file" +- name: "[{{ target_service_name_lower }}] Substitute deploy-time tokens in the IOC files" 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 }}" } + path: "{{ item.0 }}" + regexp: '@@\s*{{ item.1.key }}\s*@@' + replace: "{{ item.1.value | string }}" + loop: >- + {{ [ioc_base_dir ~ '/' ~ target_subs_name, ioc_base_dir ~ '/' ~ target_params_name] + | product(deploy_tokens | dict2items) | list }} + loop_control: + label: "{{ item.0 | basename }} :: {{ item.1.key }}" - 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" + cmd: "ioc install -V --facility sls --ioc AGEBD-CPCL-{{ service_name_upper }}{{ agebd_env_suffix_upper }} --clean" chdir: "{{ ioc_base_dir }}" changed_when: true register: ioc_install_result diff --git a/ansible/tasks/ioc/ioc-restart.yml b/ansible/tasks/ioc/ioc-restart.yml index ad637ac..8d846c9 100644 --- a/ansible/tasks/ioc/ioc-restart.yml +++ b/ansible/tasks/ioc/ioc-restart.yml @@ -5,6 +5,9 @@ - name: Clone repo ansible.builtin.import_tasks: ../utils/clone-repo.yml +- name: Load deploy-time substitutions + ansible.builtin.import_tasks: ../utils/load-substitutions.yml + - name: "[{{ target_service_name_lower }}] Establish environment naming conventions" ansible.builtin.set_fact: service_name_upper: "{{ target_service_name_lower | upper }}" @@ -15,6 +18,6 @@ - name: "[{{ target_service_name_lower }}] Restart IOC" ansible.builtin.shell: - cmd: "ioc restart AGEBD-CPCL-{{ service_name_upper }}{{ env_suffix_upper }}" + cmd: "ioc restart AGEBD-CPCL-{{ service_name_upper }}{{ agebd_env_suffix_upper }}" chdir: "{{ ioc_base_dir }}" changed_when: true diff --git a/ansible/tasks/service/service-deploy-and-restart.yml b/ansible/tasks/service/service-deploy-and-restart.yml index 2380c7c..7509cda 100644 --- a/ansible/tasks/service/service-deploy-and-restart.yml +++ b/ansible/tasks/service/service-deploy-and-restart.yml @@ -4,6 +4,9 @@ # 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: Load deploy-time substitutions + ansible.builtin.import_tasks: ../utils/load-substitutions.yml + - 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" @@ -24,11 +27,16 @@ 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" +# Every @@token@@ is resolved from the central token table -- the token list +# is not repeated here, so a new token needs no change to this file. +- name: "[{{ target_service_name_lower }}] Substitute deploy-time tokens in the systemd unit" ansible.builtin.replace: path: "{{ svc_current_dir }}/systemd/{{ service_unit_name }}" - regexp: '@@\s*agebd_env\s*@@' - replace: "{{ agebd_env }}" + regexp: '@@\s*{{ item.key }}\s*@@' + replace: "{{ item.value | string }}" + loop: "{{ env_tokens | dict2items }}" + loop_control: + label: "{{ item.key }}" # systemctl --user link --force "./{{ service_unit_name }}" - name: "[{{ target_service_name_lower }}] Symlink systemd unit file (Absolute Path)" diff --git a/ansible/tasks/utils/load-substitutions.yml b/ansible/tasks/utils/load-substitutions.yml new file mode 100644 index 0000000..f63a26a --- /dev/null +++ b/ansible/tasks/utils/load-substitutions.yml @@ -0,0 +1,32 @@ +--- +# Load the deploy-time token values for {{ agebd_env }} from the single source +# of truth, config/environments.yml. +# +# The inventory says which environment it is; this file says what that +# environment means. Do not reintroduce suffix values into the inventories. +# +# include_vars reads on the controller, where the repo checkout lives, so this +# works for both local-connection plays and plays targeting remote hosts. +# +# Ansible substitutes tokens with ansible.builtin.replace rather than calling +# agebd.subs, because these tasks also run on hosts that have no uv or Python +# environment for this repo. The values and the token list still come from the +# central config, so there is nothing to keep in sync by hand. + +- name: Load the central substitution config + ansible.builtin.include_vars: + file: "{{ repo_root }}/config/environments.yml" + name: substitutions + +- name: Fail if this environment is not declared centrally + ansible.builtin.fail: + msg: >- + Environment '{{ agebd_env }}' is not declared in config/environments.yml. + Declared: {{ substitutions.environments.keys() | list | join(', ') }} + when: agebd_env not in substitutions.environments + +- name: Select the deploy-time token values for this environment + ansible.builtin.set_fact: + env_tokens: "{{ substitutions.environments[agebd_env] }}" + agebd_env_suffix_upper: "{{ substitutions.environments[agebd_env].agebd_env_suffix_upper }}" + agebd_env_suffix_lower: "{{ substitutions.environments[agebd_env].agebd_env_suffix_lower }}" diff --git a/scripts/ci/render_subs.py b/scripts/ci/render_subs.py new file mode 100644 index 0000000..9deb165 --- /dev/null +++ b/scripts/ci/render_subs.py @@ -0,0 +1,71 @@ +""" +Resolve deploy-time tokens in deployed files. + +Values come from config/environments.yml and config/services_registry.yml -- +the single source of truth. Nothing here knows what '-DEV' is. + + render_subs.py --env dev --service tune /path/to/ioc /path/to/systemd + render_subs.py --env prod /sls/bd/hla/prod/qt + +Without --service only the environment tokens are available, so a file that +needs a per-service token (ioc_port) fails loudly rather than shipping the +placeholder. A path that does not exist is reported and skipped, which is how +services without a systemd unit are handled. +""" + +import argparse +import sys +from pathlib import Path + +from agebd.subs import SubstitutionError, Substitutions + + +def render(subs, paths): + """ + Render every path in place. Returns the files that changed. + """ + changed = [] + for path in paths: + if not path.exists(): + print(f"skipped (does not exist): {path}") + continue + if path.is_dir(): + changed.extend(subs.render_tree(path)) + elif subs.render_file(path): + changed.append(path) + return changed + + +def main(argv=None): + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + parser.add_argument("--env", required=True, help="Deployment environment, e.g. dev") + parser.add_argument( + "--service", + default=None, + help="Service name. Required for files holding per-service tokens.", + ) + parser.add_argument("paths", nargs="+", type=Path, help="Files or directories to render") + args = parser.parse_args(argv) + + if args.service: + subs = Substitutions.for_service(args.env, args.service) + else: + subs = Substitutions.for_env(args.env) + + changed = render(subs, args.paths) + + for path in changed: + print(f"rendered: {path}") + print(f"{len(changed)} file(s) rendered for env '{args.env}'") + return 0 + + +if __name__ == "__main__": + try: + sys.exit(main()) + except SubstitutionError as e: + print(f"error: {e}", file=sys.stderr) + sys.exit(1) diff --git a/scripts/tests/test_render_subs.py b/scripts/tests/test_render_subs.py new file mode 100644 index 0000000..72b0a23 --- /dev/null +++ b/scripts/tests/test_render_subs.py @@ -0,0 +1,93 @@ +import pytest +from agebd.subs import SubstitutionError, Substitutions, UnknownTokenError +from agebd.utils import get_git_root + +from ci.render_subs import main, render + +REPO_ROOT = get_git_root(__file__) +CONFIG_DIR = REPO_ROOT / "config" + + +@pytest.fixture +def service_tree(tmp_path): + ioc = tmp_path / "ioc" + ioc.mkdir() + (ioc / "AGEBD-CPCL-TUNE_main.subs").write_text("{ AGEBD-TUNE@@agebd_env_suffix_upper@@ }\n") + (ioc / "AGEBD-CPCL-TUNE_parameters.yaml").write_text( + "ioc_host: sls-vserv-bd-01@@agebd_env_suffix_lower@@\nioc_port: @@ioc_port@@\n" + ) + systemd = tmp_path / "systemd" + systemd.mkdir() + (systemd / "AGEBD-SERVICE-TUNE.service").write_text("Environment=AGEBD_ENV=@@agebd_env@@\n") + return tmp_path + + +def test_renders_a_whole_service_for_dev(service_tree): + subs = Substitutions.for_service("dev", "tune", config_dir=CONFIG_DIR) + + changed = render(subs, [service_tree / "ioc", service_tree / "systemd"]) + + assert len(changed) == 3 + assert "AGEBD-TUNE-DEV" in (service_tree / "ioc/AGEBD-CPCL-TUNE_main.subs").read_text() + assert (service_tree / "ioc/AGEBD-CPCL-TUNE_parameters.yaml").read_text() == ( + "ioc_host: sls-vserv-bd-01-dev\nioc_port: 50007\n" + ) + assert (service_tree / "systemd/AGEBD-SERVICE-TUNE.service").read_text() == ( + "Environment=AGEBD_ENV=dev\n" + ) + + +def test_renders_a_whole_service_for_prod(service_tree): + subs = Substitutions.for_service("prod", "tune", config_dir=CONFIG_DIR) + + render(subs, [service_tree / "ioc", service_tree / "systemd"]) + + assert "{ AGEBD-TUNE }" in (service_tree / "ioc/AGEBD-CPCL-TUNE_main.subs").read_text() + assert "sls-vserv-bd-01\n" in (service_tree / "ioc/AGEBD-CPCL-TUNE_parameters.yaml").read_text() + + +def test_missing_path_is_skipped_not_fatal(service_tree, capsys): + subs = Substitutions.for_service("dev", "tune", config_dir=CONFIG_DIR) + + render(subs, [service_tree / "systemd", service_tree / "does-not-exist"]) + + assert "skipped (does not exist)" in capsys.readouterr().out + + +def test_leaves_nothing_unrendered(service_tree): + subs = Substitutions.for_service("dev", "tune", config_dir=CONFIG_DIR) + + render(subs, [service_tree]) + + for path in service_tree.rglob("*"): + if path.is_file(): + assert "@@" not in path.read_text(), path + + +def test_rendering_is_idempotent(service_tree): + subs = Substitutions.for_service("dev", "tune", config_dir=CONFIG_DIR) + + assert len(render(subs, [service_tree])) == 3 + assert render(subs, [service_tree]) == [] + + +def test_per_service_token_without_service_fails_loudly(service_tree): + """Without --service there is no ioc_port, and that must not pass silently.""" + subs = Substitutions.for_env("dev", config_dir=CONFIG_DIR) + + with pytest.raises(UnknownTokenError, match="ioc_port"): + render(subs, [service_tree / "ioc"]) + + +def test_main_renders_via_the_command_line(service_tree): + exit_code = main(["--env", "dev", "--service", "tune", str(service_tree / "systemd")]) + + assert exit_code == 0 + assert (service_tree / "systemd/AGEBD-SERVICE-TUNE.service").read_text() == ( + "Environment=AGEBD_ENV=dev\n" + ) + + +def test_main_rejects_an_undeclared_environment(service_tree): + with pytest.raises(SubstitutionError, match="staging"): + main(["--env", "staging", "--service", "tune", str(service_tree / "systemd")]) -- 2.54.0 From ee5f331f4c8a3e255f2d340e56babee554ec1db0 Mon Sep 17 00:00:00 2001 From: Benjamin Labrecque Date: Thu, 20 Aug 2026 12:12:11 +0200 Subject: [PATCH 3/4] feat: render qt/ at deploy time and enforce the suffix (step 4) qt/ was declared a render path in step 1 but nothing rendered it: the Qt deploy step was a plain rsync, so the UI files shipped with literal placeholders in every PV name. * deploy.yml renders the deployed qt/ directory with render_subs.py after the rsync. No --service is needed; qt holds no per-service token, and a file that acquired one would fail the step rather than ship the placeholder. * bin/sls_hla_launch_gui.sh no longer passes an AGEBD_ENV_SUFFIX macro. No .ui file has referenced $(AGEBD_ENV_SUFFIX) since a06fded, and the suffix is now baked in at deploy time. This removes the last hardcoded '-DEV' outside config/environments.yml. check_ui_files.py is rewritten for the chosen convention. It asserted the old caQtDM macro, and its regex had stopped matching anything at all once placeholders appeared in device names -- against the pre-fix Service Manager it inspected 0 names, where the new check finds 16 violations. The new rule: every AGEBD- device name carries the suffix token, except systemd unit names, which are the same in both environments. The token name is read from the central config so a rename cannot leave this check enforcing a stale one. Fixing what that check surfaced, all in A_BD_ServiceManager.ui: * 16 'IOC=AGEBD-CPCL-' caInclude macro values had no suffix. The included UI uses them as PV prefixes ($(IOC):STATUS, $(IOC):RESTART), so the dev Service Manager was reading status from, and sending restarts to, production IOCs. * Two ssh commands hardcoded sls-vserv-bd-hla01, so the dev GUI's restart button targeted the production HLA host. * cli generates those macro values, so the generator emits the token too and new services are no longer born with the bug. These were latent while qt/ shipped unrendered placeholders; turning rendering on would have made them live. Verified: dev renders -DEV device names and the -dev host, prod renders byte-identical to the currently deployed prod files, no placeholder survives in either, and all 24 UI files stay well-formed XML. Co-Authored-By: Claude Opus 5 --- .gitea/workflows/deploy.yml | 5 + bin/sls_hla_launch_gui.sh | 9 +- cli/src/models/service_manager_ui.py | 5 +- .../expected_output/qt/A_BD_ServiceManager.ui | 10 +- .../test_repo_root/qt/A_BD_ServiceManager.ui | 10 +- qt/A_BD_ServiceManager.ui | 10 +- scripts/ci/check_ui_files.py | 96 ++++++++++++++++--- scripts/tests/test_check_ui_files.py | 66 ++++++++++++- 8 files changed, 174 insertions(+), 37 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index ef7e9ff..d211764 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -116,6 +116,11 @@ jobs: --exclude='.pytest_cache/' \ ./qt/* "${DEST_DIR}/" + # Resolve @@token@@ in the deployed UI files. qt/ holds no + # per-service token, so no --service is needed; a file that + # acquired one would fail here rather than ship the placeholder. + uv run --directory scripts ci/render_subs.py --env "${AGEBD_ENV}" "${DEST_DIR}" + # ----------------------------------------------------------------- # Services Detection, Testing, and Deployment # ----------------------------------------------------------------- diff --git a/bin/sls_hla_launch_gui.sh b/bin/sls_hla_launch_gui.sh index 88de269..84aa7bc 100755 --- a/bin/sls_hla_launch_gui.sh +++ b/bin/sls_hla_launch_gui.sh @@ -4,12 +4,13 @@ UI_FILENAME=$1 AGEBD_ENV=$2 # 'dev' for dev environment, any other string launches prod. REMAINING_ARGS=( "${@:3}" ) +# The environment suffix is baked into the UI files when qt/ is rendered at +# deploy time, from config/environments.yml. Launching from +# /sls/bd/hla/${AGEBD_ENV}/qt therefore already targets the right devices, so +# no AGEBD_ENV_SUFFIX macro is passed here. if [ "$AGEBD_ENV" = "dev" ]; then - AGEBD_ENV_SUFFIX="-DEV" EPICS_CA_ADDR_LIST="$EPICS_CA_ADDR_LIST 129.129.146.255" -else - AGEBD_ENV_SUFFIX="" fi export EPICS_CA_ADDR_LIST -caqtdm -macro "AGEBD_ENV_SUFFIX=${AGEBD_ENV_SUFFIX}" "${REMAINING_ARGS[@]}" "${UI_FILENAME}" +caqtdm "${REMAINING_ARGS[@]}" "${UI_FILENAME}" diff --git a/cli/src/models/service_manager_ui.py b/cli/src/models/service_manager_ui.py index 8dc3a45..4d64ebe 100644 --- a/cli/src/models/service_manager_ui.py +++ b/cli/src/models/service_manager_ui.py @@ -133,8 +133,11 @@ class _ServiceManagerUIMacroElement(BaseModel): ui_filename: str def to_string(self) -> str: + # The IOC macro is used as a PV prefix inside the included UI + # ($(IOC):STATUS, $(IOC):RESTART), so it carries the environment + # suffix token and is resolved when qt/ is rendered at deploy time. return ( - f"IOC=AGEBD-CPCL-{self.service_name_upper}," + f"IOC=AGEBD-CPCL-{self.service_name_upper}@@agebd_env_suffix_upper@@," f"service={self.service_name_upper}," f"name={self.service_name_camel}," f"panel={self.panel}," diff --git a/cli/tests/fixtures/expected_output/qt/A_BD_ServiceManager.ui b/cli/tests/fixtures/expected_output/qt/A_BD_ServiceManager.ui index 4260a44..812e708 100644 --- a/cli/tests/fixtures/expected_output/qt/A_BD_ServiceManager.ui +++ b/cli/tests/fixtures/expected_output/qt/A_BD_ServiceManager.ui @@ -138,7 +138,7 @@ caLabel[statusTip="Operation"]{ - IOC=AGEBD-CPCL-DBPM3CURR,service=DBPM3CURR,name=DBPM3Curr,panel=1,svc_exist=1,panelcmd=A_BD_DBPM3Curr.ui;IOC=AGEBD-CPCL-TAUBPM,service=TAUBPM,name=TauBPM,panel=1,svc_exist=1,panelcmd=A_BD_TauBPM.ui;IOC=AGEBD-CPCL-TAUPCT,service=TAUPCT,name=TauPCT,panel=1,svc_exist=1,panelcmd=A_BD_TauPCT.ui;IOC=AGEBD-CPCL-TIMING,service=TIMING,name=Timing,panel=1,svc_exist=1,panelcmd=A_BD_Timing.ui;IOC=AGEBD-CPCL-SCRUBBING,service=SCRUBBING,name=Scrubbing,panel=1,svc_exist=1,panelcmd=A_BD_Scrubbing.ui;IOC=AGEBD-CPCL-INJECTIONGUARD,service=INJECTIONGUARD,name=InjectionGuard,panel=1,svc_exist=1,panelcmd=A_BD_InjectionGuard.ui;IOC=AGEBD-CPCL-POSTMORTEMLOG,service=POSTMORTEMLOG,name=PostMortemLog,panel=1,svc_exist=1,panelcmd=A_BD_PostMortemLog.ui;IOC=AGEBD-CPCL-TUNEBUMP,service=TUNEBUMP,name=TuneBump,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-PLOTS,service=PLOTS,name=Plots,panel=0,svc_exist=1,panelcmd=A_BD_Plots.ui;IOC=AGEBD-CPCL-ORBITBUMP,service=ORBITBUMP,name=OrbitBump,panel=1,svc_exist=0,panelcmd=A_BD_OrbitBump.ui;IOC=AGEBD-CPCL-TUNEFBX,service=TUNEFBX,name=Hor. Tune Feedback,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-TUNEFBY,service=TUNEFBY,name=Ver. Tune Feedback,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-TESTSERVICE99-X00,service=TESTSERVICE99-X00,name=TestService99-X00,panel=1,svc_exist=1,panelcmd=A_BD_TestService99-X00.ui + IOC=AGEBD-CPCL-DBPM3CURR@@agebd_env_suffix_upper@@,service=DBPM3CURR,name=DBPM3Curr,panel=1,svc_exist=1,panelcmd=A_BD_DBPM3Curr.ui;IOC=AGEBD-CPCL-TAUBPM@@agebd_env_suffix_upper@@,service=TAUBPM,name=TauBPM,panel=1,svc_exist=1,panelcmd=A_BD_TauBPM.ui;IOC=AGEBD-CPCL-TAUPCT@@agebd_env_suffix_upper@@,service=TAUPCT,name=TauPCT,panel=1,svc_exist=1,panelcmd=A_BD_TauPCT.ui;IOC=AGEBD-CPCL-TIMING@@agebd_env_suffix_upper@@,service=TIMING,name=Timing,panel=1,svc_exist=1,panelcmd=A_BD_Timing.ui;IOC=AGEBD-CPCL-SCRUBBING@@agebd_env_suffix_upper@@,service=SCRUBBING,name=Scrubbing,panel=1,svc_exist=1,panelcmd=A_BD_Scrubbing.ui;IOC=AGEBD-CPCL-INJECTIONGUARD@@agebd_env_suffix_upper@@,service=INJECTIONGUARD,name=InjectionGuard,panel=1,svc_exist=1,panelcmd=A_BD_InjectionGuard.ui;IOC=AGEBD-CPCL-POSTMORTEMLOG@@agebd_env_suffix_upper@@,service=POSTMORTEMLOG,name=PostMortemLog,panel=1,svc_exist=1,panelcmd=A_BD_PostMortemLog.ui;IOC=AGEBD-CPCL-TUNEBUMP@@agebd_env_suffix_upper@@,service=TUNEBUMP,name=TuneBump,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-PLOTS@@agebd_env_suffix_upper@@,service=PLOTS,name=Plots,panel=0,svc_exist=1,panelcmd=A_BD_Plots.ui;IOC=AGEBD-CPCL-ORBITBUMP@@agebd_env_suffix_upper@@,service=ORBITBUMP,name=OrbitBump,panel=1,svc_exist=0,panelcmd=A_BD_OrbitBump.ui;IOC=AGEBD-CPCL-TUNEFBX@@agebd_env_suffix_upper@@,service=TUNEFBX,name=Hor. Tune Feedback,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-TUNEFBY@@agebd_env_suffix_upper@@,service=TUNEFBY,name=Ver. Tune Feedback,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-TESTSERVICE99-X00@@agebd_env_suffix_upper@@,service=TESTSERVICE99-X00,name=TestService99-X00,panel=1,svc_exist=1,panelcmd=A_BD_TestService99-X00.ui A_BD_ServiceManager_inc.ui @@ -246,7 +246,7 @@ caLabel[statusTip="Operation"]{ - IOC=AGEBD-CPCL-NTURNS,service=NTURNS,name=NTurns,panel=1,svc_exist=1,panelcmd=A_BD_NTurns.ui;IOC=AGEBD-CPCL-TOPUPTOOL,service=TOPUPTOOL,name=TopUpTool,panel=1,svc_exist=1,panelcmd=A_BD_TopUpTool.ui;IOC=AGEBD-CPCL-TUNE,service=TUNE,name=Tune,panel=1,svc_exist=1,panelcmd=A_BD_Tune.ui;IOC=AGEOP-CPCL-SHIFTTOOL,service=SHIFTTOOL,name=Shifttool,panel=1,svc_exist=1,panelcmd=A_OP_SchichtProtokollTool.ui,macro=FACILITY=SLS + IOC=AGEBD-CPCL-NTURNS@@agebd_env_suffix_upper@@,service=NTURNS,name=NTurns,panel=1,svc_exist=1,panelcmd=A_BD_NTurns.ui;IOC=AGEBD-CPCL-TOPUPTOOL@@agebd_env_suffix_upper@@,service=TOPUPTOOL,name=TopUpTool,panel=1,svc_exist=1,panelcmd=A_BD_TopUpTool.ui;IOC=AGEBD-CPCL-TUNE@@agebd_env_suffix_upper@@,service=TUNE,name=Tune,panel=1,svc_exist=1,panelcmd=A_BD_Tune.ui;IOC=AGEOP-CPCL-SHIFTTOOL,service=SHIFTTOOL,name=Shifttool,panel=1,svc_exist=1,panelcmd=A_OP_SchichtProtokollTool.ui,macro=FACILITY=SLS A_BD_ServiceManager_inc.ui @@ -792,7 +792,7 @@ caLabel[statusTip="Operation"]{ /ioc/modules/qt/iocStats.ui - IOC=AGEBD-CPCL-MASTER; + IOC=AGEBD-CPCL-MASTER@@agebd_env_suffix_upper@@; @@ -986,7 +986,7 @@ caLabel[statusTip="Operation"]{ false - ssh svcusr-sls2hla@sls-vserv-bd-hla01 systemctl --user restart AGEBD-SERVICE-MASTER.service + ssh svcusr-sls2hla@sls-vserv-bd-hla01@@agebd_env_suffix_lower@@ systemctl --user restart AGEBD-SERVICE-MASTER.service @@ -1015,7 +1015,7 @@ caLabel[statusTip="Operation"]{ false - terminator -e "ssh svcusr-sls2hla@sls-vserv-bd-hla01" + terminator -e "ssh svcusr-sls2hla@sls-vserv-bd-hla01@@agebd_env_suffix_lower@@" diff --git a/cli/tests/fixtures/test_repo_root/qt/A_BD_ServiceManager.ui b/cli/tests/fixtures/test_repo_root/qt/A_BD_ServiceManager.ui index d2c3936..39cf352 100644 --- a/cli/tests/fixtures/test_repo_root/qt/A_BD_ServiceManager.ui +++ b/cli/tests/fixtures/test_repo_root/qt/A_BD_ServiceManager.ui @@ -138,7 +138,7 @@ caLabel[statusTip="Operation"]{ - IOC=AGEBD-CPCL-DBPM3CURR,service=DBPM3CURR,name=DBPM3Curr,panel=1,svc_exist=1,panelcmd=A_BD_DBPM3Curr.ui;IOC=AGEBD-CPCL-TAUBPM,service=TAUBPM,name=TauBPM,panel=1,svc_exist=1,panelcmd=A_BD_TauBPM.ui;IOC=AGEBD-CPCL-TAUPCT,service=TAUPCT,name=TauPCT,panel=1,svc_exist=1,panelcmd=A_BD_TauPCT.ui;IOC=AGEBD-CPCL-TIMING,service=TIMING,name=Timing,panel=1,svc_exist=1,panelcmd=A_BD_Timing.ui;IOC=AGEBD-CPCL-SCRUBBING,service=SCRUBBING,name=Scrubbing,panel=1,svc_exist=1,panelcmd=A_BD_Scrubbing.ui;IOC=AGEBD-CPCL-INJECTIONGUARD,service=INJECTIONGUARD,name=InjectionGuard,panel=1,svc_exist=1,panelcmd=A_BD_InjectionGuard.ui;IOC=AGEBD-CPCL-POSTMORTEMLOG,service=POSTMORTEMLOG,name=PostMortemLog,panel=1,svc_exist=1,panelcmd=A_BD_PostMortemLog.ui;IOC=AGEBD-CPCL-TUNEBUMP,service=TUNEBUMP,name=TuneBump,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-PLOTS,service=PLOTS,name=Plots,panel=0,svc_exist=1,panelcmd=A_BD_Plots.ui;IOC=AGEBD-CPCL-ORBITBUMP,service=ORBITBUMP,name=OrbitBump,panel=1,svc_exist=0,panelcmd=A_BD_OrbitBump.ui;IOC=AGEBD-CPCL-TUNEFBX,service=TUNEFBX,name=Hor. Tune Feedback,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-TUNEFBY,service=TUNEFBY,name=Ver. Tune Feedback,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui + IOC=AGEBD-CPCL-DBPM3CURR@@agebd_env_suffix_upper@@,service=DBPM3CURR,name=DBPM3Curr,panel=1,svc_exist=1,panelcmd=A_BD_DBPM3Curr.ui;IOC=AGEBD-CPCL-TAUBPM@@agebd_env_suffix_upper@@,service=TAUBPM,name=TauBPM,panel=1,svc_exist=1,panelcmd=A_BD_TauBPM.ui;IOC=AGEBD-CPCL-TAUPCT@@agebd_env_suffix_upper@@,service=TAUPCT,name=TauPCT,panel=1,svc_exist=1,panelcmd=A_BD_TauPCT.ui;IOC=AGEBD-CPCL-TIMING@@agebd_env_suffix_upper@@,service=TIMING,name=Timing,panel=1,svc_exist=1,panelcmd=A_BD_Timing.ui;IOC=AGEBD-CPCL-SCRUBBING@@agebd_env_suffix_upper@@,service=SCRUBBING,name=Scrubbing,panel=1,svc_exist=1,panelcmd=A_BD_Scrubbing.ui;IOC=AGEBD-CPCL-INJECTIONGUARD@@agebd_env_suffix_upper@@,service=INJECTIONGUARD,name=InjectionGuard,panel=1,svc_exist=1,panelcmd=A_BD_InjectionGuard.ui;IOC=AGEBD-CPCL-POSTMORTEMLOG@@agebd_env_suffix_upper@@,service=POSTMORTEMLOG,name=PostMortemLog,panel=1,svc_exist=1,panelcmd=A_BD_PostMortemLog.ui;IOC=AGEBD-CPCL-TUNEBUMP@@agebd_env_suffix_upper@@,service=TUNEBUMP,name=TuneBump,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-PLOTS@@agebd_env_suffix_upper@@,service=PLOTS,name=Plots,panel=0,svc_exist=1,panelcmd=A_BD_Plots.ui;IOC=AGEBD-CPCL-ORBITBUMP@@agebd_env_suffix_upper@@,service=ORBITBUMP,name=OrbitBump,panel=1,svc_exist=0,panelcmd=A_BD_OrbitBump.ui;IOC=AGEBD-CPCL-TUNEFBX@@agebd_env_suffix_upper@@,service=TUNEFBX,name=Hor. Tune Feedback,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-TUNEFBY@@agebd_env_suffix_upper@@,service=TUNEFBY,name=Ver. Tune Feedback,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui A_BD_ServiceManager_inc.ui @@ -246,7 +246,7 @@ caLabel[statusTip="Operation"]{ - IOC=AGEBD-CPCL-NTURNS,service=NTURNS,name=NTurns,panel=1,svc_exist=1,panelcmd=A_BD_NTurns.ui;IOC=AGEBD-CPCL-TOPUPTOOL,service=TOPUPTOOL,name=TopUpTool,panel=1,svc_exist=1,panelcmd=A_BD_TopUpTool.ui;IOC=AGEBD-CPCL-TUNE,service=TUNE,name=Tune,panel=1,svc_exist=1,panelcmd=A_BD_Tune.ui;IOC=AGEOP-CPCL-SHIFTTOOL,service=SHIFTTOOL,name=Shifttool,panel=1,svc_exist=1,panelcmd=A_OP_SchichtProtokollTool.ui,macro=FACILITY=SLS + IOC=AGEBD-CPCL-NTURNS@@agebd_env_suffix_upper@@,service=NTURNS,name=NTurns,panel=1,svc_exist=1,panelcmd=A_BD_NTurns.ui;IOC=AGEBD-CPCL-TOPUPTOOL@@agebd_env_suffix_upper@@,service=TOPUPTOOL,name=TopUpTool,panel=1,svc_exist=1,panelcmd=A_BD_TopUpTool.ui;IOC=AGEBD-CPCL-TUNE@@agebd_env_suffix_upper@@,service=TUNE,name=Tune,panel=1,svc_exist=1,panelcmd=A_BD_Tune.ui;IOC=AGEOP-CPCL-SHIFTTOOL,service=SHIFTTOOL,name=Shifttool,panel=1,svc_exist=1,panelcmd=A_OP_SchichtProtokollTool.ui,macro=FACILITY=SLS A_BD_ServiceManager_inc.ui @@ -792,7 +792,7 @@ caLabel[statusTip="Operation"]{ /ioc/modules/qt/iocStats.ui - IOC=AGEBD-CPCL-MASTER; + IOC=AGEBD-CPCL-MASTER@@agebd_env_suffix_upper@@; @@ -986,7 +986,7 @@ caLabel[statusTip="Operation"]{ false - ssh svcusr-sls2hla@sls-vserv-bd-hla01 systemctl --user restart AGEBD-SERVICE-MASTER.service + ssh svcusr-sls2hla@sls-vserv-bd-hla01@@agebd_env_suffix_lower@@ systemctl --user restart AGEBD-SERVICE-MASTER.service @@ -1015,7 +1015,7 @@ caLabel[statusTip="Operation"]{ false - terminator -e "ssh svcusr-sls2hla@sls-vserv-bd-hla01" + terminator -e "ssh svcusr-sls2hla@sls-vserv-bd-hla01@@agebd_env_suffix_lower@@" diff --git a/qt/A_BD_ServiceManager.ui b/qt/A_BD_ServiceManager.ui index 3539295..70c6b15 100644 --- a/qt/A_BD_ServiceManager.ui +++ b/qt/A_BD_ServiceManager.ui @@ -138,7 +138,7 @@ caLabel[statusTip="Operation"]{ - IOC=AGEBD-CPCL-DBPM3CURR,service=DBPM3CURR,name=DBPM3Curr,panel=1,svc_exist=1,panelcmd=A_BD_DBPM3Curr.ui;IOC=AGEBD-CPCL-TAUBPM,service=TAUBPM,name=TauBPM,panel=1,svc_exist=1,panelcmd=A_BD_TauBPM.ui;IOC=AGEBD-CPCL-TAUPCT,service=TAUPCT,name=TauPCT,panel=1,svc_exist=1,panelcmd=A_BD_TauPCT.ui;IOC=AGEBD-CPCL-TIMING,service=TIMING,name=Timing,panel=1,svc_exist=1,panelcmd=A_BD_Timing.ui;IOC=AGEBD-CPCL-SCRUBBING,service=SCRUBBING,name=Scrubbing,panel=1,svc_exist=1,panelcmd=A_BD_Scrubbing.ui;IOC=AGEBD-CPCL-INJECTIONGUARD,service=INJECTIONGUARD,name=InjectionGuard,panel=1,svc_exist=1,panelcmd=A_BD_InjectionGuard.ui;IOC=AGEBD-CPCL-POSTMORTEMLOG,service=POSTMORTEMLOG,name=PostMortemLog,panel=1,svc_exist=1,panelcmd=A_BD_PostMortemLog.ui;IOC=AGEBD-CPCL-TUNEBUMP,service=TUNEBUMP,name=TuneBump,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-PLOTS,service=PLOTS,name=Plots,panel=0,svc_exist=1,panelcmd=A_BD_Plots.ui;IOC=AGEBD-CPCL-ORBITBUMP,service=ORBITBUMP,name=OrbitBump,panel=1,svc_exist=0,panelcmd=A_BD_OrbitBump.ui;IOC=AGEBD-CPCL-TUNEFBX,service=TUNEFBX,name=TuneFBx,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-TUNEFBY,service=TUNEFBY,name=TuneFBy,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui + IOC=AGEBD-CPCL-DBPM3CURR@@agebd_env_suffix_upper@@,service=DBPM3CURR,name=DBPM3Curr,panel=1,svc_exist=1,panelcmd=A_BD_DBPM3Curr.ui;IOC=AGEBD-CPCL-TAUBPM@@agebd_env_suffix_upper@@,service=TAUBPM,name=TauBPM,panel=1,svc_exist=1,panelcmd=A_BD_TauBPM.ui;IOC=AGEBD-CPCL-TAUPCT@@agebd_env_suffix_upper@@,service=TAUPCT,name=TauPCT,panel=1,svc_exist=1,panelcmd=A_BD_TauPCT.ui;IOC=AGEBD-CPCL-TIMING@@agebd_env_suffix_upper@@,service=TIMING,name=Timing,panel=1,svc_exist=1,panelcmd=A_BD_Timing.ui;IOC=AGEBD-CPCL-SCRUBBING@@agebd_env_suffix_upper@@,service=SCRUBBING,name=Scrubbing,panel=1,svc_exist=1,panelcmd=A_BD_Scrubbing.ui;IOC=AGEBD-CPCL-INJECTIONGUARD@@agebd_env_suffix_upper@@,service=INJECTIONGUARD,name=InjectionGuard,panel=1,svc_exist=1,panelcmd=A_BD_InjectionGuard.ui;IOC=AGEBD-CPCL-POSTMORTEMLOG@@agebd_env_suffix_upper@@,service=POSTMORTEMLOG,name=PostMortemLog,panel=1,svc_exist=1,panelcmd=A_BD_PostMortemLog.ui;IOC=AGEBD-CPCL-TUNEBUMP@@agebd_env_suffix_upper@@,service=TUNEBUMP,name=TuneBump,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-PLOTS@@agebd_env_suffix_upper@@,service=PLOTS,name=Plots,panel=0,svc_exist=1,panelcmd=A_BD_Plots.ui;IOC=AGEBD-CPCL-ORBITBUMP@@agebd_env_suffix_upper@@,service=ORBITBUMP,name=OrbitBump,panel=1,svc_exist=0,panelcmd=A_BD_OrbitBump.ui;IOC=AGEBD-CPCL-TUNEFBX@@agebd_env_suffix_upper@@,service=TUNEFBX,name=TuneFBx,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-TUNEFBY@@agebd_env_suffix_upper@@,service=TUNEFBY,name=TuneFBy,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui A_BD_ServiceManager_inc.ui @@ -246,7 +246,7 @@ caLabel[statusTip="Operation"]{ - IOC=AGEBD-CPCL-NTURNS,service=NTURNS,name=NTurns,panel=1,svc_exist=1,panelcmd=A_BD_NTurns.ui;IOC=AGEBD-CPCL-TOPUPTOOL,service=TOPUPTOOL,name=TopUpTool,panel=1,svc_exist=1,panelcmd=A_BD_TopUpTool.ui;IOC=AGEBD-CPCL-TUNE,service=TUNE,name=Tune,panel=1,svc_exist=1,panelcmd=A_BD_Tune.ui;IOC=AGEOP-CPCL-SHIFTTOOL,service=SHIFTTOOL,name=Shifttool,panel=1,svc_exist=1,panelcmd=A_OP_SchichtProtokollTool.ui,macro=FACILITY=SLS + IOC=AGEBD-CPCL-NTURNS@@agebd_env_suffix_upper@@,service=NTURNS,name=NTurns,panel=1,svc_exist=1,panelcmd=A_BD_NTurns.ui;IOC=AGEBD-CPCL-TOPUPTOOL@@agebd_env_suffix_upper@@,service=TOPUPTOOL,name=TopUpTool,panel=1,svc_exist=1,panelcmd=A_BD_TopUpTool.ui;IOC=AGEBD-CPCL-TUNE@@agebd_env_suffix_upper@@,service=TUNE,name=Tune,panel=1,svc_exist=1,panelcmd=A_BD_Tune.ui;IOC=AGEOP-CPCL-SHIFTTOOL,service=SHIFTTOOL,name=Shifttool,panel=1,svc_exist=1,panelcmd=A_OP_SchichtProtokollTool.ui,macro=FACILITY=SLS A_BD_ServiceManager_inc.ui @@ -792,7 +792,7 @@ caLabel[statusTip="Operation"]{ /ioc/modules/qt/iocStats.ui - IOC=AGEBD-CPCL-MASTER; + IOC=AGEBD-CPCL-MASTER@@agebd_env_suffix_upper@@; @@ -986,7 +986,7 @@ caLabel[statusTip="Operation"]{ false - ssh svcusr-sls2hla@sls-vserv-bd-hla01 systemctl --user restart AGEBD-SERVICE-MASTER.service + ssh svcusr-sls2hla@sls-vserv-bd-hla01@@agebd_env_suffix_lower@@ systemctl --user restart AGEBD-SERVICE-MASTER.service @@ -1015,7 +1015,7 @@ caLabel[statusTip="Operation"]{ false - terminator -e "ssh svcusr-sls2hla@sls-vserv-bd-hla01" + terminator -e "ssh svcusr-sls2hla@sls-vserv-bd-hla01@@agebd_env_suffix_lower@@" diff --git a/scripts/ci/check_ui_files.py b/scripts/ci/check_ui_files.py index 6b7a9c2..1b00d52 100644 --- a/scripts/ci/check_ui_files.py +++ b/scripts/ci/check_ui_files.py @@ -1,25 +1,91 @@ -import re +""" +Guard the environment suffix in Qt UI files. +qt/ is rendered at deploy time (see config/environments.yml), so every EPICS +device name in a .ui file must carry the suffix token. A name without it +resolves to the production device in every environment -- which is how the +dev Service Manager ended up driving prod IOCs. + +The rule is: every AGEBD- name is immediately followed by the suffix token. +The one exception is systemd unit names, which genuinely have no environment +suffix (the unit file is AGEBD-SERVICE-.service in both environments). + +This replaces an earlier check for the caQtDM macro '$(AGEBD_ENV_SUFFIX)', +which was abandoned in favour of deploy-time rendering. That check had also +stopped matching anything once placeholders appeared in the names. +""" + +import re +import sys + +from agebd.subs import SubstitutionsConfig from agebd.utils import get_git_root REPO_ROOT = get_git_root(__file__) QT_DIR = REPO_ROOT / "qt" +SUFFIX_TOKEN_NAME = "agebd_env_suffix_upper" + +#: An EPICS device name belonging to us, e.g. AGEBD-ALH or AGEBD-CPCL-TUNE. +AGEBD_NAME = re.compile(r"AGEBD-[0-9A-Z][0-9A-Z-]*") + +#: Systemd unit names are the same in every environment. +EXEMPT_PREFIXES = ("AGEBD-SERVICE-",) + + +def suffix_token(config): + """ + The token text these files must carry, taken from the central config so + that renaming the token cannot leave this check enforcing a stale name. + """ + if SUFFIX_TOKEN_NAME not in config.tokens: + raise AssertionError( + f"Token '{SUFFIX_TOKEN_NAME}' is not declared in " + f"{config.environments_file}, but qt/ is checked against it." + ) + return f"@@{SUFFIX_TOKEN_NAME}@@" + + +def check_ui_file(text, token, filename): + """ + Report every AGEBD- device name in ``text`` that lacks ``token``. + """ + errors = [] + for match in AGEBD_NAME.finditer(text): + name = match.group(0) + if name.startswith(EXEMPT_PREFIXES): + continue + if text[match.end() : match.end() + len(token)] == token: + continue + line = text.count("\n", 0, match.start()) + 1 + errors.append( + f"{filename}:{line}: '{name}' is missing '{token}', so it resolves to the " + f"production device in every environment." + ) + return errors + def check_ui_files(): """ - All 'AGEBD-' PVs need to contain the '$(AGEBD_ENV_SUFFIX)' macro, - which is: - - '' in PROD - '-DEV' in DEV + Raise AssertionError listing every violation, or return silently. """ - for filename in QT_DIR.glob("*"): - with open(filename, "r") as f: - for linenum, line in enumerate(f): - matches = re.findall("AGEBD-[0-9A-Z$()_]*:", line) - if matches: - for match in matches: - assert "$(AGEBD_ENV_SUFFIX)" in match, ( - f"Missing $(AGEBD_ENV_SUFFIX) in {filename} in line number {linenum + 1}: {line} " - ) + config = SubstitutionsConfig.load(REPO_ROOT / "config") + token = suffix_token(config) + + errors = [] + for path in sorted(QT_DIR.glob("*.ui")): + errors.extend(check_ui_file(path.read_text(), token, path.relative_to(REPO_ROOT))) + + if errors: + raise AssertionError( + "Qt UI files missing the environment suffix:\n\n " + "\n ".join(errors) + ) + + +if __name__ == "__main__": + try: + check_ui_files() + except AssertionError as e: + print(e, file=sys.stderr) + sys.exit(1) + print("All AGEBD- device names in qt/ carry the environment suffix.") diff --git a/scripts/tests/test_check_ui_files.py b/scripts/tests/test_check_ui_files.py index 6dc6793..3ef1a22 100644 --- a/scripts/tests/test_check_ui_files.py +++ b/scripts/tests/test_check_ui_files.py @@ -1,5 +1,67 @@ -from ci.check_ui_files import check_ui_files +import pytest +from agebd.subs import SubstitutionsConfig +from agebd.utils import get_git_root + +from ci.check_ui_files import check_ui_file, check_ui_files, suffix_token + +REPO_ROOT = get_git_root(__file__) +TOKEN = "@@agebd_env_suffix_upper@@" -def test_check_ui_files(): +@pytest.fixture +def token(): + return suffix_token(SubstitutionsConfig.load(REPO_ROOT / "config")) + + +def test_repo_ui_files_all_carry_the_suffix(): check_ui_files() + + +def test_token_comes_from_the_central_config(token): + assert token == TOKEN + + +def test_pv_name_with_the_suffix_is_accepted(token): + text = f'AGEBD-ALH{TOKEN}:NTURNS-ONOFF' + + assert check_ui_file(text, token, "A_BD_NTurns.ui") == [] + + +def test_pv_name_without_the_suffix_is_reported(token): + text = 'AGEBD-ALH:NTURNS-ONOFF' + + errors = check_ui_file(text, token, "A_BD_NTurns.ui") + + assert len(errors) == 1 + assert "AGEBD-ALH" in errors[0] + assert "A_BD_NTurns.ui:1" in errors[0] + + +def test_ioc_macro_value_without_the_suffix_is_reported(token): + """This is the bug that had the dev Service Manager driving prod IOCs.""" + text = "IOC=AGEBD-CPCL-NTURNS,service=NTURNS,name=NTurns" + + errors = check_ui_file(text, token, "A_BD_ServiceManager.ui") + + assert len(errors) == 1 + assert "AGEBD-CPCL-NTURNS" in errors[0] + + +def test_systemd_unit_name_is_exempt(token): + text = "systemctl --user restart AGEBD-SERVICE-MASTER.service" + + assert check_ui_file(text, token, "A_BD_ServiceManager.ui") == [] + + +def test_other_facilities_are_not_our_business(token): + text = "IOC=AGEOP-CPCL-SHIFTTOOL,service=SHIFTTOOL" + + assert check_ui_file(text, token, "A_BD_ServiceManager.ui") == [] + + +def test_reports_the_line_number(token): + text = "line one\nline two\nAGEBD-TUNE:AO\n" + + errors = check_ui_file(text, token, "A_BD_Tune.ui") + + assert "A_BD_Tune.ui:3" in errors[0] -- 2.54.0 From 4a73e52a358d03a591339a0a256d133cf4e0432c Mon Sep 17 00:00:00 2001 From: Benjamin Labrecque Date: Tue, 25 Aug 2026 10:35:41 +0200 Subject: [PATCH 4/4] refactor: one definition per naming rule, drop ansible (step 5) Consolidates the last duplicated derivations, and removes the ansible tree along with the CLI surface that existed only to drive it. Naming rules: * agebd/names.py holds ServiceName -- the single definition of how a service name is spelled in each context: dir_name, module_name, ioc_name, systemd_unit_name and the case forms. The environment suffix is deliberately not part of it; that stays a deploy-time token applied to these base names. * cli's Service model delegates every name_* property to it, so the CLI and the CI scripts derive names the same way. * scripts/ci/service_names.py emits the derived forms as shell assignments, and deploy-and-restart-service.sh evals them instead of carrying its own tr calls and its own copy of the systemd naming convention. Values are shell-quoted, and an invalid name exits non-zero emitting nothing, so an eval cannot leave empty variables behind. Registry lookups: * agebd.subs.find_service_entry is now the only place that answers "which registry entry is this service", used by read_ioc_port, get_ioc_port.py and cli's ServiceRegistry. get_ioc_port.py no longer parses the registry itself. * That also settles a semantic split: ServiceRegistry matched names case-sensitively while read_ioc_port did not. Both now match case-insensitively via ServiceName, so 'tune', 'Tune' and 'TUNE' resolve to the same service everywhere. Ansible removal: * ansible/ is deleted, along with cli/src/ioc.py, cli/src/core/ ansible.py, the IOC_ENV enum, the ansible and ansible-runner dependencies, and docs/developer/ansible.md. * This removes the 'agebd ioc install|start|restart' commands. They were pure playbook wrappers, so they could not outlive the playbooks; IOC install, start and restart now have no automation path in this repo. bin/start_service.sh keeps deriving its two name forms in bash, with a comment saying why: it runs on the deploy host before the service venv exists, so it cannot import agebd. It is the one deliberate exception. Verified: get_ioc_port.py, cli's ServiceRegistry and agebd's renderer all return 50007 for 'tune', 'Tune' and 'TUNE'; the shell-emitted names match the committed on-disk layout for real services including the dashed OpticsFF-X02S; the CLI runs with only the 'service' command left. Co-Authored-By: Claude Opus 5 --- .gitea/scripts/deploy-and-restart-service.sh | 19 ++- ansible/ansible.cfg | 8 - ansible/collections/requirements.yml | 3 - ansible/inventories/dev/hosts.yml | 19 --- ansible/inventories/prod/hosts.yml | 18 --- ansible/playbooks/add-new-service.yml | 42 ----- .../deploy-and-restart-modified-services.yml | 24 --- ansible/playbooks/ioc-install.yml | 13 -- ansible/playbooks/ioc-restart.yml | 13 -- ansible/playbooks/ioc-start.yml | 16 -- ansible/tasks/ioc/ioc-install.yml | 66 -------- ansible/tasks/ioc/ioc-restart.yml | 23 --- ansible/tasks/ioc/ioc-start.yml | 17 -- .../service/service-deploy-and-restart.yml | 61 -------- ansible/tasks/utils/clone-repo.yml | 8 - ansible/tasks/utils/get-ioc-port.yml | 18 --- ansible/tasks/utils/init-service-name.yml | 5 - ansible/tasks/utils/load-substitutions.yml | 32 ---- bin/start_service.sh | 4 + cli/pyproject.toml | 2 - cli/src/core/ansible.py | 40 ----- cli/src/core/enums.py | 8 - cli/src/ioc.py | 112 ------------- cli/src/main.py | 2 - cli/src/models/service.py | 33 ++-- cli/src/models/service_registry.py | 17 +- cli/uv.lock | 147 ------------------ config/environments.yml | 6 +- docs/developer/ansible.md | 36 ----- packages/agebd/src/agebd/names.py | 113 ++++++++++++++ packages/agebd/src/agebd/subs.py | 30 +++- packages/agebd/tests/test_names.py | 66 ++++++++ packages/agebd/tests/test_runner.py | 2 +- packages/agebd/tests/test_service.py | 2 +- scripts/ci/get_ioc_port.py | 39 +++-- scripts/ci/service_names.py | 45 ++++++ scripts/tests/test_service_names.py | 72 +++++++++ 37 files changed, 393 insertions(+), 788 deletions(-) delete mode 100644 ansible/ansible.cfg delete mode 100644 ansible/collections/requirements.yml delete mode 100644 ansible/inventories/dev/hosts.yml delete mode 100644 ansible/inventories/prod/hosts.yml delete mode 100644 ansible/playbooks/add-new-service.yml delete mode 100644 ansible/playbooks/deploy-and-restart-modified-services.yml delete mode 100644 ansible/playbooks/ioc-install.yml delete mode 100644 ansible/playbooks/ioc-restart.yml delete mode 100644 ansible/playbooks/ioc-start.yml delete mode 100644 ansible/tasks/ioc/ioc-install.yml delete mode 100644 ansible/tasks/ioc/ioc-restart.yml delete mode 100644 ansible/tasks/ioc/ioc-start.yml delete mode 100644 ansible/tasks/service/service-deploy-and-restart.yml delete mode 100644 ansible/tasks/utils/clone-repo.yml delete mode 100644 ansible/tasks/utils/get-ioc-port.yml delete mode 100644 ansible/tasks/utils/init-service-name.yml delete mode 100644 ansible/tasks/utils/load-substitutions.yml delete mode 100644 cli/src/core/ansible.py delete mode 100644 cli/src/ioc.py delete mode 100644 docs/developer/ansible.md create mode 100644 packages/agebd/src/agebd/names.py create mode 100644 packages/agebd/tests/test_names.py create mode 100644 scripts/ci/service_names.py create mode 100644 scripts/tests/test_service_names.py diff --git a/.gitea/scripts/deploy-and-restart-service.sh b/.gitea/scripts/deploy-and-restart-service.sh index 95834c3..c66556b 100755 --- a/.gitea/scripts/deploy-and-restart-service.sh +++ b/.gitea/scripts/deploy-and-restart-service.sh @@ -7,17 +7,22 @@ echo "==========================================" echo "Deploying service: $SERVICE_NAME (${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 +# Name forms and the systemd naming convention come from +# agebd.names.ServiceName, so this script carries no copy of them. +if ! SERVICE_NAMES=$(uv run --directory scripts ci/service_names.py "${SERVICE_NAME}"); then + echo "Could not derive names for '${SERVICE_NAME}' -- aborting deploy" >&2 + exit 1 +fi +eval "${SERVICE_NAMES}" + +SERVICE_DIR=/sls/bd/hla/${AGEBD_ENV}/services/${SERVICE_DIR_NAME}/current SYSTEMD_UNIT_FILE_PATH=${SERVICE_DIR}/systemd/${SYSTEMD_UNIT_NAME} IOC_DIR=${SERVICE_DIR}/ioc # TODO: see https://gitea.psi.ch/sls/hla_framework_bd/issues/50 # rm -rf "${SERVICE_DIR}" # mkdir -p ${SERVICE_DIR} -# cp -r ./services/${SERVICE_NAME_LOWER}/current/* ${SERVICE_DIR}/ +# cp -r ./services/${SERVICE_DIR_NAME}/current/* ${SERVICE_DIR}/ rsync -avz --delete \ --exclude='.nfs*' \ @@ -26,7 +31,7 @@ rsync -avz --delete \ --exclude='__pycache__/' \ --exclude='*.pyc' \ --exclude='.pytest_cache/' \ - ./services/${SERVICE_NAME_LOWER}/current/* ${SERVICE_DIR}/ + ./services/${SERVICE_DIR_NAME}/current/* ${SERVICE_DIR}/ ### SUBSTITUTIONS # Every @@token@@ is resolved from config/environments.yml and @@ -34,7 +39,7 @@ rsync -avz --delete \ # deploy instead of leaving the placeholder in a file the IOC will read. if ! uv run --directory scripts ci/render_subs.py \ --env "${AGEBD_ENV}" \ - --service "${SERVICE_NAME_LOWER}" \ + --service "${SERVICE_DIR_NAME}" \ "${IOC_DIR}" "${SERVICE_DIR}/systemd"; then echo "Substitution failed -- aborting deploy of ${SERVICE_NAME}" >&2 exit 1 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 fe426e5..0000000 --- a/ansible/inventories/dev/hosts.yml +++ /dev/null @@ -1,19 +0,0 @@ -all: - vars: - # Suffix values for this environment live in config/environments.yml -- - # do not reintroduce them here. - agebd_env: "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 ec25a8e..0000000 --- a/ansible/inventories/prod/hosts.yml +++ /dev/null @@ -1,18 +0,0 @@ -all: - vars: - # Suffix values for this environment live in config/environments.yml -- - # do not reintroduce them here. - agebd_env: "prod" - - 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 c78d698..0000000 --- a/ansible/playbooks/ioc-install.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- -- name: Install an IOC - hosts: lc - gather_facts: false - - vars: - workspace_dir: "/tmp/hla_framework_bd" - # Controller-side checkout, where config/environments.yml is read from - repo_root: "{{ playbook_dir }}/../.." - - 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 7c54986..0000000 --- a/ansible/playbooks/ioc-restart.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- -- name: Restart an IOC - hosts: lc - gather_facts: false - - vars: - workspace_dir: "/tmp/hla_framework_bd" - # Controller-side checkout, where config/environments.yml is read from - repo_root: "{{ playbook_dir }}/../.." - - 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 b50b4bc..0000000 --- a/ansible/playbooks/ioc-start.yml +++ /dev/null @@ -1,16 +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" - # Controller-side checkout, where config/environments.yml is read from - repo_root: "{{ playbook_dir }}/../.." - - 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 d991c1c..0000000 --- a/ansible/tasks/ioc/ioc-install.yml +++ /dev/null @@ -1,66 +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: Load deploy-time substitutions - ansible.builtin.import_tasks: ../utils/load-substitutions.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 }}{{ agebd_env_suffix_upper }}_main.subs" - orig_params_name: "AGEBD-CPCL-{{ service_name_upper }}_parameters.yaml" - target_params_name: "AGEBD-CPCL-{{ service_name_upper }}{{ agebd_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 - -# Every @@token@@ is resolved from the central token table -- the token list -# is not repeated here, so a new token needs no change to this file. -- name: "[{{ target_service_name_lower }}] Collect deploy-time token values" - ansible.builtin.set_fact: - deploy_tokens: "{{ env_tokens | combine({'ioc_port': ioc_port}) }}" - -- name: "[{{ target_service_name_lower }}] Substitute deploy-time tokens in the IOC files" - ansible.builtin.replace: - path: "{{ item.0 }}" - regexp: '@@\s*{{ item.1.key }}\s*@@' - replace: "{{ item.1.value | string }}" - loop: >- - {{ [ioc_base_dir ~ '/' ~ target_subs_name, ioc_base_dir ~ '/' ~ target_params_name] - | product(deploy_tokens | dict2items) | list }} - loop_control: - label: "{{ item.0 | basename }} :: {{ item.1.key }}" - -- name: "[{{ target_service_name_lower }}] Run ioc install" - ansible.builtin.shell: - cmd: "ioc install -V --facility sls --ioc AGEBD-CPCL-{{ service_name_upper }}{{ agebd_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 8d846c9..0000000 --- a/ansible/tasks/ioc/ioc-restart.yml +++ /dev/null @@ -1,23 +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: Load deploy-time substitutions - ansible.builtin.import_tasks: ../utils/load-substitutions.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 }}{{ agebd_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 7509cda..0000000 --- a/ansible/tasks/service/service-deploy-and-restart.yml +++ /dev/null @@ -1,61 +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: Load deploy-time substitutions - ansible.builtin.import_tasks: ../utils/load-substitutions.yml - -- 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 - -# Every @@token@@ is resolved from the central token table -- the token list -# is not repeated here, so a new token needs no change to this file. -- name: "[{{ target_service_name_lower }}] Substitute deploy-time tokens in the systemd unit" - ansible.builtin.replace: - path: "{{ svc_current_dir }}/systemd/{{ service_unit_name }}" - regexp: '@@\s*{{ item.key }}\s*@@' - replace: "{{ item.value | string }}" - loop: "{{ env_tokens | dict2items }}" - loop_control: - label: "{{ item.key }}" - - # 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/ansible/tasks/utils/load-substitutions.yml b/ansible/tasks/utils/load-substitutions.yml deleted file mode 100644 index f63a26a..0000000 --- a/ansible/tasks/utils/load-substitutions.yml +++ /dev/null @@ -1,32 +0,0 @@ ---- -# Load the deploy-time token values for {{ agebd_env }} from the single source -# of truth, config/environments.yml. -# -# The inventory says which environment it is; this file says what that -# environment means. Do not reintroduce suffix values into the inventories. -# -# include_vars reads on the controller, where the repo checkout lives, so this -# works for both local-connection plays and plays targeting remote hosts. -# -# Ansible substitutes tokens with ansible.builtin.replace rather than calling -# agebd.subs, because these tasks also run on hosts that have no uv or Python -# environment for this repo. The values and the token list still come from the -# central config, so there is nothing to keep in sync by hand. - -- name: Load the central substitution config - ansible.builtin.include_vars: - file: "{{ repo_root }}/config/environments.yml" - name: substitutions - -- name: Fail if this environment is not declared centrally - ansible.builtin.fail: - msg: >- - Environment '{{ agebd_env }}' is not declared in config/environments.yml. - Declared: {{ substitutions.environments.keys() | list | join(', ') }} - when: agebd_env not in substitutions.environments - -- name: Select the deploy-time token values for this environment - ansible.builtin.set_fact: - env_tokens: "{{ substitutions.environments[agebd_env] }}" - agebd_env_suffix_upper: "{{ substitutions.environments[agebd_env].agebd_env_suffix_upper }}" - agebd_env_suffix_lower: "{{ substitutions.environments[agebd_env].agebd_env_suffix_lower }}" diff --git a/bin/start_service.sh b/bin/start_service.sh index 40dfde6..dd888cc 100755 --- a/bin/start_service.sh +++ b/bin/start_service.sh @@ -7,6 +7,10 @@ set -- # PSI_FACILITY=SLS SERVICES_DIR=/sls/bd/hla/${AGEBD_ENV}/services +# These two derivations are the one place that deliberately does not use +# agebd.names.ServiceName: this runs on the deploy host before any Python +# environment for the service exists (the venv is built further down), so it +# cannot import agebd. Keep the rules here in step with agebd/names.py. SVC_NAME_LOWER=${SVC_NAME,,} SVC_NAME_LOWER_UNDERSCORES="${SVC_NAME_LOWER//-/_}" SVC_DIR=${SERVICES_DIR}/${SVC_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/src/models/service.py b/cli/src/models/service.py index e7a1b49..92a5d95 100644 --- a/cli/src/models/service.py +++ b/cli/src/models/service.py @@ -1,34 +1,48 @@ -import re - +from agebd.names import ServiceName from pydantic import BaseModel, field_validator from core.enums import ServiceStatus class Service(BaseModel): + """ + A service's registry entry. + + Every spelling of the name is delegated to agebd.names.ServiceName, which + is also what the CI and deploy scripts use. + """ + name: str ioc_port: int status: ServiceStatus + @property + def service_name(self) -> ServiceName: + return ServiceName(self.name) + @property def name_camel(self): - return self.name + return self.service_name.camel @property def name_upper(self): - return self.name.upper() + return self.service_name.upper @property def name_lower(self): - return self.name.lower() + return self.service_name.lower @property def name_lower_underscores(self): - return self.name.replace("-", "_").lower() + return self.service_name.lower_underscores @property def dir_name(self): - return self.name.lower() + return self.service_name.dir_name + + @property + def ioc_name(self): + return self.service_name.ioc_name def to_dict(self): return {"name": self.name_camel, "ioc_port": self.ioc_port, "status": str(self.status)} @@ -39,8 +53,5 @@ class Service(BaseModel): @field_validator("name") @classmethod def validate_name_chars(cls, value: str) -> str: - if not re.match(r"^[a-zA-Z0-9-]+$", value): - raise ValueError( - "name can only contain uppercase and lowercase letters, numbers, and dashes" - ) + ServiceName(value) return value diff --git a/cli/src/models/service_registry.py b/cli/src/models/service_registry.py index 011238e..e40f516 100644 --- a/cli/src/models/service_registry.py +++ b/cli/src/models/service_registry.py @@ -3,6 +3,8 @@ from pathlib import Path import yaml from pydantic import BaseModel +from agebd.subs import find_service_entry + from core.enums import ServiceStatus from models.service import Service @@ -26,12 +28,15 @@ class ServiceRegistry(BaseModel): return [Service(**svc_data) for svc_data in self.services] def assert_service_exists(self, name: str) -> Service: - for svc_data in self.services: - service = Service(**svc_data) - if name == service.name_camel: - return service - - raise ValueError(f"Could not find service with name: {name}") + """ + Look a service up by name. Matching goes through + agebd.subs.find_service_entry so that the CLI, the CI scripts and the + deploy scripts all agree on what "the service named X" means. + """ + entry = find_service_entry(self.services, name) + if entry is None: + raise ValueError(f"Could not find service with name: {name}") + return Service(**entry) def add_service(self, name: str) -> Service: svc = Service( diff --git a/cli/uv.lock b/cli/uv.lock index 29a62ec..0997b49 100644 --- a/cli/uv.lock +++ b/cli/uv.lock @@ -39,8 +39,6 @@ version = "0.1.0" source = { editable = "." } dependencies = [ { name = "agebd" }, - { name = "ansible" }, - { name = "ansible-runner" }, { name = "copier" }, { name = "pydantic" }, { name = "pydantic-settings" }, @@ -62,8 +60,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" }, @@ -100,49 +96,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" @@ -152,29 +105,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" @@ -209,44 +139,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" @@ -408,15 +300,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" @@ -599,15 +482,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" @@ -750,18 +624,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" @@ -800,15 +662,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/config/environments.yml b/config/environments.yml index bf3707a..e8b906e 100644 --- a/config/environments.yml +++ b/config/environments.yml @@ -65,11 +65,9 @@ locations: - templates - cli/tests/fixtures # The substitution machinery itself: code that renders, generates or - # documents tokens. Naming a token here is expected; nothing is resolved. - # These paths use {{ }} as their own template language (Ansible, copier), so - # the leftover-delimiter check does not apply to them. + # documents tokens. Naming a token here is expected; nothing is resolved, + # and the leftover-delimiter check does not apply. references: - - ansible/tasks/* - .gitea/scripts - cli/src/models - packages/agebd/src/agebd 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/packages/agebd/src/agebd/names.py b/packages/agebd/src/agebd/names.py new file mode 100644 index 0000000..c2f2654 --- /dev/null +++ b/packages/agebd/src/agebd/names.py @@ -0,0 +1,113 @@ +""" +The one definition of how a service name is spelled in each context. + +A service has a single canonical CamelCase name, recorded in +config/services_registry.yml. Everything else is derived from it by a fixed +rule: the directory it lives in, its Python module, its EPICS IOC, its systemd +unit. Those rules live here so that the CLI, the CI scripts and the deploy +scripts cannot drift apart on them. + +The environment suffix is deliberately not part of any name here. It is a +deploy-time token (see agebd.subs), applied to the base names below. +""" + +import re + +#: Prefix of every EPICS IOC in this framework. +IOC_PREFIX = "AGEBD-CPCL" + +#: Prefix of every systemd unit in this framework. +SYSTEMD_UNIT_PREFIX = "AGEBD-SERVICE" + +#: Prefix of every service's Python package. +PACKAGE_PREFIX = "agebd" + +VALID_NAME = re.compile(r"^[a-zA-Z0-9-]+$") + + +class InvalidServiceName(ValueError): + """The name is not a legal service name.""" + + +class ServiceName: + """ + A service's canonical name and every form derived from it. + + >>> name = ServiceName("TuneFBx") + >>> name.dir_name, name.module_name, name.ioc_name + ('tunefbx', 'agebd_tunefbx', 'AGEBD-CPCL-TUNEFBX') + """ + + def __init__(self, name: str) -> None: + if not isinstance(name, str) or not VALID_NAME.match(name): + raise InvalidServiceName( + f"Invalid service name {name!r}: a service name may only contain " + f"uppercase and lowercase letters, numbers, and dashes." + ) + self._name = name + + @property + def camel(self) -> str: + """The canonical name, as written in the registry and shown in the GUI.""" + return self._name + + @property + def upper(self) -> str: + return self._name.upper() + + @property + def lower(self) -> str: + return self._name.lower() + + @property + def lower_underscores(self) -> str: + return self.lower.replace("-", "_") + + @property + def dir_name(self) -> str: + """The directory under services/ that holds this service.""" + return self.lower + + @property + def module_name(self) -> str: + """The Python package implementing this service.""" + return f"{PACKAGE_PREFIX}_{self.lower_underscores}" + + @property + def ioc_name(self) -> str: + """ + The IOC's base name. Deployments append the environment suffix token. + """ + return f"{IOC_PREFIX}-{self.upper}" + + @property + def systemd_unit_name(self) -> str: + """ + The systemd unit file name. Unit names carry no environment suffix: + dev and prod run on different hosts. + """ + return f"{SYSTEMD_UNIT_PREFIX}-{self.upper}.service" + + def matches(self, other) -> bool: + """ + Whether ``other`` names this service. Comparison is case-insensitive, + because callers hold the name in whatever casing their context uses. + """ + try: + return ServiceName(str(other)).lower == self.lower + except InvalidServiceName: + return False + + def __str__(self) -> str: + return self.camel + + def __repr__(self) -> str: + return f"ServiceName({self.camel!r})" + + def __eq__(self, other) -> bool: + if isinstance(other, ServiceName): + return self.lower == other.lower + return NotImplemented + + def __hash__(self) -> int: + return hash(self.lower) diff --git a/packages/agebd/src/agebd/subs.py b/packages/agebd/src/agebd/subs.py index dd4b1e1..28d32a3 100644 --- a/packages/agebd/src/agebd/subs.py +++ b/packages/agebd/src/agebd/subs.py @@ -36,6 +36,7 @@ from typing import Iterable, Iterator, Optional, Union import yaml +from agebd.names import InvalidServiceName, ServiceName from agebd.utils import get_git_root CONFIG_DIR_ENV_VAR = "AGEBD_CONFIG_DIR" @@ -306,19 +307,32 @@ class Substitutions: def read_ioc_port(registry_file: Union[str, Path], service_name: str) -> int: """ Look up a service's IOC port in the services registry. - - Registry names are CamelCase; callers pass whatever casing they have, so - the comparison is case-insensitive. """ with open(registry_file) as f: registry = yaml.safe_load(f) or {} - wanted = service_name.lower() - for entry in registry.get("services") or []: - if str(entry.get("name", "")).lower() == wanted: - return entry["ioc_port"] + entry = find_service_entry(registry.get("services") or [], service_name) + if entry is None: + raise SubstitutionError(f"Service '{service_name}' not found in {registry_file}") + return entry["ioc_port"] - raise SubstitutionError(f"Service '{service_name}' not found in {registry_file}") + +def find_service_entry(services: Iterable, service_name: str): + """ + Find a service's registry entry by name, or None. + + Registry names are CamelCase; callers hold whatever casing their context + uses, so matching goes through agebd.names.ServiceName. + """ + try: + wanted = ServiceName(service_name) + except InvalidServiceName: + return None + + for entry in services: + if wanted.matches(entry.get("name", "")): + return entry + return None def find_tokens(text: str) -> set: diff --git a/packages/agebd/tests/test_names.py b/packages/agebd/tests/test_names.py new file mode 100644 index 0000000..8973ed1 --- /dev/null +++ b/packages/agebd/tests/test_names.py @@ -0,0 +1,66 @@ +import pytest + +from agebd.names import InvalidServiceName, ServiceName + + +@pytest.mark.parametrize( + "name, upper, lower, underscores", + [ + ("Tune", "TUNE", "tune", "tune"), + ("TauBPM", "TAUBPM", "taubpm", "taubpm"), + ("TuneFBx", "TUNEFBX", "tunefbx", "tunefbx"), + ("OpticsFF-X02S", "OPTICSFF-X02S", "opticsff-x02s", "opticsff_x02s"), + ], +) +def test_case_forms(name, upper, lower, underscores): + service = ServiceName(name) + + assert service.camel == name + assert service.upper == upper + assert service.lower == lower + assert service.lower_underscores == underscores + + +def test_derived_names(): + service = ServiceName("OpticsFF-X02S") + + assert service.dir_name == "opticsff-x02s" + assert service.module_name == "agebd_opticsff_x02s" + assert service.ioc_name == "AGEBD-CPCL-OPTICSFF-X02S" + assert service.systemd_unit_name == "AGEBD-SERVICE-OPTICSFF-X02S.service" + + +def test_derived_names_carry_no_environment_suffix(): + """The suffix is a deploy-time token, applied to these base names.""" + service = ServiceName("Tune") + + assert "DEV" not in service.ioc_name + assert "DEV" not in service.systemd_unit_name + + +@pytest.mark.parametrize("name", ["Tune", "tune", "TUNE", "tUnE"]) +def test_matches_is_case_insensitive(name): + assert ServiceName("Tune").matches(name) + + +def test_does_not_match_a_different_service(): + assert not ServiceName("Tune").matches("TuneBump") + + +def test_does_not_match_an_invalid_name(): + assert not ServiceName("Tune").matches("Tune!") + + +@pytest.mark.parametrize("name", ["", "Tune Bump", "Tune_Bump", "Tune!", "Tune/Bump"]) +def test_invalid_names_are_rejected(name): + with pytest.raises(InvalidServiceName): + ServiceName(name) + + +def test_equality_and_hashing_ignore_case(): + assert ServiceName("Tune") == ServiceName("TUNE") + assert len({ServiceName("Tune"), ServiceName("tune")}) == 1 + + +def test_str_is_the_canonical_name(): + assert str(ServiceName("TauBPM")) == "TauBPM" diff --git a/packages/agebd/tests/test_runner.py b/packages/agebd/tests/test_runner.py index 7237ea1..da1129e 100644 --- a/packages/agebd/tests/test_runner.py +++ b/packages/agebd/tests/test_runner.py @@ -1,8 +1,8 @@ from unittest.mock import patch -from agebd.service.pvs import BasePVs from agebd.runner import CallbackRunner, PeriodicRunner from agebd.service.base import BaseService +from agebd.service.pvs import BasePVs class DummyPV: diff --git a/packages/agebd/tests/test_service.py b/packages/agebd/tests/test_service.py index 498ba17..bcf9086 100644 --- a/packages/agebd/tests/test_service.py +++ b/packages/agebd/tests/test_service.py @@ -1,5 +1,5 @@ -from agebd.service.pvs import BasePVs from agebd.service.base import BaseService +from agebd.service.pvs import BasePVs class DummyPV: diff --git a/scripts/ci/get_ioc_port.py b/scripts/ci/get_ioc_port.py index a51e914..51a09e6 100644 --- a/scripts/ci/get_ioc_port.py +++ b/scripts/ci/get_ioc_port.py @@ -1,24 +1,29 @@ +""" +Print a service's IOC port. + + get_ioc_port.py tune + +The lookup itself lives in agebd.subs, which is also what render_subs.py and +the CLI use, so there is only one answer to "which port is this service on". +""" + import sys -import yaml -from agebd.utils import get_git_root - -REPO_ROOT = get_git_root(".") -SERVICES_REGISTRY_FILE = REPO_ROOT / "config" / "services_registry.yml" +from agebd.subs import ( + SERVICES_REGISTRY_FILENAME, + SubstitutionError, + read_ioc_port, + resolve_config_dir, +) -def get_ioc_port(service_name_lower: str): - with open(SERVICES_REGISTRY_FILE) as f: - d = yaml.safe_load(f) - - for service_dict in d["services"]: - if service_dict["name"].lower() == service_name_lower: - return service_dict["ioc_port"] - - raise ValueError(f"Service with lowercase name {service_name_lower} not found") +def get_ioc_port(service_name: str) -> int: + return read_ioc_port(resolve_config_dir() / SERVICES_REGISTRY_FILENAME, service_name) if __name__ == "__main__": - service_name_lower = sys.argv[1] - port = get_ioc_port(service_name_lower) - print(port) + try: + print(get_ioc_port(sys.argv[1])) + except SubstitutionError as e: + print(f"error: {e}", file=sys.stderr) + sys.exit(1) diff --git a/scripts/ci/service_names.py b/scripts/ci/service_names.py new file mode 100644 index 0000000..20b245c --- /dev/null +++ b/scripts/ci/service_names.py @@ -0,0 +1,45 @@ +""" +Emit a service's derived names as shell assignments. + + eval "$(service_names.py TauBPM)" + echo "$SYSTEMD_UNIT_NAME" # AGEBD-SERVICE-TAUBPM.service + +Every form comes from agebd.names.ServiceName, so the deploy scripts carry no +copy of the naming conventions. Values are shell-quoted; an invalid service +name exits non-zero and emits nothing, so an unguarded eval cannot silently +leave the caller with empty variables. +""" + +import shlex +import sys + +from agebd.names import InvalidServiceName, ServiceName + +#: Shell variable name -> ServiceName attribute. +EXPORTED = { + "SERVICE_NAME_CAMEL": "camel", + "SERVICE_NAME_UPPER": "upper", + "SERVICE_NAME_LOWER": "lower", + "SERVICE_DIR_NAME": "dir_name", + "SERVICE_MODULE_NAME": "module_name", + "IOC_NAME": "ioc_name", + "SYSTEMD_UNIT_NAME": "systemd_unit_name", +} + + +def shell_assignments(name: str) -> str: + service = ServiceName(name) + return "\n".join( + f"{var}={shlex.quote(getattr(service, attr))}" for var, attr in EXPORTED.items() + ) + + +if __name__ == "__main__": + if len(sys.argv) != 2: + print(f"usage: {sys.argv[0]} ", file=sys.stderr) + sys.exit(2) + try: + print(shell_assignments(sys.argv[1])) + except InvalidServiceName as e: + print(f"error: {e}", file=sys.stderr) + sys.exit(1) diff --git a/scripts/tests/test_service_names.py b/scripts/tests/test_service_names.py new file mode 100644 index 0000000..a7e00ab --- /dev/null +++ b/scripts/tests/test_service_names.py @@ -0,0 +1,72 @@ +import subprocess +import sys + +import pytest +from agebd.names import InvalidServiceName +from agebd.utils import get_git_root + +from ci.service_names import EXPORTED, shell_assignments + +SCRIPT = get_git_root(__file__) / "scripts" / "ci" / "service_names.py" + + +def run_in_shell(name): + """Eval the output in a real shell and read the variables back.""" + assignments = shell_assignments(name) + readback = "\n".join(f'printf "%s=%s\\n" {var} "${var}"' for var in EXPORTED) + out = subprocess.run( + ["bash", "-c", f"{assignments}\n{readback}"], + capture_output=True, + text=True, + check=True, + ).stdout + return dict(line.split("=", 1) for line in out.strip().splitlines()) + + +def test_emits_every_derived_form(): + values = run_in_shell("TauBPM") + + assert values == { + "SERVICE_NAME_CAMEL": "TauBPM", + "SERVICE_NAME_UPPER": "TAUBPM", + "SERVICE_NAME_LOWER": "taubpm", + "SERVICE_DIR_NAME": "taubpm", + "SERVICE_MODULE_NAME": "agebd_taubpm", + "IOC_NAME": "AGEBD-CPCL-TAUBPM", + "SYSTEMD_UNIT_NAME": "AGEBD-SERVICE-TAUBPM.service", + } + + +def test_dashed_name_survives_the_shell(): + values = run_in_shell("OpticsFF-X02S") + + assert values["SERVICE_DIR_NAME"] == "opticsff-x02s" + assert values["SERVICE_MODULE_NAME"] == "agebd_opticsff_x02s" + assert values["IOC_NAME"] == "AGEBD-CPCL-OPTICSFF-X02S" + + +def test_invalid_name_raises(): + with pytest.raises(InvalidServiceName): + shell_assignments("Tune; rm -rf /") + + +def test_cli_exits_non_zero_and_emits_nothing_on_a_bad_name(): + result = subprocess.run( + [sys.executable, str(SCRIPT), "Tune Bump"], + capture_output=True, + text=True, + check=False, + ) + + assert result.returncode == 1 + assert result.stdout == "" + assert "Invalid service name" in result.stderr + + +def test_cli_requires_exactly_one_argument(): + result = subprocess.run( + [sys.executable, str(SCRIPT)], capture_output=True, text=True, check=False + ) + + assert result.returncode == 2 + assert "usage:" in result.stderr -- 2.54.0