构建你的服务

概述

本文档是将你已有的云服务变成tsuru服务的实战指南。为了创建一个服务,你需要为自己的服务实现配置API,当用户创建一个新的实例或者把应用绑定到实例上时,tsuru会通过HTTP协议调用。还需要创建一个YAML文档,作为服务的清单。我们提供一个命令行工具帮助你创建这个清单和管理你的服务。

创建你的service API

你可以用任意的编程语言和框架实现你的service API。本教程中我们采用Flask

验证

tsuru使用最基本的验证方式来验证服务,更多关于验证的内容请查看API工作流

使用Flask,你可以通过这个Flask代码段中的修饰符来管理最基本的验证。

准备条件

首先确保Python和pip已经安装:

  1. $ python --version
  2. Python 2.7.2
  3. $ pip
  4. Usage: pip COMMAND [OPTIONS]
  5. pip: error: You must give a command (use "pip help" to see a list of commands)

更多关于如何安装Python的内容请查看Python 下载文档,以及如何安装pip请查看pip安装指南。安装完python和pip后,就可以使用pip去安装Flask了:

  1. $ pip install flask

安装完Flask后,是时候创建名为api.py的文件并且添加创建最小的Flask应用的代码:

  1. from flask import Flask
  2. app = Flask(__name__)
  3. @app.route("/")
  4. def hello():
  5. return "Hello World!"
  6. if __name__ == "__main__":
  7. app.run()

为了运行这个应用可以这么做:

  1. $ python api.py
  2. * Running on http://127.0.0.1:5000/

打开浏览器访问http://127.0.0.1:5000/这个地址,会看到"Hello World!"这个消息。然后,你需要实现tsuru service API的资源,如:doc:tsuru service API workflow </services/api>所述。

列出可用计划

tsuru可以通过发送GET请求到/resources/plans获得可用的计划列表。让我们创建处理这个请求的视图:

  1. import json
  2. @app.route("/resources/plans", methods=["GET"])
  3. def plans():
  4. plans = [{"name": "small", "description": "small instance"},
  5. {"name": "medium", "description": "medium instance"},
  6. {"name": "big", "description": "big instance"},
  7. {"name": "giant", "description": "giant instance"}]
  8. return json.dumps(plans)

创建新的实例

对于新的实例,tsuru会发送POST请求到/resources加上必要参数去创建一个实例。如果服务实例创建成功,你的API应该返回201状态码。让我们为这个动作创建视图:

  1. from flask import request
  2. @app.route("/resources", methods=["POST"])
  3. def add_instance():
  4. name = request.form.get("name")
  5. plan = request.form.get("plan")
  6. team = request.form.get("team")
  7. # use the given parameters to create the instance
  8. return "", 201

把实例绑定到应用

在绑定动作中,tsuru通过发送POST请求加上必要参数到/resources/<service-instance-name>/bind-app来调用服务去把应用绑定到服务实例。如果绑定操作成功,API返回201状态码,同时在JSON消息体中会包含应用应当设置的环境变量。让我们创建一个返回伪造的名为"SOMEVAR"变量的视图,这个变量可以被插入到应用的环境中:

  1. import json
  2. from flask import request
  3. @app.route("/resources/<name>/bind-app", methods=["POST"])
  4. def bind_app(name):
  5. app_host = request.form.get("app-host")
  6. # use name and app_host to bind the service instance and the #
  7. application
  8. envs = {"SOMEVAR": "somevalue"}
  9. return json.dumps(envs), 201

从应用解绑定实例

In the unbind action, tsuru issues a DELETE request to the URL/resources/<service-instance-name>/bind-app.

If the unbind operation succeeds, the API should return 200 as status code.Let's create the view for this action:

  1. @app.route("/resources/<name>/bind-app", methods=["DELETE"])
  2. def unbind_app(name):
  3. app_host = request.form.get("app-host")
  4. # use name and app-host to remove the bind
  5. return "", 200

白名单单元

绑定和解绑定服务实例到应用时,tsuru同时会提供关于访问服务实例的单元的信息,因此service API任何需要的白名单(比如,在网络交换机写入ACL规则或者在防火墙授权访问)。

