0

So far I use simple code to deploy Docker stacks. I don't want to use community.general.docker_stack module, due to its ridiculous requirement: the stack definition (docker compose yml file) needs to be placed at the remote node, while I want to have them all gathered at local manager host. Example code is below (part of role/tasks and vars):

- name: deploy Docker stacks
  command: docker stack deploy --compose-file - {{ item.name }}
  args:
    stdin: "{{ lookup('file', item.source) }}"
  with_items: "{{ docker_swarm_stacks }}"
  when: (docker_swarm_stacks is defined)
docker_swarm_stacks:
  - name: portainer
    source: files/docker_swarm/stacks/portainer.yml
  - name: www-1
    source: files/docker_swarm/stacks/nginx-static.yml
  - name: www-2
    source: files/docker_swarm/stacks/wordpress.yml

So far, so good. With appropriate compose files (placed files/docker_swarm/stacks) in, it works very nice. One stack is created from one yml file (of course one yml file can be used to create similar stacks with different names). But I would like to improve it and here is a great issue: I would like to make it possible to use (merge) many compose files as definitions for 1 stack, but the "{{lookup('file', 'path/to/file.txt')}}" is limited to 1 file. I've already tried to use list of files, but it fails. Now I don't have a better idea how to solve it, so I would appreciate if you can share your knowledge and maybe someone has an idea how to solve it.

  • Do you need the files itself or is it just because of the lookup? If last - then load the YAML and merge the YAML via the combine filter. See https://stackoverflow.com/questions/25422771/merging-dictionaries-in-ansible – TRW Jan 30 '21 at 14:15
  • @TRW thx for comment. i understand the idea and the best solution would be join few **yaml** files (compose files) in one variable (dictionary) and then pass it to next command. My problem is: I cannot find a way to join these few files (list of files): _{{ lookup('file', item.source) }}_ requires 1 file, no more. The files must stay intact at Ansible local. – Michał Ciania Feb 02 '21 at 07:31

1 Answers1

0

You need one big combined YAML file. The lookup filter only "reads" the single file into a variable. So what you want is a loop over all files and read the content from the files into one "variable" - so you combine each dict-var. And that variable is something, you send to the docker command.

Here an example:

- name: "Define an empty definition"
  set_fact:
    combined_config: {}

- name: "Load all definitions into the definition"
  set_fact:
    combined_config: "{{ combined_config | combine(lookup('file', item.source)) }}"
  loop: "{{ docker_swarm_stacks | default([]) }}"

- name: "Deploy Docker stacks"
  command: docker stack deploy --compose-file - {{ item.name }}
  args:
    stdin: "{{ combined_config }}"

I didn't test, if the YAML is really good combined and imported correctly (especially with duplicate keys in the dict). If it isn't working, you could test the lookup result with debug.

TRW
  • 438
  • 3
  • 14