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 use OR because if we use AND the object would need to be both entityTypes AWS.EC2.NetworkAcl and AWS.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). Properties pn can be used interchangably with propertyName, the same for pv and propertyValue.

Inventory search within a specific region
Inventory search within a specific region

Multiple entityType search
Multiple entityType search

Search across multiple regions based on the entityType, displayed as a count per region
Search across multiple regions based on the entityType, displayed as a count per region

#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).

Object Properties
Object Properties

#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.

GraphiQL UI
GraphiQL UI

Altair UI
Altair UI

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.

Altair IDE Setup
Altair IDE Setup

Altair IDE Headers
Altair IDE Headers

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.

Return all AWS EC2 Instances
Return all AWS EC2 Instances

{
  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.

Return AWS EC2 Instances and all of their properties
Return AWS EC2 Instances and all of their properties

{
  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.

Return AWS EC2 Instances and only some properties
Return AWS EC2 Instances and only some properties

{
  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 for
  • startTime - from what point we want to see the metrics
  • intervalMins - 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.

Return specific AWS EC2 Instance with metrics/stats
Return specific AWS EC2 Instance with metrics/stats

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.

__typeName field information
__typeName field information

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 HubExcel

Metrics in Aria Hub chart
Metrics in Aria Hub chart

Metrics in Excel chart
Metrics in Excel chart

#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.

Web Browser Developer Tools to find GraphQL queries
Web Browser Developer Tools to find GraphQL queries

Altair query with Developer Tools information
Altair query with Developer Tools information

#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

Set Authorization to Bearer Token
Set Authorization to Bearer Token
Set Payload Body
Set Payload Body
Set Pre-Request Script
Set Pre-Request Script
Returned Data
Returned Data

#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.

#Resources

Share to TwitterShare to FacebookShare to LinkedinShare to PocketCopy URL address
Written by

Sam Perrin@samperrin

Automation Consultant, currently working at Xtravirt. Interested in all things automation/devops related.

Related Posts