GraphQL
The GraphQL interface is the main interface to interact with Infrahub. The GraphQL schema is automatically generated based on the core models and the user-defined schema models.
The endpoint to interact with the main branch is accessible at https://<host>/graphql
.
To interact with a branch the URL must include the name of the branch, such as https://<host>/graphql/<branch_name>
.
If you need to extract the current GraphQL schema in your environment you can issue an HTTP get request to:
https://<host>//schema.graphql
https://<host>//schema.graphql?branch=some-other-branch
Query & mutations
In GraphQL, a query is used to fetch data and mutations are use to create/update or delete data. In Infrahub, a GraphQL query and 4 mutations will be generated for each model you define in the schema. The name of the query or mutation is based on the namespace and name of the model.
For example, for the model CoreRepository
the following query and mutations have been generated:
Query
: CoreRepository to fetchCoreRepository
nodes from InfrahubMutation
: CoreRepositoryCreate to create aCoreRepository
nodeMutation
: CoreRepositoryUpdate to update an existingCoreRepository
nodeMutation
: CoreRepositoryUpsert to create or update aCoreRepository
nodeMutation
: CoreRepositoryDelete to delete aCoreRepository
node
Query format
The top level query for each model will always return a list of objects and the query will have the following format CoreRepository
> edges
> node
> display_label
query {
CoreRepository { # PaginatedCoreRepository object
count
edges { # EdgedCoreRepository object
node { # CoreRepository object
id
hfid
display_label
__typename
}
}
}
}
All list of objects will be nested under edges
& node
to make it possible to control the pagination and access the attribute count
.
ID
, hfid
and display_label
For all nodes, the attribute id
, hfid
and display_label
are automatically available.
The value used to generate the display_label
can be defined for each model in the schema. If no value has been provided a generic display label with the kind and the ID of the Node will be generated.
The value used to generate the hfid
can be defined for each model in the schema. If no value has been provided and the model
has a single uniqueness constraint defined, then the hfid
will be automatically generated from the uniqueness constraint.
At the object level, there are mainly 3 types of resources that can be accessed, each with a different format:
Attribute
Relationship
ofCardinality One
Relationship
ofCardinality Many
Attribute
Each attribute is its own object in GraphQL to expose the value and all the metadata.
In the query below, to access the attribute name of the object the query must be CoreRepository
> edges
> node
> name
> value
.
At the same level all the metadata of the attribute are also available example: is_protected
, is_visible
, source
& owner
query {
CoreRepository {
count
edges {
node {
name { # TextAttribute object
value
is_protected
is_visible
source {
id
display_label
}
}
}
}
}
}
Relationship of Cardinality One
A relationship to another model with a cardinality of One
will be represented with a NestedEdged
object composed of a node
and a properties
objects. The node
gives access to the remote node
(the peer of the relationship) while properties
gives access to the properties of the relationship itself.
query {
CoreRepository {
count
edges {
node {
account {
properties {
is_visible
is_propected
source {
id
display_label
}
}
node {
display_label
hfid
id
}
}
}
}
}
}
Relationship of Cardinality Many
A relationship with a cardinality of Many
will be represented with a NestedPaginated
object composed. It was the same format as the top level PaginatedObject
with count
and edges
but the child element will expose both node
and properties
. The node
gives access to the remote node
(the peer of the relationship) while properties
gives access to the properties of the relationship itself.
query {
CoreRepository {
count
edges {
node {
tags { # NestedPaginatedBuiltinTag object
count
edges { # NestedEdgedBuiltinTag object
properties {
is_protected
source {
id
}
}
node {
display_label
hfid
id
}
}
}
}
}
}
}
Mutations format
The format of the mutation to Create
, Update
and Upsert
an object has some similarities with the query format. The format will be slightly different for:
- An
Attribute
- A relationship of
Cardinality One
- A relationship of
Cardinality Many
Create, update and upsert
To Create
, Update
or Upsert
an object, the mutations will have the following properties.
- The input for the mutation must be provided inside
data
. - All mutations will return
ok
andobject
to access some information after the mutation has been executed. Update
mutations require you to provide anid
orhfid
to identify the object you want to update.Upsert
mutations do not require you to provide theid
or thehfid
, but enough information needs to be provided for the back-end to uniquely identify the node. Typically this means that all the attribute or relationship values need to be provided that make up thehfid
oruniqueness_constraints
of the node.
mutation {
CoreRepositoryCreate(
data: {
name: { value: "myrepop" }, # Attribute
location: { value: "myrepop" }, # Attribute
account: { hfid: ["my_account"] }, # Relationship One
tags: [ { hfid: ["my_tag"] } ]} # Relationship Many
) {
ok
object {
id
hfid
}
}
}
Delete
For a Delete
mutation, we have to provide the id
or the hfid
of the node as part of the data
argument.
mutation {
CoreRepositoryDelete(data: {hfid: ["myrepo"]}) {
ok
}
}
Branch management
In addition to the queries and the mutations automatically generated based on the schema, there are some queries and mutations to interact with the branches.
- Query:
Branch
, Query a list of all branches - Mutation:
BranchCreate
, Create a new branch - Mutation:
BranchUpdate
, Update the description of a branch - Mutation:
BranchDelete
, Delete an existing branch - Mutation:
BranchRebase
, Rebase an existing branch with the main branch - Mutation:
BranchMerge
, Merge a branch into main - Mutation:
BranchValidate
, Validate if a branch has some conflicts
Stored GraphQL queries in the database
The GraphQLQuery
model has been designed to store a GraphQL query in order to simplify its execution and to associate it with other internal objects like Transformation
.
A GraphQLQuery
object can be created via the web interface, the API or it can be imported from a Git repository.
Every time a GraphQLQuery
is created or updated, the content of the query will be analyzed to:
- Ensure the query is valid and compatible with the schema.
- Extract some information about the query itself (see below).
Information extracted from the query
- Type of operations present in the Query [Query, Mutation, Subscription]
- Variables accepted by the query
- Depth, number of nested levels in the query
- Height, total number of fields requested in the query
- List of Infrahub models referenced in the query
Import from a Git repository
GraphQL queries could be defined in file(s) with a .gql
extension in a remote repository. Then queries must also be explicitly identified in the .infrahub.yml
file under queries
.
More details on the .infrahub.yml
file format can be found in .infrahub.yml topic.
Executing stored GraphQL queries
Stored GraphQL queries can be executed by using the /api/query/{query_id}
REST API endpoint. The {query_id}
can be the name or the id of the GraphQLQuery
node in the database. More information can be found in the Swagger documentation.