I have to read every line from a text file and add that in yaml. Here is my play book
- hosts: localhost
tasks:
- name: Register a file content as a variable
ansible.builtin.shell: cat /home/packages.txt
register: result
- name: Print the transformed variable
ansible.builtin.debug:
msg: '{{ item }}'
loop: '{{ result.stdout | list }}'
- name: install
shell: yum install '{{ item }}'
loop: '{{ result.stdout | list }}'
packages.txt contains
nginx
vim
grafana
When I run this, the packages are not getting installed. This is the console output,
TASK [Register a file content as a variable] **********************************************************************************
changed: [localhost]
TASK [Print the transformed variable] *****************************************************************************************
TASK [install] ****************************************************************************************************************
PLAY RECAP ********************************************************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
Requirement is to install those packages from the text file through this ansible playbook
Given the file
shell> cat packages.txt
nginx
vim
grafana
On localhost, iterate the list. For example, the playbook below
shell> cat test.yml
- hosts: localhost
tasks:
- name: install
package:
name: "{{ item }}"
loop: "{{ lookup('file', 'packages.txt').split() }}"
gives (abridged, if the packages have already been installed)
TASK [install] *******************************************************
ok: [localhost] => (item=nginx)
ok: [localhost] => (item=vim)
ok: [localhost] => (item=grafana)
The module package says:
To operate on several packages this can accept a comma-separated string of packages or a list of packages, depending on the underlying package manager.
You can check with the package managers. For example, the below package managers allow the list of packages:
Then, you don't have to iterate the installation
- name: install
when: ansible_os_family in ['Debian', 'FreeBSD', 'RedHat']
package:
name: "{{ lookup('file', 'packages.txt').split() }}"
You can check with other package managers and fit the list of the systems to your needs.
The variable ansible_pkg_mgr keeps the system's package manager. For example, in FreeBSD
shell> ansible <remote_host> -m setup | grep ansible_pkg_mgr
"ansible_pkg_mgr": "pkgng",
On a remote host (lookup works on the localhost only), iterate stdout_lines. For example,
- name: Register a file content as a variable
command: cat packages.txt
register: result
- name: install
package:
name: "{{ item }}"
loop: "{{ result.stdout_lines }}"
Optionally, if you want to avoid the command or shell module use fetch. For example, in the playbook below
shell> cat test.yml
- hosts: test_11
tasks:
- name: Get file
fetch:
src: packages.txt
dest: files
- name: install
package:
name: "{{ item }}"
loop: "{{ lookup('file', path).split() }}"
vars:
path: 'files/{{ inventory_hostname }}/packages.txt'
fetch the file from the remote host(s) first. This will create the file
shell> cat files/test_11/packages.txt
nginx
vim
grafana
Then iterate the lines from the file
TASK [install] ***************************************************
changed: [test_11] => (item=nginx)
changed: [test_11] => (item=vim)
changed: [test_11] => (item=grafana)