--- - name: Deploy Prestashop stack via Portainer through SSH tunnel hosts: localhost connection: local gather_facts: false vars: bastion_host: bdc.cci17.fr bastion_port: 17100 bastion_user: ansible portainer_url: https://127.0.0.1:9443 portainer_internal_ip: 10.30.0.151 portainer_internal_port: 9443 ssh_control_socket: /tmp/ssh-tunnel-portainer-9443.sock stack_type: 2 # 2 standalone, 1 swarm stack_name_prefix: ps- template_src: templates/prestashop-stack.yml.j2 rendered_compose_path: /tmp/prestashop-stack-rendered.yml tasks: - name: Ensure SITE_NAME provided assert: that: - SITE_NAME is defined - SITE_NAME | length > 0 fail_msg: "SITE_NAME doit etre fourni dans Semaphore (Options avancees)." - name: Ensure PORTAINER_API_KEY provided assert: that: - PORTAINER_API_KEY is defined - PORTAINER_API_KEY | length > 10 fail_msg: "PORTAINER_API_KEY doit etre fourni via Groupe de variables Semaphore." - block: - name: Check local port 9443 is free shell: ss -lnt | grep -q ':9443 ' register: port_in_use changed_when: false failed_when: port_in_use.rc == 0 - name: Open SSH tunnel to Portainer shell: > ssh -p {{ bastion_port }} -o ExitOnForwardFailure=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -M -S {{ ssh_control_socket }} -f -N -L 127.0.0.1:9443:{{ portainer_internal_ip }}:{{ portainer_internal_port }} {{ bastion_user }}@{{ bastion_host }} changed_when: true - name: Wait for tunnel to be ready wait_for: host: 127.0.0.1 port: 9443 timeout: 20 - name: Render docker-compose from template (Jinja2) template: src: "{{ template_src }}" dest: "{{ rendered_compose_path }}" - name: Read rendered compose content slurp: src: "{{ rendered_compose_path }}" register: compose_b64 - name: Get Portainer endpoints uri: url: "{{ portainer_url }}/api/endpoints" method: GET validate_certs: false headers: X-API-Key: "{{ PORTAINER_API_KEY }}" status_code: [200] register: endpoints_resp - name: Select first endpoint set_fact: endpoint_id: "{{ endpoints_resp.json[0].Id }}" - name: Create stack in Portainer uri: url: "{{ portainer_url }}/api/stacks?type={{ stack_type }}&method=string&endpointId={{ endpoint_id }}" method: POST validate_certs: false headers: X-API-Key: "{{ PORTAINER_API_KEY }}" Content-Type: application/json body_format: json body: Name: "{{ stack_name_prefix }}{{ SITE_NAME }}" StackFileContent: "{{ compose_b64.content | b64decode }}" Env: [] status_code: [200, 201, 409] register: create_stack - name: Result debug: msg: > Stack '{{ stack_name_prefix }}{{ SITE_NAME }}' creation status {{ create_stack.status }} (409 means it already exists) always: - name: Close SSH tunnel shell: > test -S {{ ssh_control_socket }} && ssh -p {{ bastion_port }} -S {{ ssh_control_socket }} -O exit {{ bastion_user }}@{{ bastion_host }} || true ignore_errors: true