Providers

API: Stable

Providers, the backbone of UCloud, expose compute and storage resources to end-users.

Rationale

UCloud/Core is an orchestrator of Resources. This means, that the core doesn’t actually know how to serve files or run computational workloads. Instead, the core must ask one or more Providers to fulfil requests from the user.

Figure: UCloud/Core receives a request from the user and forwards it to a provider.

The core isn’t a simple proxy. Before passing the request, UCloud performs the following tasks:

  • Authentication: UCloud ensures that users have authenticated.

  • Authorization: The Project system of UCloud brings role-based authorization to all Resources. The core verifies all actions before forwarding the request.

  • Resolving references: UCloud maintains a catalog of all Resources in the system. All user requests only contain a reference to these Resources. UCloud verifies and resolves all references before proxying the request.

The communication between UCloud/Core and the provider happens through the provider APIs. Throughout the developer guide, you will find various sections describing these APIs. These APIs contain both an ingoing (from the provider’s perspective) and outgoing APIs. This allows for bidirectional communication between both parties. In almost all cases, the communication from the user goes through UCloud/Core. The only exception to this rule is when the data involved is either sensitive or large. In these cases, UCloud will only be responsible for facilitating direct communication. A common example of this is file uploads.

Suggested Reading

Table of Contents

1. Examples
Description
Definition of a Provider (Retrieval)
Registering a Provider
A Provider authenticating with UCloud/Core
2. Remote Procedure Calls
Name Description
browse Browses the catalog of available Providers
retrieve Retrieves a single Provider
retrieveSpecification Retrieves the specification of a Provider
search Searches the catalog of available resources
approve Used for the last step of the approval protocol
create Creates one or more Providers
init Request (potential) initialization of resources
renewToken Replaces the current refresh-token and certificate of a Provider
requestApproval Used for the approval protocol
update Updates the specification of one or more providers
updateAcl Updates the ACL attached to a resource
3. Data Models
Name Description
Provider Providers, the backbone of UCloud, expose compute and storage resources to end-users.
ProviderIncludeFlags Flags used to tweak read queries
ProviderSpecification The specification of a Provider contains basic (network) contact information
ProviderStatus A placeholder document used only to conform with the Resources API
ProviderSupport A placeholder document used only to conform with the Resources API
ProviderUpdate Updates regarding a Provider, not currently in use
ResourceOwner The owner of a `Resource`
ResourcePermissions No description
UpdatedAcl No description
ProvidersApproveRequest Request type used as part of the approval process
ProvidersRenewRefreshTokenRequestItem Request type for renewing the tokens of a Provider
ProvidersRequestApprovalRequest Request type used as part of the approval process
ProvidersRequestApprovalRequest.Information Request type used as part of the approval process, provides contact information
ProvidersRequestApprovalRequest.Sign Request type used as part of the approval process, associates a UCloud user to previously uploaded information
ProvidersRequestApprovalResponse Response type used as part of the approval process
ProvidersRequestApprovalResponse.AwaitingAdministratorApproval Response type used as part of the approval process
ProvidersRequestApprovalResponse.RequiresSignature Response type used as part of the approval process

Example: Definition of a Provider (Retrieval)

Frequency of useCommon
Actors
  • A UCloud administrator (admin)
Communication Flow: Kotlin
/* This example shows an example provider. The provider's specification contains basic contact
information. This information is used by UCloud when it needs to communicate with a provider. */

Providers.retrieveSpecification.call(
    FindByStringId(
        id = "51231", 
    ),
    admin
).orThrow()

/*
ProviderSpecification(
    domain = "provider.example.com", 
    https = true, 
    id = "example", 
    port = 443, 
    product = ProductReference(
        category = "", 
        id = "", 
        provider = "ucloud_core", 
    ), 
)
*/
Communication Flow: Curl
# ------------------------------------------------------------------------------------------------------
# $host is the UCloud instance to contact. Example: 'http://localhost:8080' or 'https://cloud.sdu.dk'
# $accessToken is a valid access-token issued by UCloud
# ------------------------------------------------------------------------------------------------------

# This example shows an example provider. The provider's specification contains basic contact
# information. This information is used by UCloud when it needs to communicate with a provider.

