Avassa API (v1)

Download OpenAPI specification:Download

Generated at: 2025-01-16T10:27:12+00:00

Introduction

This API is a HTTP-based REST API with predictable resource URIs. The API accepts and returns data encoded in YAML or JSON.

The API provides a clean separation between configuration, operational state, and operations (RPCs).

API URLs

When connecting to a Control Tower API, assuming your Control Tower is at https://my-env.acme.avassa.net, the API URL is https://api.my-env.acme.avassa.net

From inside an application container, the API endpoint for the local Edge Enforcer is always reachable at https://api.internal:4646.

Configuration and Operational State

Configuration data is read and written under the path /v1/config. This data is called the intended configuration. It is the configuration data provided by the user of the system. All data in the intended configuration is both readable and writable.

The operational state of the system can be read under the path /v1/state. The operational state is read only. The operational state contains the state of all intended configuration (this is called the applied configuration), and all system state.

The state of a configured object under /v1/config/<PATH> can be read from /v1/state/<PATH>.

URIs and Methods

The table below shows the structure of the API.

URI GET POST PUT PATCH DELETE
/v1/config read all crud - - -
/v1/config/LIST read all create - - -
/v1/config/LIST/NAME read one - create/replace update delete
/v1/config/OBJECT read - create/replace update delete
/v1/state read all - - - -
/v1/state/LIST read all - - - -
/v1/state/LIST/NAME read one - - - -
/v1/state/OBJECT read - - - -
/v1/state/OPERATION - invoke - - -
/v1/OPERATION - invoke - - -

All resources also support the OPTIONS method.

PATCH

The PATCH method (RFC 5789) can be used for updates of an existing resource.

Two formats of the body are supported, plain patch and JSON Patch (RFC 6902).

The strongbox resources support plain patch only.

Plain patch

Plain patch is indicated by using the Content-Type header application/json or application/yaml.

The existing object is merged with the data in the payload.

A scalar value in the payload replaces the corresponding value in the object, if it exists; otherwise the given scalar value is created.

Arrays where the order is significant are replaced with the new array.

Arrays where the order is not significant are merged. This means that it is not possible to delete entries in such arrays with plain patch. In order to do that, JSON Patch can be used.

JSON Patch

JSON Patch is indicated by using the Content-Type header application/json-patch+json or application/json-patch+yaml.

The JSON Patch operations copy and move are not supported.

In addition to the standard operations add, remove, replace, and test, the following operations are also supported:

  • safe-remove: works just like remove, except that no error is raised if the target location object does not exist.
  • safe-replace: works just like replace, except that if the target location object does not exist it is created.

For example, given the site object:

name: stockholm-sergel
type: edge
topology:
  parent-site: control-tower
labels:
  region: europe
  country: sweden
management-ipv4-access-list:
  - 192.168.100.1
  - 10.0.4.1
hosts:
  - host-id: 38cfff0d-cce6-4f71-99dd-98612719cd79

we can add a new label and change the management-ipv4-access-list with the following request:

- op: add
  path: /labels
  value:
    city: stockholm
- op: replace
  path: /management-ipv4-access-list/0
  value: 192.168.200.1
- op: remove
  path: /management-ipv4-access-list/1

The resulting site is now:

name: sthlm-sergel
type: edge
topology:
  parent-site: control-tower
labels:
  region: europe
  country: sweden
  city: stockholm
management-ipv4-access-list:
  - 192.168.200.1
hosts:
  - host-id: 38cfff0d-cce6-4f71-99dd-98612719cd79

ETag Usage

All objects in the intended configuration have an entity tag (ETag) that can be used to control concurrent access to the object, and detect if an object has been modified.

Use standard HTTP mechanisms (e.g., the header If-Match) to handle entity tags.

The /v1/config Endpoint

This endpoint represents the tenant's entire intended configuration.

GET

A GET to this endpoint returns the entire intended configuration.

If YAML is requested, each object is returned as a separate YAML document. If JSON is requested, a list of objects is returned.

In the representation of each object, an additional field x-path is included, that contains the path to the object.

If the query parameter send-etag=true is sent, each object also has a field x-etag.

For example, the reply could look like this:

---
x-path: /v1/config/applications/my-app
name: my-app
version: 1.2.2
# more data here ...
---
x-path: /v1/config/application-deployments/my-dep
name: my-dep
application-name: my-app
application-version: 1.2.2
# more data here ...

POST

A POST to this endpoint is used to update multiple objects in one transaction, i.e., either all included operations are accepted, or none.

The format of the POST request is the same as result of a GET request, except that each object also may have an additional field x-operation, that controls how the object is updated, and an optional field x-json-patch.

The POST request body can be YAML or JSON.

The field x-operation can have the following values:

  • create - The object is created if it doesn't exists. An error is returned if the object already exists.
  • replace - The object is replaced if it exists, and created if it doesn't exists.
  • update - The existing object is updated with the given fields. An error is returned if the object doesn't exists.
  • delete - The object is deleted if it exists. An error is returned if the object doesn't exist.
  • remove - The object is deleted if it exists. No error is returned if the object doesn't exist.

