Humanitec API (0.1.0)

API Support: [email protected]

The API is currently in beta. We are looking for feedback on both, the API design itself as well as the documentation.

Introduction

The Humanitec API allows for automating and integrating of Humanitec into your workflows The API is a REST based API. It is based around a set of concepts:

  • Core
  • External Resources
  • Sets and Deltas

Authentication

Almost all requests made to the Humanitec API require Authentication. Humanitec provides 2 ways of authenticating with the API: Bearer and JWT.

Bearer Authentication

This form of authentication makes use of a static token. It is intended to be used when machines interact with the Humanitec API. Bearer tokens should be used for very narrow purposes. This allows for the token to be revoked if it is compromised and so limit the scope of exposure. New Bearer tokens can be obtained via the UI:

  1. Log into Humanitec at https://app.humanitec.io
  2. Go to Organization Settings
  3. Select API tokens
  4. Enter a name for the new token and click on Generate new token

The token is passed to the API via the Authorization header. Assuming the issued token is HUMANITEC_TOKEN, the request could be made as follows:

    curl -H 'Authorization: Bearer HUMANITEC_TOKEN' https://api.humanitec.io/orgs/my-org/apps

JWT Authentication

This form of authentication makes use of a JSON Web Token (JWT). It is intended to be used when humans interact with the Humanitec API. JWTs expire after a period of time. This means that a new JWT will need to be generated regularly. This makes them well suited to working in short sessions, but not for automation. (See Bearer Authentication.) The token is passed to the API via the Authorization header. Assuming the issued token is HUMANITEC_JWT, the request could be made as follows:

    curl -H 'Authorization: JWT HUMANITEC_JWT' https://api.humanitec.io/orgs/my-org/apps

Content Types

All of the Humanitec API unless explicitly only accepts content types of application/json and will always return valid application/json or an empty response.

Response Codes

Success

Any response code in the 2xx range should be regarded as success.

Code Meaning
200 Success
201 Success (In future, 201 will be replaced by 200)
204 Success, but no content in response

Note: We plan to simplify the interface by replacing 201 with 200 status codes.

Failure

Any response code in the 4xx should be regarded as an error which can be rectified by the client. 5xx error codes indicate errors that cannot be corrected by the client.

Code Meaning
400 General error. (Body will contain details)
401 Attempt to access protected resource without Authorization Header.
403 The Bearer or JWT does not grant access to the requested resource.
404 Resource not found.
405 Method not allowed
409 Conflict. Usually indicated a resource with that ID already exists.
422 Unprocessable Entity. The body was not valid JSON, was empty or contained an object different from what was expected.
429 Too many requests - request rate limit has been reached.
500 Internal Error. If it occurs repeatedly, contact support.

Concepts

Core

Overview

The core objects in the API provide the structure that allows Continuous Delivery to be well organized. The core objects are summarised as:

Object Description
Organization The root of the object hierarchy representing unrelated teams or companies.
Application A logical collection of related Kubernetes workloads that should run in the same namespace.
Environment An independent space that an Application can be deployed into.
Deployment A specific version of code and configuration that has been deployed into an Environment.

The hierarchy is illustrated by this Entity Relationship Diagram (ERD):

Entity Relationship Diagram for Core Objects

Additional Objects

In addition to Organizations, Applications, Environments, and Deployments, a number of other objects are included in this section:

Object Description
Image Represents many builds (aka versions) of the same container image.
Image Source How Images are brought into Humanitec.
Environment Type A way of grouping and managing Environments.

External Resources

Overview

Not everything required by an Application can be run in a Kubernetes cluster. It does not make sense to run some things in a cluster such as Public DNS. Sometimes developers and architectures may prefer to take advantage of "Managed Services" instead of running them inside a cluster. Humanitec can manage and provision dependencies that are external to the cluster. We call these "External Resources". Examples include:

  • Postgres databases provided via a managed service such as Google CloudSQL,
  • DNS Names provisioned using Cloudflare Managed DNS, or
  • S3 buckets provided by Amazon S3.

Resource Types

All External Resources have a Type. This defines what technology the Application has the dependency on and is distinct from the implementation of that technology. For example, the redis type represents a Redis store but does not specify if it is provided via an actual Redis Cluster or via a compatible service such as Google's Memorystore or Amazon ElastiCache for Redis. Each Resource Type has its own way of being parameterized. For example, a resource of type dns needs to know the IP address that A record should point at.

Active Resources

