First off thank you for any assistance here, this is my first post on here despite using it as a great resource for years!
I have recently been learning and using Ansible a lot more as part of a new role I'm in for work and my manager has asked me to make a change that I find a little confusing.
I have a task that runs a shell command and loops through the command using the with_items
module
- name: add non-existent buckets
shell: "timeout 30 mc --config-dir={{ mc_config }} mb opt/{{item}}"
with_items: "{{ bucket_list }}"
I have been asked to change this to point directly at the variables rather than expanding them first and I am struggling to understand what this means and how to go about it.
I have tried various ways of writing this out but no luck whatsoever. The frustrating part of all this is that the above works but apparently makes the Ansible engine do more work than it needs to do.
Thanks in advance and please let me know if I need to provide any more information!
CodePudding user response:
I understand that you like to know "How to increase the performance and decrease execution time of specific tasks?". I understand that you like to create multiple new buckets or directories under a specified path opt/
in a MinIO Baremetal Infrastructure via the mc mb
command.
It is an equivalent like of mkdir -p /opt/{this,is,my,list,of,subdirectories,to,create}
. I understand that you do not want to loop over the command, instead providing a directory list for the command.
To achieve for goal you may have a look into the following example, documentation and further links.
---
- hosts: test
become: false
gather_facts: false
vars:
DIR_LIST: [this,is,my,list,of,subdirectories,to,create]
tasks:
- name: Create subdirectories (loop)
shell:
cmd: "mkdir -p /home/{{ ansible_user }}/{{ item }}"
warn: false
loop: "{{ DIR_LIST }}"
- name: Create subdirectories (list)
shell:
cmd: "mkdir -p /home/{{ ansible_user }}/{% raw %}{{% endraw %}{{ DIR_LIST | join(',') }}{% raw %}}{% endraw %}"
warn: false
resulting into run and execution times of
TASK [Create subdirectories (loop)] ******************
changed: [test.example.com] => (item=this)
changed: [test.example.com] => (item=is)
changed: [test.example.com] => (item=my)
changed: [test.example.com] => (item=list)
changed: [test.example.com] => (item=of)
changed: [test.example.com] => (item=subdirectories)
changed: [test.example.com] => (item=to)
changed: [test.example.com] => (item=create)
Friday 29 July 2022 (0:00:14.023) 0:00:14.064 ********
TASK [Create subdirectories (list)] ******************
changed: [test.example.com]
Friday 29 July 2022 (0:00:02.172) 0:00:16.236 ********
======================================================
Create subdirectories (loop) ------------------ 14.02s
Create subdirectories (list) ------------------- 2.17s
Whereby looping over modules or commands and providing one parameter for the module or command per run results into a lot of overhead, providing the list directly to the command or module might be possible and increase performance and decrease runtime and resource consumption.
An (other) example for this is the yum
module
When used with a
loop:
each package will be processed individually, it is much more efficient to pass the list directly to the name option
If your command mc mb
produce similar results as mentioned in documentation
You can also use
mc mb
against the local filesystem to produce similar results to themkdir -p
commandline tool.
you might be able provide a list of directories to the command via Ansible too, in example like
mc mb opt/{this,is,my,list,of,subdirectories,to,create}
For this the command needs to include curly braces which needs to be escaped in Ansible. The directory list would need to be a string, whereby the directories are comma separated. For this you can use the join()
filter.
Is there a way to pass a list to a command and get it to iterate over each item without a loop?
Finally you would end up with
- name: add non-existent buckets
shell:
cmd: "timeout 30 mc --config-dir={{ mc_config }} mb opt/{% raw %}{{% endraw %}{{ bucket_list | join(',') }}{% raw %}}{% endraw %}"
Further Q&A
Further Documentation
Further Readings