Create VLAN number based on the current last VLAN number - ansible

I would like to create new VLAN based on the last number of existing VLANS. For example my last VLAN number on the eos is 100 so I would like to run my playbook and create VLAN 101. However when I run my playbook it looks like set_fact iteration is not in order and playbook created for me VLAN 15 instead VLAN 101.
Even I am using sort filter it looks like asnible is not doing iteration in order. Does anyone know how to do it?
My playbook
- name: CHECK VLAN
hosts: eos
connection: local
tasks:
- name: CHECK FOR VLAN NUMBERS
eos_command:
commands: show vlan | json
provider: "{{ cli }}"
ignore_errors: yes
register: sh_vlan_output
- debug: var=sh_vlan_output.stdout[0].vlans.keys()
- name: SET VLAN NUMBER
set_fact:
vlan_index: "{{ item | int +1 }}"
with_items:
- "{{ sh_vlan_output.stdout[0].vlans.keys() | sort }}"
- debug: var=vlan_index
- name: CREATE VLAN
eos_config:
lines:
- vlan {{ vlan_index }}
provider: "{{ cli }}"
authorize: yes
PLAY [CHECK VLAN] **************************************************************
TASK [setup] *******************************************************************
ok: [eos-1]
TASK [CHECK FOR VLAN NUMBERS] **************************************************
ok: [eos-1]
TASK [debug] *******************************************************************
ok: [eos-1] => {
"sh_vlan_output.stdout[0].vlans.keys()": [
"11",
"10",
"13",
"12",
"14",
"1",
"100"
]
}
TASK [SET VLAN NUMBER] *********************************************************
ok: [eos-1] => (item=10)
ok: [eos-1] => (item=1)
ok: [eos-1] => (item=100)
ok: [eos-1] => (item=11)
ok: [eos-1] => (item=12)
ok: [eos-1] => (item=13)
ok: [eos-1] => (item=14)
TASK [debug] *******************************************************************
ok: [eos-1] => {
"vlan_index": "15"
}
TASK [CREATE VLAN] *************************************************************
changed: [eos-1]
PLAY RECAP *********************************************************************
eos-1

You can get max + 1 with the following jinja expression:
{{ sh_vlan_output.stdout[0].vlans.keys() | map('int') | max + 1 }}

Related

Ansible variables

I'm a real Ansible beginner.
Is there any way to reconstruct a variable from another ansible variable?
For example, this playbook :
- hosts: servers
vars:
ex_server1: First
ex_server2: Second
ex_server3: Third
toto: ex_
tasks:
- debug:
msg: "{{ toto+ansible_hostname }}"
It print :
ok: [server2] => {
"msg": "ex_server2"
}
ok: [server3] => {
"msg": "ex_server3"
}
ok: [server1] => {
"msg": "ex_server1"
}
Instead of "First", "Second" and "Third".
Is there a way to print variable content instead of variable name in this situation or in a jinja template ?
Use lookup vars plugin
- debug:
msg: "{{ lookup('vars', toto + ansible_hostname) }}"
gives
TASK [debug] ***********************************************************
ok: [server1] =>
msg: First
ok: [server2] =>
msg: Second
ok: [server3] =>
msg: Third
The details about the plugin are available from the command-line
shell> ansible-doc -t lookup vars

How to skip a hostname from ansible inventory file?