# Authenticated as admin
curl -XGET -H "Authorization: Bearer $accessToken" "$host/api/providers/retrieveSpecification?id=51231" 

# {
#     "id": "example",
#     "domain": "provider.example.com",
#     "https": true,
#     "port": 443,
#     "product": {
#         "id": "",
#         "category": "",
#         "provider": "ucloud_core"
#     }
# }
Communication Flow: Visual

Example: Registering a Provider

Frequency of useCommon
Actors
  • The integration module (unauthenticated) (integrationModule)
  • The admin of the provider (authenticated as a normal UCloud user) (systemAdministrator)
  • A UCloud administrator (admin)
  • The UCloud/Core service user (ucloud)
Communication Flow: Kotlin
/* WARNING: The following flow still works, but is no longer used by the default configuration of
the integration module. Instead, it has been replaced by the much simpler approach of having
a UCloud administrator register the provider manually and then exchange tokens out-of-band. */


/* This example shows how a Provider registers with UCloud/Core. In this example, the Provider will 
be using the Integration Module. The system administrator, of the Provider, has just installed the 
Integration Module. Before starting the module, the system administrator has configured the module 
to contact UCloud at a known address. */


/* When the system administrator launches the Integration Module, it will automatically contact 
UCloud. This request contains the contact information back to the Provider. */

Providers.requestApproval.call(
    ProvidersRequestApprovalRequest.Information(
        specification = ProviderSpecification(
            domain = "provider.example.com", 
            https = true, 
            id = "example", 
            port = null, 
            product = ProductReference(
                category = "", 
                id = "", 
                provider = "ucloud_core", 
            ), 
        ), 
    ),
    integrationModule
).orThrow()

/*
ProvidersRequestApprovalResponse.RequiresSignature(
    token = "9eb96d0a27b1330cdc727ef4316bd48265f71414", 
)
*/

/* UCloud/Core responds with a token and the IM displays a link to the sysadmin. The sysadmin follows 
this link, and authenticates with their own UCloud user. This triggers the following request: */

Providers.requestApproval.call(
    ProvidersRequestApprovalRequest.Sign(
        token = "9eb96d0a27b1330cdc727ef4316bd48265f71414", 
    ),
    integrationModule
).orThrow()

/*
ProvidersRequestApprovalResponse.RequiresSignature(
    token = "9eb96d0a27b1330cdc727ef4316bd48265f71414", 
)
*/

/* The sysadmin now sends his token to a UCloud administrator. This communication always happen 
out-of-band. For a production system, we expect to have been in a dialogue with you about this 
process already.

The UCloud administrator approves the request. */

Providers.approve.call(
    ProvidersApproveRequest(
        token = "9eb96d0a27b1330cdc727ef4316bd48265f71414", 
    ),
    admin
).orThrow()

/*
FindByStringId(
    id = "51231", 
)
*/

/* UCloud/Core sends a welcome message to the Integration Module. The core uses the original token to 
authenticate the request. The request also contains the refreshToken and publicKey required by the 
IM. Under normal circumstances, the IM will auto-configure itself to use these tokens. */

IntegrationProvider.welcome.call(
    IntegrationProviderWelcomeRequest(
        createdProvider = ProviderWelcomeTokens(
            publicKey = "~~ public key ~~", 
            refreshToken = "8accc446c2e3ac924ff07c77d93e1679378a5dad", 
        ), 
        token = "9eb96d0a27b1330cdc727ef4316bd48265f71414", 
    ),
    ucloud
).orThrow()

/*
Unit
*/

/* Alternatively, the sysadmin can read the tokens and perform manual configuration. */

Providers.retrieve.call(
    ResourceRetrieveRequest(
        flags = ProviderIncludeFlags(
            filterCreatedAfter = null, 
            filterCreatedBefore = null, 
            filterCreatedBy = null, 
            filterIds = null, 
            filterName = null, 
            filterProductCategory = null, 
            filterProductId = null, 
            filterProvider = null, 
            filterProviderIds = null, 
            hideProductCategory = null, 
            hideProductId = null, 
            hideProvider = null, 
            includeOthers = false, 
            includeProduct = false, 
            includeSupport = false, 
            includeUpdates = false, 
        ), 
        id = "51231", 
    ),
    systemAdministrator
).orThrow()

