piecia
piecia

Reputation: 386

How to create a nested directories structure via Ansible

Finally, I found a solution on how to create nested directory structure which is an equivalent of the Bash command

mkdir -p jenkins/cache/{war,tmp,workspace}

My playbook

---
- name: Create directories
  hosts: localhost
  vars:
    dirs: [
      jenkins, # for one elemnt it can be string
      [ cache ],
      [ war, tmp, workspace ]
    ]
    base_directory: ~/tmp

  tasks:
  - debug:
      msg="{{base_directory}}/{{item.0}}/{{item.1}}/{{item.2}}"
    with_nested: "{{ dirs | list }}"

It generates:

PLAY [Create directories] **********************************************************************************************************************************

TASK [debug] ***********************************************************************************************************************************************
ok: [localhost] => (item=['jenkins', 'cache', 'war']) => {
    "msg": "~/tmp/jenkins/cache/war"
}
ok: [localhost] => (item=['jenkins', 'cache', 'tmp']) => {
    "msg": "~/tmp/jenkins/cache/tmp"
}
ok: [localhost] => (item=['jenkins', 'cache', 'workspace']) => {
    "msg": "~/tmp/jenkins/cache/workspace"
}

PLAY RECAP *************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

But there is an issue if I want to use more (or less) levels of nesting. I need more (or less) item.X.
How to do it dynamically in Ansible?

I know there is community module filetree, which can be helpfully but I don't want or need to use it.

Upvotes: 3

Views: 1606

Answers (2)

β.εηοιτ.βε
β.εηοιτ.βε

Reputation: 39294

You can definitely use a with_nested and join the second level list with a /.

So, a task like this would do:

- debug:
    msg: >-
      {{ base_directory }}/
      {{- item | join('/') }}
  with_nested: "{{ dirs }}"

Given the task:

- debug:
    msg: >-
      {{ base_directory }}/
      {{- item | join('/') }}
  with_nested: "{{ dirs }}"
  vars:
    dirs:
      - jenkins
      - - cache
      - - war
        - tmp
        - workspace
    base_directory: ~/tmp

This yields:

ok: [localhost] => (item=['jenkins', 'cache', 'war']) => 
  msg: ~/tmp/jenkins/cache/war
ok: [localhost] => (item=['jenkins', 'cache', 'tmp']) => 
  msg: ~/tmp/jenkins/cache/tmp
ok: [localhost] => (item=['jenkins', 'cache', 'workspace']) => 
  msg: ~/tmp/jenkins/cache/workspace

Upvotes: 3

Vladimir Botka
Vladimir Botka

Reputation: 68189

The filter community.general.path_join takes the items of a list and creates a path. For example, the simplified task below

    - debug:
        msg: "{{ base_directory }}/{{ item|community.general.path_join }}"
      with_nested: "{{ dirs }}"
      vars:
        dirs:
          - jenkins
          - cache
          - [war, tmp, workspace]
        base_directory: /tmp

gives

  msg: /tmp/jenkins/cache/war
  msg: /tmp/jenkins/cache/tmp
  msg: /tmp/jenkins/cache/workspace

Upvotes: 2

Related Questions