04_extensions.ymlΒΆ

---
# Installs OIDC / LDAP using a temporary Groovy page that calls the
# Extension Script Service (services.extension.install).
# Avoids REST job API and any Namespace class import for portability.
#
# Notes:
#  - We print machine-readable markers so Ansible can assert deterministically.

- name: "πŸ”¨ XWIKI | Build Groovy installer code from static file (base64 payload)"
  vars:
    _wanted_b64: "{{ XWIKI_PLUGINS | to_json | b64encode }}"
  set_fact:
    _install_code: >-
      {{ lookup('file', 'roles/web-app-xwiki/files/extension_installer_b64.groovy')
         | regex_replace('__WANTED_B64__', _wanted_b64) }}

- name: "⬇️ XWIKI | Fetch REST session + form token (extensions write ops)"
  include_tasks: utils/rest_session.yml

- name: "⬆️ XWIKI | PUT installer page Main.InstallExtensions"
  uri_retry:
    url: "{{ [XWIKI_REST_XWIKI_PAGES, 'InstallExtensions'] | url_join }}"
    method: PUT
    url_username: "{{ XWIKI_SUPERADMIN_USERNAME }}"
    url_password: "{{ XWIKI_SUPERADMIN_PASSWORD }}"
    force_basic_auth: true
    status_code: [200, 201, 202, 204]
    headers: "{{ xwiki_rest_headers_write }}"
    body: "{{ lookup('template', 'xml/install_extensions_page.xml.j2') }}"
  register: _put_page

- block:
    - name: "πŸ“‚ XWIKI | Load installer-page execution + assertion routines"
      include_tasks: 04_extensions/extensions_execute.yml

  rescue:
    - name: "🌿 XWiki | Probe extension repos + dump xwiki.properties" # nocheck: rescue-extra-diagnostics extension-repo reachability and xwiki.properties are xwiki-specific and not in any log the generic rescue script captures
      ansible.builtin.script: "{{ lookup('path_absolute', 'roles/web-app-xwiki/files/shell/rescue_extensions.sh') }}"
      environment:
        XWIKI_CONTAINER_ADDRESS: "{{ XWIKI_CONTAINER_ADDRESS }}"
      changed_when: false
      failed_when: false
    - name: "πŸ›‘ XWiki | fail after extension diagnostics"
      ansible.builtin.fail:
        msg: "Extension install failed; repo reachability + xwiki.properties were dumped into the diagnostics folder (the workflow-level rescue capture collects the
          full snapshot)"

  always:
    - name: "πŸ—‘οΈ XWIKI | Delete installer page (best effort)"
      uri_retry:
        url: "{{ [XWIKI_REST_XWIKI_PAGES, 'InstallExtensions'] | url_join }}"
        method: DELETE
        url_username: "{{ XWIKI_SUPERADMIN_USERNAME }}"
        url_password: "{{ XWIKI_SUPERADMIN_PASSWORD }}"
        force_basic_auth: true
        status_code: [204, 200, 202, 404]
        headers: "{{ xwiki_rest_headers_write | default({}) }}"
      register: _delete_page_best_effort
      changed_when: _delete_page_best_effort.status != 404
      failed_when: false

- name: "βœ… XWIKI | Verify requested extensions via Groovy checker"
  include_tasks: _check_extension_via_groovy.yml
  loop: "{{ XWIKI_PLUGINS }}"
  loop_control:
    loop_var: plugin
    label: "{{ plugin.id }}"
  vars:
    ext_id: "{{ plugin.id }}"
    ext_version: "{{ plugin.version }}"
    result_var: "probe_{{ plugin.id | regex_replace('[^A-Za-z0-9_]', '_') }}"

- name: "πŸ“Š XWIKI | Collect probe results"
  set_fact:
    _xwiki_probe_results: "{{ _xwiki_probe_results | default([]) + [ { 'id': plugin.id, 'status': ( (hostvars[inventory_hostname]['probe_' ~ (plugin.id | regex_replace('[^A-Za-z0-9_]',
      '_'))] | default({})).status | default(404) | int ) } ] }}"
  loop: "{{ XWIKI_PLUGINS }}"
  loop_control:
    loop_var: plugin
  changed_when: false

- name: "βœ… XWIKI | Assert all requested extensions are on their pinned version"
  vars:
    missing: "{{ (_xwiki_probe_results | default([])) | selectattr('status','equalto',404) | map(attribute='id') | list }}"
  fail:
    msg: "Extensions missing or not on their pinned version: {{ missing | join(', ') }}"
  when: missing | length > 0

- name: "πŸ—‘οΈ XWIKI | Delete installer page"
  uri_retry:
    url: "{{ [XWIKI_REST_XWIKI_PAGES, 'InstallExtensions'] | url_join }}"
    method: DELETE
    url_username: "{{ XWIKI_SUPERADMIN_USERNAME }}"
    url_password: "{{ XWIKI_SUPERADMIN_PASSWORD }}"
    force_basic_auth: true
    status_code: [204, 200, 202, 404]
    headers: "{{ xwiki_rest_headers_write }}"
  register: _delete_page
  changed_when: _delete_page.status != 404