Add OneLab Helm chart, Argo CD Application, and GitOps values for k3s

Made-with: Cursor
This commit is contained in:
timotheereausanofi
2026-03-20 10:15:15 +01:00
commit 52847814e0
102 changed files with 4476 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
---
- name: Checking if OneLab is running
shell: docker stack ls | grep 'onelab' | grep -v 'onelab_proxy' | wc -l
become: true
register: backup_stack_count
# Start DB if OneLab is not running
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/start-db-only.yml"
when: backup_stack_count.stdout == "0"
- name: Creating backup directory
file:
path: "{{ onelab_path }}/backups/{{ ansible_date_time.iso8601_basic_short }}_1.27.0"
state: directory
register: backup_path
- name: Backing up files
shell:
tar --exclude='temp' -czvf {{ backup_path.path }}/onelab.tar.gz -C {{ onelab_path }} ./data ./installation ./nginx ./proxy ./rabbit ./ssl ./backup.sh ./configurations.yml ./docker-compose.yml ./reconfigure.sh ./start.sh ./stop.sh ./update.sh
become: yes
- name: Backing up database
shell:
docker exec -i $(docker ps --filter "name=onelab_db|onelab-db" -q) pg_dump -Upostgres -Fc > {{ backup_path.path }}/db.tar.gz
become: yes
- name: Creating restore script files
copy:
src: "{{ onelab_path }}/installation/latest/resources/restore/{{ item }}"
dest: "{{ backup_path.path }}"
with_items:
- 'restore.yml'
- 'restore.sh'
# Stop DB if OneLab was not running
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/stop-db-only.yml"
when: backup_stack_count.stdout == "0"

View File

@@ -0,0 +1,7 @@
---
# Check if Docker images are existing locally
- name: Checking local Docker images bundle
stat:
path: "{{ main_path }}/onelab-images-1.27.0.tar.gz"
get_checksum: no
register: docker_images_tar

View File

@@ -0,0 +1,71 @@
---
- name: Checking internet connection
uri:
url: "https://hub.andrewalliance.com"
register: pingresult
until:
- pingresult.status == 200
retries: 3 # 3 * 5 seconds = 15s
delay: 5 # Every 5 seconds
when: (docker_images_tar is undefined) or (not docker_images_tar.stat.exists)
- name: Getting current logged-in user
shell: whoami
register: login_user
- debug: var=login_user.stdout
# User running the process may have to enter their sudo password at this step
- name: Checking if the logged-in user has sudo privileges
shell: sudo whoami
register: sudo_check
failed_when: sudo_check.stdout != "root"
- name: Checking Ansible
debug:
msg: "{{ item }}"
with_items:
- "{{ ansible_distribution }}"
- "{{ ansible_distribution_version }}"
- "{{ ansible_distribution_major_version }}"
- name: Checking Docker version
shell: docker -v | cut -d ' ' -f 3 | cut -d ',' -f 1
become: true
register: docker_version
- debug: var=docker_version.stdout
# workaround: add a dumb failed condition to avoid any failure here as the service is maybe not installed/existing
- name: Check if "docker compose" is available
shell: docker compose version
become: true
register: docker_compose_check
failed_when: "'FAILED' in docker_compose_check.stderr"
- name: Set the compose command to "docker compose"
set_fact:
compose_command: "docker compose"
when: docker_compose_check.rc == 0
- name: Fallback to "docker-compose" if "docker compose" is not available
set_fact:
compose_command: "docker-compose"
when: docker_compose_check.rc != 0
- name: Checking Docker Compose version
shell: "{{ compose_command }} version"
become: true
register: compose_version_output
- debug: var=compose_version_output.stdout
- name: Checking tar pacakge
shell: tar --usage
become: true
- name: Checking unzip pacakge
shell: unzip
become: true
- name: Checking openssl package
shell: openssl
become: true

View File

