12-29-2022 02:40 AM
Hi dear community,
I am currently playing with Ansible and wondered if it is possible to have a play at the top of my playbook that requires a user input.
The user would need to input a device name so all the following plays will rely on that input to achieve different tasks such as :
At the moment, the device name can be found statically at several places in my playbook and want to let the user to input the device name ony once.
Thanks in advance for your kind help, i wish you a happy end of year.
Solved! Go to Solution.
12-30-2022 01:55 PM - edited 12-30-2022 01:56 PM
Hi,
I finaly found a solution/workaround using a python script :
#!/opt/homebrew/bin/python3
# -*- coding:utf-8 -*-
########################################################################################################################
# This file is a part of Jeyriku.net
#
# Created: 30.12.2022 15:27:57
# Author: Jeremie Rouzet
#
# Last Modified: 30.12.2022 15:35:42
# Modified By: Jeremie Rouzet
#
# Copyright (c) 2022 Jeyriku.net
########################################################################################################################
# Imports from Json to export datas in Json Format
import json
# Imports from Request to create REST API Call
import requests
# Imports from Jmespath to Filter Json data
import jmespath
# Define Netbox object and correct IP to build REST API Request
netbox = {
"ip": "127.0.0.1"
}
headers = {
"Accept" : "application/json",
"Content-Type" : "application/json",
"Authorization" : "Token XXXXXXXXXXXXXXXXXXXXXXXXXXX",
}
devices_path = "/api/dcim/devices"
url = f"https://{netbox['ip']}{devices_path}"
devices = requests.get(url, headers=headers, verify=False, timeout=30).json() # timeout:30sec
with open('./Python/devices.json', 'w', encoding='utf-8') as f:
json.dump(devices, f, ensure_ascii=False, indent=4)
data = jmespath.search('results[*].{Name: name, snmp_loc: custom_fields.snmp_location,IP: primary_ip.address, snmp_com: custom_fields.snmp_community, snmp_srv: custom_fields.snmp_server}', devices)
with open('./Python/results.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
input_dev = input("Enter the Hostname of the device to be configured: \n")
print(f"Is this what you just said?\n {input_dev}")
print("Started Reading JSON file")
with open('./Python/results.json', "r" , encoding='utf-8') as check_dev:
print("Converting JSON encoded data into Python dictionary")
data = json.load(check_dev)
# Search data based on key and value using filter and list method
result = (list(filter(lambda x:x["Name"]== input_dev, data)))
with open("./Python/target_dev.json", "w" , encoding='utf-8') as outfile:
json.dump(result, outfile)
Hope this help some others
12-29-2022 04:44 AM
Hi @Jerems
Its been a while since I worked with Ansible but here is an example of an interactive playbook (may need "freshening up" depending on your Ansible version). You can also provide arguments via the command line if that works, depending on how you are executing your playbook.
###############################################################################
# This interactive playbook queries for information and action and performs
# the selection Tenant action against the DevNet Sandbox APIC
# EXECUTION:
# ansible-playbook -i hosts aci_tenant_prompt.yml
###############################################################################
- name: ACI Playbook to Perform User Prompted Action on Tenant
hosts: aci_sandbox
gather_facts: no
vars:
avar: some_var
# Prompt for the Tenant Name and Tenant action
vars_prompt:
- name: "tenant_name"
prompt: "Enter Tenant Name"
default: "LAX_Tenant"
private: no
- name: "tenant_state"
prompt: "Enter Tenant State (absent | present | query)"
default: "query"
private: no
12-29-2022 05:09 AM
Hi @Claudia de Luna,
Thank you so much for your quick reply, let me try this between today or tomorrow and revert to you at that time.
Jerems
12-29-2022 06:06 AM
It works well thank you !
Here is the output:
TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [pause] ********************************************************************************************************************************************************************************************************************
[pause]
Enter Device Name:
jeyniper01^Mok: [localhost]
TASK [set_fact] *****************************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [debug] ********************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"dev": "jeyniper01"
}
You can see from the screenshot below, i gather some parameters from netbox registered as "netbox_devices".
---
- name: Prompt for the device to configure
hosts: localhost
tasks:
- pause:
prompt: "Enter Device Name"
echo: yes
register: input_dev
- set_fact:
dev: "{{ input_dev.user_input }}"
- debug:
var: dev
- name: Config Junos context SNMP
gather_facts: no
hosts: all
connection: local
become: false
vars:
server: "https://127.0.0.1"
endpoint1: "/api/dcim/devices/?limit=1000"
netbox_token: "123456789"
tasks:
# Make a Netbox API call to retrieve devices'components
- name: Get Device List from Netbox
uri:
url: "{{ server }}{{ endpoint1 }}"
headers:
Authorization: "Token {{ netbox_token }}"
Accept: 'application/json'
body_format: json
method: GET
status_code: [200, 201]
timeout: 30
validate_certs: false
return_content: no
register: netbox_devices
run_once: yes
- name: QueryDeviceName
ansible.builtin.debug:
msg: "{{ netbox_devices.json.results | to_json | from_json | community.general.json_query(jmesquery) }}"
vars:
jmesquery: "[?name== 'dev' ].{Name: name, snmp_loc: custom_fields.snmp_location, IP: primary_ip.address, snmp_com: custom_fields.snmp_community, snmp_srv: custom_fields.snmp_server}"
register: device_name
I would need the input device "jeyniper01" which is stored as a variable (in var: dev from initial task) to be used and matched in the jmesquery.
I gave it a try like this :
I even tried like this:
But it doesn't as i was expecting.
Can you please advise ?
Thanks in advance,
Jerems
12-29-2022 07:37 AM
So I'm assuming this works?
jmesquery: "[?name=='jeyniper01' ].{Name: name, snmp_loc: custom_fields.snmp_location, IP: primary_ip.address, snmp_com: custom_fields.snmp_community, snmp_srv: custom_fields.snmp_server}"
If so, what I would try next is to build out that string explicitly so that no variable interpretation needs to be done in the query string. Basically build out a variable called jmesquery_str or something and then pass that entire variable.
jmesquery: {{ jmesquery_str }}
Having said that its very possible I have no idea what I'm talking about!!
12-29-2022 07:46 AM
Yes this one works correctly.
jmesquery: "[?name=='jeyniper01' ].{Name: name, snmp_loc: custom_fields.snmp_location, IP: primary_ip.address, snmp_com: custom_fields.snmp_community, snmp_srv: custom_fields.snmp_server}"
12-30-2022 01:55 PM - edited 12-30-2022 01:56 PM
Hi,
I finaly found a solution/workaround using a python script :
#!/opt/homebrew/bin/python3
# -*- coding:utf-8 -*-
########################################################################################################################
# This file is a part of Jeyriku.net
#
# Created: 30.12.2022 15:27:57
# Author: Jeremie Rouzet
#
# Last Modified: 30.12.2022 15:35:42
# Modified By: Jeremie Rouzet
#
# Copyright (c) 2022 Jeyriku.net
########################################################################################################################
# Imports from Json to export datas in Json Format
import json
# Imports from Request to create REST API Call
import requests
# Imports from Jmespath to Filter Json data
import jmespath
# Define Netbox object and correct IP to build REST API Request
netbox = {
"ip": "127.0.0.1"
}
headers = {
"Accept" : "application/json",
"Content-Type" : "application/json",
"Authorization" : "Token XXXXXXXXXXXXXXXXXXXXXXXXXXX",
}
devices_path = "/api/dcim/devices"
url = f"https://{netbox['ip']}{devices_path}"
devices = requests.get(url, headers=headers, verify=False, timeout=30).json() # timeout:30sec
with open('./Python/devices.json', 'w', encoding='utf-8') as f:
json.dump(devices, f, ensure_ascii=False, indent=4)
data = jmespath.search('results[*].{Name: name, snmp_loc: custom_fields.snmp_location,IP: primary_ip.address, snmp_com: custom_fields.snmp_community, snmp_srv: custom_fields.snmp_server}', devices)
with open('./Python/results.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
input_dev = input("Enter the Hostname of the device to be configured: \n")
print(f"Is this what you just said?\n {input_dev}")
print("Started Reading JSON file")
with open('./Python/results.json', "r" , encoding='utf-8') as check_dev:
print("Converting JSON encoded data into Python dictionary")
data = json.load(check_dev)
# Search data based on key and value using filter and list method
result = (list(filter(lambda x:x["Name"]== input_dev, data)))
with open("./Python/target_dev.json", "w" , encoding='utf-8') as outfile:
json.dump(result, outfile)
Hope this help some others
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide