From 70bafcc0169e6c5d2f105d762dbec001a0ce7e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20Mass=C3=A9?= Date: Thu, 21 Jun 2018 16:49:52 +0200 Subject: [PATCH] Add documentation --- README.md | 348 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 347 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 90fc1a2..553d345 100644 --- a/README.md +++ b/README.md @@ -115,9 +115,355 @@ ansible-galaxy install nmasse-itix.threescale-cicd ansible-playbook -i inventory deploy-api.yaml ``` +## Inventory + +Three kinds of systems can be declared in the inventory and used with this role: + +- 3scale Admin Portal +- Red Hat SSO +- APIcast instances + +The 3scale Admin Portal that will be provisionned is the one that is referenced +in the playbook that includes this role. For instance, in the previous example, +the provisioned 3scale Admin Portal will be `-admin.3scale.net` because +the main playbook specifies `hosts: threescale` and the `threescale` group +contains only one host: `-admin.3scale.net`. + +If you specifies multiple hosts for the 3scale Admin Portal, they all will be +provisionned with the exact same configuration (useful for multi-site deployments). + +To connect to the 3scale Admin Portal, you will have to provide an Access Token +having read/write privileges on the Account Management API. You can provide this +token at the host level, group level or globally with the +`threescale_cicd_access_token` variable. + +At the host level, it is defined as such: + +```ini +[threescale] +tenant1-admin.3scale.net threescale_cicd_access_token=123...456 +tenant2-admin.3scale.net threescale_cicd_access_token=789...012 +``` + +At the group level, you can define it as such: + +```ini +[threescale:vars] +threescale_cicd_access_token=123...456 + +[threescale] +tenant1-admin.3scale.net +tenant2-admin.3scale.net +``` + +And you can also define it globally, for instance as playbook vars: + +```yaml +- hosts: threescale + vars: + threescale_cicd_access_token: 123...456 +``` + +The Red Hat SSO instance (currently there can only be one), is taken by convention +from the `sso` group. The `client_id`/`client_secret` used by Zync to synchronize +the 3scale applications are fetched from the inventory variables, as well as the +scheme (`http`/`https`) and the target realm. + +Example: + +```ini +[sso] +sso.acme.corp client_id=3scale client_secret=123 realm=acme scheme=https +``` + +Otherwise, if you don't want to follow this convention, you can use the +corresponding extra variable: `threescale_cicd_sso_issuer_endpoint`. For +the previous example, the variable would be: + +```ini +threescale_cicd_sso_issuer_endpoint=https://3scale:123@sso.acme.corp/auth/realms/acme +``` + +If both the `sso` group and the `threescale_cicd_sso_issuer_endpoint` extra +variable are specified, the extra variable has precedence over the inventory. + +The APIcast instances are fetched from the `apicast-sandbox` and `apicast-production` +groups. There can only be one hostname in each group and it is the public hostname +of each APIcast cluster (not each individual member). + +Example: + +```ini +[apicast-sandbox] +api-test.acme.corp scheme=http + +[apicast-production] +api.acme.corp scheme=https +``` + +If you do not want to follow this convention, you can use the corresponding extra +variables: + +- `threescale_cicd_apicast_sandbox_endpoint` +- `threescale_cicd_apicast_production_endpoint` + +For the previous example, the variables would be: + +```ini +threescale_cicd_apicast_sandbox_endpoint=http://api-test.acme.corp +threescale_cicd_apicast_production_endpoint=https://api.acme.corp +``` + +If both the `apicast-*` groups and the `threescale_cicd_apicast_*_endpoint` +extra variables are specified, the extra variables have precedence over the +inventory. + +## OpenAPI Specification fields + +This role currently supports only OpenAPI Specifications v2.0 (aka. Swagger 2.0). + +The following extended fields of the OpenAPI Specifications can be used: + +- `x-threescale-system-name`, in the `info` structure is used as basis + to construct the system_name for the configuration objects in 3scale. +- `x-threescale-smoketests-operation` in a method definition is used to flag + one operation as usable for smoke tests. The method needs to be idempotent, + read-only and without parameters. If no method is flagged as smoke tests, + the smoke tests are just skipped. + +If the extended fields cannot be used (if for instance you do not want to alter +your API Contract), you can use the corresponding extra variable: + +- `threescale_cicd_api_system_name` +- `threescale_cicd_openapi_smoketest_operation` + +Here is an example of an OpenAPI Specification using those extended fields: + +```yaml +swagger: '2.0' +info: + x-threescale-system-name: 'echo-api' + title: 'Echo API' + version: '1.0' +host: 'echo-api.3scale.net' +paths: + /: + get: + operationId: Echo + summary: 'Get an echo' + description: 'Get an echo from the server' + x-threescale-smoketests-operation: true + responses: + 200: + description: 'An Echo from the server' +security: +- apikey: [] +securityDefinitions: + apikey: + name: api-key + in: header + type: apiKey +``` + +Namely, `echo-api` would be used as a basis to construct the system_name +of the 3scale service definition and a `GET` on `/` would be used as +smoketests. + +To achieve the same effect without the OpenAPI extended fields, you would have +to pass the following extra variables: + +```ini +threescale_cicd_api_system_name=echo-api +threescale_cicd_openapi_smoketest_operation=Echo # The operationId of the "GET /" method +``` + +The following standard fields of the OpenAPI Specifications are used. + +In the `info` section: + +- `title` is used as the display name of the 3scale service definition. +- `version` is used for proper versioning and follows the [semver scheme](https://semver.org/). +- `host` is the DNS name of the existing API backend to expose. + +For each defined method: + +- the `operationId` fields is used as the system_name for the corresponding + methods/metrics. +- the `summary` and `description` fields are used as name and description + for the methods/metrics. +- the `security` and `securityDefinitions` are used to determine the security + scheme of the exposed API. + +To have a one-to-one mapping between the OpenAPI Specifications and the 3scale features, +some restrictions are applied on the `security`/`securityDefinitions` structures. +Namely, there must be one and exactly one security requirement in the `security` +structure. The security requirement needs to be applied globally (not on a per +method basis). + +The security definitions also have restrictions: you can choose between only two +security schemes: + +- OAuth / OpenID Connect +- API Key + +The App Key Pair scheme proposed by 3scale has no corresponding definition in the +OpenAPI Specifications and is currently not supported by this role. + +So to be more concrete, to secure your API with API Key, use this excerpt in your +OpenAPI Specification file: + +```yaml +securityDefinitions: + apikey: + name: api-key + in: header + type: apiKey +security: +- apikey: [] +``` + +You can of course, choose the HTTP header name that will be used to send the +API Key by changing the `name` field (in this example: `api-key`). + +And to secure it with OpenID Connect use this excerpt in your OpenAPI +Specification file: + +```yaml +securityDefinitions: + oidc: + type: oauth2 + flow: accessCode + scopes: + openid: Get an OpenID Connect token +security: +- oidc: + - openid +``` + +You can of course use the OpenID Connect flow of your choice: + +- `implicit` +- `password` +- `application` +- `accessCode` + ## Role Variables -TODO +This section presents extensively all the variables used by this role. As a +foreword, this role adopt a convention-over-configuration scheme. This means +that sensible defaults and opinionated naming schemes are provided out-of-the-box. + +### `threescale_cicd_openapi_file` + +Specifies the OpenAPI Specification file to read. + +- Syntax: Complete path to the OpenAPI Specification, on the local filesystem. + Avoid relative paths, prefer absolute ones. If you need to read a file that is + relative to your playbook, use the `{{ playbook_dir }}` placeholder. +- Required: yes +- Example: `/tmp/openapi.yaml` + +### `threescale_cicd_openapi_file_format` + +Specifies the format (JSON or YAML) of the OpenAPI Specification file to read. + +- Syntax: `JSON` or `YAML` +- Required: yes +- Example: `YAML` + +### `threescale_cicd_api_system_name` + +Defines the system_name of the 3scale Service that will be provisioned. + +- Syntax: lower case alphanumeric + underscore +- Required: no +- Default value: if not defined, the system_name is taken from the OpenAPI + Specification `x-threescale-system-name` extended field, suffixed by the + API major version number. If there is no `x-threescale-system-name` + extended field can be found, the `title` field is sanitized and then used. + If no title can be found, the default value `API` is used. If no version + number can be found, `0` is used. +- Example: `my_wonderful_service` + +### `threescale_cicd_wildcard_domain` + +Automatically defines the APIcast public URLs based on a scheme. + +- Syntax: DNS domain suffix +- Required: no +- Default value: if defined, computes the `threescale_cicd_apicast_sandbox_endpoint` + and `threescale_cicd_apicast_production_endpoint` from the API system_name. + The sandbox APIcast will be `-staging.` and the + production APIcast will be `.`. The suffix for the + staging (`-staging`) and the production (empty) can be customized with the + `threescale_cicd_default_staging_suffix` and `threescale_cicd_default_production_suffix` + variables. +- Example: the following two variables + + ```ini + threescale_cicd_wildcard_domain=acme.corp + threescale_cicd_api_system_name=my_wonderful_service + ``` + + are equivalent to: + + ```ini + threescale_cicd_apicast_sandbox_endpoint=https://my-wonderful-service-staging.acme.corp/ + threescale_cicd_apicast_production_endpoint=https://my-wonderful-service.acme.corp/ + ``` + +### `threescale_cicd_api_backend_hostname` + +Defines the backend hostname, overriding the `host` field of the OpenAPI Specification. +The resulting value is used to define the `threescale_cicd_private_base_url` variable +if missing. + +- Syntax: FQDN with an optional port +- Required: no +- Default value: the `host` field of the OpenAPI Specification. +- Examples: `mybackend.acme.corp` or `mybackend.acme.corp:8080` + +### `threescale_cicd_api_backend_scheme` + +Defines the scheme to use to connect to the backend, overriding the `schemes` field of the OpenAPI Specification. +The resulting value is used to define the `threescale_cicd_private_base_url` variable +if missing. + +- Syntax: `http` or `https` +- Required: no +- Default value: the first item of the `scheme` field of the OpenAPI Specification, + defaulting to `http` if missing. +- Examples: `https` + +### `threescale_cicd_private_base_url` + +Defines the 3scale Private Base URL. + +- Syntax: `://:` +- Required: no +- Default value: `://` +- Examples: `http://mybackend.acme.corp:8080` + +### `threescale_cicd_openapi_smoketest_operation` + +Defines the OpenAPI Specification method to use for smoke tests. + +- Syntax: the `operationId` of the OpenAPI Specification method +- Required: no +- Default value: none. If this variable is undefined and if there is no operation + flagged with `x-threescale-system-name` in the OpenAPI Specification, the + smoke tests are skipped. +- Examples: `http://mybackend.acme.corp:8080` + +### `threescale_cicd_api_environment_name` + +Prefix all services with an environment name to prevent any name collision +when deploying the same API multiple times on the same 3scale instance. + +- Syntax: lowercase, alphanumeric + underscore +- Required: no +- Default value: none, no prefixing is performed. +- Examples: `dev`, `test` or `prod` ## Dependencies