The query parameter default-operation can be given to specify which operation is used for a object that doesn't have an x-operation field. If no such query parameter is given, the default operation is replace.

When the operation is update, the object can be updated with plain patch (which means that the object is merged with the given fields), or with JSON Patch. In order to use JSON Patch, set the array of JSON Patch operations in the field x-json-patch.

The operation update corresponds to the PATCH method for single resources. See PATCH for details. Note that even though the name of the format is json-patch, the data can be encoded in both JSON and YAML.

For example, the following request deletes the application other-app and updates the application deployments my-dep and another-dep:

---
x-path: /v1/config/applications/other-app
x-operation: delete
---
x-path: /v1/config/application-deployments/my-dep
x-operation: update
application-version: 1.2.3
---
x-path: /v1/config/application-deployments/another-dep
x-operation: update
x-json-patch:
  - op: replace
    path: /placement/match-site-labels
    value:
      os-type: debian

If an object has a field x-etag, the operation succeeds only if the object exists with the given etag.

NOTE: It is not possible to update objects in strongbox through this endpoint.

The /v1/state Endpoint

This endpoint represents the tenant's entire operational state.

GET

A GET to this endpoint returns the entire operational state.

If YAML is requested, each object is returned as a separate YAML document. If JSON is requested, a list of objects is returned.

In the representation of each object, an additional field x-path is included, that contains the path to the object.

For example, the reply could look like this:

---
x-path: /v1/config/applications/my-app
name: my-app
version: 1.2.2
# more data here ...
---
x-path: /v1/config/application-deployments/my-dep
name: my-dep
application-name: my-app
application-version: 1.2.2
# more data here ...

Error Handling

The API uses standard HTTP status codes to indicate success or failure of the requests. When an error body is returned, it is on the form:

{
  "errors": [
    "error-message": "string",
    "error-info": "optional operation-specific error info"
  ]
}

The error is returned as JSON or YAML depending on the given Accept header.

Common Query Parameters

fields

The fields query parameter can be used in GET requests to return only the requested fields in the reply.

The syntax of this parameter is:

sequence           = expr ( ',' expr )*
expr               = path ( '/'  '[' sequence ']' )?
path               = field-name ( '/' path )?
field-name         = identifier
                       / identifier '=' identifier

For example:

  • foo,bar - selects the fields foo and bar
  • foo/bar - selects the field bar in foo
  • foo/[bar,baz] - selects the fields bar and baz in foo
  • foo=x/bar - selects bar in foo, and renames foo to x in the output

where

The where query parameter can be used in GET requests to list endpoints to return only list items that match the given expression.

The syntax of this parameter is:

expr               = path-expr / logical-expr / arith-expr / function-call
                     / literal / number

path-expr          = ['/'] relative-path-expr
relative-path-expr = ( ('.' | '..' | identifier) [ predicate ] )*
predicate          = '[' expr ']'

logical-expr       = expr logical-operator expr
logical-operator   = '>' / '>=' / '<' / '<='
                     / '=' / '!='
                     / 'and'
                     / 'or'

arith-expr         = '-' expr
                     / expr arith-operator expr
arith-operator     = '+' / '-' / '*' / 'div' / 'mod'

function-call      = function '(' arg? (',' arg)* ')'
arg                = expr

literal            = '"' text '"'
                     / "'" text "'"

The following functions are implemented:

  • boolean(object) - converts its argument to a boolean.
  • number(object) - converts its argument to a number.
  • string(object) - converts its argument to a string.
  • true() - returns true.
  • false() - returns false.
  • not(boolean) - returns true if its argument is false and returns false otherwise.
  • starts-with(string, string) - returns true if the first argument string starts with the second argument string, and false otherwise.
  • contains(string, string) - returns true if the first argument string contains the second argument string, and false otherwise.
  • re-match(string, string) - the second argument is a regular expression. returns true if the regular expression matches the first argument string.
  • string-compare(string, string) - returns -1 if the first argument string is lexicographically smaller than the second argument string, 0 if the strings are equal, and 1 otherwise.
  • match-labels(object, string) - the string argument is a label match expression, and the object argument is a field with labels. returns true of the string argument matches the labels in the object argument, and false otherwise.

For example, when doing a GET to the list of assigned sites:

  • type = 'edge' - selects all sites where the field type is "edge". Note that edge must be given as a string!
  • 'edge' = type - also selects all sites where the field type is "edge".
  • type = 'edge' and connection-state/connected = true()` - selects all connected edge sites.
  • deployed-applications > 0 - selects all sites with at least one deployed application.
  • starts-with(name, 'sto-') - selects all sites where the name field starts with the string "sto".
  • contains(name, 'swe') - selects all sites where the name field contains the string "swe".
  • re-match(name, 'sto-[0-9]+') - selects all sites where the name field matches the given regular expression.
  • string-compare(connection-state/last-connect, '2024-04-01') == -1 - selects all sites that connected before 2024-04-01.
  • match-labels(host-labels, 'security = high') - selects all sites that have a security host label with the value high.

This syntax is a subset of XPath 1.0. For a complete description of the syntax and evaluation semantics, see the XPath 1.0 spec (https://www.w3.org/TR/1999/REC-xpath-19991116/).