/*
Provider(
    createdAt = 1633329776235, 
    id = "51231", 
    owner = ResourceOwner(
        createdBy = "sysadmin", 
        project = null, 
    ), 
    permissions = null, 
    publicKey = "~~ public key ~~", 
    refreshToken = "8accc446c2e3ac924ff07c77d93e1679378a5dad", 
    specification = ProviderSpecification(
        domain = "provider.example.com", 
        https = true, 
        id = "example", 
        port = null, 
        product = ProductReference(
            category = "", 
            id = "", 
            provider = "ucloud_core", 
        ), 
    ), 
    status = ProviderStatus(
        resolvedProduct = null, 
        resolvedSupport = null, 
    ), 
    updates = emptyList(), 
    providerGeneratedId = "51231", 
)
*/
Communication Flow: Curl
# ------------------------------------------------------------------------------------------------------
# $host is the UCloud instance to contact. Example: 'http://localhost:8080' or 'https://cloud.sdu.dk'
# $accessToken is a valid access-token issued by UCloud
# ------------------------------------------------------------------------------------------------------

# WARNING: The following flow still works, but is no longer used by the default configuration of
# the integration module. Instead, it has been replaced by the much simpler approach of having
# a UCloud administrator register the provider manually and then exchange tokens out-of-band.

# This example shows how a Provider registers with UCloud/Core. In this example, the Provider will 
# be using the Integration Module. The system administrator, of the Provider, has just installed the 
# Integration Module. Before starting the module, the system administrator has configured the module 
# to contact UCloud at a known address.

# When the system administrator launches the Integration Module, it will automatically contact 
# UCloud. This request contains the contact information back to the Provider.

# Authenticated as integrationModule
curl -XPOST -H "Authorization: Bearer $accessToken" -H "Content-Type: content-type: application/json; charset=utf-8" "$host/api/providers/requestApproval" -d '{
    "type": "information",
    "specification": {
        "id": "example",
        "domain": "provider.example.com",
        "https": true,
        "port": null,
        "product": {
            "id": "",
            "category": "",
            "provider": "ucloud_core"
        }
    }
}'


# {
#     "type": "requires_signature",
#     "token": "9eb96d0a27b1330cdc727ef4316bd48265f71414"
# }

# UCloud/Core responds with a token and the IM displays a link to the sysadmin. The sysadmin follows 
# this link, and authenticates with their own UCloud user. This triggers the following request:

curl -XPOST -H "Authorization: Bearer $accessToken" -H "Content-Type: content-type: application/json; charset=utf-8" "$host/api/providers/requestApproval" -d '{
    "type": "sign",
    "token": "9eb96d0a27b1330cdc727ef4316bd48265f71414"
}'


# {
#     "type": "requires_signature",
#     "token": "9eb96d0a27b1330cdc727ef4316bd48265f71414"
# }

# The sysadmin now sends his token to a UCloud administrator. This communication always happen 
# out-of-band. For a production system, we expect to have been in a dialogue with you about this 
# process already.
# 
# The UCloud administrator approves the request.

# Authenticated as admin
curl -XPOST -H "Authorization: Bearer $accessToken" -H "Content-Type: content-type: application/json; charset=utf-8" "$host/api/providers/approve" -d '{
    "token": "9eb96d0a27b1330cdc727ef4316bd48265f71414"
}'


# {
#     "id": "51231"
# }

# UCloud/Core sends a welcome message to the Integration Module. The core uses the original token to 
# authenticate the request. The request also contains the refreshToken and publicKey required by the 
# IM. Under normal circumstances, the IM will auto-configure itself to use these tokens.

# Authenticated as ucloud
curl -XPOST -H "Authorization: Bearer $accessToken" -H "Content-Type: content-type: application/json; charset=utf-8" "$host/ucloud/example/integration/welcome" -d '{
    "token": "9eb96d0a27b1330cdc727ef4316bd48265f71414",
    "createdProvider": {
        "refreshToken": "8accc446c2e3ac924ff07c77d93e1679378a5dad",
        "publicKey": "~~ public key ~~"
    }
}'


# {
# }

# Alternatively, the sysadmin can read the tokens and perform manual configuration.

