How can I merge lists with ansible 2.6.3 - ansible

In the past I used ansible 2.3.1.0 and now want to use ansible 2.6.3.
I now want to install some packages with apt. therefore I have to source lists and I want to merge them in one. In ansible 2.3.1.0 I just used the following:
apt_packages:
- "{{ packages_list1 + packages_list2 }}"
And I am getting the following error:
Traceback (most recent call last):\r\n File \"/tmp/ansible_k0tmag/ansible_module_apt.py\", line 1128, in <module>\r\n main()\r\n File \"/tmp/ansible_k0tmag/ansible_module_apt.py\", line 1106, in main\r\n
allow_unauthenticated=allow_unauthenticated\r\n File \"/tmp/ansible_k0tmag/ansible_module_apt.py\", line 521, in install\r\n pkgspec = expand_pkgspec_from_fnmatches(m, pkgspec, cache)\r\n File \"/tmp/ansible_k0tmag/ansible_module_apt.py\", line 439, in expand_pkgspec_from_fnmatches\r\n
pkgname_pattern, version = package_split(pkgspec_pattern)\r\n File \"/tmp/ansible_k0tmag/ansible_module_apt.py\", line 312, in package_split\r\n
parts = pkgspec.split('=', 1)\r\nAttributeError: 'list' object has no attribute 'split'\r\n", "msg": "MODULE FAILURE", "rc": 1}
Content of the role:
apt:
state: present
name: "{{ apt_packages }}"
force: yes
when: apt_packages is defined```

With apt_packages: "{{ packages_list1 + packages_list2 }}"(without the -), it will work.
Working sample:
- hosts: localhost
gather_facts: no
vars:
pkgs1:
- perl
- python
pkgs2:
- vim
- tar
packages: "{{ pkgs1 + pkgs2 }}"
tasks:
- apt:
name: "{{ packages }}"
state: present

Related

Loading environment variables from YAML file (using include_vars) in Ansible

I am trying to load variables from a YAML file to be used as environment variables in a later task of the same playbook. This is what I am doing:
Template host vars in YAML format:
- name: builtin | template | template host variables file
ansible.builtin.template:
src: templates/django/hostvars.j2
dest: "host_vars/{{ inventory_hostname_short }}.yml"
mode: 0640
output_encoding: "utf-8"
delegate_to: localhost
This is producing the following file:
--
# Host variables to be set as environment variables in tasks that need it
POSTGRES_PASSWORD: "<password>"
POSTGRES_USER: "dbuser"
POSTGRES_DB: "dbname"
POSTGRES_HOST: "dbhost"
POSTGRES_PORT: 5432
POSTGRES_SSLMODE: "verify-full"
POSTGRES_SSLCA: "/etc/ssl/certs/ISRG_Root_X1.pem"
POSTGRES_APPNAME: "myproject"
DJANGO_SITE_NAME: "mysite"
DJANGO_SITE_PASSWORD: "mypassword"
DJANGO_SITE_USER: "myuser"
DJANGO_SITE_ID: 2
DJANGO_SECRET_KEY: "<very-long-and-random-secret>"
[..]
Use include_vars to load the vars into the playbook:
- name: builtin | include_vars | load host vars
ansible.builtin.include_vars:
file: "host_vars/{{ inventory_hostname_short }}.yml"
name: envvars
Later on the playbook, check that the variables are there:
- name: builtin | debug | print variable 'envvars'
ansible.builtin.debug:
var: envvars
This is working as intended (apparently) and a list of KEY: value variables is being printed, such as:
TASK [builtin | debug | print variable 'envvars'] ***************************************************************
ok: [django1.mydomain.com] => {
"envvars": {
"DJANGO_DEBUG": 0,
"DJANGO_LOGS_DIR": "/opt/django/logs",
"DJANGO_MEDIA_BASE": "/opt/django/media",
"DJANGO_SECRET_KEY": "<very-long-and-random-secret>",
[..]
Use django_manage to update the database schema:
- name: community.general | django_manage | update database schema
community.general.django_manage:
command: migrate
settings: myproject.settings
project_path: "/opt/django/src"
virtualenv: "/opt/django/venv"
become: true
become_user: django
become_method: su
environment: "{{ envvars }}"
This, unfortunately, is failing. Django is complaining that it cannot find the SECRET_KEY environment variable, which it should build based on one of the variables in the abovementioned list (especifically, DJANGO_SECRET_KEY).
Incidentally, if I run the following task, nothing is printed out:
- name: print environment variables
ansible.builtin.command: env
become: true
become_user: django
become_method: su
environment: "{{ envvars }}"
And I don't understand why. I've tried to debug using -vvv and they are being sent by Ansible though the SSH connection (at least so it seems).
Any hints on what bit I am doing wrong?
EDIT 1
I've changed the tasks list file where I use django_manage into the following code:
- name: builtin | shell | capture DJANGO_ environment variables
debugger: on_failed
ansible.builtin.shell:
cmd: "env | grep DJANGO_"
register: out
environment: "{{ envvars }}"
become: true
become_user: django
become_method: su
- name: builtin | debug | pinrt content of out.stdout
ansible.builtin.debug:
var: out.stdout
- name: builtin | debug | print variable 'envvars'
ansible.builtin.debug:
var: envvars
- name: community.general | django_manage | populate the static subdirectory
community.general.django_manage:
command: collectstatic
clear: yes
project_path: "/opt/django/src"
virtualenv: "/opt/django/venv"
become: true
become_user: django
become_method: su
environment: "{{ envvars }}"
The second and third tasks both print the values of the variables (the first one from the env | grep DJANGO_ command sent via shell and the second is the value of the envvars variable which is being sent via the environment: directive.
This is the error of the last task:
TASK [builtin | shell | capture DJANGO_ environment variables] *************************************************************************************************************
changed: [django1.donmain.com]
TASK [builtin | debug | pinrt content of out.stdout] ***********************************************************************************************************************
ok: [django1.django.com] => {
"out.stdout": "DJANGO_SITE_USER=mysite\nDJANGO_MEDIA_BASE=/opt/django/media\nDJANGO_SITE_NAME=mysite\nDJANGO_SITE_ID=2\nDJANGO_SECRET_KEY=<very-secret-key>\nDJANGO_LOGS_DIR=/opt/django/logs\nDJANGO_SETTINGS_MODULE=myproject.settings.production\nDJANGO_DEBUG=0\nDJANGO_STATIC_BASE=/opt/django/static\nDJANGO_SITE_PASSWORD=mypassword\nDJANGO_SITE_VERSION=57a2f3c168d86243f03809e5d02a0f50a8fa892e"
}
TASK [builtin | debug | print variable 'envvars'] **************************************************************************************************************************
ok: [django1.domain.com] => {
"envvars": {
"DJANGO_DEBUG": 0,
"DJANGO_LOGS_DIR": "/opt/django/logs",
"DJANGO_MEDIA_BASE": "/opt/django/media",
"DJANGO_SECRET_KEY": "<very-secret-key>",
"DJANGO_SETTINGS_MODULE": "myproject.settings.production",
"DJANGO_SITE_ID": 2,
"DJANGO_SITE_NAME": "mysite",
"DJANGO_SITE_PASSWORD": "mypassword",
"DJANGO_SITE_USER": "myuser",
[..]
}
}
TASK [community.general | django_manage | populate the static subdirectory] ************************************************************************************************
fatal: [django1.domain.com]: FAILED! => {"changed": false, "cmd": ["./manage.py", "collectstatic", "--noinput", "--clear"], "msg": "\n:stderr: Traceback (most recent call last):\n File \"/opt/django/venv/lib/python3.9/site-packages/django/core/management/__init__.py\", line 204, in fetch_command\n app_name = commands[subcommand]\nKeyError: 'collectstatic'\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/opt/django/src/./manage.py\", line 22, in <module>\n execute_from_command_line(sys.argv)\n File \"/opt/django/venv/lib/python3.9/site-packages/django/core/management/__init__.py\", line 381, in execute_from_command_line\n utility.execute()\n File \"/opt/django/venv/lib/python3.9/site-packages/django/core/management/__init__.py\", line 375, in execute\n self.fetch_command(subcommand).run_from_argv(self.argv)\n File \"/opt/django/venv/lib/python3.9/site-packages/django/core/management/__init__.py\", line 211, in fetch_command\n settings.INSTALLED_APPS\n File \"/opt/django/venv/lib/python3.9/site-packages/django/conf/__init__.py\", line 57, in __getattr__\n self._setup(name)\n File \"/opt/django/venv/lib/python3.9/site-packages/django/conf/__init__.py\", line 44, in _setup\n self._wrapped = Settings(settings_module)\n File \"/opt/django/venv/lib/python3.9/site-packages/django/conf/__init__.py\", line 107, in __init__\n mod = importlib.import_module(self.SETTINGS_MODULE)\n File \"/usr/lib/python3.9/importlib/__init__.py\", line 127, in import_module\n return _bootstrap._gcd_import(name[level:], package, level)\n File \"<frozen importlib._bootstrap>\", line 1030, in _gcd_import\n File \"<frozen importlib._bootstrap>\", line 1007, in _find_and_load\n File \"<frozen importlib._bootstrap>\", line 986, in _find_and_load_unlocked\n File \"<frozen importlib._bootstrap>\", line 680, in _load_unlocked\n File \"<frozen importlib._bootstrap_external>\", line 790, in exec_module\n File \"<frozen importlib._bootstrap>\", line 228, in _call_with_frames_removed\n File \"/opt/django/src/black_pearl/settings/production.py\", line 3, in <module>\n from black_pearl.settings.common import *\n File \"/opt/django/src/black_pearl/settings/common.py\", line 301, in <module>\n path_app = import_module(app).__path__\n File \"/usr/lib/python3.9/importlib/__init__.py\", line 127, in import_module\n return _bootstrap._gcd_import(name[level:], package, level)\nModuleNotFoundError: No module named 'None'\n", "path": "/opt/django/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "syspath": ["/tmp/ansible_community.general.django_manage_payload_l53eeo4g/ansible_community.general.django_manage_payload.zip", "/usr/lib/python39.zip", "/usr/lib/python3.9", "/usr/lib/python3.9/lib-dynload", "/usr/local/lib/python3.9/dist-packages", "/usr/lib/python3/dist-packages"]}
PLAY RECAP *****************************************************************************************************************************************************************
django1.domain.com : ok=14 changed=1 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
Thanks in advance.
Q: "Nothing is printed out."
A: Register the output if you want to see it. For example
- hosts: localhost
tasks:
- command: echo $DJANGO_DEBUG
register: out
environment:
DJANGO_DEBUG: 0
- debug:
var: out.stdout
gives (abridged)
out.stdout: '0'
This should work for you. Step by step add the complexity to your code and isolate the problem. For example, the playbook below should display the environment at the remote host
- hosts: test_11
vars:
env:
DJANGO_DEBUG: 0
DJANGO_SITE_NAME: mysite
DJANGO_SITE_PASSWORD: mypassword
DJANGO_SITE_USER: myuser
DJANGO_SITE_ID: 2
tasks:
- shell: env | grep DJANGO_
register: out
environment: "{{ env }}"
- debug:
var: out.stdout

Ansible: Copying files from local to remote - "AttributeError: 'dict' object has no attribute 'endswith'"

I am trying to copy files (scripts and rpms) stored locally to a set of servers. I can copy the files when the names are hard coded, but not when I am using a variable.
ansible-lint comes back with no errors.
When use variable replacement I get the error:
TASK [Copy cpu_gov.sh]
***************************************************************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: AttributeError: 'dict' object has no attribute 'endswith'
fatal: [ceph3]: FAILED! => {"msg": "Unexpected failure during module execution.", "stdout": ""}
In debug mode I can see that it is a Python error on a trailing "/". All other uses of the variable work fine, only when it is in the ""src:" field does it fail.
The full traceback is:
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/ansible/executor/task_executor.py", line 145, in run
res = self._execute()
File "/usr/lib/python2.7/site-packages/ansible/executor/task_executor.py", line 650, in _execute
result = self._handler.run(task_vars=variables)
File "/usr/lib/python2.7/site-packages/ansible/plugins/action/copy.py", line 461, in run
trailing_slash = source.endswith(os.path.sep)
AttributeError: 'dict' object has no attribute 'endswith'
fatal: [ceph3]: FAILED! => {
"msg": "Unexpected failure during module execution.",
"stdout": ""
}
---
### Test
#
- hosts: all
vars:
#isdct_rpm: foobar.txt
isdct_rpm: isdct-3.0.16-1.x86_64.rpm
cpu_gov: cpu_gov.sh
irq_bal: irq_balance.sh
root_dir: /root
bin_dir: /root/bin
files_dir: /root/projects/ansible/bootstrap/files
remote_user: root
tasks:
These work just fine -
- name: ISDCT rpm exists?
stat:
path: "{{ root_dir }}/{{ isdct_rpm }}"
register: isdct_rpm
tags:
- tools
- name: cpu_gov exists?
stat:
path: "{{ bin_dir }}/{{ cpu_gov }}"
register: cpu_gov
tags:
- tools
- name: irq_balance exists?
stat:
path: "{{ bin_dir }}/{{ irq_bal }}"
register: irq_bal
tags:
- tools
The first task is the failing one:
- name: Copy ISDCT rpm
copy:
remote_src: no
src: "{{ isdct_rpm }}"
dest: "{{ root_dir }}"
when: not isdct_rpm.stat.exists
These work fine:
- name: Copy rpm
copy:
remote_src: no
src: isdct-3.0.16-1.x86_64.rpm
dest: /root
when: not isdct_rpm.stat.exists
- name: Copy cpu_gov.sh
copy:
remote_src: no
src: cpu_gov.sh
# - fails - src: "{{ cpu_gov }}"
dest: "{{ bin_dir }}"
when: not cpu_gov.stat.exists
- name: Copy irq_balance.sh
copy:
remote_src: no
src: irq_balance.sh
dest: /root
when: not irq_bal.stat.exists
The full traceback is:
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/ansible/executor/task_executor.py", line 145, in run
res = self._execute()
File "/usr/lib/python2.7/site-packages/ansible/executor/task_executor.py", line 650, in _execute
result = self._handler.run(task_vars=variables)
File "/usr/lib/python2.7/site-packages/ansible/plugins/action/copy.py", line 461, in run
trailing_slash = source.endswith(os.path.sep)
AttributeError: 'dict' object has no attribute 'endswith'
fatal: [ceph3]: FAILED! => {
"msg": "Unexpected failure during module execution.",
"stdout": ""
}
You have a variable in your vars section named isdct_rpm which is a string, but you're registering a dictionary variable with the same name in your ISDCT rpm exists? task. This overrides the string value.
Stop trying to use the same variable name for two different purposes and I suspect things will work as expected.
#larsks Answered my question. I was using the same name for my variable and the register value.
This works:
#
###--- Copy the scripts over if needed
#
- name: Copy ISDCT rpm
copy:
remote_src: no
src: "{{ isdct_rpm }}"
dest: "{{ root_dir }}"
when: not isdctrpm.stat.exists
- name: Copy cpu_gov.sh
copy:
remote_src: no
#src: cpu_gov.sh
src: "{{ cpu_gov }}"
dest: "{{ bin_dir }}"
when: not cpugov.stat.exists
- name: Copy irq_balance.sh
copy:
remote_src: no
src: "{{ irq_bal }}"
dest: "{{ bin_dir }}"
when: not irqbal.stat.exists

Ansible pamd: module failure

i have this playbook as a part of a role that do some changes in pam modules :
---
- name: "{{ BANNER}} - SET MODE"
copy:
remote_src: True
src: "{{ LOGIN_DEF }}"
dest: "{{ LOGIN_DEF_BCK }}_RH7-021_{{ CK_ORA }}"
replace:
path: "{{ LOGIN_DEF }}"
regexp: '{{ item.src }}'
replace: '{{ item.dst }}'
with_items:
- { src: '(.*FAIL_DELAY.*)', dst: '#\1' }
lineinfile:
path: "{{ LOGIN_DEF }}"
line: 'FAIL_DELAY 10'
replace:
path: "{{ PASSWORDAUTH }}"
regexp: '{{ item.src }}'
replace: '{{ item.dst }}'
with_items:
- { src: '^auth .* pam_faildelay.so', dst: '' }
pamd:
name: password-auth
type: auth
control: sufficient
module_path: 'pam_unix.so'
new_type: auth
new_control: optional
new_module_path: 'pam_faildelay.so'
module_arguments:
state: after
replace:
path: "{{ SYSTEMAUTH }}"
regexp: '{{ item.src }}'
replace: '{{ item.dst }}'
with_items:
- { src: '^auth .* pam_faildelay.so', dst: '' }
pamd:
name: system-auth
type: auth
control: sufficient
module_path: 'pam_unix.so'
new_type: auth
new_control: optional
new_module_path: 'pam_faildelay.so'
module_arguments:
state: after
debug: msg="{{ MSG_SET }}"
When i run i have this error :
TASK [RH7-021 : pamd] ***********************************************************************************************************************************************
fatal: [10.13.203.165]: FAILED! => {"changed": false, "module_stderr": "", "module_stdout": "\r\nTraceback (most recent call last):\r\n
File \"/home/ccansible/.ansible/tmp/ansible-tmp-1561986679.75-245340126875212/AnsiballZ_pamd.py\", line 113, in <module>\r\n _ansiballz_main()\r\n
File \"/home/ccansible/.ansible/tmp/ansible-tmp-1561986679.75-245340126875212/AnsiballZ_pamd.py\", line 105, in _ansiballz_main\r\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n
File \"/home/ccansible/.ansible/tmp/ansible-tmp-1561986679.75-245340126875212/AnsiballZ_pamd.py\", line 48, in invoke_module\r\n imp.load_module('__main__', mod, module, MOD_DESC)\r\n
File \"/tmp/ansible_pamd_payload_NpycuP/__main__.py\", line 880, in <module>\r\n File \"/tmp/ansible_pamd_payload_NpycuP/__main__.py\", line 816, in main\r\n File \"/tmp/ansible_pamd_payload_NpycuP/__main__.py\", line 458, in __init__\r\n
File \"/tmp/ansible_pamd_payload_NpycuP/__main__.py\", line 371, in rule_from_string\r\n
AttributeError: 'NoneType' object has no attribute 'group'\r\n",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}
to retry, use: --limit #/home/PG005856/HARDENING/main.retry
I can't figure it out what's wrong morover i used the same method on other playbook at it worked fine.
The control node has this ansible version :
ansible 2.7.6
config file = /home/PG005856/HARDENING/ansible.cfg
configured module search path = [u'/home/PG005856/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /ansible/lib/python2.7/site-packages/ansible
executable location = /ansible/bin/ansible
python version = 2.7.5 (default, Feb 20 2018, 09:19:12) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)]
Thr target server is :
Linux rh7-test-ansible 3.10.0-693.17.1.el7.x86_64 #1 SMP Sun Jan 14 10:36:03 EST 2018 x86_64 x86_64 x86_64 GNU/Linux
cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.4 (Maipo)
I have read that was a bug but i could imagined that with ansible version 2.7 was resolved.
I don't know what to do i could archieve the same result with some lines of sed with shell module but i'd like to use the pamd: module.

"Error reading package header" when using the Ansible yum install module

I have an ansible script that looks like this, and it was working properly yesterday -
- name: Dockerfile
hosts: localhost
connection: local
tasks:
- name: Install repositories packages
yum:
name: "{{ item }}"
state: present
with_items:
- https://centos7.iuscommunity.org/ius-release.rpm
- http://download.gluster.org/pub/gluster/glusterfs/3.7/3.7.10/CentOS/glusterfs-epel.repo
However this morning when I ran it, I got the following error -
failed: [localhost] (item=[u'https://centos7.iuscommunity.org/ius-release.rpm', u'http://download.gluster.org/pub/gluster/glusterfs/3.7/3.7.10/CentOS/glusterfs-epel.repo']) => {"failed": true, "invocation": {"module_name": "yum"}, "item": ["https://centos7.iuscommunity.org/ius-release.rpm", "http://download.gluster.org/pub/gluster/glusterfs/3.7/3.7.10/CentOS/glusterfs-epel.repo"], "module_stderr": "Traceback (most recent call last):\n File \"/tmp/ansible_mdVzzz/ansible_module_yum.py\", line 1064, in <module>\n main()\n File \"/tmp/ansible_mdVzzz/ansible_module_yum.py\", line 1053, in main\n disablerepo, disable_gpg_check, exclude, repoquery)\n File \"/tmp/ansible_mdVzzz/ansible_module_yum.py\", line 969, in ensure\n res = install(module, pkgs, repoq, yum_basecmd, conf_file, en_repos, dis_repos)\n File \"/tmp/ansible_mdVzzz/ansible_module_yum.py\", line 595, in install\n pkg_name = local_name(module, package)\n File \"/tmp/ansible_mdVzzz/ansible_module_yum.py\", line 492, in local_name\n header = ts.hdrFromFdno(fd)\n File \"/usr/lib64/python2.7/site-packages/rpm/transaction.py\", line 160, in hdrFromFdno\n raise rpm.error(\"error reading package header\")\n_rpm.error: error reading package header\n", "module_stdout": "", "msg": "MODULE FAILURE", "parsed": false}
The actual error description is
raise rpm.error(\"error reading package header\")\n_rpm.error: error reading package header\n", "module_stdout": "", "msg": "MODULE FAILURE", "parsed": false}
Did I break something? Or is this more of an issue with the gluster RPM?
Did you try this one:
- name: Install repositories packages
yum:
name: "{{ item }}"
state: present
with_items:
- https://centos7.iuscommunity.org/ius-release.rpm
- name: Install the gluster repo
get_url:
url: "http://download.gluster.org/pub/gluster/glusterfs/3.7/3.7.10/CentOS/glusterfs-epel.repo"
dest: "/etc/yum.repos.d/glusterfs-epel.repo"
mode: 0644

Ansible: `RequirementParseError` when feeding a variable to `pip: name=pkg version="{{ v }}"`

When I have this role:
# playbooks/roles/ansible/tasks/main.yml
- name: Install Ansible
pip:
state: present
name: ansible
version: "{{ ansible_version }}"
# playbooks/roles/ansible/defaults/main.yml
ansible_version: 1.9.4
I get this error while running ansible-playbook version 1.9.4 or 2.0.0.2:
TASK: [ansible | Install Ansible] *********************************************
failed: [localhost] => {"cmd": "/usr/local/bin/pip install ansible=={'major': 1, 'full': '1.9.4', 'string': '1.9.4\\n configured module search path = None', 'minor': 9, 'revision': 4}", "failed": true}
msg:
:stderr: Invalid requirement: 'ansible=={major:'
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/pip/req/req_install.py", line 73, in __init__
req = pkg_resources.Requirement.parse(req)
File "/usr/local/lib/python2.7/dist-packages/pip/_vendor/pkg_resources/__init__.py", line 3036, in parse
req, = parse_requirements(s)
File "/usr/local/lib/python2.7/dist-packages/pip/_vendor/pkg_resources/__init__.py", line 2980, in parse_requirements
"version spec")
File "/usr/local/lib/python2.7/dist-packages/pip/_vendor/pkg_resources/__init__.py", line 2945, in scan_list
raise RequirementParseError(msg, line, "at", line[p:])
RequirementParseError: Expected version spec in ansible=={major: at =={major:
This is the playbook:
- name: Install Sensu
serial: "100%"
hosts: all
sudo: yes
roles:
- role: "ansible-pull"
server_type: "sensu"
ansible_version: "2"
Where the ansible-pull role depends on the ansible role in meta/main.yml.
Am I injecting the variable incorrectly in this case? Is there some problem with setting the variable in the dependent ansible-pull roll rather than directly in the ansible role?
It turns out that ansible_version is a magic variable set by Ansible.
Who knew?
Using an arbitrarily different but unused variable name does the trick.

Resources