Ansible Router Template Generator - Trouble with vars_prompt [duplicate] - network-programming

I was trying to use vars_prompt in Ansible with default values taken from facts (or otherwise a previously defined variable). The playbook is intended be used as an ad-hoc one for initial provisioning.
My playbook:
---
- hosts: server01
gather_facts: True
vars_prompt:
- name: new_hostname
prompt: please enter the name for the target
default: "{{ ansible_hostname }}"
private: no
tasks:
- debug: msg="{{ new_hostname }}"
Current result:
please enter the name for the target [{{ ansible_hostname }}]:
ERROR! 'ansible_hostname' is undefined
Expected results (assuming ansible_hostname=server01:
please enter the name for the target [server01]:
Is it possible to achieve in Ansible?

This can be implemented using the pause module:
---
- hosts: server01
gather_facts: True
tasks:
- pause:
prompt: please enter the name for the target [{{ ansible_hostname }}]
register: prompt
- debug:
msg: "{{ prompt.user_input if prompt.user_input else ansible_hostname }}"

Related

Ansible known_hosts module ssh key propagation question

I'm trying to craft a playbook that will update the known_hosts for a machine / user however I'm getting an error I can't make sense of.
---
- name: Keys
hosts: adminslaves
gather_facts: false
no_log: false
remote_user: test
#pre_tasks:
# - setup:
# gather_subset:
# - '!all'
tasks:
- name: Scan for SSH host keys.
shell: ssh-keyscan myhost.mydomain.com 2>/dev/null
changed_when: False
register: ssh_scan
# - name: show vars
# debug:
# msg: "{{ ssh_scan.stdout_lines }}"
#
- name: Update known_hosts.
known_hosts:
key: "{{ item }}"
name: "{{ ansible_host }}"
state: present
with_items: "{{ ssh_scan.stdout_lines }}"
My error is "msg": "Host parameter does not match hashed host field in supplied key"}
I think the variable has the right information (at least it does when I debug it).
My end goal is a playbook that will add ssh keys of a list of hosts to a list of hosts for Jenkins auth.
Appreciate any help.
the problem is that the output of ssh-keyscan myhost.mydomain.com 2>/dev/null usually contains more than one key so you need to process it.
Someone with the same error message raised an issue, but again the problem was with the ssh-key format. I better understood checking the code used by known_hosts task.
Here the code I use:
- name: Populate known_hosts
hosts: spectrum_scale
tags: set_known_hosts
become: true
tasks:
- name: Scan for SSH keys
ansible.builtin.shell:
cmd: "ssh-keyscan {{ hostvars[spectrum_scale].ansible_fqdn }}
{{ hostvars[spectrum_scale].ansible_hostname }}
{{ hostvars[spectrum_scale].ansible_default_ipv4.address }}
2>/dev/null"
loop: "{{ groups['spectrum_scale'] }}"
loop_control:
loop_var: spectrum_scale
register: ssh_scan
- name: Set stdout_lines array for ssh_scan
set_fact:
ssout: []
- name: Fill ssout
set_fact:
ssout: "{{ ssout + ss_r.stdout_lines }}"
loop: "{{ ssh_scan.results }}"
loop_control:
loop_var:
ss_r
when: ss_r.stdout_lines is defined
- name: Add client ssh keys to known_hosts
ansible.builtin.known_hosts:
name: "{{ hk.split()[0] }}"
key: "{{ hk }}"
state: present
loop: "{{ ssout }}"
loop_control:
loop_var: hk

Ansible - Set environment path as inventory variable

