I have a target linux node with default umask=0077
.
When I run a playbook
- name: Create folder for app
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: app_user
mode: 0755
with_items:
- "/opt/app/folder1/bin"
- "/etc/program/folder2"
parameter "mode" is applicable only to the last folder(bin
and folder2
).
All parent directories got strict rights, according umask.
How can I set required permission to parent directories (not for all /opt
or /etc
, only for chains):
/opt
, /opt/app
, /opt/app/folder1
, /opt/app/folder1/bin
/etc
, /etc/program
, /etc/program/folder2
Q: "Change rights on all intermediate parent folders."
Short answer: The module file doesn't know where to start changing the permissions when all subdirectories exist.
Details: For example, given the paths, declare depth where you want to start changing the rights. In this case, depth=1 is the root directory and depth=2 is /tmp9
path1: /tmp9/a/b/c
path2: /tmp9/x/y/z
depth: 2
Create a file with the loop that incrementally changes the subdirectories
shell> cat subdirs.yml
- file:
path: "{{ root }}/{{ subs[:ansible_loop.index] | join('/') }}"
state: directory
owner: admin
mode: 0755
loop: "{{ subs }}"
loop_control:
extended: true
vars:
dirs: "{{ outer_item | split('/') }}"
root: "{{ dirs[:depth] | join('/') }}"
subs: "{{ dirs[depth:] }}"
Include this task in a loop
- include_tasks: subdirs.yml
loop:
- "{{ path1 }}"
- "{{ path2 }}"
loop_control:
loop_var: outer_item
Given the below tree, the task is idempotent
shell> tree -pu /tmp9
[drwxr-xr-x root ] /tmp9
├── [drwxr-xr-x admin ] a
│ └── [drwxr-xr-x admin ] b
│ └── [drwxr-xr-x admin ] c
└── [drwxr-xr-x admin ] x
└── [drwxr-xr-x admin ] y
└── [drwxr-xr-x admin ] z
If you change the mode
mode: 0700
the task changes the permissions
shell> tree -pu /tmp9
[drwxr-xr-x root ] /tmp9
├── [drwx------ admin ] a
│ └── [drwx------ admin ] b
│ └── [drwx------ admin ] c
└── [drwx------ admin ] x
└── [drwx------ admin ] y
└── [drwx------ admin ] z
Example of a complete playbook for testing
- hosts: localhost
become: true
vars:
path1: /tmp9/a/b/c
path2: /tmp9/x/y/z
depth: 2
tasks:
- include_tasks: subdirs.yml
loop:
- "{{ path1 }}"
- "{{ path2 }}"
loop_control:
loop_var: outer_item
The module file works as expected. Quoting:
If `directory', all intermediate subdirectories will be created if they do not exist. Since Ansible 1.7 they will be created with the supplied permissions.
For example, given the empty directory
shell> tree -pu /tmp9
[drwxr-xr-x root ] /tmp9
the play
- hosts: localhost
become: true
vars:
path1: /tmp9/a/b/c
path2: /tmp9/x/y/z
tasks:
- file:
path: "{{ item }}"
state: directory
owner: admin
mode: 0755
loop:
- "{{ path1 }}"
- "{{ path2 }}"
creates the tree
shell> tree -pu /tmp9
[drwxr-xr-x root ] /tmp9
├── [drwxr-xr-x admin ] a
│ └── [drwxr-xr-x admin ] b
│ └── [drwxr-xr-x admin ] c
└── [drwxr-xr-x admin ] x
└── [drwxr-xr-x admin ] y
└── [drwxr-xr-x admin ] z
, but changing the mode
mode: 0700
changes the last subdirectory permissions only
shell> tree -pu /tmp9
[drwxr-xr-x root ] /tmp9
├── [drwxr-xr-x admin ] a
│ └── [drwxr-xr-x admin ] b
│ └── [drwx------ admin ] c
└── [drwxr-xr-x admin ] x
└── [drwxr-xr-x admin ] y
└── [drwx------ admin ] z