@@ -0,0 +1,49 @@
---
# Check SSL files
- name: Getting the list of Docker secrets
shell: docker secret ls | tail -n +2 | awk '{print $2}'
register: docker_secrets
become: true
- name: Checking if dhparam.pem file exists in /onelab/ssl
stat:
path: "{{ onelab_path }}/ssl/dhparam.pem"
register: dhparam
failed_when: not dhparam.stat.exists
- name: Checking if server.pem file exists in /onelab/ssl
stat:
path: "{{ onelab_path }}/ssl/server.pem"
register: serverpem
failed_when: not serverpem.stat.exists
- name: Checking if server.key file exists in /onelab/ssl
stat:
path: "{{ onelab_path }}/ssl/server.key"
register: serverkey
failed_when: not serverkey.stat.exists
- name: Checking if chain.pem file exists in /onelab/ssl
stat:
path: "{{ onelab_path }}/ssl/chain.pem"
register: chain
failed_when: not chain.stat.exists
- name: Checking if certificate and key are matching (part 1/2)
shell: >
openssl rsa -noout -modulus -in {{ onelab_path }}/ssl/server.key | openssl md5
register: serverkey_modulus
become: true
when:
- "'ssl_passphrase' not in docker_secrets.stdout_lines"
- (onelab.deployment.skip_ssl is undefined) or (onelab.deployment.skip_ssl == false)
- name: Checking if certificate and key are matching (part 2/2)
shell: >
openssl x509 -noout -modulus -in {{ onelab_path }}/ssl/server.pem | openssl md5
register: serverpem_modulus
failed_when: serverpem_modulus.stdout != serverkey_modulus.stdout
become: true
when:
- "'ssl_passphrase' not in docker_secrets.stdout_lines"
- (onelab.deployment.skip_ssl is undefined) or (onelab.deployment.skip_ssl == false)

View File

@@ -0,0 +1,21 @@
---
#
# Configure Docker
#
- name: Ensuring Docker status
service:
name: "docker"
state: started
- name: Determining Docker swarm status
shell: >
docker info | egrep 'Swarm: '
register: swarm_status
become: true
- name: Configuring Docker Swarm
shell: >
docker swarm init --advertise-addr "{{ ansible_default_ipv4.address }}"
when: "' Swarm: inactive' in swarm_status.stdout_lines"
become: true

View File

@@ -0,0 +1,119 @@
---
#
# Start Installation
#
# Folders creation
- name: Creating OneLab directory
file:
path: "{{ onelab_path }}"
state: directory
- name: Creating OneLab directory structure
file:
path: "{{ onelab_path }}/{{ item }}"
state: directory
with_items:
- 'backups'
- 'data'
- 'data/shared'
- 'data/shared/inputs'
- 'data/shared/archived'
- 'logs'
- 'installation'
- 'ssl'
- 'rabbit'
- name: Creating directory for rabbit SSL certificates
file:
path: "{{ onelab_path }}/rabbit/ssl"
state: directory
- name: Creating directory for Ansible logs
file:
path: "{{ onelab_path }}/logs/ansible"
state: directory
# Copy version
- name: Cleaning latest installation
ansible.builtin.file:
path: "{{ onelab_path }}/installation/latest"
state: absent
- name: Copying current installation bundle
ansible.builtin.copy:
src: "{{ installer_path }}/"
dest: "{{ onelab_path }}/installation/{{ item }}"
directory_mode: no
remote_src: yes
with_items:
- 'latest'
- '1.27.0'
# Copy files
- name: Copying applicative files
copy:
src: "{{ onelab_path }}/installation/latest/app/{{ item }}"
dest: "{{ onelab_path }}/"
directory_mode: yes
remote_src: yes
with_items:
- 'nginx'
- 'proxy'
- 'rabbit'
- name: Copying routine scripts
copy:
src: "{{ onelab_path }}/installation/latest/app/{{ item }}.sh"
dest: "{{ onelab_path }}/"
directory_mode: yes
remote_src: yes
with_items:
- 'start'
- 'stop'
- 'reconfigure'
- 'backup'
- 'update'
- name: Initializing custom config proxy files
file:
path: "{{ onelab_path }}/proxy/{{ item }}"
state: touch
with_items:
- 'custom-http.conf'
- 'custom-server.conf'
when: not is_update
# Initialize configurations.yml file
- name: Initializing configurations.yml file
copy:
src: "{{ onelab_path }}/installation/latest/app/configurations.yml"
dest: "{{ onelab_path }}/configurations.yml"
remote_src: yes
when: not is_update
- name: Initializing unique Password and Tokens
ansible.builtin.replace:
path: "{{ onelab_path }}/configurations.yml"
regexp: '{{ item.placeholder }}'
replace: '{{ item.value }}'
with_items:
- { placeholder: DBPasswordPlaceholder, value: '{{ lookup("password", "/dev/null length=16 chars=ascii_letters,digits") }}' }
- { placeholder: TokenAuthPlaceholder, value: '{{ lookup("password", "/dev/null length=32 chars=ascii_letters,digits") }}' }
- { placeholder: TokenRabbitPlaceholder, value: '{{ lookup("password", "/dev/null length=32 chars=ascii_letters,digits") }}' }
- { placeholder: TokenMonitoringPlaceholder, value: '{{ lookup("password", "/dev/null length=32 chars=ascii_letters,digits") }}' }
when: not is_update
- name: Initializing Rabbit SSL certificate
shell: |
openssl req -x509 -nodes -days 7300 -newkey rsa:2048 -keyout {{ onelab_path }}/rabbit/ssl/rabbit.key -out {{ onelab_path }}/rabbit/ssl/rabbit.crt -subj "/C=CH/ST=Geneva/L=Geneva/O=Andrew Alliance/OU=OneLab/CN=andrewalliance.com"
cat {{ onelab_path }}/rabbit/ssl/rabbit.crt > {{ onelab_path }}/rabbit/ssl/rabbit.fullchain.pem
become: true
when: not is_update
- name: Initializing DH Param
shell: |
openssl dhparam -out {{ onelab_path }}/ssl/dhparam.pem 2048
become: true
when: not is_update

