Deploy API

This is the API specification and some examples for the RESTful HTTP Deploy API that can be used to deploy applications in a Vespa. The API supports multiple tenants and applications. Each tenant may have multiple applications deployed in different environments and different regions, all of which can be deployed using this API.

For a tenant, upload, prepare and activate applications. The response format is JSON. Examples are found in the use-cases.

The current API version is 2. The API port is 19071 - use vespa-model-inspect service configserver to find config server hosts. Example: http://myconfigserver.mydomain.com:19071/application/v2/tenant/mytenant/session. All operations are synchronous across the cluster of config servers, meaning that requests return after the operations complete on all servers.

Note: An application file path in a request URL or parameter refers to a relative path in the application package. A path ending with '/' refers to a directory.

Entities:

Tenant The tenant used in this API is created using the tenant REST API. The tenant name is required for all operations. Tenant names may only contain word characters and dash: [a-zA-Z_0-9-].
Application The application is the name of the application taken from the application package or given during prepare. Application names may only contain word characters: [a-zA-Z_0-9].
Environment Multiple environments are not yet supported. Default is used.
Region Multiple regions are not yet supported. Default is used.
Instance Multiple instances are not yet supported. Default is used.
Session-id The session id used in this API is generated by the server and is required for all operations after creating a session. The session id is valid as long as it is one of the last 10 session ids created.
Path

When deploying to Vespa, use the vespa-deploy tool which wraps the Deploy API.

POST /application/v2/tenant/[tenant name]/session

Creates a new session with the application package that is included in the request.

Parameters
NameDefaultDescription
from N/A Should only be used when you want to create a session based on an active application. Valid values are a url to an active application. A new session will be created based on the corresponding application.
Request body
RequiredContentNote
Yes, unless from parameter is used A compressed application package (with gzip or zip compression) It is required to set the Content-Type HTTP header to application/x-gzip or application/zip, unless the from parameter is used.
Response A response includes:
  • A session id to the application that was created.
  • A prepared URL for preparing the application.

Examples (both requests return same response):
POST /application/v2/tenant/mytenant/session
POST /application/v2/tenant/mytenant/session?from=http://myconfigserver.mydomain.com:19071/application/v2/tenant/mytenant/application/myapp/environment/default/region/default/instance/default

{
    "tenant": "mytenant",
    "session-id": "1",
    "prepared": "http://myconfigserver.mydomain.com:19071/application/v2/tenant/mytenant/session/session-id/prepared/",
    "content": "http://myconfigserver.mydomain.com:19071/application/v2/tenant/mytenant/session/session-id/content/",
    "message": "Session 1 for tenant 'mytenant' created."
}

PUT /application/v2/tenant/[tenant name]/session/[session id]/content/[path]

Writes the content to the given path, or creates a directory if the path ends with '/'.

Parameters None
Request body
  • If path is a directory, none.
  • If path is a file, the contents of the file.
Response None
  • Any errors or warnings from writing the file/creating the directory.

GET /application/v2/tenant/[tenant name]/session/[session id]/content/[path]

Returns the content of the file at this path, or lists files and directories if path ends with '/'.

Parameters
NameDefaultDescription
recursive false If true, directory content will be listed recursively.
return content
  • If set to content and path refers to a file, the content will be returned.
  • If set to content and path refers to a directory, the files and subdirectories in the directory will be listed.
  • If set to status and path refers to a file, the file status and hash will be returned.
  • If set to status and path refers to a directory, a list of file/subdirectory statuses and hashes will be returned.
Request body None.
Response
  • If path is a directory: a JSON array of URLs to the files and subdirectories of that directory.
  • If path is a file: the contents of the file.
  • If status parameter is set, the status and hash will be returned.
Examples: GET /application/v2/tenant/mytenant/session/3/content/
[
    "http://myconfigserver.mydomain.com:19071/application/v2/tenant/mytenant/session/3/content/hosts.xml",
    "http://myconfigserver.mydomain.com:19071/application/v2/tenant/mytenant/session/3/content/services.xml",
    "http://myconfigserver.mydomain.com:19071/application/v2/tenant/mytenant/session/3/content/searchdefinitions/"
]
GET /application/v2/tenant/mytenant/session/3/content/?recursive=true
[
    "http://myconfigserver.mydomain.com:19071/application/v2/tenant/mytenant/session/3/content/hosts.xml",
    "http://myconfigserver.mydomain.com:19071/application/v2/tenant/mytenant/session/3/content/services.xml",
    "http://myconfigserver.mydomain.com:19071/application/v2/tenant/mytenant/session/3/content/searchdefinitions/",
    "http://myconfigserver.mydomain.com:19071/application/v2/tenant/mytenant/session/3/content/searchdefinitions/music.sd",
    "http://myconfigserver.mydomain.com:19071/application/v2/tenant/mytenant/session/3/content/searchdefinitions/video.sd"
]
GET /application/v2/tenant/mytenant/session/3/content/hosts.xml
<?xml version="1.0" encoding="utf-8" ?>
<hosts>
  <host name="myhost.mydomain.com">
    <alias>vespa1</alias>
  </host>
  <host name="myhost.mydomain.com">
    <alias>vespa2</alias>
  </host>
