---
- name: "π Resolve the OpenProject web hosting node and container id"
ansible.builtin.include_tasks: "{{ lookup('path_absolute', 'roles/sys-svc-compose/tasks/utils/swarm/resolve_host_cid.yml') }}"
vars:
resolve_service_key: web
resolve_service_name: "{{ lookup('container_service', 'web-app-openproject', 'web') }}"
resolve_output_prefix: NEXTCLOUD_OPENPROJECT
resolve_compose_cid: "{{ NEXTCLOUD_OPENPROJECT_CONTAINER_ADDRESS }}"
resolve_converge_retries: 120
resolve_converge_delay: 5
- name: β³ Wait for the OpenProject web endpoint
wait_for:
host: "{{ DOCKER_REACH_HOST }}"
port: "{{ lookup('config', 'web-app-openproject', 'services.openproject.ports.local.http') }}"
delay: 5
timeout: "{{ lookup('timeout', 600) | int }}"
- name: π Ensure the Nextcloud OAuth2 client OpenProject signs in with
ansible.builtin.shell:
cmd: >-
{{ NEXTCLOUD_DOCKER_EXEC_INTERACTIVE }} php --
{{ NEXTCLOUD_DOCKER_WORK_DIRECTORY | quote }}
{{ NEXTCLOUD_OPENPROJECT_URL | quote }}
{{ NEXTCLOUD_OPENPROJECT_CLIENT_NAME | quote }}
{{ nextcloud_op_nc_client_current.stdout | trim | quote }}
stdin: "{{ lookup('file', 'php/addons/openproject/ensure_nc_client.php') }}"
register: nextcloud_op_ncclient_ensure
changed_when: (nextcloud_op_ncclient_ensure.stdout | nextcloud_oauth_client_state).changed
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: π Build the OpenProject provisioning input
set_fact:
nextcloud_op_ncclient: "{{ nextcloud_op_ncclient_ensure.stdout | nextcloud_oauth_client_state }}"
nextcloud_op_provision_input: |
PROVISION_INPUT = JSON.parse(<<~'INPUT')
{{ {
'nextcloud_host': NEXTCLOUD_URL,
'nextcloud_base_urls': NEXTCLOUD_NETWORK_BASE_URLS,
'storage_name': nextcloud_op_storage_name,
'nc_op_client_secret': nextcloud_op_client_secret_current.stdout | trim,
'rotate_op_secret': lookup('config', 'web-app-nextcloud', 'addons.integration_openproject.config.rotate_oauth_client') | bool,
'nc_oauth_client_id': (nextcloud_op_ncclient_ensure.stdout | nextcloud_oauth_client_state).client_id
if (nextcloud_op_ncclient_ensure.stdout | nextcloud_oauth_client_state).action == 'created' else '',
'nc_oauth_client_secret': (nextcloud_op_ncclient_ensure.stdout | nextcloud_oauth_client_state).client_secret
if (nextcloud_op_ncclient_ensure.stdout | nextcloud_oauth_client_state).action == 'created' else ''
} | to_json }}
INPUT
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: π Ensure the OpenProject storage, OAuth application and Nextcloud client
ansible.builtin.shell:
cmd: >- # nocheck: container-exec-resolver NEXTCLOUD_OPENPROJECT_LOCAL_CID resolved at delegate_to runtime; container_address would return a manager-only subshell
container exec -i
{{ NEXTCLOUD_OPENPROJECT_LOCAL_CID | quote }}
bash -lc 'cd /app && bundle exec rails runner -'
stdin: "{{ 'require \"json\"\n' ~ nextcloud_op_provision_input ~ lookup('file', 'ruby/utils/doorkeeper_allow_onion_redirect.rb') ~ '\n' ~ lookup('file', 'ruby/addons/openproject/ensure_nextcloud_storage.rb')
}}"
delegate_to: "{{ NEXTCLOUD_OPENPROJECT_HOST_NODE }}"
register: nextcloud_op_storage_create
changed_when: >-
'"oauth_application_secret_issued":true' in nextcloud_op_storage_create.stdout
or nextcloud_op_ncclient.action == 'created'
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: β¬οΈ Push a newly created Nextcloud OAuth2 client into integration_openproject
shell: >
{{ NEXTCLOUD_DOCKER_EXEC_OCC }} config:app:set integration_openproject nc_oauth_client_id
--value={{ nextcloud_op_ncclient.id | string | quote }}
when: nextcloud_op_ncclient.action == 'created'
changed_when: true
- name: π Parse the OpenProject OAuth application credentials
set_fact:
nextcloud_op_oauth: "{{ nextcloud_op_storage_create.stdout | regex_search('{.*}') | from_json }}"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: π Resolve the effective OpenProject OAuth client secret (fresh or persisted)
set_fact:
nextcloud_op_client_secret: >-
{{ nextcloud_op_oauth.openproject_client_secret
| default((nextcloud_op_client_secret_current.stdout | trim), true) }}
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: π Fail when no usable OpenProject OAuth application secret is available
assert:
that:
- nextcloud_op_oauth.openproject_client_id | default('') | length > 0
- (nextcloud_op_client_secret | default('') | trim) | length > 0
fail_msg: >-
OpenProject did not return a usable OAuth application and no client secret is persisted in
Nextcloud. Set addons.integration_openproject.config.rotate_oauth_client to true for one
deploy to issue a new secret.
- name: β¬οΈ Push the OpenProject OAuth application credentials into Nextcloud
ansible.builtin.shell:
cmd: "{{ NEXTCLOUD_DOCKER_EXEC_INTERACTIVE }} sh -s"
stdin: |
set -eu
{{ NEXTCLOUD_INTERNAL_OCC_COMMAND | quote }} config:app:set integration_openproject authorization_method --value=oauth2
{{ NEXTCLOUD_INTERNAL_OCC_COMMAND | quote }} config:app:set integration_openproject openproject_client_id --value={{ nextcloud_op_oauth.openproject_client_id | quote }}
{{ NEXTCLOUD_INTERNAL_OCC_COMMAND | quote }} config:app:set integration_openproject openproject_client_secret --value={{ nextcloud_op_client_secret | quote }}
when: >-
nextcloud_op_oauth.oauth_application_secret_issued
or (nextcloud_op_client_id_current.stdout | trim) != nextcloud_op_oauth.openproject_client_id
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"