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 |
|
||||||
---|---|---|---|---|---|---|---|
Request body |
|
||||||
Response |
A response includes:
|
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 |
|
Response |
None
|
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 |
|
|||||||||
---|---|---|---|---|---|---|---|---|---|---|
Request body | None. | |||||||||
Response |
|
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 |
|
|||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Request body | None | |||||||||||||||||||||
Response |
Returns a session id and a link to activate the session.
|
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 |
|
||||||
---|---|---|---|---|---|---|---|
Request body | None | ||||||
Response |
Returns a session id, a message and a URL to the activated application.
|
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
|
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.
|
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 |
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. |
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 code | Error code | Description |
---|---|---|
400 | BAD_REQUEST | Bad request. Client error. The error message should indicate the cause. |
400 | INVALID_APPLICATION_PACKAGE | There is an error in the application package. The error message should indicate the cause. |
400 | OUT_OF_CAPACITY | Not enough nodes available for the request to be fulfilled. |
401 | Not authorized. The error message should indicate the cause. | |
404 | NOT_FOUND | Not found. E.g. when using a session id that doesn't exist. |
405 | METHOD_NOT_ALLOWED | Method not implemented. E.g. using GET where only POST or PUT is allowed. |
409 | CONFLICT | Conflict, returned when activating an application fails due to a conflict with other changes to the same application (in another session). Client should retry. |
500 | INTERNAL_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.