REST API

The Nelson service provides a fairly extensive HTTP API. Most endpoints accept and return application/json representations. As the API is quite extensive (every action Nelson takes has an API), this document has been broken down into a set of logical sections outlined below:


Overview

This section describes some common themes in the Nelson API.

  1. Authentication
  2. User Agent Required
  3. Error Reporting

Authentication

All requests to Nelson are secured. The expectation is that every request includes the Nelson security token. The following is an example:

curl -H Cookie: nelson.session=XXXXXXXXXXXXXXXXXXXXXXXXXXXX https://your.domain.com/v1/

The cookie can be obtained via two of methods. The typical user path will be via the OAuth workflow, authenticating with the backend Github endpoint (Github Enterprise or github.com). In this case, the browser automatically collects the token and stores it in the browser cache.

For programatic API access, the user needs to supply a Github personal access token to Nelson, which will then be exchanged for a Nelson security token.

POST /auth/github
Name Type Description
access_token string The personal access token obtained from the aforementioned Github instance

User Agents

Nelson restricts the User-Agent of callers, so every request sent to Nelson must supply a User-Agent. The server configuration details a set of banned user-agent strings, which is used as a mechanism to force clients to upgrade over time.

The following is an example.

User-Agent: NelsonCLI/1.0

If you provide an invalid or restricted User-Agent header, you will recieve a 403 Forbidden response.

Error Reporting

Nelson endpoints attempt to be good HTTP citizens and return appropriate 4xx status codes when the calling client is at fault, and only falls back to 5xx errors when the service itself was at fault.

Code Description
400 Bad Request Returned if a request body could not be parsed. For instance, if a POST request contains ill-formed JSON, the following would be returned.

{"message":"Could not parse JSON"}
415 Unsupported Media Type Returned if a request did not send an acceptable media type.Requests with a JSON body should send a Content-Type: application/json header.

{"message":"No media type specified in Content-Type header. Expected one of the following media ranges: application/json"}
422 Unprocessable Entity Returned if a request body could be parsed, but not decoded, due to a missing or mistyped field. The error returns a message and a cursor_history field from the JSON decoder. This response is for a request that's missing an `access_token`:

{
  "message": "Validation failed",
  "cursor_history": "CursorHistory([*.--\\(access_token)])"
}
500 Internal Server Error The service encountered an unexpected exception whilst processing a request. This was not expected, and information is reported to the server log, but not reported in the response for security reasons.

{"message":"An internal error occurred"}

Auditing

  1. List Events

List all the audit events, matching the query parameters (if supplied).

List Events

GET /v1/audit
Paramaters
Name Type Required Description
release_id int No The release ID that you specifically want to fetch audit events for
limit int No The maximum number of events to return in a given response
offset int No Where to start reading events from in the audit stream

Datacenters

  1. List Datacenters
  2. Inspect Datacenter
  3. Create Namespaces

List Datacenters

GET /v1/datacenters
Response
[
  {
    "namespaces": [
      {
        "id": 3,
        "name": "dev",
        "units_url": "https://nelson.domain.com/v1/units?dc=massachusetts&status=active,manual,deprecated",
        "deployments_url": "https://nelson.domain.com/v1/deployments?dc=massachusetts&ns=dev",
      }
    ],
    "datacenter_url": "https://nelson.domain.com/v1/datacenters/massachusetts",
    "name": "massachusetts"
  },
  {
    "namespaces": [
      {
        "id": 4,
        "name": "dev",
        "units_url": "https://nelson.domain.com/v1/units?dc=texas&status=active,manual,deprecated",
        "deployments_url": "https://nelson.domain.com/v1/deployments?dc=texas&ns=dev",
      }
    ],
    "datacenter_url": "https://nelson.domain.com/v1/datacenters/texas",
    "name": "texas"
  }
]

Inspect Datacenter

GET /v1/datacenters/:dcname
Response
{
  "namespaces": [
    {
      "id": 4,
      "name": "dev",
      "units_url": "https://nelson.domain.com/v1/units?dc=texas&status=active,manual,deprecated",
      "deployments_url": "https://nelson.domain.com/v1/deployments?dc=texas&ns=dev",
    }
  ],
  "datacenter_url": "https://nelson.domain.com/v1/datacenters/texas",
  "name": "texas"
}

Create Namespaces

POST /v1/datacenters/:dcname/namespaces
Input
Name Type Required Description
namespaces array[string] Yes A list of namespace labels
Example
{
  "namespaces": [
    "dev",
    "stage",
    "prod"
  ]
}
Response

Successful completion of this operation yields a 200 with empty response body.


Load Balancers

  1. List Load Balancers
  2. Inspect Load Balancers
  3. Create Load Balancer
  4. Destroy Load Balancer

List Load Balancers

Listing the available load balancers in a given namespace displays all the associated routes for that load balancers, and optionally (depending on the load balancer backend in use), the externally accessible URL.

