Writing a custom Driver
Drivers should be simple and isolated; this means that they should be responsible for managing precisely one Resource Type per endpoint and that the Resources created should not interfere with each other.
When creating a Driver, you will need to consider three elements:
- How to provision the Resources
- How to store the provisioned Resource's state
- How to handle the Resource Account(s) needed to provision the Resources
In general, Drivers are APIs that fulfil the Humanitec Driver Interface. This interface allows Humanitec to create and destroy Resources as required by Deployments.
Drivers typically call APIs associated with managed services, using the credentials provided by the Resource Accounts as necessary. Resource Accounts are identities used to provision and manage resources via Dynamic Resource Definitions. They can represent a range of identities, including cloud provider service accounts, VPN accounts, SSH accounts, and other credentials.
If you are interested in writing your own Driver get in touch with us, as we are happy to support you and likely already have a solution.
We're currently working on improvements to the API spec for custom drivers that will, unfortunately, result in this version of the API spec being deprecated.
Before you start writing a new Driver, you must understand the flows that will trigger your Driver's API.
When deploying an Application (App), the Platform Orchestrator will evaluate the Delta and the Deployment and begin resource matching. Once the Platform Orchestrator has identified the necessary Drivers and Resource Accounts, it will contact the Drivers and supply any relevant configuration. This process begins by issuing a
PUTrequest to the Driver's API. The Driver will then need to evaluate whether it needs to create or update the resource. It does this by comparing the contents of the
PUTto its internal state representation. If the Driver responds with a
202 Accepted, the orchestrator will periodically poll it with the same data until it returns a
When redeploying (or updating) an App, the Platform Orchestrator follows the same process and hits the same endpoints as when handling new Deployments. This use of a common process simplifies the interface and implementation of Drivers as the Platform Orchestrator doesn't need to differentiate between new resources and ones that already exist.
When a Resource is no longer needed, the Platform Orchestrator will contact the relevant Driver with a
DELETErequest for the specific resource. If the Driver responds with a
202 Accepted, the Platform Orchestrator will periodically poll the Driver until it receives a
204 No Content.
Drivers receive a Globally Unique Resource ID (
GUResID) as a
pathparameter, uniquely identifying the Resource that needs to be provisioned, updated, or deallocated.
GUResIDsare uniquely tied to the context of a resource. This means that if a resource is deleted and recreated, it would have the same
A Humanitec Driver must only create one instance of a Resource for a particular
GUResID. How a Resource instance is defined is up to the Driver. It is critical that multiple
PUTrequests to the Driver with the same
DELETErequests not create new instances.
Humanitec provides a mechanism for a Driver to store a small amount of state via a cookie-like Header called the Humanitec Driver Cookie. This Cookie allows the implementation of Divers without needing to handle their own state storage.
To set the Cookie, supply a
Set-Humanitec-Driver-Cookieheader in the response to the
PUTrequest. This Cookie can contain up to 10kB (10240bytes) of data, returned via a header called
Humanitec-Driver-Cookieon all subsequent requests. After a successful
DELETE, Humanitec automatically clears this Cookie. The Cookie can also be cleared by the Driver by sending an empty
Set-Humanitec-Driver-Cookie. To avoid character encoding issues, we recommend encoding the data you wish to store in the Cookie as a base64 string.
Humanitec considers the Cookie to be a sensitive opaque blob. It is stored securely in the configured secret store.
For resources that take little time to provision (i.e., under 180seconds), we recommend building your Driver to be synchronous. Meaning that it should only return once an action has finished executing, waiting until the action (provisioning/de-provisioning) is complete before returning a response with an HTTP Status Code of either
200for Create or Update requests or a
204for Delete requests.
Frequently, however, provisioning Resources can take a long time. For example, provisioning a new database instance or Kubernetes cluster can take tens of minutes on some platforms. Long-running HTTP requests are often subject to timeout due to underlying policies in various nodes of the TCP network.
As writing asynchronous Drivers can be more complex, we recommend only implementing an asynchronous Driver if resource provisioning could take longer than 3 minutes (180s).
An asynchronous Driver is fundamentally similar to the default synchronous type, except the first return to any action is an HTTP status code of
202. Humanitec will then periodically poll the Driver until a response with an HTTP status code of
200(on Create & Update),
204(on Delete), or a non-2xx status code is received.
An asynchronous driver needs must be able to independently track the state of the resource being provisioned and ensure that it can handle edge cases such as:
- A resource being deallocated before provisioning is complete.
- A resource being updated while provisioning is still ongoing.
- A resource being recreated while the previous instance is deallocated.
We maintain the following open-source reference implementations: