Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
6b242a0
feat(roles/php): update template for RedHat-based systems, Docs (part…
ebuerki-lf May 12, 2026
2aab24c
fix(roles/php): update timestamp in pool template, use 'd()' in accor…
ebuerki-lf May 13, 2026
e827354
Merge branch 'main' into feat/php_fpm_pool
ebuerki-lf May 13, 2026
858e8df
Merge remote-tracking branch 'origin/main' into feat/php_fpm_pool
ebuerki-lf May 13, 2026
c94b7de
feat(roles/php): update template for Debian-based systems, update doc…
ebuerki-lf May 13, 2026
e222cbe
Add roles/repo_google_chrome
danyalberchtoldlf May 12, 2026
d86d699
Add roles/google_chrome
danyalberchtoldlf May 12, 2026
cc9fbad
fix(roles/icingaweb2_module_pdfexport): wire to chrome-headless service
danyalberchtoldlf May 12, 2026
717ebda
docs(roles/google_chrome): explain why systemd-socket-proxyd is neede…
danyalberchtoldlf May 13, 2026
2a58303
fix(roles/google_chrome): also set systemd_socket_proxyd_bind_any boo…
danyalberchtoldlf May 13, 2026
fa0e98e
refactor(roles/google_chrome): drop migration-specific handler logic
danyalberchtoldlf May 13, 2026
bd20c34
feat(roles/repo_google_chrome): add meta/argument_specs.yml
danyalberchtoldlf May 13, 2026
95852fc
refactor(roles/google_chrome): tighten handler flow and tag boundaries
danyalberchtoldlf May 15, 2026
f0332bc
chore(deps): bump step-security/harden-runner from 2.19.1 to 2.19.3 (…
dependabot[bot] May 15, 2026
a75706e
refactor(roles/google_chrome): rename systemd units and wire CRB repo
NavidSassan May 20, 2026
8f25b4b
refactor(roles/chromium_headless): replace google_chrome with EPEL ch…
NavidSassan May 21, 2026
b7dd3c8
fix(roles/chromium_headless): keep Chromium debugging port bound to l…
NavidSassan May 21, 2026
22aa564
style(roles/chromium_headless): align defaults order and internal nam…
NavidSassan May 21, 2026
04b9251
docs(changelog): condense chromium_headless and pdfexport entries
NavidSassan May 21, 2026
fb859d4
docs(contributing): list chromium_headless under roles with special f…
NavidSassan May 21, 2026
dfad123
style(roles/icingaweb2_module_pdfexport): silence risky-file-permissi…
NavidSassan May 21, 2026
09becac
feat(roles/chromium_headless): add Debian support
NavidSassan May 21, 2026
987b9d4
fix(roles/redis): add missing vars for Debian
NavidSassan May 21, 2026
8f2f227
docs(compatibility): correct chromium_headless tested platforms
NavidSassan May 22, 2026
5ca8fe9
feat(roles/graylog_datanode, roles/graylog_server): add template for …
bhatti-lf May 16, 2026
50d00ef
fix(roles/keycloak): run kc.sh build as keycloak user
jihan-lf May 18, 2026
6b85f06
feat(roles/keycloak): auto-remove bootstrap admin credentials after f…
jihan-lf May 18, 2026
7fd7c41
style(roles/keycloak): improve state file handling and variable naming
NavidSassan May 19, 2026
638b1b3
docs(roles/motd): update default value of motd__legal_notice
ebuerki-lf May 18, 2026
f5a1dcc
fix(roles/nodejs): support switching module stream
bhatti-lf May 19, 2026
429eb22
docs(roles/network): hint towards checking connection name
bhatti-lf May 19, 2026
8ac42d2
fix(roles/blocky): ensure blocky service is restarted after updating …
ebuerki-lf May 19, 2026
66255c1
fix(roles/graylog_server): fix input creation failure by removing a d…
bhatti-lf May 20, 2026
de31e97
fix(roles/graylog_server): enforce a key marked as mandatory in the r…
bhatti-lf May 20, 2026
8e485aa
docs(roles/graylog_server): specify where to get input types from
bhatti-lf May 20, 2026
cb0fd10
fix(roles/graylog_server): fix "conditional result was of type str" d…
bhatti-lf May 20, 2026
33a6579
feat(roles/redis): raise net.core.somaxconn default to 4096
markuslf May 18, 2026
f71a94c
docs(roles): standardize role README structure across the fleet
NavidSassan May 21, 2026
4ccc398
docs(roles/acme_sh): fix indentation
NavidSassan May 21, 2026
dca1bf4
fix(roles): enable CRB and EPEL
jihan-lf May 13, 2026
deabc5b
fix(playbooks): address review on CRB/EPEL enablement
NavidSassan May 21, 2026
77ca813
chore(deps): bump actions/dependency-review-action from 4.9.0 to 5.0.0
dependabot[bot] May 15, 2026
e6df15b
chore(deps): bump step-security/harden-runner from 2.19.3 to 2.19.4 (…
dependabot[bot] May 22, 2026
917297d
chore(deps): bump github/codeql-action from 4.35.4 to 4.35.5 (#256)
dependabot[bot] May 22, 2026
77a7e48
docs(roles/alternatives): fix whitespace
NavidSassan May 22, 2026
b0f7eb2
fix(roles/influxdb): always install `curl`
NavidSassan May 22, 2026
197522e
feat(roles/repo_baseos): add Rocky security repo, enabled by default
bhatti-lf May 22, 2026
612cfa7
docs(contributing): improve content
NavidSassan May 22, 2026
5170633
fix(roles/mariadb_server): add mariadb_server__cnf_innodb_snapshot_is…
ebuerki-lf May 22, 2026
90bfd7d
fix(roles/repo_*): only write basic-auth credentials when a custom mi…
NavidSassan May 22, 2026
246fe7a
fix(roles/kernel_settings): actually apply systemd_cpu_affinity setting
markuslf May 24, 2026
76785d8
chore: remove leftover particle/Vagrantfile
markuslf May 25, 2026
0060cf1
Add plugin unit-test infrastructure + combine_lod fixes (#264)
markuslf May 25, 2026
22c33f7
refactor(plugins): unify bitwarden family and add unit tests (#265)
markuslf May 25, 2026
bd178b7
fix(plugins): make ansible-doc render all in-house plugins + add guar…
markuslf May 25, 2026
7912dcd
refactor(plugins): unify uptimerobot family and add unit tests (#268)
markuslf May 25, 2026
b7701b9
refactor(plugins): unify nextcloud/sqlite/gpg_key/ipa_diff + safe fix…
markuslf May 25, 2026
3a7e80c
fix(plugins/modules/sqlite_query): fail the task on a failed query (#…
markuslf May 25, 2026
2170cc8
fix(plugins/modules/bitwarden_item): honor check mode and preserve pa…
markuslf May 25, 2026
1ddef3d
fix(plugins/modules/nextcloud_occ_app_config): compare array values a…
markuslf May 25, 2026
1b08dc0
fix(plugins/modules/gpg_key): refresh vendored python-gnupg and corre…
markuslf May 25, 2026
c69b622
feat(roles/php): update template for RedHat-based systems, Docs (part…
ebuerki-lf May 12, 2026
f51610d
Merge remote-tracking branch 'origin/main' into feat/php_fpm_pool
ebuerki-lf Jun 3, 2026
b54c7fc
fix(roles/php): remove opcache pool parameters as opcache is shared a…
ebuerki-lf Jun 3, 2026
65b2e9a
docs(roles/php): update examples
ebuerki-lf Jun 3, 2026
3bc1aa4
Merge remote-tracking branch 'origin/main' into feat/php_fpm_pool
ebuerki-lf Jun 5, 2026
a29d132
feat(roles/php): create per-pool session/opcache dirs and wire pool d…
NavidSassan Jun 9, 2026
3d06f92
feat(playbooks/php): run repo_sury on the Debian os family
NavidSassan Jun 9, 2026
4f46f1b
refactor(roles/php): use standard Jinja2 delimiters in the pool confi…
NavidSassan Jun 9, 2026
5935f50
refactor(roles/php): drop dead default() fallbacks from the .ini temp…
NavidSassan Jun 9, 2026
aca11de
Merge branch 'main' into feat/php_fpm_pool
NavidSassan Jun 9, 2026
990bdf0
Merge branch 'main' into feat/php_fpm_pool
ebuerki-lf Jun 11, 2026
79b113e
Merge branch 'main' into feat/php_fpm_pool
ebuerki-lf Jun 11, 2026
b99379a
fix(roles/php): create the php-fpm log dir and rotate per-pool logs o…
NavidSassan Jun 10, 2026
1549184
test(roles/php): add molecule scenario for the php-fpm pools
NavidSassan Jun 11, 2026
1fe1c5c
Merge branch 'main' into feat/php_fpm_pool
NavidSassan Jun 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Breaking Changes

* **role:php**: The PHP-FPM pool config changed for existing hosts. Sessions now live in a per-pool directory (the default `www` pool moves from `/var/lib/php/session` to `/var/lib/php/session/www`), so logged-in users are signed out once after the upgrade. `memory_limit`, `max_execution_time`, `max_input_vars`, `post_max_size`, `upload_max_filesize` and `session.save_path` are now enforced as `php_admin_value`, so applications can no longer raise them at runtime via `ini_set()`. The FPM status path moved from `/fpm-status` to `/www-fpm-status`, and `soap.wsdl_cache_dir` is no longer set (PHP default applies). Worker processes now recycle after 500 requests (`pm.max_requests`), where previously they ran indefinitely.
* **plugin:combine_lod, role:apache_httpd, role:mariadb_server, role:proxysql, role:selinux**: A composite `unique_key` (a list of keys) now requires every component to be set on each item, instead of letting one be filled by a downstream default. Set the previously optional component explicitly: `virtualhost_port` on every `apache_httpd` vHost, `host` on every `mariadb_server` user/role, `port` on every `proxysql` server, and `proto` on every `selinux` port. Otherwise the play fails with a clear error.
* **role:apache_httpd, role:apache_tomcat, role:mastodon, role:postgresql_server**: Rename tags to the project-wide naming scheme. `apache_httpd:config` becomes `apache_httpd:configure`, and `apache_tomcat:users`, `mastodon:users`, `postgresql_server:users` and `postgresql_server:databases` lose their trailing `s` (`...:user`, `...:database`). Adjust any `--tags` / `--skip-tags` invocations and automation that reference the old tag names.
* **role:sshd**: Ship hardened SSH defaults that change the behaviour of existing installations on the next run: X11 forwarding, agent forwarding and TCP keepalives are now off, `MaxAuthTries` is lowered to `3`, `ClientAliveCountMax` to `2`, and `LogLevel` is raised to `VERBOSE`. Sessions relying on X11 or agent forwarding stop working, and a client offering more than three keys from its SSH agent can be locked out. Restore the previous behaviour where needed via the new variables: `sshd__x11_forwarding: true`, `sshd__allow_agent_forwarding: true`, `sshd__tcp_keep_alive: true`, `sshd__max_auth_tries: 6`, `sshd__client_alive_count_max: 3`, `sshd__log_level: 'INFO'`. Additionally configurable are `sshd__allow_tcp_forwarding` and `sshd__max_sessions`.
Expand All @@ -31,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

* **role:php**: PHP-FPM pools are now fully configurable, each with its own user/group, process-manager tuning, timeouts and `php_admin_value` overrides. Every pool gets its own isolated session directory (created automatically, with correct ownership and SELinux labeling on RedHat).
* **testing**: Add a Molecule-based test framework that runs the playbooks (and through them the roles) against throwaway libvirt/KVM VMs or Podman containers. Scenarios live under `extensions/molecule`; see the Testing section in `CONTRIBUTING.md`.
* **role:icinga2_master, role:icingadb, role:icingaweb2, role:icingaweb2_module_reporting, role:icingaweb2_module_x509**: Add explicit Ubuntu variable files, making Ubuntu support visible alongside Debian. The Icinga repository, GPG key and package names were verified on Debian 13 and Ubuntu 24.04.
* **role:nextcloud**: Add `meta/argument_specs.yml` declaring the user-facing variables, so role-entry validation catches type mismatches and missing mandatory variables.
Expand Down
2 changes: 2 additions & 0 deletions extensions/molecule/php/install/converge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- name: 'Converge php playbook'
ansible.builtin.import_playbook: 'linuxfabrik.lfops.php'
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Variables the php playbook needs, applied to every system under test.

# RedHat only: repo_remi enables the php and composer module streams only when a
# version is set. Without it the composer package is filtered out by dnf
# modularity and the install fails. Debian's repo_sury needs no version. The php
# role itself autodetects whichever version ends up installed.
repo_remi__enabled_php_version: '8.3'

# Debian only: repo_sury activates a package repo only for the repos listed here.
repo_sury__enabled_repos:
- 'php'

# Add a second pool with non-default values through the __group_var injection
# slot, so the role's combine_lod merges it over the default 'www' pool. The two
# differing pools let verify.yml prove each running pool uses its own config
# (isolation), not just that a pool exists. 'www' stays at the role defaults
# (pm dynamic, memory_limit 128M).
php__fpm_pools__group_var:
- name: 'app1'
pm: 'static'
pm_max_children: 4
php_admin_value_memory_limit: '256M'
state: 'present'
20 changes: 20 additions & 0 deletions extensions/molecule/php/install/inventory/hosts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# yamllint disable rule:empty-values

# Put the systems under test into the group the playbook targets. The php
# playbook runs against 'lfops_php' (see playbooks/php.yml: hosts).
lfops_php:
children:
systems_under_test:

# 'systems_under_test' holds the actual hosts. Trim this (or use
# LFOPS_TEST_TARGETS at runtime) to test against fewer hosts.
systems_under_test:
hosts:
debian12-vm:
debian13-vm:
rocky8-vm:
rocky9-vm:
rocky10-vm:
ubuntu2204-vm:
ubuntu2404-vm:
ubuntu2604-vm:
1 change: 1 addition & 0 deletions extensions/molecule/php/install/molecule.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Molecule scenario marker
255 changes: 255 additions & 0 deletions extensions/molecule/php/install/verify.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
# verify.yml runs after converge and again after the idempotence step. It checks
# the observable end result, never by re-running the role. The guiding question
# is "what can only be confirmed by looking at the running system?".
#
# The headline check here is the PR's core promise: a pool's
# php_admin_value[memory_limit] is enforced by the running workers and cannot be
# raised with ini_set(). We prove it by speaking FastCGI to each pool's unix
# socket and asking the running PHP what its effective config is, rather than
# grepping the rendered pool file.
#
# We talk FastCGI with a tiny stdlib-only Python client instead of cgi-fcgi: the
# fcgi / libfcgi-bin package is not available across the whole OS matrix (no EPEL
# is enabled by the php playbook, and EPEL 10 does not ship it), whereas python3
# is always present on a managed node.
- name: 'Verify the php-fpm pools are configured and enforced at runtime'
hosts: 'systems_under_test'
gather_facts: true
become: true
tasks:

# The role's __php__ internals are not visible here, so recompute the few
# OS-specific names/paths we need from ansible_facts (mirrors the role).
- name: 'Gather the package facts'
ansible.builtin.package_facts: # yamllint disable-line rule:empty-values

- name: 'Set OS-specific php-fpm facts'
ansible.builtin.set_fact:
__molecule__php_version: '{{ ansible_facts["packages"]["php"][0]["version"] | regex_search("\d\.\d") }}'
__molecule__php_runtime_path: '{{ "/run/php-fpm" if ansible_facts["os_family"] == "RedHat" else "/run/php" }}'

- name: 'Set the php-fpm service name'
ansible.builtin.set_fact:
__molecule__php_service: '{{ "php-fpm" if ansible_facts["os_family"] == "RedHat" else "php" ~ __molecule__php_version ~ "-fpm" }}'

# Floor check: did the install happen at all? On its own this would pass even
# if the service never starts, so it is the start, not the goal.
- name: 'Assert the php packages are installed'
ansible.builtin.assert:
that:
- '"composer" in ansible_facts["packages"]'
- '"php" in ansible_facts["packages"]'
- '"php-fpm" in ansible_facts["packages"]'

# Real check: is the service up and enabled? A pool config that deployed
# without error but crashes php-fpm on start is only caught here. This also
# guards the Debian log-dir regression (missing dir -> php-fpm fails to
# start).
- name: 'Gather the service facts'
ansible.builtin.service_facts: # yamllint disable-line rule:empty-values

- name: 'Assert php-fpm is running and enabled'
ansible.builtin.assert:
that:
- 'ansible_facts["services"][__molecule__php_service ~ ".service"]["state"] == "running"'
- 'ansible_facts["services"][__molecule__php_service ~ ".service"]["status"] == "enabled"'

# Place the probe under /var/www/html so the php-fpm worker can read it: it
# survives the service's PrivateTmp (which namespaces /tmp away from the
# worker) and, after restorecon, carries the httpd_sys_content_t SELinux type
# the worker is allowed to read on RedHat.
- name: 'Create the probe directory'
ansible.builtin.file:
path: '/var/www/html/molecule-php'
state: 'directory'
owner: 'root'
group: 'root'
mode: 0o755

# One probe per pool, on its own path. opcache SHM is shared across all pools
# of a single FPM master, so if both pools requested the same script path the
# first pool to compile it would serve its cached copy (and its
# php_admin_value-affected runtime values) to the other within
# revalidate_freq. A distinct path per pool keeps each probe isolated.
- name: 'Deploy a per-pool php probe script'
ansible.builtin.copy:
dest: '/var/www/html/molecule-php/probe-{{ item }}.php'
owner: 'root'
group: 'root'
mode: 0o644
content: |
<?php
echo 'memory_limit=' . ini_get('memory_limit') . "\n";
// php_admin_value must block this raise; the value has to stay put.
@ini_set('memory_limit', '1024M');
echo 'memory_limit_after=' . ini_get('memory_limit') . "\n";
echo 'session_save_path=' . ini_get('session.save_path') . "\n";
loop:
- 'app1'
- 'www'

- name: 'restorecon -Rv /var/www/html/molecule-php'
ansible.builtin.command: 'restorecon -Rv /var/www/html/molecule-php'
changed_when: false
when:
- 'ansible_facts["os_family"] == "RedHat"'
- 'ansible_facts["selinux"]["status"] != "disabled"'

# Minimal FastCGI client: connects to a pool's unix socket, sends one GET
# request with the given SCRIPT_NAME / SCRIPT_FILENAME and prints the
# response body. Stdlib only, so no package install is needed.
- name: 'Deploy the FastCGI probe client'
ansible.builtin.copy:
dest: '/usr/local/sbin/molecule-fcgi-request.py'
owner: 'root'
group: 'root'
mode: 0o755
content: |
#!/usr/bin/env python3
import socket
import struct
import sys

FCGI_VERSION = 1
FCGI_BEGIN_REQUEST = 1
FCGI_END_REQUEST = 3
FCGI_PARAMS = 4
FCGI_STDIN = 5
FCGI_STDOUT = 6
FCGI_STDERR = 7
FCGI_RESPONDER = 1
REQ_ID = 1

sock_path, script_name, script_filename = sys.argv[1], sys.argv[2], sys.argv[3]

def enc_len(n):
if n < 128:
return struct.pack('!B', n)
return struct.pack('!I', n | 0x80000000)

def encode_pair(name, value):
nb, vb = name.encode(), value.encode()
return enc_len(len(nb)) + enc_len(len(vb)) + nb + vb

def record(rtype, content):
return struct.pack('!BBHHBx', FCGI_VERSION, rtype, REQ_ID, len(content), 0) + content

params = {
'DOCUMENT_ROOT': '/var/www/html',
'GATEWAY_INTERFACE': 'CGI/1.1',
'QUERY_STRING': '',
'REQUEST_METHOD': 'GET',
'REQUEST_URI': script_name,
'SCRIPT_FILENAME': script_filename,
'SCRIPT_NAME': script_name,
'SERVER_PROTOCOL': 'HTTP/1.1',
}

data = record(FCGI_BEGIN_REQUEST, struct.pack('!HB5x', FCGI_RESPONDER, 0))
data += record(FCGI_PARAMS, b''.join(encode_pair(k, v) for k, v in params.items()))
data += record(FCGI_PARAMS, b'')
data += record(FCGI_STDIN, b'')

s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect(sock_path)
s.sendall(data)

out, err = b'', b''
while True:
header = b''
while len(header) < 8:
chunk = s.recv(8 - len(header))
if not chunk:
break
header += chunk
if len(header) < 8:
break
_, rtype, _, clen, plen, _ = struct.unpack('!BBHHBB', header)
content = b''
while len(content) < clen:
chunk = s.recv(clen - len(content))
if not chunk:
break
content += chunk
if plen:
s.recv(plen)
if rtype == FCGI_STDOUT:
out += content
elif rtype == FCGI_STDERR:
err += content
elif rtype == FCGI_END_REQUEST:
break
s.close()
sys.stdout.write(out.decode('utf-8', 'replace'))
sys.stderr.write(err.decode('utf-8', 'replace'))

# pm mode reaches the running pool: the status page reports the live process
# manager, which differs per pool (www: dynamic default, app1: static
# override). This fails if the value never made it into the running pool.
- name: 'Query the www pool status over its socket'
ansible.builtin.command:
argv:
- '/usr/local/sbin/molecule-fcgi-request.py'
- '{{ __molecule__php_runtime_path }}/www.sock'
- '/www-fpm-status'
- '/www-fpm-status'
register: '__molecule__www_status_result'
changed_when: false

- name: 'Assert the www pool runs with pm dynamic'
ansible.builtin.assert:
that: '__molecule__www_status_result["stdout"] is search("process manager:\s+dynamic")'

- name: 'Query the app1 pool status over its socket'
ansible.builtin.command:
argv:
- '/usr/local/sbin/molecule-fcgi-request.py'
- '{{ __molecule__php_runtime_path }}/app1.sock'
- '/app1-fpm-status'
- '/app1-fpm-status'
register: '__molecule__app1_status_result'
changed_when: false

- name: 'Assert the app1 pool runs with pm static'
ansible.builtin.assert:
that: '__molecule__app1_status_result["stdout"] is search("process manager:\s+static")'

# The headline check: run the same probe through each socket and confirm the
# workers enforce their own php_admin_value. app1 must report 256M, the value
# must not budge after ini_set (php_admin_value, not php_value), and the
# session path must be the per-pool directory.
- name: 'Run the php probe through the app1 pool socket'
ansible.builtin.command:
argv:
- '/usr/local/sbin/molecule-fcgi-request.py'
- '{{ __molecule__php_runtime_path }}/app1.sock'
- '/molecule-php/probe-app1.php'
- '/var/www/html/molecule-php/probe-app1.php'
register: '__molecule__app1_probe_result'
changed_when: false

- name: 'Assert app1 enforces its own php_admin_value memory_limit and session path'
ansible.builtin.assert:
that:
- '"memory_limit=256M" in __molecule__app1_probe_result["stdout"]'
- '"memory_limit_after=256M" in __molecule__app1_probe_result["stdout"]'
- '__molecule__app1_probe_result["stdout"] is search("session_save_path=.*/app1")'
fail_msg: 'app1 probe returned: {{ __molecule__app1_probe_result["stdout"] }}'

# Same script, different pool: www must report the role-default 128M. This is
# the isolation proof - one shared script, a different effective config per
# pool.
- name: 'Run the php probe through the www pool socket'
ansible.builtin.command:
argv:
- '/usr/local/sbin/molecule-fcgi-request.py'
- '{{ __molecule__php_runtime_path }}/www.sock'
- '/molecule-php/probe-www.php'
- '/var/www/html/molecule-php/probe-www.php'
register: '__molecule__www_probe_result'
changed_when: false

- name: 'Assert www uses the default memory_limit, proving pool isolation'
ansible.builtin.assert:
that: '"memory_limit=128M" in __molecule__www_probe_result["stdout"]'
fail_msg: 'www probe returned: {{ __molecule__www_probe_result["stdout"] }}'
2 changes: 2 additions & 0 deletions extensions/molecule/php/remove/converge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- name: 'Converge php playbook'
ansible.builtin.import_playbook: 'linuxfabrik.lfops.php'
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# The remove scenario runs the same playbook but flips the app1 pool to
# state: 'absent', exercising the list-with-state removal path. The default
# 'www' pool is untouched and must keep running.
#
# In a real suite, run the install sub-scenario first to create app1, then this
# one to remove it.

# Same repo inputs as the install sub-scenario (see its group_vars for why these
# are needed). RedHat: enable the php/composer module streams. Debian: activate
# the sury php repo.
repo_remi__enabled_php_version: '8.3'
repo_sury__enabled_repos:
- 'php'

php__fpm_pools__group_var:
- name: 'app1'
state: 'absent'
18 changes: 18 additions & 0 deletions extensions/molecule/php/remove/inventory/hosts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# yamllint disable rule:empty-values

# Same host-to-group mapping as the install sub-scenario. Sub-scenarios do not
# share inventory with each other, so each repeats the hosts it runs against.
lfops_php:
children:
systems_under_test:

systems_under_test:
hosts:
debian12-vm:
debian13-vm:
rocky8-vm:
rocky9-vm:
rocky10-vm:
ubuntu2204-vm:
ubuntu2404-vm:
ubuntu2604-vm:
1 change: 1 addition & 0 deletions extensions/molecule/php/remove/molecule.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Molecule scenario marker
Loading