View File

@@ -0,0 +1,33 @@
---
#
# Create onelab.service
#
- name: Check ansible-playbook bin
shell: whereis ansible-playbook | cut -d ' ' -f 2
register: ansiblebin_result
become: true
# workaround: add a dumb failed condition to avoid any failure here as the service is maybe not installed/existing
- name: Check onelab.service
shell: |
systemctl disable onelab.service
rm /etc/systemd/system/onelab.service
register: command_result
failed_when: "'FAILED' in command_result.stderr"
become: true
# playbook_dir will be /home/ubuntu/onelab/test/onelab-enterprise-installer-release-1.13.0/app/playbooks for install.sh
# but will be /home/ubuntu/onelab/test/onelab/installation/latest/app/playbooks/ for update.sh
- debug: var=playbook_dir
- name: Creating onelab.service
ansible.builtin.template:
src: "{{ installer_path }}/resources/services/onelab.service"
dest: "/etc/systemd/system/onelab.service"
become: true
- name: Configuring onelab.service
shell: |
systemctl daemon-reload
systemctl enable onelab.service
become: true

View File

@@ -0,0 +1,81 @@
---
#
# Offline-resources-check
#
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/check-offline-resources.yml"
#
# Pre-check
#
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/check-requirements.yml"
#
# Configure Docker
#
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/init-docker.yml"
- name: Loading Docker images
debug:
msg:
- "Loading images could take few minutes, please do not interrupt"
when: (docker_images_tar is defined) and (docker_images_tar.stat.exists)
- name: Loading OneLab images from the tar file
shell:
docker load --input {{ main_path }}/onelab-images-1.27.0.tar.gz
become: true
when: (docker_images_tar is defined) and (docker_images_tar.stat.exists)
#
# Check if we are running a fresh installation or an update on an existing installation
#
- name: Checking if OneLab is already installed
stat:
path: "{{ onelab_path }}/docker-compose.yml"
register: onelab_result
#
# Pre-migration task
#
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/pre-update.yml"
when: onelab_result.stat.exists
#
# Install OneLab
#
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/init-onelab.yml"
vars:
is_update: "{{ onelab_result.stat.exists|bool }}"
#
# Init Service
#
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/init-service.yml"
# Checking Docker volumes
- name: Checking if RabbitMQ exists
shell: docker volume ls
become: true
register: list_volumes
# Cleaning cache
- name: Cleaning RabbitMQ cache
shell: docker volume rm onelab_rabbitmq_data
become: true
when: "'onelab_rabbitmq_data' in list_volumes.stdout"
#
# Reconfigure
#
- include_vars:
file: "{{ onelab_path }}/configurations.yml"
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/update-conf-files.yml"
#
# Post-migration task
#
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/post-update.yml"
when: onelab_result.stat.exists

View File

