Building your service¶
This guide shows how to turn your existing cloud service into a tsuru service.
Overview¶
To create a service you need to:
- Implement a provisioning API that tsuru will call via HTTP
- Create a YAML manifest file describing your service
Creating your service API¶
You can use any programming language or framework. This tutorial uses Flask.
Authentication¶
tsuru uses basic authentication. See the service API workflow for details.
For Flask, you can use the decorator from this Flask snippet.
Prerequisites¶
$ pip install flask
Minimal Flask application¶
Create api.py:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
Run with:
$ python api.py
* Running on http://127.0.0.1:5000/
Listing available plans¶
Endpoint: GET /resources/plans
import json
@app.route("/resources/plans", methods=["GET"])
def plans():
plans = [
{"name": "small", "description": "small instance"},
{"name": "medium", "description": "medium instance"},
{"name": "big", "description": "big instance"},
{"name": "giant", "description": "giant instance"}
]
return json.dumps(plans)
Creating new instances¶
Endpoint: POST /resources
from flask import request
@app.route("/resources", methods=["POST"])
def add_instance():
name = request.form.get("name")
plan = request.form.get("plan")
team = request.form.get("team")
# use the given parameters to create the instance
return "", 201
Updating service instances¶
Endpoint: PUT /resources/<name> (optional)
@app.route("/resources/<name>", methods=["PUT"])
def update_instance(name):
description = request.form.get("description")
tags = request.form.get("tag")
team = request.form.get("team")
plan = request.form.get("plan")
# use the given parameters to update the instance
return "", 200
Binding instances to apps¶
Endpoint: POST /resources/<name>/bind-app
import json
from flask import request
@app.route("/resources/<name>/bind-app", methods=["POST"])
def bind_app(name):
app_host = request.form.get("app-host")
# use name and app_host to bind the service instance and the application
envs = {"SOMEVAR": "somevalue"}
return json.dumps(envs), 201
Unbinding instances from apps¶
Endpoint: DELETE /resources/<name>/bind-app
@app.route("/resources/<name>/bind-app", methods=["DELETE"])
def unbind_app(name):
app_host = request.form.get("app-host")
# use name and app-host to remove the bind
return "", 200
Whitelisting units¶
Endpoint: POST/DELETE /resources/<name>/bind
Handle access control when units are added or removed:
@app.route("/resources/<name>/bind", methods=["POST", "DELETE"])
def access_control(name):
app_host = request.form.get("app-host")
unit_host = request.form.get("unit-host")
# use unit-host and app-host for access control
return "", 201
Removing instances¶
Endpoint: DELETE /resources/<name>
@app.route("/resources/<name>", methods=["DELETE"])
def remove_instance(name):
# remove the instance named "name"
return "", 200
Checking the status of an instance¶
Endpoint: GET /resources/<name>/status
@app.route("/resources/<name>/status", methods=["GET"])
def status(name):
# check the status of the instance named "name"
return "", 204
Complete example¶
import json
from flask import Flask, request
app = Flask(__name__)
@app.route("/resources/plans", methods=["GET"])
def plans():
plans = [
{"name": "small", "description": "small instance"},
{"name": "medium", "description": "medium instance"},
{"name": "big", "description": "big instance"},
{"name": "giant", "description": "giant instance"}
]
return json.dumps(plans)
@app.route("/resources", methods=["POST"])
def add_instance():
name = request.form.get("name")
plan = request.form.get("plan")
team = request.form.get("team")
return "", 201
@app.route("/resources/<name>/bind-app", methods=["POST"])
def bind_app(name):
app_host = request.form.get("app-host")
envs = {"SOMEVAR": "somevalue"}
return json.dumps(envs), 201
@app.route("/resources/<name>/bind-app", methods=["DELETE"])
def unbind_app(name):
app_host = request.form.get("app-host")
return "", 200
@app.route("/resources/<name>", methods=["DELETE"])
def remove_instance(name):
return "", 200
@app.route("/resources/<name>/bind", methods=["POST", "DELETE"])
def access_control(name):
app_host = request.form.get("app-host")
unit_host = request.form.get("unit-host")
return "", 201
@app.route("/resources/<name>/status", methods=["GET"])
def status(name):
return "", 204
if __name__ == "__main__":
app.run()
Creating a service manifest¶
Generate a template with:
$ tsuru service-template
This creates manifest.yaml:
id: servicename
password: abc123
endpoint:
production: production-endpoint.com
Update with your service details:
id: servicename
username: username_to_auth
password: 1CWpoX2Zr46Jhc7u
endpoint:
production: production-endpoint.com
test: test-endpoint.com:8080
Submitting your service API¶
Submit your service with:
$ tsuru service-create manifest.yaml
For more details, see the service API workflow and the tsuru-client service management reference.