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).
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 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>
.
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 | - | - | - |
The PATCH method can be used for simple updates of an existing resource.
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 PATCH. In order to do that, the entire object must be replaced by using PUT.
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.
This endpoint represents the tenant's entire intended configuration.
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 ...
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. It
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 create if
it doesn't exists.update
- The existing object is merged 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
.
For example, the following request deletes the application
other-app
and updates the application deployment my-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
If an object has a field x-etag
, the operation succeeds only if
the object exists with the same etag.
NOTE: It is not possible to update objects in strongbox through this endpoint.
This endpoint represents the tenant's entire operational state.
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 ...
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.
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:
fields=foo,bar
- selects the fields foo
and bar
fields=foo/bar
- selects the fields bar
in foo
fields=foo/[bar,baz]
- selects bar
and baz
in foo
fields=foo=x/bar
- selects bar
in foo
, and renames foo
to x
in the output