Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable deployment of engine and federation-api on a single server #41

Merged
merged 49 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
86f77fc
Flatten roles structure
Ndpnt May 6, 2024
fb35d57
Extract `github` role
Ndpnt May 6, 2024
ef2cd8c
Create pm2 role
Ndpnt May 6, 2024
dd73717
Rewrite Nginx role
Ndpnt May 6, 2024
4ada481
Rewrite how OTA applications are deployed
Ndpnt May 6, 2024
aabe4d5
Update tests
Ndpnt May 6, 2024
1d0c9c5
Expose VM remote port 80 to host 8080 to test APIs
Ndpnt May 6, 2024
602986b
Rename ota/applications in ota/apps
Ndpnt May 15, 2024
211eccb
Remove obsolete file
Ndpnt May 15, 2024
e6d1e06
Improve variable name
Ndpnt May 15, 2024
7bc6266
Rename federated-api in federation-api
Ndpnt May 15, 2024
a92374a
Ensure ota apps variables are available to the play
Ndpnt May 15, 2024
0b3f291
Remove obsolete code
Ndpnt May 15, 2024
398d620
Name the VM
Ndpnt May 15, 2024
a0bd647
Avoid to specify to ansible the python interpreter
Ndpnt May 15, 2024
a417c67
Update test inventory
Ndpnt May 15, 2024
a69744b
Improve variables naming
Ndpnt May 20, 2024
a136773
Fix .env file existence check on local machine
Ndpnt May 20, 2024
60a1695
Add Github private file existence check on local machine
Ndpnt May 20, 2024
13511cf
Make pm2 config file required next to the inventory
Ndpnt May 20, 2024
0601316
Ensure `delegate_to` works with Vagrant
Ndpnt May 20, 2024
d6701ab
Update README
Ndpnt May 20, 2024
ceb81be
Add changelog entry
Ndpnt May 20, 2024
c360ddd
Improve copywriting
Ndpnt May 22, 2024
2d215fe
Fix application name
Ndpnt May 22, 2024
79ecd59
Display all variables in example
Ndpnt May 22, 2024
71cba8a
Remove useless READMEs
Ndpnt May 22, 2024
55b23b0
Lint
Ndpnt May 22, 2024
b6f623c
Improve wording
Ndpnt May 29, 2024
ad5a05e
Improve documentation
Ndpnt May 29, 2024
f857f5c
Improve roles structure
Ndpnt May 29, 2024
e8eb61d
Use long option name
Ndpnt May 29, 2024
975d50a
Improve mongo role structure
Ndpnt May 29, 2024
54b60b4
Make block more readable
Ndpnt May 29, 2024
5b1fafe
Improve deploy playbook
Ndpnt May 29, 2024
a23df23
Rename role
Ndpnt May 29, 2024
37568e7
Remove obsolete condition
Ndpnt May 29, 2024
36604f6
Update test pm2 config
Ndpnt May 29, 2024
ee875e0
Fix deploy playbook
Ndpnt May 29, 2024
faab2b7
Factorize condition
Ndpnt May 29, 2024
118622a
Group entries in changelog
Ndpnt May 29, 2024
08592ec
Update Readme
Ndpnt May 29, 2024
afccdf0
Avoid regex
Ndpnt May 29, 2024
cf20df2
Fix variable definition
Ndpnt May 29, 2024
6d80206
Improve git based database role
Ndpnt May 29, 2024
407b470
Use ota_apps_config variables only in the playbook
Ndpnt May 29, 2024
634498f
Improve restart delays
Ndpnt May 31, 2024
a13f2d5
Minor README improvements
Ndpnt May 31, 2024
c3200a0
Remove obsolete test config
Ndpnt May 31, 2024
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
27 changes: 26 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,32 @@

