Lately I've been tinkering with Ansible and want to achieve following on my test node using Ansible:
- Clone a repo to the Remote Node
grep
a packagelist from a textfile within the git repo- Load the tools from the packagelist into an Ansible variable
- Install these tools via the Ansible
package
module orapt
module.
So far I've got this:
---
- hosts: all
become: true
vars:
username: foobar
tasks:
- name: Install git package
package:
name: git
state: present
- name: Clone GIT Repo
git:
repo: https://github.com/somerepo/.dotfiles.git
dest: /home/{{ username }}/.dotfiles
clone: yes
version: master
update: yes
force: yes
- name: Set permission on folder ~/.dotfiles
file:
dest: /home/{{ username }}/.dotfiles
recurse: yes
owner: "{{ username }}"
group: "{{ username }}"
mode: "0775"
- name: Extract list of needed tools from install.sh
shell:
cmd: grep "^tools=" /home/{{ username }}/.dotfiles/install.sh | tr '"' " " | cut -c7-
register: grep_output
- name: Install following packages "{{ grep_output }}"
apt:
name: "{{ grep_output }}"
state: present
update_cache: yes
The shell command gathers a list with tools:
grep "^tools=" install.sh |tr '"' " " | cut -c7-
with the STDOUT
output
zsh neovim vim tmux ranger stow wget curl git fzf
Those values I want to store in an Ansible variable and install it via package plugin.
When I run the playbook on my test VM
PLAY [all] *******************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************
[WARNING]: Platform linux on host vm-mint21 is using the discovered Python interpreter at /usr/bin/python3.10, but future
installation of another Python interpreter could change the meaning of that path. See https://docs.ansible.com/ansible-
core/2.12/reference_appendices/interpreter_discovery.html for more information.
ok: [vm-mint21]
TASK [Install git package] ***************************************************************************************************
ok: [vm-mint21]
TASK [Clone GIT Repo] ********************************************************************************************************
changed: [vm-mint21]
TASK [Set permission on folder ~/.dotfiles] **********************************************************************************
changed: [vm-mint21]
TASK [Extract list of needed tools from install.sh] **************************************************************************
changed: [vm-mint21]
TASK [Install following packages "{'changed': True, 'stdout': ' zsh neovim vim tmux ranger stow wget curl git fzf ', 'stderr': '', 'rc': 0, 'cmd': 'grep "^tools=" /home/soeren/.dotfiles/install.sh | tr \'"\' " " | cut -c7-', 'start': '2022-09-12 22:33:37.056914', 'end': '2022-09-12 22:33:37.061264', 'delta': '0:00:00.004350', 'msg': '', 'stdout_lines': [' zsh neovim vim tmux ranger stow wget curl git fzf '], 'stderr_lines': [], 'failed': False}"] ***
fatal: [vm-mint21]: FAILED! => {"changed": false, "msg": "argument 'package' is of type <class 'dict'> and we were unable to convert to list: <class 'dict'> cannot be converted to a list"}
PLAY RECAP *******************************************************************************************************************
vm-mint21 : ok=5 changed=3 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
I get following error:
argument 'package' is of type <class 'dict'> and we were unable to convert to list: <class 'dict'> cannot be converted to a list"
CodePudding user response:
To narrow down such issue one may have a look into the following example
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: Create STDOUT output
command: 'echo "1 2 3 4 5 6"'
register: result
- name: Show full result
debug:
var: result
- name: Show '.stdout'
debug:
msg: "The result in '.stdout': {{ result.stdout }} is of type {{ result.stdout | type_debug }}"
resulting into an output of
TASK [Show full result] ****************************************************************************
ok: [localhost] =>
result:
changed: true
cmd:
- echo
- 1 2 3 4 5 6
delta: '0:00:00.009634'
end: '2022-09-12 23:00:00.788265'
failed: false
rc: 0
start: '2022-09-12 23:00:00.778631'
stderr: ''
stderr_lines: []
stdout: 1 2 3 4 5 6
stdout_lines:
- 1 2 3 4 5 6
TASK [Show '.stdout'] ****************************************************************************
ok: [localhost] =>
msg: 'The result in ''.stdout'': 1 2 3 4 5 6 is of type AnsibleUnsafeText'
In this way one can debug the Return Values of an Ansible module
Ansible modules normally return a data structure that can be registered into a variable, or seen directly when output by the
ansible
program. Each module can optionally document its own unique return values (visible through ansible-doc and on the main docsite).
in a variable which became registered.
Registered variables may be simple variables, list variables, dictionary variables, or complex nested data structures. The documentation for each module includes a
RETURN
section describing the return values for that module.
For your specific case you can see that the shell
module has a <yourVarName>.stderr
and <yourVarName>.stdout
, whereby you are interested in .stdout
only. The type of the registered output is text marked as unsafe so it will not become templated.
To feed the registered output to the next module package
or apt
, which will require a list, you can just use the from Zeittounator within the comments mentioned name: "{{ grep_output.stdout.split(' ') }}"
line. It will split the string into a list based on a delimiter.
CodePudding user response:
You can modify your last task as below. Using "split" function you can convert string to a list.
- name: Install following packages "{{ grep_output }}"
apt:
name: "{{ item }}"
state: present
update_cache: yes
loop: "{{ grep_output.stdout.split() }}"