nmasse-itix.threescale-cicd
ansible-cicd
This project helps you to set up Continuous Delivery with the Red Hat 3scale API Management Platform (3scale AMP).
Requirements
To use this project, you need:
- A 3scale API Management Platform (either hosted or on your own servers)
- A Red Hat SSO instance if you want to use OpenID Connect for authentication
- Two APIcast gateways (one for staging and one for production), which can be hosted or managed by you
- A Swagger 2.0 file that describes the API you want to publish
Everything is done via APIs, so you don't need an SSH connection!
On the control node, you'll need the jmespath library. If it's not there, install it using:
pip install jmespath
You'll also need a recent version of Jinja (2.8 or higher). Upgrade with:
pip install -U Jinja2
If your control node is running on RHEL7, you can run this playbook to install any missing parts.
Example: Deploying an API on 3scale SaaS with hosted APIcast gateways
To deploy a simple "Echo API" on a SaaS 3scale instance using API Keys, follow these steps:
- Create a Swagger file for your Echo API
- Build your inventory file
- Write the playbook
- Run the playbook!
First, ensure your Swagger file (api-swagger.yaml) contains the necessary information:
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
In this Swagger file, these fields are crucial:
x-threescale-system-nameis used for the system name in configuration.titleis used as the name of the service definition.versionis important for proper versioning.hostis the DNS name of the existing API backend.operationIdis the system name for methods/metrics.summaryanddescriptionare the name and description for methods/metrics.x-threescale-smoketests-operationflags an operation as suitable for smoke tests.securityandsecurityDefinitionsdefine the security for the exposed API. In this case, it's using API Keys.
Next, write the inventory file:
[all:vars]
ansible_connection=local
[threescale]
<TENANT>-admin.3scale.net
[threescale:vars]
threescale_cicd_access_token=<ACCESS_TOKEN>
Key points in the inventory file:
- The 3scale admin portal should be in a group called
threescale. - The 3scale access token needs to be set in the
threescale_cicd_access_tokenvariable. - As there’s no SSH connection (only the 3scale Admin APIs are used),
ansible_connection=localis set for the entire inventory.
Now, create the playbook (deploy-api.yaml):
- hosts: threescale
gather_facts: no
vars:
threescale_cicd_openapi_file: 'api-swagger.yaml'
roles:
- nmasse-itix.threescale-cicd
Main elements include:
threescale_cicd_openapi_fileis the path to your Swagger file.- The
nmasse-itix.threescale-cicdrole is being used. gather_facts: nois necessary since there's no SSH connection to the systems.
Finally, run the playbook:
ansible-galaxy install nmasse-itix.threescale-cicd
ansible-playbook -i inventory deploy-api.yaml
Inventory
The 3scale Admin Portal referenced in the playbook that includes this role will be provisioned. In our above example, it will be <TENANT>-admin.3scale.net because the playbook specifies hosts: threescale which has just that one host.
If you specify multiple hosts for the 3scale Admin Portal, they will all be set up with the same configuration (useful for multi-site setups).
To connect to the 3scale Admin Portal, you'll need to provide an Access Token that has read/write privileges on the Account Management API. You can set this token at the host level, group level, or globally with the threescale_cicd_access_token variable.
At the host level, it looks like this:
[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 like this:
[threescale:vars]
threescale_cicd_access_token=123...456
[threescale]
tenant1-admin.3scale.net
tenant2-admin.3scale.net
You can also set it globally, for example in the playbook variables:
- hosts: threescale
vars:
threescale_cicd_access_token: 123...456
The Red Hat SSO instance (there can only be one) is defined by the threescale_cicd_sso_issuer_endpoint variable within the threescale group.
Its format is https://<client_id>:<client_secret>@hostname/auth/realms/<realm>.
The client_id and client_secret are used by Zync to sync 3scale applications with Red Hat SSO.
Example:
threescale_cicd_sso_issuer_endpoint=https://3scale:123@sso.acme.corp/auth/realms/acme
The APIcast instances are defined using these extra variables:
threescale_cicd_apicast_sandbox_endpointthreescale_cicd_apicast_production_endpoint
Example:
threescale_cicd_apicast_sandbox_endpoint=http://api-test.acme.corp
threescale_cicd_apicast_production_endpoint=https://api.acme.corp
OpenAPI Specification fields
This project currently supports only OpenAPI Specification v2.0 (also known as Swagger 2.0).
You can use the following extended fields in the OpenAPI Specification:
x-threescale-system-namein theinfosection is used to set the system name for the configuration objects in 3scale.x-threescale-smoketests-operationflags methods suitable for smoke tests. The method must be idempotent, read-only, and have no parameters. If no methods are flagged, smoke tests will be skipped.
If you can't use the extended fields (for example, you don't want to change your API Contract), you can use the corresponding extra variables:
threescale_cicd_api_base_system_namethreescale_cicd_openapi_smoketest_operation
Here’s an example OpenAPI Specification using the extended fields:
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
Here, echo-api is used for the system name of the 3scale service definition and a GET request on / is used for smoke tests.
To achieve the same without using the OpenAPI extended fields, set the extra variables:
threescale_cicd_api_base_system_name=echo-api
threescale_cicd_openapi_smoketest_operation=Echo # operationId of the "GET /" method
The standard fields of the OpenAPI Specification used include:
- In the
infosection:titleis the display name of the 3scale service definition.versionis important for proper versioning.hostis the DNS name of the API backend you want to expose.
For each method defined:
- The
operationIdis used as the system name for the corresponding methods/metrics. - The
summaryanddescriptionare used as the name and description for the methods/metrics. - The
securityandsecurityDefinitionsspecify the security for the exposed API.
To map the OpenAPI Specifications to the 3scale features, some restrictions apply to the security and securityDefinitions structures. Specifically, there should be one and only one security requirement in the security structure, applied globally (not per method).
You can choose between two security schemes for API access:
- OAuth / OpenID Connect
- API Key
The App Key Pair scheme isn't supported in this role, as it doesn't have a corresponding definition in OpenAPI Specifications.
To secure your API with API Key, use this in your OpenAPI Specification:
securityDefinitions:
apikey:
name: api-key
in: header
type: apiKey
security:
- apikey: []
You can change the HTTP header name to send the API Key by modifying the name field (e.g., api-key).
To secure it with OpenID Connect, use this:
securityDefinitions:
oidc:
type: oauth2
flow: accessCode
authorizationUrl: http://dummy/placeholder
tokenUrl: http://dummy/placeholder
scopes:
openid: Get an OpenID Connect token
security:
- oidc:
- openid
You have the flexibility to choose your OpenID Connect flow:
implicitpasswordapplicationaccessCode
Role Variables
This section describes all variables used in the role. The project aims for convention over configuration, meaning it offers sensible defaults and structured naming from the start.
threescale_cicd_openapi_file
Specifies the OpenAPI Specification file to read.
- Syntax: Full path to the OpenAPI Specification on your local system (use absolute paths).
- Required: yes
- Examples:
/tmp/openapi.yamlor{{ playbook_dir }}/git/openapi.json
threescale_cicd_openapi_file_format
Specifies the format (JSON or YAML) of the OpenAPI Specification file.
- Syntax:
JSONorYAML - Required: no
- Default value:
YAML - Example:
YAML
threescale_cicd_api_system_name
Defines the system_name of the 3scale service being provisioned.
- Syntax: lower case letters, numbers, and underscores
- Required: no
- Default value: If not defined, it will be based on
threescale_cicd_api_base_system_name, appending the API major version and prefixing it with the environment name if applicable. - Example:
dev_my_service_1
threescale_cicd_api_base_system_name
Used to compute the threescale_cicd_api_system_name.
- Syntax: lower case letters, numbers, and underscores
- Required: no
- Default value: If not provided, it checks for the
x-threescale-system-nameortitlefield in the OpenAPI Specification and uses a sanitized version. Default toAPIif none found, and0for versioning. - Example:
my_service
Note: If both threescale_cicd_api_base_system_name and threescale_cicd_api_system_name are set, the latter takes precedence.
threescale_cicd_wildcard_domain
Automatically defines the public URLs for APIcast.
Syntax: DNS domain suffix
Required: no
Default value: If defined, computes endpoints based on the API system name with a suffix for staging and production.
Example: If using
threescale_cicd_wildcard_domain=acme.corp threescale_cicd_api_base_system_name=my_serviceThen the resulting endpoints would be:
threescale_cicd_apicast_sandbox_endpoint=https://my-service-staging.acme.corp/ threescale_cicd_apicast_production_endpoint=https://my-service.acme.corp/
threescale_cicd_api_basepath
Defines a base path for the backend API, overriding the OpenAPI Specification's basePath.
- Syntax: URI part starting with /
- Required: no
- Default value: the
basePathfrom the OpenAPI Specification. - Examples:
/apior/context
threescale_cicd_api_backend_hostname
Defines the backend hostname, overriding the OpenAPI Specification's host.
- Syntax: Fully Qualified Domain Name (FQDN) with optional port
- Required: no
- Default value: the
hostfrom the OpenAPI Specification. - Examples:
mybackend.acme.corpormybackend.acme.corp:8080
threescale_cicd_api_backend_scheme
Defines the scheme to connect to the backend, overriding the schemes field from the OpenAPI Specification.
- Syntax:
httporhttps - Required: no
- Default value: Defaulting to the first scheme from the OpenAPI Specification,
httpif missing. - Examples:
https
threescale_cicd_private_base_url
Defines the 3scale Private Base URL.
- Syntax:
<schema>://<host>:<port> - Required: no
- Default value: Based on the backend scheme and hostname.
- Examples:
http://mybackend.acme.corp:8080
threescale_cicd_apicast_policies_cors
Allows enabling CORS policy on the APIcast gateway if your API should support cross-origin requests.
- Syntax: boolean
yesorno - Required: no
- Default value:
no - Example:
yesto enable CORS policy on APIcast
threescale_cicd_openapi_smoketest_operation
Defines the method from OpenAPI Specification to use for smoke tests.
- Syntax: the
operationIdfrom the OpenAPI Specification method. - Required: no
- Default value: If not set and no smoke test method flagged, smoke tests will be skipped.
- Example:
GetName
threescale_cicd_api_environment_name
Prefixes all services with an environment name to avoid name collisions when deploying the same API multiple times.
- Syntax: lowercase, alphanumeric, and underscore
- Required: no
- Default value: none (no prefixing).
- Examples:
dev,test, orprod
threescale_cicd_validate_openapi
Validates the OpenAPI Specification file using the official schema with the go-swagger tool.
You can pre-install this tool or point to its location with the threescale_cicd_goswagger_command variable.
If the tool is missing, it can be downloaded automatically.
- Syntax: boolean (
yes,no,true,false) - Required: no
- Default value:
yes - Examples:
threescale_cicd_validate_openapi=nothreescale_cicd_goswagger_command=/usr/local/bin/swaggerthreescale_cicd_local_bin_path=/tmp
threescale_cicd_oicd_flows
Overrides or updates supported OAuth flows for this API.
- Syntax: array of strings (
[ 'application', 'accessCode' ]) - Required: no
- Default value: defaults to
flowfrom thesecuritySchemein your OpenAPI Specification. - Examples:
threescale_cicd_oicd_flows="{{ [ 'application', 'accessCode' ] }}"(overrides the flow list)threescale_cicd_oicd_flows="{{ [ 'application', threescale_cicd_api_security_scheme.flow ] }}"(adds a flow)
threescale_cicd_create_default_application
Allows creating a default test application with the default application plan.
- Syntax: boolean (
yes,no,true,false) - Required: no
- Default value:
no - Example: Set to
yesto create a default application
Miscellaneous variables
Other variables are listed in defaults/main.yml, which provides sensible defaults. Check them out.
Dependencies
This project has no dependencies on other roles, but it requires:
- Ansible (at least version 2.4)
- JMESPath
- Jinja (version 2.8 or higher)
- 3scale API Management 2.3
Integration with other technologies
Support for major technologies is found in the support folder. This includes Jenkins, Kubernetes, Docker, OpenShift, and a pre-built docker image.
License
MIT
Author Information
- Nicolas Massé, Red Hat
- Laurent Broudoux, Red Hat
- Daria Mayorova, Red Hat
Enables Continuous Deployment with 3scale API Management Platform
ansible-galaxy install nmasse-itix.threescale-cicd