@@ -0,0 +1,40 @@
- name: Connecting to Docker Hub
shell: >
docker login -u {{ onelab.docker.login.user|default('public') }} -p {{ onelab.docker.login.password|default('Andrew01..Release') }} hub.andrewalliance.com
become: true
when: (docker_images_tar is undefined) or (not docker_images_tar.stat.exists)
- name: Checking current OneLab images
shell: >
{% raw %}
docker image ls --format '{{.ID}} {{.Repository}}:{{.Tag}}' |
egrep 'onelab-' |
egrep -v '1.27.0' |
awk '{ print $1 }'
{% endraw %}
register: onelab_old_images
become: true
- name: Pruning OneLab old images
shell:
docker rmi {{ item }}
become: true
loop: "{{ onelab_old_images.stdout_lines }}"
- name: Gathering OneLab images
shell: >
cat {{ onelab_path }}/docker-compose.yml | egrep 'image: ' | awk '{ print $2 }'
register: onelab_images
become: true
when: (docker_images_tar is undefined) or (not docker_images_tar.stat.exists)
- name: Pulling OneLab images
shell: >
docker image pull {{ item }}
become: true
register: pullimages
loop: "{{ onelab_images.stdout_lines }}"
until: pullimages is not failed
retries: 10
delay: 5
when: (docker_images_tar is undefined) or (not docker_images_tar.stat.exists)

View File

@@ -0,0 +1,28 @@
---
- name: Pull new postgres image
shell: |
docker image pull hub.andrewalliance.com/releases/postgres:17.8
become: true
when: (docker_images_tar is undefined) or (not docker_images_tar.stat.exists)
- name: Cleaning database
shell: >
docker volume rm onelab_pgdata
become: true
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/start-db-only.yml"
- name: Restoring & Migrating database
shell: |
docker exec -i $(docker ps --filter "name=onelab_db|onelab-db" -q) pg_restore -Upostgres -dpostgres -v -Fc < {{ onelab_path }}/db-migration-postgres.tar.gz
rm {{ onelab_path }}/db-migration-postgres.tar.gz
become: true
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/stop-db-only.yml"
- name: Removing lock file
shell: >
rm {{ onelab_path }}/.lock_db_migration
become: true

View File

@@ -0,0 +1,21 @@
---
#
# Specfic update tasks for version
#
#
# Migrate SSL structure (1.12.0 -> 1.13.0)
#
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/ssl-cert-migration.yml"
#
# Postgres13 post-migration
#
- name: Checking if database has to be migrated
stat:
path: "{{ onelab_path }}/.lock_db_migration"
register: onelab_lock_db_result
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/post-db-migration.yml"
when: onelab_lock_db_result.stat.exists

View File

@@ -0,0 +1,14 @@
---
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/start-db-only.yml"
- name: Backing up database
shell:
docker exec -i $(docker ps --filter "name=onelab_db|onelab-db" -q) pg_dump -Upostgres -Fc > {{ onelab_path }}/db-migration-postgres.tar.gz
become: yes
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/stop-db-only.yml"
- name: Creating lock file
shell: >
touch {{ onelab_path }}/.lock_db_migration
become: true

View File

@@ -0,0 +1,12 @@
---
- name: Checking current database
shell: >
cat {{ onelab_path }}/docker-compose.yml | egrep 'image: postgres' | awk '{ print $2 }'
register: onelab_db
become: true
#
# Postgres pre-migration
#
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/pre-db-migration.yml"
when: onelab_db.stdout != 'hub.andrewalliance.com/releases/postgres:17.8'

View File

@@ -0,0 +1,17 @@
---
# Evaluate Docker images bundle
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/check-offline-resources.yml"
when: (policy | default('')) != "no-pull" and (onelab.docker.policy | default('')) != "no-pull"
# Update conf files
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/update-conf-files.yml"
# Check SSL files
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/check-ssl-files.yml"
# Rotate Rabbit SSL files
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/rotate-ssl-files-for-rabbit.yml"
# Connect to Docker and pull images, and clean up old images
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/manage-images.yml"
when: (policy | default('')) != "no-pull" and (onelab.docker.policy | default('')) != "no-pull"

View File

