The REST API
1. What is Axebow API
Note, some parts of the document refer to features not yet implemented as of the date of publication of the document. They are marked as NYI
AxebowAPI is the specification of the service that the Axebow platform exposes to its users (mostly excluding operators of the platform itself). It is in charge of attending requests to manage services, platform resources (volumes, secrets, …), users and tenants.
The API can be divided in three main sections:
- System Information
-
To retrieve information about the Axebow service and its underlying elements.
- Tenants
-
To manage tenants, their services and resources.
- Users
-
To manage users accessing Axebow.
In addition, The Tenant section is composed of several subsections
- Resources
-
To manage registration, removal, and modifications, and sharing Kumori Resources.
- Services
-
To manage the deployment of kumori applications and the lifecycle of the resulting services.
- Accounts
-
To manage IaaS access to its resources.
- Deployment environments
-
To define and manage IaaS environments where to run the services of the tenant.
(See Kumori Platform for information about the technology underlying Axebow)
Finally, The Resource section deals with the following elements
- CA
-
to manage certificate authorities.
- Certificates
-
to manage certificates.
- Domains
-
to manage the internet domains used to access the deployed services through HTTP inbounds.
- Ports
-
to manage the ports used to access the deployed services through TCP ports.
- Secrets
-
to manage the secrets used in deployed services.
- Volumes
-
to manage the volumes used by deployed services to store data.
2. API
AxebowAPI is HTTP based, routing different actions based on the request’s URL and the HTTP method being used.
Axebow authenticates its users by the use of mTLS client certs (only for operations) or through a set of federated ID providers. All calls to the API (except the call to get the information about Axebow) must be authenticated.
In general the API manipulates entities. For this API version, we consider the following entities:
- platform
-
The platform instance itself.
- tenant
-
Organizations contracting services with the platform.
- user
-
Users authenticating to the platform.
Those entities are named, and the names are scoped to the entity types.
Within an instance of an entity, we can manipulate subentities that we will refer to as objects. Depending on the entity, there will be different object types.
Like entities, object instances will also be named, and names will be scoped to their entity as well as their object type.
The platform
entity has only one instance, and calls to access it may not include its name.
At this point in time, platform instances have no object types associated.
Likewise, the user
entity has no object types in this API version.
tenants
admit the following object types:
account
-
Axebow tenant IaaS information management.
service
-
Deployed service management and updates.
domain
-
Kumori Resource
domain
management port
-
Kumori resource
port
management certificate
-
Kumori resource
port
management ca
-
Kumori resource
ca
(certificate authority) management secret
-
Kumori resource
secret
management volume
-
Kumori resource
volume
management
Accounts also admit the following object type:
environment
-
Axebow tenant deployment environment management within an account
2.1. API Format
2.1.1. Request
The notation below uses angle brackets to specify elements of a URI that MUST be present. Square brackets are used for optional elements.
The HTTP API paths general format is as follows:
<OPERATION> /api/<version>/<entity>/[entity name]/[<object_type>/[object_name]/[section...]]?[params]
The <OPERATION>
, version
and <entity>
sections are mandatory.
The <OPERATION>
must be one of the following:
GET
-
to read information.
POST
-
to register a new object in the system.
PUT
-
to modify a previously registered object.
DELETE
-
to delete a previously registered object.
PATCH
-
To partially modify a previously registered object
In this document we describe the API versioned as 1.0-beta
, thus 1.0-beta MUST be included in the URL path.
Further versions will be assigned different version numbers following a semantic versioning approach
with only two components (and potentially, a prerelease qualifier).
The [section]
part is used when the call refers to a specific portion of the object,
for those objects for which such sections are defined. They will be discussed when describing
each object type.
The [params]
are query parameters defined per <entity-kind>/<object-type>/[section]
and operation.
In addition, some requests may carry with them files and/or JSON objects in the body.
AxebowAPI offers a swagger endpoint (/docs
).
Example:
GET /api/1.0-beta/tenant/mycompany/service/myservice/history
Reads section history
within the myservice
service of tenant mycompany
In this document, JSON body structure will be specified using the CUE language. The JSON Schma specification can be obtained from Axebow’s endpoint.
2.1.2. Response
Each call will receive an Http response code.
Content resulting from a return Http code of 2XX has the following format:
#APIResponse: {
data? : #PlatformResponse | #TenantResponse | #UserResponse (1)
events?: [...{ (2)
message: _ (3)
level : "ERROR" | "WARNING" | "INFO" (4)
}]
}
1 | The response content itself, if any. Will follow a different schema for different calls. |
2 | Array of events related to this call (if any). Each event has the following format: |
3 | An object containing information about the event |
4 | Level of severity for the event ERROR , WARNING or INFO - |
HTTP error codes to be expected are:
4xx error codes
- 400
-
client make an invalid request
- 401
-
invalid authentication credentials
- 403
-
authorization failure
- 404
-
cannot find the requested resource
- 409
-
request conflicts with the current state of the server
- 415
-
unsupported payload format
- 429
-
the user has sent too many requests in a given amount of time
5xx error codes
- 500
-
internal server error
- 501
-
functionality to fulfill the request is not supported
- 502
-
invalid response from the upstream server
- 503
-
server is not ready to handle the request
- 504
-
request timeout from the upstream server
Error responses will have a JSON body with the following structure
#ErrorBody: {
code: #AxebowErrorCodes, (1)
content: _ (2)
}
1 | A string among a reduced set of strings encoding additional info about the error |
2 | An object, with a structure dependent on the code |
3. System Information
3.1. Get Instance Information
GET /platform
Gets information about the Kumori platform instance.
-
Parameters: none.
-
Request body: none.
-
Example response data (TBD):
#PlatformInfo: { apiVersions : [...#ProtocolVersion], (1) instanceName : string, (2) platformVersion: #Version, (3) oidProviders: string[] (4) iaasProviders: [provider:string]: {...} (5) freemiumAdvancedLimits: #Limits (6) freemiumLimits: #Limits (7) portRange: number[] (8) referenceDomain: string (9) }
1 The list of API versions supported 2 The name of the platform instance 3 The version of the platform tech stack 4 The set of oid providers accepted by Axebow 5 a dictionary with the IaaS providers supported, and their configurable characteristics 6 Resource consumption limits for freemium accounts 7 Resource consumption limits for basic freemium accounts 8 Range of ports available 9 Reference domain of the platform
4. Users
Users in Axebow are agents that operate on behalf of tenants and must authenticated by means of some openid provider (alternatively, Certificates can also be used for mTLS interactions).
Axebow will establish a trust relationship with a set of openid providers. Only users that can authenticate against one of those providers will be able to use Axebow’s API.
All interactions with the API described here must come from an authenticated user: the agent of the API request.
When a user is registered to Axebow it is issued a platform-generated UID, that is associated to the authenticated user.
A user can add openid provider profiles to its Axebow registration.
In this section we provide the APIs Axebow provides to handle users on the platform.
The agent of a user request can only be the user itself or an operator.
4.1. User registration
A user registers by simply posting a profile and providing an Authentication token containing the user’s information, as well as a few more parameters in the body for providing more information.
POST /api/1.0-beta/user
Registers the authenticated user.
If the user has already been registered, the call fails.
-
Parameters: none
-
Request body:
-
JSON structure as
{ name: string, surname: string, discoveryMethod?: string, companyName?: string, companyRole?: string }
-
-
Response: standard response with the data field containing the UID of the created user.
-
internal UID
-
{ success: true, errors: [], data: { userid: urecord.id.name } }
4.2. Add profile
POST /api/1.0-beta/user/provider
Creates a user’s profile for one of the platform’s known oid providers.
The call fails if
-
the user already has a profile for <oidp>
-
Parameters: none
-
Request body:
-
JSON structure as
-
{
jwt: string
}
-
Response: Generic, with no data
Note that the jwt must be signed by the provider, and must not have expired.
UNIMPLEMENTED |
4.3. Remove profile
DELETE /api/1.0-beta/user/provider/<oidp>
Will only succeed if oid
is not the only profile for the user
-
Parameters: none
-
Request body: none
-
Response: Generic
4.4. Remove user
DELETE /api/1.0-beta/user
Removes the user making the request.
The user can’t be removed when: * The user is the last "owner" member in a tenant
-
Parameters: none
-
Request body: none
-
Response: Generic
4.5. Get info
GET /api/1.0-beta/user/info
Gets the information of the user making the request.
-
Parameters: none
-
Request body: none
-
Response:
-
JSON with user detailed data
#UserInfo: { tenants: { [string]: #TenanUserRole } profiles: { [oidp=string]: #OIdPProfile[oidp] } }
-
4.6. List
GET /api/1.0-beta/user
Gets the list of users. Can only be used by the operator tenant.
-
Parameters: none
-
Request body: none
-
Response:
-
JSON with the list of users ID.
[...{ name: string, // user given name uid: string, // internal user ID. }]
-
5. Tenants
A tenant is an organization that has established a contract of usage with Axebow. Tenants are created by registered users that act on their behalf.
When a registered user creates a tenant, it becomes its owner, and can request any action on behalf of the tenant, including adding other users to it.
Users in a tenant can have one of three roles: owner
, admin
, and plain
, in descending
order of privileges.
Detailed authorization to perform specific actions on behalf of a tenant by any of its users MUST be established by the tenant itself, with its own authorization model and policies that can only be established by admins of the tenant.
Axebow authorizes calls in two phases: the first phase it implements directly and simply checks that the user has been added to the tenant it wants to request an action for.
If the first phase check passes, a second phase authorization is performed by executing a series of selectors to determine if an action, specially a deployment action, can be carried out.
Tenant API calls, as a general rule, must be carried out by users of a tenant, or by operators. Operators are not subject to tenant’s authorization policies.
An operator is a user of the operator
tenant.
5.1. Create Tenant
POST /api/1.0-beta/tenant/<name>
Creates a new tenant whose owner is the user making the request. If the name is taken the request fails
-
Parameters: none
-
Request body:
-
JSON
#TenantSpec: { rules: { // Selecting an environment to deploy a service selectEnvironmentService : [...{reason: string, sel: #Selector}] // Selecting an environment with explicit acceptance selectAcceptEnvironmentService: [...{reason: string, sel: #Selector}] // Validates an environment to place a resource within validateEnvironmentResource : [...{reason: string, sel: #Selector}] // Validates an environment for a User to deploy there validateEnvironmentUser : [...{reason: string, sel: #Selector}] }, registry: { endpoint : string, (1) credentials? : string, (2) domain : string, (3) public : *true | bool (4) } }
When registering a tenant a NMP registry account can be configured in which can be published kumori modules.
1 endpoint
: endpoint of your npm registry2 credentials
: credentials for your npm registry3 domain
: domain under which the modules will be published in the registry4 public
: selector for choosing wheter to make published modules public or private.
-
-
Response: common response
5.2. Update Tenant
PATCH /api/1.0-beta/tenant/<name>
Updates an existing tenant information. If the tenant does not exist the request fails.
-
Parameters: none
-
Request body:
-
JSON
#TenantSpec: { rules: { // Selecting an environment to deploy a service selectEnvironmentService : [...{reason: string, sel: #Selector}] // Selecting an environment with explicit acceptance selectAcceptEnvironmentService: [...{reason: string, sel: #Selector}] // Validates an environment to place a resource within validateEnvironmentResource : [...{reason: string, sel: #Selector}] // Validates an environment for a User to deploy there validateEnvironmentUser : [...{reason: string, sel: #Selector}] }, registry: { endpoint : string, (1) credentials? : string, (2) domain : string, (3) public : *true | bool (4) } }
-
-
Response: common response
5.3. Remove
DELETE /api/1.0-beta/tenant/<tenant>
Removes the tenant <tenant>.
The request will fail when:
-
The user making the call is not the only owner of the tenant
-
There are services running for the tenant.
When a tenant is removed, all its resource registrations are also removed, as well as all its environments and accounts. Axebow may keep whatever information it needs for proper reporting the usage of the platform, but such information will no longer be available to the tenant through this API.
When a tenant is removed, its name can be re-used for a new tenant after the removal has been completed.
-
Parameters: none
-
Request body: none
-
Response: common response
5.4. Accounts
Tenants can establish accounts. An account identifies a IaaS provider and fills in information needed to access its API (credentials)
In addition, when adding an account, a tenant establishes which IaaS resource flavors
(VMs, storage classes,…) it wants to consider when allocating them on the IaaS.
5.4.1. Add Account
POST /api/1.0-beta/tenant/<tenant>/account/<acname>
-
Parameters: none
-
Request body:
-
JSON
#TenantAccount: this={ spec : { iaas : #IaaSProviderKey iaasInfo : #IaaSProviderInfo[this.iaas] marks : #Marks } meta: { labels: [string]: string } }
-
-
Result: none
5.4.2. Update Account
PATCH /api/1.0-beta/tenant/<tenant>/account/<acname>
-
Parameters: none
-
Request body:
-
JSON
#TenantAccount: this={ spec : { iaas : #IaaSProviderKey iaasInfo : #IaaSProviderInfo[this.iaas] marks : #Marks } meta: { labels: [string]: string } }
-
-
Result: none
5.4.3. Get Account
PATCH /api/1.0-beta/tenant/<tenant>/account/<acname>
-
Parameters: none
-
Result:
-
JSON
#TenantAccount: this={ spec : { iaas : #IaaSProviderKey iaasInfo : #IaaSProviderInfo[this.iaas] marks : #Marks } meta: { labels: [string]: string } }
-
5.4.4. List Accounts in Tenant
PATCH /api/1.0-beta/tenant/<tenant>/account
Return the list of names of the accounts in the tenant
-
Parameters: none
-
Result:
-
JSON
[...string]
-
5.4.5. Remove Account / Purge Account
DELETE /api/1.0-beta/tenant/<tenant>/account/<acname>
-
Parameters:
-
delete
: boolean
-
If delete
is true
removes a given account only if there is no environment for the account.
Removal of the account, eventually results in the release of all IaaS resources
previously reserved under it.
If delete
is false
purges an account of all unused IaaS resources.
5.5. Deployment Environments
A deployment environment is a mechanism primarily for:
-
Determining the IaaS account to use for the resources to employ by the services deployed by the tenant.
-
Establishing a set of variables and values for them so that quotas can be established and decisions can be made on where to deploy a service, or wether to allow a user to deploy in it or a Kumori resource to actually be established in it (see selectors).
An IaaS account, as mentioned above, establishes an isolated environment even for billing purposes for the IaaS provider itself. Depending on the IaaS, spending limits can be set up (not on Axebow) and specific flavors of the resources provided by the IaaS can be specified (on Axebow) to be considered for allocation.
An environment is created within an account, and it must specify if needs to be further isolated.
Isolated environments will give rise to their own clusters, so that interference with other services deployed in other environments can be avoided. |
Environments declaring different accounts will be isolated from each other. |
It is important to understand that environment isolation may (likely) incur extra IaaS costs, as control planes must be reserved to achieve this isolation.
Isolation is convenient when the tenant needs to guarantee absence of contention in network usage, for instance separating pre-production from testing, from production loads.
In addition, a deployment environment can also be used to
-
Establish limits in axebow resource usage (vcpu, ram, storage)
-
Select the environment where to deploy a service
-
Determine which users can deploy which loads on an environment
-
Determine which kumori resources can be propagated to an environment to be used by the services that can be deployed there
To provide the above extra features, Axebow lets a tenant associate metadata with an environment. The metadata structure is an arbitrary Json object. Such objects will be interpreted by selectors
5.5.1. Create Environment
POST /api/1.0-beta/tenant/<tenant>/account/<acname>/environment/<name>
Creates a new deployment environment within the given account.
-
Parameters: none
-
Request body:
-
JSON describing the environment,
#EnvironmentSpec
:#EnvironmentSpec: this={ // Marks are used to define limits in resource usage. marks: #Marks // Arbitrary metadata, including any kind of quota info. labels?: {...} }
-
-
Response: common response
5.5.2. Update Environment
Only the metadata can be changed on an environment
PATCH /api/1.0-beta/tenant/<tenant>/account/<acname>/environment/<name>
Modifies an existing deployment-environment.
-
Parameters: none
-
Request body: JSON describing the environment **
{ marks: #Marks }
-
Response: common response
changing the metadata will only affect future selector runs. Decisions made in the past will not be reconsidered. |
5.5.3. Remove Environemnt
DELETE /api/1.0-beta/tenant/<tenant>/account/<acname>/environment/<name>
Removes a deployment environment.
The request will fail if there are services deployed in the environment
-
Parameters: none
-
Request body: none
-
Response: none
5.5.4. Get Environment Info
GET /api/1.0-beta/tenant/<tenant>/account/<acname>/environment/<name>
Gets the information of a deployment-environment.
-
Parameters: none
-
Request body: none
-
Response: JSON describing the environment. **
// The status of an environment shows dynamic data like the number of vsrious // resources in used, and for vcpus, their accumulated usage. #MarksStatus: { vcpu: {current: number, unit: "m"} memory: {current: number, unit: "MB"} vstorage: {current: number, unit: "MB"} nrstorage: {current: number, unit: "MB"} rstorage: {current: number, unit: "MB"} storage: {current: number, unit: "MB"} cost: {current: number, unit: "EUR"} } #EnvironmentInfo: { spec : #EnvironmentSpec status: { marks: #MarksStatus } }
5.5.5. List Environments in Tenant
GET /api/1.0-beta/tenant/<tenant>/account/<acname>/environment
Gets the list of deployment-environments for the given tenant+
-
Parameters:none
-
Request body: none
-
Response: JSON array with the list of dep-envs names **
[...string]
5.6. Get Tenant Info
GET /api/1.0-beta/tenant/<name>
Gets detailed information for a tenant. The user making the request must be a confirmed user of the tenant or of the "operator" tenant.
-
Parameters: none
-
Request body: none
-
Response:
-
JSON with all the tenant data:
#TenantInfo: this={ accounts: [account=string]: { account : #TenantAccount environments: [string]: #EnvironmentSpec & {_account: account, account: this.account} } users: [string]: { role : #TenantUserRole confirmed: bool } resources: [kind=#ResourceKind]: [string]: #ResourceSpec[kind] rules: #TenantSpec.rules }
-
5.7. List Tenants
GET /api/1.0-beta/tenant?[params]
Gets the list of tenants satisfying the role parameter.
If no parameters are supplied, the user making the request must be part of the operator
tenant
-
Parameters:
-
strict?:
bool
. By defaulttrue
, returns the list of tenants the user making the request has access to. Iffalse
, the request can only be done by and opeator user, which will return a list of all the tenants in the platform.
-
-
Request body: none
-
Response:
-
JSON with the list of tenant IDs.
{ [string]: #TenantRole | "none" // the key is the tenant name. // The value, the role of the user in the tenant }
-
5.8. Tenant users
Users are added to tenants with specific roles.
5.8.1. Invite a user to a tenant with a role
POST /api/1.0-beta/tenant/<tenant>/user/<user>?role=`owner | admin | plain`
Adds a user to a tenant with the proposed role: owner
, admin
, plain
.
If the user already belongs to the tenant, the call fails.
The request adds the user to the tenant in the pending
state.
In this state, the user cannot still act on behalf of the tenant except to confirm its
acceptance (see ahead)
The request fails if
-
The user making the request is not at least admin.
-
role
isowner
, and the user making the request is not an owner of the tenant. -
Parameters:
-
role
: One ofowner | admin | plain
. Default:plain
-
-
Response: common response
5.8.2. Confirm an invitation to a tenant
PUT /api/1.0-beta/tenant/<tenant>/user?role=`owner | admin | plain`
Confirms the user making the request to a tenant.
The call will fail if:
-
<user> is not
unconfirmed
in the tenant. -
role
in this call is different from the role the user was added with. -
Parameters:
-
role
: One ofowner | admin | plain
. No default. The parameter MUST be provided.
-
-
Request body: none:
-
Response: common response
5.8.3. Reject an invitation to a tenant
DELETE /api/1.0-beta/tenant/<tenant>/user
The user making the requet rejects the invitation to a tenant.
The call will fail if:
-
<user> is not confirmed in the tenant.
-
<user> has no invitation in the tenant.
-
Parameters:
-
role
: One ofowner | admin | plain
. No default. The parameter MUST be provided.
-
-
Request body: none:
-
Response: common response
5.8.4. Modify a user’s role
PUT /api/1.0-beta/tenant/<tenant>/user/<user>?role=`owner | admin | plain`
Modifies the role of <user> within <tenant>. The call will take immediate action if it does not fail (no confirmation needed)
The call will fail if:
-
The user making the request is not at least admin in the tenant.
-
<user> is not
confirmed
in the tenant. -
role
in this call is above the role of the user making the call. -
<user> is the last owner of the tenant and role is not
owner
. -
Parameters:
-
role
: One ofowner | admin | plain
. No default. The parameter MUST be provided.
-
-
Request body: none:
-
Response: common response
5.8.5. Exclude a user from a tenant member list
DELETE /api/1.0-beta/tenant/<tenant>/user/<user>
Removes a user from the tenant member list.
If the requesting user has a privilege (role) less than admin
the request fails.
If <user> is the last owner of the tenant, the request fails.
-
Parameters: none
-
Request body: none
-
Response: none
5.9. Tenant Services
Tenants can deploy Kumori applications to create services.
Running services on Axebow imply indicating somehow on which deployment environment a service should be deployed into. Thus, such information must be part of a request to create a service.
Services on Axebow proceed through a series of revisions, where each revision implements changes in configuration of the service, or implementation of the service, or topology, or all of them. All revisions are deployed within the deployment environment specified for the service when created.
Every time a request for setting up a revision for a service is received by Axebow, the costs that the revision would incur are computed. Afterwards, the revision must go through a process of acceptance. Until a revision is not accepted, it cannot be actually deployed.
When a service is created, a first revision for the service is also created. If this first revision is not accepted, the revision and the service are removed.
5.9.1. List Services in a tenant
GET /api/1.0-beta/tenant/<tenant>/service
Gets the list of running services for a given tenant.
-
Parameters: none
-
Request body: none
-
Response data:
[...string] // a simple array of service names
5.9.2. Get Service
GET /api/1.0-beta/tenant/<tenant>/service/<name>?summary=bool
Gets information about a running service
-
Parameters:
-
summary
: Iftrue
returns a summarized version of the service information, indicating basic information about the state of the service, as well as, a summarized view of the resources this service depends on. If set tofalse
, it returns an extended version which include information abount the instances the services has, its resource ( CPU, memory…) usage, and much more useful information related to the service.
-
-
Request body: none
-
Response data: contains general information about the service (creation and last modification timestamps, name, tenant), the service configuration in JSON format, the service topology (in JSON format) and the existing links with other services:
-
if
summary = true
{ id: number deleted: number current: number deployed: number resources: {...} }
-
if
summary = false
{ "comment": "Blah...", "revision": 12345678, "configuration": { "parameters": {...}, "resources": {...}, "scale": { "frontend": 1 }, "resilience": 0 }, "creationTimestamp": "2023-06-15T14:50:25Z", "events": [{ "counter": 1, "firstTimestamp": "...", "lastTimestamp": "...", "message": "...", "source": { "id": "...", "kind": "...", "name": "..." }, "reason": "..." }], "instances": { "frontend": { "instance-hfkhdskfs": {} } }, "lastModification": "2023-06-19T11:45:35Z", "links": [{ "source": { "tenant": "democomp", "deployment": "helloinb", "channel": "inbound" }, "target": { "tenant": "democomp", "deployment": "helloworld", "channel": "service" } }], "ref": { "name": "hellodemo", "tenant": "democomp", "domain": "kumori.examples", "module": "helloworld", "artifact": "helloworldsvc", "version": [1,0,7] } }
-
-
Request cost: none
5.9.3. Get Service Scale
GET /api/1.0-beta/tenant/<tenant>/service/<name>/scale
Gets the number of replicas per role for a running service.
-
Parameters: none
-
Request body: none
-
Response data: the number of replicas per service role.
#Scale: { [string]: uint }
Where each entry in the json object represents the name of one of the deployed roles.
For example:
{
"frontend": 1,
"worker": 3
}
-
Request cost: none
5.9.4. Get Service channels
GET /api/1.0-beta/tenant/<tenant>/service/<name>/channels
-
Parameters: none
-
Request body: none
-
Response data:
{ client: { [string]: any // metadata TBD } server: { [string]: any // metadata TBD } }
5.9.5. Get Service History
GET /api/1.0-beta/tenant/<tenant>/service/<name>/history
Gets the history of versions (updates) registered in the system, including the running one.
-
Parameters: none
-
Request body: none
-
Response data:
{ reinstates?: number, // Only if the revision is a Rollback revision: number, previous: number, original: number, comment: string, type: "PUT" | "PATCH" | "SCALE" | "ROLLBACK", }
In the response, field original
will be filled if a previous update was selected to run the service (see ahead),
in which case, no patch against previous
has been performed.
5.9.6. Get Service Roles
GET /api/1.0-beta/tenant/<tenant>/service/<name>/role/<name>
Gets information about a given role in a given service.
The result follows this structure:
{
artifactref: #ArtifactRef,
config: #Config,
instances: {
[string]: {
containers: [...#Container],
creationTimestamp: string,
events: [
...{
counter: number
firstTimestamp: string
lastTimestamp: string
message: string
reason: string
type: string
}
]
id: string,
metrics: {
usage: {
cpu: number,
memory: number
}
},
node: string
ready: bool,
status: string
}
}
}
5.9.7. Restart Service Role
DELETE /api/1.0-beta/tenant/<tenant>/service/<name>/role/<name>
Restarts all the role <role> instances
-
Parameters: none
-
Request body: none
-
Response data: Generic
5.9.8. Get Service Role Instances
GET /api/1.0-beta/service/<tenant>/<name>/role/<name>/instance/<iid>
Gets information about a given role instance in a given service.
If the role <name>
is a sub-service, an extra /role/<name>
section should be added until a leaf role is reached.
-
Parameters: none
-
Request body: none
-
Response data:
{ containers: { [string]: { metrics: { usage: { cpu: number // In vCPUs memory: number // In bytes } } ready: bool restarts: number states: { running: { startedAt: string } } } } creationTimestamp: string events: [ ...{ counter: number firstTimestamp: string lastTimestamp: string message: string reason: string type: string } ] id: string metrics: { usage: { cpu: number // In vCPUs memory: number // In bytes } } node: string ready: bool status: string }
-
Request cost: none
Instance name should be known by the request issuer after having gotten a description of the role or the complete service |
5.9.9. Restart Service Role Instance
DELETE /api/1.0-beta/tenant/<tenant>/service/<name>/role/<name>/instance/<iid>
Restarts the specified instance of the given role.
-
Parameters: none
-
Request body: none
-
Response data: Generic
5.9.10. Get Service Role Instance Container Logs
GET /api/1.0-beta/tenant/<tenant>/logs/service/<name>/role/<name>/instance/<iid>/[container/<name>][?parameters]
Returns the standard output and error of the given instance. If an instance has more than one container, one of them must be specified.
-
Parameters:
-
tail=N
: to show the last N log lines of the container involved: -
delta=N
: to show the last N seconds of logs of the container involved:GET /api/1.0-beta/tenant/<tenant>/logs/service/<name>/role/<name>/instance/<iid>/[container/<name>]?tail=1000
-
5.9.11. Create a service
POST /api/1.0-beta/tenant/<tenant>/service/<name>
Registers a new service for a tenant. Requires the kumori deployment specification as a module:
-
The service artifact describing the service being deployed, with all its dependencies, either as references to published artifacts, or included inline within the deployment
bundle
(see below) -
Autoscaling parameters if any.
-
Deployment environment selection parameters
The payload will consist of a Kumori Bundle and a JSON structure (multipart).
A Kumori Bundle is a zip archive containing a set of top-level directories
each one representing a Kumori module. There must be a directory with the name deployment
, and at the top level of its module
it MUST define a deployment
package that resolves to a #Deployment
structure as defined in Kumori’s service model.
A deployment creation creates implicitly a revision deployment request. The deployment request will not be carried out until the costs are accepted (see [section-api-accept-deployment]). |
-
Parameters:
-
dryrun
: iftrue
, the manifest is processed and the costs calculated but the new service is never deployed.. -
wait
: if set, the request ends once the new service is up and running or the specified timeout is reached. In the last case, a201
code is returned, and thedata
field contains the request ID that can be used. to retrieve information about the request. If0
, the timeout is infinite. Otherwise, the request ends once the deployment operation is validated and registered. -
accept
: if set, the request is automatically accepted if resource consumption falls within the declared bounds, and the accept step (see [section-api-accept-deployment]) is not required.
-
-
Request body: a multipart body containing:
-
A Kumori bundle (see above)
-
A JSON document containing a metadata JSON object used to select the deployment environment.
#ServiceSpec: { bundle: ZipFile // Arbitrary JSON used for environment selection as well as // later on, for scaling decisions. // Note that his metadata is not available within the service being // deployed. meta : {...} // Not available for decisions comment: string }
-
A bundle with the deployment manifest and, optionally, some other modules required to deploy the service.
-
-
Response data: a structure with the following fields
#ServiceStatus: {
// ID of the first revision
firstRevision : number
currentRevision : number
history : [...number]
environment ?: string
}
#SerficeInfo: {
spec : #ServiceSpec
status: #ServiceStatus
}
Where the revision field is the revision ID assigned by the platform to the created revision request created as a consequence.
5.9.12. Create a service (simple)
POST /api/1.0-beta/tenant/<tenant>/service/<name>/simple
It is the same as the previous method but this one does not require a bundle, instead just an artifact reference is provided to deploy a service or component whose manifests are already published in a registry.
-
Parameters:
-
dryrun
: iftrue
, the manifest is processed and the costs calculated but the new service is never deployed.. -
wait
: if set, the request ends once the new service is up and running or the specified timeout is reached. In the last case, a201
code is returned, and thedata
field contains the request ID that can be used. to retrieve information about the request. If0
, the timeout is infinite. Otherwise, the request ends once the deployment operation is validated and registered. -
accept
: if set, the request is automatically accepted if resource consumption falls within the declared bounds, and the accept step (see [section-api-accept-deployment]) is not required.
-
-
Request body:
{ deployment: { name: string up: null, meta: {...}, config: { parameter: [string]: {...}, resource: {...}, resilience: number, scale: #Scale }, artifact: { ref: #ArtifactRef } } comment: string meta: {...} }
5.9.13. Accept Service deployment request
Revision requests are accepted/rejected by explicitly "updating" its acceptance status
PUT /api/1.0-beta/tenant/<tenant>/service/<name>/revision/<revision>?accept=true/false
Accepting a service revision means that the configuration of that revision will be deployed for the service. A revision can only be accepted if it has been authorized and validated but it has not been accepted or rejected yet.
Rejecting the revision will remove it from the system, not deploying it. Moreover, if it was the first revision of a service the service itself will be removed.
<revision>
is the revision number to be accepted to be deployed for an existing service.
This revision id has been returned from the POST deployment calls above.
If only the first revision of a deployment exists,<revision>
can be omitted.
-
Parameters:
-
accept
: boolean that indicates to accept (true) or reject the revision deployment request.
-
-
Request body: none
-
Response data: none *
5.9.14. Partial Update Service
PATCH /api/1.0-beta/tenant/<tenant>/service/<name>/revision/<previous>
Sends a request for an update of an existing deployment. When an update request is received, it must be accepted again. An update request will be immediately rejected if there is a previous pending update request. An update request MUST provide the revision it is updating (see below). If that revision is not the current one for the deployment, the update request is immediately rejected.
-
Parameters:
-
dryrun
: iftrue
, the manifest is processed and the costs calculated but the update is not performed. -
wait
: same as for initial deployment. -
accept
: if set, the request is automatically accepted and the accept step (see [section-api-accept-deployment]) is not required. -
previous
: Non-optional parameter that MUST indicate the revision this one patches.
-
-
Request body
-
A deployment bundle as for initial deployment, but the bundle itself may be partial: some of the modules may not be included, in which case they should have been part of a previous revision. Also, the deployment module can be partial, in which case, configuration values not included in the deployment manifest are taken from the revision this one updates. So, an update bundle is in reality a patch of the bundle of the previous revision.
-
-
Response data:
-
Info about the revision as JSON
#RevisionStatus: { accepted: bool resources: : [#ResourceKind]: [...string] usage: { max: { vcpu: uint ram: uint // in MB } min: { vcpu: uint ram: uint // in MB } } } #RevisionInfo: { spec : #RevisionSpec status: #RevisionStatus }
-
5.9.15. Update Service
POST /api/1.0-beta/tenant/<tenant>/service/<name>/revision/<previous>
Sends a request for an update of an existing deployment. When an update request is received, it must be accepted again. An update request will be immediately rejected if there is a previous pending update request. An update request MUST provide the revision it is updating (see below). If that revision is not the current one for the deployment, the update request is immediately rejected.
-
Parameters:
-
dryrun
: iftrue
, the manifest is processed and the costs calculated but the update is not performed. -
wait
: same as for initial deployment. -
accept
: if set, the request is automatically accepted and the accept step (see [section-api-accept-deployment]) is not required. -
remove_links
: iftrue
, if the update removes a service channel that was being used the link gets removed, iffalse
, it will prevent updating the service so the links are not broken.
-
-
Request body
-
A complete deployment bundle as for initial deployment. This is not PATCHED.
-
-
Response data:
-
Info about the revision as JSON
#RevisionStatus: { accepted: bool resources: : [#ResourceKind]: [...string] usage: { max: { vcpu: uint ram: uint // in MB } min: { vcpu: uint ram: uint // in MB } } } #RevisionInfo: { spec : #RevisionSpec status: #RevisionStatus }
-
5.9.16. Update Service (simple)
POST /api/1.0-beta/tenant/<tenant>/service/<name>/revision/<previous>/simple
The same as the previous method but this one does not require a bundle, instead just an artifact reference is provided to deploy a service or component whose manifests are already published in a registry.
-
Parameters:
-
dryrun
: iftrue
, the manifest is processed and the costs calculated but the update is not performed. -
wait
: same as for initial deployment. -
accept
: if set, the request is automatically accepted and the accept step (see [section-api-accept-deployment]) is not required. -
remove_links
: iftrue
, if the update removes a service channel that was being used the link gets removed, iffalse
, it will prevent updating the service so the links are not broken.
-
-
Request body:
{ deployment: { name: string up: null, meta: {...}, config: { parameter: [string]: {...}, resource: {...}, resilience: number, scale: #Scale }, artifact: { ref: #ArtifactRef } } comment: string meta: {...} }
-
Response data:
-
Info about the revision as JSON
-
5.9.17. Rollback Service
PUT /api/1.0-beta/tenant/<tenant>/service/<name>/revision/<previous>/rollback/<target>
Rollback a running service to a previous revision (target).
A service cannot be rolled back if there is a pending revision for the deployment.
If when the rollback request is received the current revision of the service is nor the one denoted by previous
the request fails.
Note that rolling back takes the whole configuration of the revision we are rolling back to. The only possible changes are those derived of changes in the resources.
-
Parameters:
-
dryrun
: iftrue
, the manifest is processed and the costs calculated byt the update is not performed. -
wait
: if set, the request ends once the new service is up and running or the specified timeout is reached. In the last case, an408
error code is returned. If0
, the timeout is infinite. Otherwise, the request ends once the deployment operation is validated and registered. -
accept
: if set, the request is automatically accepted and the accept step (see [section-api-accept-deployment]) is not required. -
remove_links
: iftrue
, if the update removes a service channel that was being used the link gets removed, iffalse
, it will prevent updating the service so the links are not broken.
-
-
Response data:
-
Info about the revision as JSON
#RevisionStatus: { accepted: bool resources: : [#ResourceKind]: [...string] usage: { max: { vcpu: uint ram: uint // in MB } min: { vcpu: uint ram: uint // in MB } } } #RevisionInfo: { spec : #RevisionSpec status: #RevisionStatus }
-
The previous revision is the version being updated by the user. If the previous revision is not the currently deployed revision for the service,
the request will be rejected.
|
5.9.18. Change Service Scale
PATCH /api/1.0-beta/tenant/<tenant>/service/<name>/revision/:previous/scale
Shorthand update of a service, where the only "patch" is the scale configuration, provided in a JSON body. Changes the number of role replicas in an existing service. A service cannot be scaled if a previous update (or the initial registration) has not been accepted or rejected yet.
As a streamlined update, it follows all the rules of an update.
-
Parameters:
-
dryrun
: iftrue
, the manifest is processed and the costs calculated byt the update is not performed. -
wait
: if set, the request ends once the service is up and running or the specified timeout is reached. In the last case, an408
error code is returned. If0
, the timeout is infinite. Otherwise, the request ends once it has been validated and registered. -
accept
: if set, the request is automatically accepted and the accept step (see [section-api-accept-deployment]) is not required. -
remove_links
: iftrue
, if the update removes a service channel that was being used the link gets removed, iffalse
, it will prevent updating the service so the links are not broken.
-
-
Request body:
-
a JSON document indicating which roles are going to be scaled and to which number. Roles not included are not modified.
{ // an entry per role whose scale must change. scale: [string]: uint }
-
-
Response data:
-
Info about the revision as JSON
#RevisionStatus: { accepted: bool resources: : [#ResourceKind]: [...string] usage: { max: { vcpu: uint ram: uint // in MB } min: { vcpu: uint ram: uint // in MB } } } #RevisionInfo: { spec : #RevisionSpec status: #RevisionStatus }
-
5.9.19. Remove Service
DELETE /api/1.0-beta/tenant/<tenant>/service/<name>
Removes a deployed service, releasing its resources, and removing all its revision history.
-
Parameters:
-
wait
: if set, the request ends once the service has been completely removed or the specified timeout is reached. In the last case, an408
error code is returned. If0
, the timeout is infinite. Otherwise, the request ends once it has been validated and registered.
-
-
Request body: none
-
Response data: none
-
Request cost: none
5.9.20. Link services
POST /api/1.0-beta/tenant/<client_tenant>/service/<client_service>/client/<client_channel>/tenant/<server_tenant>/service/<server_service>/server/<server_channel>
Creates a link between a service client channel and a service server channel.
A link establishes a path between two different services through a client channel from the client service to a server channel of the server service.
-
Parameters: none
-
Request body: none
-
Response data: none
at this point in time, for two services to be linked, both must be deployed on the same deployment environment. |
5.9.21. Unlink services
DELETE /api/1.0-beta/tenant/<client_tenant>/service/<client_service>/client/<client_channel>/tenant/<server_tenant>/service/<server_service>/server/<server_channel>
Removes an existing link between two services.
-
Parameters: none
-
Request body: none
-
Response data: none
-
Request cost: none
5.9.22. List service links
GET /api/1.0-beta/tenant/<tenant>/service/<service>/links
Lists the links a service is part of.
-
Parameters: none
-
Request body: none
-
Response data:
[ ...{ id: #EntityId, spec: { client_tenant: string client_service: string client_channel: string server_tenant: string server_service: string server_channel: string }, meta: #Meta, status: { linked: bool } } ]
-
Request cost: none
5.10. Kumori Resources
Kumori resources are pieces on information that are protected by the platform and can be used by deployed services.
Kumori resources can be registered at the platform level. Later on, when a service needs to use them they can be made available within the environment where the service finally gets deployed.
A Kumori resource can be provided with metadata that can be used by generic tenant policies to determine what environments can use them.
Additionally, a given resource can be provided with a selector that further restricts the set of environments it can be deployed to
APIs for kumori resources all look the same. What varies are the structures of the request body and part of the response data.
A couple of special cases are port
and domain
resources, whose values CANNOT be shared by different
services, and thus, different tenants.
We provide the generic request shape for all resources, and then, for each one of them, specify the request body spec.
GET /api/1.0-beta/tenant/<tenant>/[kind]
Gets the list of registered resources of kind <kind> in a given tenant. Where <kind> is one of
#ResourceKind: "domain" | // Kumori Resource `domain`
"port" | // Kumori resource `port`
"certificate" | // Kumori resource `port`
"ca" | // Kumori resource `ca` (certificate authority)
"secret" | // Kumori resource `secret`
"volume" // Kumori resource `volume`
If no kind provided it will return information about all the resources registered in the tenant.
When requesting information only for ports, the following extra fields will be included:
* usedports
: List of ports owned by the current tenant.
* additionalshared
: When using a freemium tenant, this is the list of ports owned
by other freemium tenants.
-
Parameters: none
-
Request body: none
-
Response data:
[...{ id: #ResourceId accounts: [string]: string (1) }] (2)
1 list of accounts and environemnts in which the resource is being used. 2 array of resources
if no <kind>
is specified then all resources for the tenant are listed like so:
{
[#ResourceKind]: [...string] (1)
}
5.10.1. Get information about a particular resource
GET /api/1.0-beta/tenant/<tenant>/<kind>/<name>
Returns information of a the resource of kind <kind> and name <name>
-
Parameters: none
-
Request body: none
-
Response data:
-
A Json struct
#ResourceInfo (1)
1 see Section 5.10.5
-
5.10.2. Register Resource
POST /api/1.0-beta/tenant/<tenant>/<kind>/<name>
Registers a new resource of kind <kind> and name <name> for the <tenant>
-
Parameters:
-
Request body:
-
A Json structure following Section 5.10.5
#ResourceSpec[kind]
-
-
Response data: none
5.10.3. Update Resource
Similar to resource creation.
PUT /api/1.0-beta/tenant/<tenant>/<kind>/<name>
Updates the resource information of a previously registered resource.
-
Parameters: none
-
Request body: Same as for the creation request. The new spec substitutes the original one.
5.10.4. Unregister resource
DELETE /api/1.0-beta/tenant/<tenant>/<kind>/<name>
Removes an previously registered resource. A resource cannot be removed if it is being used by a service.
-
Parameters: none.
-
Request body: none.
-
Response data: none.
-
Request cost: none.
5.10.5. Resource structures
Resource related requests use a JSON request body, producing a JSON response, as specified in the APIs
JSON request bodies fully depend on the resource being accessed, describing it.
Response JSON bodies have a common part, and data part, where the data part is the same JSON structure used to create it/modify it.
Thus a response JSON body has the following structure:
package axebow
#ResourceKind: "ca" | "certificate" | "domain" | "port" | "secret" | "volume"
#ResourceId: [id_kind=#ResourceKind]: {
name: string
kind: id_kind
parent: {
name: string
kind: "tenant"
}
}
#Resource: [kind=#ResourceKind]: {
id : #ResourceId[kind] // The id of the resource
spec : #ResourceSpec[kind] // The actual spec of the resource
meta? : [string]: string // Optional dictionary of values
selector? : #SelectorResource // Optional selector of the environment
status : { // list of cluster/accounts/environments where the resources registered/used
clusters: [string]: bool
requested: [string]: number
environment: [string]: number
}
}
#ResourceSpec: [kind=#ResourceKind]: {
data : #ResourceData[kind] // Actual data spec to be provided when creating
}
// Dictionary of resource data structures
#ResourceData: {
ca : #Data_CA
certificate: #Data_Certificate
domain : #Data_Domain
port : #Data_Port
secret : #Data_Secret
volume : #Data_Volume
}
#Data_CA: string
#Data_Certificate: {
cert: string, // String representation of a cert
key: string, // String representation of the private key
domain: #DomainString // A string representing a domain name
}
#Data_Domain: #DomainString
#Data_Port: uint16
#Data_Secret: string
#Data_Volume: {
items: uint // How many subvolumes
size: #Magnitude // a magnitude string, e.g. 10M, 5G
type: "replicated" | "single" // kind of volumes
provider: string // CSI provider, as named by the platform
}
5.11. Selectors
We can declare a set of rules in a tenant that specify selectors to be run at specific points of request processing.
A tenant spec has a section with rules. Those rules contain selectors.
A selector is a stack program that when run, returns a boolean value on top of the stack.
The spec for selectors is here:
package axebow
// Selection of environments for resources and deployments
// and validation of environments for users
#Ops: "::getor" | // 2 => 1: gets the reference on top, if it exists.
// Else returns the next element
"::exists" | // 1 => 1: returns true is the reference exists, false otherwise
"::dup" | // 1 => 2: duplicate top of the stack
"::pop" | // 1 => 0: pops top value
"::swap" | // 2 => 2: Swap top two values on the stack
"::num" | // 1 => 1: Convert to decimal number or leave a 0
"::bool" | // 1 => 1: Convert to boolean (anything not null or false is true)
"::eq" | // 2 => 1: Is equal
"::neq" | // 2 => 1: Is not equal
"::gt" | // 2 => 1: Is greater than
"::gte" | // 2 => 1: Is greater than or equal
"::lt" | // 2 => 1: Is less than
"::lte" | // 2 => 1: Is less than or equal
"::not" | // 1 => 1: Logical not
"::and" | // 2 => 1: Logical and
"::nand" | // 2 => 1: Logical nand
"::or" | // 2 => 1: Logical or
"::nor" | // 2 => 1: Logical nor
"::xor" // 2 => 1: Logical xor
#Ref : =~ "^\\$\\.(this|user|service|resource|environment)(\\.[^.]+)+$"
#NotRef: !~ "^\\$\\."
#NotOps: !~ "^::"
#string: #Ref | #Ops | (#NotOps & #NotRef)
#SelectorItem: #string | number | bool | null
#Selector_Item_Resource: #SelectorItem & !~ "^\\$\\.(user|service|resource)"
#Selector_Item_User : #SelectorItem & !~ "^\\$\\.(user|resource)"
#Selector_Item_Service : #SelectorItem & !~ "^\\$\\.(user|resource|service)"
#Selector: [...#SelectorItem]
/**
A selector is a stack program evaluating to a boolean
A selector item can be data, a reference (special kind of data) or an operation
Operations act on the top of the stack and consume the value therein, potentially
producing a new value that gets pushed.
When evaluated, the value on top of the stack is the result of the evaluation.
If evaluation produces an error (e.g., conversion errors to num or bool)
Evaluation of a selector occurs in a context from which some objects
can be references for values out of a JSON structure for the object
Selectors are represented as CUE arrays constrained as shown below
References in a selector MUST be to only
$this
$user
$environment
$deployment
$resource
objects, and must consist of paths into them.
Those paths can reach into any of the structures of those objects as defined
in each objects INFO section (info: structure returned with a get info op)
The $this object will always exist and will represent the object on which
the selector has been defined.
The rest of the objects may, or may not exist, depending the kind of object
$this is. For each case where a selector can be specified, the context objects available
will be defined.
*/
#Selector_Resource: [...#Selector_Item_Resource]
#Selector_User : [...#Selector_Item_User ]
#Selector_Service : [...#Selector_Item_Service ]
a: #Selector & [1, 2, "$.this.that.there.where", "::dup", "::getor"]
From the spec we see that formally, a selector is a JSON array, whose items are just data, references, or operations.
5.12. Kumori Modules Marketplace
When registering a tenant we have seen that an npm registry can be configured to publish there the kumori modules that you will build in the platform. In this section, the endpoints related to module publishing and consumption will be described.
5.12.1. Publish Module
PUT /api/1.0-beta/tenant/<tenant>/marketplace/module
Publishes a module to the registry configured in the tenant.
-
Parameters: none
-
Request Body:
-
It expects a form data containing the following fields:
-
bundle
: zip file containing a kumori module like the one discussed in previous sections. -
bundle-target-kind
:component | service
, you must indicate whether the module to be publish contains a component or a service. -
bundle-target-dir
: the relative path in the bundle where the main artifact is located. -
bundle-tags
: a JSON array containing a list of strings.
-
-
-
Response body: Generic
5.12.2. List Modules
GET /api/1.0-beta/tenant/<tenant>/marketplace/module
Returs the list of all the modules the tenant has access to. It can also filter the result based on a few parameters.
-
Parameters:
-
name
: string. Optional. Find closest match by artifact name -
tags
: JSON array. Optional. Array of tags the modules should contain. -
domain
: string. Optional. Filter modules under the given domain -
limit
: number. Optional. Pagination page size. -
offset
: number. Optional. Pagination offset.
-
-
Request Body: none
-
Response body:
{ pagination: { total: number offset: number }, items: [ ...{ name: string domain: string version: string tags: [...string] artifactTypes: "component" | "service" } ] }
5.12.3. Get Module Info
GET /api/1.0-beta/tenant/<tenant>/marketplace/module/schema
Gets detailed information about a publish module. It fails if no module is found with the parameters provided.
This endpoint also returns a JSON Schema of the artificat configuration.
-
Parameters:
-
domain
: string. Domain of the module. -
name
: string. Name of the module. -
version
: string. Version of the module.
-
-
Request Body: none
-
Response body:
{ [artifact_name: string]: { kind: "component" | "service" schemas: [...#JSONSchema] roles: [...string] } }
5.12.4. Selector operations
Selector operations are explained in the comments. Each operation takes its arguments from the top of the stack, and pushes its results to the top of the stack.
For each operation we show its arity (args in, result out).
The array must be interpreted as this:
-
The array is processed from left to right
-
A non-operation item is pushed on the stack
-
an operation item is executed on the stack state, modifying it.
5.12.5. References in selectors and the context
A selector execution is carried out within a context providing some top level objects, accessed
with a string like $.<object>
. Where <object>, in general, can vary depending where the selector
is declared.
Selectors declared on the tenant selectEnvironmentService
set of rules,
have available to them, when preparing a deployment the tenant info (through the this
object)
the service info and the revision info (including the usage info), through the service
object.
Selector declared on the tenant validateEnvironmentResource
set of rules have available to them
the environment
info the tenant info (this
) and the resource
info.
Selector declared on the tenant validateEnvironmentUser
set of rules have available to them
the environment
info, the tenant info (this
) and the tenant user
info.
Armed with such a context, complex rules (non-recursive) can be specified and they are run as follows:
When a new revision of a service is requested:
-
If the environment for the service is not set, the set of rules in
selectEnvironmentService
are evaluated for each environment. When on an environment, the contextenvironment
object is set to that environment info. The set of environments for which a true is obtained is labeled as accepted, becoming candidates for the next phase -
If the environment has already been set, the set of rules in
selectEnvironmentService
is run on the environment selected. If all of them pass, we proceed labeling the environment as accepted. -
We repeat the above with the
selectAcceptEnvironmentService
list on the set of environments that did not pass. The set of environments passing this phase is labeled asrequiring
. -
For each environment that passed the above selections (as either
accepted
orrequiring
), we run the set of selectors invalidateEnvironmentResource
for each resource the revision needs. If a resource passes, we run the selector of the resource, if any. If all resources pass the environment stays as candidate with the same label it had, if any resource fails, the environment is removed from the candidate list. -
Finally, for all surviving candidate environments we run the
validateEnvironmentUser
list of selectors on the tenant user info of the user making the request. If no environment passes, we fail the request. If more than one environment is still candidate, we select the environment with the most vcpus extant, priorizingaccepted
environments. -
If the selected environment is labeled as
accepted
, it is setup as the environment of the deployment, and we proceed to deploy the revision. If, on the contrary, it is labeled as requiring, we assign the environment, but leave the revision as not accepted, and wait for an explicit acceptance call.
The above process can be used to implement access control for users.
Execution of selectors, in most cases, will be fast and low complexity