# Authenticated as systemAdministrator
curl -XGET -H "Authorization: Bearer $accessToken" "$host/api/providers/retrieve?includeOthers=false&includeUpdates=false&includeSupport=false&includeProduct=false&id=51231" 

# {
#     "id": "51231",
#     "specification": {
#         "id": "example",
#         "domain": "provider.example.com",
#         "https": true,
#         "port": null,
#         "product": {
#             "id": "",
#             "category": "",
#             "provider": "ucloud_core"
#         }
#     },
#     "refreshToken": "8accc446c2e3ac924ff07c77d93e1679378a5dad",
#     "publicKey": "~~ public key ~~",
#     "createdAt": 1633329776235,
#     "status": {
#         "resolvedSupport": null,
#         "resolvedProduct": null
#     },
#     "updates": [
#     ],
#     "owner": {
#         "createdBy": "sysadmin",
#         "project": null
#     },
#     "permissions": null
# }
Communication Flow: Visual

Example: A Provider authenticating with UCloud/Core

Frequency of useCommon
Pre-conditions
  • The provider has already been registered with UCloud/Core
Actors
  • The UCloud/Core service user (ucloud)
  • The provider (provider)
Communication Flow: Kotlin
/* 📝 Note: The tokens shown here are not representative of tokens you will see in practice */

AuthProviders.refresh.call(
    bulkRequestOf(RefreshToken(
        refreshToken = "fb69e4367ee0fe4c76a4a926394aee547a41d998", 
    )),
    provider
).orThrow()

/*
BulkResponse(
    responses = listOf(AccessToken(
        accessToken = "eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIjUF9leGFtcGxlIiwicm9sZSI6IlBST1ZJREVSIiwiaWF0IjoxNjMzNTIxMDA5LCJleHAiOjE2MzM1MjE5MTl9.P4zL-LBeahsga4eH0GqKpBmPf-Sa7pU70QhiXB1BchBe0DE9zuJ_6fws9cs9NOIo", 
    )), 
)
*/
Communication Flow: Curl
# ------------------------------------------------------------------------------------------------------
# $host is the UCloud instance to contact. Example: 'http://localhost:8080' or 'https://cloud.sdu.dk'
# $accessToken is a valid access-token issued by UCloud
# ------------------------------------------------------------------------------------------------------

# 📝 Note: The tokens shown here are not representative of tokens you will see in practice

# Authenticated as provider
curl -XPOST -H "Authorization: Bearer $accessToken" -H "Content-Type: content-type: application/json; charset=utf-8" "$host/auth/providers/refresh" -d '{
    "items": [
        {
            "refreshToken": "fb69e4367ee0fe4c76a4a926394aee547a41d998"
        }
    ]
}'


# {
#     "responses": [
#         {
#             "accessToken": "eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIjUF9leGFtcGxlIiwicm9sZSI6IlBST1ZJREVSIiwiaWF0IjoxNjMzNTIxMDA5LCJleHAiOjE2MzM1MjE5MTl9.P4zL-LBeahsga4eH0GqKpBmPf-Sa7pU70QhiXB1BchBe0DE9zuJ_6fws9cs9NOIo"
#         }
#     ]
# }
Communication Flow: Visual

Remote Procedure Calls

browse

API: Stable Auth: Users

Browses the catalog of available Providers

Request Response Error
ResourceBrowseRequest<ProviderIncludeFlags> PageV2<Provider> CommonErrorMessage

This endpoint can only be used my users who either own a Provider or are a UCloud administrator.

retrieve

API: Stable Auth: Users

Retrieves a single Provider

Request Response Error
ResourceRetrieveRequest<ProviderIncludeFlags> Provider CommonErrorMessage

This endpoint can only be used my users who either own a Provider or are a UCloud administrator.

retrieveSpecification

API: Stable Auth: Services

Retrieves the specification of a Provider

Request Response Error
FindByStringId ProviderSpecification CommonErrorMessage

This endpoint is used by internal services to look up the contact information of a Provider

approve

API: Stable Auth: Public Deprecated: Yes

Used for the last step of the approval protocol

Request Response Error
ProvidersApproveRequest FindByStringId CommonErrorMessage

This call is used as part of the approval protocol. View the example for more information.

Examples:

