Setting vars in ansible and using them as arguments - yaml

I want to set variables and use them as parameters later on. This is the code I have
---
- hosts: localhost
connection: local
vars:
vcenter_hostname: hellothere.hey.com
user: root
pass: ohheytherehowareyou
vars_prompt:
- name: 'vm_task_action'
prompt: 'Enter vm action to execute (none, delete)'
default: 'none'
private: no
- name: 'guest_vm'
prompt: "Enter the guest vm you want to delete"
default: 'none'
private: no
when: vm_task_action == "delete"
tasks:
- name: deleting VMs
vsphere_guest:
vcenter_hostname: vcenter_hostname
username: user
password: pass
guest: "{{ guest_vm }}"
state: absent
force: yes
when: vm_task_action == 'delete'
What is wrong with this code and how do I fix it. Any help would be greatly appreciated.

The Error says for itself:
'pass' is not a valid variable name
pass is a special keyword, so it can't be used as variable.
Use mypass: ohheytherehowareyou, for example.
P.S. also note that when: can't be used in vars_prompt section.

Related

Ansible: redefine variable value only if another variable defined

For some reasons I need from time to time run my playbook for same hosts with different users (different from hosts default ansible_user).
My problem is how to rewrite value of ansible_user and ansible_password **ONLY **if my temp vars from vars_prompt are defined. Instead it it should use host default ansible_user and ansible_password
I tried
- name: Some playbook
hosts: my_host_group
vars_prompt:
- name: custom_ssh_user
prompt: "Print SSH user login(Print blank if default)"
private: no
- name: custom_ssh_passw
prompt: "Print SSH user password(Print blank if default)"
private: yes
confirm: yes
unsafe: no
vars:
ansible_user: "{{ custom_ssh_user if custom_ssh_user|length > 0 else ansible_user }}"
ansible_password: "{{ custom_ssh_passw if custom_ssh_passw|length > 0 else ansible_password }}"
But this IF construct failed with error on loop defining vars when vars_prompt are empty.
How to do this defining properly?

Ansible - prompt for a confirmation to run tasks and share the fact by multiple hosts

I have this simple playbook named delete.yml
- hosts: all
become: false
tasks:
- pause:
prompt: "Are you sure you want to delete \" EVERYTHING \"? Please confirm with \"yes\". Abort with \"no\" or Ctrl+c and then \"a\""
register: confirm_delete
- set_fact:
confirm_delete_fact: "{{ confirm_delete.user_input | bool }}"
- hosts: all
become: false
roles:
- {role: destroy when: confirm_delete_fact }
my inventory is
[my_group]
192.168.10.10
192.168.10.11
192.168.10.12
so I run the playbook with
ansible-playbook delete.yml -i inventoryfile -l my_group
Everything works but only for one host, the others in my_group are skipped because of the conditional check
What is wrong?
you could try that:
- hosts: all
become: false
tasks:
- pause:
prompt: "Are you sure you want to delete \" EVERYTHING \"? Please confirm with \"yes\". Abort with \"no\" or Ctrl+c and then \"a\""
register: confirm_delete
- name: Register dummy host with variable
add_host:
name: "DUMMY_HOST"
confirm_delete_fact: "{{ confirm_delete.user_input | bool }}"
- hosts: all
become: false
vars:
confirm_delete_fact: "{{ hostvars['DUMMY_HOST']['confirm_delete_fact'] }}"
roles:
- {role: destroy when: confirm_delete_fact }
if you dont want error on DUMMY_HOST (try to connect ssh), just do
- hosts: all,!DUMMY_HOST
explanations:
if you put your prompt in task, it will be used one time and belongs to hostvars of the first host, so i create a new dummy host and pass variable to other playbook.
you could avoid that:
by putting the prompt over the tasks and testing the variable hostvars:
- hosts: all
become: false
vars_prompt:
- name: confirm_delete
prompt: "Are you sure you want to delete \" EVERYTHING \"? Please confirm with \"yes\". Abort with \"no\" or Ctrl+c and then \"a\""
private: no
default: no
tasks:
- set_fact:
confirm_delete_fact: "{{ confirm_delete | bool }}"
- hosts: all
become: false
roles:
- {role: destroy when: hostvars[inventory_hostname]['confirm_delete_fact'] }
you could use the second solution because, you have the same hosts in both playbook. If different, i suggest you to use the first solution.

How add hosts from user's input in a ansible playbook?