My ansible inventory file has the following entry
[non_prod_servers]
oracle[1:13]
How can I eliminate hosts "oracle7" and "oracle10" from the above specification, without having to create the following entries?
[non_prod_servers]
oracle[1:6]
oracle[8:9]
oracle[11:13]
Essentially, looking for an elegant solution than what I have come up with.
Thanks in advance.
FR
IMHO, the functionality, you're looking for, is not available. You can use Python slicing inside the inventory. The inventory patterns do not apply inside the inventory file.
If you need it for automation, i.e. you want to control the process by a couple of variables the inventory and playbook below create the group dynamically
shell> cat hosts
[non_prod_servers]
localhost
[non_prod_servers:vars]
_name=oracle
_from=1
_to=13
_deny=[7,10]
shell> cat playbook.yml
---
- hosts: non_prod_servers
gather_facts: false
tasks:
- add_host:
hostname: "{{ _name }}{{ item }}"
groups: non_prod_servers_dyn
loop: "{{ range(_from, _to + 1)|difference(_deny) }}"
- hosts: non_prod_servers_dyn
gather_facts: false
tasks:
- debug:
var: ansible_play_hosts_all
run_once: true
gives
shell> ansible-playbook -i hosts playbook.yml
PLAY [non_prod_servers] *************************************************
TASK [add_host] *********************************************************
ok: [localhost] => (item=1)
ok: [localhost] => (item=2)
ok: [localhost] => (item=3)
ok: [localhost] => (item=4)
ok: [localhost] => (item=5)
ok: [localhost] => (item=6)
ok: [localhost] => (item=8)
ok: [localhost] => (item=9)
ok: [localhost] => (item=11)
ok: [localhost] => (item=12)
ok: [localhost] => (item=13)
PLAY [non_prod_servers_dyn] **********************************************
TASK [debug] *************************************************************
ok: [oracle1] =>
ansible_play_hosts_all:
- oracle1
- oracle2
- oracle3
- oracle4
- oracle5
- oracle6
- oracle8
- oracle9
- oracle11
- oracle12
- oracle13

Ansible - Looping and Debug/Register

I have the following task.
However, it doesn't output the output for each ping that is produced, and I only get a 1 x output. When there should be x 5.
Task
tasks:
- name: "Check Connectivity (ping)"
nxos_ping:
provider: "{{ nxos_ssh }}"
source: "{{ hostvars[inventory_hostname]['lo0_ipaddr'] }}"
vrf: default
dest: "192.168.1.{{item}}"
with_sequence: start=1 end=5
register: out
- debug:
msg:
- "command: {{ out['results'][0]['commands'][0] }}"
Example
TASK [Check Connectivity (ping)] ***************************************************************************************************
ok: [spine-nxos-1] => (item=1)
ok: [spine-nxos-2] => (item=1)
ok: [spine-nxos-2] => (item=2)
ok: [spine-nxos-1] => (item=2)
ok: [spine-nxos-1] => (item=3)
ok: [spine-nxos-2] => (item=3)
ok: [spine-nxos-1] => (item=4)
ok: [spine-nxos-2] => (item=4)
ok: [spine-nxos-1] => (item=5)
ok: [spine-nxos-2] => (item=5)
TASK [debug] ***********************************************************************************************************************
ok: [spine-nxos-1] => {
"msg": [
"command: ping 192.168.1.1 count 5 source 192.168.1.1 vrf default"
]
}
ok: [spine-nxos-2] => {
"msg": [
"command: ping 192.168.1.1 count 5 source 192.168.1.2 vrf default"
]
}
Your code is working correct, as you only print out the first element of the registered output. If you want to see all your commands you should replace the last line of your playbook with:
- "command {{ out | json_query('results[*].commands[*]') }}"
or loop through your output corresponding to your sequence:
debug:
msg:
- "command {{ out.results[item|int].commands[0]}}"
with_sequence: start=0 end=2

In Ansible, how can I iterate over stdout with an array?