@@ -0,0 +1,8 @@
---
# Check SSL files
- name: Rotate Rabbit SSL certificate
shell: |
openssl req -x509 -nodes -days 7300 -newkey rsa:2048 -keyout {{ onelab_path }}/rabbit/ssl/rabbit.key -out {{ onelab_path }}/rabbit/ssl/rabbit.crt -subj "/C=CH/ST=Geneva/L=Geneva/O=Andrew Alliance/OU=OneLab/CN=andrewalliance.com"
cat {{ onelab_path }}/rabbit/ssl/rabbit.crt > {{ onelab_path }}/rabbit/ssl/rabbit.fullchain.pem
become: true

View File

@@ -0,0 +1,18 @@
---
- name: Checking if fullchain.pem file exists in /onelab/ssl
stat:
path: "{{ onelab_path }}/ssl/fullchain.pem"
register: fullchain
- name: Migrating legacy SSL structure to the new one
shell: |
cp {{ onelab_path }}/ssl/fullchain.pem {{ onelab_path }}/ssl/server.pem
cp {{ onelab_path }}/ssl/fullchain.pem {{ onelab_path }}/ssl/chain.pem
rm {{ onelab_path }}/ssl/server.crt
rm {{ onelab_path }}/ssl/fullchain.pem
when: fullchain.stat.exists
register: command_result
failed_when: "'FAILED' in command_result.stderr"
become: true

View File

@@ -0,0 +1,23 @@
---
# workaround: add a dumb failed condition to avoid any failure here as the service is maybe not installed/existing
- name: Check if "docker compose" is available
shell: docker compose version
become: true
register: docker_compose_check
failed_when: "'FAILED' in docker_compose_check.stderr"
- name: Set the compose command to "docker compose"
set_fact:
compose_command: "docker compose"
when: docker_compose_check.rc == 0
- name: Fallback to "docker-compose" if "docker compose" is not available
set_fact:
compose_command: "docker-compose"
when: docker_compose_check.rc != 0
- name: Starting database service
shell: |
{{ compose_command }} -f {{ onelab_path }}/docker-compose.yml up -d db
sleep 30
become: true

View File

@@ -0,0 +1,19 @@
---
- name: Starting OneLab
shell: >
docker stack deploy onelab --compose-file {{ onelab_path }}/docker-compose.yml --with-registry-auth --prune
become: true
- name: Checking OneLab health status (could take up to 5min to be alive)
uri:
url: "{{ onelab.domain }}/api/status?token={{ onelab.security.monitoring.token }}"
return_content: yes
validate_certs: no
register: json_response
until:
- json_response.status == 200
- (json_response is defined) and (json_response.content|length > 0)
- json_response.content is search('status')
- "(json_response.content | from_json).status == 'running'"
retries: 60 # 60 * 10 seconds = 10m
delay: 10 # Every 10 seconds

View File

@@ -0,0 +1,6 @@
---
- name: Starting Proxy
shell: |
docker stack deploy onelab_proxy --compose-file {{ onelab_path }}/proxy/docker-compose.yml
sleep 10
become: true

View File

@@ -0,0 +1,6 @@
---
- name: Stopping database service
shell: |
{{ compose_command }} -f {{ onelab_path }}/docker-compose.yml down
sleep 30
become: true

View File

@@ -0,0 +1,6 @@
---
- name: Stopping OneLab
shell: |
docker stack rm onelab
sleep 30
become: true

View File

@@ -0,0 +1,6 @@
---
- name: Stopping Proxy
shell: |
docker stack rm onelab_proxy
sleep 20
become: true

View File

@@ -0,0 +1,24 @@
---
- name: Loading Docker Swarm configuration
shell: >
docker node ls | grep "Ready" | wc -l
register: nodecount
become: true
- set_fact:
deploy_on: "{{ 'manager' if (nodecount.stdout == '1') else 'worker' }}"
- name: Getting the list of Docker secrets
shell: docker secret ls | tail -n +2 | awk '{print $2}'
register: docker_secrets
become: true
- name: Reconfiguring files
ansible.builtin.template:
src: "{{ onelab_path }}/installation/latest/app/{{ item }}"
dest: "{{ onelab_path }}/{{ item }}"
with_items:
- 'docker-compose.yml'
- 'nginx/onelab.conf'
- 'proxy/proxy.conf'
- 'proxy/docker-compose.yml'