</hosts>
GET /application/v2/tenant/mytenant/session/3/content/hosts.xml?return=status
{
    "name": "http://myconfigserver.mydomain.com:19071/application/v2/tenant/mytenant/session/3/content/hosts.xml",
    "status": "new",
    "md5": "03d7cff861fcc2d88db70b7857d4d452"
}
GET /application/v2/tenant/mytenant/session/3/content/searchdefinitions/?return=status
[
    {
        "name": "http://myconfigserver.mydomain.com:19071/application/v2/tenant/mytenant/session/3/content/searchdefinitions/music.sd",
        "status": "new",
        "md5": "03d7cff861fcc2d88db70b7857d4d452"
    },
    {
        "name": "http://myconfigserver.mydomain.com:19071/application/v2/tenant/mytenant/session/3/content/searchdefinitions/video.sd",
        "status": "changed",
        "md5": "03d7cff861fcc2d88db70b7857d4d452"
    },
    {
        "name": "http://myconfigserver.mydomain.com:19071/application/v2/tenant/mytenant/session/3/content/searchdefinitions/book.sd",
        "status": "deleted",
        "md5": "03d7cff861fcc2d88db70b7857d4d452"
    }
]

DELETE /application/v2/tenant/[tenant name]/session/[session id]/content/[path]

Deletes the resource at the given path.

Parameters None
Request body None
Response Any errors or warnings from deleting the resource.

PUT /application/v2/tenant/[tenant name]/session/[session id]/prepared

Prepares an application with the session id given.

Parameters
ParameterDefaultDescription
applicationName N/A Name of the application to be deployed
environment default Environment where application should be deployed
region default Region where application should be deployed
instance default Name of application instance
debug false If true, include stack trace in response if prepare fails.
timeout 300 seconds Timeout in seconds to wait for session to be prepared.
Request body None
Response Returns a session id and a link to activate the session.
  • Log with any errors or warnings from preparing the application.
  • An activate URL for activating the application with this session id, if there were no errors.
  • A list of actions (possibly empty) that must be performed in order to apply some config changes between the current active application and this next prepared application. These actions are organized into two categories; restart and refeed:
    • Restart actions are done after the application has been activated and are handled by restarting all listed services. Please see search definitions for more information.
    • Refeed actions require several steps to handle. Please see search definitions for more information.
Example: PUT /application/v2/tenant/mytenant/session/3/prepared
{
    "tenant": "mytenant",
    "activate": "http://myconfigserver.mydomain.com:19071/application/v2/tenant/mytenant/session/3/active",
    "message": "Session 3 for tenant 'mytenant' prepared.",
    "log": [
           { "level": "WARNING",
             "message": "Warning message 1",
             "time": 1430134091319
           },
           { "level": "WARNING",
             "message": "Warning message 2",
             "time": 1430134091320
           }
        ],
    "configChangeActions": {
        "restart": [ {
            "clusterName": "mycluster",
            "clusterType": "search",
            "serviceType": "searchnode",
            "messages": [ "Document type 'test': Field 'f1' changed: add attribute aspect" ],
            "services": [ {
                "serviceName": "searchnode",
                "serviceType": "searchnode",
                "configId": "mycluster/search/cluster.mycluster/0",
                "hostName": "myhost.mydomain.com"
            } ]
        } ],
        "refeed": [ {
            "documentType": "test",
            "clusterName": "mycluster",
            "messages": [ "Document type 'test': Field 'f1' changed: add index aspect" ],
            "services": [ {
                "serviceName": "searchnode",
                "serviceType": "searchnode",
                "configId": "mycluster/search/cluster.mycluster/0",
                "hostName": "myhost.mydomain.com"
            } ]
        } ]
    }
}

GET /application/v2/tenant/mytenant/session/[session id]/prepared

Returns the state of a prepared session. The response is the same as a successful prepare operation (above), however the configChangeActions element will be empty.

PUT /application/v2/tenant/[tenant name]/session/[session id]/active

Activates an application with the session id given. The session id must be for a prepared session. The operation will make sure the session is activated on all config servers, if more than one is configured.

Parameters
ParameterDefaultDescription
timeout 60 seconds Timeout in seconds to wait for session to be activated (when several config servers are used, they might need to sync before activate can be done).
Request body None
Response Returns a session id, a message and a URL to the activated application.
Example: PUT /application/v2/tenant/mytenant/session/3/active
{
    "tenant": "mytenant",
    "message": "Session 3 for tenant 'mytenant' activated.",
    "url": "http://myconfigserver.mydomain.com:19071/application/v2/tenant/mytenant/application/myapp/environment/default/region/default/instance/default"
}

GET /application/v2/tenant/[tenant name]/application/

Returns a list of the currently active applications for the given tenant

Parameters None
Request body None
Response Returns a list of applications
  • Array of active applications
Example: GET /application/v2/tenant/mytenant/application/
{
    ["http://myconfigserver.mydomain.com:19071/application/v2/tenant/default/application/default/environment/default/region/default/instance/default"]
}

