GraphQL is a powerful query tool because it allows efficient queries for specific information that can span multiple resources that would otherwise require literally dozens of individual REST queries and extensive data filtering, post-processing, and isolation.
This article builds on the prior articles in this series, which describe how to craft GraphQL queries in Nautobot’s GraphiQL interface and how to use GraphQL aliasing to customize the returned key names and do multiple queries in a single GraphQL request.
The previous post in this series demonstrated how to leverage the Pynautobot Python package for programmatic GraphQL queries, showing a contrasting way (from the Postman-centric way described in the post below) to construct programmatic GraphQL queries in Python against Nautobot. The Pynautobot Python path provides a very clean, customized way to programmatically run simple or sophisticated GraphQL requests against Nautobot. The methodology described in this post examines a more general way to go about that, but at the expense of additional steps. Depending on your use case, one way or the other may be preferable.
This post will demonstrate three different techniques for configuring token authentication within Postman and two different data formats in the request body.
This post uses Postman version 8.0.6.
The examples in this post all use the public Nautobot demo site and the free Postman app. Readers are encouraged to follow along.
Security tokens are typically required for programmatic access to Nautobot’s data. The following sections cover how to obtain a token and how to leverage it within Postman to craft GraphQL API calls.
Nautobot security tokens are created in the Web UI. To view your token(s), navigate to the API Tokens page under your user profile. If there is no token present, create one or get the necessary permissions to do so.
There are multiple ways to authenticate your Nautobot API queries in Postman:
Inserting the token authentication information directly in the header allows individual queries to authenticate, but the user must manually populate the header with the authentication info on each new query.
To start a query that uses this method within Postman, create a new Postman collection:
NOTE: A Postman Collection is a group of saved requests, oftentimes with a common theme, workflow, or function
Name the collection Authentication Testing.
Create a new API request by clicking on the ‘+’ sign to the right of the new collection tab.
Before we create the actual request, we’ll edit the header by adding the authentication/token info:
Authorization
in the Key column (it should allow you to auto-complete)Token<space><key>
Token aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
The Nautobot public sandbox key is
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Your Authorization portion is now complete.
The next steps will guide you through crafting the rest of the query. This query will retrieve the name of each device along with the device’s site name.
This example will use the GraphQL format in the body.
<server>/api/graphql/
query {
devices {
name
site {
name
}
}
}
Click the Send button and wait for the return data. You should see output similar to the picture below if you are using the public-facing Nautobot demo site.
Save the request in the collection.
This section will show an example of authentication in the request’s Authorization tab. This example will reside in the same Authentication Testing collection.
To create the new request:
Configure the Authorization tab first, using the settings shown below; the Token aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
entry is the same as in the prior section.
Go to the Headers tab. If the hidden headers are not already being shown, click on the hidden headers eyeball to view the hidden headers. The Authorization key-value pair should be visible now. This was auto-generated from info in the Authorization tab.
Finish out the query, but this time use raw in the Body section. Be sure to specify the format as JSON.
This query will return the device names in the bkk
site, along with each device’s rack name and device role name. Be sure to escape the double-quotes in the site query parameter as shown below.
{
"query": "query {devices(site:\"bkk\") {name device_role { name } rack { name } } }"
}
NOTE: Raw format is really cumbersome to work with, in part because of the requirement to escape quotes
Notice the potentially tedious nature of crafting the query above using the raw data option. It may be best to use the GraphQL format in the body for more complex queries.
If you check the Headers tab again, you’ll notice that changing the body format to JSON sets the Content-Type
value to application/json
.
Within a Postman collection, it is more practical to configure authentication in the collection’s environment instead of configuring authentication for each request. Configuring authentication for the entire collection lets the user configure authentication just once.
This next section will describe how to set authentication at the collection level.
To the right of the collection name there are 3 dots (1); click on them and select Edit (2).
From here
Token<space><key>
Any added requests in this collection can now use the Inherit auth from parent setting.
To configure a request to use the collection’s authentication:
Save this updated request if you wish.
Postman has helped us construct our GraphQL requests. This next section describes how to leverage those requests programmatically in Python.
This section will continue on from where we left off above, with the bkk devices request.
Postman has a very useful capability to export your crafted requests into a code format of your choice. On the right-hand side of the app, select the Code snippet button, marked as </>
.
Within the search box that appears you can type Python or select from any of the languages that appear in the dropdown menu. This example will use the Python requests library.
Selecting the Python – Requests option, you will now see Python code that will programmatically make the request using Python’s requests library and return the response.
If cookie information appears in the code and you do not wish this to be present, you can manually delete it from the code or prevent it from being generated by clicking on Cookies (located directly beneath the Send button) to open the Cookie Manager; delete any cookies configured and then regenerate the Python code.
This Python code snippet can be added to any script or simply inserted into a Python interpreter:
~ % python3
Python 3.9.2 (v3.9.2:1a79785e3e, Feb 19 2021, 09:06:10)
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>>
>>> url = "https://demo.nautobot.com/api/graphql/"
>>>
>>> payload="{\n \"query\": \"query {devices(site:\\"bkk\\") {name device_role { name } rack { name } } }\"\n}"
>>> headers = {
... 'Authorization': 'Token aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
... 'Content-Type': 'application/json'
... }
>>>
>>> response = requests.request("POST", url, headers=headers, data=payload)
>>>
>>> print(response.text)
{"data":{"devices":[{"name":"bkk-edge-01","device_role":{"name":"edge"},"rack":{"name":"bkk-101"}},{"name":"bkk-edge-02","device_role":{"name":"edge"},"rack":{"name":"bkk-102"}},{"name":"bkk-leaf-01","device_role":{"name":"leaf"},"rack":{"name":"bkk-101"}},{"name":"bkk-leaf-02","device_role":{"name":"leaf"},"rack":{"name":"bkk-102"}},{"name":"bkk-leaf-03","device_role":{"name":"leaf"},"rack":{"name":"bkk-103"}},{"name":"bkk-leaf-04","device_role":{"name":"leaf"},"rack":{"name":"bkk-104"}},{"name":"bkk-leaf-05","device_role":{"name":"leaf"},"rack":{"name":"bkk-105"}},{"name":"bkk-leaf-06","device_role":{"name":"leaf"},"rack":{"name":"bkk-106"}},{"name":"bkk-leaf-07","device_role":{"name":"leaf"},"rack":{"name":"bkk-107"}},{"name":"bkk-leaf-08","device_role":{"name":"leaf"},"rack":{"name":"bkk-108"}}]}}
>>>
NOTE: Being that there are multiple ways to use the requests library, you can also use the more concise
requests.post
method:response = requests.post(url, headers=headers, data=payload)
.
Here is a Python script that uses the requests.post
method. The script executes the GraphQL request, prints the text response, and then pretty prints the returned json data:
import json
import requests
from pprint import pprint
print("Querying Nautobot via graphQL API call.")
print()
url = "https://demo.nautobot.com/api/graphql/"
print("url is: {}".format(url))
print()
payload="{\n \"query\": \"query {devices(site:\\"bkk\\") {name device_role { name } rack { name } } }\"\n}"
print("payload is: {}".format(payload))
print()
headers = {
'Authorization': 'Token aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
'Content-Type': 'application/json'
}
print("headers is: {}".format(headers))
print()
response = requests.post(url, headers=headers, data=payload)
response_data = response.json()
print("Here is the response data in json:")
pprint(response_data)
Note the tedious nature of crafting payload
variable in the script above – it’s fairly complex with all the escaping backslashes. Luckily, the Postman app will create the object in the code for us, whether we use GraphQL or raw for the Body format.
To fully leverage GraphQL’s efficiency, it must be used programmatically. Prior posts in this series demonstrated using Nautobot’s GraphiQL interface to craft GraphQL queries and how to use GraphQL aliasing. This post builds on that by showing how to convert those GraphQL queries into remote requests in Postman and going on to export those requests to Python code for programmatic use. Also be sure to check out the prior post on using programmatic GraphQL requests with Nautobot via the pynautobot
package and how that stacks up against the methodology in this post. Generally, the pynautobot
path has fewer moving parts and offers customized APIs for Nautobot that allow sophisticated GraphQL queries. The Postman+requests path offers a more general framework but with more steps.
Share details about yourself & someone from our team will reach out to you ASAP!