--- # docker_compose_v2 validates project_src with os.path.isdir, which is false both # for a path that is missing and for one that is a file, and reports either as # `"..." is not a directory`. Stat it first so the two are told apart here rather # than left to that one message. - name: Look for the stack directory on the host ansible.builtin.stat: path: "{{ stack_dest }}" register: compose_stack_dir changed_when: false - name: Verify the stack directory is a directory ansible.builtin.assert: that: - compose_stack_dir.stat.isdir | default(false) fail_msg: >- {{ stack_dest }} exists on {{ inventory_hostname }} but is not a directory quiet: true when: compose_stack_dir.stat.exists # A check run creates nothing, so on a host that has never deployed this stack # there is no project directory for the module to inspect and it fails on its # absence — a first `--check` would report the payload diff correctly and then # die for a reason that says nothing about the stack. Skip it instead; the sync # tasks above have already reported everything check mode can know. - name: Note that the stack cannot be checked before its first deploy ansible.builtin.debug: msg: >- {{ stack_dest }} does not exist yet, so the compose step was skipped. Deploy for real to create it. when: - stack_start | bool - ansible_check_mode - not compose_stack_dir.stat.exists # The counterpart to that message, for `-e start=false`. Without it the play ends # with the compose task skipped and nothing saying so, which reads exactly like a # run that quietly failed to do its job. - name: Note that the stack was synced but deliberately not started ansible.builtin.debug: msg: >- start=false, so the payload is on {{ inventory_hostname }} and {{ stack_name }} was left as it was. Run again without the flag to start it. when: not stack_start | bool - name: Bring the stack up community.docker.docker_compose_v2: project_src: "{{ stack_dest }}" files: "{{ stack_files }}" state: "{{ stack_state }}" pull: "{{ stack_pull }}" build: "{{ stack_build }}" remove_orphans: true # A compose file that interpolates ${PWD} — a common way to hand a host path to # a sibling container — resolves it against the *invoking shell*, not the # project directory. The module sets the process working directory but not PWD, # so ${PWD} would silently become the SSH login directory. Set it explicitly. environment: "{{ {'PWD': stack_dest} | combine(stack_env) }}" # stack_start is gated here rather than around the include in main.yml, because # a two-phase playbook calls tasks_from: up directly and main.yml never sees it. when: - stack_start | bool - compose_stack_dir.stat.exists or not ansible_check_mode