--- - name: Check whether podman is installed ansible.builtin.command: podman --version register: trade_hub_podman_check changed_when: false failed_when: false check_mode: false - name: Install podman when requested ansible.builtin.package: name: podman state: present become: true when: - trade_hub_podman_check.rc != 0 - trade_hub_install_podman | bool - name: Re-check podman after installation ansible.builtin.command: podman --version register: trade_hub_podman_recheck changed_when: false failed_when: false check_mode: false when: trade_hub_podman_check.rc != 0 - name: Require podman to be available ansible.builtin.assert: that: - trade_hub_podman_check.rc == 0 or (trade_hub_podman_recheck.rc | default(1)) == 0 fail_msg: >- podman is not installed on {{ inventory_hostname }}. Install it first (for example with the "packages" role) or run this role with -e trade_hub_install_podman=true. quiet: true - name: Remove the legacy Apache container when requested containers.podman.podman_container: name: "{{ trade_hub_legacy_apache_container }}" state: absent when: trade_hub_remove_legacy_apache | bool - name: Create the application directory ansible.builtin.file: path: "{{ trade_hub_app_dir }}" state: directory mode: "0755" - name: Create the application source directories ansible.builtin.file: path: "{{ trade_hub_app_dir }}/{{ item }}" state: directory mode: "0755" loop: "{{ trade_hub_app_subdirs }}" - name: Stage the application build context ansible.builtin.copy: src: "{{ role_path }}/files/trade-hub/{{ item.src }}" dest: "{{ trade_hub_app_dir }}/{{ item.dest }}" mode: preserve loop: # Only the files needed by the two Dockerfiles are staged. Copying the # whole tree would also ship local development artefacts such as .venv. - { src: "backend/Dockerfile", dest: "backend/Dockerfile" } - { src: "backend/requirements.txt", dest: "backend/requirements.txt" } - { src: "backend/main.py", dest: "backend/main.py" } - { src: "backend/app/", dest: "backend/app/" } - { src: "backend/scripts/", dest: "backend/scripts/" } - { src: "frontend/Dockerfile", dest: "frontend/Dockerfile" } - { src: "frontend/nginx.conf", dest: "frontend/nginx.conf" } - { src: "frontend/src/", dest: "frontend/src/" } register: trade_hub_source - name: Check whether the backend image exists ansible.builtin.command: argv: - podman - image - exists - "{{ trade_hub_backend_image }}:{{ trade_hub_image_tag }}" register: trade_hub_backend_image_check changed_when: false failed_when: false check_mode: false - name: Check whether the frontend image exists ansible.builtin.command: argv: - podman - image - exists - "{{ trade_hub_frontend_image }}:{{ trade_hub_image_tag }}" register: trade_hub_frontend_image_check changed_when: false failed_when: false check_mode: false - name: Build the backend image ansible.builtin.command: argv: - podman - build - --tag - "{{ trade_hub_backend_image }}:{{ trade_hub_image_tag }}" - "{{ trade_hub_app_dir }}/backend" when: - trade_hub_build_images | bool - trade_hub_force_rebuild | bool or trade_hub_source.changed or trade_hub_backend_image_check.rc != 0 register: trade_hub_backend_build - name: Build the frontend image ansible.builtin.command: argv: - podman - build - --tag - "{{ trade_hub_frontend_image }}:{{ trade_hub_image_tag }}" - "{{ trade_hub_app_dir }}/frontend" when: - trade_hub_build_images | bool - trade_hub_force_rebuild | bool or trade_hub_source.changed or trade_hub_frontend_image_check.rc != 0 register: trade_hub_frontend_build - name: Require prebuilt images when image builds are disabled ansible.builtin.assert: that: - trade_hub_backend_image_check.rc == 0 - trade_hub_frontend_image_check.rc == 0 fail_msg: >- trade_hub_build_images is false but {{ trade_hub_backend_image }}:{{ trade_hub_image_tag }} and/or {{ trade_hub_frontend_image }}:{{ trade_hub_image_tag }} are missing on {{ inventory_hostname }}. quiet: true when: not trade_hub_build_images | bool - name: Record whether the application containers need to be recreated ansible.builtin.set_fact: trade_hub_recreate_containers: >- {{ (trade_hub_force_rebuild | bool) or ((trade_hub_build_images | bool) and (trade_hub_source.changed | default(false))) or (trade_hub_backend_build.changed | default(false)) or (trade_hub_frontend_build.changed | default(false)) }} - name: Ensure the PostgreSQL image is present containers.podman.podman_image: name: "{{ trade_hub_postgres_image }}" state: present when: not ansible_check_mode - name: Create the podman network containers.podman.podman_network: name: "{{ trade_hub_network }}" state: present - name: Check whether the shared proxy network exists ansible.builtin.command: podman network exists npm_internal register: trade_hub_npm_network_check changed_when: false failed_when: false check_mode: false - name: Require the shared proxy network to exist ansible.builtin.assert: that: - trade_hub_npm_network_check.rc == 0 fail_msg: >- The npm_internal podman network does not exist on {{ inventory_hostname }}. Run the network role first, e.g. ansible-playbook -i inventory.ini ansible-playbook.yml --tags "network,trade_hub". quiet: true - name: Create the PostgreSQL data volume containers.podman.podman_volume: name: "{{ trade_hub_volume }}" state: present - name: Run the PostgreSQL container containers.podman.podman_container: name: "{{ trade_hub_db_container }}" image: "{{ trade_hub_postgres_image }}" state: started recreate: "{{ trade_hub_force_rebuild | bool }}" network: "{{ trade_hub_network }}" network_aliases: - db env: POSTGRES_USER: "{{ trade_hub_postgres_user }}" POSTGRES_PASSWORD: "{{ trade_hub_postgres_password }}" POSTGRES_DB: "{{ trade_hub_postgres_db }}" volumes: - "{{ trade_hub_volume }}:/var/lib/postgresql/data:Z" restart_policy: unless-stopped when: not ansible_check_mode - name: Run the backend container containers.podman.podman_container: name: "{{ trade_hub_backend_container }}" image: "{{ trade_hub_backend_image }}:{{ trade_hub_image_tag }}" state: started # podman does not recreate a container when its image tag resolves to a new # ID, so recreate whenever the image was rebuilt or the app changed. recreate: "{{ trade_hub_recreate_containers | bool }}" network: "{{ trade_hub_network }}" # The nginx upstream is http://backend:8000, so this alias must match. network_aliases: - backend env: DATABASE_URL: "{{ trade_hub_database_url }}" DB_WAIT_SECONDS: "{{ trade_hub_db_wait_seconds }}" COOKIE_SECURE: "{{ trade_hub_cookie_secure | bool | lower }}" restart_policy: unless-stopped when: not ansible_check_mode - name: Run the frontend container containers.podman.podman_container: name: "{{ trade_hub_frontend_container }}" image: "{{ trade_hub_frontend_image }}:{{ trade_hub_image_tag }}" state: started recreate: "{{ trade_hub_recreate_containers | bool }}" # Keep sc-inventory for the "backend" DNS alias and join the shared proxy # network with a fixed address so the proxy-manager upstream never changes. network: - "{{ trade_hub_network }}" - "npm_internal:ip={{ trade_hub_frontend_ip }}" ports: - "{{ trade_hub_frontend_bind }}:{{ trade_hub_frontend_port }}:{{ trade_hub_frontend_port }}" restart_policy: unless-stopped when: not ansible_check_mode - name: Enable podman-restart so containers survive a reboot ansible.builtin.systemd: name: podman-restart.service enabled: true state: started when: trade_hub_enable_restart_service | bool - name: Wait for the application to answer health checks ansible.builtin.uri: url: "{{ trade_hub_healthcheck_url }}" status_code: 200 register: trade_hub_health until: trade_hub_health.status == 200 retries: "{{ trade_hub_healthcheck_retries }}" delay: "{{ trade_hub_healthcheck_delay }}" changed_when: false when: not ansible_check_mode