providers

« Previous section Next section »

UCloud Developer Guide / Accounting and Project Management / Providers

Providers

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

2. Remote Procedure Calls

3. Data Models

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

Browses the catalog of available Providers

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

retrieve

Retrieves a single Provider

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

retrieveSpecification

Retrieves the specification of a Provider

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

Searches the catalog of available resources

approve

Used for the last step of the approval protocol

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

Examples:

create

Creates one or more Providers

This endpoint can only be invoked by a UCloud administrator.

init

Request (potential) initialization of resources

RequestResponseError

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

Replaces the current refresh-token and certificate of a Provider


⚠️ 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

Used for the approval protocol

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

Examples:

update

Updates the specification of one or more providers

This endpoint can only be invoked by a UCloud administrator.

updateAcl

Updates the ACL attached to a resource

Data Models

Provider

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


ProviderIncludeFlags

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


ProviderSpecification

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


ProviderStatus

A placeholder document used only to conform with the Resources API

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


ProviderSupport

A placeholder document used only to conform with the Resources API

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


ProviderUpdate

Updates regarding a Provider, not currently in use

data class ProviderUpdate(
    val timestamp: Long,
    val status: String?,
)
Properties


ResourceOwner

The owner of a Resource

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


ResourcePermissions

data class ResourcePermissions(
    val myself: List<Permission>,
    val others: List<ResourceAclEntry>?,
)
Properties


UpdatedAcl

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


ProvidersApproveRequest

Request type used as part of the approval process

data class ProvidersApproveRequest(
    val token: String,
)
Properties


ProvidersRenewRefreshTokenRequestItem

Request type for renewing the tokens of a Provider

data class ProvidersRenewRefreshTokenRequestItem(
    val id: String,
)
Properties


ProvidersRequestApprovalRequest

Request type used as part of the approval process

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

ProvidersRequestApprovalRequest.Information

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

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


ProvidersRequestApprovalRequest.Sign

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


ProvidersRequestApprovalResponse

Response type used as part of the approval process

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

ProvidersRequestApprovalResponse.AwaitingAdministratorApproval

Response type used as part of the approval process

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


ProvidersRequestApprovalResponse.RequiresSignature

Response type used as part of the approval process

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


Last updated