Example
Registration protocol

create

API: Stable Auth: Users

Creates one or more Providers

Request Response Error
BulkRequest<ProviderSpecification> BulkResponse<FindByStringId> CommonErrorMessage

This endpoint can only be invoked by a UCloud administrator.

init

API: Stable Auth: Users

Request (potential) initialization of resources

Request Response Error
Unit Unit CommonErrorMessage

This request is sent by the client, if the client believes that initialization of resources might be needed. NOTE: This request might be sent even if initialization has already taken place. UCloud/Core does not check if initialization has already taken place, it simply validates the request.

renewToken

API: Stable Auth: Users

Replaces the current refresh-token and certificate of a Provider

Request Response Error
BulkRequest<ProvidersRenewRefreshTokenRequestItem> Unit CommonErrorMessage

⚠️ WARNING: This endpoint will immediately invalidate all traffic going to your Provider This endpoint should only be used if the current tokens are compromised.


requestApproval

API: Stable Auth: Public Deprecated: Yes

Used for the approval protocol

Request Response Error
ProvidersRequestApprovalRequest ProvidersRequestApprovalResponse CommonErrorMessage

This call is used as part of the approval protocol. View the example for more information.

Examples:

Example
Registration protocol

update

API: Stable Auth: Users

Updates the specification of one or more providers

Request Response Error
BulkRequest<ProviderSpecification> BulkResponse<FindByStringId> CommonErrorMessage

This endpoint can only be invoked by a UCloud administrator.

updateAcl

API: Stable Auth: Users

Updates the ACL attached to a resource

Request Response Error
BulkRequest<UpdatedAcl> BulkResponse<Unit> CommonErrorMessage

Data Models

Provider

API: Stable

Providers, the backbone of UCloud, expose compute and storage resources to end-users.

data class Provider(
    val id: String,
    val specification: ProviderSpecification,
    val refreshToken: String,
    val publicKey: String,
    val createdAt: Long,
    val status: ProviderStatus,
    val updates: List<ProviderUpdate>,
    val owner: ResourceOwner,
    val permissions: ResourcePermissions?,
    val providerGeneratedId: String?,
)

You can read more about providers here.

Properties
id: String A unique identifier referencing the `Resource`

The ID is unique across a provider for a single resource type.

specification: ProviderSpecification
refreshToken: String
publicKey: String
createdAt: Long Timestamp referencing when the request for creation was received by UCloud
status: ProviderStatus Holds the current status of the `Resource`
updates: List<ProviderUpdate> Contains a list of updates from the provider as well as UCloud

Updates provide a way for both UCloud, and the provider to communicate to the user what is happening with their resource.

owner: ResourceOwner Contains information about the original creator of the `Resource` along with project association
permissions: ResourcePermissions? Permissions assigned to this resource

A null value indicates that permissions are not supported by this resource type.

providerGeneratedId: String?

API: Internal/Beta


ProviderIncludeFlags

API: Stable

Flags used to tweak read queries

data class ProviderIncludeFlags(
    val includeOthers: Boolean?,
    val includeUpdates: Boolean?,
    val includeSupport: Boolean?,
    val includeProduct: Boolean?,
    val filterCreatedBy: String?,
    val filterCreatedAfter: Long?,
    val filterCreatedBefore: Long?,
    val filterProvider: String?,
    val filterProductId: String?,
    val filterProductCategory: String?,
    val filterProviderIds: String?,
    val filterIds: String?,
    val filterName: String?,
    val hideProductId: String?,
    val hideProductCategory: String?,
    val hideProvider: String?,
)
Properties
includeOthers: Boolean?
includeUpdates: Boolean?
includeSupport: Boolean?
includeProduct: Boolean? Includes `specification.resolvedProduct`
filterCreatedBy: String?
filterCreatedAfter: Long?
filterCreatedBefore: Long?
filterProvider: String?
filterProductId: String?
filterProductCategory: String?
filterProviderIds: String? Filters by the provider ID. The value is comma-separated.
filterIds: String? Filters by the resource ID. The value is comma-separated.
filterName: String?
hideProductId: String?
hideProductCategory: String?
hideProvider: String?

ProviderSpecification

API: Stable

The specification of a Provider contains basic (network) contact information