Osmc media player needs a specific path for playbooks
https://github.com/osmc/osmc/issues/319
environment:
PATH: "{{ ansible_env.PATH }}:/sbin:/usr/sbin"
I was wondering whether I can set this as an environmental variable in the inventory for those machines, rather than have it in every playbook or create separate playbooks.
In common usage - is that path likely to cause problems for general *nix machines if it is implemented on non-osmc installations?
If you can't set this an an inventory variable:
Is that just because it's no implemented/ useful to most?
Or because the inventory has no relation to path - e.g. it's not invoked at that point?
Or is a better way for all of this to have it as a machine specific variable/ task in a role?
How would that look please?
New to ansible and still trying to get my head round some of the concepts.
As said, the environment keyword can be used only at task or playbook level.
You will be able to use an standard playbook just adding the following:
---
- name: Environment
hosts: localhost
connection: local
gather_facts: False
tasks:
- name: Setup
setup:
gather_subset:
- "!all"
or
---
- name: Environment
hosts: localhost
connection: local
gather_facts: True
gather_subset:
- "!all"
If you debug the variable:
---
- name: Environment
hosts: localhost
connection: local
gather_facts: False
tasks:
- name: Setup
setup:
gather_subset:
- "!all"
- name: Debug
debug:
var: ansible_env.PATH
You will get something like:
TASK [Setup] *******************************************************************************************************************************************************
ok: [localhost]
TASK [Debug] *******************************************************************************************************************************************************
ok: [localhost] => {
"ansible_env.PATH": "/Users/imjoseangel/source/venv/ansible/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
}
And what if you want to pass that variable to another play with different inventory?
Just do hostvars.localhost.ansible_env.PATH
- name: Environment2
hosts: windows
connection: local
gather_facts: False
tasks:
- name: Debug
debug:
var: hostvars.localhost.ansible_env.PATH
So the
environment:
PATH: "{{ ansible_env.PATH }}:/sbin:/usr/sbin"
Will be valid only with gather_facts or setup module under the defined inventory but you don't need to split playbooks.

Getting just volume id ansible

This has been answered before here on Stack.
ansible get aws ebs volume id which already exist
Get volume id from newly created ebs volume using ansible
For the life of me I am trying ec2_vol.volume_id and some other jmespath query bits but not getting the right output help. I just want the vol id. Nothing more.
---
- hosts: localhost
connection: local
gather_facts: no
tasks:
- name: get associated vols
ec2_vol:
instance: i-xxxxxxxxxxxxx
state: list
profile: default
region: us-east-1
register: ec2_vol
- debug:
msg: "{{ ec2_vol.volume_id }}"
also doesn't work
---
- hosts: localhost
connection: local
gather_facts: no
tasks:
- name: get associated vols
ec2_vol:
instance: i-xxxxxxxxxxxxxx
state: list
profile: default
region: us-east-1
register: ec2_vol
- debug: msg="{{ item.volume_id }}"
with_items: ec2_vol.results
Ansible 2.2 and 2.3 tested
Taking bits from the prior answer you will need to understand JMESPATH like filtering to get what you want out of the output.
Here is the answer
---
- hosts: localhost
connection: local
gather_facts: no
tasks:
- name: get associated vols
ec2_vol:
instance: i-xxxxxxxxxxxxxx
state: list
profile: default
region: us-east-1
register: ec2_vol
- debug: msg="{{ ec2_vol.volumes | map(attribute='id') | list }}"

Ansible - Include environment variables from external YML

I'm attempting to store all my environment variables in a file called variables.yml that looks like so:
---
doo: "external"
Then I have a playbook like so:
---
- hosts: localhost
tasks:
- name: "i can totally echo"
environment:
include: variables.yml
ugh: 'internal'
shell: echo "$doo vs $ugh"
register: results
- debug: msg="{{ results.stdout }}"
The result of the echo is ' vs internal'.
How can I change this so that the result is 'external vs internal'. Many thanks!
Assuming the external variable file called variables.ext is structured as follow
---
EXTERNAL:
DOO: "external"
than, according Setting the remote environment and Load variables from files, dynamically within a task a small test could look like
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: Load environment variables
include_vars:
file: variables.ext
- name: Echo variables
shell:
cmd: 'echo "${DOO} vs ${UGH}"'
environment:
DOO: "{{ EXTERNAL.DOO }}"
UGH: "internal"
register: result
- name: Show result
debug:
msg: "{{ result.stdout }}"
resulting into an output of
TASK [Show result] ********
ok: [localhost] =>
msg: external vs internal

Add swap memory with ansible

