diff --git a/.travis.yml b/.travis.yml index 32241d2..3340f21 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,18 +12,12 @@ install: # infrastructures because of rate limits imposed by GitHub on its API. - mkdir tests/bin/ && curl -L -o tests/bin/swagger https://github.com/go-swagger/go-swagger/releases/download/0.16.0/swagger_linux_amd64 && chmod 755 tests/bin/swagger script: -- ansible-playbook tests/write-inventory-files.yml -- ansible-playbook -v -i tests/inventory tests/3scale-saas-with-hosted-apicast-apikey.yml -- ansible-playbook -v -i tests/inventory tests/3scale-saas-with-hosted-apicast-oidc.yml -- ansible-playbook -v -i tests/inventory tests/3scale-saas-with-hosted-apicast-with-basePath.yml -- ansible-playbook -v -i tests/inventory tests/3scale-saas-with-hosted-apicast-multi-environment.yml -- ansible-playbook -v -i tests/inventory tests/3scale-saas-with-hosted-apicast-with-smoketest-in-extra-vars.yml -- ansible-playbook -v -i tests/inventory tests/3scale-saas-with-hosted-apicast-without-smoketest.yml +- tests/run-tests.sh notifications: webhooks: https://galaxy.ansible.com/api/v1/notifications/ branches: except: - /^dev.*/ before_install: -- openssl aes-256-cbc -K $encrypted_7bf6043000c3_key -iv $encrypted_7bf6043000c3_iv - -in tests/3scale-inventory.yaml.enc -out tests/3scale-inventory.yaml -d +# travis encrypt-file tests/3scale-inventory.yaml tests/3scale-inventory.yaml.enc +- openssl aes-256-cbc -K $encrypted_5ba3c614c7e1_key -iv $encrypted_5ba3c614c7e1_iv -in tests/3scale-inventory.yaml.enc -out tests/3scale-inventory.yaml -d diff --git a/tests/3scale-inventory.yaml.enc b/tests/3scale-inventory.yaml.enc index a51a212..032a4d7 100644 Binary files a/tests/3scale-inventory.yaml.enc and b/tests/3scale-inventory.yaml.enc differ diff --git a/tests/3scale-saas-with-hosted-apicast-multi-environment.yml b/tests/3scale-saas-with-hosted-apicast-multi-environment.yml deleted file mode 100644 index 7f45ea2..0000000 --- a/tests/3scale-saas-with-hosted-apicast-multi-environment.yml +++ /dev/null @@ -1,45 +0,0 @@ ---- - -- name: Deploy the Beer Catalog API to a 3scale SaaS instance in multi environment - hosts: threescale - gather_facts: no - vars: - threescale_cicd_openapi_file: '{{ playbook_dir }}/api/beer-catalog-api.json' - threescale_cicd_openapi_file_format: 'JSON' - threescale_cicd_api_backend_hostname: echo-api.3scale.net - threescale_cicd_openapi_smoketest_operation: GET_beer - threescale_cicd_api_base_system_name: beer_catalog_envs - tasks: - # Deploy in DEV - - import_role: - name: 'nmasse-itix.threescale-cicd' - vars: - threescale_cicd_api_environment_name: dev - # Deploy in TEST - - import_role: - name: 'nmasse-itix.threescale-cicd' - vars: - threescale_cicd_api_environment_name: test - # Deploy in PROD - - import_role: - name: 'nmasse-itix.threescale-cicd' - vars: - threescale_cicd_api_environment_name: prod - # Cleanup the DEV - - import_role: - name: 'nmasse-itix.threescale-cicd' - tasks_from: 'cleanup' - vars: - threescale_cicd_api_environment_name: dev - # Cleanup the TEST - - import_role: - name: 'nmasse-itix.threescale-cicd' - tasks_from: 'cleanup' - vars: - threescale_cicd_api_environment_name: test - # Cleanup the PROD - - import_role: - name: 'nmasse-itix.threescale-cicd' - tasks_from: 'cleanup' - vars: - threescale_cicd_api_environment_name: prod diff --git a/tests/3scale-saas-with-hosted-apicast-oidc.yml b/tests/3scale-saas-with-hosted-apicast-oidc.yml deleted file mode 100644 index 028c0b4..0000000 --- a/tests/3scale-saas-with-hosted-apicast-oidc.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- - -- name: Deploy the Echo API to a 3scale SaaS instance, with hosted APIcasts and OpenID Connect - hosts: threescale - gather_facts: no - vars: - threescale_cicd_openapi_file: '{{ playbook_dir }}/api/echo-api-oidc.yaml' - threescale_cicd_api_base_system_name: echo_api_oidc - tasks: - # Test a first deployment - - import_role: - name: 'nmasse-itix.threescale-cicd' - # Verify idempotence - - import_role: - name: 'nmasse-itix.threescale-cicd' - # Delete the service - - import_role: - name: 'nmasse-itix.threescale-cicd' - tasks_from: 'cleanup' diff --git a/tests/3scale-saas-with-hosted-apicast-with-basePath.yml b/tests/3scale-saas-with-hosted-apicast-with-basePath.yml deleted file mode 100644 index 0d114d9..0000000 --- a/tests/3scale-saas-with-hosted-apicast-with-basePath.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- - -- name: Deploy the Echo API to a 3scale SaaS instance, with hosted APIcasts - hosts: threescale - gather_facts: no - vars: - threescale_cicd_openapi_file: '{{ playbook_dir }}/api/echo-api-with-basePath.yaml' - threescale_cicd_api_base_system_name: echo_api_with_basepath - tasks: - # Test a first deployment - - import_role: - name: 'nmasse-itix.threescale-cicd' - # Verify idempotence - - import_role: - name: 'nmasse-itix.threescale-cicd' - # Delete the service - - import_role: - name: 'nmasse-itix.threescale-cicd' - tasks_from: 'cleanup' diff --git a/tests/3scale-saas-with-hosted-apicast-with-smoketest-in-extra-vars.yml b/tests/3scale-saas-with-hosted-apicast-with-smoketest-in-extra-vars.yml deleted file mode 100644 index fdbc53e..0000000 --- a/tests/3scale-saas-with-hosted-apicast-with-smoketest-in-extra-vars.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- - -- name: Deploy the Echo API to a 3scale SaaS instance, with hosted APIcasts and smoketests in extra vars - hosts: threescale - gather_facts: no - vars: - threescale_cicd_openapi_smoketest_operation: Echo - threescale_cicd_openapi_file: '{{ playbook_dir }}/api/echo-api-bare.yaml' - threescale_cicd_api_base_system_name: echo_api_bare_extra - tasks: - # Deploy the service - - import_role: - name: 'nmasse-itix.threescale-cicd' - # Delete the service - - import_role: - name: 'nmasse-itix.threescale-cicd' - tasks_from: 'cleanup' diff --git a/tests/ansible.cfg b/tests/ansible.cfg new file mode 120000 index 0000000..61278e8 --- /dev/null +++ b/tests/ansible.cfg @@ -0,0 +1 @@ +../ansible.cfg \ No newline at end of file diff --git a/tests/environments/.gitignore b/tests/environments/.gitignore new file mode 100644 index 0000000..f59ec20 --- /dev/null +++ b/tests/environments/.gitignore @@ -0,0 +1 @@ +* \ No newline at end of file diff --git a/tests/inventory.j2 b/tests/inventory.j2 index e291b14..747d059 100644 --- a/tests/inventory.j2 +++ b/tests/inventory.j2 @@ -1,9 +1,26 @@ +{# Select the target CI platform using the THREESCALE_POOL environment variable #} +{% set pool = lookup('env', 'THREESCALE_POOL') %} +{% set test_environment = test_environment[pool|int] %} + [all:vars] ansible_connection=local +{% if 'apicast_staging_domain' in test_environment.threescale %} +apicast_staging_domain={{ test_environment.threescale.apicast_staging_domain }} +{% endif %} +{% if 'apicast_production_domain' in test_environment.threescale %} +apicast_production_domain={{ test_environment.threescale.apicast_production_domain }} +{% endif %} [threescale] -{{ threescale_inventory.threescale_hosted.admin_portal }} +{{ test_environment.threescale.admin_portal }} [threescale:vars] -threescale_cicd_access_token={{ threescale_inventory.threescale_hosted.access_token }} -threescale_cicd_sso_issuer_endpoint=https://{{ threescale_inventory.sso.client_id }}:{{ threescale_inventory.sso.client_secret }}@{{ threescale_inventory.sso.host }}/auth/realms/{{ threescale_inventory.sso.realm }} +threescale_cicd_access_token={{ test_environment.threescale.access_token }} +threescale_cicd_sso_issuer_endpoint=https://{{ test_environment.sso.client_id }}:{{ test_environment.sso.client_secret }}@{{ test_environment.sso.host }}/auth/realms/{{ test_environment.sso.realm }} +{% if 'wildcard_domain' in test_environment.threescale %} +threescale_cicd_wildcard_domain={{ test_environment.threescale.wildcard_domain }} +{% endif %} +# Disable throttling when running on-premises +{% if test_environment.threescale.admin_portal is match(".*[.]3scale[.]net") %} +threescale_cicd_throttling=0 +{% endif %} diff --git a/tests/roles/nmasse-itix.threescale-cicd b/tests/roles/nmasse-itix.threescale-cicd deleted file mode 120000 index c25bddb..0000000 --- a/tests/roles/nmasse-itix.threescale-cicd +++ /dev/null @@ -1 +0,0 @@ -../.. \ No newline at end of file diff --git a/tests/run-tests.sh b/tests/run-tests.sh new file mode 100755 index 0000000..3c18a03 --- /dev/null +++ b/tests/run-tests.sh @@ -0,0 +1,39 @@ +#!/bin/bash + + +cd "${0%/*}" || exit 1 + +echo "--> Generating the Ansible inventory files..." +ansible-playbook -i /dev/null write-inventory-files.yml +ret=$? +if [ "$ret" -gt 0 ]; then + echo "--> Ansible inventory files generation FAILED !" + exit 1 +else + echo "--> Ansible inventory files generation SUCCEEDED !" +fi + +# Because of a bug in Ansible, we need to move one directory upper before running +# the playbooks. +# +# The bug makes the playbooks fail after the Application Plans creation/update +# with this error message: +# +# ERROR! Unexpected Exception, this is probably a bug: expected str, bytes or os.PathLike object, not NoneType +# +cd ".." || exit 1 + +for environment in tests/environments/3scale-*; do + for testcase in tests/test-cases/*.y*ml; do + echo "--> Running $testcase against $environment..." + ansible-playbook -i "$environment" -v "$testcase" + ret=$? + if [ "$ret" -gt 0 ]; then + echo "--> $testcase against $environment FAILED !" + exit 1 + else + echo "--> $testcase against $environment SUCCEEDED !" + fi + break + done +done \ No newline at end of file diff --git a/tests/setup/README.md b/tests/setup/README.md new file mode 100644 index 0000000..ebd9675 --- /dev/null +++ b/tests/setup/README.md @@ -0,0 +1,67 @@ +# Test Environment setup + +## 3scale SaaS with APIcast Self-Managed + +Create a project in an OpenShift cluster: + +```sh +oc new-project apicast-3scale-ci +``` + +Deploy two 3scale gateways (staging and production): + +```sh +oc create secret generic 3scale-tenant- --from-literal=password=https://@-admin.3scale.net +oc create -f https://raw.githubusercontent.com/3scale/apicast/v3.4.0/openshift/apicast-template.yml +oc new-app --template=3scale-gateway --name=apicast--staging -p CONFIGURATION_URL_SECRET=3scale-tenant- -p CONFIGURATION_CACHE=0 -p RESPONSE_CODES=true -p LOG_LEVEL=info -p CONFIGURATION_LOADER=lazy -p APICAST_NAME=apicast--staging -p DEPLOYMENT_ENVIRONMENT=sandbox -p IMAGE_NAME=quay.io/3scale/apicast:v3.4.0 +oc new-app --template=3scale-gateway --name=apicast--production -p CONFIGURATION_URL_SECRET=3scale-tenant- -p CONFIGURATION_CACHE=60 -p RESPONSE_CODES=true -p LOG_LEVEL=info -p CONFIGURATION_LOADER=boot -p APICAST_NAME=apicast--production -p DEPLOYMENT_ENVIRONMENT=production -p IMAGE_NAME=quay.io/3scale/apicast:v3.4.0 +oc scale dc/apicast--staging --replicas=1 +oc scale dc/apicast--production --replicas=1 +oc expose svc/apicast--staging --wildcard-policy=Subdomain --overrides='{ "apiVersion": "route.openshift.io/v1", "kind": "Route", "spec": { "tls": { "insecureEdgeTerminationPolicy": "Allow", "termination": "edge" } } }' --hostname=wildcard.-staging.app... +oc expose svc/apicast--production --wildcard-policy=Subdomain --overrides='{ "apiVersion": "route.openshift.io/v1", "kind": "Route", "spec": { "tls": { "insecureEdgeTerminationPolicy": "Allow", "termination": "edge" } } }' --hostname=wildcard.-production.app... +``` + +Provision the Red Hat SSO tenants with the included playbooks: + +```sh +ansible-playbook tests/setup/setup-sso.yml -e sso_admin_password=secret -e sso_hostname=sso.app.example.test +``` + +## 3scale on-premise + +Create a project in an OpenShift cluster: + +```sh +oc new-project 3scale-ci-23 --display-name="3scale CI 2.3" +``` + +Deploy 3scale AMP 2.3: + +```sh +oc create -f https://raw.githubusercontent.com/3scale/3scale-amp-openshift-templates/2.3.0.GA/amp/amp.yml +oc new-app --template=3scale-api-management -p WILDCARD_DOMAIN=3scale-ci-23.app.example.test -p WILDCARD_POLICY=Subdomain +``` + +Create two tenants: `pool1` and `pool2` and expose them: + +```sh +oc expose svc/system-provider --hostname pool1-admin.3scale-ci-23.app.example.test --overrides='{ "apiVersion": "route.openshift.io/v1", "kind": "Route", "spec": { "tls": { "insecureEdgeTerminationPolicy": "Allow", "termination": "edge" } } }' --name=pool1-admin +oc expose svc/system-provider --hostname pool2-admin.3scale-ci-23.app.example.test --overrides='{ "apiVersion": "route.openshift.io/v1", "kind": "Route", "spec": { "tls": { "insecureEdgeTerminationPolicy": "Allow", "termination": "edge" } } }' --name=pool2-admin +``` + +Provision the Red Hat SSO tenants with the included playbooks: + +```sh +ansible-playbook tests/setup/setup-sso.yml -e sso_admin_password=secret -e sso_hostname=sso.app.example.test +``` + +Delete the wildcard route and recreate it with two more routes: + +```sh +oc delete route apicast-wildcard-router +oc expose svc/apicast-wildcard-router --wildcard-policy=Subdomain --overrides='{ "apiVersion": "route.openshift.io/v1", "kind": "Route", "spec": { "tls": { "insecureEdgeTerminationPolicy": "Allow", "termination": "edge" } } }' --hostname=apicast-wildcard.pool1.3scale-ci-23.app.example.test --name=pool1-apicast-wildcard-router +oc expose svc/apicast-wildcard-router --wildcard-policy=Subdomain --overrides='{ "apiVersion": "route.openshift.io/v1", "kind": "Route", "spec": { "tls": { "insecureEdgeTerminationPolicy": "Allow", "termination": "edge" } } }' --hostname=apicast-wildcard.pool2.3scale-ci-23.app.example.test --name=pool2-apicast-wildcard-router +oc expose svc/apicast-wildcard-router --wildcard-policy=Subdomain --overrides='{ "apiVersion": "route.openshift.io/v1", "kind": "Route", "spec": { "tls": { "insecureEdgeTerminationPolicy": "Allow", "termination": "edge" } } }' --hostname=apicast-wildcard.3scale-ci-23.app.example.test --name=apicast-wildcard-router +``` + +Do the same with other versions of 3scale. diff --git a/tests/setup/common/create-sso-client.yml b/tests/setup/common/create-sso-client.yml new file mode 100644 index 0000000..dd42a01 --- /dev/null +++ b/tests/setup/common/create-sso-client.yml @@ -0,0 +1,77 @@ +--- + +- name: Create the SSO client + keycloak_client: + auth_keycloak_url: 'https://{{ sso_hostname }}/auth' + auth_password: '{{ sso_admin_password }}' + auth_realm: '{{ sso_admin_realm }}' + auth_username: '{{ sso_admin_username }}' + name: '{{ item.client_id }}' + description: 'Zync account for 3scale instance {{ item.admin_portal }}' + realm: '{{ item.realm }}' + enabled: true + state: present + protocol: openid-connect + client_id: '{{ item.client_id }}' + secret: '{{ item.client_secret }}' + direct_access_grants_enabled: false + full_scope_allowed: true + implicit_flow_enabled: false + public_client: false + service_accounts_enabled: true + standard_flow_enabled: false + validate_certs: no + register: create_client_response + +- name: Get the service account user tied to the client + uri: + url: 'https://{{ sso_hostname }}/auth/admin/realms/{{ item.realm }}/clients/{{ client_uuid }}/service-account-user' + validate_certs: no + headers: + Authorization: 'Bearer {{ access_token }}' + register: service_account_response + changed_when: false + vars: + client_uuid: '{{ create_client_response.end_state.id }}' + +- name: Get the "realm-management" client details + keycloak_client: + auth_keycloak_url: 'https://{{ sso_hostname }}/auth' + auth_password: '{{ sso_admin_password }}' + auth_realm: '{{ sso_admin_realm }}' + auth_username: '{{ sso_admin_username }}' + realm: '{{ item.realm }}' + state: present + client_id: realm-management + validate_certs: no + check_mode: yes + register: realm_management_client_response + +- name: Get the role description of the "realm-management" client + uri: + url: 'https://{{ sso_hostname }}/auth/admin/realms/{{ item.realm }}/clients/{{ realm_management_client_uuid }}/roles/manage-clients' + validate_certs: no + headers: + Authorization: 'Bearer {{ access_token }}' + register: get_role_response + changed_when: false + vars: + realm_management_client_uuid: '{{ realm_management_client_response.existing.id }}' + +- name: Add the 'manage-clients' role mapping to the service account user + uri: + url: 'https://{{ sso_hostname }}/auth/admin/realms/{{ item.realm }}/users/{{ service_account_uuid }}/role-mappings/clients/{{ realm_management_client_uuid }}' + body: + - '{{ manage_clients_role }}' + body_format: json + method: POST + validate_certs: no + headers: + Authorization: 'Bearer {{ access_token }}' + status_code: "204" + register: set_role_mapping_response + changed_when: set_role_mapping_response.status == 204 + vars: + service_account_uuid: '{{ service_account_response.json.id }}' + realm_management_client_uuid: '{{ realm_management_client_response.existing.id }}' + manage_clients_role: '{{ get_role_response.json }}' diff --git a/tests/setup/setup-sso.yml b/tests/setup/setup-sso.yml new file mode 100644 index 0000000..d6dd266 --- /dev/null +++ b/tests/setup/setup-sso.yml @@ -0,0 +1,106 @@ +--- + +- name: Configure Red Hat SSO according to the 3scale inventory file + hosts: localhost + gather_facts: no + vars: + ansible_connection: local + sso_admin_username: admin + sso_admin_realm: master + sso_admin_client_id: admin-cli + tasks: + - assert: + that: + - sso_admin_password is defined + - sso_hostname is defined + msg: > + Please pass the SSO admin credentials as extra vars + + - set_fact: + threescale_inventory: '{{ lookup(''env'', ''THREESCALE_INVENTORY'')|b64decode|from_json }}' + when: 'threescale_inventory is not defined and lookup(''env'', ''THREESCALE_INVENTORY'')|length > 0' + + - set_fact: + threescale_inventory: '{{ lookup(''file'', ''{{ playbook_dir }}/../3scale-inventory.yaml'')|from_yaml }}' + when: 'threescale_inventory is not defined' + + - name: Authenticate to RH-SSO + uri: + url: 'https://{{ sso_hostname }}/auth/realms/{{ sso_admin_realm }}/protocol/openid-connect/token' + body: 'grant_type=password&client_id={{ sso_admin_client_id|urlencode }}&username={{ sso_admin_username|urlencode }}&password={{ sso_admin_password|urlencode }}' + method: POST + validate_certs: no + register: auth_response + changed_when: false + + - name: Delete the RH-SSO realm + uri: + url: 'https://{{ sso_hostname }}/auth/admin/realms/{{ item }}' + method: DELETE + validate_certs: no + headers: + Authorization: 'Bearer {{ access_token }}' + status_code: "204,404" + register: delete_realm_response + changed_when: delete_realm_response.status == 204 + with_items: '{{ realms }}' + vars: + realms: '{{ threescale_inventory|json_query(''@.*[].sso.realm'')|unique }}' + access_token: '{{ auth_response.json.access_token }}' + + - name: Create the RH-SSO realm + uri: + url: 'https://{{ sso_hostname }}/auth/admin/realms' + body: + id: '{{ item }}' + enabled: true + realm: '{{ item }}' + displayName: '{{ item }}' + notBefore: 0 + revokeRefreshToken: false + refreshTokenMaxReuse: 0 + registrationAllowed: false + registrationEmailAsUsername: false + rememberMe: false + verifyEmail: false + loginWithEmailAllowed: false + duplicateEmailsAllowed: false + resetPasswordAllowed: false + bruteForceProtected: false + permanentLockout: false + roles: + realm: [] + defaultRoles: [] + requiredCredentials: + - password + scopeMappings: [] + editUsernameAllowed: false + accessTokenLifespanForImplicitFlow: 86400 # 1 day + accessTokenLifespan: 86400 # 1 day + accessCodeLifespanUserAction: 86400 # 1 day + accessCodeLifespanLogin: 86400 # 1 day + accessCodeLifespan: 86400 # 1 day + ssoSessionIdleTimeout: 86400 # 1 day + ssoSessionMaxLifespan: 86400 # 1 day + offlineSessionIdleTimeout: 2592000 # 30 days + actionTokenGeneratedByAdminLifespan: 86400 # 1 day + actionTokenGeneratedByUserLifespan: 86400 # 1 day + sslRequired: none + body_format: json + method: POST + validate_certs: no + headers: + Authorization: 'Bearer {{ access_token }}' + status_code: "201,409" + register: create_realm_response + changed_when: create_realm_response.status == 201 + with_items: '{{ realms }}' + vars: + realms: '{{ threescale_inventory|json_query(''@.*[].sso.realm'')|unique }}' + access_token: '{{ auth_response.json.access_token }}' + + - include_tasks: "common/create-sso-client.yml" + with_items: '{{ clients }}' + vars: + clients: '{{ threescale_inventory|json_query(''@.*[].{client_id: sso.client_id, client_secret: sso.client_secret, realm: sso.realm, admin_portal: threescale.admin_portal }'')|unique }}' + access_token: '{{ auth_response.json.access_token }}' diff --git a/tests/3scale-saas-with-hosted-apicast-apikey.yml b/tests/test-cases/01-beer-catalog-apikey.yml similarity index 51% rename from tests/3scale-saas-with-hosted-apicast-apikey.yml rename to tests/test-cases/01-beer-catalog-apikey.yml index fbecdcd..0887386 100644 --- a/tests/3scale-saas-with-hosted-apicast-apikey.yml +++ b/tests/test-cases/01-beer-catalog-apikey.yml @@ -1,15 +1,21 @@ --- -- name: Deploy the Beer Catalog API to a 3scale SaaS instance, with hosted APIcasts +- name: Deploy the Beer Catalog API with API Key hosts: threescale gather_facts: no vars: - threescale_cicd_openapi_file: '{{ playbook_dir }}/api/beer-catalog-api.json' + threescale_cicd_openapi_file: '{{ playbook_dir }}/api-contracts/beer-catalog-api.json' threescale_cicd_openapi_file_format: 'JSON' threescale_cicd_api_backend_hostname: echo-api.3scale.net threescale_cicd_openapi_smoketest_operation: GET_beer - threescale_cicd_api_base_system_name: beer_catalog_apikey tasks: + - name: Generate a random system_name for this test run + import_tasks: "common/random-system-name.yml" + + - name: Compute custom public base urls for APIcast self-managed environments + include_vars: "common/apicast-selfmanaged-vars.yml" + when: apicast_staging_domain is defined or apicast_production_domain is defined + # Test a first deployment - import_role: name: 'nmasse-itix.threescale-cicd' diff --git a/tests/test-cases/02-echo-api-oidc.yml b/tests/test-cases/02-echo-api-oidc.yml new file mode 100644 index 0000000..366e472 --- /dev/null +++ b/tests/test-cases/02-echo-api-oidc.yml @@ -0,0 +1,25 @@ +--- + +- name: Deploy the Echo API with OpenID Connect + hosts: threescale + gather_facts: no + vars: + threescale_cicd_openapi_file: '{{ playbook_dir }}/api-contracts/echo-api-oidc.yaml' + tasks: + - name: Generate a random system_name for this test run + import_tasks: "common/random-system-name.yml" + + - name: Compute custom public base urls for APIcast self-managed environments + include_vars: "common/apicast-selfmanaged-vars.yml" + when: apicast_staging_domain is defined or apicast_production_domain is defined + + # Test a first deployment + - import_role: + name: 'nmasse-itix.threescale-cicd' + # Verify idempotence + - import_role: + name: 'nmasse-itix.threescale-cicd' + # Delete the service + - import_role: + name: 'nmasse-itix.threescale-cicd' + tasks_from: 'cleanup' diff --git a/tests/test-cases/03-multi-environment.yml b/tests/test-cases/03-multi-environment.yml new file mode 100644 index 0000000..49d3758 --- /dev/null +++ b/tests/test-cases/03-multi-environment.yml @@ -0,0 +1,53 @@ +--- + +- name: Deploy the Beer Catalog API in multi environment + hosts: threescale + gather_facts: no + vars: + threescale_cicd_openapi_file: '{{ playbook_dir }}/api-contracts/beer-catalog-api.json' + threescale_cicd_openapi_file_format: 'JSON' + threescale_cicd_api_backend_hostname: echo-api.3scale.net + threescale_cicd_openapi_smoketest_operation: GET_beer + tasks: + - name: Generate a random system_name for this test run + import_tasks: "common/random-system-name.yml" + + # Deploy in DEV + - import_role: + name: 'nmasse-itix.threescale-cicd' + vars: + threescale_cicd_api_environment_name: dev + threescale_cicd_apicast_sandbox_endpoint: '{{ threescale_cicd_default_apicast_scheme }}://{{ (threescale_cicd_api_environment_name ~ "-" ~ threescale_cicd_api_base_system_name ~ "-" ~ threescale_cicd_api_version_major)|regex_replace(''[^a-zA-Z0-9-]+'', ''-'')|lower }}{{ threescale_cicd_default_staging_suffix }}.{{ apicast_staging_domain }}' + threescale_cicd_apicast_production_endpoint: '{{ threescale_cicd_default_apicast_scheme }}://{{ (threescale_cicd_api_environment_name ~ "-" ~threescale_cicd_api_base_system_name ~ "-" ~ threescale_cicd_api_version_major)|regex_replace(''[^a-zA-Z0-9-]+'', ''-'')|lower }}{{ threescale_cicd_default_production_suffix }}.{{ apicast_production_domain }}' + # Deploy in TEST + - import_role: + name: 'nmasse-itix.threescale-cicd' + vars: + threescale_cicd_api_environment_name: test + threescale_cicd_apicast_sandbox_endpoint: '{{ threescale_cicd_default_apicast_scheme }}://{{ (threescale_cicd_api_environment_name ~ "-" ~ threescale_cicd_api_base_system_name ~ "-" ~ threescale_cicd_api_version_major)|regex_replace(''[^a-zA-Z0-9-]+'', ''-'')|lower }}{{ threescale_cicd_default_staging_suffix }}.{{ apicast_staging_domain }}' + threescale_cicd_apicast_production_endpoint: '{{ threescale_cicd_default_apicast_scheme }}://{{ (threescale_cicd_api_environment_name ~ "-" ~threescale_cicd_api_base_system_name ~ "-" ~ threescale_cicd_api_version_major)|regex_replace(''[^a-zA-Z0-9-]+'', ''-'')|lower }}{{ threescale_cicd_default_production_suffix }}.{{ apicast_production_domain }}' + # Deploy in PROD + - import_role: + name: 'nmasse-itix.threescale-cicd' + vars: + threescale_cicd_api_environment_name: prod + threescale_cicd_apicast_sandbox_endpoint: '{{ threescale_cicd_default_apicast_scheme }}://{{ (threescale_cicd_api_environment_name ~ "-" ~ threescale_cicd_api_base_system_name ~ "-" ~ threescale_cicd_api_version_major)|regex_replace(''[^a-zA-Z0-9-]+'', ''-'')|lower }}{{ threescale_cicd_default_staging_suffix }}.{{ apicast_staging_domain }}' + threescale_cicd_apicast_production_endpoint: '{{ threescale_cicd_default_apicast_scheme }}://{{ (threescale_cicd_api_environment_name ~ "-" ~threescale_cicd_api_base_system_name ~ "-" ~ threescale_cicd_api_version_major)|regex_replace(''[^a-zA-Z0-9-]+'', ''-'')|lower }}{{ threescale_cicd_default_production_suffix }}.{{ apicast_production_domain }}' + # Cleanup the DEV + - import_role: + name: 'nmasse-itix.threescale-cicd' + tasks_from: 'cleanup' + vars: + threescale_cicd_api_environment_name: dev + # Cleanup the TEST + - import_role: + name: 'nmasse-itix.threescale-cicd' + tasks_from: 'cleanup' + vars: + threescale_cicd_api_environment_name: test + # Cleanup the PROD + - import_role: + name: 'nmasse-itix.threescale-cicd' + tasks_from: 'cleanup' + vars: + threescale_cicd_api_environment_name: prod diff --git a/tests/test-cases/04-one-gateway.yml b/tests/test-cases/04-one-gateway.yml new file mode 100644 index 0000000..ffcff22 --- /dev/null +++ b/tests/test-cases/04-one-gateway.yml @@ -0,0 +1,24 @@ +--- + +- name: Deploy the Beer Catalog API with only one gateway + hosts: threescale + gather_facts: no + vars: + threescale_cicd_openapi_file: '{{ playbook_dir }}/api-contracts/beer-catalog-api.json' + threescale_cicd_openapi_file_format: 'JSON' + threescale_cicd_api_backend_hostname: echo-api.3scale.net + threescale_cicd_openapi_smoketest_operation: GET_beer + # Both Public Base URL are the same + threescale_cicd_apicast_sandbox_endpoint: '{{ threescale_cicd_apicast_production_endpoint }}' + threescale_cicd_apicast_production_endpoint: '{{ threescale_cicd_default_apicast_scheme }}://{{ (threescale_cicd_api_base_system_name ~ "-" ~ threescale_cicd_api_version_major)|regex_replace(''[^a-zA-Z0-9-]+'', ''-'')|lower }}{{ threescale_cicd_default_production_suffix }}.{{ apicast_production_domain }}' + tasks: + - name: Generate a random system_name for this test run + import_tasks: "common/random-system-name.yml" + + # Deploy the service + - import_role: + name: 'nmasse-itix.threescale-cicd' + # Delete the service + - import_role: + name: 'nmasse-itix.threescale-cicd' + tasks_from: 'cleanup' diff --git a/tests/test-cases/05-echo-api-with-basePath.yml b/tests/test-cases/05-echo-api-with-basePath.yml new file mode 100644 index 0000000..dc68553 --- /dev/null +++ b/tests/test-cases/05-echo-api-with-basePath.yml @@ -0,0 +1,25 @@ +--- + +- name: Deploy the Echo API to a 3scale SaaS instance, with hosted APIcasts + hosts: threescale + gather_facts: no + vars: + threescale_cicd_openapi_file: '{{ playbook_dir }}/api-contracts/echo-api-with-basePath.yaml' + tasks: + - name: Generate a random system_name for this test run + import_tasks: "common/random-system-name.yml" + + - name: Compute custom public base urls for APIcast self-managed environments + include_vars: "common/apicast-selfmanaged-vars.yml" + when: apicast_staging_domain is defined or apicast_production_domain is defined + + # Test a first deployment + - import_role: + name: 'nmasse-itix.threescale-cicd' + # Verify idempotence + - import_role: + name: 'nmasse-itix.threescale-cicd' + # Delete the service + - import_role: + name: 'nmasse-itix.threescale-cicd' + tasks_from: 'cleanup' diff --git a/tests/3scale-saas-with-hosted-apicast-with-cors-policy.yml b/tests/test-cases/06-echo-api-with-cors-policy.yml similarity index 50% rename from tests/3scale-saas-with-hosted-apicast-with-cors-policy.yml rename to tests/test-cases/06-echo-api-with-cors-policy.yml index 055c222..83c6cd9 100644 --- a/tests/3scale-saas-with-hosted-apicast-with-cors-policy.yml +++ b/tests/test-cases/06-echo-api-with-cors-policy.yml @@ -6,9 +6,15 @@ vars: threescale_cicd_openapi_smoketest_operation: Echo threescale_cicd_apicast_policies_cors: yes - threescale_cicd_openapi_file: '{{ playbook_dir }}/api/echo-api-bare.yaml' - threescale_cicd_api_base_system_name: echo_api_cors + threescale_cicd_openapi_file: '{{ playbook_dir }}/api-contracts/echo-api-bare.yaml' tasks: + - name: Generate a random system_name for this test run + import_tasks: "common/random-system-name.yml" + + - name: Compute custom public base urls for APIcast self-managed environments + include_vars: "common/apicast-selfmanaged-vars.yml" + when: apicast_staging_domain is defined or apicast_production_domain is defined + # Deploy the service - import_role: name: 'nmasse-itix.threescale-cicd' diff --git a/tests/test-cases/07-echo-api-with-smoketest-in-extra-vars.yml b/tests/test-cases/07-echo-api-with-smoketest-in-extra-vars.yml new file mode 100644 index 0000000..3cb5782 --- /dev/null +++ b/tests/test-cases/07-echo-api-with-smoketest-in-extra-vars.yml @@ -0,0 +1,23 @@ +--- + +- name: Deploy the Echo API to a 3scale SaaS instance, with hosted APIcasts and smoketests in extra vars + hosts: threescale + gather_facts: no + vars: + threescale_cicd_openapi_smoketest_operation: Echo + threescale_cicd_openapi_file: '{{ playbook_dir }}/api-contracts/echo-api-bare.yaml' + tasks: + - name: Generate a random system_name for this test run + import_tasks: "common/random-system-name.yml" + + - name: Compute custom public base urls for APIcast self-managed environments + include_vars: "common/apicast-selfmanaged-vars.yml" + when: apicast_staging_domain is defined or apicast_production_domain is defined + + # Deploy the service + - import_role: + name: 'nmasse-itix.threescale-cicd' + # Delete the service + - import_role: + name: 'nmasse-itix.threescale-cicd' + tasks_from: 'cleanup' diff --git a/tests/3scale-saas-with-hosted-apicast-without-smoketest.yml b/tests/test-cases/08-echo-api-without-smoketest.yml similarity index 50% rename from tests/3scale-saas-with-hosted-apicast-without-smoketest.yml rename to tests/test-cases/08-echo-api-without-smoketest.yml index 07c0cfa..2f5a866 100644 --- a/tests/3scale-saas-with-hosted-apicast-without-smoketest.yml +++ b/tests/test-cases/08-echo-api-without-smoketest.yml @@ -5,9 +5,15 @@ gather_facts: no vars: # There is no "threescale_cicd_openapi_smoketest_operation" variable - threescale_cicd_openapi_file: '{{ playbook_dir }}/api/echo-api-bare.yaml' - threescale_cicd_api_base_system_name: echo_api_no_smoketests + threescale_cicd_openapi_file: '{{ playbook_dir }}/api-contracts/echo-api-bare.yaml' tasks: + - name: Generate a random system_name for this test run + import_tasks: "common/random-system-name.yml" + + - name: Compute custom public base urls for APIcast self-managed environments + include_vars: "common/apicast-selfmanaged-vars.yml" + when: apicast_staging_domain is defined or apicast_production_domain is defined + # Deploy the service - import_role: name: 'nmasse-itix.threescale-cicd' diff --git a/tests/api/beer-catalog-api.json b/tests/test-cases/api-contracts/beer-catalog-api.json similarity index 100% rename from tests/api/beer-catalog-api.json rename to tests/test-cases/api-contracts/beer-catalog-api.json diff --git a/tests/api/echo-api-bare.yaml b/tests/test-cases/api-contracts/echo-api-bare.yaml similarity index 100% rename from tests/api/echo-api-bare.yaml rename to tests/test-cases/api-contracts/echo-api-bare.yaml diff --git a/tests/api/echo-api-oidc.yaml b/tests/test-cases/api-contracts/echo-api-oidc.yaml similarity index 100% rename from tests/api/echo-api-oidc.yaml rename to tests/test-cases/api-contracts/echo-api-oidc.yaml diff --git a/tests/api/echo-api-with-basePath.yaml b/tests/test-cases/api-contracts/echo-api-with-basePath.yaml similarity index 100% rename from tests/api/echo-api-with-basePath.yaml rename to tests/test-cases/api-contracts/echo-api-with-basePath.yaml diff --git a/tests/api/echo-api.yaml b/tests/test-cases/api-contracts/echo-api.yaml similarity index 100% rename from tests/api/echo-api.yaml rename to tests/test-cases/api-contracts/echo-api.yaml diff --git a/tests/test-cases/common/apicast-selfmanaged-vars.yml b/tests/test-cases/common/apicast-selfmanaged-vars.yml new file mode 100644 index 0000000..b4f8b14 --- /dev/null +++ b/tests/test-cases/common/apicast-selfmanaged-vars.yml @@ -0,0 +1,3 @@ +--- +threescale_cicd_apicast_sandbox_endpoint: '{{ threescale_cicd_default_apicast_scheme }}://{{ (threescale_cicd_api_base_system_name ~ "-" ~ threescale_cicd_api_version_major)|regex_replace(''[^a-zA-Z0-9-]+'', ''-'')|lower }}{{ threescale_cicd_default_staging_suffix }}.{{ apicast_staging_domain }}' +threescale_cicd_apicast_production_endpoint: '{{ threescale_cicd_default_apicast_scheme }}://{{ (threescale_cicd_api_base_system_name ~ "-" ~ threescale_cicd_api_version_major)|regex_replace(''[^a-zA-Z0-9-]+'', ''-'')|lower }}{{ threescale_cicd_default_production_suffix }}.{{ apicast_production_domain }}' diff --git a/tests/test-cases/common/random-system-name.yml b/tests/test-cases/common/random-system-name.yml new file mode 100644 index 0000000..9bc89c4 --- /dev/null +++ b/tests/test-cases/common/random-system-name.yml @@ -0,0 +1,5 @@ +--- + +- name: Generate a random system_name for this test run + set_fact: + threescale_cicd_api_base_system_name: 'testcase_{{ lookup(''password'', ''/dev/null length=12 chars=hexdigits'')|lower }}' \ No newline at end of file diff --git a/tests/test-cases/roles/nmasse-itix.threescale-cicd b/tests/test-cases/roles/nmasse-itix.threescale-cicd new file mode 120000 index 0000000..a8a4f8c --- /dev/null +++ b/tests/test-cases/roles/nmasse-itix.threescale-cicd @@ -0,0 +1 @@ +../../.. \ No newline at end of file diff --git a/tests/write-inventory-files.yml b/tests/write-inventory-files.yml index 0d7e8f8..49c0103 100644 --- a/tests/write-inventory-files.yml +++ b/tests/write-inventory-files.yml @@ -11,24 +11,13 @@ when: 'threescale_inventory is not defined and lookup(''env'', ''THREESCALE_INVENTORY'')|length > 0' - set_fact: - threescale_inventory: '{{ lookup(''file'', ''3scale-inventory.yaml'')|from_yaml }}' + threescale_inventory: '{{ lookup(''file'', ''{{ playbook_dir }}/3scale-inventory.yaml'')|from_yaml }}' when: 'threescale_inventory is not defined' - - name: Find the Jinja2 templates to process - find: - paths: '{{ playbook_dir }}' - patterns: '*.j2' - recurse: no - register: templates - - - name: Select the target CI platform using the THREESCALE_POOL environment variable - set_fact: - threescale_inventory: '{{ threescale_inventory[env|int] }}' - vars: - env: '{{ lookup(''env'', ''THREESCALE_POOL'') }}' - - name: Process the Jinja2 templates template: - src: '{{ item }}' - dest: '{{ item|replace(".j2", "") }}' - with_items: '{{ templates.files|json_query(''[*].path'') }}' + src: '{{ playbook_dir }}/inventory.j2' + dest: '{{ playbook_dir }}/environments/{{ item.key }}' + with_dict: '{{ threescale_inventory }}' + vars: + test_environment: '{{ item.value }}'