I need to add a host from the user's input. Now I'm trying to use the ansible in-memory inventory, add_host module and prompt to add the target host to execute the remaining tasks. This is the content of my playbook:
Deploy.yml
- name: Adding the host server
hosts: localhost
- vars_prompt:
- name: "Server IP"
prompt: "Server"
private: no
- name: "Username (default: Ubuntu)"
prompt: "User"
default: "Ubuntu"
private: no
- name: "Password"
prompt: "Passwd"
private: yes
encrypt: "sha512_crypt"
- name: "Identity file path"
prompt: "IdFile"
private: no
when: Passwd is undefined
tasks:
- name: Add host server
add_host:
name: "{{ Server }}"
ansible_ssh_user: "{{ User }}"
ansible_ssh_private_key_file: "{{ IdFile }}"
when: IdFile is defined
- name: Add host server
add_host:
name: "{{ Server }}"
ansible_ssh_user: "{{ User }}"
ansible_ssh_pass: "{{ Passwd }}"
when: Passwd is defined
- hosts: "{{ Server }}"
tasks:
- name: Copy the script file to the server
copy:
src: script.sh
dest: "{{ ansible_env.HOME }}/folder/"
mode: 755
force: yes
attr:
- +x
When I run this playbook with this command $ ansible-playbook Deploy.yml, The output is:
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [Adding the host server] ***********************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************
ok: [localhost]
Server: <server-ip>
User [Ubuntu]:
Passwd:
IdFile: <path/to/id/file>
ERROR! the field 'hosts' is required but was not set
I don't know why it throws this error:
ERROR! the field 'hosts' is required but was not set
How can I do what I need to do?
UPDATE:
It still not working. This is the content of my playbook:
Deploy.yml
- name: Adding the host server
hosts: localhost
vars_prompt:
- name: "Server"
prompt: "Server IP"
private: no
- name: "User"
prompt: "Username"
default: "Ubuntu"
private: no
- name: "Passwd"
prompt: "Password"
private: yes
encrypt: "sha512_crypt"
- name: "IdFile"
prompt: "Identity file path"
private: no
when: Passwd is undefined
tasks:
- name: Add host server
add_host:
name: "{{ Server }}"
ansible_ssh_user: "{{ User }}"
ansible_ssh_private_key_file: "{{ IdFile }}"
when: IdFile is defined
- name: Add host server
add_host:
name: "{{ Server }}"
ansible_ssh_user: "{{ User }}"
ansible_ssh_pass: "{{ Passwd }}"
when: IdFile is undefined
- hosts: "{{ Server }}"
tasks:
- name: Copy the script file to the server
copy:
src: script.sh
dest: "{{ ansible_env.HOME }}/folder/"
mode: 755
force: yes
attr:
- +x
When I run this playbook with this command $ ansible-playbook Deploy.yml, The output is:
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [Adding the host server] ***********************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************
ok: [localhost]
Server IP: <server-ip>
Username [Ubuntu]:
Password:
Identity file path: <path/to/id/file>
ERROR! the field 'hosts' is required but was not set
I don't know why it throws this error:
ERROR! The field 'hosts' has an invalid value, which includes an undefined variable. The error was: 'Server' is undefined
Here is a flowchart of how the playbook should works:
+------------------+ +---------------+ +-----------------+
|Use ansible to run| |Get host IP fom| |Get ssh User from|
| this playbook +---->+ user's input +---->+ user's input |
+------------------+ +---------------+ +--------+--------+
|
v
+------------+--------+
|Get ssh password from|
| user's input |
+------------+--------+
|
v
+---------------+ *************************
|Add a host with| Yes | Did the user inputted |
v----------+ password +<---+| a password? |
+----------------+ +---------------+ ***************+*********
||Run some tasks|| |No
||in recently || v
||added host || +---------------+ +------------+--------+
+----------------+ |Add a host with| |Get ssh identity file|
^----------+ identity file +<------+ from user's input |
+---------------+ +---------------------+
Ok I've updated my answer to suit the changes in your question, with the original answer left for historic reasons.
To solve the substitution error you are seeing, which results in an empty host list in your second play, I would instead use an inventory group.
There are also two other syntax errors in the second play
The file mode needs to be octal (i.e. 0700)
The attribute is invalid. My assumption is you are trying to make the file executable, so fix the file mode and remove the attribute.
Here is an updated playbook:
- name: Adding the host server
hosts: localhost
vars_prompt:
- name: "Server"
prompt: "Server IP"
private: no
- name: "User"
prompt: "Username"
default: "Ubuntu"
private: no
- name: "Passwd"
prompt: "Password"
private: yes
encrypt: "sha512_crypt"
- name: "IdFile"
prompt: "Identity file path"
private: no
when: Passwd is undefined
tasks:
- name: Add host server
add_host:
name: "{{ Server }}"
ansible_ssh_user: "{{ User }}"
ansible_ssh_private_key_file: "{{ IdFile }}"
group: added_hosts
when: IdFile is defined
- name: Add host server
add_host:
name: "{{ Server }}"
ansible_ssh_user: "{{ User }}"
ansible_ssh_pass: "{{ Passwd }}"
group: added_hosts
when: IdFile is undefined
- hosts: added_hosts
tasks:
- name: Copy the script file to the server
copy:
src: script.sh
dest: "{{ ansible_env.HOME }}/folder/"
mode: 0755
force: yes
=== OLD ANSWER ===
User input is stored in the whatever variable you are using for the name attribute in each of the variable prompts.
You need to switch around your name and prompt values under vars_prompt
There are also YAML formatting issues
For example:
- vars_prompt:
- name: "Server IP"
prompt: "Server"
private: no
should be:
vars_prompt:
- name: "server"
prompt: "Server IP"
private: no
Then you can refer to the {{ server }} variable in your tasks
Your ansible script is having a problem.
vars_prompt:
remove - from vars_prompt line it will work properly.
I tried in my local server the same script is working properly.
- name: Adding the host server
hosts: localhost
vars_prompt:
- name: "Server"
prompt: "Server IP"
private: no
- name: "User"
prompt: "Username"
default: "Ubuntu"
private: no
- name: "Passwd"
prompt: "Password"
private: yes
encrypt: "sha512_crypt"
- name: "IdFile"
prompt: "Identity file path"
private: no
when: Passwd is undefined
tasks:
- name: Add host server
add_host:
name: "{{ Server }}"
ansible_ssh_user: "{{ User }}"
ansible_ssh_private_key_file: "{{ IdFile }}"
when: IdFile is defined
- name: Add host server
add_host:
name: "{{ Server }}"
ansible_ssh_user: "{{ User }}"
ansible_ssh_pass: "{{ Passwd }}"
when: Passwd is defined
- name: Create a file
shell: touch newfile
delegate_to: "{{ Server }}"
In the last task update to your task and run it.
- name: Create a file
shell: touch newfile
delegate_to: "{{ Server }}"