All changes that impact users of this module are documented in this file, in the [Common Changelog](https://common-changelog.org) format with some additional specifications defined in the CONTRIBUTING file. This codebase adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased
## Unreleased [major]

_Full changeset and discussions: [#41](https://github.com/OpenTermsArchive/deployment/pull/41)._

> Development of this release was supported by the [French Ministry for Foreign Affairs](https://www.diplomatie.gouv.fr/fr/politique-etrangere-de-la-france/diplomatie-numerique/) through its ministerial [State Startups incubator](https://beta.gouv.fr/startups/open-terms-archive.html) under the aegis of the Ambassador for Digital Affairs.

### Changed

- **Breaking:** Replace all playbooks with a single `deploy` playbook; update your scripts by using `ansible-playbook opentermsarchive.deployment.deploy` and use [tags to refine execution](./README.md#refining-playbook-execution)
- **Breaking:** Change the `federation-api` deployment process to be a dependency of the source repository
- **Breaking:** Require `engine>=2` and `federation-api>=v2`
- **Breaking:** Make `ota_source_repository` variable mandatory
- **Breaking:** Define environment variables in a `.env` file instead of in inventory variables; move `ota_engine_github_token`, `ota_engine_smtp_password`, `ota_engine_sendinblue_api_key`, and `ota_federated_api_smtp_password` to a `.env` file placed next to the inventory file and rename them according to the new naming conventions in `engine` v2 and `federation-api` v2
- **Breaking:** Rename `ota_engine_declarations_branch` to `ota_source_repository_branch`
- **Breaking:** Rename `ota_engine_declarations_directory` to `ota_directory`
- **Breaking:** Extract the PM2 config file `pm2.config.cjs`; provide this file next to the inventory file
- **Breaking:** Remove the `ota_engine_restart_delay` variable; define this setting directly in the `pm2.config.cjs`
- **Breaking:** Remove the `ota_engine_github_bot_private_key` variable in favor of the `github-bot-private-key` file; define the GitHub SSH private key in the `github-bot-private-key`

### Removed

- **Breaking:** Remove `ota_reverse_proxy_federated_api_path` config; define this path in your `config/production.json` under the key `@opentermsarchive/federation-api: { basePath: "" }`
- **Breaking:** Remove `ota_reverse_proxy_engine_path` config; define this path in your `config/production.json` under the key `@opentermsarchive/engine: { collection-api: { basePath: "" } }`
- **Breaking:** Remove obsolete `ota_engine_config_path`, `ota_federated_api_branch`, `ota_federated_api_directory`, and `ota_federated_api_repo` configs
- **Breaking:** Remove obsolete `update-declarations` tag


## 1.2.1 - 2024-05-22

Expand Down
225 changes: 78 additions & 147 deletions README.md

Large diffs are not rendered by default.

108 changes: 108 additions & 0 deletions playbooks/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
- name: Deploy Open Terms Archive applications
hosts: all
tasks:
- name: Load OTA applications configs
ansible.builtin.include_role:
name: ota/apps
public: true # ensure that the role's variables and defaults are accessible to the play
vars:
ota_apps_read_config_only: true

- name: Set required variables
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extracting this into a dedicated role would make deploy even more readable 🙂

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, I prefer to have a top down approach for global variables

set_fact:
chromium_required: "{{ ota_apps_config['@opentermsarchive/engine'] is defined }}"
# Skip Debian 11 with ARM architecture as it is not currently supported by MongoDB; see https://www.mongodb.com/docs/manual/installation/#supported-platforms
mongo_required:
"{{
(ansible_distribution != 'Debian' or (ansible_distribution == 'Debian' and ansible_facts['architecture'] != 'aarch64'))
and (
(ota_apps_config['@opentermsarchive/engine'].recorder.versions.storage.type is defined and ota_apps_config['@opentermsarchive/engine'].recorder.versions.storage.type == 'mongo')
or
(ota_apps_config['@opentermsarchive/engine'].recorder.snapshots.storage.type is defined and ota_apps_config['@opentermsarchive/engine'].recorder.snapshots.storage.type == 'mongo')
) | bool
}}"

snapshots_repository: "{{ ota_apps_config['@opentermsarchive/engine'].recorder.snapshots.storage.git.repository is defined and ota_apps_config['@opentermsarchive/engine'].recorder.snapshots.storage.git.repository }}"
snapshots_path: "{{ ota_apps_config['@opentermsarchive/engine'].recorder.snapshots.storage.git.path is defined and ota_apps_config['@opentermsarchive/engine'].recorder.snapshots.storage.git.path }}"

versions_repository: "{{ ota_apps_config['@opentermsarchive/engine'].recorder.versions.storage.git.repository is defined and ota_apps_config['@opentermsarchive/engine'].recorder.versions.storage.git.repository }}"
versions_path: "{{ ota_apps_config['@opentermsarchive/engine'].recorder.versions.storage.git.path is defined and ota_apps_config['@opentermsarchive/engine'].recorder.versions.storage.git.path }}"

collection_api_basePath: "{{ ota_apps_config['@opentermsarchive/engine']['collection-api'].basePath is defined and ota_apps_config['@opentermsarchive/engine']['collection-api'].basePath }}"
collection_api_port: "{{ ota_apps_config['@opentermsarchive/engine']['collection-api'].port is defined and ota_apps_config['@opentermsarchive/engine']['collection-api'].port }}"

federation_api_basePath: "{{ ota_apps_config['@opentermsarchive/federation-api'].basePath is defined and ota_apps_config['@opentermsarchive/federation-api'].basePath }}"
federation_api_port: "{{ ota_apps_config['@opentermsarchive/federation-api'].port is defined and ota_apps_config['@opentermsarchive/federation-api'].port }}"

- name: Install infrastructure
become: true
tags: [infrastructure]
block:
- name: Install Node
ansible.builtin.include_role:
name: node

- name: Install PM2
ansible.builtin.include_role:
name: pm2/install

- name: Install Chromium
ansible.builtin.include_role:
name: chromium
when: chromium_required

- name: Install Nginx
ansible.builtin.include_role:
name: nginx/install

- name: Install Mongo
ansible.builtin.include_role:
name: mongo/install
when:
- mongo_required

- name: Configure Mongo
ansible.builtin.include_role:
name: mongo/configure
apply:
become: true
Comment on lines +68 to +69
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we apply the become here rather than become in the role itself? Is there a way in which mongo/configure can run without become?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to manage all become: true settings at the playbook level for the following reasons:

  • Centralization of privilege escalation in one place.
  • Setting become: true once at the playbook level simplifies the roles, avoiding repetitive configuration in each task.

However, this approach has some drawbacks:

  • It might escalate privileges for tasks that don't require it, but this it seems to me that it is not an issue in our case as each task in infrastructure need privileges.
  • It reduces the control over which specific tasks need privilege escalation. However, the way our roles are structured means this granularity is not necessary.

Another solution considered was using block in roles to wrap all tasks with a become: true instruction. However, similar to defining global variables, I believe it is clearer to specify where privilege escalation will occur at the entry point of the playbook.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing, thank you for these clear explanations!

when:
- mongo_required

- name: Setup Git-based versions database
ansible.builtin.include_role:
name: ota/git-database
vars:
ota_git_database_repository: "{{ versions_repository }}"
ota_git_database_directory: "{{ versions_path }}"
ota_git_database_branch: main
when:
- versions_repository and versions_path

- name: Setup Git-based snapshots database
ansible.builtin.include_role:
name: ota/git-database
vars:
ota_git_database_repository: "{{ snapshots_repository }}"
ota_git_database_directory: "{{ snapshots_path }}"
ota_git_database_branch: main
when:
- snapshots_repository and snapshots_path

- name: Setup OTA applications
ansible.builtin.include_role:
name: ota/apps

- name: Start OTA applications
ansible.builtin.include_role:
name: pm2/manage

- name: Configure NGINX
ansible.builtin.include_role:
name: nginx/configure
apply:
become: true
vars:
ota_nginx_config_template: ./templates/nginx.conf.j2
ota_nginx_reverse_proxy_config_template: ./templates/nginx-reverse-proxy-conf.j2
6 changes: 0 additions & 6 deletions playbooks/engine/all.yml

This file was deleted.

14 changes: 0 additions & 14 deletions playbooks/engine/application.yml

This file was deleted.

25 changes: 0 additions & 25 deletions playbooks/engine/infrastructure.yml

This file was deleted.

6 changes: 0 additions & 6 deletions playbooks/engine_and_federated_api/all.yml

This file was deleted.

43 changes: 0 additions & 43 deletions playbooks/engine_and_federated_api/application.yml

This file was deleted.

7 changes: 0 additions & 7 deletions playbooks/engine_and_federated_api/infrastructure.yml

This file was deleted.

6 changes: 0 additions & 6 deletions playbooks/federated_api/all.yml

This file was deleted.

6 changes: 0 additions & 6 deletions playbooks/federated_api/application.yml

This file was deleted.

8 changes: 0 additions & 8 deletions playbooks/federated_api/infrastructure.yml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,22 @@
server {
listen 80;
server_name {{ inventory_hostname }};

location {{ ota_reverse_proxy_engine_path }} {

{% if collection_api_basePath and collection_api_port %}
location {{ collection_api_basePath }} {
# Allowing for a `burst` of up to 5 requests beyond the specified rate limit. The `nodelay` parameter ensures that excessive requests beyond the burst limit are immediately rejected with a 429 error response instead of being queued. See https://www.nginx.com/blog/rate-limiting-nginx/.
limit_req zone=limited burst=5 nodelay;
rewrite ^{{ ota_reverse_proxy_engine_path }}/(.*)$ /$1 break;
proxy_pass http://localhost:{{ ota_engine_app_config.api.port }};
proxy_pass http://localhost:{{ collection_api_port }};
proxy_redirect off;
}
{% endif %}

location {{ ota_reverse_proxy_federated_api_path }} {
{% if federation_api_basePath and federation_api_port %}
location {{ federation_api_basePath }} {
# Allowing for a `burst` of up to 5 requests beyond the specified rate limit. The `nodelay` parameter ensures that excessive requests beyond the burst limit are immediately rejected with a 429 error response instead of being queued. See https://www.nginx.com/blog/rate-limiting-nginx/.
limit_req zone=limited burst=5 nodelay;
rewrite ^{{ ota_reverse_proxy_federated_api_path }}/(.*)$ /$1 break;
proxy_pass http://localhost:{{ ota_federated_api_app_config.port }};
proxy_pass http://localhost:{{ federation_api_port }};
proxy_redirect off;
}
{% endif %}
}
3 changes: 3 additions & 0 deletions roles/chromium/meta/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
dependencies:
- { role: common }
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
state: latest
when: ansible_distribution == 'Ubuntu'

# See https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#recommended-enable-user-namespace-cloning
# See https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#recommended-enable-user-namespace-cloning
- name: Enable user namespace cloning to allow running Chromium in a sandbox
ansible.builtin.command: sysctl -w kernel.unprivileged_userns_clone=1
when: ansible_facts['architecture'] != 'aarch64'
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
- zip
update_cache: true
state: latest
become: true
Ndpnt marked this conversation as resolved.
Show resolved Hide resolved
2 changes: 0 additions & 2 deletions roles/engine/README.md

This file was deleted.

5 changes: 0 additions & 5 deletions roles/engine/defaults/main.yml

This file was deleted.

6 changes: 0 additions & 6 deletions roles/engine/handlers/main.yml

This file was deleted.

40 changes: 0 additions & 40 deletions roles/engine/tasks/database.yml

This file was deleted.

Loading
Loading