From c2095fd4dc60d549e9367657c9853191d5d9da5f Mon Sep 17 00:00:00 2001 From: quinn snyder Date: Wed, 22 Apr 2020 14:04:43 -0700 Subject: [PATCH 1/2] updated code for ACI API --- coding201-parsing-xml/get-tenants-xml-1.py | 34 ++++++++++++++++ coding201-parsing-xml/get-tenants-xml-2.py | 36 +++++++++++++++++ coding201-parsing-xml/get-tenants-xml-3.py | 47 ++++++++++++++++++++++ coding201-parsing-xml/get-tenants-xml-4.py | 45 +++++++++++++++++++++ 4 files changed, 162 insertions(+) create mode 100644 coding201-parsing-xml/get-tenants-xml-1.py create mode 100644 coding201-parsing-xml/get-tenants-xml-2.py create mode 100644 coding201-parsing-xml/get-tenants-xml-3.py create mode 100644 coding201-parsing-xml/get-tenants-xml-4.py diff --git a/coding201-parsing-xml/get-tenants-xml-1.py b/coding201-parsing-xml/get-tenants-xml-1.py new file mode 100644 index 0000000..514f26a --- /dev/null +++ b/coding201-parsing-xml/get-tenants-xml-1.py @@ -0,0 +1,34 @@ +import requests +import xml.dom.minidom +# We need to import the JSON library just to handle our request to the APIC for login +import json + + +# We need to log in to the APIC and gather a token, before we can access any data +# Let's construct a request with a body + +# We'll need to disable certificate warnings +requests.packages.urllib3.disable_warnings() + +# We need to have a body of data consisting of a username and password to gather a cookie from APIC +encoded_body = json.dumps({ + "aaaUser": { + "attributes": { + "name": "admin", + "pwd": "ciscopsdt" + } + } +}) + +# Now lets make the request and store the data +resp = requests.post("https://sandboxapicdc.cisco.com/api/aaaLogin.json", data=encoded_body, verify=False) + +# This stores the received APIC-cookie from the login as a value to be used in subsequent REST calls +header = {"Cookie": "APIC-cookie=" + resp.cookies["APIC-cookie"]} + +# Now we make a call towards the tenant class on the ACI fabric with the proper header value set. +# We leverage the .xml ending to receive the data back as XML +tenants = requests.get("https://sandboxapicdc.cisco.com/api/node/class/fvTenant.xml?rsp-subtree-include=health,faults", headers=header, verify=False) + +# Requests stores the text of the response in the .text attribute. Lets print it to see raw XML +print(tenants.text) \ No newline at end of file diff --git a/coding201-parsing-xml/get-tenants-xml-2.py b/coding201-parsing-xml/get-tenants-xml-2.py new file mode 100644 index 0000000..c59ea12 --- /dev/null +++ b/coding201-parsing-xml/get-tenants-xml-2.py @@ -0,0 +1,36 @@ +import requests +import xml.dom.minidom +# We need to import the JSON library just to handle our request to the APIC for login +import json + + +# We need to log in to the APIC and gather a token, before we can access any data +# Let's construct a request with a body + +# We'll need to disable certificate warnings +requests.packages.urllib3.disable_warnings() + +# We need to have a body of data consisting of a username and password to gather a cookie from APIC +encoded_body = json.dumps({ + "aaaUser": { + "attributes": { + "name": "admin", + "pwd": "ciscopsdt" + } + } +}) + +# Now lets make the request and store the data +resp = requests.post("https://sandboxapicdc.cisco.com/api/aaaLogin.json", data=encoded_body, verify=False) + +# This stores the received APIC-cookie from the login as a value to be used in subsequent REST calls +header = {"Cookie": "APIC-cookie=" + resp.cookies["APIC-cookie"]} + +# Now we make a call towards the tenant class on the ACI fabric with the proper header value set. +# We leverage the .xml ending to receive the data back as XML +tenants = requests.get("https://sandboxapicdc.cisco.com/api/node/class/fvTenant.xml?rsp-subtree-include=health,faults", headers=header, verify=False) + +# Now lets use DOM to clean up the XML from its completely raw format +dom = xml.dom.minidom.parseString(tenants.text) +xml = dom.toprettyxml() +print(xml) \ No newline at end of file diff --git a/coding201-parsing-xml/get-tenants-xml-3.py b/coding201-parsing-xml/get-tenants-xml-3.py new file mode 100644 index 0000000..93b1cfd --- /dev/null +++ b/coding201-parsing-xml/get-tenants-xml-3.py @@ -0,0 +1,47 @@ +import requests +import xml.dom.minidom +# We need to import the JSON library just to handle our request to the APIC for login +import json + + +# We need to log in to the APIC and gather a token, before we can access any data +# Let's construct a request with a body + +# We'll need to disable certificate warnings +requests.packages.urllib3.disable_warnings() + +# We need to have a body of data consisting of a username and password to gather a cookie from APIC +encoded_body = json.dumps({ + "aaaUser": { + "attributes": { + "name": "admin", + "pwd": "ciscopsdt" + } + } +}) + +# Now lets make the request and store the data +resp = requests.post("https://sandboxapicdc.cisco.com/api/aaaLogin.json", data=encoded_body, verify=False) + +# This stores the received APIC-cookie from the login as a value to be used in subsequent REST calls +header = {"Cookie": "APIC-cookie=" + resp.cookies["APIC-cookie"]} + +# Now we make a call towards the tenant class on the ACI fabric with the proper header value set. +# We leverage the .xml ending to receive the data back as XML +tenants = requests.get("https://sandboxapicdc.cisco.com/api/node/class/fvTenant.xml?rsp-subtree-include=health,faults", headers=header, verify=False) + +# Now lets use DOM to clean up the XML from its completely raw format +dom = xml.dom.minidom.parseString(tenants.text) +xml = dom.toprettyxml() +print(xml) + +# Now we want to parse the resulting XML and print only the tenant name and its current health score. We'll do this through iteration over the elements in the XML +tenant_objects = dom.firstChild +if tenant_objects.hasChildNodes: + tenant_element = tenant_objects.firstChild + while tenant_element is not None: + if tenant_element.tagName == 'fvTenant': + health_element = tenant_element.firstChild + output = "Tenant: " + tenant_element.getAttribute('name') + '\t Health Score: ' + health_element.getAttribute('cur') + print(output.expandtabs(40)) + tenant_element = tenant_element.nextSibling \ No newline at end of file diff --git a/coding201-parsing-xml/get-tenants-xml-4.py b/coding201-parsing-xml/get-tenants-xml-4.py new file mode 100644 index 0000000..419ac85 --- /dev/null +++ b/coding201-parsing-xml/get-tenants-xml-4.py @@ -0,0 +1,45 @@ +import requests +import xml.dom.minidom +# We need to import the JSON library just to handle our request to the APIC for login +import json + + +# We need to log in to the APIC and gather a token, before we can access any data +# Let's construct a request with a body + +# We'll need to disable certificate warnings +requests.packages.urllib3.disable_warnings() + +# We need to have a body of data consisting of a username and password to gather a cookie from APIC +encoded_body = json.dumps({ + "aaaUser": { + "attributes": { + "name": "admin", + "pwd": "ciscopsdt" + } + } +}) + +# Now lets make the request and store the data +resp = requests.post("https://sandboxapicdc.cisco.com/api/aaaLogin.json", data=encoded_body, verify=False) + +# This stores the received APIC-cookie from the login as a value to be used in subsequent REST calls +header = {"Cookie": "APIC-cookie=" + resp.cookies["APIC-cookie"]} + +# Now we make a call towards the tenant class on the ACI fabric with the proper header value set. +# We leverage the .xml ending to receive the data back as XML +tenants = requests.get("https://sandboxapicdc.cisco.com/api/node/class/fvTenant.xml?rsp-subtree-include=health,faults", headers=header, verify=False) + +# Now lets use DOM to clean up the XML from its completely raw format +dom = xml.dom.minidom.parseString(tenants.text) +xml = dom.toprettyxml() +print(xml) + +# Now we'll do something similar, but done using a direct access method of the data, rather than interation and loops +tenant_list = dom.getElementsByTagName('fvTenant') +for tenants in tenant_list: + tenant_name = tenants.getAttribute('name') + tenant_dn = tenants.getAttribute('dn') + health_score = tenants.firstChild.getAttribute('cur') + output = "Tenant: " + tenant_name + "\t Health Score: " + health_score + "\n DN: " + tenant_dn + print(output.expandtabs(40)) \ No newline at end of file From fdc9f937f1f08a013f8ff8ff4dbcd33f7fe33cce Mon Sep 17 00:00:00 2001 From: Quinn Snyder Date: Tue, 7 Jul 2020 22:17:09 -0700 Subject: [PATCH 2/2] adding json parsing updates --- coding202-parsing-json/get-tenant-json-1.py | 33 +++++++++++++ coding202-parsing-json/get-tenant-json-2.py | 37 ++++++++++++++ coding202-parsing-json/get-tenant-json-3.py | 54 +++++++++++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 coding202-parsing-json/get-tenant-json-1.py create mode 100644 coding202-parsing-json/get-tenant-json-2.py create mode 100644 coding202-parsing-json/get-tenant-json-3.py diff --git a/coding202-parsing-json/get-tenant-json-1.py b/coding202-parsing-json/get-tenant-json-1.py new file mode 100644 index 0000000..a5b55e4 --- /dev/null +++ b/coding202-parsing-json/get-tenant-json-1.py @@ -0,0 +1,33 @@ +import requests +# We need to import the JSON library just to handle our request to the APIC for login +import json + + +# We need to log in to the APIC and gather a token, before we can access any data +# Let's construct a request with a body + +# We'll need to disable certificate warnings +requests.packages.urllib3.disable_warnings() + +# We need to have a body of data consisting of a username and password to gather a cookie from APIC +encoded_body = json.dumps({ + "aaaUser": { + "attributes": { + "name": "admin", + "pwd": "ciscopsdt" + } + } +}) + +# Now lets make the request and store the data +resp = requests.post("https://sandboxapicdc.cisco.com/api/aaaLogin.json", data=encoded_body, verify=False) + +# This stores the received APIC-cookie from the login as a value to be used in subsequent REST calls +header = {"Cookie": "APIC-cookie=" + resp.cookies["APIC-cookie"]} + +# Now we make a call towards the tenant class on the ACI fabric with the proper header value set. +# We leverage the .xml ending to receive the data back as XML. We're adding health and faults to the printout to ensure that we get levels of data back from the APIC +tenants = requests.get("https://sandboxapicdc.cisco.com/api/node/class/fvTenant.json?rsp-subtree-include=health,faults", headers=header, verify=False) + +# Requests stores the text of the response in the .text attribute. Lets print it to see raw JSON +print(tenants.text) \ No newline at end of file diff --git a/coding202-parsing-json/get-tenant-json-2.py b/coding202-parsing-json/get-tenant-json-2.py new file mode 100644 index 0000000..df4f238 --- /dev/null +++ b/coding202-parsing-json/get-tenant-json-2.py @@ -0,0 +1,37 @@ +import requests +# We need to import the JSON library just to handle our request to the APIC for login +import json + + +# We need to log in to the APIC and gather a token, before we can access any data +# Let's construct a request with a body + +# We'll need to disable certificate warnings +requests.packages.urllib3.disable_warnings() + +# We need to have a body of data consisting of a username and password to gather a cookie from APIC +encoded_body = json.dumps({ + "aaaUser": { + "attributes": { + "name": "admin", + "pwd": "ciscopsdt" + } + } +}) + +# Now lets make the request and store the data +resp = requests.post("https://sandboxapicdc.cisco.com/api/aaaLogin.json", data=encoded_body, verify=False) + +# This stores the received APIC-cookie from the login as a value to be used in subsequent REST calls +header = {"Cookie": "APIC-cookie=" + resp.cookies["APIC-cookie"]} + +# Now we make a call towards the tenant class on the ACI fabric with the proper header value set. +# We leverage the .xml ending to receive the data back as XML. We're adding health and faults to the printout to ensure that we get levels of data back from the APIC +tenants = requests.get("https://sandboxapicdc.cisco.com/api/node/class/fvTenant.json?rsp-subtree-include=health,faults", headers=header, verify=False) + +# Requests stores the text of the response in the .text attribute. Lets print it to see raw JSON +#print(tenants.text) + +# Lets make this response a bit prettier, by converting it to a JSON object and using the dumps method to provide indentation +json_response = json.loads(tenants.text) +print(json.dumps(json_response, sort_keys=True, indent=4)) \ No newline at end of file diff --git a/coding202-parsing-json/get-tenant-json-3.py b/coding202-parsing-json/get-tenant-json-3.py new file mode 100644 index 0000000..b14c51e --- /dev/null +++ b/coding202-parsing-json/get-tenant-json-3.py @@ -0,0 +1,54 @@ +import requests +# We need to import the JSON library just to handle our request to the APIC for login +import json + + +# We need to log in to the APIC and gather a token, before we can access any data +# Let's construct a request with a body + +# We'll need to disable certificate warnings +requests.packages.urllib3.disable_warnings() + +# We need to have a body of data consisting of a username and password to gather a cookie from APIC +encoded_body = json.dumps({ + "aaaUser": { + "attributes": { + "name": "admin", + "pwd": "ciscopsdt" + } + } +}) + +# Now lets make the request and store the data +resp = requests.post("https://sandboxapicdc.cisco.com/api/aaaLogin.json", data=encoded_body, verify=False) + +# This stores the received APIC-cookie from the login as a value to be used in subsequent REST calls +header = {"Cookie": "APIC-cookie=" + resp.cookies["APIC-cookie"]} + +# Now we make a call towards the tenant class on the ACI fabric with the proper header value set. +# We leverage the .xml ending to receive the data back as XML. We're adding health and faults to the printout to ensure that we get levels of data back from the APIC +tenants = requests.get("https://sandboxapicdc.cisco.com/api/node/class/fvTenant.json?rsp-subtree-include=health,faults", headers=header, verify=False) + +# Requests stores the text of the response in the .text attribute. Lets print it to see raw XML +#print(tenants.text) + +# Lets make this response a bit prettier, by converting it to a JSON object and using the dumps method to provide indentation +json_response = json.loads(tenants.text) +#print(json.dumps(json_response, sort_keys=True, indent=4)) + + +# We've commented out the pretty-print, but now lets return only the values we want. +# Everything within the returned JSON is containted within the `imdata` dictionary, so lets strip that away +json_tenants = json_response['imdata'] + +# Now we have to loop through the resulting list (using the `for` loop) and drill into the subsequent dictionaries by name +# When we get to `tenant health`, we move from `attributes` dictionary to `children` dictionary. +# Inside of the `children` dictionary is a list, which will need an index value to move further. +# Since there is only one child object within the `children` list, we can safely set this value to `0` +# This is the result of how the original query was structured, so don't assume you can always set that value to `0` +for tenant in json_tenants: + tenant_name = tenant['fvTenant']['attributes']['name'] + tenant_dn = tenant['fvTenant']['attributes']['dn'] + tenant_health = tenant['fvTenant']['children'][0]['healthInst']['attributes']['cur'] + output = "Tenant: " + tenant_name + "\t Health Score: " + tenant_health + "\n DN: " + tenant_dn + print(output.expandtabs(40)) \ No newline at end of file