How do i create a user (not hard-coded) to a pre-existing group and prompt the new user to enter his new password?

I am new to ansible and this is a project i am working on. so far the below code is what i put together. This code works however, the password does not register and when i log in with the new user i created. it says authentication failure. Please help
---
- hosts: box432
gather_facts: false
vars_prompt:
- name: 'creating user with password'
prompt: 'enter password for user'
private: yes
encrypt: sha512_crypt
confirm: yes
salt_size: 7
tasks:
- pause: prompt="enter user name"
register: user_name
- name: "Print"
debug: msg="{{ user_name }}"
- name: updating user password
become: true
user:
name: "{{ user_name }}"
state: present
groups: stackflow
Firstly, name in vars_prompt is not an arbitrary comment, but the name of the variable to be set, so this section should be:
vars_prompt:
- name: "provided_password"
prompt: "enter password for user"
private: yes
encrypt: sha512_crypt
confirm: yes
salt_size: 7
Secondly, in your code you are not even trying to use that variable. You should provide the value in the password argument:
- name: updating user password
become: true
user:
name: "{{ user_name }}"
password: "{{ provided_password }}"
state: present
groups: stackflow

How to delay running playbook?

I have a playbook which creates a virtual machine in vCenter. During creation the VM mounts iso image and installs OS automatically. After installation VM gets its IP address. I want to continue running playbook, but using the IP.
I read about wait_for, but I don't understand how to use it. Or maybe there is another way do it?
Playbook below:
- hosts: localhost
gather_facts: false
connection: local
user: ansible
become: true
vars_files:
- ../roles/vm-create/vars/default.yml
vars_prompt:
- name: "name_VM"
prompt: "VM name:"
private: no
default: "vm001"
- name: "vcenter_user"
prompt: "vCenter user"
private: no
default: "root"
- name: "vcenter_pass"
prompt: "Enter password vCenter"
private: yes
roles:
- vm-create
# waiting for the installation and gets ip (Do-Until Loops or wait_for)
- name: setting VM
become: true
hosts: '{{ get_ip }}'
roles:
- { role: ldap-client, tags: [ 'ldap' ] }
You don't show how you assign the get_ip variable, so I assume you can reference it. It's not straightforward, because you would have to either access it with hostvars['localhost']['get_ip]` or you should create a dynamic inventory.
Then you just need to use a very basic wait_for task, but because you want to assign a role to the machine, you need to define the task in the pre_tasks section.
Your second play should be:
- name: setting VM
become: true
hosts: '{{ get_ip }}'
pre_tasks:
- name: Ensure machine at {{ get_ip }} SSH port is listening
wait_for:
host: "{{ get_ip }}"
port: 22 # SSH port
delay: 60 # wait 1 minute before trying
roles:
- { role: ldap-client, tags: [ 'ldap' ] }

Resources