GET /v1/loadbalancers
Response
[
  {
    "name": "foobar-lb--1--6i07ecdr",
    "routes": [
      {
        "backend_port_reference": "default",
        "backend_name": "foobar-http",
        "lb_port": 8444
      }
    ],
    "guid": "e2e09310d926",
    "deploy_time": 1483739055573,
    "address": "foobar-lb--1--6i07ecdr-1888907488.texas.elb.amazonaws.com",
    "datacenter": "texas",
    "namespace": "dev",
    "major_version": 1
  },
  ...
]

Inspect Load Balancer

GET /v1/loadbalancers/:guid
Response
{
  "name": "foobar-lb--1--6i07ecdr",
  "routes": [
    {
      "backend_port_reference": "default",
      "backend_name": "foobar-http",
      "lb_port": 8444
    }
  ],
  "guid": "e2e09310d926",
  "deploy_time": 1483739055573,
  "address": "foobar-lb--1--6i07ecdr-1888907488.texas.elb.amazonaws.com",
  "datacenter": "texas",
  "namespace": "dev",
  "major_version": 1
}

Create Load Balancer

POST /v1/loadbalancers
Request
{
  "name": "foobar-lb",
  "major_version": 1,
  "datacenter": "texas",
  "namespace": "dev"
}
Response

Successful completion of this operation yields a 200 with empty response body.

Destroy Load Balancer

DELETE /v1/loadbalancers/:guid
Response

Successful completion of this operation yields a 200 with empty response body.


Misc

  1. Sync User Profile
  2. Lint Manifest
  3. Lint Template
  4. List Cleanup Policies

Sync User Profile

POSTing to this URL will result in Nelson fetching the latest list of repositories from Github and updating this users permission set. Typically this API is used by the user-interface, but might need to be called when a new repository was created that the user wishes to enable deployment for.

POST /v1/profile/sync

Lint Manifest

The service can verify if a supplied manifest is valid or not (e.g. if the dependencies specified in the file dont exist, validation will fail).

POST /v1/lint
Input
Name Type Required Description
units array Yes List of informational objects about the available units
manifest string Yes Base64 encoded string representation of the .nelson.yml file
Example
{
  "units": [
    {
      "kind": "foo"
      "name": "foo-1.0"
    }
  ],
  "manifest": "XXXXXXXX"
}
Response

Lint Template

The service can verify if a supplied Consul template will render or not in the container. A template is uploaded with the name of its unit and a set of resources. The template is rendered with a vault token appropriate to the unit and resources, along with all the NELSON_ environment variables. If the template renders successfully, a successful status is returned. If the template can’t be rendered, the errors are displayed so the developer can fix them before deploying the unit.

POST /v1/validate-template
Input
Name Type Required Description
unit string Yes Name of the unit owning the template. Units will be validated in dev against the policy for this unit.
resources array Yes An array of resources accessed by the unit. Access will be granted to these resources in the policy.
template string Yes Base64 encoded string representation of the template to render
Example
{
  "unit": "howdy-http",
  "resources": ["s3"],
  "template": "SGVsbG8sIGNvbnN1bC10ZW1wbGF0ZQo="
}
Response

On success, a 204. The rendered template output is suppressed for security reasons.

On failure, a 400 with details and message:

{
    "details": "2017/02/06 20:25:47.495957 [INFO] consul-template v0.18.0 (5211c66)\n2017/02/06 20:25:47.495969 [INFO] (runner) creating new runner (dry: true, once: true)\n2017/02/06 20:25:47.496155 [INFO] (runner) creating watcher\n2017/02/06 20:25:47.500011 [INFO] (runner) starting\n2017/02/06 20:25:47.500083 [INFO] (runner) initiating run\nConsul Template returned errors:\n/consul-template/templates/nelson2613876961835551321.template: parse: template: :3: unterminated quoted string\n",
    "message": "template rendering failed"
}

List Cleanup Policies

List the available cleanup policies available in this instance of Nelson

GET /v1/cleanup-policies
Response
[
  {
    "description": "retains forever, or until someone manually decommissions",
    "policy": "retain-always"
  },
  ...
]

Repositories

  1. List Repositories
  2. List Repository Releases
  3. List All Releases
  4. Inspect Release
  5. Enable Repository
  6. Disable Repository

List Repositories

GET /v1/repos
GET /v1/repos?owner=tim
GET /v1/repos?state=active
Paramaters
Name Type Required Description
owner string No List only repositories with the specified owner
manifest string state List only repositories with the specified state; options are: active
Response
[
  {
    "repository": "foobar",
    "slug": "tim/foobar",
    "id": 6124,
    "hook": null,
    "owner": "tim",
    "access": "admin"
  },
  ...
]

List Repository Releases