Ansible v2.6.3
I have the simple task, which gets the AWS ARNs in my jenkins ECS cluster
tasks:
- command: aws ecs list-container-instances --cluster jenkins
register: jenkins_ecs_containers
- debug: var=jenkins_ecs_containers.stdout
and has the following output
TASK [debug] *******************************************************************
ok: [localhost] => {
"jenkins_ecs_containers.stdout": {
"containerInstanceArns": [
"arn:aws:ecs:us-east-1:arn0",
"arn:aws:ecs:us-east-1:arn1"
]
}
}
How can I iterate over the ARNs? I tried
- debug: var=item
with_items: jenkins_ecs_containers.stdout.containerInstanceArns
gives
TASK [debug] *******************************************************************
ok: [localhost] => (item=jenkins_ecs_containers.stdout.containerInstanceArns) => {
"item": "jenkins_ecs_containers.stdout.containerInstanceArns"
}
or
- debug: var=item
with_items: "{{ jenkins_ecs_containers.stdout.containerInstanceArns }}"
gives
TASK [debug] *******************************************************************
fatal: [localhost]: FAILED! => {"msg": "'ansible.utils.unsafe_proxy.AnsibleUnsafeText object' has no attribute 'containerInstanceArns'"}
to retry, use: --limit #/Users/cfouts/git-repos/ansible/playbooks/loop.retry
Thanks!
I created a file with your output. So I used set_fact. Otherwise, it's just a string, not a JSON object:
tasks:
- command: cat files/stdout.txt
register: result
- debug: var=result.stdout
- set_fact:
jenkins_ecs_containers: "{{ result.stdout }}"
- debug:
msg: "{{ item }}"
with_items: "{{ jenkins_ecs_containers.containerInstanceArns }}"
This gave me the following output:
PLAY [localhost] ***************************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [command] *****************************************************************
changed: [localhost]
TASK [debug] *******************************************************************
ok: [localhost] => {
"result.stdout": {
"containerInstanceArns": [
"arn:aws:ecs:us-east-1:arn0",
"arn:aws:ecs:us-east-1:arn1"
]
}
}
TASK [set_fact] ****************************************************************
ok: [localhost]
TASK [debug] *******************************************************************
ok: [localhost] => (item=None) => {
"msg": "arn:aws:ecs:us-east-1:arn0"
}
ok: [localhost] => (item=None) => {
"msg": "arn:aws:ecs:us-east-1:arn1"
}
PLAY RECAP *********************************************************************
localhost : ok=5 changed=1 unreachable=0 failed=0
You can iterate over like this:
- debug:
msg: "{{ item[1] }}"
with_subelements:
- "{{ jenkins_ecs_containers }}"
- containerInstanceArns
Go through this link, it will make it clearer.

How to access a programmatically constructed ansible variable?

I have constructed an ansible variable using two other defined ansible variables. The constructed variable is defined in the vars/main.yml and I want to access the defined value in vars/main.yml.
vars/main.yml
---
var1_var2: "some value"
Now, I construct the variable
---
- name: Construct and get the value
hosts: localhost
tasks:
- include_vars: "vars/main.yml"
- set_fact:
variable1: "var1"
variable2: "var2"
- set_fact:
final_variable: "{{ variable1 }}_{{ variable2 }}"
- set_fact:
ultimate_variable: "{{ final_variable }}"
If I run the playbook with -vvv flag, I can see that ultimate_variable sets to var1_var2 while I want to get the value defined in the vars/main.yml
i.e., some value
TASK [set_fact]
ok: [localhost] => {
"ansible_facts": {
"variable1": "var1",
"variable2": "var2"
},
"changed": false,
"failed": false
}
TASK [set_fact] task path: /home/ubuntu/test.yml:78
ok: [localhost] => {
"ansible_facts": {
"final_variable": "var1_var2"
},
"changed": false,
"failed": false
}
TASK [set_fact]
ok: [localhost] => {
"ansible_facts": {
"ultimate_variable": "var1_var2"
},
"changed": false,
"failed": false
}
updated answer:
use the lookup plugin to do the double replacement:
ultimate_variable: "{{ lookup('vars', '{{final_variable}}') }}"
playbook:
- include_vars: "vars/main.yml"
- set_fact:
variable1: "var1"
variable2: "var2"
- set_fact:
final_variable: "{{ variable1 }}_{{ variable2 }}"
- set_fact:
ultimate_variable: "{{ lookup('vars', '{{final_variable}}') }}"
- debug:
var: ultimate_variable
output:
PLAY [localhost] ****************************************************************************************************************************************************************************************************
TASK [include_vars] *************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [set_fact] *****************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [set_fact] *****************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [set_fact] *****************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [debug] ********************************************************************************************************************************************************************************************************
ok: [localhost] => {
"ultimate_variable": "some value"
}
PLAY RECAP **********************************************************************************************************************************************************************************************************
localhost : ok=5 changed=0 unreachable=0 failed=0
hope it helps.
You could also skip the intermediary variable definition:
- include_vars: "vars/main.yml"
- set_fact:
variable1: "var1"
variable2: "var2"
- set_fact:
ultimate_variable: "{{ lookup('vars', variable1 ~ '_' ~ variable2) }}"
- debug:
var: ultimate_variable

Resources