• 构建你的服务
  • 概述
  • 创建你的service API
  • 验证
    • 准备条件
    • 列出可用计划
    • 创建新的实例
    • 把实例绑定到应用
    • 从应用解绑定实例
    • 白名单单元
    • 删除实例
    • 检查实例的状态
  • 创建一个服务清单
  • 提交你的service API

    构建你的服务

    概述

    本文档是将你已有的云服务变成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