mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
refactor(layout): sort shipped scripts by language and split the unit suite
Every script a role ships now lives under `files/<language>/`, and the unit
suite is split the same way: `tests/unit/python/` beside new sibling trees for
the other languages. `tests/lint/filesystem/test_role_files_layout.py` keeps it
that way; directories whose shape is dictated from outside carry a `.nocheck`
naming the constraint (Docker build contexts, WordPress mu-plugins, the Joomla
extension, Odoo addons, Playwright suites, the `files/test/test.sh` harness
that `test-e2e-cli` resolves generically).
This cannot be applied in halves. Moving a file and repointing what names it
are the same change: 14 references resolve only at deploy time, so the tree is
green either before or after, never between.
Those 14 were found by static resolution over every reference class, not by the
test suite -- a full `make quality-high` was green while all of them were
broken:
* 7 `src:` values built from a role variable holding a bare filename
(svc-bkp-remote-2-local, decidim, espocrm, friendica, joomla, pixelfed x2).
The variable doubles as the destination name inside the container, so the
language segment belongs at the call site, not in the variable.
* `sys-service/tasks/04_base.yml` resolved every consumer's systemd script
through `first_found(..., errors='strict')` over `files/script.{sh,py}`.
18 roles ship exactly that and have no template fallback: the play would
have died on each.
* `sys-front-inj-javascript` fell back to `<role>/files/javascript.js`; the
interface now reads `files/javascript/javascript.js`.
* `sys-front-inj-logout/templates/head_sub.j2` built the cache-busting mtime
path through `path_absolute(... 'files', ...)`.
* 4 `ansible.builtin.script:` invocations naming a bare command
(pull.py, prune.sh, set_postgres_superuser_password.sh, ganesha-serve.sh).
* `dev-python/files/shell/install.sh` pointed at a sibling role's script.
Depth-dependent paths inside the moved trees were bumped accordingly: 59
`parents[N]` computations, 12 relative climbs, and the per-role recover CLI,
whose path `cli/administration/recover/recoverers.py` still assembled from the
pre-move location.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
6eff9d2ca1
commit
575a5a87ac
1076 files changed
+2141
-550
No files matched your search
@@ -106,7 +106,7 @@ Every invokable role in the tested lifecycle envelope, with its upstream homepag
|
||||
| [Jenkins](roles/web-app-jenkins/) | beta | Open-source automation server for CI/CD pipelines, builds, and plugin-driven deployment workflows | [🌐](https://www.jenkins.io/) [🎬](https://www.youtube.com/channel/UC5JBtmoz7ePk-33ZHimGiDQ) [🛠️](roles/web-app-jenkins/README.md#quick-setup) | [Backup Docker Volumes](roles/svc-bkp-volume-2-local/), [Corporate Design](roles/web-svc-css/), [Dashboard](roles/web-app-dashboard/), [Keycloak](roles/web-app-keycloak/), [Matomo](roles/web-app-matomo/), [OpenLDAP](roles/svc-db-openldap/), [Prometheus](roles/web-app-prometheus/), [Tor Onion Service](roles/svc-net-tor/), [Universal Logout](roles/web-svc-logout/) |
|
||||
| [Jitsi Meet](roles/web-app-jitsi/) | beta | Self-hosted WebRTC platform for end-to-end-encryptable video conferencing with federated authentication | [🌐](https://jitsi.org/) [🎬](https://www.youtube.com/channel/UCyXuxN-aNUpRv0juUXLyjbw) [🛠️](roles/web-app-jitsi/README.md#quick-setup) | [Corporate Design](roles/web-svc-css/), [Dashboard](roles/web-app-dashboard/), [Keycloak](roles/web-app-keycloak/), [Mailu](roles/web-app-mailu/), [Matomo](roles/web-app-matomo/), [OpenLDAP](roles/svc-db-openldap/), [Prometheus](roles/web-app-prometheus/), [Universal Logout](roles/web-svc-logout/) |
|
||||
| [Joomla](roles/web-app-joomla/) | beta | Open-source content management system for building websites, intranets, and online applications without writing code | [🌐](https://www.joomla.org/) [🎬](https://www.youtube.com/user/joomla) [🛠️](roles/web-app-joomla/README.md#quick-setup) | [Backup Docker Volumes](roles/svc-bkp-volume-2-local/), [Corporate Design](roles/web-svc-css/), [Dashboard](roles/web-app-dashboard/), [Keycloak](roles/web-app-keycloak/), [Mailu](roles/web-app-mailu/), [MariaDB](roles/svc-db-mariadb/), [Matomo](roles/web-app-matomo/), [Prometheus](roles/web-app-prometheus/), [Tor Onion Service](roles/svc-net-tor/), [Universal Logout](roles/web-svc-logout/) |
|
||||
| [Keycloak](roles/web-app-keycloak/) | beta | Self-hosted identity and access management platform for single sign-on, multi-factor authentication, and user federation | [🌐](https://www.keycloak.org/) [🛠️](roles/web-app-keycloak/README.md#quick-setup) | [Corporate Design](roles/web-svc-css/), [Dashboard](roles/web-app-dashboard/), [Mailu](roles/web-app-mailu/), [Matomo](roles/web-app-matomo/), [PostgreSQL](roles/svc-db-postgres/), [Prometheus](roles/web-app-prometheus/), [Tor Onion Service](roles/svc-net-tor/) |
|
||||
| [Keycloak](roles/web-app-keycloak/) | beta | Self-hosted identity and access management platform for single sign-on, multi-factor authentication, and user federation | [🌐](https://www.keycloak.org/) [🛠️](roles/web-app-keycloak/README.md#quick-setup) | [Content Delivery Network](roles/web-svc-cdn/), [Corporate Design](roles/web-svc-css/), [Dashboard](roles/web-app-dashboard/), [Mailu](roles/web-app-mailu/), [Matomo](roles/web-app-matomo/), [PostgreSQL](roles/svc-db-postgres/), [Prometheus](roles/web-app-prometheus/), [Tor Onion Service](roles/svc-net-tor/) |
|
||||
| [KIX](roles/web-app-kix/) | beta | Open-source ITSM and helpdesk platform (OTRS fork) for ticketing, CMDB, knowledge base, and reporting | [🌐](https://www.kixdesk.com/en/) [🎬](https://www.youtube.com/watch?v=D62emos1FQ8) [🛠️](roles/web-app-kix/README.md#quick-setup) | [Backup Docker Volumes](roles/svc-bkp-volume-2-local/), [Corporate Design](roles/web-svc-css/), [Dashboard](roles/web-app-dashboard/), [Keycloak](roles/web-app-keycloak/), [Mailu](roles/web-app-mailu/), [Matomo](roles/web-app-matomo/), [OpenLDAP](roles/svc-db-openldap/), [PostgreSQL](roles/svc-db-postgres/), [Prometheus](roles/web-app-prometheus/), [Tor Onion Service](roles/svc-net-tor/), [Universal Logout](roles/web-svc-logout/) |
|
||||
| [LAM](roles/web-app-lam/) | beta | Web interface for administering LDAP directories: managing users, groups, and other directory objects | [🌐](https://www.ldap-account-manager.org/) [🛠️](roles/web-app-lam/README.md#quick-setup) | [Corporate Design](roles/web-svc-css/), [Dashboard](roles/web-app-dashboard/), [Keycloak](roles/web-app-keycloak/), [Matomo](roles/web-app-matomo/), [OpenLDAP](roles/svc-db-openldap/), [Prometheus](roles/web-app-prometheus/), [Tor Onion Service](roles/svc-net-tor/), [Universal Logout](roles/web-svc-logout/) |
|
||||
| [LibreTranslate](roles/web-svc-libretranslate/) | beta | Self-hosted open-source machine translation API for translating and detecting text across languages | [🌐](https://libretranslate.com/) [🛠️](roles/web-svc-libretranslate/README.md#quick-setup) | [Corporate Design](roles/web-svc-css/), [Keycloak](roles/web-app-keycloak/), [Matomo](roles/web-app-matomo/), [Prometheus](roles/web-app-prometheus/), [Tor Onion Service](roles/svc-net-tor/) |
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# recover
|
||||
|
||||
Uniform recovery for the `svc-bkp-*` backup roles. One command wraps each
|
||||
role's `files/recover.py` behind a single grammar and drives a full
|
||||
role's `files/python/recover.py` behind a single grammar and drives a full
|
||||
disaster recovery in the correct order.
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Recoverer classes: one per svc-bkp-* recovery type.
|
||||
|
||||
Each Recoverer parses and validates its own colon-encoded ``source`` and
|
||||
builds the role's ``files/recover.py`` invocation. Colon segments are
|
||||
builds the role's ``files/python/recover.py`` invocation. Colon segments are
|
||||
classified by shape: an ABSOLUTE path is the restore destination (replacing
|
||||
a --target flag); for device a RELATIVE segment is the on-device snapshot
|
||||
subpath and an all-digit ``YYYYMMDDHHMMSS`` segment is the generation to
|
||||
@@ -47,7 +47,7 @@ def remote_target(target: str) -> bool:
|
||||
|
||||
|
||||
class Recoverer(ABC):
|
||||
"""One recovery type backed by a role's ``files/recover.py``."""
|
||||
"""One recovery type backed by a role's ``files/python/recover.py``."""
|
||||
|
||||
name: str
|
||||
role: str
|
||||
@@ -55,7 +55,9 @@ class Recoverer(ABC):
|
||||
no_backup_flag: bool = True
|
||||
|
||||
def script(self) -> str:
|
||||
return str(PROJECT_ROOT / "roles" / self.role / "files" / "recover.py")
|
||||
return str(
|
||||
PROJECT_ROOT / "roles" / self.role / "files" / "python" / "recover.py"
|
||||
)
|
||||
|
||||
@abstractmethod
|
||||
def args(self, source: str, target: str) -> list[str]:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
# Recovery schema for `infinito administration recover`.
|
||||
# One uniform command wraps each svc-bkp-* role's files/recover.py.
|
||||
# One uniform command wraps each svc-bkp-* role's files/python/recover.py.
|
||||
|
||||
command: "recover <type> <source> <target> [--preview] [--no-safety-backup]"
|
||||
target: "host to restore onto (positional label)"
|
||||
|
||||
+2
-2
@@ -140,7 +140,7 @@ INFINITO_DNS_HOSTS_FILE=/etc/hosts
|
||||
INFINITO_DNS_IP=172.30.0.53
|
||||
|
||||
# Repo-relative path of the docker CLI install script.
|
||||
INFINITO_DOCKER_CLI_INSTALL_SCRIPT=roles/sys-svc-container/files/install-cli.sh
|
||||
INFINITO_DOCKER_CLI_INSTALL_SCRIPT=roles/sys-svc-container/files/shell/install-cli.sh
|
||||
|
||||
# Filesystem the docker data root runs on; empty until scripts/tests/deploy/utils/filesystem/resolve.sh settles the row's kind.
|
||||
INFINITO_DOCKER_FILESYSTEM=
|
||||
@@ -257,7 +257,7 @@ INFINITO_PUBLISH_PORTS=true
|
||||
INFINITO_PULL_POLICY=never
|
||||
|
||||
# Repo-relative path of the system python install script.
|
||||
INFINITO_PYTHON_INSTALL_SCRIPT=roles/dev-python/files/install.sh
|
||||
INFINITO_PYTHON_INSTALL_SCRIPT=roles/dev-python/files/shell/install.sh
|
||||
|
||||
# The compose deploy runs the recover drill between PASS 1 and PASS 2 (backup/recover verification); set `false` to skip.
|
||||
INFINITO_RECOVER_DRILL=true
|
||||
|
||||
@@ -13,7 +13,7 @@ For injector wiring, activation, and repository-wide behavior rules, see [Contri
|
||||
## Implement
|
||||
|
||||
- You MUST use `templates/javascript.js.j2` when runtime values from the inventory or role variables must be rendered into the browser code.
|
||||
- You MUST use `files/javascript.js` when the script is static and does not depend on templating.
|
||||
- You MUST use `files/javascript/javascript.js` when the script is static and does not depend on templating.
|
||||
- You MUST wait for the DOM before touching elements, and guard missing elements so unrelated pages do not break.
|
||||
- You MUST keep event handlers, observers, and DOM mutations idempotent because injected scripts may run on dynamic pages or be triggered repeatedly.
|
||||
- You MUST prefer stable selectors and narrow hooks over text matching or timing-based hacks.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
End-to-end flow of the backup chain and its recover counterparts. Solid
|
||||
arrows run on schedule (systemd units + pull); dashed arrows are the
|
||||
recover direction (`files/recover.py` of each role, enforced by
|
||||
recover direction (`files/python/recover.py` of each role, enforced by
|
||||
`tests/lint/ansible/roles/test_bkp_roles_have_recover.py`). The swarm
|
||||
test pipeline exercises the full chain in
|
||||
`scripts/tests/deploy/swarm/routine/backup/base.sh`.
|
||||
@@ -65,7 +65,7 @@ underneath the replay.
|
||||
|
||||
Per-role recover procedures live in each role's `## Recover` README
|
||||
section; `svc-bkp-remote-2-local` documents its one-way opt-out in
|
||||
`files/recover.py.nocheck`.
|
||||
`files/python/recover.py.nocheck`.
|
||||
|
||||
## Deploy-time trigger flow
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ You MUST use these linting and quality tools where applicable:
|
||||
You MUST apply these repo-wide rules when you add, move, or review files:
|
||||
|
||||
- Keep broad folders shallow when that helps readability. Direct children SHOULD stay at 12 or fewer items per folder.
|
||||
- Treat structural hubs such as `roles/`, `cli/`, `tests/unit/plugins/filter`, `tests/unit/roles`, `inventories/bundles/servers`, `inventories/bundles/workstations`, `plugins/filter`, `plugins/lookup`, `group_vars/all`, and `.github/workflows` as intentional exceptions when they are used to organize the tree.
|
||||
- Treat structural hubs such as `roles/`, `cli/`, `tests/unit/python/plugins/filter`, `tests/unit/python/roles`, `inventories/bundles/servers`, `inventories/bundles/workstations`, `plugins/filter`, `plugins/lookup`, `group_vars/all`, and `.github/workflows` as intentional exceptions when they are used to organize the tree.
|
||||
- You SHOULD prefer smaller, more focused folders over dumping many unrelated files into one directory.
|
||||
|
||||
For refactoring guidance, see [Refactoring](../refactoring.md).
|
||||
|
||||
@@ -67,8 +67,8 @@ The placement rule is per check. The catalog "Position" column uses these labels
|
||||
| `hardcoded-dns-resolver` | same or above | [test_no_hardcoded_dns_resolvers.py](../../../../tests/lint/repository/network/test_no_hardcoded_dns_resolvers.py) | Marks a line that needs a literal IP from `NETWORK_PUBLIC_DNS_RESOLVERS` where the substitution point cannot consume the variable (CoreDNS non-Jinja templates, host-bootstrap shell, doc examples). |
|
||||
| `dynamic-flag` | same line OR comment block above key | [test_dynamic_flags.py](../../../../tests/integration/roles/meta/services/test_dynamic_flags.py) | Marks a `roles/*/meta/services.yml` flag whose value stays literal. Per-flag (same line) for databases. Block-level (comment block above) when both flags stay literal. |
|
||||
| `native-metrics` | comment block above | [test_native_metrics_contract.py](../../../../tests/integration/roles/meta/services/prometheus/test_native_metrics_contract.py) | Marks a role whose `services.prometheus.native_metrics.enabled` and `templates/prometheus.yml.j2` presence are intentionally inconsistent. Reserved for prepared-but-default-off scrape fragments (operator opt-in). |
|
||||
| `prometheus-scrape` | same or above | [test_roles_with_service.py](../../../../tests/unit/plugins/lookup/test_roles_with_service.py) | Documents a `services.prometheus.scrape: false` opt-out in `roles/<role>/meta/services.yml`. The role keeps `services.prometheus.{enabled,shared}: true` (so the role-wiring contract stays satisfied) but `roles_with_service('prometheus')` drops it from `PROMETHEUS_TARGET_ROLES_JSON`. Reserved for 301-redirect-only vhosts that never serve a request through lua-resty-prometheus, so they emit no `app="<role>"` label and have no scrape target. The marker accompanies the `scrape:` data flag the lookup honors. |
|
||||
| `matomo-track` | same or above | [test_roles_with_service.py](../../../../tests/unit/plugins/lookup/test_roles_with_service.py) | Documents a `services.matomo.track: false` opt-out in `roles/<role>/meta/services.yml`. The role keeps `services.matomo.{enabled,shared}: true` (so the role-wiring contract stays satisfied) but `roles_with_service('matomo')` drops it from `MATOMO_TARGET_ROLES_JSON` and the matomo tracker e2e contract. Reserved for static-file (autoindex) and 301-redirect vhosts that carry no user-facing HTML page worth a `_paq` tracker. The marker accompanies the `track:` data flag the lookup honors. |
|
||||
| `prometheus-scrape` | same or above | [test_roles_with_service.py](../../../../tests/unit/python/plugins/lookup/test_roles_with_service.py) | Documents a `services.prometheus.scrape: false` opt-out in `roles/<role>/meta/services.yml`. The role keeps `services.prometheus.{enabled,shared}: true` (so the role-wiring contract stays satisfied) but `roles_with_service('prometheus')` drops it from `PROMETHEUS_TARGET_ROLES_JSON`. Reserved for 301-redirect-only vhosts that never serve a request through lua-resty-prometheus, so they emit no `app="<role>"` label and have no scrape target. The marker accompanies the `scrape:` data flag the lookup honors. |
|
||||
| `matomo-track` | same or above | [test_roles_with_service.py](../../../../tests/unit/python/plugins/lookup/test_roles_with_service.py) | Documents a `services.matomo.track: false` opt-out in `roles/<role>/meta/services.yml`. The role keeps `services.matomo.{enabled,shared}: true` (so the role-wiring contract stays satisfied) but `roles_with_service('matomo')` drops it from `MATOMO_TARGET_ROLES_JSON` and the matomo tracker e2e contract. Reserved for static-file (autoindex) and 301-redirect vhosts that carry no user-facing HTML page worth a `_paq` tracker. The marker accompanies the `track:` data flag the lookup honors. |
|
||||
| `variants-static-override` | same line | [test_variants_no_static_override.py](../../../../tests/integration/roles/meta/services/test_variants_no_static_override.py) | Allows a `roles/*/meta/variants.yml` leaf override of an attribute whose base value in `meta/services.yml` is a static literal. Place on the override line in `variants.yml`. Use only when the consumer chain is provably immune to the variant-merge propagation gap; the default is to make the base value dynamic via `"{{ '<role>' in group_names }}"`. |
|
||||
| `variants-shared-false-once` | same or above | [test_variants_shared_false_once.py](../../../../tests/lint/ansible/services/test_variants_shared_false_once.py) | Exempts one `roles/*/meta/variants.yml` `services.<key>.shared: false` pin from the one-local-provider-variant limit for a service whose base `meta/services.yml` uses literal `enabled: true` and dynamic `shared`. Place on the extra `shared: false` line or service key line. Place above the service key in `meta/services.yml` to exempt the service. |
|
||||
| `variants-services-match` | same or above | [test_services_match.py](../../../../tests/integration/roles/meta/variants/test_services_match.py) | Allows a `roles/*/meta/variants.yml` `services.<key>` entry to reference a service key that is NOT declared as a top-level entry in `meta/services.yml`. Reserved for resolver-only matrix hooks (typically on invokable infrastructure roles) whose variant entries pin the round's companion topology via service-key flags the resolver maps to provider roles, with no real consumer contract in the base meta. |
|
||||
|
||||
@@ -7,7 +7,7 @@ Run unit tests with `make test-unit`.
|
||||
|
||||
- You MUST use Python `unittest` as the test framework.
|
||||
- Tests MUST live under `tests/unit/`.
|
||||
- Mirror the source tree: a file at `plugins/lookup/service.py` gets its tests at `tests/unit/plugins/lookup/test_service.py`.
|
||||
- Mirror the source tree: a file at `plugins/lookup/service.py` gets its tests at `tests/unit/python/plugins/lookup/test_service.py`.
|
||||
|
||||
## Requirements 📋
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ applications:
|
||||
|---|---|
|
||||
| [applications.py](../../../../../../plugins/lookup/applications.py) | Runtime entry point for the `applications` lookup. |
|
||||
| [applications.py (cache)](../../../../../../utils/cache/applications.py) | Shared aggregation helper that builds and caches defaults (`get_application_defaults`, `get_variants`, `get_merged_applications`). |
|
||||
| [test_applications.py](../../../../../../tests/unit/plugins/lookup/test_applications.py) | Unit tests covering the full-dict, single-entry, override, strict missing, and non-strict missing cases. |
|
||||
| [test_applications.py](../../../../../../tests/unit/python/plugins/lookup/test_applications.py) | Unit tests covering the full-dict, single-entry, override, strict missing, and non-strict missing cases. |
|
||||
|
||||
For the related users pattern see [users.md](users.md).
|
||||
For the per-role matrix-variant list that backs `applications` when more than one shape exists, see [variants.md](../../../../design/variants.md) (deploy-time mechanism) and [variants.md](../../role/variants.md) (file format).
|
||||
@@ -82,6 +82,6 @@ users:
|
||||
|---|---|
|
||||
| [users.py](../../../../../../plugins/lookup/users.py) | Runtime entry point for the `users` lookup. |
|
||||
| [users/ (cache)](../../../../../../utils/cache/users/) | Shared aggregation helper package that builds and caches defaults, handles reserved users, UID/GID allocation, and uniqueness validation. Placeholder substitution (DOMAIN_PRIMARY / ORGANIZATION / SOFTWARE_NAME) lives in [users/placeholders.py](../../../../../../utils/cache/users/placeholders.py). |
|
||||
| [test_users.py](../../../../../../tests/unit/plugins/lookup/test_users.py) | Unit tests covering the full-dict, single-entry, override, strict missing, and non-strict missing cases. |
|
||||
| [test_users.py](../../../../../../tests/unit/python/plugins/lookup/test_users.py) | Unit tests covering the full-dict, single-entry, override, strict missing, and non-strict missing cases. |
|
||||
|
||||
For the related applications pattern see [applications.md](applications.md).
|
||||
@@ -7,10 +7,10 @@ For browser-side validation requirements after visible behavior changes, see [Pl
|
||||
|
||||
## `javascript.js.j2` ⚙️
|
||||
|
||||
- `sys-front-inj-javascript` loads `templates/javascript.js.j2` when it exists and otherwise falls back to `files/javascript.js`.
|
||||
- `sys-front-inj-javascript` loads `templates/javascript.js.j2` when it exists and otherwise falls back to `files/javascript/javascript.js`.
|
||||
- The injector runs when `services.javascript.enabled` is enabled.
|
||||
- The loaded script is collapsed into a one-liner before injection and added to the CSP hash list so inline execution remains consistent with the generated policy.
|
||||
- You MUST use `javascript.js.j2` when the script depends on role variables or inventory values, and use `files/javascript.js` when the script is static.
|
||||
- You MUST use `javascript.js.j2` when the script depends on role variables or inventory values, and use `files/javascript/javascript.js` when the script is static.
|
||||
|
||||
## Inventory 📋
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ This declares two variants. Variant 0 pins every dynamic service-key from `meta/
|
||||
2. Make sure variant 0 pins every dynamic service-key from `meta/services.yml` to `enabled: true, shared: true`.
|
||||
3. Append a list entry for the new variant. For every dynamic service-key variant 0 enables, the new entry MUST either keep it on (re-pin `enabled: true, shared: true`) or explicitly disable it (`enabled: false, shared: false`). Add the variant-specific overrides that justify the new entry.
|
||||
4. If the new variant relies on cleanup steps that the standard inter-round entity purge does not cover, extend the role's purge handling. The matrix wrapper invokes the standard purge between rounds for every app whose variant changed.
|
||||
5. Add or extend the deep-merge edge-case tests in [test_variants.py](../../../../../tests/unit/utils/cache/test_variants.py) when the new variant exercises behaviour beyond the existing fixtures (for example list replacement vs. nested scalar override).
|
||||
5. Add or extend the deep-merge edge-case tests in [test_variants.py](../../../../../tests/unit/python/utils/cache/test_variants.py) when the new variant exercises behaviour beyond the existing fixtures (for example list replacement vs. nested scalar override).
|
||||
|
||||
## What Not To Do 🚫
|
||||
|
||||
|
||||
@@ -220,8 +220,8 @@ The `lookup('database', ...)` API is the convenience accessor for database conne
|
||||
| [load_service.yml](../../../../../roles/sys-service-loader/tasks/load_service.yml) | Per-service load helper used by the central service loader |
|
||||
| [01_constructor.yml](../../../../../tasks/stages/01_constructor.yml) | Calls the service loader during constructor |
|
||||
| [load/app.yml](../../../../../tasks/utils/load/app.yml) | Run-once role loader |
|
||||
| [test_service_registry.py](../../../../../tests/unit/utils/roles/applications/services/test_registry.py) | Unit tests for discovery, buckets, and `run_after` ordering |
|
||||
| [test_service.py](../../../../../tests/unit/plugins/lookup/test_service.py) | Unit tests for `lookup('service', ...)` |
|
||||
| [test_service_registry.py](../../../../../tests/unit/python/utils/roles/applications/services/test_registry.py) | Unit tests for discovery, buckets, and `run_after` ordering |
|
||||
| [test_service.py](../../../../../tests/unit/python/plugins/lookup/test_service.py) | Unit tests for `lookup('service', ...)` |
|
||||
| [test_resolvable.py](../../../../../tests/integration/infrastructure/services/test_resolvable.py) | Integration checks for discovered service resolution |
|
||||
| [test_canonical.py](../../../../../tests/integration/infrastructure/services/test_canonical.py) | Canonical alias consistency checks |
|
||||
| [test_transitive_dependencies.py](../../../../../tests/integration/infrastructure/services/test_transitive_dependencies.py) | Integration coverage for transitive dependency resolution |
|
||||
@@ -6,7 +6,7 @@ For administrator-facing configuration (keys, override variables, precedence), s
|
||||
Primary files:
|
||||
|
||||
- [email.py](../../../../../plugins/lookup/email.py) for the plugin.
|
||||
- [test_email.py](../../../../../tests/unit/plugins/lookup/test_email.py) for unit tests.
|
||||
- [test_email.py](../../../../../tests/unit/python/plugins/lookup/test_email.py) for unit tests.
|
||||
|
||||
## Call Shapes 📞
|
||||
|
||||
|
||||
@@ -66,9 +66,9 @@ Apps without a `meta/variants.yml` file collapse to a single empty overlay in `_
|
||||
| [init.py](../../../cli/administration/deploy/development/init.py) | Dev CLI entry that drives `build_dev_inventory_matrix` to materialise `<inventory-dir>-<round>` folders. |
|
||||
| [deploy/cli.py](../../../cli/administration/deploy/development/deploy/cli.py) | Dev CLI entry that re-derives the matrix plan and iterates one deploy per folder, with per-app cleanup between rounds. |
|
||||
| [entity.sh](../../../scripts/tests/deploy/local/purge/entity.sh) | Cleanup script invoked between rounds for every app in the previous round's include set. |
|
||||
| [test_variants.py](../../../tests/unit/utils/cache/test_variants.py) | Unit tests covering parser edge cases, deep-merge semantics, caching, and the variant-zero default path. |
|
||||
| [tests/.../inventory/](../../../tests/unit/cli/administration/deploy/development/inventory/__init__.py) | Unit-test package mirroring the source split: [`test_spec.py`](../../../tests/unit/cli/administration/deploy/development/inventory/test_spec.py), [`test_payload.py`](../../../tests/unit/cli/administration/deploy/development/inventory/test_payload.py), [`test_planner.py`](../../../tests/unit/cli/administration/deploy/development/inventory/test_planner.py), [`test_builder.py`](../../../tests/unit/cli/administration/deploy/development/inventory/test_builder.py). |
|
||||
| [test_matrix_deploy.py](../../../tests/unit/cli/administration/deploy/development/test_matrix_deploy.py) | Wrapper-level tests covering the per-round folder iteration and cleanup logic. |
|
||||
| [test_variants.py](../../../tests/unit/python/utils/cache/test_variants.py) | Unit tests covering parser edge cases, deep-merge semantics, caching, and the variant-zero default path. |
|
||||
| [tests/.../inventory/](../../../tests/unit/python/cli/administration/deploy/development/inventory/__init__.py) | Unit-test package mirroring the source split: [`test_spec.py`](../../../tests/unit/python/cli/administration/deploy/development/inventory/test_spec.py), [`test_payload.py`](../../../tests/unit/python/cli/administration/deploy/development/inventory/test_payload.py), [`test_planner.py`](../../../tests/unit/python/cli/administration/deploy/development/inventory/test_planner.py), [`test_builder.py`](../../../tests/unit/python/cli/administration/deploy/development/inventory/test_builder.py). |
|
||||
| [test_matrix_deploy.py](../../../tests/unit/python/cli/administration/deploy/development/test_matrix_deploy.py) | Wrapper-level tests covering the per-round folder iteration and cleanup logic. |
|
||||
| [cli.py (provision)](../../../cli/administration/inventory/provision/cli.py) | Parses `--app-variants <JSON>` and forwards the per-app variant index to `generate_credentials_for_roles`. |
|
||||
| [credentials_generator.py](../../../cli/administration/inventory/provision/credentials_generator.py) | Issues one credentials subprocess per app, appending `--variant <N>` when the app's variant is set. |
|
||||
| [credentials/](../../../cli/administration/inventory/credentials/__main__.py) | `InventoryManager`-backed credential generator; `--variant N` selects which `variants.yml` overlay applies. |
|
||||
|
||||
@@ -78,7 +78,7 @@ The HTTPS-only inner-build gap requires per-image CA-trust bootstrap, which is o
|
||||
|
||||
## Compose Wrapper Auto-Detection 🪄
|
||||
|
||||
The runner's `compose` wrapper at [roles/sys-svc-compose/files/compose.py](../../../roles/sys-svc-compose/files/compose.py) auto-detects compose files when invoked from per-app directories under `/opt/compose/<app>/`:
|
||||
The runner's `compose` wrapper at [roles/sys-svc-compose/files/python/compose.py](../../../roles/sys-svc-compose/files/python/compose.py) auto-detects compose files when invoked from per-app directories under `/opt/compose/<app>/`:
|
||||
|
||||
| File | When |
|
||||
|---|---|
|
||||
@@ -87,7 +87,7 @@ The runner's `compose` wrapper at [roles/sys-svc-compose/files/compose.py](../..
|
||||
| `compose.ca.override.yml` | when present (TLS self-signed CA-inject runs) |
|
||||
| `compose.cache.override.yml` | generated on the fly when `INFINITO_CACHE_PACKAGE_FRONTEND_IP` is set; emits `build.extra_hosts` for every service that has a `build:` key |
|
||||
|
||||
[pull.py](../../../roles/sys-svc-compose/files/pull.py) delegates to the same wrapper so `pull` and `build --pull` operations see the identical `-f` set.
|
||||
[pull.py](../../../roles/sys-svc-compose/files/python/pull.py) delegates to the same wrapper so `pull` and `build --pull` operations see the identical `-f` set.
|
||||
|
||||
## Environment Variables 🌳
|
||||
|
||||
@@ -119,7 +119,7 @@ When a new package manager or upstream needs caching:
|
||||
2. If the upstream uses HTTPS, add it to `HOSTNAMES` in [package-frontend-certs.sh](../../../scripts/docker/cache/package-frontend/certs.sh) so a leaf cert is issued.
|
||||
3. Add a server-block in [upstreams.conf](../../../compose/package-cache-frontend/upstreams.conf) that reverse-proxies onto the new Nexus repo path (rewrite if upstream URL prefix differs from the Nexus repo path).
|
||||
4. Add an `extra_hosts` entry on the `infinito` service in [compose/cache.override.yml](../../../compose/cache.override.yml) for runner-side traffic.
|
||||
5. If the upstream is HTTP-only and inner-`dockerd` builds need it, also add it to `_CACHE_HTTP_HOSTNAMES` in [compose.py](../../../roles/sys-svc-compose/files/compose.py) so the per-app `compose.cache.override.yml` includes it in `build.extra_hosts`.
|
||||
5. If the upstream is HTTP-only and inner-`dockerd` builds need it, also add it to `_CACHE_HTTP_HOSTNAMES` in [compose.py](../../../roles/sys-svc-compose/files/python/compose.py) so the per-app `compose.cache.override.yml` includes it in `build.extra_hosts`.
|
||||
|
||||
## Background 📚
|
||||
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ module.exports = [
|
||||
"**/__pycache__/**",
|
||||
// Jinja2-templated JS — not valid JS until rendered.
|
||||
"roles/*/templates/**/*.js",
|
||||
"roles/web-app-bigbluebutton/files/ep_redis_publisher_index.js",
|
||||
"roles/web-app-bigbluebutton/files/javascript/ep_redis_publisher_index.js",
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@ Requires: openssh-clients
|
||||
#
|
||||
# EL9 AppStream exposes only python3.9 via the generic python3 capability.
|
||||
# In those environments we still bootstrap Python 3.11+ separately via
|
||||
# roles/dev-python/files/install.sh, but the RPM metadata must remain
|
||||
# roles/dev-python/files/shell/install.sh, but the RPM metadata must remain
|
||||
# installable from the stock distro repositories.
|
||||
%if 0%{?rhel} == 9
|
||||
Requires: python3
|
||||
|
||||
+3
-3
@@ -194,8 +194,8 @@ ignore = [
|
||||
# ``patch.object(sut, "os")`` replacements). Converting these call
|
||||
# sites to ``pathlib.Path`` would require rewriting every coupled
|
||||
# test in lockstep — out of scope for the use-pathlib pass.
|
||||
"roles/sys-ctl-rpr-container-hard/files/script.py" = ["PTH"]
|
||||
"roles/sys-ctl-rpr-container-soft/files/script.py" = ["PTH"]
|
||||
"roles/sys-ctl-rpr-container-hard/files/python/script.py" = ["PTH"]
|
||||
"roles/sys-ctl-rpr-container-soft/files/python/script.py" = ["PTH"]
|
||||
|
||||
# BLE001 (flake8-blind-except) ratchet.
|
||||
# Broad `except Exception:` is now selected project-wide so NEW code is
|
||||
@@ -264,7 +264,7 @@ ignore = [
|
||||
"cli/administration/deploy/development/deploy.py" = ["N806"]
|
||||
"cli/administration/deploy/development/init.py" = ["N806"]
|
||||
"cli/administration/deploy/development/inventory.py" = ["N806"]
|
||||
"tests/unit/cli/administration/deploy/development/test_inventory.py" = ["N806"]
|
||||
"tests/unit/python/cli/administration/deploy/development/test_inventory.py" = ["N806"]
|
||||
|
||||
# Lazy-loaded class binding: ``ValueGenerator = _value_generator_cls()``
|
||||
# rebinds the imported class inside the function. PEP 8 keeps the
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -91,7 +91,7 @@
|
||||
- name: 🗑️ Optionally drop shell snippet for Nix
|
||||
ansible.builtin.script:
|
||||
cmd: >-
|
||||
{{ role_path }}/files/write_nix_shell_snippet.sh
|
||||
{{ role_path }}/files/shell/write_nix_shell_snippet.sh
|
||||
{{ dev_nix_shell_snippet_path | quote }}
|
||||
register: dev_nix_shell_snippet_result
|
||||
changed_when: >
|
||||
@@ -105,7 +105,7 @@
|
||||
- name: 🧹 Aggressively prune Nix data (GC + optimise)
|
||||
become: true
|
||||
ansible.builtin.script: >
|
||||
aggressive_prune_nix.sh
|
||||
shell/aggressive_prune_nix.sh
|
||||
{{ dev_nix_binary_path | quote }}
|
||||
changed_when: true
|
||||
when:
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
- name: 🧹 Purge stale nixbld users blocking the multi-user installer
|
||||
ansible.builtin.script:
|
||||
cmd: "{{ role_path }}/files/purge_stale_nixbld.sh"
|
||||
cmd: "{{ role_path }}/files/shell/purge_stale_nixbld.sh"
|
||||
register: dev_nix_purge_stale_nixbld_result
|
||||
changed_when: >
|
||||
dev_nix_purge_stale_nixbld_result.stdout is search('\\[CHANGED\\]')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
- name: 🧹 Purge stale nixbld users blocking the multi-user installer
|
||||
ansible.builtin.script:
|
||||
cmd: "{{ role_path }}/files/purge_stale_nixbld.sh"
|
||||
cmd: "{{ role_path }}/files/shell/purge_stale_nixbld.sh"
|
||||
register: dev_nix_purge_stale_nixbld_result
|
||||
changed_when: >
|
||||
dev_nix_purge_stale_nixbld_result.stdout is search('\\[CHANGED\\]')
|
||||
|
||||
@@ -24,8 +24,8 @@ fi
|
||||
. /etc/os-release
|
||||
ID_LIKE="${ID_LIKE:-}"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
|
||||
DOCKER_APT_SANITIZER="${REPO_ROOT}/roles/sys-svc-container/files/apt_repo.sh"
|
||||
REPO_ROOT="$(cd "${SCRIPT_DIR}/../../../.." && pwd)"
|
||||
DOCKER_APT_SANITIZER="${REPO_ROOT}/roles/sys-svc-container/files/shell/apt_repo.sh"
|
||||
|
||||
log() {
|
||||
printf '>>> [dev-python] %s\n' "$*"
|
||||
@@ -5,7 +5,7 @@
|
||||
when: run_once_sys_pip is not defined
|
||||
|
||||
- name: 📦 Install and prefer Python 3.11+ as default
|
||||
ansible.builtin.script: "{{ role_path }}/files/install.sh"
|
||||
ansible.builtin.script: "{{ role_path }}/files/shell/install.sh"
|
||||
environment:
|
||||
SKIP_DOCKER_APT_SANITIZER: "1"
|
||||
become: true
|
||||
|
||||
@@ -90,7 +90,7 @@ infinito administration deploy dedicated "$INVENTORY/devices.yml" \
|
||||
|
||||
## Recover
|
||||
|
||||
Run `files/recover.py` on the host with the backup device attached:
|
||||
Run `files/python/recover.py` on the host with the backup device attached:
|
||||
|
||||
```
|
||||
recover.py /dev/sdX1 /mnt/usb-recover /var/lib/infinito/backup [--snapshot <timestamp>]
|
||||
|
||||
+4
-1
@@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
# nocheck: mirrored-unit-test - subclasses utils.recovery.base and is exercised
|
||||
# collectively by tests/unit/python/utils/recovery/test_role_recover_scripts.py; a
|
||||
# per-role copy would assert the base class twice over
|
||||
"""Restore the local backup root from the encrypted backup device.
|
||||
|
||||
Opens the LUKS device (interactive passphrase prompt, or stdin with
|
||||
@@ -25,7 +28,7 @@ import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
_REPO_ROOT = Path(__file__).resolve().parents[3] # nocheck: project-root-import
|
||||
_REPO_ROOT = Path(__file__).resolve().parents[4] # nocheck: project-root-import
|
||||
sys.path.insert(0, str(_REPO_ROOT))
|
||||
|
||||
from utils.recovery.base import DirectoryRecovery # noqa: E402
|
||||
+3
@@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
# nocheck: mirrored-unit-test - main() is one straight line of rsync and mount
|
||||
# subprocess calls against an attached backup device; every branch it has is a return
|
||||
# code from the host, so the assertions would only restate the mocks
|
||||
|
||||
import datetime
|
||||
import glob
|
||||
@@ -97,7 +97,7 @@ infinito administration deploy dedicated "$INVENTORY/devices.yml" \
|
||||
|
||||
## Recover
|
||||
|
||||
Run `files/recover.py` on the host that serves the NFS export:
|
||||
Run `files/python/recover.py` on the host that serves the NFS export:
|
||||
|
||||
```
|
||||
recover.py <backups>/<machine-hash>/backup-nfs-to-local/<generation>/files/<state>/<volume> <export-base>/<state>/<volume>
|
||||
|
||||
+4
-1
@@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
# nocheck: mirrored-unit-test - subclasses utils.recovery.base and is exercised
|
||||
# collectively by tests/unit/python/utils/recovery/test_role_recover_scripts.py; a
|
||||
# per-role copy would assert the base class twice over
|
||||
"""Restore an NFS export subtree from a backup snapshot.
|
||||
|
||||
Runs the role's deployed backup unit first (the usual differential
|
||||
@@ -17,7 +20,7 @@ import argparse
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
_REPO_ROOT = Path(__file__).resolve().parents[3] # nocheck: project-root-import
|
||||
_REPO_ROOT = Path(__file__).resolve().parents[4] # nocheck: project-root-import
|
||||
sys.path.insert(0, str(_REPO_ROOT))
|
||||
|
||||
from utils.recovery.base import DirectoryRecovery # noqa: E402
|
||||
File renamed without changes.
@@ -92,7 +92,7 @@ infinito administration deploy dedicated "$INVENTORY/devices.yml" \
|
||||
|
||||
## Recover
|
||||
|
||||
This role's direction is one-way by design (`files/recover.py.nocheck`): it pulls provider backups onto this host, so the pulled tree under `<backups>/<machine-hash>/<repo>/<generation>/` IS the recovery store and there is no live target here to restore into.
|
||||
This role's direction is one-way by design (`files/python/recover.py.nocheck`): it pulls provider backups onto this host, so the pulled tree under `<backups>/<machine-hash>/<repo>/<generation>/` IS the recovery store and there is no live target here to restore into.
|
||||
|
||||
To recover a source system, transfer the wanted generation to it (the provider's `backup` user only whitelists pull commands, so pushing requires an explicit operator rsync with a root-capable target) and run the matching role's `recover.py` there (`svc-bkp-volume-2-local` for docker volumes, `svc-bkp-nfs-2-local` for NFS exports).
|
||||
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -19,7 +19,7 @@
|
||||
|
||||
- name: "🚀 Deploy '{{ DOCKER_BACKUP_REMOTE_2_LOCAL_SCRIPT }}'"
|
||||
copy:
|
||||
src: "{{ DOCKER_BACKUP_REMOTE_2_LOCAL_FILE }}"
|
||||
src: "python/{{ DOCKER_BACKUP_REMOTE_2_LOCAL_FILE }}"
|
||||
dest: "{{ DOCKER_BACKUP_REMOTE_2_LOCAL_SCRIPT }}"
|
||||
mode: "0755"
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ infinito administration deploy dedicated "$INVENTORY/devices.yml" \
|
||||
|
||||
## Recover
|
||||
|
||||
Run `files/recover.py` on the target host:
|
||||
Run `files/python/recover.py` on the target host:
|
||||
|
||||
```
|
||||
recover.py <backups>/<machine-hash>/backup-secrets-to-local/<generation>/files [--restore-node-identity]
|
||||
|
||||
+4
-1
@@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
# nocheck: mirrored-unit-test - subclasses utils.recovery.base and is exercised
|
||||
# collectively by tests/unit/python/utils/recovery/test_role_recover_scripts.py; a
|
||||
# per-role copy would assert the base class twice over
|
||||
"""Restore host-generated secret material from a backup snapshot.
|
||||
|
||||
Runs the role's deployed backup unit first (a fresh differential
|
||||
@@ -24,7 +27,7 @@ import shutil
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
_REPO_ROOT = Path(__file__).resolve().parents[3] # nocheck: project-root-import
|
||||
_REPO_ROOT = Path(__file__).resolve().parents[4] # nocheck: project-root-import
|
||||
sys.path.insert(0, str(_REPO_ROOT))
|
||||
|
||||
from utils.paths import DIR_SECRETS # noqa: E402
|
||||
File renamed without changes.
@@ -75,7 +75,7 @@ flowchart TD
|
||||
BAUDOLO --> CHECK3B["DR drill [3b]<br>newest backup-docker-to-local generation<br>must be fresh + non-empty<br>(catches over-exclusion)"]
|
||||
EXPORT["svc-bkp-nfs-2-local<br>on the export host<br>rsyncs the export tree"] --> TREE["backup-nfs-to-local/<generation><br>the single capture"]
|
||||
BAUDOLO -.->|"no second copy<br>through the mount"| TREE
|
||||
TREE --> RECOVER["files/recover.py volume<br>resolves Mountpoint + Options"]
|
||||
TREE --> RECOVER["files/python/recover.py volume<br>resolves Mountpoint + Options"]
|
||||
RECOVER -->|"Options set"| PROBE{"mountpoint -q<br>(ssh for --docker-host)"}
|
||||
PROBE -->|unmounted| REFUSE["SystemExit: a restore would land<br>on the node disk and be shadowed<br>on the next mount"]
|
||||
PROBE -->|mounted| RSYNC["rsync -a --delete through the<br>mounted export onto the server"]
|
||||
@@ -296,7 +296,7 @@ credentials live in the target host's own `databases.csv`.
|
||||
|
||||
### A single volume
|
||||
|
||||
Run `files/recover.py` on the backed-up host to restore one volume's files:
|
||||
Run `files/python/recover.py` on the backed-up host to restore one volume's files:
|
||||
|
||||
```
|
||||
recover.py <backups>/<machine-hash>/backup-docker-to-local/<generation>/<volume>/files <volume>
|
||||
|
||||
+4
-1
@@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
# nocheck: mirrored-unit-test - subclasses utils.recovery.base and is exercised
|
||||
# collectively by tests/unit/python/utils/recovery/test_role_recover_scripts.py; a
|
||||
# per-role copy would assert the base class twice over
|
||||
"""Restore a backup-docker-to-local generation: a volume's files, or the
|
||||
generation's database dumps.
|
||||
|
||||
@@ -26,7 +29,7 @@ import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
_REPO_ROOT = Path(__file__).resolve().parents[3] # nocheck: project-root-import
|
||||
_REPO_ROOT = Path(__file__).resolve().parents[4] # nocheck: project-root-import
|
||||
sys.path.insert(0, str(_REPO_ROOT))
|
||||
|
||||
from utils.paths import FILE_DATABASE_SECRETS # noqa: E402
|
||||
@@ -0,0 +1 @@
|
||||
# nocheck: role-files-layout - Role test harness with test.sh as its entry point; grouped by purpose, screened and kept on 2026-08-21.
|
||||
@@ -32,7 +32,7 @@ through the recover chain, require the marker and every recorded container
|
||||
back, and finally let the host's own container health service judge.
|
||||
|
||||
That last step is deliberately the deployed
|
||||
[`sys-ctl-hlth-container` script](../../../sys-ctl-hlth-container/files/script.sh)
|
||||
[`sys-ctl-hlth-container` script](../../../sys-ctl-hlth-container/files/shell/script.sh)
|
||||
rather than a check of the drill's own: it is what watches the host in
|
||||
production, it knows swarm services, and it dumps 200 log lines per sick
|
||||
container. It is invoked as a script, not as its systemd unit — the unit's
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
# nocheck: role-files-layout - Role test harness with test.sh as its entry point; grouped by purpose, screened and kept on 2026-08-21.
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1 @@
|
||||
# nocheck: role-files-layout - Role test harness with test.sh as its entry point; grouped by purpose, screened and kept on 2026-08-21.
|
||||
@@ -18,8 +18,8 @@
|
||||
dest: "{{ [ lookup('container', application_id, 'directories.instance'), item.dest ] | path_join }}"
|
||||
mode: "{{ item.mode }}"
|
||||
loop:
|
||||
- { src: "entrypoint.sh", dest: "entrypoint.sh", mode: "0755" }
|
||||
- { src: "healthcheck.sh", dest: "healthcheck.sh", mode: "0755" }
|
||||
- { src: "shell/entrypoint.sh", dest: "entrypoint.sh", mode: "0755" }
|
||||
- { src: "shell/healthcheck.sh", dest: "healthcheck.sh", mode: "0755" }
|
||||
loop_control:
|
||||
label: "{{ item.dest }}"
|
||||
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1 @@
|
||||
# nocheck: role-files-layout - Role test harness with test.sh as its entry point; grouped by purpose, screened and kept on 2026-08-21.
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
- name: "✅ POSTGRES | Ensure postgres superuser password matches inventory"
|
||||
ansible.builtin.script: > # nocheck: container-address-quote script evals the fragment itself
|
||||
set_postgres_superuser_password.sh {{ POSTGRES_CONTAINER_ADDRESS | quote }} {{ POSTGRES_PASSWORD | quote }}
|
||||
shell/set_postgres_superuser_password.sh {{ POSTGRES_CONTAINER_ADDRESS | quote }} {{ POSTGRES_PASSWORD | quote }}
|
||||
register: postgres_pw_result
|
||||
delegate_to: "{{ STACK_HOST }}"
|
||||
run_once: true
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
rescue:
|
||||
- name: "💾 Postgres | Dump pg_hba.conf into the diagnostics folder" # nocheck: rescue-extra-diagnostics pg_hba.conf is postgres-specific auth config the generic rescue script cannot capture, and it is what a failed TCP-auth wait needs
|
||||
ansible.builtin.script: "{{ lookup('path_absolute', 'roles/svc-db-postgres/files/dump_pg_hba.sh') }}"
|
||||
ansible.builtin.script: "{{ lookup('path_absolute', 'roles/svc-db-postgres/files/shell/dump_pg_hba.sh') }}"
|
||||
environment:
|
||||
POSTGRES_CONTAINER_ADDRESS: "{{ POSTGRES_LOCAL_CID }}"
|
||||
PGPASSWORD: "{{ POSTGRES_PASSWORD }}"
|
||||
|
||||
@@ -20,7 +20,7 @@ RUN rm -rf /var/lib/apt/lists/* \
|
||||
{% endif %}
|
||||
|
||||
COPY <<'BOOT_ENTRYPOINT_EOF' /usr/local/bin/boot-entrypoint.sh
|
||||
{{ lookup('file', lookup('path_absolute', 'roles/svc-db-postgres/files/boot-entrypoint.sh')) }}
|
||||
{{ lookup('file', lookup('path_absolute', 'roles/svc-db-postgres/files/shell/boot-entrypoint.sh')) }}
|
||||
BOOT_ENTRYPOINT_EOF
|
||||
RUN chmod +x /usr/local/bin/boot-entrypoint.sh
|
||||
|
||||
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1 @@
|
||||
# nocheck: role-files-layout - Role test harness with test.sh as its entry point; grouped by purpose, screened and kept on 2026-08-21.
|
||||
@@ -68,7 +68,7 @@
|
||||
|
||||
- name: "🚀 Stage the Tor container entrypoint into the build context"
|
||||
stack_host_copy:
|
||||
src: "{{ role_path }}/files/entrypoint.sh"
|
||||
src: "{{ role_path }}/files/shell/entrypoint.sh"
|
||||
dest: "{{ TOR_ENTRYPOINT_HOST }}"
|
||||
mode: "0755"
|
||||
become: true
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
- name: "⏳ Wait until the node onion answers internally (loopback fast path)"
|
||||
ansible.builtin.script:
|
||||
cmd: "{{ role_path }}/files/onion_self_reach.py {{ TOR_NODE_ONION }}"
|
||||
cmd: "{{ role_path }}/files/python/onion_self_reach.py {{ TOR_NODE_ONION }}"
|
||||
register: _tor_self_reach
|
||||
retries: 90
|
||||
delay: 5
|
||||
|
||||
File renamed without changes.
File renamed without changes.
@@ -1,3 +1,6 @@
|
||||
# nocheck: mirrored-unit-test - orchestrates docker stop/start around an rsync move
|
||||
# between disks; its helpers read live container state through docker inspect and a unit
|
||||
# test would pin the mock, not the migration
|
||||
import argparse
|
||||
import shutil
|
||||
import subprocess
|
||||
File renamed without changes.
@@ -0,0 +1 @@
|
||||
# nocheck: role-files-layout - Role test harness with test.sh as its entry point; grouped by purpose, screened and kept on 2026-08-21.
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
- name: 📄 Copy entrypoint to build context
|
||||
ansible.builtin.copy: # nocheck: stack-host-consumer (include is IS_STACK_HOST-gated)
|
||||
src: entrypoint.sh
|
||||
src: shell/entrypoint.sh
|
||||
dest: "{{ RUNNER_INSTALL_DIR }}/build/entrypoint.sh"
|
||||
mode: "0755"
|
||||
|
||||
|
||||
File renamed without changes.
@@ -66,7 +66,7 @@
|
||||
|
||||
- name: "🔍 Detect {{ DIR_VAR_LIB }} pre-mount state"
|
||||
ansible.builtin.script:
|
||||
cmd: "{{ role_path }}/files/premount_state.sh"
|
||||
cmd: "{{ role_path }}/files/shell/premount_state.sh"
|
||||
executable: /bin/bash
|
||||
environment:
|
||||
DIR_VAR_LIB: "{{ DIR_VAR_LIB }}"
|
||||
|
||||
File renamed without changes.
@@ -1,7 +1,7 @@
|
||||
---
|
||||
- name: "🔍 Detect controller {{ DIR_VAR_LIB }} pre-mount state"
|
||||
ansible.builtin.script:
|
||||
cmd: "{{ lookup('path_absolute', 'roles/svc-storage-nfs-client/files/premount_state.sh') }}"
|
||||
cmd: "{{ lookup('path_absolute', 'roles/svc-storage-nfs-client/files/shell/premount_state.sh') }}"
|
||||
executable: /bin/bash
|
||||
environment:
|
||||
DIR_VAR_LIB: "{{ DIR_VAR_LIB }}"
|
||||
|
||||
@@ -18,7 +18,7 @@ SVC_STORAGE_NFS_SERVER_STATE_ALLOWED_CIDRS:
|
||||
- "*"
|
||||
|
||||
SVC_STORAGE_NFS_SERVER_GANESHA_SERVE: >-
|
||||
ganesha-serve.sh
|
||||
shell/ganesha-serve.sh
|
||||
{{ SVC_STORAGE_NFS_SERVER_SERVICE['ganesha'][ansible_facts['os_family']] | quote }}
|
||||
2049
|
||||
{{ lookup('timeout', 120) | int }}
|
||||
File renamed without changes.
File renamed without changes.
@@ -90,7 +90,7 @@
|
||||
- name: "📦 CA | install trust helper script (SPOT) on host"
|
||||
become: true
|
||||
ansible.builtin.copy:
|
||||
src: "with-ca-trust.sh"
|
||||
src: "shell/with-ca-trust.sh"
|
||||
dest: "{{ BIN_CA_TRUST }}"
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
File renamed without changes.
@@ -1,7 +1,7 @@
|
||||
---
|
||||
- name: "🧹 Cleanup caches and logs (cross-distro: arch/debian/ubuntu/fedora/centos)"
|
||||
become: true
|
||||
ansible.builtin.script: cleanup_caches.sh
|
||||
ansible.builtin.script: shell/cleanup_caches.sh
|
||||
changed_when: true
|
||||
|
||||
- name: 🧹 Cleanup journald logs (CI/container only)
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -6,7 +6,7 @@
|
||||
javascript_file_custom: >-
|
||||
{{ (application_id | abs_role_path_by_application_id ~ '/templates/javascript.js.j2')
|
||||
if lookup('fileglob', application_id | abs_role_path_by_application_id ~ '/templates/javascript.js.j2')
|
||||
else application_id | abs_role_path_by_application_id ~ '/files/javascript.js' }}
|
||||
else application_id | abs_role_path_by_application_id ~ '/files/javascript/javascript.js' }}
|
||||
|
||||
- name: "📄 Load JavaScript code for '{{ application_id }}'"
|
||||
set_fact:
|
||||
|
||||
File renamed without changes.
@@ -1,6 +1,6 @@
|
||||
---
|
||||
- name: 🚀 Deploy logout.js
|
||||
copy:
|
||||
src: logout.js
|
||||
src: javascript/logout.js
|
||||
dest: "{{ INJ_LOGOUT_JS_DESTINATION }}"
|
||||
mode: "0644"
|
||||
@@ -1 +1 @@
|
||||
<script src="{{ lookup('cdn', 'web-svc-cdn').urls.shared.js }}/{{ INJ_LOGOUT_JS_FILE_NAME }}{{ lookup('local_mtime_qs', lookup('path_absolute', 'roles', 'sys-front-inj-logout', 'files', INJ_LOGOUT_JS_FILE_NAME)) }}"></script>
|
||||
<script src="{{ lookup('cdn', 'web-svc-cdn').urls.shared.js }}/{{ INJ_LOGOUT_JS_FILE_NAME }}{{ lookup('local_mtime_qs', lookup('path_absolute', 'roles', 'sys-front-inj-logout', 'files', 'javascript', INJ_LOGOUT_JS_FILE_NAME)) }}"></script>
|
||||
File renamed without changes.
@@ -2,7 +2,7 @@
|
||||
- block:
|
||||
- name: 📁 create {{ BIN_LOCK }}
|
||||
copy:
|
||||
src: sys-lock.py
|
||||
src: python/sys-lock.py
|
||||
dest: "{{ BIN_LOCK }}"
|
||||
mode: "0755"
|
||||
|
||||
|
||||
File renamed without changes.
Loaded 100 of 1076 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user