GET /v1/repos/:org/:repo/releases
Response
[
  {
    "timestamp": "2016-06-28T20:01:40.091Z",
    "release_url": "https://nelson.example.com/v1/releases/990",
    "slug": "example/howdy",
    "github_html_url": "https://github.com/example/howdy/releases/tag/0.38.131",
    "version": "0.38.131",
    "id": 990,
    "deployments": [
      {
        "name": "howdy-http",
        "timestamp": "2016-06-28T20:02:26.810Z",
        "description": "provides the server component of the 'howdy' demo",
        "unit_id": 2,
        "deployment_url": "https://nelson.example.com/v1/deployments/2aa6e4c0295d",
        "hash": "i5hbv0bd",
        "id": 3,
        "status": "deploying",
        "kind": "service",
        "dependencies": []
      },
      {
        "name": "howdy-batch",
        "timestamp": "2016-06-28T20:01:40.370Z",
        "description": "example batch job\n",
        "unit_id": 3,
        "deployment_url": "https://nelson.example.com/v1/deployments/5555d15b54a4",
        "hash": "o6sbrepj",
        "id": 2,
        "status": "deploying",
        "kind": "job",
        "dependencies": []
      }
    ]
  },
  ...
]

List All Releases

GET /v1/releases

Inspect Release

GET /v1/releases/:id

Enable Repository

POST /v1/repos/:org/:repo/hook

Disable Repository

DELETE /v1/repos/:org/:repo/hook

Stacks

  1. List Stacks
  2. Inspect Stack
  3. Create Manually
  4. Redeploy
  5. Inspect Logs

List Stacks

GET /v1/deployments
Paramaters
Name Type Required Description
namespace string[,string,...] Yes Comma delimited set of namespace(s) you want to list deployments for
status string[,string,...] No Comma delimited set of status values (e.g. active,deploying)
dc string[,string,...] No Comma delimited set of datacenter names the result set include
unit string No Unit name
Response
[
  {
    "workflow": "magnetar",
    "guid": "b5280a26c026",
    "stack_name": "howdy-batch--0-38-155--aclq8j4j",
    "deployed_at": 1470784352740,
    "unit": "howdy-batch",
    "datacenter": "texas",
    "namespace": "dev",
    "plan": "dev-plan"
  },
  {
    "workflow": "magnetar",
    "guid": "072bdf0b99e8",
    "stack_name": "howdy-batch--0-38-155--5mrkdta9",
    "deployed_at": 1470784281154,
    "unit": "howdy-batch",
    "datacenter": "massachusetts",
    "namespace": "dev",
    "plan": "dev-plan"
  }
]

Inspect Stack

GET /v1/deployments/:guid
Response
{
  "workflow": "magnetar",
  "guid": "072bdf0b99e8",
  "statuses": [
    {
      "timestamp": "2016-08-09T23:12:07.267Z",
      "message": "howdy-batch deployed to massachusetts",
      "status": "active"
    },
    {
      "timestamp": "2016-08-09T23:12:06.727Z",
      "message": "instructing massachusetts's nomad to handle job container",
      "status": "deploying"
    },
    {
      "timestamp": "2016-08-09T23:12:06.063Z",
      "message": "writing alert definitions to massachusetts's consul",
      "status": "deploying"
    },
    {
      "timestamp": "2016-08-09T23:11:21.295Z",
      "message": "replicating docker.yourcompany.com/units/howdy-batch-0.38:0.38.155 to remote registry",
      "status": "deploying"
    },
    {
      "timestamp": "2016-08-09T23:11:21.243Z",
      "message": "",
      "status": "pending"
    }
  ],
  "stack_name": "howdy-batch--0-38-155--5mrkdta9",
  "deployed_at": 1470784281154,
  "unit": "howdy-batch",
  "expiration": 1470902303320,
  "dependencies": {
    "outbound": [],
    "inbound": []
  },
  "namespace": "dev",
  "plan": "dev-plan"
}

Create Manually

POST /v1/deployments
Input
Name Type Required Description
datacenter string Yes TBD
namespace string Yes TBD
service_type string Yes TBD
version string Yes TBD
hash string Yes TBD
description string Yes TBD
port int Yes TBD

Redeploy

Sometimes it is necessary to redeploy an exist stack. In this event, simply POST an empty body to the following API:

POST /v1/deployments/:guid/redeploy

Redeploy

Sometimes it is necessary to reverse and in progress traffic shift. In this event, simply POST an empty body to the following API:

POST /v1/deployments/:guid/trafficshift/reverse

Inspect Logs

Collect the entire log of workflow execution as Nelson processed it, for a given stack deployment. The workflow log allows the caller to see exactly what Nelson did on the users behalf, without requiring access to the Nelson server. The response includes every log line, and an offset that allows the caller to only receive a subset of the log output.

GET /v1/deployments/:guid/logs
Response
{
  "content": [
    "deployment initialized",
    "",
    "container extracted docker.yourcompany.com/units/heydiddlyho-http-0.33",
    ...
    "======> workflow completed <======",
    "decommissioning deployment heydiddlyho-http--0-33-69--56rk8kv0 in massachusetts"
  ],
  "offset": 0
}

Units

Units blah blah blah blah blah blah blah blah blah blah blah

  1. List Units
  2. Commit Units
  3. Deprecate Unit

List Units

GET /v1/units

Commit Units

Commits a unit@version combination to a target namespace. See Committing for more.

POST /v1/units/commit

{
  "unit": "unit-name",
  "version": "1.9.32",
  "target": "qa"
}

Deprecate Unit

POST /v1/units/deprecate

Webhooks

  1. Github Listener

Github Listener

POST /listener