tsuru会发送POST和DELETE请求,加上应用的主机以及单元,到路由到/resources/<name>/bind,所以API可以处理任何的访问控制:

  1. @app.route("/resources/<name>/bind", methods=["POST", "DELETE"])
  2. def access_control(name):
  3. app_host = request.form.get("app-host")
  4. unit_host = request.form.get("unit-host")
  5. # use unit-host and app-host, according to the access control tool, and
  6. # the request method.
  7. return "", 201

删除实例

tsuru会通过发送DELETE请求到/resources/<service_name>来执行删除操作。如果服务实例成功删除,API应担返回201状态码。让我们为这个动作创建视图:

  1. @app.route("/resources/<name>", methods=["DELETE"])
  2. def remove_instance(name):
  3. # remove the instance named "name"
  4. return "", 200

检查实例的状态

tsuru通过发送GET请求到/resources/<service_name>/status来检查一个实例的状态。如果实例完好,这个链接应当返回204。让我们为这个动作创建视图:

  1. @app.route("/resources/<name>/status", methods=["GET"])
  2. def status(name):
  3. # check the status of the instance named "name"
  4. return "", 204

我们用Flask开发的“伪API”的最终代码如下:

  1. import json
  2. from flask import Flask, request
  3. app = Flask(__name__)
  4. @app.route("/resources/plans", methods=["GET"])
  5. def plans():
  6. plans = [{"name": "small", "description": "small instance"},
  7. {"name": "medium", "description": "medium instance"},
  8. {"name": "big", "description": "big instance"},
  9. {"name": "giant", "description": "giant instance"}]
  10. return json.dumps(plans)
  11. @app.route("/resources", methods=["POST"])
  12. def add_instance():
  13. name = request.form.get("name")
  14. plan = request.form.get("plan")
  15. team = request.form.get("team")
  16. # use the given parameters to create the instance
  17. return "", 201
  18. @app.route("/resources/<name>/bind-app", methods=["POST"])
  19. def bind_app(name):
  20. app_host = request.form.get("app-host")
  21. # use name and app_host to bind the service instance and the #
  22. application
  23. envs = {"SOMEVAR": "somevalue"}
  24. return json.dumps(envs), 201
  25. @app.route("/resources/<name>/bind-app", methods=["DELETE"])
  26. def unbind_app(name):
  27. app_host = request.form.get("app-host")
  28. # use name and app-host to remove the bind
  29. return "", 200
  30. @app.route("/resources/<name>", methods=["DELETE"])
  31. def remove_instance(name):
  32. # remove the instance named "name"
  33. return "", 200
  34. @app.route("/resources/<name>/bind", methods=["POST", "DELETE"])
  35. def access_control(name):
  36. app_host = request.form.get("app-host")
  37. unit_host = request.form.get("unit-host")
  38. # use unit-host and app-host, according to the access control tool, and
  39. # the request method.
  40. return "", 201
  41. @app.route("/resources/<name>/status", methods=["GET"])
  42. def status(name):
  43. # check the status of the instance named "name"
  44. return "", 204
  45. if __name__ == "__main__":
  46. app.run()

.. _service_manifest:

创建一个服务清单

可以使用crane去创建一个清单的模板:

  1. $ crane template

这会在当前路径下创建包含如下内容的manifest.yaml文件:

  1. id: servicename
  2. password: abc123
  3. endpoint:
  4. production: production-endpoint.com

manifest.yaml是crane用来定义ID,密码和服务的产品环境端点的文件。在清单中修改这些信息,然后提交服务

  1. id: servicename
  2. username: username_to_auth
  3. password: 1CWpoX2Zr46Jhc7u
  4. endpoint:
  5. production: production-endpoint.com
  6. test: test-endpoint.com:8080

submit your service: Submiting your service API

提交你的service API

可以运行下面的命令来提交service API:

  1. $ crane create manifest.yaml

更多内容,请查看:doc:service API workflow </services/api> and the:doc:crane usage guide </services/usage>.

原文: http://doc.oschina.net/tsuru-paas?t=52835