Hoping someone can help me figure out what I feel should be a simple nested string problem. I have the following tasks to randomly choose a string, save it to a variable and print it:
tasks:
- name: Debug Section 1
debug:
msg: "{{ item }}"
with_random_choice:
- MY_CHOICE1
- MY_CHOICE2
register: choice
- name: Set result to a fact
set_fact:
THE_CHOICE: "{{ choice.results }}"
- name: Debug Section 3
debug:
msg: "{{ THE_CHOICE }}"
The results return with:
PLAY [Testing variable] **********************************************************************************************************************************************************************************************************************
TASK [Debug Section 1] ***********************************************************************************************************************************************************************************************************************ok: [localhost] => (item=MY_CHOICE1) => {
"msg": "MY_CHOICE1"
}
TASK [Set result to a fact] ******************************************************************************************************************************************************************************************************************ok: [localhost]
TASK [Debug Section 3] ***********************************************************************************************************************************************************************************************************************ok: [localhost] => {
"msg": [
{
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"item": "MY_CHOICE1",
"msg": "MY_CHOICE1"
}
]
}
PLAY RECAP ***********************************************************************************************************************************************************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
I would like the variable THE_CHOICE to just return the item, but I can't seem to get it to work. In the set_fact section I've tried the following:
THE_CHOICE: "{{ choice.results['item'] }}"
THE_CHOICE: "{{ choice.results.item }}"
THE_CHOICE: "{{ choice['results']['item'] }}"
All attempts result in something to the effect of this:
"The task includes an option with an undefined variable. The error was: 'list object' has no attribute 'item'
Could anybody provide some insight into what I'm missing?
It would be simpler to use the random filter (since Ansible 1.6):
vars:
choices:
- MY_CHOICE1
- MY_CHOICE2
tasks:
- name: Set fact random
set_fact:
THE_CHOICE: "{{ choices | random }}"
About your original playbook, choice.results is a list, containing one result for each item of the loop. In your case, it only contains one result, because the with_random_choice loop only iterates once. So, in order to access your item, you must select the first result of the list with [0]:
- name: Set result to a fact
set_fact:
THE_CHOICE: "{{ choice.results[0].item }}"
Related
debug:
msg: "{{backup_facts | replace(',world',',{{custom}}')}}"
register: replace_csv
in the above code, I am trying to replace a string/word in a variable with a variable.
so in this case these are the vars:
backup_facts = "hello,world"
custom = "prab"
so the end results I would like is: "hello, prab" after the replace. But everytime I run the playbook, I get the following:
"replace_csv": {
"changed": false,
"failed": false,
"msg": "hello,{{custom}}"
}
I have attempted different variation such as putting a quotation around the curly brackets or not putting the curly brackets at all but no results.
Q: "The result is: hello,prab after the replace."
Keep it simple. Put the parameters into variables. This will simplify the code. For example,
- hosts: localhost
vars:
backup_facts: "hello,world"
custom: "prab"
tasks:
- debug:
msg: "{{ backup_facts|replace(old, new) }}"
vars:
old: ",world"
new: ",{{ custom }}"
gives (abridged)
ok: [localhost] =>
msg: hello,prab
I'm just a beginner and write some small playbook.
For now I get some little error.
- name: Facts
ios_command:
commands: show interface status
register: ios_comm_result
In this playbook, for beginner I get the list of interfaces and then in next task I get list with first position including column name.
- name: get a list of ports to modify
set_fact:
newlist: "{{ (newlist | default([])) + [item.split()[0]] }}"
with_items: "{{ ios_comm_result.stdout_lines }}"
Output:
'Port'
'fa0/1'
'gi0/2'
....
etc
How can I delete first line? Or where can I read about this?
Based on your requirement and the given comments about Accessing list elements with Slice notation ([1:]) and Jinja Filters (| reject()) I've setup an short test
---
- hosts: localhost
become: false
gather_facts: false
vars:
STDOUT_LINES: ['Port', 'fa0/1', 'gi0/2', 'etc/3']
tasks:
# Slice notation
- name: Show 'stdout_lines' from the 2nd line to the end
debug:
msg: "{{ item }}"
loop: "{{ STDOUT_LINES[1:] }}"
# Jinja2 filter
- name: Show 'stdout_lines' and drop any lines which match
debug:
msg: "{{ item }}"
loop: "{{ STDOUT_LINES | reject('match', '^Port') | list }}"
# Conditionals
- name: Show 'stdout_lines' but not the first one
debug:
msg: "{{ item }}"
when: ansible_loop.index != 1
loop: "{{ STDOUT_LINES }}"
loop_control:
extended: true
label: "{{ ansible_loop.index0 }}"
with some value added about Extended loop variables and using conditionals in loops.
All three options show the expected result.
Need some help to retrieve child values from var file.
Below is my var file
api_user: root
api_password: !vault |
$ANSIBLE_VAULT;1.2;AES256;isi33835326238346338613761366531376662613865376263656262
6138
Huston:
onefs_host: 10.88.55.00
Phoenix:
onefs_host: 10.76.52.01
Below is my playbook
---
- name: isi_increase
hosts: localhost
connection: local
vars_files:
- isilonvars.yml
tasks:
- name: Print
debug:
msg:
- "{{ Huston.onefs_host }}"
- "{{ api_user }}"
- "{{ api_password }}"
This code works perfectly
TASK [Print] ********************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
"10.88.55.00",
"root",
"Sh00tm3!"
]
}
But as per my requirement i have to retrieve onefs_host IP as per location in my playbook. I am using extra vars here -e "location=Huston"
- name: Print
debug:
msg:
# - "{{ wcc.onefs_host }}"
- "{{ {{location}}.onefs_host }}"
- "{{ api_user }}"
- "{{ api_password }}"
I am getting the below error.
fatal: [localhost]: FAILED! => {"msg": "template error while templating string: expected token ':', got '}'. String: {{ {{isilon_location}}.onefs_host }}"}
Can you try this way
- name: Print
debug:
msg:
- "{{ vars[location]['onefs_host'] }}"
- "{{ api_user }}"
- "{{ api_password }}"
If the user does not pass dest_path parameter or if dest_path is EMPTY i.e contains only whitespaces then dest_path should be the same as source_file value.
Below is my playbook:
---
- name: "Play 1"
hosts: localhost
any_errors_fatal: false
gather_facts: false
tasks:
- set_fact:
dest_path: "{{ dest_path | default(source_file) }}"
- set_fact:
dest_path: "{{ source_file }}"
when: dest_path | length == 0
- debug:
msg: "DESTINATION PATH IS: {{ dest_path }} and the SOURCE PATH is: {{ source_file }}"
This is how you run this playbook:
ansible-playbook -i /web/playbooks/allmwhosts.hosts /web/playbooks/test.yml -e '{ source_file: /web/bea_apps/CURRENT }' -e dest_path=
In the above example when the user does not specify any value for dest_path I m expecting dest_path should be source_file i.e /web/bea_apps/CURRENT
However, as you can see in the output below that is not the case:
Output:
PLAY [Play 1] *******************
TASK [set_fact] **************************************************************************************
ok: [localhost]
TASK [set_fact] **************************************************************************************
ok: [localhost]
TASK [debug] *****************************************************************************************
ok: [localhost] => {
"msg": "DESTINATION PATH IS: and the SOURCE PATH is: /web/bea_apps/CURRENT"
}
PLAY RECAP *******************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0
Can you please suggest?
The extra variable that you pass as parameter is overriding the variable in set_fact variable dest_path. Below is the working code. In set_fact instead of dest_path I replaced with path.
---
- name: "Play 1"
hosts: localhost
any_errors_fatal: false
gather_facts: false
tasks:
- set_fact:
path: "{{ source_file }}"
when: (dest_path is not defined) or (dest_path | length == 0)
- set_fact:
path: "{{ dest_path }}"
when: (dest_path is defined) or (dest_path | length != 0)
- debug:
msg: "DESTINATION PATH IS: {{ path }} and the SOURCE PATH is: {{ source_file }}"
I'm using Ansible to grab an VIP from InfoBlox and running into an issue when trying to build my exclude list. I need to exclude the first 3 IP's as they are reserved, however the CIDR range is a dynamic variable so I need to build this exclude list on the fly. Here's a representation of what I have so far:
---
- name: Assign VIP to FQDN in Grid Manager
hosts: all
connection: local
gather_facts: false
vars:
CIDR: 10.0.0.
tasks:
- set_fact:
EXCLUDES: "{{ EXCLUDES | default([]) + [item] }}"
with_sequence: start=1 end=3 format=''{{ CIDR }}%d''
- set_fact:
formated_excludes: "{{ EXCLUDES |join(', ') }}"
- debug:
msg: "{{ formated_excludes }}"
- set_fact:
VIP: "{{ lookup('nios_next_ip', '10.0.0.0/25', exclude=[formated_excludes]) | first }}"
- name: Print next IP address
debug:
msg: "The next available IP is {{ VIP }}"
Here are the results of the play:
PLAY [Assign VIP to FQDN in Grid Manager] *****************************************************************************************************************
TASK [set_fact] *******************************************************************************************************************************************
ok: [localhost] => (item='10.0.0.1')
ok: [localhost] => (item='10.0.0.2')
ok: [localhost] => (item='10.0.0.3')
TASK [set_fact] *******************************************************************************************************************************************
ok: [localhost]
TASK [debug] **********************************************************************************************************************************************
ok: [localhost] => {
"msg": "'10.0.0.1', '10.0.0.2', '10.0.0.3'"
}
TASK [set_fact] *******************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "An unhandled exception occurred while running the lookup plugin 'nios_next_ip'. Error was a <class 'ansible.errors.AnsibleError'>, original message: Invalid value for exclude: \"'10.0.0.1', '10.0.0.2', '10.0.0.3'\": Invalid IPv4 address"}
PLAY RECAP ************************************************************************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
The formatting appears to be fine, however the lookup won't accept it. For comparison, using the following works fine:
- set_fact:
VIP: "{{ lookup('nios_next_ip', '10.0.0.0/25', exclude=['10.0.0.1', '10.0.0.2', '10.0.0.3']) | first }}"
Here are the results:
PLAY [Assign VIP to FQDN in Grid Manager] *****************************************************************************************************************
TASK [set_fact] *******************************************************************************************************************************************
ok: [localhost]
TASK [Print next IP address] ******************************************************************************************************************************
ok: [localhost] => {
"msg": "The next available IP is 10.0.0.4"
}
PLAY RECAP ************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Any thoughts on why this variable isn't working would be much appreciated!
Parameter exclude is "List of IP's ...", but the filter join makes a string from the list
- set_fact:
formated_excludes: "{{ EXCLUDES |join(', ') }}"
Use the list EXCLUDES in the parameter
- set_fact:
VIP: "{{ lookup('nios_next_ip', '10.0.0.0/25', exclude=EXCLUDES) | first }}"