In this post, we will learn how to search within Aria Hub and query our inventory using GraphQL and Altair. We will cover search examples and the use of operators, comparison functions and property names and values. We will also discuss using Aria Graph and Altair for advanced GraphQL queries.
#Aria Hub Search
As we briefly covered in the previous post Getting started with Aria Hub Free Tier we can search for objects using any of the objects data/properties - such as IP address
, name
, ID
. Here we will cover some of our options for querying data within the UI.
#Search Examples
These queries can be used within the Aria Hub UI.
- Find all EC2 Instances:
entityType = AWS.EC2.Instance
. - Find all EC2 Network ACL’s:
entityType = AWS.EC2.NetworkAcl
. - Find all EC2 Instances and EC2 Network ACL’s:
entityType = AWS.EC2.NetworkAcl OR entityType = AWS.EC2.Instance
. We useOR
because if we useAND
the object would need to be both entityTypesAWS.EC2.NetworkAcl
andAWS.EC2.Instance
at the same time, which it cant be. - Find everything within a particular AWS region:
region = us-east-1
. - Find the EC2 Network ACL’s in either of the two specified regions and provide a count of how many per region:
AWS.EC2.NetworkAcl HAS (region = us-east-2 OR region = us-east-1) count(region)
. - Find EC2 Instances launched before a specific data (e.g. 31st December 2022):
AWS.EC2.Instance HAS LaunchTime < 2022-12-31
. - Find EC2 Instances launched within the last 7 days:
AWS.EC2.Instance HAS LaunchTime > daysAgo(7)
. - Use wildcards, such as a PrivateIpAddress in the 172.31.82.x network:
AWS.EC2.Instance HAS PrivateIpAddress = 172.31.82.*
. - Find EC2 Instances that do not have InstanceType t2.large:
AWS.EC2.Instance HAS InstanceType != t2.large
. Can also be represented as:AWS.EC2.Instance HAS NOT InstanceType = t2.large
. - Find EC2 Instances with PrivateIpAddress and PublicIpAddress properties:
AWS.EC2.Instance HAS pn(PrivateIpAddress) AND propertyName(PublicIpAddress)
. Propertiespn
can be used interchangably withpropertyName
, the same forpv
andpropertyValue
.
#Operators, Comparison Operators and Functions
#Operators
These Operators are case-insentive.
HAS
- Apply one or more conditions to a resource type.AND
- Group conditions when all of them must be satisfied.OR
- Group conditions when at least one of them must be satisfied.NOT
- Reverse a condition.()
- Specify the order in which conditions are evaluated.
#Functions
hoursAgo(x)
- The time x hours earlier than now.daysAgo(x)
- The time x days earlier than now.monthsAgo(x)
- The time x months earlier than now.yearsAgo(x)
- The time x years earlier than now.
#Comparison Operators
=
- Equal to.!=
- Not equal to.<=
- Less than or equal to.=>
- Equal to or more than.<
- Less than.>
- More than.
#Identifying Object Properties
In the above queries we use various property names, we can find these names by browsing to an object of the type we are interested in, such as an AWS.EC2.Instance. Once selected we can expand the Properties pane, the left side of the table is the PropertyName (pn) and the right side of the table is the PropertyValue (pv).
#Altair
VMware Aria Graph provides built-in access to an open-source client for developing and testing your GraphQL queries and includes features like collections and pre- and post-scripts.
We have explored how to query data directly within the UI, but a key point to VMware Aria Hub is that it is powered by VMware Aria Graph. Aria Graph has been developed with an API-first approach, for us to start consuming these API’s, and specifically the data behind them, we need to use GraphQL.
There are a couple of browser based methods for this, the GraphiQL UI or with Altair, which is ”…a feature-rich GraphQL Client IDE for all platforms”. It is very similar to the GraphiQL UI but gives us a few more features.
You can access Altair either through Aria Hub > Developer Resources > Altair GraphQL Client or directly using the following link: https://api.mgmt.cloud.vmware.com/aria/altair/.
#CSP Token
Before we can use Altair we need to generate a CSP Token, you can do this by going to the Cloud Services Portal > Select the dropdown by your username (top right) > My Account > API Tokens.
- Press GENERATE TOKEN
- Provide a Token Name
- Select a Token TTL
- Select Service Role > VMware Aria Hub
- Press GENERATE and take note of the CSP token value - we will need this token for Altair
#Altair Setup
Once generated, head back to Altair. For us to be able to query data we need to authorize our requests, we can use the mutation that is provided by default to help generate a Bearer token.
At the bottom of your Altair window press the VARIABLES button and construct the input like below and then press (Run mutation). Take note of the returned Bearer token.
{
"CSP_USER_TOKEN": "c-l7aUhW7OWzJaOAaq2Ho8MYEXAMPLECSPTOKENBrJF3i9M_3N6R_JFHglYX"
}
Once you have the Bearer token, within Altair select the Set Headers menu on the left (yellow box in the image below). For the Header key enter authorization
and for the Header value enter the Bearer token, including the Bearer word. Press Save.
Now Altair is ready for us to start making some queries. Clear out the existing code in the Query panel or open a new tab by pressing + Add new at the top (make sure you set the header again).
#GraphQL Queries
Using Altair we can start to query our data that exists in Aria Hub. Lets repeat some of the searches that we did within the UI.
#Return all AWS EC2 Instances
This query returns all entities that match entityType: "AWS.EC2.Instance"
. For each of the returned entities we want the values for fields entityName
and entityType
.
{
entityQuery {
queryEntities(entityType: "AWS.EC2.Instance") {
entities {
entityName
entityId
}
}
}
}
#Return AWS EC2 Instances and all of their properties.
Similar to the above example, but this time we want to see all property names and values for each entity.
{
entityQuery {
queryEntities(entityType: "AWS.EC2.Instance") {
entities {
entityName
entityId
properties {
name
value
}
}
}
}
}
#Return AWS EC2 Instances and only some properties.
In this search we only want the name and value for specific properties from each entity. In this instance PrivateDnsName
, PrivateIpAddress
and StateName
.
{
entityQuery {
queryEntities(entityType: "AWS.EC2.Instance") {
entities {
entityName
entityId
properties(name: ["PrivateDnsName","PrivateIpAddress","StateName"]) {
name
value
}
}
}
}
}
#Introducing Variables
The previous examples were static queries, if we want to change what data gets returned we have to manually update the GraphQL query. To make it more dynamic we can start to use variables.
In the below query we take in four variables
entityId
- the ID of the object we want to look at.statKey
the metric(s) we want values forstartTime
- from what point we want to see the metricsintervalMins
- the interval of the timestamps for the metrics.
We can utilise the Altair variables window to input our values. The key of the variables payload must match the variable name in the GraphQL query, for example key entityId
matches variable $entityId
.
query awsStats($entityId: [EntityId!], $statKey: [String!], $startTime: DateTime, $intervalMins: Int) {
entityQuery {
queryEntities(entityId: $entityId) {
entities {
entityName
entityId
stats(
input: {keys: $statKey, startTime: $startTime, intervalMins: $intervalMins}
) {
key
values
timestampsMillis
}
}
}
}
}
{
"entityId": "AWS.EC2.628637233703.us-east-1.Instance.i-069ecb9cb0e422211",
"statKey": ["CPUUtilization", "NetworkIn"],
"startTime": "2022-12-27T09:49:30.629Z",
"intervalMins": 30
}
#Introducing Fragments
From the GraphQL docs, the core capability of Fragments is as follows…
Fragments let you construct sets of fields, and then include them in queries where you need to.
The query below, which is for a single AWS EC2 Instance, returns the following information
- The name, type and ID or our queried entity.
- The tags for our queried entity.
- Relationships to children entities (
entitiesIn
), including their properties and their own children. - Relationships to parent entities (
entitiesOut
), including their properties - Stats keys of our queried entity.
- Costing information of our queried entity.
If we look at the query below we are asking for the same information multiple times, for example on the queried entity we want entityId
, entityType
, entityName
and properties
, we then ask for the same with the parent and child entities that are connected. By using fragments we can reduce some of this repetition and utilise reuable information.
query entityDetails($entityId: EntityId!) {
entityQuery {
queryEntities(entityId: [$entityId]) {
entities {
entityId entityType entityName properties { name value } tags {
key
value
}
entitiesIn: entitiesIn(first: 500, traversalScope: SAME_PARTITION) {
count
totalCount
entities {
entityId entityType entityName properties { name value } service
entitiesIn: entitiesIn(first: 500, traversalScope: SAME_PARTITION) {
count
totalCount
entities {
entityId
entityType
entityName
provider
}
}
}
}
entitiesOut: entitiesOut(first: 500, traversalScope: ANY_PARTITION) {
count
entities {
entityId entityType entityName properties { name value } service
}
}
service
stats(input: {namespace: "AWS"}) {
key
}
costing {
listPrices {
publicPrice
displayName
description
}
}
}
}
}
}
To construct a Fragment we need to know the schema type, we can find that out in two ways - through the Aria GraphQL docs or by adding the __typename
field to our queries.
By using the __typeName
method we have identified two schema types that we want to construct our Fragments on: Entity and EntityConnection.
A fragment consists of two things, its name and the schema type we are fragmenting on - fragment <fragmentName> on <type>
. By using them we can reduce the overall length of our query. We can use a Fragment by referencing its name ...<fragmentName>
, as seen in the highlighted code below.
query entityDetails($entityId: EntityId!) {
entityQuery {
queryEntities(entityId: [$entityId]) {
entities {
...entity tags {
key
value
}
entitiesIn: entitiesIn(first: 500, traversalScope: SAME_PARTITION) {
...connection entities {
...entity entitiesIn: entitiesIn(first: 500, traversalScope: SAME_PARTITION) {
...connection entities {
...childrenChildrenEntity }
}
}
}
entitiesOut: entitiesOut(first: 500, traversalScope: ANY_PARTITION) {
...connection entities {
...entity }
}
stats(input: {namespace: "AWS"}) {
key
}
costing {
listPrices {
publicPrice
displayName
description
}
}
}
}
}
}
fragment entity on Entity {
__typename
entityId
entityName
entityType
service
properties {
name
value
}
}
fragment childrenChildrenEntity on Entity {
entityId
entityName
entityType
provider
}
fragment connection on EntityConnection {
__typename
count
totalCount
}
#Using our Data
One example of returned data is the stats object. Depending on what you ask for this is typically returned as values and timestamps. They are returned as seperate keys, like the example below, however they are ordered the same - e.g. the top value relates to the top timestamp.
{
"key": "CPUUtilization",
"values": [
"0.1832291531770028",
"0.18350209991521224",
"0.18358360369332824",
"0.18885047821375775"
],
"timestampsMillis": [
1672226340000,
1672224540000,
1672222740000,
1672220940000
]
}
With the metrics results we can take them and use an external tool, such as Excel to build out charts similar to the one within Aria Hub.
Aria Hub | Excel |
#Exploring Queries with Web Browser Developer Tools
Developer Tools within your web browser are a great way to find the queries being used to generate the graphics within the UI. Once you have Developer Tools open you need to find the relevant GraphQL query, in my case it was the one with operationName: "entityDetails"
.
This particular query shows the relationships as well as all of the information for the selected entity. With the query selected in Developer Tools, right click on the query field and press Copy Value for get the GraphQL query data. Do the same for the Variables entry.
The outputs from both of these can be used in Altair or other tools.
#REST API
When it comes to real world use it is unlikely you will spend all of your time within Altair, so lets explore how we can use a tool such as Postman to get the same information back via REST API.
First we need to setup Postman
- Set the Authorization header to Bearer Token and paste in our token value.
- Setup the payload Body
- Use Postman Pre-request scripts to convert our raw GraphQL query to a JSON string
- Request Method: POST
- API Endpoint: https://api.mgmt.cloud.vmware.com/aria/graphql
#Closing
This brings us to the end of this post, its been a long one. The Aria Hub Free Tier is limited to two Cloud Accounts, Azure and AWS. With the paid for version you can integrate additional clouds and data sources, such as Aria Automation and Aria Operations - with data from these sources your queries will become a lot more powerful.