Merge pull request #9251 from backstage/freben/catalog-api-docs

add catalog API docs
This commit is contained in:
Fredrik Adelöw
2022-01-31 10:01:14 +01:00
committed by GitHub
+235 -2
View File
@@ -1,7 +1,240 @@
---
id: software-catalog-api
title: API
description: Documentation on Software Catalog API
description: The Software Catalog API
---
## TODO
The software catalog backend has a JSON based REST API, which can be leveraged
by external systems. This page describes its shape and features.
## Overview
The API surface consists of a few distinct groups of functionality. Each has a
dedicated section below.
{% note %}
**Note:** This page only describes some of the most commonly used parts of the
API, and is a work in progress.
{% endnote %}
All of the URL paths in this article are assumed to be on top of some base URL
pointing at your catalog installation. For example, if the path given in a
section below is `/entities`, and the catalog is located at
`http://localhost:7007/api/catalog` during local development, the full URL would
be `http://localhost:7007/api/catalog/entities`. The actual URL may vary from
one organization to the other, especially in production, but is commonly your
`backend.baseUrl` in your app config, plus `/catalog` at the end.
Some or all of the endpoints may accept or require an `Authorization` header
with a `Bearer` token, which should then be the Backstage token returned by the
[`identity API`](https://backstage.io/docs/reference/core-plugin-api.identityapiref).
## Entities
These are the endpoints that deal with reading of entities directly. What it
exposes are final entities - i.e. the output of all processing and the stitching
process, not the raw originally ingested entity data. See [The Life of an
Entity](life-of-an-entity.md) for more details about this process and
distinction.
### `GET /entities`
Lists entities. Supports the following query parameters, described in sections
below:
- [`filter`](#filtering), for selecting only a subset of all entities
- [`fields`](#field-selection), for selecting only parts of the full data
structure of each entity
- [`offset`, `limit`, and `after`](#pagination) for pagination
The return type is JSON, as an array of [`Entity`](descriptor-format.md).
#### Filtering
You can pass in one or more filter sets that get matched against each entity.
Each filter set is a number of conditions that all have to match for the
condition to be true (conditions effectively have an AND between them). At least
one filter set has to be true for the entity to be part of the result set
(filter sets effectively have an OR between them).
Example:
```text
/entities?filter=kind=user,metadata.namespace=default&filter=kind=group,spec.type
Return entities that match
Filter set 1:
Condition 1: kind = user
AND
Condition 2: metadata.namespace = default
OR
Filter set 2:
Condition 1: kind = group
AND
Condition 2: spec.type exists
```
Each condition is either on the form `<key>`, or on the form `<key>=<value>`.
The first form asserts on the existence of a certain key (with any value), and
the second asserts that the key exists and has a certain value. All checks are
always case _insensitive_.
In all cases, the key is a simplified JSON path in a given piece of entity data.
Each part of the path is a key of an object, and the traversal also descends
through arrays. There are two special forms:
- Array items that are simple value types (such as strings) match on a key-value
pair where the key is the item as a string, and the value is the string `true`
- Relations can be matched on a `relations.<type>=<targetRef>` form
Let's look at a simplified example to illustrate the concept:
```json
{
"a": {
"b": ["c", { "d": 1 }],
"e": 7
}
}
```
This would match any one of the following conditions:
- `a`
- `a.b`
- `a.b.c`
- `a.b.c=true`
- `a.b.d`
- `a.b.d=1`
- `a.e`
- `a.e=7`
Some more real world usable examples:
- Return all orphaned entities:
`/entities?filter=metadata.annotations.backstage.io/orphan=true`
- Return all users and groups:
`/entities?filter=kind=user&filter=kind=group`
- Return all service components:
`/entities?filter=kind=component,spec.type=service`
- Return all entities with the `java` tag:
`/entities?filter=metadata.tags.java`
- Return all users who are members of the `ops` group (note that the full
[reference](references.md) of the group is used):
`/entities?filter=kind=user,relations.memberof=group:default/ops`
#### Field selection
By default the full entities are returned, but you can pass in a `fields` query
parameter which selects what parts of the entity data to retain. This makes the
response smaller and faster to transfer, and may allow the catalog to perform
more efficient queries.
The query parameter value is a comma separated list of simplified JSON paths
like above. Each path corresponds to the key of either a value, or of a subtree
root that you want to keep in the output. The rest is pruned away. For example,
specifying `?fields=metadata.name,metadata.annotations,spec` retains only the
`name` and `annotations` fields of the `metadata` of each entity (it'll be an
object with at most two keys), keeps the entire `spec` unchanged, and cuts out
all other roots such as `relations`.
Some more real world usable examples:
- Return only enough data to form the full ref of each entity:
`/entities?fields=kind,metadata.namespace,metadata.name`
#### Pagination
You may pass the `offset` and `limit` query parameters to do classical
pagination through the set of entities. There is also an `after` query parameter
to return the next page of results after the previous one when performing cursor
based pagination.
Each paginated response that has a next page of data, will have a `Link`,
`rel="next"` header pointing to the query path to the next page.
Example: Getting the first page:
```text
GET /entities?limit=2
HTTP/1.1 200 OK
link: </entities?limit=2&after=eyJsaW1pdCI6Miwib2Zmc2V0IjoyfQ%3D%3D>; rel="next"
[{"metadata":{...
```
Getting the next page, since we detect the presence of the `Link` header:
```text
GET /entities?limit=2&after=eyJsaW1pdCI6Miwib2Zmc2V0IjoyfQ%3D%3D
HTTP/1.1 200 OK
link: </entities?limit=2&after=eyJsaW1pdCI6Miwib2Zmc2V0Ijo0fQ%3D%3D>; rel="next"
[{"metadata":{...
```
### `GET /entities/by-uid/<uid>`
Gets an entity by its `metadata.uid` field value.
The return type is JSON, as a single [`Entity`](descriptor-format.md), or a 404
error if there was no entity with that UID.
### `DELETE /entities/by-uid/<uid>`
Deletes an entity by its `metadata.uid` field value.
{% note %}
**Note:** This method of deletion is appropriate for orphaned entities, but not
for removal of "live" entities that are actively being updated by a location.
Please read below.
{% endnote %}
The most common user flow is that you register a location (see below), and then
the catalog keeps itself up to date with that location and the subtree of things
that may spawn from it. This means that the catalog is a live-updating view of
an actual authoritative data source. If there's something keeping the entity
"alive" in the catalog, it will just reappear shortly after deletion with the
method described in this section. To properly remove entities, you typically
want to instead unregister the location that causes the entity to appear.
However if you have an orphaned entity, for example after removing the reference
to its file from a `Location` entity, or if a processor has stopped producing
your entity, then this deletion method is appropriate.
The return type is always an empty 204 response, whether an entity with this UID
existed or not.
### `GET /entities/by-name/<kind>/<namespace>/<name>`
Gets an entity by its `kind`, `metadata.namespace`, and `metadata.name` field
value. These are special in that they form the entity's unique
[reference](references.md) triplet.
The return type is JSON, as a single [`Entity`](descriptor-format.md), or a 404
error if there was no entity with that reference triplet.
## Locations
TODO
## Other
TODO