An Active Resource describes a provisioned and usable resource. This represents an instance of the resource, e.g. the actual database that data can be stored in or the DNS name that can be used to resolve the IP address serving a service.

Resource Definitions

Active Resources are specified via Resource Definitions. These tell Humanitec how to provision a resource of a particular Resource Type. Resource Definitions are chosen based on Matching Criteria. There are two different kinds of Resource Definition, Dynamic Resource Definitions, and Static Resource Definitions.

Matching Criteria

Humanitec chooses which Resource Definition to use based on Matching Criteria. A Matching Criteria specifies a set of values that the properties of an Environment must have in order for the Resource Definition to be matched and so used to provision the resource. These properties include:

Property Description
app_id The ID of the Application that an Environment belongs to.
env_id The ID of a particular Environment.
env_type The Environment Type that an Environment has.
res_id The ID of the resource as specified in the Deployment Set.

A Matching Criteria can specify 0, 1, or more properties at once. In the event of multiple matches, the most specific match is chosen. For example: if two Resource Definitions for resources with type postgres have the matching criteria:

  Resource Definition A:
    env_type = development

  Resource Definition B:
    env_type = development
    res_id   = modules.my-service.exernals.my-db

and a resource is needed for an Environment of type development and a Postgres database with ID modules.my-service.exernals.my-db, Resource Definition B will be chosen.

Dynamic Resource Definitions

Dynamic Resource Definitions specify Active Resources where Humanitec manages the full lifecycle. In this instance, if a resource is needed it it created by Humanitec and destoryed when it is no longer needed. This is done by specifying a Resource Driver that manages the resource.

Static Resource Definitions

Static Resource Definitions specify Active Resources that are managed outside of Humanitec. For example, a pre-existing database can be used via a Static Resource Definition. In this case, nothing is created or destroyed by Humanitec.

Resource Drivers

Resource Drivers are code that fulfills the Humanitec Resource Driver Interface. This interface allows for certain actions to be performed on resources such as creation and destruction. Humanitec provides a number of Resource Drivers "out of the box". It is also possible to use 3rd party Resource Drivers or even to write your own. Resource Drivers typically call APIs associated with managed services. They use the credentials provided by Resource Accounts in order to manipulate resources provided via managed services.

Resource Accounts

Resource Accounts are identities that are used to provision and manage resources via Dynamic Resource Definitions. They can represent a range of identities including Cloud Provider Service Accounts, VPN Accounts and SSH accounts

Sets and Deltas

Overview

Deployment Sets and Deployment Deltas (referred to in the rest of this document as "Sets" and "Deltas") provide the means of managing the non-environment specific configuration for an Application. A Set contains all non-environment specific configuration for an Application. A Delta describes the difference between two Sets - specifically what needs to be done to change one Set into another.

Basic Operations

Sets and Deltas form a closed algebra over a 3 operations:

Apply

   Set [apply] Delta -> Set

A Delta applied to a Set generates another set. NOTE: This is the only operation that generates a Set. To bootstrap the creation of Sets, a Delta can be applied to the "Empty Set".

Difference

   Set [diff] Set -> Delta

The difference between two Sets generates a Delta.

Combine

   Delta [combine] Delta -> Delta

Combining 2 or more Deltas results in a Delta.

Relationship to Deployments

Every Deployment that occurs through Humanitec is based on a Set. Every Deployment has one Set associated with it. Upon deployment, the supplied Delta is applied to the Set associated with a previous Deployment. This previous Deployment is often but not always the last Deployment in an Environment. See Rebasing an Environment for a description of such a scenario.

Comparison to Version Control Systems

A good model for understanding how Sets and Deltas work is by analogy with Version Control Systems.

VCS Concept Analogous Concept in Humanitec
Commit A Set
Branch Environment
Log Deployment History in an Environment
Diff A Delta generated from the difference between 2 Sets
Patch A Delta that can be applied to a Set

There is no analogy to "merging" - however, an Environment can have the same Set deployed in it by way of Rebasing an Environment.

How to Deploy an Application

In this guide, we would like to show you how to deploy your application via the Humanitec API. Please refer to the API reference for any specific details.

A brief Overview

We will go over the creation of an application with the default environment Development. Then, we'll add a frontend and a backend service to the application based on our Sample Tutorial Application. We'll go over the configuration of those services and finally, we will deploy the application environment to a kubernetes cluster.

Requirements

This example is using bash commands and is requiring cURL as well as jq to be installed.

Obtain an API Token

