Earlier in the year, we announced updates to the Harness API. We introduced the capability of interacting with the Harness API through GraphQL. This blog post will share additional insights into GraphQL, giving you what you need to know in order to interact with the Harness API.
Let’s start with a graphQL primer first!
GraphQL, it is an open-source API query language created by Facebook that enables declarative data fetching. Since its introduction, GraphQL has taken developer mindshare as an alternative to REST APIs, offering solutions to issues that API developers and users experience when working with RESTful architectures.
The most significant advantage to be had when working with GraphQL is its flexibility. Instead of having multiple endpoints that return fixed data structures, GraphQL exposes a single endpoint and responds to multiple queries. As the name suggests, GraphQL models your business domain in a graph structure. The fields and relationships represented as nodes and edges of a graph structure minimize the amount of data passed between the client and the server per request.
The client specifies precisely the data it needs in a query, and the structure of the response follows precisely the nested structure defined by the query. This prevents the common issues of overfetching (returning a query where the client has more information than what is required) or underfetching (and thus requiring multiple queries) data.
To define the capabilities of an API, GraphQL requires the object types to be defined in a schema using the GraphQL Schema Definition Language (SDL). This schema serves as the contract between the client and the server to define how a client can access the data. This benefits development teams as they’ve defined a shared language and understanding of the domain model.
Here are some SDL examples.
// To define a person:
type Person {
name: String!
age: Int!
}
// Expressing a relationship between a Post and a Person:
type Post {
title: String!
author: Person!
}
//Expressing the other end of the relationship. A Person with multiple posts:
type Person {
name: String!
age: Int!
posts: [Post!]!
}
The examples show that objects have strongly typed fields. Fields with an exclamation mark at the end denote mandatory fields that will be part of the client request.
Once a GraphQL service is running it can receive queries to validate and execute based on the schema. The query is checked to ensure it only refers to the types and fields defined then it runs the functions produce a result. For example the query:
{
post {
title
author
}
}
Could produce the JSON result:
{
"post": {
"title": "Star Wars",
"author": "Luke Skywalker"
}
}
Understanding the SDL gives you what you need to start using Harness’ API Explorer to perform queries and mutations. Let's discuss some features and examples of the API Explorer.
Harness' API Explorer gives users the ability to perform CRUD operations on Harness entities. The API Explorer is based on a GraphQL Integrated Development Environment(IDE) called GraphQL. Find functional buttons along the top part of the left side of the screen, an editor, and a "query variables" for passing along variables for mutations.
The documentation explorer lets you easily model your queries. Click on the Docs hyperlink on the right-hand side of the explorer to access the documentation explorer. You can utilize the search bar capabilities to quickly access Harness specific schema details.
Here is how to do a simple query in the API explorer. As shown in the video I edited the query to return more information about the application.
If you'd like to fetch a list of services based on an applicationID you can specify in a query that looks like this.
{
services(
filters: [
{ application: { operator: EQUALS, values: ["<applicationId>"] } }
]
limit: 1000
) {
pageInfo {
total
}
nodes {
id
name
}
}
}
Note here that query.services function returns paginated data so we include the pageinfo and nodes objects in the query to shape the return.
For more samples for basic queries, please see the documentation chapter here.
Mutations offer a way to modify (create, update, delete) server-side data. Below an example mutation that creates applications within Harness.
I first define the mutation, which I call createApp, which takes a query variable called app as the required CreateApplicationInput. I use the createApplication functionality and pass app as an input. The input requires at a minimum a name field, so I define the query variable with the required field along with a clientMutationId and description for the app. I would like to get the created application’s name and id along with the clientMutationId, so I specify that return in lines 3-8.
Through mutations, you can create, update, and delete Harness objects, including users, applications, secrets, and pipelines. If you would like additional examples of queries and mutations, see the Harness API documentation here.
Virtually all of Harness' meaningful entities are exposed through the API, including Applications, Services, artifacts, Cloud Providers, Environments, Workflows, Pipelines, deployed instances, and deployment data. We announced in our February product update the ability to use GraphQL to interact with the Harness API. GraphQL offers these efficiency and reliability features for your consuming applications:
This blog shares the basics of GraphQL and how to use the Harness API Explorer. You can also perform the Harness GraphQL queries through Postman, refer to the Harness documentation for the setup.
If you’d like to learn more about GraphQL click here for the official learning link. I hope this serves you well as a resource for using GraphQL to use Harness your way.
Cheers!
-- Tiff