data class ProviderSpecification(
    val id: String,
    val domain: String,
    val https: Boolean,
    val port: Int?,
    val product: ProductReference,
)
Properties
id: String
domain: String
https: Boolean
port: Int?
product: ProductReference

API: Internal/Beta


ProviderStatus

API: Stable

A placeholder document used only to conform with the Resources API

data class ProviderStatus(
    val resolvedSupport: ResolvedSupport<Product, ProviderSupport>?,
    val resolvedProduct: Product?,
)
Properties
resolvedSupport: ResolvedSupport<Product, ProviderSupport>? 📝 NOTE: Always null
resolvedProduct: Product? 📝 NOTE: Always null

ProviderSupport

API: Stable

A placeholder document used only to conform with the Resources API

data class ProviderSupport(
    val product: ProductReference,
    val maintenance: Maintenance?,
)
Properties
product: ProductReference
maintenance: Maintenance?

ProviderUpdate

API: Stable

Updates regarding a Provider, not currently in use

data class ProviderUpdate(
    val timestamp: Long,
    val status: String?,
)
Properties
timestamp: Long A timestamp referencing when UCloud received this update
status: String? A generic text message describing the current status of the `Resource`

ResourceOwner

API: Stable

The owner of a Resource

data class ResourceOwner(
    val createdBy: String,
    val project: String?,
)
Properties
createdBy: String
project: String?

ResourcePermissions

API: Stable

data class ResourcePermissions(
    val myself: List<Permission>,
    val others: List<ResourceAclEntry>?,
)
Properties
myself: List<Permission> The permissions that the requesting user has access to
others: List<ResourceAclEntry>? The permissions that other users might have access to

This value typically needs to be included through the includeFullPermissions flag


UpdatedAcl

API: Stable

data class UpdatedAcl(
    val id: String,
    val added: List<ResourceAclEntry>,
    val deleted: List<AclEntity>,
)
Properties
id: String
added: List<ResourceAclEntry>
deleted: List<AclEntity>

ProvidersApproveRequest

API: Stable Deprecated: Yes

Request type used as part of the approval process

data class ProvidersApproveRequest(
    val token: String,
)
Properties
token: String

ProvidersRenewRefreshTokenRequestItem

API: Stable

Request type for renewing the tokens of a Provider

data class ProvidersRenewRefreshTokenRequestItem(
    val id: String,
)
Properties
id: String

ProvidersRequestApprovalRequest

API: Stable Deprecated: Yes

Request type used as part of the approval process

sealed class ProvidersRequestApprovalRequest {
    class Information : ProvidersRequestApprovalRequest()
    class Sign : ProvidersRequestApprovalRequest()
}

ProvidersRequestApprovalRequest.Information

API: Stable Deprecated: Yes

Request type used as part of the approval process, provides contact information

data class Information(
    val specification: ProviderSpecification,
    val type: String /* "information" */,
)
Properties
specification: ProviderSpecification
type: String /* "information" */ The type discriminator

ProvidersRequestApprovalRequest.Sign

API: Stable Deprecated: Yes

Request type used as part of the approval process, associates a UCloud user to previously uploaded information

data class Sign(
    val token: String,
    val type: String /* "sign" */,
)
Properties
token: String
type: String /* "sign" */ The type discriminator

ProvidersRequestApprovalResponse

API: Stable Deprecated: Yes

Response type used as part of the approval process

sealed class ProvidersRequestApprovalResponse {
    class AwaitingAdministratorApproval : ProvidersRequestApprovalResponse()
    class RequiresSignature : ProvidersRequestApprovalResponse()
}

ProvidersRequestApprovalResponse.AwaitingAdministratorApproval

API: Stable Deprecated: Yes

Response type used as part of the approval process

data class AwaitingAdministratorApproval(
    val token: String,
    val type: String /* "awaiting_admin_approval" */,
)
Properties
token: String
type: String /* "awaiting_admin_approval" */ The type discriminator

ProvidersRequestApprovalResponse.RequiresSignature

API: Stable Deprecated: Yes

Response type used as part of the approval process

data class RequiresSignature(
    val token: String,
    val type: String /* "requires_signature" */,
)
Properties
token: String
type: String /* "requires_signature" */ The type discriminator