Exoscale Marketplace Integration
To integrate services from the VSHN Application Catalog into the Exoscale Marketplace, we provide an Exoscale-specific Open Service Broker (OSB) API endpoint to provision Organizations and enable access to the service offering. A web portal is provided by VSHN to the end-user of Exoscale to provision and manage services.
When an Exoscale customer enables a service on the Exoscale Marketplace, access to the service will be enabled on the VSHN Application Marketplace. The Exoscale customer then self-service provisions and configures the service instances on the VSHN portal. Disabling a service by an Exoscale customer will disable access to the service on our side, and after a grace period, all instances are deleted if they haven’t been deleted by the customer yet.
Except the Central Control Plane (CCP, see Central Control Plane (CCP)) everything runs on Exoscale premises. Every Exoscale zone will run at least one Worker Cluster which hosts the service instances and a Cloud Service Provider Control Plane (CSPCP).
We regularly send usage data from VSHN Central (Odoo) to Exoscale for invoicing the end-user. Every month an invoice is sent from VSHN to Exoscale for the service usage of the last month.
Terminology
- Open Service Broker API
-
"The Open Service Broker API project allows independent software vendors, SaaS providers and developers to easily provide backing services to workloads running on cloud native platforms." See official API spec.
- OSB API
-
Abbreviation of Open Service Broker API.
- OSB Specific Terms
-
Excerpt from API spec Terminology:
-
Service Offering: The advertisement of a Service that a Service Broker supports.
-
Service Plan: The representation of the costs and benefits for a given variant of the Service Offering, potentially as a tier.
-
Service Instance: An instantiation of a Service Offering and Service Plan.
-
- Exoscale Marketplace
-
The marketplace of Exoscale enabling the self-service ordering of services from third-party providers.
Architecture
The Central Control Plane (CCP) is doing the heavy lifting, while the custom OSB API endpoint is used for Exoscale integration, acting like an end-user which directly interacts with the control-plane API (which is a custom Kubernetes API).
The "Enable" button in the Exoscale Marketplace Portal will:
-
Provision an Organization at VSHN (if it not already exists) which is tied to Exoscale (
origin=exoscale
). See Exoscale Organizations. -
Enable access to the enabled service, ready to be provisioned in the VSHN Portal
This Organization will be tied to Exoscale services, it can only see services from Exoscale and only provision at Exoscale premises.
OSB API at Exoscale
Exoscale uses the OpenServiceBroker (OSB) API for service provisioning and deprovisioning with external vendors, that’s why we’re integrating this way.
The API currently has the following features:
-
Service instance provisioning
-
Service instance update (plan changes, suspensions, user sync)
-
Service instance deprovisioning
-
Synchronous requests support
-
CloudFoundry platform compatibility mode
Service Listing
Every service in the VSHN Application Catalog that is available in the Exoscale Marketplace is individually listed in the Exoscale Marketplace.
Listing in the Exoscale Marketplace is done on the Exoscale side (they manually add them to their database). We don’t offer the listing from our side through the OSB API (no catalog
endpoint).
We specifically only list services in the VSHN Portal which are enabled on the Exoscale Marketplace.
This is handled by the ProvidedService
object in the Central Control Plane.
Other available services do get a hint in the VSHN Portal that they need to be enabled first on the Exoscale Marketplace to get available for provisioning.
OSB Plans and Services
There are a few OSB plan requirements:
-
An OSB API service must match one product on the Exoscale marketplace.
-
An OSB API plan should be setup for each published plan for that product.
-
An additional technical plan must be available for managing suspensions of end user organizations.
Mapping of service ID and plan ID to Compositions is configured in the OSB API.
It will set the values in ProvidedService
(see Central Control Plane (CCP)).
We don’t provide the OSB API /v2/catalog endpoint as this is not required for the Exoscale Marketplace (See Service Listing).
|
Exoscale Organizations
When an Exoscale user clicks on the green "Enable" button on a service offering page, the onboarding flow is triggered in the Central Control Plane (CCP).
Onboarding
PUT http://exo-osbapi.vshn.net/v2/service_instances/:instance_id
{
"service_id": "service-test-guid", (1)
"plan_id": "plan1-test-guid", (2)
"organization_guid": "org-guid-here", (3)
"space_guid": "space-guid-here", (3)
"parameters": {
"users": [ (4)
{
"email":"email",
"full_name": "full name",
"role":"owner|tech"
}
]
},
"context": {
"organization_guid": "org-guid-here", (3)
"space_guid": "space-guid-here", (3)
}
}
1 | The UUID of the service on VSHN side |
2 | The UUID of the plan on VSHN side |
3 | The Exoscale organization UUID |
4 | List of users |
-
200
:ProvidedService
already exists -
201
: Successfully createdProvidedService
object
Sources:
On the Central Control Plane (CCP) an Organization
object is created by the OSB API if it doesn’t exist yet.
- Organization Object Name
-
We use the Exoscale organization UUID for the object name
metadata.name
, prefixed byexo-
. - Organization Display Name
-
The display name
spec.displayName
is set to the name of the Exoscale organization. TODO: How do we get this name? - Organization Origin
-
The origin
spec.origin
is set to "Exoscale" (hardcoded in the OSB API service) - Invitation
-
When the Organization is created the first time, an
Invitation
object is created, sending an invitation to the user in the fieldparameters.users[0].email
from the OSB API.
To keep track of provisioning requests and enabling access to services, we store an ProvidedService
(see Central Control Plane (CCP)) object in the organization namespace, containing all the details of the provisioning call, including .status
which stores the details what happened (for example organization created or already existed, Exoscale API informed, …)
Suspension
This flow is triggered when an Exoscale organization:
-
changes their current plan
-
is suspended
-
changes the user list on Exoscale side and user sync is turned on
The suspension uses a special "suspension" plan.
PATCH http://exo-osbapi.vshn.net/v2/service_instances/:instance_id
{
"service_id": "service-test-guid",
"plan_id": "plan1-test-guid", (1)
"parameters": {
"users": [
{
"email":"email",
"full_name": "full name",
"role":"owner|tech"
}
]
}
}
1 | Special suspension plan, to be defined |
-
200
:ProvidedService
updated
Sources:
When the suspension plan is triggered, we send an E-Mail to customers@vshn.ch with all the information we have, so that we can check back with Exoscale what to do. No service is automatically suspended. If it has to happen, we’ll do it manually.
Also, the annotation exoscale.com/planId
in the affected ProvidedService
of the instance_id
is updated with the plan_id
.
Offboarding
This flow is triggered when an Exoscale organization:
-
decides to unsubscribe the product
-
suspension is not resolved before 7 days in trial mode, or 30 days outside of trial mode, which triggers a purge of their resources
-
decides to close their Exoscale account, or their account is terminated
DELETE http://exo-osbapi.vshn.net/v2/service_instances/:instance_id?service_id=service-test-guid&plan_id=plan1-test-guid
-
200
:ProvidedService
updated with deletionTimestamp
Sources:
When all ProvidedService
objects are deleted (none exists anymore), an email is sent to customer@vshn.ch for the final closure of the organization.
Also, there is a monitoring check which triggers when no ProvidedService
is available, but service instances are still there and the deletion grace period is over.
This means something failed in cleaning up.
See also Deprovisioning, which details the single service deprovisioning.
User Synchronization
We don’t do user synchronization from Exoscale to VSHN.
When user sync is disabled, only the information of the user that made the product purchase will be provided. The information will never be updated.
Instances
Provisioning
Instances aren’t directly provisioned via the OSB API.
Instead, a ProvidedService
is stored which enables access to the enabled service in the VSHN Portal.
See Onboarding for more details, as it’s mostly the same flow.
apiVersion: appcat.vshn.io/v1
kind: ProvidedService
metadata:
name: $instance_id (1)
namespace: $organization (2)
labels:
exoscale.com/serviceId: $service_id (3)
exoscale.com/planId: $plan_id (4)
exoscale.com/email: $email (5)
spec:
compositionSelector: (6)
metadata.appcat.vshn.io/serviceprovider: exoscale
metadata.appcat.vshn.io/servicename: VSHNPostgreSQL
1 | From OSB API :instance_id |
2 | From Onboarding |
3 | From OSB API .service_id |
4 | From OSB API .plan_id |
5 | From OSB API .parameters.users[0].email |
6 | From OSB API static configuration, mapping of service_id |
An E-Mail is sent to the address in the annotation exoscale.com/email
with a well-crafted link to the portal to actually provision the instance.
The portal link encodes:
-
The Organization GUID (
exo-$UUID
) -
The
service_id
-
The
plan_id
When this portal link is opened, a pre-filled service ordering form is presented in the portal, ready for the user to actually provision the service.
This flow allows an Exoscale user to have more than one instance per service per Exoscale organization.
The actual service provisioning happens via the Central Control Plane (CCP).
E-Mail sending is handled the same way as in Invitation.
Plan Change
We don’t support plan changes on the Exoscale console, all service parameters are configured on our portal on the actual service provisioning. There is only one plan per service, the default plan.
One exception is the "suspension plan" which is described in the suspension flow.
Deprovisioning
See also Offboarding which talks about Organization offboarding and the OSB API flow.
The matching ProvidedService
gets updated, storing the deletion intention in spec.deletionTimestamp
.
After a grace period, all service instances matching the service are deleted automatically by a custom controller.
The ProvidedService
gets updated with the information which service instances have been deleted.
We also send an E-Mail for each service instance which gets deleted that way, telling the customer that the service either has to be removed from the VSHN Portal or that it’s automatically deleted after the deletion grace period.
Billing
This part is still in its early stages! |
The basic flow: We send billing data to Exoscale, Exoscale invoices the end-user, VSHN sends an invoice to Exoscale, Exoscale pays VSHN.
Exoscale must keep track on our pricing on their end, because we only send usage data and they do the calculation.
TODO
-
Send billing data to Exoscale billing API - Exoscale does invoicing to customer - we send invoice to Exoscale
-
One SO on VSHN side for Exoscale, to send invoice to Exoscale
-
We track the Exoscale organization ID in the SO
-
Maybe different product in product DB? Or different variant?
-
-
How to send billing data to Exoscale? Once per month directly from Odoo data, so that we send the same data?
From Exoscale docs:
You can define one or more plans corresponding to various service offerings or service levels on your platform.
Monthly fees
Each plan can have an optional monthly fee. When a subscriber unsubscribes from your service, the service is cancelled immediately and they are charged with a pro-rated amount dating from their last subscription charge.
Additional charges
It is possible to charge for additional products and services in addition to the optional monthly fee. All additional billing dimensions must be declared in advance with a defined price for each available plan.
Billing dimensions are specified by:
a technical name
a unit
Supported units are:
h : hours
gb : gigabytes
gb.h : gigabytes per hour
u : arbitrary quantity
The frequency of metering reporting is up to the vendor. You can meter as frequently as every hour. Metering should be reported at least once a month per customer. Metering is reported per client organization with the consumption that has occurred since the last successful report. Multiple charges can be reported at once. When reporting usage, you send the quantity for each defined variable and the client is charged accordingly.
POST /orgs/:uuid/usage (1)
{
"records": [
{
"variable": "something",
"quantity": 12.5
},
{
"variable": "something_else",
"quantity": 1.2
}
]
}
1 | :uuid is the technical ID of the client organization in the Exoscale backend, which will be shared during the onboarding process. |