I get this error message when running a playbook locally and I cannot figure out why.
fatal: [localhost]: FAILED! =>
msg: |-
The task includes an option with an undefined variable. The error was: /home/{{ new_user }}/.nvs: {{ ansible_user }}: 'ansible_user' is undefined
The error appears to be in '/home/sturm/ansible-dotfiles/playbooks/prephome.yml': line 127, column 7, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: Clone the NVS repo
^ here
Here's the relevant part of the playbook:
# playbooks/prephome.yml
- hosts: all
gather_facts: true
vars_files:
- ../inventories/group_vars/all/vars.yml
tasks:
- name: Clone the NVS repo
ansible.builtin.git:
repo: https://github.com/jasongin/nvs
dest: "{{ nvs_home }}"
version: v1.6.0
And the relevant portion of the variables file:
# inventories/group_vars/all/vars.yml
new_user: "{{ ansible_user }}"
nvs_home: "/home/{{ new_user }}/.nvs"
I thought ansible_user was a built-in variable that always had a value. How can it possibly be 'undefined?'
I've seen other issues talk about how they cannot use ansible_user if their task has become_user in it, but this task clearly does not. So what else could be the problem?
EDIT: I guess I should also note that, when running the playbook, I use the command:
ansible-playbook -K -i "localhost," -c local ./playbooks/prephome.yml
EDIT 2: It might help to see repository from which this problem stems.
TL;DR: I changed the playbook command to:
ansible-playbook -K ./playbooks/prephome.yml
Having a discussion with Jack made me realize that the -i "localhost," -c local portion of the command was not only unnecessary—because I only have a 'localhost' in the inventory—but it was somehow causing the playbook to not see the group_vars files and not set the ansible_user var.
I still don't know the exact reason for it—my money is on the -c local argument. I would certainly be interested as to why removing those arguments from the playbook command suddenly makes the playbook run flawlessly.
Related
I have a playbook that runs correctly when used with ansible-playbook.
It contains an encrypted variable. According to the manual https://docs.ansible.com/ansible/latest/user_guide/vault.html#id16, I can view the variable with
$ ansible localhost -m ansible.builtin.debug -a var="ansible_value" -e
"'debug_playbook.yml" --vault-password-file=./pw_file
But I get an error of
ERROR! failed at splitting arguments, either an unbalanced jinja2 block or quotes: 'debug_playbook.yml
As the playbook itself runs, presumably its syntax is correct.
The playbook is
- name: Run a series of debug tasks to see the value of variables
hosts: localhost
vars:
ansible_password: vault |
$ANSIBLE_VAULT;1.1;AES256
63343064633966653833383264346638303466663265363566643062623436383364376639636630
3032653839323831316361613138333999999999999999999a313439383536353737616334326636
63616162323230333635663364643935383330623637633239626632626539656434333434316631
3965373931643338370a393530323165393762656264306130386561376362353863303232346462
3039
user: myuser
tasks:
- name: show env variable HOME and LOGNAME
debug:
msg: "environment variable {{ item }}"
with_items:
- "{{ lookup('env','HOME') }}"
- "{{ lookup('env','LOGNAME') }}"
- name: now show all of the variables for the current managed machine
debug:
msg: "{{ hostvars[inventory_hostname] }}"
- name: now show all of the hosts in the group from inventory file
debug:
msg: "server {{ item }}"
with_items:
- "{{ groups.mintServers }}"
- "{{ groups.centosServers }}"
I have googled the error and nothing jumps out (to me anyway). Is the manual correct? I have seen other methods where the encrypted variable is echoed into ansible-vault decrypt but it is all a bit of a bother.
I have yamllint'd the playbook. So interested to know what the error means and a way of debugging.
Regards
Following my comments: you cannot view an encrypted var inside a playbook with the technique proposed in the documentation, for memory:
ansible localhost -m debug -a "var=your_var" \
-e #your_file.yml --ask-vault-password
This will only work if your file is a "simple" var file where the top level element is a dictionary.
What I have done in the past is use the yq command line tool (which is a wrapper above jq) that you can easily install with pip install yq. (Note that jq needs to be installed separately and is available in most linux distribution channels. On ubuntu: apt install jq).
Once the prerequisites are available you can use yq to extract the var from you playbook and decrypt it with ansible-vault directly.
For this to work, you will still need to fix your var value which is not a valid vault definition as it misses a question mark in front of the vault marker:
vars:
ansible_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
63343064633966653833383264346638303466663265363566643062623436383364376639636630
3032653839323831316361613138333999999999999999999a313439383536353737616334326636
63616162323230333635663364643935383330623637633239626632626539656434333434316631
3965373931643338370a393530323165393762656264306130386561376362353863303232346462
3039
The solution is not so trivial as yq will get the vault value adding some garbage white-space and new line at the end that will make ansible-vault literally freak out. With your above fixed playbook example, this would give:
yq -r '.[0].vars.ansible_password|rtrimstr(" \n")' your_playbook.yaml \
| ansible-vault decrypt --ask-vault-pass
This is driving me crazy. My playbook looks as follows:
---
- hosts: all
become_user: root
become_method: sudo
become: yes
vars:
ansible_become_password: "{{ ansible_password }}"
ansible_password is a variable that is supposed to be populated by Ansible Tower / AWX. But I am getting below error message:
fatal: [RHEL8]: FAILED! => {"msg": "The field 'become_pass' has an invalid
value, which includes an undefined variable. The error was: 'ansible_password' is undefined"}
It tells me that ansible_password is undefined. But if I a hardcode the password there and log ansible_password at the end of the playbook execution, i see that ansible_password is well defined. So, it seems like ansible_password is only defined in the scope of tasks.
Anybody has experience with this? What would be the way around this issue?
This error occurs if you don't provide ansible_password variable,
if you run ansible using ansible-playbook command pass ansible_password as argument to your command :
ansible-playbook test.yml -i host.ini -e "ansible_password=YourPassword"
or add it to your host.ini file like:
[all]
0.0.0.0
[all:vars]
ansible_password=YourPassword
or if you use AWX, add this variable to your extra variables:
That should work.
Good luck!
I trying to create a simple paybook with a common role. Unfortunately I get stymied by ansible. I have looked up and down the internet for solution for this error.
The setup:
I am running ansible 2.7.4 on Ubuntu 18.04
directory structure:
~/Ansible_Do
playbook.yml
inventory (hosts file)
/roles
/common
/defaults
main.yml (other variables)
/tasks
main.yml
richard_e.yml
/vars
vars_and_stuff.yml (vault)
I have a simple playbook.yml
---
# My playbook 1
- hosts: test
- name: Go to common role to run tasks.
roles:
- common
tasks:
- name: echo something
shell: echo $(ip addr | grep inet)
...
I run this command to start the playbook:
~/Ansible_Do$ ansible-playbook -vv --vault-id #prompt -i ~/Ansible_Do/inventory playbook.yml
I enter the vault password continuing the playbook.
The playbook starts pulls facts from the test group of servers. Then reads the role and works to /roles/common. That calls the /common/tasks/main.yml file. This is where the error happens.
The error appears to have been in '/home/~/Ansible_Do/roles/common/tasks/main.yml': line 8, column 3
# Common/tasks file
---
- name: Bring variable from vault
include_vars:
file: vars_and_stuff.yml
name: My_password
- name: Super Richard <====== Error
become: yes
vars:
ansible_become_pass: "{{ My_password }}"
- import_tasks: ./roles/common/tasks/ricahrd_e.yml
...
The ./roles/common/tasks/ricahrd_e.yml is a simple testing task.
---
- name: say hi
debug:
msg: "Active server."
...
The error on "- name". I have checked online and in the Ansible docs to see if there is a key I'm missing. I found an example for include_vars in a /role/tasks (https://gist.github.com/halberom/ef3ea6d6764e929923b0888740e05211) showing proper syntax (I presume) in a simple role. The code works as parts, but not together.
I have reached what I can understand. I feel that is error is utterly simple and I am missing something (forest for the trees).
The error means exactly what it says, except the "module name" is not misspelled in your case, but missing altogether.
This...
- name: Super Richard <====== Error
become: yes
vars:
ansible_become_pass: "{{ My_password }}"
... is not a valid task definition, it does not declare an action.
An action in Ansible is a call to a module, hence "misspelled module name".
The error comes after name, because that's where Ansible expects the name of the "module" that you want to call, e.g. shell in your first example.
You are probably assuming that become is a "module", but it is not.
It is a "playbook keyword", in this case applied on the task level, which has the effect that you become another user for this task only.
But as the task has no action, you get this error.
See docs:
Playbook keywords
Understanding privilege escalation
After a bit of work I got the playbook to work. Knowing that 'become' is not a task was the start. I also found out how to pull the proper vars from the vault.
# My first playbook 1
- hosts: test
become: yes
vars_files:
- ./roles/common/vars/vars_and_stuff.yml
vars:
ansible_become_pass: "{{ My_password }}"
roles:
- common
tasks:
- name: echo something
shell: echo $(ip addr | grep inet)
The vars file access the vault and then vars: pulls the password used by become. With become in force I ran the other tasks in the common role with a last standalone task. Lastly, don't try to - name: at the top level of the playbook as it trigger a hosts undefined error.
I have an ansible-playbook and when i try to run this playbook i am getting this error
(specified line no longer in file, maybe it changed?)
--
- name: check if the public/private key exist at ~/.ssh/
stat:
path: /root/.ssh/id_rsa.pub
register: st
- name: run the command
command: cat /root/.ssh/id_rsa.pub|ssh -i /root/.ssh/bi_ppc.pem ubuntu#"{{items}" "cat >> .ssh/authorized_keys"
with_items:
- groups['ubuntu']
when: st.changed
~
ansible --version
ansible 2.2.0.0
config file = /home/swathi/Desktop/infrastructure/ansible.cfg
configured module search path = Default w/o overrides
You can use authorized_key module, copy pub key from local to remote.
--
- name: get public key
local_action: shell cat /home/user/.ssh/id_rsa.pub
register: pubkey
- name: check keys
debug: msg="{{ pubkey.stdout }}"
- name: add public key on the remote server
authorized_key: user=root key="{{ item[0] }}"
delegate_to: "{{ item[1] }}"
with_nested:
- "{{ pubkey.stdout }}"
- "{{groups['ubuntu']}}"
I faced the same error message from ansible:
$ ansible-playbook t.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
ERROR! Syntax Error while loading YAML.
found unexpected end of stream
The error appears to be in '/root/ansible/t.yml': line 6, column 1, but may
be elsewhere in the file depending on the exact syntax problem.
(specified line no longer in file, maybe it changed?)
The playbook is:
$ cat t.yml
---
- hosts: localhost
tasks:
- debug:
msg: "unterminated quoted string
In fact there is a YAML syntax error, at the end of the playbook missing a double quote. As it finish the playbook my editor doesn't help me by showing a different color.
Hope that will help someone else.
I know accessing Ansible facts is well documented, but I can't get this code to work.
# site.yml
---
- name: get fact
hosts: webservers
tasks:
- debug: msg="{{ hostvars['web01.example.com']['ansible_all_ipv4_addresses'] }}"
- fail:
When I run it, I get this error:
fatal: [web01.example.com] => One or more undefined variables: 'dict object' has no attribute 'ansible_all_ipv4_addresses'
Yet when I run the command "ansible -i inventory -m setup", I do see the dictionary key:
web01.example.com | success >> {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"<ip_address>"
],
(other objects...)
}
}
This is my inventory file:
# inventory
[webservers]
web01.example.com ansible_host=<ip_address>
I also tried the following hostvars setting but I get the same error:
hostvars['web01.example.com']['ansible_facts']['ansible_all_ipv4_addresses']
What am I doing wrong here? It seems like this should be pretty easy.
It is a little confusing with ansible, but you just use (without ansible_facts in the middle):
hostvars['web01.example.com']['ansible_all_ipv4_addresses']
Or as #oley posted
hostvars[inventory_hostname]['ansible_all_ipv4_addresses']
for the respective host in a task
In documentation you posted it is also always without ansible_facts in the middle, but it is just easy to overlook :)
This should do the trick:
- debug: msg="{{ hostvars[inventory_hostname]['ansible_all_ipv4_addresses'] }}"