Locate string/integer not in list
Locate string/integer not in list
Im pulling a list of VLANs from our IPAM via an API and I want to be able to locate an unused "vlanId" that isnt in the list. I was expecting that I could use with_items for the JSON content and then use the random function with an until loop and occasionally it will initially generate a number that doesnt exist in the list. Mostly it just gets stuck and doesnt generate a new random number when the one generated already exists.
Playbook:
- uri:
url: "#"
validate_certs: no
headers:
token: "{{ token }}"
method: GET
force_basic_auth: yes
return_content: yes
register: ipam
- set_fact:
value: "{{ 4094 | random(start=1) }}"
until: value not in item.vlanId
with_items: "{{ ipam.json.data }}"
retries: 4093
- debug: msg="{{ value }}"
Relevant Output:
ok: [localhost] => (item={u'domainId': u'3', u'description': u'#', u'editDate': None, u'Customer ID': None, u'number': u'2241', u'vlanId': u'548', u'name': u'2241', u'Customer Name': None, u'custom_fields': None, u'Engineer': None}) => {
"ansible_facts": {
"value": "2727"
},
"ansible_facts_cacheable": false,
"attempts": 1,
"changed": false,
"item": {
"Customer ID": null,
"Customer Name": null,
"Engineer": null,
"custom_fields": null,
"description": "#",
"domainId": "3",
"editDate": null,
"name": "2241",
"number": "2241",
"vlanId": "548"
}
}
ok: [localhost] => (item={u'domainId': u'3', u'description': u'#', u'editDate': None, u'Customer ID': None, u'number': u'2242', u'vlanId': u'549', u'name': u'2242', u'Customer Name': None, u'custom_fields': None, u'Engineer': None}) => {
"ansible_facts": {
"value": "1955"
},
"ansible_facts_cacheable": false,
"attempts": 1,
"changed": false,
"item": {
"Customer ID": null,
"Customer Name": null,
"Engineer": null,
"custom_fields": null,
"description": "#",
"domainId": "3",
"editDate": null,
"name": "2242",
"number": "2242",
"vlanId": "549"
}
}
FAILED - RETRYING: set_fact (4000 retries left).Result was: {
"ansible_facts": {
"value": "50"
},
"ansible_facts_cacheable": false,
"attempts": 1,
"changed": false,
"retries": 4001
}
FAILED - RETRYING: set_fact (3999 retries left).Result was: {
"ansible_facts": {
"value": "50"
},
"ansible_facts_cacheable": false,
"attempts": 2,
"changed": false,
"retries": 4001
}
FAILED - RETRYING: set_fact (3998 retries left).Result was: {
"ansible_facts": {
"value": "50"
},
"ansible_facts_cacheable": false,
"attempts": 3,
"changed": false,
"retries": 4001
Im currently using ansible 2.4.2.0
If this is something that cant/shouldnt be done in Ansible, any guidance would be appreciated.
1 Answer
1
Here's what you want:
- debug:
msg: "{{ range(1, 4095) | difference(vlanIds) | random }}"
vars:
vlanIds: "{{ ipam.json.data | map(attribute='vlanId') | list }}"
Explanation:
map(attribute=...
- create a list of vlan IDs,
map(attribute=...
range
- generate a sequence from 1 to 4094,
range
difference
- select all the elements from the above. that are not on the vlanIds
list,
difference
vlanIds
random
- select a random element from the above.
random
For strings (as the title suggests) replace range
with a list of possible strings.
range
Assuming Im following and ended up with this: - debug: msg: "{{ range(1, 4095) | difference(ipam.json.data|map(attribute='vlanId')) | random }}")
code
But I get the following error: fatal: [localhost]: FAILED! => { "msg": "Unexpected templating type error occurred on ({{ range(1, 4095) | difference(ipam.json.data|map(attribute='vlanId')) | random }}): 'set' object does not support indexing"– Kyle Quilliam
20 mins ago
code
Sorry i really suck at formatting on here....
– Kyle Quilliam
13 mins ago
Added one more filter.
– techraf
11 mins ago
Truly, you are a god amongst men. That works beautifully.
– Kyle Quilliam
7 mins ago
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Thanks for your response, that does seem to do the trick for the most part. My only concern is that its diffing all the elements, is there a way to dig in to only utilize the vlanId element?
– Kyle Quilliam
1 hour ago