I'm working on a project where having swap memory on my servers is a needed to avoid some python long running processes to go out of memory and realized for the first time that my ubuntu vagrant boxes and AWS ubuntu instances didn't already have one set up.
In https://github.com/ansible/ansible/issues/5241 a possible built in solution was discussed but never implemented, so I'm guessing this should be a pretty common task to automatize.
How would you set up a file based swap memory with ansible in an idempotent way? What modules or variables does ansible provide help with this setup (like ansible_swaptotal_mb variable) ?
This is my current solution:
- name: Create swap file
command: dd if=/dev/zero of={{ swap_file_path }} bs=1024 count={{ swap_file_size_mb }}k
creates="{{ swap_file_path }}"
tags:
- swap.file.create
- name: Change swap file permissions
file: path="{{ swap_file_path }}"
owner=root
group=root
mode=0600
tags:
- swap.file.permissions
- name: "Check swap file type"
command: file {{ swap_file_path }}
register: swapfile
tags:
- swap.file.mkswap
- name: Make swap file
command: "sudo mkswap {{ swap_file_path }}"
when: swapfile.stdout.find('swap file') == -1
tags:
- swap.file.mkswap
- name: Write swap entry in fstab
mount: name=none
src={{ swap_file_path }}
fstype=swap
opts=sw
passno=0
dump=0
state=present
tags:
- swap.fstab
- name: Mount swap
command: "swapon {{ swap_file_path }}"
when: ansible_swaptotal_mb < 1
tags:
- swap.file.swapon
I tried the answer above but "Check swap file type" always came back as changed and therefore isn't idempotent which is encouraged as a best practice when writing Ansible tasks.
The role below has been tested on Ubuntu 14.04 Trusty and doesn't require gather_facts to be enabled.
- name: Set swap_file variable
set_fact:
swap_file: "{{swap_file_path}}"
tags:
- swap.set.file.path
- name: Check if swap file exists
stat:
path: "{{swap_file}}"
register: swap_file_check
tags:
- swap.file.check
- name: Create swap file
command: fallocate -l {{swap_file_size}} {{swap_file}}
when: not swap_file_check.stat.exists
tags:
- swap.file.create
- name: Change swap file permissions
file: path="{{swap_file}}"
owner=root
group=root
mode=0600
tags:
- swap.file.permissions
- name: Format swap file
sudo: yes
command: "mkswap {{swap_file}}"
when: not swap_file_check.stat.exists
tags:
- swap.file.mkswap
- name: Write swap entry in fstab
mount: name=none
src={{swap_file}}
fstype=swap
opts=sw
passno=0
dump=0
state=present
tags:
- swap.fstab
- name: Turn on swap
sudo: yes
command: swapon -a
when: not swap_file_check.stat.exists
tags:
- swap.turn.on
- name: Set swappiness
sudo: yes
sysctl:
name: vm.swappiness
value: "{{swappiness}}"
tags:
- swap.set.swappiness
As of Ansible 2.9, sudo declarations should be become:
- name: Set swap_file variable
set_fact:
swap_file: "{{swap_file_path}}"
tags:
- swap.set.file.path
- name: Check if swap file exists
stat:
path: "{{swap_file}}"
register: swap_file_check
tags:
- swap.file.check
- name: Create swap file
command: fallocate -l {{swap_file_size}} {{swap_file}}
when: not swap_file_check.stat.exists
tags:
- swap.file.create
- name: Change swap file permissions
file: path="{{swap_file}}"
owner=root
group=root
mode=0600
tags:
- swap.file.permissions
- name: Format swap file
become: yes
command: "mkswap {{swap_file}}"
when: not swap_file_check.stat.exists
tags:
- swap.file.mkswap
- name: Write swap entry in fstab
mount: name=none
src={{swap_file}}
fstype=swap
opts=sw
passno=0
dump=0
state=present
tags:
- swap.fstab
- name: Turn on swap
become: yes
command: swapon -a
when: not swap_file_check.stat.exists
tags:
- swap.turn.on
- name: Set swappiness
become: yes
sysctl:
name: vm.swappiness
value: "{{swappiness}}"
tags:
- swap.set.swappiness
Vars required:
swap_file_path: /swapfile
# Use any of the following suffixes
# c=1
# w=2
# b=512
# kB=1000
# K=1024
# MB=1000*1000
# M=1024*1024
# xM=M
# GB=1000*1000*1000
# G=1024*1024*1024
swap_file_size: 4G
swappiness: 1
I based my take on the great Ashley's answer (please upvote it!) and added the following extra features:
global flag to manage the swap or not,
allow changing the swap size,
allow disabling swap,
...plus these technical improvements:
full idempotency (only ok & skipping when nothing is changed, otherwise some changed),
use dd instead of fallocate for compatibility with XFS fs (see this answer for more info),
Limitations:
changes the existing swapfile works correctly only if you provide its path as swap_file_path.
Tested on Centos 7.7 with Ansible 2.9 and Rocky 8 with Ansible
4.8.0.
Requires using privilege escalation as many of the commands need to run as root. (The easiest way to do it is to add --become to ansible-playbook arguments or to set the appropriate value in your ansible.cfg).
Parameters:
swap_configure: true # or false
swap_enable: true # or false
swap_file_path: /swapfile
swap_file_size_mb: 4096
swappiness: 1
Code:
- name: Configure swap
when: swap_configure | bool
block:
- name: Check if swap file exists
stat:
path: "{{swap_file_path}}"
get_checksum: false
get_md5: false
register: swap_file_check
changed_when: false
- name: Set variable for existing swap file size
set_fact:
swap_file_existing_size_mb: "{{ (swap_file_check.stat.size / 1024 / 1024) | int }}"
when: swap_file_check.stat.exists
- name: Check if swap is on
shell: swapon --show | grep {{swap_file_path}}
register: swap_is_enabled
changed_when: false
failed_when: false
- name: Disable swap
command: swapoff {{swap_file_path}}
register: swap_disabled
when: >
swap_file_check.stat.exists
and 'rc' in swap_is_enabled and swap_is_enabled.rc == 0
and (not swap_enable or (swap_enable and swap_file_existing_size_mb != swap_file_size_mb))
- name: Delete the swap file
file:
path: "{{swap_file_path}}"
state: absent
when: not swap_enable
- name: Remove swap entry from fstab
mount:
name: none
src: "{{swap_file_path}}"
fstype: swap
opts: sw
passno: '0'
dump: '0'
state: present
when: not swap_enable
- name: Configure swap
when: swap_enable | bool
block:
- name: Create or change the size of swap file
command: dd if=/dev/zero of={{swap_file_path}} count={{swap_file_size_mb}} bs=1MiB
register: swap_file_created
when: >
not swap_file_check.stat.exists
or swap_file_existing_size_mb != swap_file_size_mb
- name: Change swap file permissions
file:
path: "{{swap_file_path}}"
mode: 0600
- name: Check if swap is formatted
shell: file {{swap_file_path}} | grep 'swap file'
register: swap_file_is_formatted
changed_when: false
failed_when: false
- name: Format swap file if it's not formatted
command: mkswap {{swap_file_path}}
when: >
('rc' in swap_file_is_formatted and swap_file_is_formatted.rc > 0)
or swap_file_created.changed
- name: Add swap entry to fstab
mount:
name: none
src: "{{swap_file_path}}"
fstype: swap
opts: sw
passno: '0'
dump: '0'
state: present
- name: Turn on swap
shell: swapon -a
# if swap was disabled from the start
# or has been disabled to change its params
when: >
('rc' in swap_is_enabled and swap_is_enabled.rc != 0)
or swap_disabled.changed
- name: Configure swappiness
sysctl:
name: vm.swappiness
value: "{{ swappiness|string }}"
state: present
I'm not able to reply to Greg Dubicki answer so I add my 2 cents here:
I think adding casting to int when doing calculation on swap_file_size_mb * 1024 * 1024 to transform it into swap_file_size_mb | int * 1024 * 1024 will make the code a bit smarter in case you want to use a fact to extract the final swap size based on the amount of RAM installed like:
swap_file_size_mb: "{{ ansible_memory_mb['real']['total'] * 2 }}"
else it will always resize the swap file even if the size it's the same.
Here is the ansible-swap playbook that I use to install 4GB (or whatever I configure group_vars for dd_bs_size_mb * swap_count) of swap space on new servers:
https://github.com/tribou/ansible-swap
I also added a function in my ~/.bash_profile to help with the task:
# Path to where you clone the repo
ANSIBLE_SWAP_PLAYBOOK=$HOME/dev/ansible-swap
install-swap ()
{
usage='Usage: install-swap HOST';
if [ $# -ne 1 ]; then
echo "$usage";
return 1;
fi;
ansible-playbook $ANSIBLE_SWAP_PLAYBOOK/ansible-swap/site.yml --extra-vars "target=$1"
}
Just make sure to add your HOST to your ansible inventory first.
Then it's just install-swap HOST.
Here is a preexisting role on Galaxy which achieves the same thing: https://galaxy.ansible.com/geerlingguy/swap
What works for me is to add 4Gib swap through the playbook.
Check this:
.

Resources