GET /application/v2/tenant/[tenant name]/application/[application name]

Gets info about the application.

Parameters None
Request body None
Response Returns information about the application specified.
  • config generation
Example: GET /application/v2/tenant/mytenant/application/foo
{
    "generation": 2
}

DELETE /application/v2/tenant/[tenant name]/application/[application name]

Deletes an active application

Parameters None
Request body None
Response Returns a message stating if the operation was successful or not
Example: DELETE /application/v2/tenant/mytenant/application/foo
{
    "message": "Application 'foo' was deleted"
}

GET /application/v2/host/[hostname]

Gets information about which tenant and application a hostname is used by.

Parameters None
Request body None
Response Returns a message with tenant and application details.
Example: GET /application/v2/host/myhost.mydomain.com
{
    "tenant":"mytenant"
    "application":"foo"
    "environment":"test"
    "region":"Europe"
    "instance":"1"
}

Error Handling

Errors are returned using standard HTTP status codes. Any additional info is included in the body of the return call, JSON-formatted. The general format for an error response is:

{
    "error-code": "ERROR_CODE",
    "message": "An error message"
}
HTTP status codeError codeDescription
400BAD_REQUEST Bad request. Client error. The error message should indicate the cause.
400INVALID_APPLICATION_PACKAGE There is an error in the application package. The error message should indicate the cause.
400OUT_OF_CAPACITY Not enough nodes available for the request to be fulfilled.
401 Not authorized. The error message should indicate the cause.
404NOT_FOUND Not found. E.g. when using a session id that doesn't exist.
405METHOD_NOT_ALLOWED Method not implemented. E.g. using GET where only POST or PUT is allowed.
409CONFLICT Conflict, returned when activating an application fails due to a conflict with other changes to the same application (in another session). Client should retry.
500INTERNAL_SERVER_ERROR Internal server error. Generic error. The error message should indicate the cause.

Request log

The log files for calls to the Deploy API are named configserver.<timestamp> and are found in $VESPA_HOME/logs/vespa/configserver/access.log. The format is the same as for the container access log - example:

10.76.246.20 - - [31/Jan/2013:22:05:45 +0000] "PUT /application/v2/tenant/mytenant/session/1/active HTTP/1.1" 200 1238 "" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:18.0) Gecko/20100101 Firefox/18.0" 1359669945.93 1 0.0 1

Use Cases

It is assumed that the tenant mytenant is already created in these use cases, and the application package is in app.

Create, prepare and activate an application

Create a session with the application package:

$ tar -C app -cf - . | gzip | curl -s --header "Content-Type:
application/x-gzip" --data-binary @- \
"http://host:19071/application/v2/tenant/mytenant/session"
Prepare the application with the URL in the prepared link from the response:
$ curl -s -X PUT "http://host:19071/application/v2/tenant/mytenant/session/1/prepared?applicationName=fooapp"
Activate the application with the URL in the activate link from the response:
$ curl -s -X PUT "http://host:19071/application/v2/tenant/mytenant/session/1/active"

Modify the application package

Dump services.xml from session 1:

$ curl -s -X GET "http://host:19071/application/v2/tenant/mytenant/session/1/content/services.xml"
<?xml version="1.0" encoding="utf-8" ?>
<services version="1.0">
  <admin version="2.0">
    <config name="config.logd">
      <logserver>
        <port>12345</port>
      </logserver>
    </config>
    <adminserver hostalias="node1" />
  </admin>
</services>
Session 1 is activated and cannot be changed - create a new session based on the active session:
$ curl -s -X POST "http://host:19071/application/v2/tenant/mytenant/session?from=http://host:19071/application/v2/tenant/mytenant/application/fooapp/environment/default/region/default/instance/default"

Modify port number in services.xml, deploy the change:

$ curl -s -X PUT --data-binary @app/services.xml \
"http://host:19071/application/v2/tenant/mytenant/session/2/content/services.xml"
Get services.xml from session 2 to validate:
$ curl -s -X GET "http://host:19071/application/v2/tenant/mytenant/session/2/content/services.xml"
<?xml version="1.0" encoding="utf-8" ?>
<services version="1.0">
  <admin version="2.0">
    <config name="config.logd">
      <logserver>
        <port>12346</port>
      </logserver>
    </config>
    <adminserver hostalias="node1" />
  </admin>
</services>
To add the file files/test1.txt, first create the directory, then add the file:
$ curl -s -X PUT "http://host:19071/application/v2/tenant/mytenant/session/2/content/files/"
$ curl -s -X PUT --data-binary @app/files/test1.txt "http://host:19071/application/v2/tenant/mytenant/session/2/content/files/test1.txt"
Prepare and activate the session:
$ curl -s -X PUT "http://host:19071/application/v2/tenant/mytenant/session/2/prepared?applicationName=fooapp"
$ curl -s -X PUT "http://host:19071/application/v2/tenant/mytenant/session/2/active"

Rollback

Say that you find out that the changes done in the latest application did not work out as expected and you want to rollback to a previous state known to work. This is achieved by having multiple instance of an application. To rollback, simply create a new session passing the previous instance as the from argument.