In order to make authenticated requests to the Humanitec API you'll need to have a valid API token. Please refer to API Authentication to learn how to obtain one. Export the token as an environment variable to use it with your API calls.

export HUMANITEC_TOKEN="your-token"

Obtain your Organization ID

First, we need to obtain your organization id as it is essential for the API path.

HUMANITEC_USER_JSON=$(curl -XGET -H 'Authorization:Bearer '$HUMANITEC_TOKEN'' 'https://api.humanitec.io/users/me' | jq .)
HUMANITEC_ORG=$(echo $HUMANITEC_USER_JSON | jq '.orgs[].id' | tr -d '"')

Create an Application Draft with an Empty Delta

This cURL will create an application draft with the default environment Development. The application will act as a container for your environments which can contain different configurations of your application.

curl -X POST -H 'Content-Type: application/json' -H 'Authorization:Bearer '$HUMANITEC_TOKEN'' \n -d '{"id":"my-sample-app","name":"My Sample App"}' \n https://api.humanitec.io/orgs/$HUMANITEC_ORG/apps

To fill this application with services we need to define an empty application delta first. The delta is a configuration that is getting applied to the environment of your application upon deployment.

DELTA_ID=$(curl -X POST -H 'Content-Type: application/json' -H 'Authorization:Bearer '$HUMANITEC_TOKEN'' \n -d '{"modules": {}}' \n https://api.humanitec.io/orgs/$HUMANITEC_ORG/apps/my-sample-app/deltas | tr -d '"')

Add Backend and Frontend Service to Your Application Delta

The images for the Sample Tutorial Application already exist in Humanitec. If you'd like to add your own images and services to an application, please refer to the API Documentation about Images.

First the Backend Service

Create the payload for the cURL command. In this payload, we already define some default settings. These settings like resource limits and requests as well as the service port can be overwritten later if required.

cat << 'EOF' > payload.json
[
  {
    "modules": {
      "add": {
        "sample-service": {
          "profile": "humanitec/default-module",
          "spec": {
            "service": {
              "ports": [
                {
                  "service_port": 8080
                }
              ]
            },
            "ingress": {
              "enabled": false
            },
            "containers": {
              "sample-service": {
                "id": "sample-service",
                "image": "dev-registry.humanitec.io/public/sample-service:1.2.0",
                "resources": {
                  "limits": {
                    "cpu": "0.250",
                    "memory": "256Mi"
                  },
                  "requests": {
                    "cpu": "0.025",
                    "memory": "64Mi"
                  }
                },
                "variables": {

                },
                "secrets": {

                }
              }
            }
          },
          "externals": {

          }
        }
      }
    }
  }
]
EOF

Now we apply the payload.json via a PATCH call to update the existing Delta for the application.

curl -X PATCH -H 'Content-Type: application/json' -H 'Authorization:Bearer '$HUMANITEC_TOKEN'' \n -d "@payload.json" \n https://api.humanitec.io/orgs/$HUMANITEC_ORG/apps/my-sample-app/deltas/$DELTA_ID

Adding a Postgres Database to the Backend Service

With this payload and PATCH to the delta, we will add a cloudsql Postgres DB to the backend service.

cat << 'EOF' > payload.json
[
  {
    "modules": {
      "update": {
        "sample-service": [
          {
            "op": "add",
            "path": "/externals/postgres",
            "value": {
              "type": "postgres"
            }
          }
        ]
      }
    }
  }
]
EOF

Applying the payload with PATCHing the delta.

curl -X PATCH -H 'Content-Type: application/json' -H 'Authorization:Bearer '$HUMANITEC_TOKEN'' \n -d "@payload.json" \n https://api.humanitec.io/orgs/$HUMANITEC_ORG/apps/my-sample-app/deltas/$DELTA_ID

Adding a Database Connection String as an Environment Variable

With this payload and PATCH to the delta, we will add an environment variable to the service which is containing the connection string to the database. In this string are placeholder variables which will be automatically filled with the credentials to connect to the database once it's created with the deployment.

cat << 'EOF' > payload.json
[
  {
    "modules": {
      "update": {
        "sample-service": [
          {
            "op": "add",
            "path": "/spec/containers/sample-service/variables/CONNECTION_STRING",
            "value": "postgresql://${externals.postgres.username}:${externals.postgres.password}@${externals.postgres.host}:${externals.postgres.port}/${externals.postgres.name}"
          }
        ]
      }
    }
  }
]
EOF

Applying the payload with PATCHing the delta.

curl -X PATCH -H 'Content-Type: application/json' -H 'Authorization:Bearer '$HUMANITEC_TOKEN'' \n -d "@payload.json" \n https://api.humanitec.io/orgs/$HUMANITEC_ORG/apps/my-sample-app/deltas/$DELTA_ID

Now the Frontend

Similar to the Backend, we add a second module/service to the application delta containing the frontend service.

cat << 'EOF' > payload.json
[
  {
    "modules": {
      "add": {
        "sample-app": {
          "profile": "humanitec/default-module",
          "spec": {
            "service": {
              "ports": [
                {
                  "service_port": 8080
                }
              ]
            },
            "ingress": {
              "enabled": false
            },
            "containers": {
              "sample-app": {
                "id": "sample-app",
                "image": "dev-registry.humanitec.io/public/sample-app:1.3.0",
                "resources": {
                  "limits": {
                    "cpu": "0.250",
                    "memory": "256Mi"
                  },
                  "requests": {
                    "cpu": "0.025",
                    "memory": "64Mi"
                  }
                },
                "variables": {

                },
                "secrets": {

                }
              }
            }
          },
          "externals": {

          }
        }
      }
    }
  }
]
EOF

Now we apply the payload.json via a PATCH call to update the existing Delta for the application.

curl -X PATCH -H 'Content-Type: application/json' -H 'Authorization:Bearer '$HUMANITEC_TOKEN'' \n -d "@payload.json" \n https://api.humanitec.io/orgs/$HUMANITEC_ORG/apps/my-sample-app/deltas/$DELTA_ID

Exposing the Frontend to a generated URL

Here we define an ingress to be created in order for the app to be exposed under a generated DNS and URL.

cat << 'EOF' > payload.json
[
  {
    "modules": {
      "update": {
        "sample-app": [
          {
            "op": "add",
            "path": "/spec/ingress/enabled",
            "value": true
          }
        ]
      }
    }
  }
]
EOF

Now we apply the payload.json via a PATCH call to update the existing Delta for the application.

curl -X PATCH -H 'Content-Type: application/json' -H 'Authorization:Bearer '$HUMANITEC_TOKEN'' \n -d "@payload.json" \n https://api.humanitec.io/orgs/$HUMANITEC_ORG/apps/my-sample-app/deltas/$DELTA_ID

Deploying the Application

Now everything is configured. We can now deploy the application using the updated delta.

curl -X POST -v -H 'Content-Type: application/json' -H 'Authorization:Bearer '$HUMANITEC_TOKEN'' \n -d '{"delta_id":"'$DELTA_ID'","comment":"My Sample App Deployment"}' \n https://api.humanitec.io/orgs/$HUMANITEC_ORG/apps/my-sample-app/envs/development/deploys

The running Application

Within seconds the application will be deployed to a kubernetes cluster. In addition, a cloudsql database is provisioned and connected to the backend. Also, a DNS record has been created pointing to the exposed Frontend service. The status of the running application can be obtained via a GET call to the /runtime endpoint. Here is an example of obtaining the dynamically generated URL/DNS of the frontend service.

APP_RUNTIME_JSON=$(curl -XGET -H 'Authorization:Bearer '$HUMANITEC_TOKEN'' 'https://api.humanitec.io/orgs/'$HUMANITEC_ORG'/apps/my-sample-app/envs/development/runtime' | jq .)
echo $APP_RUNTIME_JSON | jq '.dns."sample-app"' | tr -d '"'

Additional Notes

In this example, we did a lot of different updates to the delta object to separate clearly the different features. As you might have already guessed, these changes to the delta can also be done in one PATCH request by merging the JSON payloads.

Applications

An Application is a collection of Modules that work together. When deployed, all Modules in an Application are deployed to the same namespace.

Apps are the root of the configuration tree holding Environments, Deployments, Shared Values, and Secrets.

id
required
string ^[a-z0-9][a-z0-9-]+[a-z0-9]$

The ID which refers to a specific application.

name
required
string

The Human-friendly name for the Application.

Copy
Expand all Collapse all
{
  • "created_at": "2020-05-22T14:53:27Z",
  • "created_by": "[email protected]",
  • "envs":
    [
    ],
  • "id": "my-app",
  • "name": "My Application"
}

List all Applications in an Organization.

Listing or lists of all Applications that exist within a specific Organization.

path Parameters
orgId
required
string

The Organization ID.

Responses

200

Possibly empty list of Applications.

get/orgs/{orgId}/apps
/orgs/{orgId}/apps

Response samples