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.
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 programmatic 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 receive 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.
|
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.
|
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 :
|
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.
|
Auditing
List all the audit events, matching the query parameters (if supplied).
List Events
GET /v1/audit
Parameters
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
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
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
Sync User Profile
POST
ing to this URL will result in Nelson fetching the latest list of repositories from GitHub and updating this user’s 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 don’t 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
- List Repositories
- List Repository Releases
- List All Releases
- Inspect Release
- Enable Repository
- Disable Repository
List Repositories
GET /v1/repos
GET /v1/repos?owner=tim
GET /v1/repos?state=active
Parameters
Name | Type | Required | Description |
owner |
string |
No | List only repositories with the specified owner. |
state |
string |
No | 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
List Stacks
GET /v1/deployments
Parameters
Name | Type | Required | Description |
namespace |
string[,string,...] |
Yes | Comma delimited set of namespaces 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 existing stack. In this event, simply POST
an empty body to the following API:
POST /v1/deployments/:guid/redeploy
Reverse Traffic Shift
Sometimes it is necessary to reverse an 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 user’s 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
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
GitHub Listener
POST /listener