While provisioning via Vagrant and Ansible I keep running into this issue.
TASK [postgresql : Create extensions] ******************************************
failed: [myapp] (item=postgresql_extensions) => {"changed": true, "cmd": "psql myapp -c 'CREATE EXTENSION IF NOT EXISTS postgresql_extensions;'", "delta": "0:00:00.037786", "end": "2017-04-01 08:37:34.805325", "failed": true, "item": "postgresql_extensions", "rc": 1, "start": "2017-04-01 08:37:34.767539", "stderr": "ERROR: could not open extension control file \"/usr/share/postgresql/9.3/extension/postgresql_extensions.control\": No such file or directory", "stdout": "", "stdout_lines": [], "warnings": []}
I'm using a railsbox.io generated playbook.
Turns out that railsbox.io is still using a deprecated syntax in the task.
- name: Create extensions
sudo_user: '{{ postgresql_admin_user }}'
shell: "psql {{ postgresql_db_name }} -c 'CREATE EXTENSION IF NOT EXISTS {{ item }};'"
with_items: postgresql_extensions
when: postgresql_extensions
The last line should use full jinja2 syntax.
when: '{{postgresql_extensions}}'
Related
Team,
Works locally on my laptop manually but fails only when calling via ansible. Is ansible looking at it in different shell? I have ansible controller as MAC book.
I am trying to store the path of a binary in register variable but shell command is not executing.
- name: "Find kubectl binary"
register: kubectl_path
shell: which kubectl
args:
executable: /bin/bash
output:
TASK [Find kubectl binary] ***************************************************************************************************************
fatal: [target1]: FAILED! => {"changed": true, "cmd": "which kubectl", "delta": "0:00:00.007541", "end": "2019-10-01 17:17:45.515963", "msg": "non-zero return code", "rc": 1, "start": "2019-10-01 17:17:45.508422", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
To disable logins for root I would like to set its shell to the path of nologin, which is determined by a command.
The command module registers the variable properly:
- name: Get nologin path
command: which nologin
register: nologin
- debug:
var: nologin
Debug info:
ok: [192.168.178.25] => {
"nologin": {
"changed": true,
"cmd": [
"which",
"nologin"
],
"delta": "0:00:00.001612",
"end": "2019-08-26 11:23:41.764847",
"failed": false,
"rc": 0,
"start": "2019-08-26 11:23:41.763235",
"stderr": "",
"stderr_lines": [],
"stdout": "/usr/sbin/nologin",
"stdout_lines": [
"/usr/sbin/nologin"
]
}
}
But when I use the user module it takes the registered variable as a string:
- name: Disable root
user:
name: root
shell: nologin.stdout
state: present
Result in /etc/passwd:
$ cat /etc/passwd
root:x:0:0:root:/root:nologin.stdout
Thanks for any help!
It's a variable, to use it you need to put in jinja2 template {{ }} and inside " " as it is required by YAML:
shell: "{{ nologin.stdout }}"
Ref:
https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#using-variables-with-jinja2
https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#hey-wait-a-yaml-gotcha
- name: Create directory for python files
file: path=/home/vuser/test/
state=directory
owner={{ user }}
group={{ user }}
mode=755
- name: Copy python file over
copy:
src=sample.py
dest=/home/vuser/test/sample.py
owner={{ user }}
group={{ user }}
mode=777
- name: Execute script
command: python sample.py
args:
chdir: /home/vuser/test/
ignore_errors: yes
error
fatal: [n]: FAILED! => {"changed": true, "cmd": ["python", "sample.py"], "delta": "0:00:00.003200", "end": "2019-07-18 13:57:40.213252", "msg": "non-zero return code", "rc": 1, "start": "2019-07-18 13:57:40.221132", "stderr": "", "stderr_lines": [], "stdout": "1", "stdout_lines": ["1"]}
not able to figure out, help would be appreciated
Change the indent like below and remove ignore_errors.
- name: Execute script
command: python sample.py
args:
chdir: /home/vuser/test/
register: cat_contents
- name: Print contents
debug:
msg: "{{ cat_contents.stdout }}"
- name: Create directory for python files
file: path=/home/vuser/test/
state=directory
owner={{ user }}
group={{ user }}
mode=755
- name: Copy python file over
copy:
src=/home/vuser/sample.py
dest=/home/vuser/test/
owner={{ user }}
group={{ user }}
mode=777
- name: Execute script
command: python sample.py
args:
chdir: /home/vuser/test/
The sample.py is copied correctly in the destination folder at the node1 at dest=/home/vuser/test/
but the I get this error after I have done the change also
fatal: [node1]: FAILED! => {"changed": true, "cmd": ["python", "sample.py"], "delta": "0:00:00.002113", "end": "2019-07-19 10:59:53.7535351", "msg": "non-zero return code", "rc": 1, "start": "2019-07-19 10:59:53.358678548", "stderr": "", "stderr_lines": [], "stdout": "hello world", "stdout_lines": ["hello world"]}
As new nodes (CentOS 7.6) are added, there are basic groups and users that need to be created. Some of the nodes have some of the groups and users. I would like to only create the groups and users on the nodes where they don't exist via my Ansible (version 2.8.0) basic role file.
Currently, I'm testing for the group/user, but the there's always a "fatal" printed and my conditionals don't appear to work.
roles/basic/tasks/main.yml
- name: "Does k8s group exist?"
shell: grep -q "^k8s" /etc/group
register: gexist
- name: "Create k8s group"
shell: groupadd -g 8000 k8s
when: gexist.rc != 0
- name: "Does k8s user exist?"
shell: id -u k8s > /dev/null 2>&1
register: uexist
- name: "Create k8s user"
shell: useradd -g 8000 -d /home/k8s -s /bin/bash -u 8000 -m k8s
when: uexist.rc != 0
which yields:
TASK [basic : Does k8s group exist?] *****************************************************************************************************************************
fatal: [master]: FAILED! => {"changed": true, "cmd": "grep -q \"^k8s:\" /etc/group", "delta": "0:00:00.009424", "end": "2019-05-29 14:42:17.947350", "msg": "non-zero return code", "rc": 1, "start": "2019-05-29 14:42:17.937926", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
fatal: [node3]: FAILED! => {"changed": true, "cmd": "grep -q \"^k8s:\" /etc/group", "delta": "0:00:00.012089", "end": "2019-05-29 06:41:36.661356", "msg": "non-zero return code", "rc": 1, "start": "2019-05-29 06:41:36.649267", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
fatal: [node1]: FAILED! => {"changed": true, "cmd": "grep -q \"^k8s:\" /etc/group", "delta": "0:00:00.010104", "end": "2019-05-29 14:42:17.990460", "msg": "non-zero return code", "rc": 1, "start": "2019-05-29 14:42:17.980356", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
changed: [node2]
There has got to be a better to do conditionals (if-then-else) than the way I'm doing it.
See user and group. The code below is probably what you're looking for.
- name: "Create k8s group"
group:
gid: 8000
name: k8s
- name: "Create k8s user"
user:
group: k8s
home: /home/k8s
shell: /bin/bash
uid: 8000
name: k8s
The only if-then-else in Ansible I'm aware of is the ternary filter (for other options see jinja). The control flow is rather poor in Ansible compared to other procedural languages. It's because of the code rather defines a state of the system then a procedure.
To answer your question:
How to do an Ansible condition test of user/group existence?
Your code does it correctly, but the purpose of Ansible is to define the state of the system. It's not important a user or group existed before or not. After successfully having run the code they will exist (definition of a state) and running the code again makes sure they still exist (audit).
I'm using with_items iterator to execute command: brew services stop {{ item }}.
To handle errors I'd like to use changed_when and use item value in it.
command: brew services stop {{ item }}
register: stop_services
changed_when:
- "'Error: Service `{{ item }}` is not started.' not in stop_services.stderr"
with_items:
- memcached
- kafka
If service is not started, I get following error
failed: [127.0.0.1] (item=memcached) => {"changed": false, "cmd": ["brew", "services", "stop", "memcached"], "delta": "0:00:00.464519", "end": "2016-12-29 18:02:37.795973", "failed": true, "item": "memcached", "rc": 1, "start": "2016-12-29 18:02:37.331454", "stderr": "Error: Service memcached is not started.", "stdout": "", "stdout_lines": [], "warnings": []}
But changed_when statement is ignored.
Is it possible to inject item into changed_when statement?
Ansible version: 2.2
You've got a failing task in the first place. The command module will report failure if the return code from the command was other than zero (in your case "rc": 1) and that's why your changed_when condition is not taken into consideration.
Add the following to prevent failing:
failed_when: false