100 changed files with 1281 additions and 1162 deletions
@ -0,0 +1,2 @@ |
|||
[defaults] |
|||
jinja2_extensions = jinja2.ext.do |
|||
@ -0,0 +1,23 @@ |
|||
--- |
|||
|
|||
- debug: |
|||
var: threescale_cicd_create_activedoc_payload |
|||
verbosity: 1 |
|||
|
|||
- name: Create the ActiveDocs |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/active_docs.json |
|||
validate_certs: no |
|||
method: POST |
|||
body: '{{ threescale_cicd_create_activedoc_payload }}' |
|||
status_code: 201 |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 201' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_existing_activedocs: '{{ threescale_cicd_existing_activedocs|union([ threescale_cicd_tmpresponse.json.api_doc.system_name ]) }}' |
|||
threescale_cicd_existing_activedocs_details: '{{ threescale_cicd_existing_activedocs_details|union([ { ''id'': threescale_cicd_tmpresponse.json.api_doc.id, ''system_name'': threescale_cicd_tmpresponse.json.api_doc.system_name } ]) }}' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -0,0 +1,22 @@ |
|||
--- |
|||
|
|||
- debug: |
|||
var: threescale_cicd_create_application_payload |
|||
verbosity: 1 |
|||
|
|||
- name: Create the application |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/accounts/{{ threescale_cicd_default_account_id }}/applications.json |
|||
validate_certs: no |
|||
method: POST |
|||
body: '{{ threescale_cicd_create_application_payload }}' |
|||
status_code: 201 |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 201' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_default_application_details: '{{ threescale_cicd_tmpresponse.json.application }}' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -0,0 +1,23 @@ |
|||
--- |
|||
|
|||
- debug: |
|||
var: threescale_cicd_create_application_plan_payload |
|||
verbosity: 1 |
|||
|
|||
- name: Create the application plan |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/application_plans.json |
|||
validate_certs: no |
|||
method: POST |
|||
body: '{{ threescale_cicd_create_application_plan_payload }}' |
|||
status_code: 201 |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 201' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_existing_application_plans: '{{ threescale_cicd_existing_application_plans|union([ threescale_cicd_application_plan.system_name ]) }}' |
|||
threescale_cicd_existing_application_plans_details: '{{ threescale_cicd_existing_application_plans_details|union([{ "system_name": threescale_cicd_application_plan.system_name, "id": threescale_cicd_tmpresponse.json.application_plan.id }]) }}' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -0,0 +1,19 @@ |
|||
--- |
|||
|
|||
- debug: |
|||
var: threescale_cicd_create_mapping_rule_payload |
|||
verbosity: 1 |
|||
|
|||
- name: Create the mapping rule |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/proxy/mapping_rules.json |
|||
validate_certs: no |
|||
method: POST |
|||
body: '{{ threescale_cicd_create_mapping_rule_payload }}' |
|||
status_code: 201 |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 201' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -0,0 +1,23 @@ |
|||
--- |
|||
|
|||
- debug: |
|||
var: threescale_cicd_create_method_payload |
|||
verbosity: 1 |
|||
|
|||
- name: Create the method |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/metrics/{{ threescale_cicd_metric_id }}/methods.json |
|||
validate_certs: no |
|||
method: POST |
|||
body: '{{ threescale_cicd_create_method_payload }}' |
|||
status_code: 201 |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 201' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_existing_metrics: '{{ threescale_cicd_existing_metrics|union([ threescale_cicd_api_operation.key ]) }}' |
|||
threescale_cicd_existing_metrics_details: '{{ threescale_cicd_existing_metrics_details|union([ { "system_name": threescale_cicd_api_operation.key, "id": threescale_cicd_tmpresponse.json|json_query("method.id") } ]) }}' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -0,0 +1,24 @@ |
|||
--- |
|||
|
|||
- debug: |
|||
var: threescale_cicd_create_service_payload |
|||
verbosity: 1 |
|||
|
|||
- name: Create the service |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services.json |
|||
validate_certs: no |
|||
method: POST |
|||
body: '{{ threescale_cicd_create_service_payload }}' |
|||
status_code: 201 |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 201' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_existing_services: '{{ threescale_cicd_existing_services|union([ threescale_cicd_tmpresponse.json.service.system_name ]) }}' |
|||
threescale_cicd_existing_services_details: '{{ threescale_cicd_existing_services_details|union([ { ''id'': threescale_cicd_tmpresponse.json.service.id, ''system_name'': threescale_cicd_tmpresponse.json.service.system_name } ]) }}' |
|||
cacheable: true |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -0,0 +1,14 @@ |
|||
--- |
|||
|
|||
- name: Delete the unused mapping rules |
|||
uri: |
|||
url: "https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/proxy/mapping_rules/{{ threescale_cicd_existing_mapping_rules[threescale_cicd_mapping_rule] }}.json?access_token={{ threescale_cicd_access_token|urlencode }}" |
|||
validate_certs: no |
|||
method: DELETE |
|||
status_code: 200,404 |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 200' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -0,0 +1,17 @@ |
|||
--- |
|||
|
|||
- debug: |
|||
msg: "Deleting unused metric {{ threescale_cicd_metric.system_name }}..." |
|||
|
|||
- name: Delete the metric |
|||
uri: |
|||
url: "https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/metrics/{{ threescale_cicd_metric_id }}/methods/{{ threescale_cicd_metric.id }}.json?access_token={{ threescale_cicd_access_token|urlencode }}" |
|||
validate_certs: no |
|||
method: DELETE |
|||
status_code: 200,404 |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 200' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -0,0 +1,13 @@ |
|||
--- |
|||
|
|||
- name: Check if the default application exists |
|||
uri: |
|||
url: 'https://{{ inventory_hostname }}/admin/api/applications/find.json?{{ threescale_cicd_find_application_payload }}' |
|||
validate_certs: no |
|||
method: GET |
|||
status_code: 200,404 |
|||
register: threescale_cicd_tmpresponse |
|||
|
|||
- set_fact: |
|||
threescale_cicd_default_application_id: '{{ threescale_cicd_tmpresponse.json.application.id }}' |
|||
when: 'threescale_cicd_tmpresponse.status == 200' |
|||
@ -0,0 +1,10 @@ |
|||
--- |
|||
|
|||
- name: Get the default (first) account |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/accounts.json?access_token={{ threescale_cicd_access_token|urlencode }}&state=approved&page=1&per_page=1 |
|||
validate_certs: no |
|||
register: threescale_cicd_tmpresponse |
|||
|
|||
- set_fact: |
|||
threescale_cicd_default_account_id: '{{ threescale_cicd_tmpresponse.json.accounts[0].account.id }}' |
|||
@ -0,0 +1,20 @@ |
|||
--- |
|||
|
|||
- name: Get the version of the staging proxy definition |
|||
uri: |
|||
url: 'https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/proxy/configs/{{ threescale_cicd_staging_environment_name }}/latest.json?access_token={{ threescale_cicd_access_token|urlencode }}' |
|||
validate_certs: no |
|||
register: threescale_cicd_tmpresponse |
|||
|
|||
- set_fact: |
|||
threescale_cicd_staging_proxy_version: '{{ threescale_cicd_tmpresponse.json.proxy_config.version }}' |
|||
|
|||
- name: Get the version of the production proxy definition |
|||
uri: |
|||
url: 'https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/proxy/configs/{{ threescale_cicd_production_environment_name }}/latest.json?access_token={{ threescale_cicd_access_token|urlencode }}' |
|||
validate_certs: no |
|||
status_code: 200,404 |
|||
register: threescale_cicd_tmpresponse |
|||
|
|||
- set_fact: |
|||
threescale_cicd_production_proxy_version: '{{ threescale_cicd_tmpresponse.json.proxy_config.version if threescale_cicd_tmpresponse.status == 200 else ''NONE'' }}' |
|||
@ -0,0 +1,22 @@ |
|||
--- |
|||
|
|||
- debug: |
|||
var: threescale_cicd_authenticate_to_keycloak_payload |
|||
verbosity: 1 |
|||
|
|||
- name: Authenticate to RH-SSO |
|||
uri: |
|||
url: '{{ threescale_cicd_sso_realm_endpoint }}/protocol/openid-connect/token' |
|||
body: '{{ threescale_cicd_authenticate_to_keycloak_payload }}' |
|||
method: POST |
|||
validate_certs: no |
|||
return_content: yes |
|||
register: threescale_cicd_tmpresponse |
|||
retries: '{{ threescale_cicd_retries }}' |
|||
delay: '{{ threescale_cicd_delay }}' |
|||
# temporary fix for https://github.com/ansible/ansible/issues/28078 |
|||
until: 'threescale_cicd_tmpresponse is success' |
|||
|
|||
- name: Extract the access_token |
|||
set_fact: |
|||
threescale_cicd_keycloak_access_token: '{{ threescale_cicd_tmpresponse.json |json_query("access_token") }}' |
|||
@ -0,0 +1,23 @@ |
|||
--- |
|||
|
|||
- debug: |
|||
var: threescale_cicd_patch_keycloak_client_payload |
|||
verbosity: 1 |
|||
|
|||
- name: Patch the client in RH-SSO to support the "client_credentials" and "password" grant_type. |
|||
uri: |
|||
url: '{{ threescale_cicd_sso_admin_endpoint }}/clients/{{ threescale_cicd_default_application_sso_id|urlencode }}' |
|||
method: PUT |
|||
validate_certs: no |
|||
body: '{{ threescale_cicd_patch_keycloak_client_payload }}' |
|||
body_format: json |
|||
status_code: '200,204' |
|||
headers: |
|||
Authorization: 'Bearer {{ threescale_cicd_keycloak_access_token }}' |
|||
Content-Type: 'application/json' |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 200' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -0,0 +1,18 @@ |
|||
--- |
|||
|
|||
- name: Wait for the new client to appear in RH-SSO |
|||
uri: |
|||
url: '{{ threescale_cicd_sso_admin_endpoint }}/clients?clientId={{ threescale_cicd_default_application_appid|urlencode }}' |
|||
method: GET |
|||
validate_certs: no |
|||
return_content: yes |
|||
headers: |
|||
Authorization: 'Bearer {{ threescale_cicd_keycloak_access_token }}' |
|||
register: threescale_cicd_tmpresponse |
|||
retries: '{{ threescale_cicd_retries }}' |
|||
delay: '{{ threescale_cicd_delay }}' |
|||
until: 'threescale_cicd_tmpresponse is success and threescale_cicd_tmpresponse.json|length > 0' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_default_application_sso_id: '{{ threescale_cicd_tmpresponse.json[0].id }}' |
|||
threescale_cicd_default_application_sso_body: '{{ threescale_cicd_tmpresponse.json[0] }}' |
|||
@ -0,0 +1,19 @@ |
|||
--- |
|||
|
|||
- debug: |
|||
var: threescale_cicd_promote_proxy_payload |
|||
verbosity: 1 |
|||
|
|||
- name: Promote to production |
|||
uri: |
|||
url: 'https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/proxy/configs/{{ threescale_cicd_staging_environment_name }}/{{ threescale_cicd_staging_proxy_version }}/promote.json' |
|||
body: '{{ threescale_cicd_promote_proxy_payload }}' |
|||
status_code: 201 |
|||
validate_certs: no |
|||
method: POST |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 201' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -0,0 +1,20 @@ |
|||
--- |
|||
|
|||
- debug: |
|||
var: threescale_cicd_smoke_test_headers |
|||
verbosity: 1 |
|||
|
|||
- debug: |
|||
msg: "Starting a smoke test on '{{ threescale_cicd_smoke_test_url }}'..." |
|||
|
|||
- name: Running smoke tests ! |
|||
uri: |
|||
url: '{{ threescale_cicd_smoke_test_url }}' |
|||
headers: '{{ threescale_cicd_smoke_test_headers }}' |
|||
validate_certs: no |
|||
method: GET |
|||
register: threescale_cicd_tmpresponse |
|||
retries: '{{ threescale_cicd_retries }}' |
|||
delay: '{{ threescale_cicd_delay }}' |
|||
# temporary fix for https://github.com/ansible/ansible/issues/28078 |
|||
until: 'threescale_cicd_tmpresponse is success' |
|||
@ -0,0 +1,19 @@ |
|||
--- |
|||
|
|||
- debug: |
|||
var: threescale_cicd_update_activedoc_payload |
|||
verbosity: 1 |
|||
|
|||
- name: Update the ActiveDocs |
|||
uri: |
|||
url: 'https://{{ inventory_hostname }}/admin/api/active_docs/{{ threescale_cicd_api_activedocs_id }}.json' |
|||
validate_certs: no |
|||
method: PUT |
|||
body: '{{ threescale_cicd_update_activedoc_payload }}' |
|||
status_code: 200 |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 200' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -0,0 +1,21 @@ |
|||
--- |
|||
|
|||
- debug: |
|||
var: threescale_cicd_update_application_payload |
|||
verbosity: 1 |
|||
|
|||
- name: Update the application |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/accounts/{{ threescale_cicd_default_account_id }}/applications/{{ threescale_cicd_default_application_id }}.json |
|||
validate_certs: no |
|||
method: PUT |
|||
body: '{{ threescale_cicd_update_application_payload }}' |
|||
status_code: 200 |
|||
register: threescale_cicd_tmpresponse |
|||
|
|||
- set_fact: |
|||
threescale_cicd_default_application_details: '{{ threescale_cicd_tmpresponse.json.application }}' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -0,0 +1,19 @@ |
|||
--- |
|||
|
|||
- debug: |
|||
var: threescale_cicd_update_application_plan_payload |
|||
verbosity: 1 |
|||
|
|||
- name: Update the application plan |
|||
uri: |
|||
url: 'https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/application_plans/{{ (threescale_cicd_existing_application_plans_details|selectattr("system_name", "equalto", threescale_cicd_application_plan.system_name)|first).id }}.json' |
|||
validate_certs: no |
|||
method: PUT |
|||
body: '{{ threescale_cicd_update_application_plan_payload }}' |
|||
status_code: 200 |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 200' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -0,0 +1,21 @@ |
|||
--- |
|||
|
|||
- debug: |
|||
var: threescale_cicd_update_mapping_rule_payload |
|||
verbosity: 1 |
|||
|
|||
- name: Update the mapping rule |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/proxy/mapping_rules/{{ threescale_cicd_mapping_rule_id }}.json |
|||
validate_certs: no |
|||
method: PUT |
|||
body: '{{ threescale_cicd_update_mapping_rule_payload }}' |
|||
status_code: 200 |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 200' |
|||
vars: |
|||
threescale_cicd_mapping_rule_id: '{{ threescale_cicd_existing_mapping_rules[threescale_cicd_mapping_rule] }}' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -0,0 +1,18 @@ |
|||
--- |
|||
|
|||
- debug: |
|||
var: threescale_cicd_update_method_payload |
|||
verbosity: 1 |
|||
|
|||
- name: Update the method |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/metrics/{{ threescale_cicd_metric_id }}/methods/{{ (threescale_cicd_existing_metrics_details|selectattr('system_name', 'equalto', threescale_cicd_api_operation.key)|first).id }}.json |
|||
validate_certs: no |
|||
method: PATCH |
|||
body: '{{ threescale_cicd_update_method_payload }}' |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 200' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -0,0 +1,23 @@ |
|||
--- |
|||
|
|||
- debug: |
|||
var: threescale_cicd_update_proxy_payload |
|||
verbosity: 1 |
|||
|
|||
- name: Update the proxy definition |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/proxy.json |
|||
validate_certs: no |
|||
method: PATCH |
|||
body: '{{ threescale_cicd_update_proxy_payload }}' |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 200' |
|||
|
|||
- name: Extract the staging and production gateway endpoint from the proxy definition |
|||
set_fact: |
|||
threescale_cicd_apicast_discovered_sandbox_endpoint: '{{ threescale_cicd_tmpresponse.json.proxy.sandbox_endpoint }}' |
|||
threescale_cicd_apicast_discovered_production_endpoint: '{{ threescale_cicd_tmpresponse.json.proxy.endpoint }}' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -0,0 +1,19 @@ |
|||
--- |
|||
|
|||
- debug: |
|||
var: threescale_cicd_update_service_payload |
|||
verbosity: 1 |
|||
|
|||
- name: Update the service |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}.json |
|||
validate_certs: no |
|||
method: PUT |
|||
body: '{{ threescale_cicd_update_service_payload }}' |
|||
status_code: 200 |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 200' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -1,32 +0,0 @@ |
|||
--- |
|||
|
|||
- name: Verify that Ansible version is >= 2.4 |
|||
assert: |
|||
that: "ansible_version.full is version_compare('2.4', '>=')" |
|||
msg: This module requires at least Ansible 2.4 |
|||
|
|||
- name: Check if jmespath is installed locally |
|||
debug: msg={{dummy|json_query('@')}} |
|||
register: check_jmespath |
|||
ignore_errors: yes |
|||
vars: |
|||
dummy: Hello World |
|||
|
|||
- name: Check if jinja 2.8 is installed locally |
|||
debug: msg={{(dummy|selectattr("id", "equalto", "hello")|first)['value']}} |
|||
vars: |
|||
dummy: |
|||
- id: hello |
|||
value: Hello World |
|||
register: check_jinja28 |
|||
ignore_errors: yes |
|||
|
|||
- assert: |
|||
that: |
|||
- 'check_jmespath is success' |
|||
msg: "The JMESPath library is required by this role. Please install the JMESPath library with 'pip install jmespath'." |
|||
|
|||
- assert: |
|||
that: |
|||
- 'check_jinja28 is success' |
|||
msg: "At least Jinja v2.8 is required by this role. Please update Jinja with 'pip install -U Jinja2'." |
|||
@ -1,113 +0,0 @@ |
|||
--- |
|||
|
|||
- name: Retrieve existing ActiveDocs from the 3scale Admin Portal |
|||
uri: |
|||
url: "https://{{ inventory_hostname }}/admin/api/active_docs.json?access_token={{ threescale_cicd_access_token|urlencode }}" |
|||
validate_certs: no |
|||
register: threescale_cicd_tmp_allactivedocs |
|||
|
|||
- set_fact: |
|||
threescale_cicd_existing_activedocs: '{{ threescale_cicd_tmp_allactivedocs.json|json_query(''api_docs[*].api_doc.system_name'') }}' |
|||
threescale_cicd_existing_activedocs_details: '{{ threescale_cicd_tmp_allactivedocs.json|json_query(''api_docs[].{"system_name": api_doc.system_name, "id": api_doc.id}'') }}' |
|||
|
|||
- name: Get the production gateway endpoint from the proxy definition |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/proxy.json?access_token={{ threescale_cicd_access_token|urlencode }} |
|||
validate_certs: no |
|||
method: GET |
|||
register: threescale_cicd_tmpresponse |
|||
when: "threescale_cicd_apicast_production_endpoint is not defined" |
|||
|
|||
- name: Extract the production gateway endpoint from the proxy definition |
|||
set_fact: |
|||
threescale_cicd_apicast_production_endpoint: '{{ threescale_cicd_tmpresponse.json|json_query(''proxy.endpoint'') }}' |
|||
when: "threescale_cicd_apicast_production_endpoint is not defined" |
|||
|
|||
- set_fact: |
|||
threescale_cicd_apicast_production_scheme: '{{ threescale_cicd_apicast_production_endpoint|regex_findall(''^(\w+)://'')|first }}' |
|||
threescale_cicd_apicast_production_hostname: '{{ threescale_cicd_apicast_production_endpoint|regex_findall(''^\w+://(.+)$'')|first }}' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_openapi_rewritten: '{{ threescale_cicd_openapi_file_content }}' |
|||
|
|||
- name: Rewrite the OpenAPI file (schemes) |
|||
set_fact: |
|||
threescale_cicd_openapi_rewritten: '{{ threescale_cicd_openapi_rewritten|combine({ ''schemes'': [ threescale_cicd_apicast_production_scheme ] }) }}' |
|||
|
|||
- name: Rewrite the OpenAPI file (host) |
|||
set_fact: |
|||
threescale_cicd_openapi_rewritten: '{{ threescale_cicd_openapi_rewritten|combine({ ''host'': threescale_cicd_apicast_production_hostname }) }}' |
|||
|
|||
- name: Rewrite the Swagger file (swagger version as string) |
|||
set_fact: |
|||
threescale_cicd_openapi_rewritten: '{{ threescale_cicd_openapi_rewritten|combine({ ''swagger'': threescale_cicd_openapi_rewritten.swagger ~ "" }) }}' |
|||
|
|||
- name: Add the RH-SSO endpoints to the OpenAPI securityDefinitions |
|||
set_fact: |
|||
threescale_cicd_api_security_definitions: '{{ threescale_cicd_api_security_definitions|combine({ threescale_cicd_api_security_scheme_name: (threescale_cicd_api_security_definitions[threescale_cicd_api_security_scheme_name]|combine({ ''authorizationUrl'': threescale_cicd_sso_realm_endpoint ~ ''/protocol/openid-connect/auth'', ''tokenUrl'': threescale_cicd_sso_realm_endpoint ~ ''/protocol/openid-connect/token'' })) }) }}' |
|||
when: 'threescale_cicd_api_security_scheme.type == ''oauth2''' |
|||
|
|||
- name: Add the RH-SSO default scope to the OpenAPI securityDefinitions |
|||
set_fact: |
|||
threescale_cicd_api_security_definitions: '{{ threescale_cicd_api_security_definitions|combine({ threescale_cicd_api_security_scheme_name: (threescale_cicd_api_security_definitions[threescale_cicd_api_security_scheme_name]|combine({ ''scopes'': threescale_cicd_default_oauth_scopes})) }) }}' |
|||
when: 'threescale_cicd_api_security_scheme.type == ''oauth2'' and ''scopes'' not in threescale_cicd_api_security_scheme' |
|||
|
|||
- name: Rewrite the OpenAPI file (securityDefinitions) |
|||
set_fact: |
|||
threescale_cicd_openapi_rewritten: '{{ threescale_cicd_openapi_rewritten|combine({ ''securityDefinitions'': threescale_cicd_api_security_definitions }) }}' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_activedoc_payload: |
|||
name: '{{ threescale_cicd_api_name }}' |
|||
system_name: '{{ threescale_cicd_api_system_name }}' |
|||
body: '{{ threescale_cicd_openapi_rewritten|to_nice_json }}' |
|||
description: '{{ threescale_cicd_api_description }}' |
|||
published: 'true' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_body_update_method: '{{ "access_token=" ~ threescale_cicd_access_token|urlencode }}' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_body_update_method: '{{ threescale_cicd_tmp_body_update_method ~ "&" ~ (threescale_cicd_tmp_param.key|urlencode) ~ "=" ~ (threescale_cicd_tmp_param.value|urlencode) }}' |
|||
with_dict: '{{ threescale_cicd_tmp_activedoc_payload }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_tmp_param |
|||
|
|||
- set_fact: |
|||
threescale_cicd_api_activedocs_id: '{{ (threescale_cicd_existing_activedocs_details|selectattr(''system_name'', ''equalto'', threescale_cicd_api_system_name)|first).id }}' |
|||
when: 'threescale_cicd_api_system_name in threescale_cicd_existing_activedocs' |
|||
|
|||
- name: Update the ActiveDocs |
|||
uri: |
|||
url: 'https://{{ inventory_hostname }}/admin/api/active_docs/{{ threescale_cicd_api_activedocs_id }}.json' |
|||
validate_certs: no |
|||
method: PUT |
|||
body: '{{ threescale_cicd_tmp_body_update_method }}' |
|||
status_code: 200 |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 200' |
|||
when: 'threescale_cicd_api_system_name in threescale_cicd_existing_activedocs' |
|||
|
|||
- name: Create the ActiveDocs |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/active_docs.json |
|||
validate_certs: no |
|||
method: POST |
|||
body: '{{ threescale_cicd_tmp_body_update_method }}' |
|||
status_code: 201 |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 201' |
|||
when: 'threescale_cicd_api_system_name not in threescale_cicd_existing_activedocs' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_api_activedocs_id: '{{ threescale_cicd_tmpresponse.json.api_doc.id }}' |
|||
when: 'threescale_cicd_api_system_name not in threescale_cicd_existing_activedocs' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_existing_services: '{{ threescale_cicd_existing_activedocs|union([ threescale_cicd_tmpresponse.json.api_doc.system_name ]) }}' |
|||
threescale_cicd_existing_services_details: '{{ threescale_cicd_existing_activedocs_details|union([ { ''id'': threescale_cicd_tmpresponse.json.api_doc.id, ''system_name'': threescale_cicd_tmpresponse.json.api_doc.system_name } ]) }}' |
|||
when: 'threescale_cicd_api_system_name not in threescale_cicd_existing_activedocs' |
|||
@ -1,38 +0,0 @@ |
|||
--- |
|||
- set_fact: |
|||
threescale_cicd_tmp_body_update_method: '{{ "access_token=" ~ threescale_cicd_access_token|urlencode }}' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_body_update_method: '{{ threescale_cicd_tmp_body_update_method ~ "&" ~ (threescale_cicd_tmp_param.key|urlencode) ~ "=" ~ (threescale_cicd_tmp_param.value|urlencode) }}' |
|||
with_dict: '{{ threescale_cicd_tmp_plan }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_tmp_param |
|||
|
|||
- name: Update the application plan |
|||
uri: |
|||
url: 'https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/application_plans/{{ (threescale_cicd_existing_application_plans_details|selectattr("system_name", "equalto", threescale_cicd_tmp_plan.system_name)|first).id }}.json' |
|||
validate_certs: no |
|||
method: PUT |
|||
body: '{{ threescale_cicd_tmp_body_update_method }}' |
|||
status_code: 200 |
|||
register: threescale_cicd_tmpresponse |
|||
when: 'threescale_cicd_tmp_plan.system_name in threescale_cicd_existing_application_plans' |
|||
|
|||
- name: Create the application plan |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/application_plans.json |
|||
validate_certs: no |
|||
method: POST |
|||
body: '{{ threescale_cicd_tmp_body_update_method }}' |
|||
status_code: 201 |
|||
register: threescale_cicd_tmpresponse |
|||
when: 'threescale_cicd_tmp_plan.system_name not in threescale_cicd_existing_application_plans' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_existing_application_plans: '{{ threescale_cicd_existing_application_plans|union([ threescale_cicd_tmp_plan.system_name ]) }}' |
|||
threescale_cicd_existing_application_plans_details: '{{ threescale_cicd_existing_application_plans_details|union([{ "system_name": threescale_cicd_tmp_plan.system_name, "id": threescale_cicd_tmpresponse.json.application_plan.id }]) }}' |
|||
when: 'threescale_cicd_tmp_plan.system_name not in threescale_cicd_existing_application_plans' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -1,89 +0,0 @@ |
|||
--- |
|||
|
|||
- name: Get the default (first) account |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/accounts.json?access_token={{ threescale_cicd_access_token|urlencode }}&state=approved&page=1&per_page=1 |
|||
validate_certs: no |
|||
register: threescale_cicd_tmp_allaccounts |
|||
when: 'threescale_cicd_default_account_id is not defined' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_default_account_id: '{{ threescale_cicd_tmp_allaccounts.json.accounts[0].account.id }}' |
|||
when: 'threescale_cicd_default_account_id is not defined' |
|||
|
|||
- name: Pick the first given application plan if no default application plan is given |
|||
set_fact: |
|||
threescale_cicd_default_application_plan: '{{ (threescale_cicd_application_plans|first).system_name }}' |
|||
when: 'threescale_cicd_default_application_plan is not defined and threescale_cicd_application_plans is defined and threescale_cicd_application_plans|length > 0' |
|||
|
|||
- name: Find the application plan id |
|||
set_fact: |
|||
threescale_cicd_default_application_plan_id: '{{ (threescale_cicd_existing_application_plans_details|selectattr("system_name", "equalto", threescale_cicd_default_application_plan)|first).id }}' |
|||
when: 'threescale_cicd_default_application_plan is defined' |
|||
|
|||
- name: Compute the appid for the default application |
|||
set_fact: |
|||
# The default appid is a SHA1 hash of the application name, api name and salted with the 3scale access token so that it cannot be guessed |
|||
threescale_cicd_default_application_appid: '{{ (threescale_cicd_default_application_name ~ threescale_cicd_api_system_name ~ threescale_cicd_access_token)|hash(''sha1'') }}' |
|||
when: 'threescale_cicd_default_application_appid is not defined' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_search_criteria: 'app_id' |
|||
threescale_cicd_tmp_app_id_field: 'application_id' |
|||
when: 'threescale_cicd_api_security_scheme.type == ''oauth2''' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_search_criteria: 'user_key' |
|||
threescale_cicd_tmp_app_id_field: 'user_key' |
|||
when: 'threescale_cicd_api_security_scheme.type == ''apiKey''' |
|||
|
|||
- name: Check if the default application exists |
|||
uri: |
|||
url: 'https://{{ inventory_hostname }}/admin/api/applications/find.json?access_token={{ threescale_cicd_access_token|urlencode }}&{{ threescale_cicd_tmp_search_criteria }}={{ threescale_cicd_default_application_appid|urlencode }}' |
|||
validate_certs: no |
|||
method: GET |
|||
status_code: 200,404 |
|||
register: threescale_cicd_tmpresponse |
|||
when: 'threescale_cicd_default_application_id is not defined and threescale_cicd_default_application_appid is defined' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_default_application_id: '{{ threescale_cicd_tmpresponse.json.application.id }}' |
|||
when: 'threescale_cicd_default_application_id is not defined and threescale_cicd_default_application_appid is defined and threescale_cicd_tmpresponse.status == 200' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_body_update_method: '{{ "access_token=" ~ (threescale_cicd_access_token|urlencode) ~ "&plan_id=" ~ threescale_cicd_default_application_plan_id ~ "&name=" ~ (threescale_cicd_default_application_name|urlencode) ~ "&description=" ~ (threescale_cicd_default_application_description|urlencode) ~ "&" ~ threescale_cicd_tmp_app_id_field ~ "=" ~ (threescale_cicd_default_application_appid|urlencode) }}' |
|||
|
|||
- name: Create the application |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/accounts/{{ threescale_cicd_default_account_id }}/applications.json |
|||
validate_certs: no |
|||
method: POST |
|||
body: '{{ threescale_cicd_tmp_body_update_method }}' |
|||
status_code: 201 |
|||
register: threescale_cicd_tmpresponse |
|||
when: 'threescale_cicd_default_application_id is not defined' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_default_application_details: '{{ threescale_cicd_tmpresponse.json.application }}' |
|||
when: 'threescale_cicd_default_application_id is not defined' |
|||
|
|||
- name: Update the application |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/accounts/{{ threescale_cicd_default_account_id }}/applications/{{ threescale_cicd_default_application_id }}.json |
|||
validate_certs: no |
|||
method: PUT |
|||
body: '{{ threescale_cicd_tmp_body_update_method }}' |
|||
status_code: 200 |
|||
register: threescale_cicd_tmpresponse |
|||
when: 'threescale_cicd_default_application_id is defined' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_default_application_details: '{{ threescale_cicd_tmpresponse.json.application }}' |
|||
when: 'threescale_cicd_default_application_id is defined' |
|||
|
|||
- include_tasks: patch_default_application_for_oauth.yml |
|||
when: 'threescale_cicd_api_security_scheme.type == ''oauth2''' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -1,28 +0,0 @@ |
|||
--- |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_body_update_method: '{{ "access_token=" ~ threescale_cicd_access_token|urlencode }}' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_body_update_method: '{{ threescale_cicd_tmp_body_update_method ~ "&" ~ (threescale_cicd_tmp_param.key|urlencode) ~ "=" ~ (threescale_cicd_tmp_param.value|urlencode) }}' |
|||
with_dict: '{{ threescale_cicd_tmp_wanted_mapping_rules[threescale_cicd_tmp_mapping_rule_to_create] }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_tmp_param |
|||
|
|||
- set_fact: |
|||
# Add the metric_id to the payload |
|||
threescale_cicd_tmp_body_update_method: '{{ threescale_cicd_tmp_body_update_method ~ "&" ~ "metric_id=" ~ ((threescale_cicd_existing_metrics_details|selectattr("system_name", "equalto", threescale_cicd_tmp_mapping_rule_to_create)|first).id|urlencode) }}' |
|||
|
|||
- name: Create the mapping rule |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/proxy/mapping_rules.json |
|||
validate_certs: no |
|||
method: POST |
|||
body: '{{ threescale_cicd_tmp_body_update_method }}' |
|||
status_code: 201 |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 201' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -1,58 +0,0 @@ |
|||
--- |
|||
|
|||
- name: Retrieve existing Services from the 3scale Admin Portal |
|||
uri: |
|||
url: "https://{{ inventory_hostname }}/admin/api/services.json?access_token={{ threescale_cicd_access_token|urlencode }}" |
|||
validate_certs: no |
|||
register: threescale_cicd_tmp_allservices |
|||
|
|||
- set_fact: |
|||
threescale_cicd_existing_services: '{{ threescale_cicd_tmp_allservices.json|json_query(''services[*].service.system_name'') }}' |
|||
threescale_cicd_existing_services_details: '{{ threescale_cicd_tmp_allservices.json|json_query(''services[].{"system_name": service.system_name, "id": service.id}'') }}' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_body_create_svc: '{{ "access_token=" ~ threescale_cicd_access_token|urlencode }}' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_body_create_svc: '{{ threescale_cicd_tmp_body_create_svc ~ "&" ~ (threescale_cicd_tmp_param.key|urlencode) ~ "=" ~ (threescale_cicd_tmp_param.value|urlencode) }}' |
|||
with_dict: '{{ threescale_cicd_api_service_definition }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_tmp_param |
|||
|
|||
- set_fact: |
|||
threescale_cicd_api_service_id: '{{ (threescale_cicd_existing_services_details|selectattr(''system_name'', ''equalto'', threescale_cicd_api_system_name)|first)[''id''] }}' |
|||
when: 'threescale_cicd_api_system_name in threescale_cicd_existing_services' |
|||
|
|||
- name: Update the service |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}.json |
|||
validate_certs: no |
|||
method: PUT |
|||
body: '{{ threescale_cicd_tmp_body_create_svc }}' |
|||
status_code: 200 |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 200' |
|||
when: 'threescale_cicd_api_system_name in threescale_cicd_existing_services' |
|||
|
|||
- name: Create the service |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services.json |
|||
validate_certs: no |
|||
method: POST |
|||
body: '{{ threescale_cicd_tmp_body_create_svc }}' |
|||
status_code: 201 |
|||
register: threescale_cicd_tmpresponse |
|||
when: 'threescale_cicd_api_system_name not in threescale_cicd_existing_services' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_api_service_id: '{{ threescale_cicd_tmpresponse.json.service.id }}' |
|||
when: 'threescale_cicd_api_system_name not in threescale_cicd_existing_services' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_existing_services: '{{ threescale_cicd_existing_services|union([ threescale_cicd_tmpresponse.json.service.system_name ]) }}' |
|||
threescale_cicd_existing_services_details: '{{ threescale_cicd_existing_services_details|union([ { ''id'': threescale_cicd_tmpresponse.json.service.id, ''system_name'': threescale_cicd_tmpresponse.json.service.system_name } ]) }}' |
|||
when: 'threescale_cicd_api_system_name not in threescale_cicd_existing_services' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -1,25 +0,0 @@ |
|||
--- |
|||
- set_fact: |
|||
threescale_cicd_tmp_metrics_to_delete: [] |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_metrics_to_delete: '{{ threescale_cicd_tmp_metrics_to_delete|union([threescale_cicd_tmp_metric.id]) }}' |
|||
with_items: '{{ threescale_cicd_existing_metrics_details }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_tmp_metric |
|||
when: 'threescale_cicd_tmp_metric.system_name != "hits" and threescale_cicd_tmp_metric.system_name not in threescale_cicd_api_operations' |
|||
|
|||
- name: Delete the method |
|||
uri: |
|||
url: "https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/metrics/{{ threescale_cicd_metric_id }}/methods/{{ threescale_cicd_tmp_metric }}.json?access_token={{ threescale_cicd_access_token|urlencode }}" |
|||
validate_certs: no |
|||
method: DELETE |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 200' |
|||
with_items: '{{ threescale_cicd_tmp_metrics_to_delete }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_tmp_metric |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -1,143 +1,53 @@ |
|||
--- |
|||
|
|||
- import_tasks: check_requirements.yml |
|||
# Make sure we have everything we need to run this playbook |
|||
- import_tasks: steps/requirements.yml |
|||
|
|||
- name: Ensure pre-requisites are met |
|||
assert: |
|||
that: |
|||
- "threescale_cicd_access_token is defined" |
|||
- "threescale_cicd_openapi_file is defined" |
|||
msg: |- |
|||
This module requires at least two variables: |
|||
- threescale_cicd_access_token that contains an Access Token with Read/Write privileges on the 3scale Account Management API. This variable is usually set in your inventory file. |
|||
- threescale_cicd_openapi_file that is the path to the OpenAPI file you want to deploy in 3scale. This variable is usually passed as an extra variable (-e threescale_cicd_openapi_file=...) |
|||
|
|||
- name: Set the threescale_cicd_sso_issuer_endpoint variable from the inventory |
|||
set_fact: |
|||
threescale_cicd_sso_issuer_endpoint: '{{ (hostvars[groups[''sso''][0]].scheme|default(''https'')) ~ ''://'' ~ hostvars[groups[''sso''][0]].client_id ~ '':'' ~ hostvars[groups[''sso''][0]].client_secret ~ ''@'' ~ groups[''sso''][0] ~ ''/auth/realms/'' ~ hostvars[groups[''sso''][0]].realm }}' |
|||
when: 'threescale_cicd_sso_issuer_endpoint is not defined and ''sso'' in groups and groups[''sso''] > 0' |
|||
|
|||
- name: Set the threescale_cicd_sso_realm_endpoint variable from the threescale_cicd_sso_issuer_endpoint |
|||
set_fact: |
|||
threescale_cicd_sso_realm_endpoint: '{{ (threescale_cicd_sso_issuer_endpoint|urlsplit(''scheme'')) ~ ''://'' ~ (threescale_cicd_sso_issuer_endpoint|urlsplit(''hostname'')) ~ (threescale_cicd_sso_issuer_endpoint|urlsplit(''path'')) }}' |
|||
when: 'threescale_cicd_sso_realm_endpoint is not defined and threescale_cicd_sso_issuer_endpoint is defined' |
|||
|
|||
- name: Set the threescale_cicd_sso_admin_endpoint variable from the threescale_cicd_sso_realm_endpoint |
|||
set_fact: |
|||
threescale_cicd_sso_admin_endpoint: '{{ threescale_cicd_sso_realm_endpoint|replace(''/auth/realms/'', ''/auth/admin/realms/'') }}' |
|||
when: 'threescale_cicd_sso_admin_endpoint is not defined and threescale_cicd_sso_realm_endpoint is defined' |
|||
|
|||
- name: Set the threescale_cicd_apicast_sandbox_endpoint variable from the inventory |
|||
set_fact: |
|||
threescale_cicd_apicast_sandbox_endpoint: '{{ (hostvars[groups[''apicast-sandbox''][0]].scheme|default(''https'')) ~ ''://'' ~ groups[''apicast-sandbox''][0] }}' |
|||
when: 'threescale_cicd_apicast_sandbox_endpoint is not defined and ''apicast-sandbox'' in groups and groups[''apicast-sandbox''] > 0' |
|||
|
|||
- name: Set the threescale_cicd_apicast_production_endpoint variable from the inventory |
|||
set_fact: |
|||
threescale_cicd_apicast_production_endpoint: '{{ (hostvars[groups[''apicast-production''][0]].scheme|default(''https'')) ~ ''://'' ~ groups[''apicast-production''][0] }}' |
|||
when: 'threescale_cicd_apicast_production_endpoint is not defined and ''apicast-production'' in groups and groups[''apicast-production''] > 0' |
|||
# Warn the user about those deprecated features |
|||
- import_tasks: steps/variables_from_inventory.yml |
|||
|
|||
# Load the API definition from the provided OpenAPI file |
|||
- import_tasks: read_openapi_file.yml |
|||
|
|||
|
|||
- name: Compute the service system_name |
|||
set_fact: |
|||
threescale_cicd_api_system_name: '{{ threescale_cicd_api_environment_name ~ "_" ~ threescale_cicd_api_system_name }}' |
|||
when: 'threescale_cicd_api_environment_name is defined' |
|||
|
|||
- debug: |
|||
msg: "Will work on service with system_name = {{ threescale_cicd_api_system_name }}" |
|||
|
|||
- set_fact: |
|||
threescale_cicd_api_deployment_type: 'self_managed' |
|||
when: 'threescale_cicd_api_deployment_type is not defined and (threescale_cicd_apicast_sandbox_endpoint is defined or threescale_cicd_apicast_production_endpoint is defined)' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_api_deployment_type: 'hosted' |
|||
when: 'threescale_cicd_api_deployment_type is not defined' |
|||
- import_tasks: steps/read_openapi.yml |
|||
|
|||
- set_fact: |
|||
threescale_cicd_api_service_definition: |
|||
name: '{{ threescale_cicd_api_name }}' |
|||
deployment_option: '{{ threescale_cicd_api_deployment_type }}' |
|||
system_name: '{{ threescale_cicd_api_system_name }}' |
|||
backend_version: '{{ threescale_cicd_api_backend_version }}' |
|||
# Discover the current state of the platform |
|||
- import_tasks: steps/discover.yml |
|||
|
|||
# Create the service definition |
|||
- import_tasks: create_service.yml |
|||
# Create or update the service definition |
|||
- import_tasks: steps/service.yml |
|||
|
|||
- set_fact: |
|||
threescale_cicd_api_credentials_location: '{{ ''headers'' if threescale_cicd_api_security_scheme.in == ''header'' else threescale_cicd_api_security_scheme.in }}' |
|||
when: 'threescale_cicd_api_security_scheme.type == ''apiKey''' |
|||
# Create or update the methods |
|||
- import_tasks: steps/methods.yml |
|||
|
|||
- set_fact: |
|||
threescale_cicd_api_credentials_location: 'headers' |
|||
when: 'threescale_cicd_api_security_scheme.type == ''oauth2''' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_api_proxy_definition: |
|||
credentials_location: '{{ threescale_cicd_api_credentials_location }}' |
|||
api_backend: '{{ threescale_cicd_private_base_url }}' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_api_proxy_definition: '{{ threescale_cicd_api_proxy_definition|combine({ ''auth_user_key'': threescale_cicd_api_security_scheme.name }) }}' |
|||
when: 'threescale_cicd_api_security_scheme.type == ''apiKey''' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_api_proxy_definition: '{{ threescale_cicd_api_proxy_definition|combine({ ''oidc_issuer_endpoint'': threescale_cicd_sso_issuer_endpoint }) }}' |
|||
when: 'threescale_cicd_api_security_scheme.type == ''oauth2''' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_api_proxy_definition: '{{ threescale_cicd_api_proxy_definition|combine({ ''sandbox_endpoint'': threescale_cicd_apicast_sandbox_endpoint }) }}' |
|||
when: 'threescale_cicd_apicast_sandbox_endpoint is defined' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_api_proxy_definition: '{{ threescale_cicd_api_proxy_definition|combine({ ''endpoint'': threescale_cicd_apicast_production_endpoint }) }}' |
|||
when: 'threescale_cicd_apicast_production_endpoint is defined' |
|||
|
|||
# Update the metrics |
|||
- import_tasks: update_metrics.yml |
|||
|
|||
# Update the mapping rules |
|||
- import_tasks: update_mapping_rules.yml |
|||
# Create, update or delete the mapping rules |
|||
- import_tasks: steps/mapping_rules.yml |
|||
|
|||
# Update the proxy |
|||
- import_tasks: update_proxy.yml |
|||
- import_tasks: steps/proxy.yml |
|||
|
|||
- name: Get the list of existing application plans |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/application_plans.json?access_token={{ threescale_cicd_access_token|urlencode }} |
|||
validate_certs: no |
|||
register: threescale_cicd_tmpresponse |
|||
# Create or update application plans |
|||
- import_tasks: steps/application_plans.yml |
|||
|
|||
- set_fact: |
|||
threescale_cicd_existing_application_plans: '{{ threescale_cicd_tmpresponse.json|json_query(''plans[*].application_plan.system_name'') }}' |
|||
threescale_cicd_existing_application_plans_details: '{{ threescale_cicd_tmpresponse.json|json_query(''plans[].{"system_name": application_plan.system_name, "id": application_plan.id}'') }}' |
|||
|
|||
# Create application plans if needed |
|||
- include_tasks: create_application_plans.yml |
|||
with_items: '{{ threescale_cicd_application_plans|default([]) }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_tmp_plan |
|||
# Create or update the default application if smoke tests are needed |
|||
- include_tasks: steps/default_application.yml |
|||
when: 'threescale_cicd_openapi_smoketest_path is defined and threescale_cicd_application_plans is defined' |
|||
|
|||
# Run smoke tests on the staging gateway |
|||
- include_tasks: smoke_tests.yml |
|||
- include_tasks: steps/smoke_test.yml |
|||
vars: |
|||
threescale_cicd_env: staging |
|||
threescale_cicd_smoke_test_env: staging |
|||
when: 'threescale_cicd_openapi_smoketest_path is defined and threescale_cicd_application_plans is defined' |
|||
|
|||
# Promote to production |
|||
- import_tasks: promote.yml |
|||
- import_tasks: steps/promote.yml |
|||
|
|||
# Run smoke tests on the production gateway |
|||
- include_tasks: smoke_tests.yml |
|||
- include_tasks: steps/smoke_test.yml |
|||
vars: |
|||
threescale_cicd_env: production |
|||
threescale_cicd_smoke_test_env: production |
|||
when: 'threescale_cicd_openapi_smoketest_path is defined and threescale_cicd_application_plans is defined' |
|||
|
|||
# Delete the metrics that are not needed anymore |
|||
- import_tasks: delete_unused_metrics.yml |
|||
- import_tasks: steps/cleanup_metrics.yml |
|||
|
|||
# Publish the OpenAPI Specifications file on the 3scale Admin Portal |
|||
- import_tasks: create_activedocs.yml |
|||
- import_tasks: steps/activedoc.yml |
|||
|
|||
@ -1,65 +0,0 @@ |
|||
--- |
|||
|
|||
- name: Prepare the OAuth Request to RH-SSO (static params) |
|||
set_fact: |
|||
threescale_cicd_tmp_body: "" |
|||
|
|||
- name: Prepare the OAuth Request to RH-SSO (urlencode dynamic params) |
|||
set_fact: |
|||
threescale_cicd_tmp_body: '{{ threescale_cicd_tmp_body ~ "&" ~ threescale_cicd_tmp_param.key ~ "=" ~ (threescale_cicd_tmp_param.value|urlencode) }}' |
|||
with_dict: |
|||
client_id: '{{ threescale_cicd_sso_issuer_endpoint|urlsplit(''username'') }}' |
|||
client_secret: '{{ threescale_cicd_sso_issuer_endpoint|urlsplit(''password'') }}' |
|||
scope: '{{ threescale_cicd_openapi_smoketest_default_scope }}' |
|||
grant_type: client_credentials |
|||
loop_control: |
|||
loop_var: threescale_cicd_tmp_param |
|||
|
|||
- name: Authenticate to RH-SSO using the 3scale service account |
|||
uri: |
|||
url: '{{ threescale_cicd_sso_realm_endpoint }}/protocol/openid-connect/token' |
|||
body: '{{ threescale_cicd_tmp_body }}' |
|||
method: POST |
|||
validate_certs: no |
|||
return_content: yes |
|||
register: threescale_cicd_tmpresponse |
|||
retries: '{{ threescale_cicd_retries }}' |
|||
delay: '{{ threescale_cicd_delay }}' |
|||
# temporary fix for https://github.com/ansible/ansible/issues/28078 |
|||
until: 'threescale_cicd_tmpresponse|success' |
|||
|
|||
- name: Extract the access_token |
|||
set_fact: |
|||
threescale_cicd_openapi_tmp_access_token: '{{ threescale_cicd_tmpresponse.json |json_query("access_token") }}' |
|||
|
|||
- name: Wait for the new client to appear in RH-SSO |
|||
uri: |
|||
url: '{{ threescale_cicd_sso_admin_endpoint }}/clients?clientId={{ threescale_cicd_default_application_appid|urlencode }}' |
|||
method: GET |
|||
validate_certs: no |
|||
return_content: yes |
|||
headers: |
|||
Authorization: 'Bearer {{ threescale_cicd_openapi_tmp_access_token }}' |
|||
register: threescale_cicd_tmpresponse |
|||
retries: '{{ threescale_cicd_retries }}' |
|||
delay: '{{ threescale_cicd_delay }}' |
|||
until: 'threescale_cicd_tmpresponse|success and threescale_cicd_tmpresponse.json|length > 0' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_default_application_sso_id: '{{ threescale_cicd_tmpresponse.json[0].id }}' |
|||
threescale_cicd_tmp_body: '{{ threescale_cicd_tmpresponse.json[0]|combine({ ''serviceAccountsEnabled'': true, ''standardFlowEnabled'': false, ''implicitFlowEnabled'': false, ''directAccessGrantsEnabled'': true }) }}' |
|||
|
|||
- name: Patch the client in RH-SSO to support the "client_credentials" and "password" grant_type. |
|||
uri: |
|||
url: '{{ threescale_cicd_sso_admin_endpoint }}/clients/{{ threescale_cicd_default_application_sso_id|urlencode }}' |
|||
method: PUT |
|||
validate_certs: no |
|||
body: '{{ threescale_cicd_tmp_body|to_json }}' |
|||
status_code: '200,204' |
|||
headers: |
|||
Authorization: 'Bearer {{ threescale_cicd_openapi_tmp_access_token }}' |
|||
Content-Type: 'application/json' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -1,42 +0,0 @@ |
|||
--- |
|||
|
|||
- name: Get the version of the staging proxy definition |
|||
uri: |
|||
url: 'https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/proxy/configs/{{ threescale_cicd_staging_environment_name }}/latest.json?access_token={{ threescale_cicd_access_token|urlencode }}' |
|||
validate_certs: no |
|||
register: threescale_cicd_tmpresponse |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_staging_proxy_version: '{{ threescale_cicd_tmpresponse.json.proxy_config.version }}' |
|||
|
|||
- name: Get the version of the production proxy definition |
|||
uri: |
|||
url: 'https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/proxy/configs/{{ threescale_cicd_production_environment_name }}/latest.json?access_token={{ threescale_cicd_access_token|urlencode }}' |
|||
validate_certs: no |
|||
status_code: 200,404 |
|||
register: threescale_cicd_tmpresponse |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_production_proxy_version: '{{ threescale_cicd_tmpresponse.json.proxy_config.version }}' |
|||
when: 'threescale_cicd_tmpresponse.status == 200' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_production_proxy_version: 'NONE' |
|||
when: 'threescale_cicd_tmpresponse.status == 404' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_body_create_svc: 'access_token={{ threescale_cicd_access_token|urlencode }}&to={{ threescale_cicd_production_environment_name|urlencode }}' |
|||
|
|||
- name: Promote to production |
|||
uri: |
|||
url: 'https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/proxy/configs/{{ threescale_cicd_staging_environment_name }}/{{ threescale_cicd_tmp_staging_proxy_version }}/promote.json' |
|||
body: '{{ threescale_cicd_tmp_body_create_svc }}' |
|||
status_code: 201 |
|||
validate_certs: no |
|||
method: POST |
|||
register: threescale_cicd_tmpresponse |
|||
when: 'threescale_cicd_tmp_staging_proxy_version != threescale_cicd_tmp_production_proxy_version' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -1,188 +0,0 @@ |
|||
--- |
|||
- name: Parse the OpenAPI file (YAML format) |
|||
set_fact: |
|||
threescale_cicd_openapi_file_content: '{{ lookup(''file'', threescale_cicd_openapi_file) |from_yaml }}' |
|||
when: "threescale_cicd_openapi_file_format|upper == 'YAML'" |
|||
|
|||
- name: Parse the OpenAPI file (JSON format) |
|||
set_fact: |
|||
threescale_cicd_openapi_file_content: '{{ lookup(''file'', threescale_cicd_openapi_file) |from_json }}' |
|||
when: "threescale_cicd_openapi_file_format|upper == 'JSON'" |
|||
|
|||
- name: Extract the OpenAPI format version |
|||
set_fact: |
|||
threescale_cicd_openapi_file_version: '{{ threescale_cicd_openapi_file_content|json_query(''swagger'') }}' |
|||
|
|||
- name: Check the OpenAPI format version |
|||
assert: |
|||
that: |
|||
- "threescale_cicd_openapi_file_version == '2.0'" |
|||
msg: "Currently only the OpenAPI/Swagger 2.0 is handled. If needed, fill an issue or submit a pull request!" |
|||
|
|||
# TODO rewrite this in a more "Ansible compatible" way |
|||
- name: Extract API Methods |
|||
set_fact: |
|||
threescale_cicd_api_name: '{{ threescale_cicd_openapi_file_content.info.title|default("API") }}' |
|||
threescale_cicd_api_description: '{{ threescale_cicd_openapi_file_content.info.description|default("") }}' |
|||
threescale_cicd_api_version: '{{ threescale_cicd_openapi_file_content.info.version|default("0.0.1") }}' |
|||
threescale_cicd_api_basepath: '{{ threescale_cicd_openapi_file_content.basePath|default("") }}' |
|||
threescale_cicd_api_operations: >- |
|||
{% set operations = {} -%} |
|||
{% if 'paths' in threescale_cicd_openapi_file_content -%} |
|||
{% for path, verbs in threescale_cicd_openapi_file_content['paths'].items() -%} |
|||
{% if path.startswith('/') -%} |
|||
{% for verb, method_description in verbs.items() -%} |
|||
{% if verb != '$ref' and verb != 'parameters' -%} |
|||
{% if 'operationId' in method_description -%} |
|||
{% set operation_id = method_description['operationId'] -%} |
|||
{% else -%} |
|||
{% set operation_id = verb.upper() + path -%} |
|||
{% endif -%} |
|||
{% set operation_id = operation_id|regex_replace('[^0-9a-zA-Z_]+', '_') -%} |
|||
{% set operation = { operation_id: { 'path': path, 'verb': verb } } -%} |
|||
{% if 'summary' in method_description -%} |
|||
{% if operation[operation_id].update({ 'friendly_name': method_description.summary }) -%}{% endif -%} |
|||
{% endif -%} |
|||
{% if 'description' in method_description -%} |
|||
{% if operation[operation_id].update({ 'description': method_description.description }) -%}{% endif -%} |
|||
{% endif -%} |
|||
{% if operations.update(operation) -%}{% endif -%} |
|||
{% endif -%} |
|||
{% endfor -%} |
|||
{% endif -%} |
|||
{% endfor -%} |
|||
{% endif -%} |
|||
{{ operations }} |
|||
|
|||
- name: Extract components from the version number |
|||
set_fact: |
|||
threescale_cicd_api_version_components: '{{ threescale_cicd_api_version.split(".") }}' |
|||
|
|||
- name: Find the major version |
|||
set_fact: |
|||
threescale_cicd_api_version_major: '{{ threescale_cicd_api_version_components|first }}' |
|||
|
|||
- name: Compute the system_name suffix to append to the generated system_name |
|||
set_fact: |
|||
threescale_cicd_api_system_name_suffix: '{{ (threescale_cicd_api_system_name is not defined)|ternary("_" ~ (threescale_cicd_api_version_major|regex_replace(''[^a-zA-Z0-9_]+'', ''_'')), "") }}' |
|||
|
|||
- name: Compute the system_name prefix to prepend to the generated system_name |
|||
set_fact: |
|||
threescale_cicd_api_system_name_prefix: '{{ (threescale_cicd_api_system_name is not defined and threescale_cicd_api_environment_name is defined)|ternary((threescale_cicd_api_environment_name|default("")|regex_replace(''[^a-zA-Z0-9_]+'', ''_'')) ~ "_", "") }}' |
|||
|
|||
- name: Extract the wanted system_name from OpenAPI |
|||
set_fact: |
|||
threescale_cicd_api_system_name: '{{ threescale_cicd_openapi_file_content.info[''x-threescale-system-name'']|regex_replace(''[^a-zA-Z0-9_]+'', ''_'')|lower }}' |
|||
when: 'threescale_cicd_api_system_name is not defined and ''x-threescale-system-name'' in threescale_cicd_openapi_file_content.info' |
|||
|
|||
- name: Generate a system_name from the API title |
|||
set_fact: |
|||
threescale_cicd_api_system_name: '{{ threescale_cicd_openapi_file_content.info[''title'']|default(''api'')|regex_replace(''[^a-zA-Z0-9_]+'', ''_'')|lower }}' |
|||
when: 'threescale_cicd_api_system_name is not defined' |
|||
|
|||
- name: Append the major version to the system_name |
|||
set_fact: |
|||
threescale_cicd_api_system_name: '{{ threescale_cicd_api_system_name }}{{ threescale_cicd_api_system_name_suffix }}' |
|||
|
|||
- name: Set the threescale_cicd_apicast_{sandbox,production}_endpoint variable from the wildcard domain |
|||
set_fact: |
|||
threescale_cicd_apicast_sandbox_endpoint: '{{ threescale_cicd_default_apicast_scheme }}://{{ threescale_cicd_api_system_name|regex_replace(''[^a-zA-Z0-9-]+'', ''-'')|lower }}{{ threescale_cicd_default_staging_suffix }}.{{ threescale_cicd_wildcard_domain }}' |
|||
threescale_cicd_apicast_production_endpoint: '{{ threescale_cicd_default_apicast_scheme }}://{{ threescale_cicd_api_system_name|regex_replace(''[^a-zA-Z0-9-]+'', ''-'')|lower }}{{ threescale_cicd_default_production_suffix }}.{{ threescale_cicd_wildcard_domain }}' |
|||
when: 'threescale_cicd_wildcard_domain is defined' |
|||
|
|||
- name: Prefix the system_name with the environment |
|||
set_fact: |
|||
threescale_cicd_api_system_name: '{{ threescale_cicd_api_system_name_prefix }}{{ threescale_cicd_api_system_name }}' |
|||
|
|||
- name: Append the full version to the API title |
|||
set_fact: |
|||
threescale_cicd_api_name: '{{ threescale_cicd_api_name }} (v{{ threescale_cicd_api_version }})' |
|||
when: 'threescale_cicd_api_environment_name is not defined' |
|||
|
|||
- name: Append the full version and the environment to the API title |
|||
set_fact: |
|||
threescale_cicd_api_name: '{{ threescale_cicd_api_name }} ({{ threescale_cicd_api_environment_name|upper }}, v{{ threescale_cicd_api_version }})' |
|||
when: 'threescale_cicd_api_environment_name is defined' |
|||
|
|||
- name: Extract the security definitions and requirements from OpenAPI |
|||
set_fact: |
|||
threescale_cicd_api_security_requirements: '{{ threescale_cicd_openapi_file_content.security|default([]) }}' |
|||
threescale_cicd_api_security_definitions: '{{ threescale_cicd_openapi_file_content.securityDefinitions|default({}) }}' |
|||
|
|||
- name: Make sure there is one and exactly one security requirement |
|||
assert: |
|||
that: |
|||
- 'threescale_cicd_api_security_requirements|length == 1' |
|||
msg: 'You have {{ threescale_cicd_api_security_requirements|length }} global security requirements. There must be one and only one security requirement.' |
|||
|
|||
- name: Find the security requirement to use |
|||
set_fact: |
|||
threescale_cicd_api_security_scheme_name: '{{ threescale_cicd_api_security_requirements[0].keys()[0] }}' |
|||
|
|||
- name: Make sure the requested security definition exists |
|||
assert: |
|||
that: |
|||
- 'threescale_cicd_api_security_scheme_name in threescale_cicd_api_security_definitions' |
|||
|
|||
- name: Find the security definition to use |
|||
set_fact: |
|||
threescale_cicd_api_security_scheme: '{{ threescale_cicd_api_security_definitions[threescale_cicd_api_security_scheme_name] }}' |
|||
|
|||
- name: Make sure the security scheme is consistent with 3scale |
|||
assert: |
|||
that: |
|||
- 'threescale_cicd_api_security_scheme.type == ''apiKey'' or (threescale_cicd_api_security_scheme.type == ''oauth2'' and threescale_cicd_sso_issuer_endpoint is defined)' |
|||
|
|||
- name: Find the correct backend_version to use |
|||
set_fact: |
|||
threescale_cicd_api_backend_version: '1' |
|||
when: 'threescale_cicd_api_security_scheme.type == ''apiKey''' |
|||
|
|||
- name: Find the correct backend_version to use |
|||
set_fact: |
|||
threescale_cicd_api_backend_version: 'oidc' |
|||
when: 'threescale_cicd_api_security_scheme.type == ''oauth2''' |
|||
|
|||
- name: Extract the backend hostname from OpenAPI |
|||
set_fact: |
|||
threescale_cicd_api_backend_hostname: '{{ threescale_cicd_openapi_file_content.host }}' |
|||
when: 'threescale_cicd_api_backend_hostname is not defined and ''host'' in threescale_cicd_openapi_file_content' |
|||
|
|||
- name: Extract the backend scheme from OpenAPI |
|||
set_fact: |
|||
threescale_cicd_api_backend_scheme: '{{ threescale_cicd_openapi_file_content.schemes|default(["http"])|first }}' |
|||
when: 'threescale_cicd_api_backend_scheme is not defined' |
|||
|
|||
- name: Compute the private base url from the OpenAPI file |
|||
set_fact: |
|||
threescale_cicd_private_base_url: '{{ threescale_cicd_api_backend_scheme ~ ''://'' ~ threescale_cicd_api_backend_hostname }}' |
|||
when: threescale_cicd_api_backend_hostname is defined and threescale_cicd_private_base_url is not defined |
|||
|
|||
- assert: |
|||
that: |
|||
- 'threescale_cicd_private_base_url is defined' |
|||
msg: 'Either the private base url or the tuple backend hostname/scheme must be declared as extra variables (either threescale_cicd_private_base_url or threescale_cicd_api_backend_scheme / threescale_cicd_api_backend_hostname)' |
|||
|
|||
- name: Find the smoke-test flagged operation |
|||
set_fact: |
|||
threescale_cicd_openapi_smoketest_operation: '{{ threescale_cicd_openapi_file_content|json_query(''paths.*.get[? "x-threescale-smoketests-operation" ].operationId|[0]'') }}' |
|||
when: 'threescale_cicd_openapi_smoketest_operation is not defined' |
|||
|
|||
- assert: |
|||
that: |
|||
# Operation must exists |
|||
- 'threescale_cicd_openapi_smoketest_operation in threescale_cicd_api_operations' |
|||
# Must be a GET |
|||
- 'threescale_cicd_api_operations[threescale_cicd_openapi_smoketest_operation].verb == ''get''' |
|||
# Must NOT have a placeholder in the path |
|||
- 'threescale_cicd_api_operations[threescale_cicd_openapi_smoketest_operation].path.find("{") == -1' |
|||
msg: "The smoketest operation {{ threescale_cicd_openapi_smoketest_operation }} must be a GET and cannot have a placeholder in its path." |
|||
when: 'threescale_cicd_openapi_smoketest_operation is defined and threescale_cicd_openapi_smoketest_operation|length > 0' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_openapi_smoketest_operation: '{{ threescale_cicd_openapi_smoketest_operation|regex_replace(''[^0-9a-zA-Z_]+'', ''_'') }}' |
|||
when: 'threescale_cicd_openapi_smoketest_operation is defined and threescale_cicd_openapi_smoketest_operation|length > 0' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_openapi_smoketest_path: '{{ threescale_cicd_api_basepath }}{{ threescale_cicd_api_operations[threescale_cicd_openapi_smoketest_operation].path }}' |
|||
when: 'threescale_cicd_openapi_smoketest_operation is defined and threescale_cicd_openapi_smoketest_operation|length > 0' |
|||
@ -1,59 +0,0 @@ |
|||
--- |
|||
|
|||
- import_tasks: create_default_application.yml |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_gateway_endpoint: "" |
|||
|
|||
- name: Try to get the staging gateway url from extra var / inventory |
|||
set_fact: |
|||
threescale_cicd_tmp_gateway_endpoint: '{{ threescale_cicd_apicast_sandbox_endpoint }}' |
|||
when: "threescale_cicd_apicast_sandbox_endpoint is defined and threescale_cicd_env == 'staging'" |
|||
|
|||
- name: Try to get the production gateway url from extra var / inventory |
|||
set_fact: |
|||
threescale_cicd_tmp_gateway_endpoint: '{{ threescale_cicd_apicast_production_endpoint }}' |
|||
when: "threescale_cicd_apicast_production_endpoint is defined and threescale_cicd_env == 'production'" |
|||
|
|||
- name: Get the gateway endpoint from the proxy definition |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/proxy.json?access_token={{ threescale_cicd_access_token|urlencode }} |
|||
validate_certs: no |
|||
method: GET |
|||
register: threescale_cicd_tmpresponse |
|||
when: "threescale_cicd_tmp_gateway_endpoint|length == 0" |
|||
|
|||
- name: Extract the staging gateway endpoint from the proxy definition |
|||
set_fact: |
|||
threescale_cicd_tmp_gateway_endpoint: '{{ threescale_cicd_tmpresponse.json|json_query(''proxy.sandbox_endpoint'') }}' |
|||
when: "threescale_cicd_tmp_gateway_endpoint|length == 0 and threescale_cicd_env == 'staging'" |
|||
|
|||
- name: Extract the production gateway endpoint from the proxy definition |
|||
set_fact: |
|||
threescale_cicd_tmp_gateway_endpoint: '{{ threescale_cicd_tmpresponse.json|json_query(''proxy.endpoint'') }}' |
|||
when: "threescale_cicd_tmp_gateway_endpoint|length == 0 and threescale_cicd_env == 'production'" |
|||
|
|||
- set_fact: |
|||
threescale_cicd_openapi_smoketest_querystring: "" |
|||
threescale_cicd_openapi_smoketest_headers: {} |
|||
|
|||
- include_tasks: smoke_tests_apikey.yml |
|||
when: 'threescale_cicd_api_security_scheme.type == ''apiKey''' |
|||
|
|||
- include_tasks: smoke_tests_oauth.yml |
|||
when: 'threescale_cicd_api_security_scheme.type == ''oauth2''' |
|||
|
|||
- debug: |
|||
msg: "Starting a smoke test on '{{ threescale_cicd_tmp_gateway_endpoint }}{{ threescale_cicd_openapi_smoketest_path }}'..." |
|||
|
|||
- name: Running smoke tests ! |
|||
uri: |
|||
url: '{{ threescale_cicd_tmp_gateway_endpoint }}{{ threescale_cicd_openapi_smoketest_path }}{{ threescale_cicd_openapi_smoketest_querystring }}' |
|||
headers: '{{ threescale_cicd_openapi_smoketest_headers }}' |
|||
validate_certs: no |
|||
method: GET |
|||
register: threescale_cicd_tmpresponse |
|||
retries: '{{ threescale_cicd_retries }}' |
|||
delay: '{{ threescale_cicd_delay }}' |
|||
# temporary fix for https://github.com/ansible/ansible/issues/28078 |
|||
until: 'threescale_cicd_tmpresponse|success' |
|||
@ -1,9 +0,0 @@ |
|||
--- |
|||
|
|||
- set_fact: |
|||
threescale_cicd_openapi_smoketest_querystring: "?{{ threescale_cicd_api_security_scheme.name|urlencode }}={{ threescale_cicd_default_application_details.user_key }}" |
|||
when: 'threescale_cicd_api_credentials_location == "query"' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_openapi_smoketest_headers: "{{ threescale_cicd_openapi_smoketest_headers|combine({ threescale_cicd_api_security_scheme.name|urlencode: threescale_cicd_default_application_details.user_key}) }}" |
|||
when: 'threescale_cicd_api_credentials_location == "headers"' |
|||
@ -1,36 +0,0 @@ |
|||
--- |
|||
|
|||
- name: Prepare the OAuth Request to RH-SSO (static params) |
|||
set_fact: |
|||
threescale_cicd_tmp_body: "" |
|||
|
|||
- name: Prepare the OAuth Request to RH-SSO (urlencode dynamic params) |
|||
set_fact: |
|||
threescale_cicd_tmp_body: '{{ threescale_cicd_tmp_body ~ "&" ~ threescale_cicd_tmp_param.key ~ "=" ~ (threescale_cicd_tmp_param.value|urlencode) }}' |
|||
with_dict: |
|||
client_id: '{{ threescale_cicd_default_application_details.client_id }}' |
|||
client_secret: '{{ threescale_cicd_default_application_details.client_secret }}' |
|||
scope: '{{ threescale_cicd_openapi_smoketest_default_scope }}' |
|||
grant_type: client_credentials |
|||
loop_control: |
|||
loop_var: threescale_cicd_tmp_param |
|||
|
|||
- name: Authenticate to RH-SSO using the default application credentials |
|||
uri: |
|||
url: '{{ threescale_cicd_sso_realm_endpoint }}/protocol/openid-connect/token' |
|||
body: '{{ threescale_cicd_tmp_body }}' |
|||
method: POST |
|||
validate_certs: no |
|||
return_content: yes |
|||
register: threescale_cicd_tmpresponse |
|||
retries: '{{ threescale_cicd_retries }}' |
|||
delay: '{{ threescale_cicd_delay }}' |
|||
# temporary fix for https://github.com/ansible/ansible/issues/28078 |
|||
until: 'threescale_cicd_tmpresponse|success' |
|||
|
|||
- name: Extract the access_token |
|||
set_fact: |
|||
threescale_cicd_openapi_smoketest_access_token: '{{ threescale_cicd_tmpresponse.json |json_query("access_token") }}' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_openapi_smoketest_headers: "{{ threescale_cicd_openapi_smoketest_headers|combine({ 'Authorization': 'Bearer ' ~ threescale_cicd_openapi_smoketest_access_token }) }}" |
|||
@ -0,0 +1,10 @@ |
|||
--- |
|||
- debug: |
|||
var: threescale_cicd_openapi_rewritten |
|||
verbosity: 1 |
|||
|
|||
- include_tasks: api-calls/update_activedoc.yml |
|||
when: 'threescale_cicd_api_system_name in threescale_cicd_existing_activedocs' |
|||
|
|||
- include_tasks: api-calls/create_activedoc.yml |
|||
when: 'threescale_cicd_api_system_name not in threescale_cicd_existing_activedocs' |
|||
@ -0,0 +1,8 @@ |
|||
--- |
|||
|
|||
- include_tasks: api-calls/update_application_plan.yml |
|||
when: 'threescale_cicd_application_plan.system_name in threescale_cicd_existing_application_plans' |
|||
|
|||
- include_tasks: api-calls/create_application_plan.yml |
|||
when: 'threescale_cicd_application_plan.system_name not in threescale_cicd_existing_application_plans' |
|||
|
|||
@ -0,0 +1,6 @@ |
|||
--- |
|||
|
|||
- include_tasks: steps/application_plan.yml |
|||
with_items: '{{ threescale_cicd_application_plans|default([]) }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_application_plan |
|||
@ -0,0 +1,6 @@ |
|||
--- |
|||
|
|||
- include_tasks: "api-calls/delete_metric.yml" |
|||
with_items: '{{ threescale_cicd_metrics_to_delete }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_metric |
|||
@ -0,0 +1,32 @@ |
|||
--- |
|||
|
|||
- import_tasks: "api-calls/find_first_account.yml" |
|||
when: 'threescale_cicd_default_account_id is not defined' |
|||
|
|||
- import_tasks: "api-calls/find_application.yml" |
|||
|
|||
- import_tasks: "api-calls/update_application.yml" |
|||
when: 'threescale_cicd_default_application_id is defined' |
|||
|
|||
- import_tasks: "api-calls/create_application.yml" |
|||
when: 'threescale_cicd_default_application_id is not defined' |
|||
|
|||
## |
|||
## When using OAuth / OIDC authentication, we need to patch the Keycloak client |
|||
## to support the client_credentials grant. |
|||
## |
|||
|
|||
- include_tasks: api-calls/keycloak/authenticate.yml |
|||
when: 'threescale_cicd_api_security_scheme.type == ''oauth2''' |
|||
vars: |
|||
oauth_payload: |
|||
client_id: '{{ threescale_cicd_sso_issuer_endpoint|urlsplit(''username'') }}' |
|||
client_secret: '{{ threescale_cicd_sso_issuer_endpoint|urlsplit(''password'') }}' |
|||
scope: '{{ threescale_cicd_openapi_smoketest_default_scope }}' |
|||
grant_type: 'client_credentials' |
|||
|
|||
- include_tasks: api-calls/keycloak/wait_for_client.yml |
|||
when: 'threescale_cicd_api_security_scheme.type == ''oauth2''' |
|||
|
|||
- include_tasks: api-calls/keycloak/patch_client.yml |
|||
when: 'threescale_cicd_api_security_scheme.type == ''oauth2''' |
|||
@ -0,0 +1,59 @@ |
|||
--- |
|||
|
|||
- name: Retrieve existing Services from the 3scale Admin Portal |
|||
uri: |
|||
url: "https://{{ inventory_hostname }}/admin/api/services.json?access_token={{ threescale_cicd_access_token|urlencode }}" |
|||
validate_certs: no |
|||
register: threescale_cicd_tmpresponse |
|||
when: threescale_cicd_existing_services is not defined |
|||
|
|||
- set_fact: |
|||
threescale_cicd_existing_services: '{{ threescale_cicd_tmpresponse.json|json_query(''services[*].service.system_name'') }}' |
|||
threescale_cicd_existing_services_details: '{{ threescale_cicd_tmpresponse.json|json_query(''services[].{"system_name": service.system_name, "id": service.id}'') }}' |
|||
cacheable: true |
|||
when: threescale_cicd_existing_services is not defined |
|||
|
|||
- debug: |
|||
msg: "Found {{ threescale_cicd_existing_services|length }} services" |
|||
verbosity: 1 |
|||
|
|||
- debug: |
|||
var: threescale_cicd_existing_services_details |
|||
verbosity: 1 |
|||
|
|||
- name: Get the list of existing application plans |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/application_plans.json?access_token={{ threescale_cicd_access_token|urlencode }} |
|||
validate_certs: no |
|||
register: threescale_cicd_tmpresponse |
|||
when: threescale_cicd_api_system_name in threescale_cicd_existing_services |
|||
|
|||
- set_fact: |
|||
threescale_cicd_existing_application_plans: '{{ threescale_cicd_tmpresponse.json|json_query(''plans[*].application_plan.system_name'') if threescale_cicd_api_system_name in threescale_cicd_existing_services else [] }}' |
|||
threescale_cicd_existing_application_plans_details: '{{ threescale_cicd_tmpresponse.json|json_query(''plans[].{"system_name": application_plan.system_name, "id": application_plan.id}'') if threescale_cicd_api_system_name in threescale_cicd_existing_services else [] }}' |
|||
|
|||
- debug: |
|||
msg: "Found {{ threescale_cicd_existing_application_plans|length }} application plans" |
|||
verbosity: 1 |
|||
|
|||
- debug: |
|||
var: threescale_cicd_existing_application_plans_details |
|||
verbosity: 1 |
|||
|
|||
- name: Retrieve existing ActiveDocs from the 3scale Admin Portal |
|||
uri: |
|||
url: "https://{{ inventory_hostname }}/admin/api/active_docs.json?access_token={{ threescale_cicd_access_token|urlencode }}" |
|||
validate_certs: no |
|||
register: threescale_cicd_tmp_allactivedocs |
|||
|
|||
- set_fact: |
|||
threescale_cicd_existing_activedocs: '{{ threescale_cicd_tmp_allactivedocs.json|json_query(''api_docs[*].api_doc.system_name'') }}' |
|||
threescale_cicd_existing_activedocs_details: '{{ threescale_cicd_tmp_allactivedocs.json|json_query(''api_docs[].{"system_name": api_doc.system_name, "id": api_doc.id}'') }}' |
|||
|
|||
- debug: |
|||
msg: "Found {{ threescale_cicd_existing_activedocs|length }} active docs" |
|||
verbosity: 1 |
|||
|
|||
- debug: |
|||
var: threescale_cicd_existing_activedocs_details |
|||
verbosity: 1 |
|||
@ -0,0 +1,25 @@ |
|||
--- |
|||
|
|||
- name: Retrieve existing mapping rules from the 3scale Admin Portal |
|||
uri: |
|||
url: "https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/proxy/mapping_rules.json?access_token={{ threescale_cicd_access_token|urlencode }}" |
|||
validate_certs: no |
|||
register: threescale_cicd_tmpresponse |
|||
|
|||
- set_fact: |
|||
threescale_cicd_existing_mapping_rules_details: '{{ threescale_cicd_tmpresponse.json|json_query(''mapping_rules[].{"metric_id": mapping_rule.metric_id, "id": mapping_rule.id}'') }}' |
|||
|
|||
- include_tasks: "api-calls/create_mapping_rule.yml" |
|||
with_items: '{{ threescale_cicd_mapping_rules_to_create }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_mapping_rule |
|||
|
|||
- include_tasks: "api-calls/update_mapping_rule.yml" |
|||
with_items: '{{ threescale_cicd_mapping_rules_to_update }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_mapping_rule |
|||
|
|||
- include_tasks: "api-calls/delete_mapping_rule.yml" |
|||
with_items: '{{ threescale_cicd_mapping_rules_to_delete }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_mapping_rule |
|||
@ -0,0 +1,7 @@ |
|||
--- |
|||
|
|||
- include_tasks: api-calls/update_method.yml |
|||
when: 'threescale_cicd_api_operation.key in threescale_cicd_existing_metrics' |
|||
|
|||
- include_tasks: api-calls/create_method.yml |
|||
when: 'threescale_cicd_api_operation.key not in threescale_cicd_existing_metrics' |
|||
@ -0,0 +1,16 @@ |
|||
--- |
|||
|
|||
- name: Retrieve existing metrics from the 3scale Admin Portal |
|||
uri: |
|||
url: "https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/metrics.json?access_token={{ threescale_cicd_access_token|urlencode }}" |
|||
validate_certs: no |
|||
register: threescale_cicd_tmpresponse |
|||
|
|||
- set_fact: |
|||
threescale_cicd_existing_metrics: '{{ threescale_cicd_tmpresponse.json|json_query(''metrics[*].metric.system_name'') }}' |
|||
threescale_cicd_existing_metrics_details: '{{ threescale_cicd_tmpresponse.json|json_query(''metrics[].{"system_name": metric.system_name, "id": metric.id}'') }}' |
|||
|
|||
- include_tasks: "steps/method.yml" |
|||
with_dict: '{{ threescale_cicd_api_operations }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_api_operation |
|||
@ -0,0 +1,6 @@ |
|||
--- |
|||
|
|||
- import_tasks: "api-calls/get_proxy_version.yml" |
|||
|
|||
- include_tasks: "api-calls/promote_proxy.yml" |
|||
when: 'threescale_cicd_staging_proxy_version != threescale_cicd_production_proxy_version' |
|||
@ -0,0 +1,3 @@ |
|||
--- |
|||
|
|||
- import_tasks: api-calls/update_proxy.yml |
|||
@ -0,0 +1,42 @@ |
|||
--- |
|||
|
|||
- name: Check the OpenAPI format version |
|||
assert: |
|||
that: |
|||
- "threescale_cicd_openapi_file_version == '2.0'" |
|||
msg: "Currently only the OpenAPI/Swagger 2.0 is handled. If needed, fill an issue or submit a pull request!" |
|||
|
|||
- name: Make sure there is one and exactly one security requirement |
|||
assert: |
|||
that: |
|||
- 'threescale_cicd_api_security_requirements|length == 1' |
|||
msg: 'You have {{ threescale_cicd_api_security_requirements|length }} global security requirements. There must be one and only one security requirement.' |
|||
|
|||
- name: Make sure the security scheme is consistent with 3scale |
|||
assert: |
|||
that: |
|||
- '''type'' in threescale_cicd_api_security_scheme and threescale_cicd_api_security_scheme.type == ''apiKey'' or (threescale_cicd_api_security_scheme.type == ''oauth2'' and threescale_cicd_sso_issuer_endpoint is defined)' |
|||
msg: |- |
|||
The embedded security definition {{ threescale_cicd_api_security_scheme_name }} is not compatible with 3scale. |
|||
Please make sure you chose an "apiKey" or "oauth2" scheme. |
|||
Also, if you chose "oauth2", you will need to pass the threescale_cicd_sso_issuer_endpoint extra variable. |
|||
The security definition you chose: {{ threescale_cicd_api_security_scheme|to_nice_json }} |
|||
|
|||
- assert: |
|||
that: |
|||
- 'threescale_cicd_private_base_url is defined' |
|||
msg: 'Either the private base url or the tuple backend hostname/scheme must be declared as extra variables (either threescale_cicd_private_base_url or threescale_cicd_api_backend_scheme / threescale_cicd_api_backend_hostname)' |
|||
|
|||
- assert: |
|||
that: |
|||
# Operation must exists |
|||
- 'threescale_cicd_openapi_smoketest_operation in threescale_cicd_api_operations' |
|||
# Must be a GET |
|||
- 'threescale_cicd_api_operations[threescale_cicd_openapi_smoketest_operation].verb == ''get''' |
|||
# Must NOT have a placeholder in the path |
|||
- 'threescale_cicd_api_operations[threescale_cicd_openapi_smoketest_operation].path.find("{") == -1' |
|||
msg: "The smoketest operation {{ threescale_cicd_openapi_smoketest_operation }} must be a GET and cannot have a placeholder in its path." |
|||
when: 'threescale_cicd_openapi_smoketest_operation|length > 0' |
|||
|
|||
- debug: |
|||
msg: "Will work on service with system_name = {{ threescale_cicd_api_system_name }}" |
|||
@ -0,0 +1,64 @@ |
|||
--- |
|||
|
|||
- name: Ensure pre-requisites are met |
|||
assert: |
|||
that: |
|||
- "threescale_cicd_access_token is defined" |
|||
- "threescale_cicd_openapi_file is defined" |
|||
msg: |- |
|||
This module requires at least two variables: |
|||
- threescale_cicd_access_token that contains an Access Token with Read/Write privileges on the 3scale Account Management API. This variable is usually set in your inventory file. |
|||
- threescale_cicd_openapi_file that is the path to the OpenAPI file you want to deploy in 3scale. This variable is usually passed as an extra variable (-e threescale_cicd_openapi_file=...) |
|||
|
|||
- name: Make sure the OpenAPI File Format is YAML or JSON |
|||
assert: |
|||
that: |
|||
- threescale_cicd_openapi_file_format|upper == 'JSON' or threescale_cicd_openapi_file_format|upper == 'YAML' |
|||
msg: |- |
|||
The threescale_cicd_openapi_file_format parameter needs to be either 'JSON' or 'YAML' |
|||
|
|||
- name: Verify that Ansible version is >= 2.4 |
|||
assert: |
|||
that: "ansible_version.full is version_compare('2.4', '>=')" |
|||
msg: This module requires at least Ansible 2.4 |
|||
|
|||
- name: Check if jmespath is installed locally |
|||
debug: msg={{dummy|json_query('@')}} |
|||
register: check_jmespath |
|||
ignore_errors: yes |
|||
vars: |
|||
dummy: Hello World |
|||
|
|||
- name: Check if jinja 2.8 is installed locally |
|||
debug: msg={{(dummy|selectattr("id", "equalto", "hello")|first)['value']}} |
|||
vars: |
|||
dummy: |
|||
- id: hello |
|||
value: Hello World |
|||
register: check_jinja28 |
|||
ignore_errors: yes |
|||
|
|||
- name: Check if the "do" jinja extension is enabled |
|||
debug: msg={% do {}.update({}) %}{{ success }} |
|||
vars: |
|||
success: 'The do extension is enabled' |
|||
register: check_jinja_do_ext |
|||
ignore_errors: yes |
|||
|
|||
- assert: |
|||
that: |
|||
- 'check_jmespath is success' |
|||
msg: "The JMESPath library is required by this role. Please install the JMESPath library with 'pip install jmespath'." |
|||
|
|||
- assert: |
|||
that: |
|||
- 'check_jinja28 is success' |
|||
msg: "At least Jinja v2.8 is required by this role. Please update Jinja with 'pip install -U Jinja2'." |
|||
|
|||
- assert: |
|||
that: |
|||
- 'check_jinja_do_ext is success' |
|||
msg: |- |
|||
You need to enable the 'do' extension of Jinja in your ansible.cfg: |
|||
[default] |
|||
jinja2_extensions = jinja2.ext.do |
|||
@ -0,0 +1,7 @@ |
|||
--- |
|||
|
|||
- include_tasks: api-calls/update_service.yml |
|||
when: 'threescale_cicd_api_system_name in threescale_cicd_existing_services' |
|||
|
|||
- include_tasks: api-calls/create_service.yml |
|||
when: 'threescale_cicd_api_system_name not in threescale_cicd_existing_services' |
|||
@ -0,0 +1,14 @@ |
|||
--- |
|||
|
|||
# Retrieve a valid access token if the API is secured with OAuth/OIDC |
|||
- include_tasks: api-calls/keycloak/authenticate.yml |
|||
when: 'threescale_cicd_api_security_scheme.type == ''oauth2''' |
|||
vars: |
|||
oauth_payload: |
|||
client_id: '{{ threescale_cicd_default_application_details.client_id }}' |
|||
client_secret: '{{ threescale_cicd_default_application_details.client_secret }}' |
|||
scope: '{{ threescale_cicd_openapi_smoketest_default_scope }}' |
|||
grant_type: 'client_credentials' |
|||
|
|||
# Do the smoke test |
|||
- import_tasks: api-calls/smoke_test.yml |
|||
@ -0,0 +1,28 @@ |
|||
--- |
|||
|
|||
- name: Abort on deprecated feature -> the "sso" inventory group |
|||
fail: |
|||
msg: > |
|||
You are currently using a deprecated feature (the 'sso' group in your inventory). |
|||
Please replace it with the 'threescale_cicd_sso_issuer_endpoint' variable. |
|||
Alternatively, you can also bypass this warning by setting the 'threescale_cicd_deprecated_features' |
|||
extra variable to 'true'. |
|||
when: 'threescale_cicd_sso_issuer_endpoint|default("")|length > 0 and ''sso'' in groups and groups[''sso''] > 0 and threescale_cicd_api_backend_version == ''oidc'' and not threescale_cicd_deprecated_features|default(false)|bool' |
|||
|
|||
- name: Abort on deprecated feature -> the "apicast-sandbox" inventory group |
|||
fail: |
|||
msg: > |
|||
You are currently using a deprecated feature (the 'apicast-sandbox' group in your inventory). |
|||
Please replace it with the 'threescale_cicd_apicast_sandbox_endpoint' variable. |
|||
Alternatively, you can also bypass this warning by setting the 'threescale_cicd_deprecated_features' |
|||
extra variable to 'true'. |
|||
when: 'threescale_cicd_apicast_sandbox_endpoint|default("")|length > 0 and ''apicast-sandbox'' in groups and groups[''apicast-sandbox''] > 0 and not threescale_cicd_deprecated_features|default(false)|bool' |
|||
|
|||
- name: Abort on deprecated feature -> the "apicast-production" inventory group |
|||
fail: |
|||
msg: > |
|||
You are currently using a deprecated feature (the 'apicast-production' group in your inventory). |
|||
Please replace it with the 'threescale_cicd_apicast_production_endpoint' variable. |
|||
Alternatively, you can also bypass this warning by setting the 'threescale_cicd_deprecated_features' |
|||
extra variable to 'true'. |
|||
when: 'threescale_cicd_apicast_production_endpoint|default("")|length > 0 and ''apicast-production'' in groups and groups[''apicast-production''] > 0 and not threescale_cicd_deprecated_features|default(false)|bool' |
|||
@ -1,30 +0,0 @@ |
|||
--- |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_body_update_method: '{{ "access_token=" ~ threescale_cicd_access_token|urlencode }}' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_body_update_method: '{{ threescale_cicd_tmp_body_update_method ~ "&" ~ (threescale_cicd_tmp_param.key|urlencode) ~ "=" ~ (threescale_cicd_tmp_param.value|urlencode) }}' |
|||
with_dict: '{{ threescale_cicd_tmp_wanted_mapping_rules[threescale_cicd_tmp_mapping_rule_to_update] }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_tmp_param |
|||
|
|||
- set_fact: |
|||
# Add the metric_id to the payload |
|||
threescale_cicd_tmp_body_update_method: '{{ threescale_cicd_tmp_body_update_method ~ "&" ~ "metric_id=" ~ ((threescale_cicd_existing_metrics_details|selectattr("system_name", "equalto", threescale_cicd_tmp_mapping_rule_to_update)|first).id|urlencode) }}' |
|||
# The ID of the mapping rule to update |
|||
threescale_cicd_tmp_mapping_rule_id: '{{ threescale_cicd_tmp_existing_mapping_rules[threescale_cicd_tmp_mapping_rule_to_update] }}' |
|||
|
|||
- name: Update the mapping rule |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/proxy/mapping_rules/{{ threescale_cicd_tmp_mapping_rule_id }}.json |
|||
validate_certs: no |
|||
method: PUT |
|||
body: '{{ threescale_cicd_tmp_body_update_method }}' |
|||
status_code: 200 |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 200' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -1,59 +0,0 @@ |
|||
--- |
|||
|
|||
- name: Retrieve existing mapping rules from the 3scale Admin Portal |
|||
uri: |
|||
url: "https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/proxy/mapping_rules.json?access_token={{ threescale_cicd_access_token|urlencode }}" |
|||
validate_certs: no |
|||
register: threescale_cicd_tmp_allmappingrules |
|||
|
|||
- set_fact: |
|||
threescale_cicd_existing_mappingrules_details: '{{ threescale_cicd_tmp_allmappingrules.json|json_query(''mapping_rules[].{"metric_id": mapping_rule.metric_id, "id": mapping_rule.id}'') }}' |
|||
threescale_cicd_tmp_wanted_mapping_rules: {} |
|||
threescale_cicd_tmp_existing_mapping_rules: {} |
|||
|
|||
- name: Build a list of our expected/wanted mapping rules |
|||
set_fact: |
|||
threescale_cicd_tmp_wanted_mapping_rules: '{{ threescale_cicd_tmp_wanted_mapping_rules|combine({ threescale_cicd_tmp_operation.key: { "http_method": threescale_cicd_tmp_operation.value.verb.upper(), "pattern": threescale_cicd_api_basepath ~ threescale_cicd_tmp_operation.value.path ~ "$", "delta": 1 } }) }}' |
|||
with_dict: '{{ threescale_cicd_api_operations }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_tmp_operation |
|||
|
|||
- name: Map metric id to system_name |
|||
set_fact: |
|||
threescale_cicd_tmp_existing_mapping_rules: '{{ threescale_cicd_tmp_existing_mapping_rules|combine({ (threescale_cicd_existing_metrics_details|selectattr("id", "equalto", threescale_cicd_tmp_metric.metric_id)|first).system_name: threescale_cicd_tmp_metric.id}) }}' |
|||
with_items: '{{ threescale_cicd_existing_mappingrules_details }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_tmp_metric |
|||
|
|||
- set_fact: |
|||
# create the items that we want but don't have yet |
|||
threescale_cicd_tmp_mapping_rules_to_create: '{{ threescale_cicd_tmp_wanted_mapping_rules.keys()|difference(threescale_cicd_tmp_existing_mapping_rules.keys()) }}' |
|||
# delete the items that we don't want but we have |
|||
threescale_cicd_tmp_mapping_rules_to_delete: '{{ threescale_cicd_tmp_existing_mapping_rules.keys()|difference(threescale_cicd_tmp_wanted_mapping_rules.keys()) }}' |
|||
# update the items that we want and we have |
|||
threescale_cicd_tmp_mapping_rules_to_update: '{{ threescale_cicd_tmp_existing_mapping_rules.keys()|intersect(threescale_cicd_tmp_wanted_mapping_rules.keys()) }}' |
|||
|
|||
- include_tasks: "create_mapping_rule.yml" |
|||
with_items: '{{ threescale_cicd_tmp_mapping_rules_to_create }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_tmp_mapping_rule_to_create |
|||
|
|||
- include_tasks: "update_mapping_rule.yml" |
|||
with_items: '{{ threescale_cicd_tmp_mapping_rules_to_update }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_tmp_mapping_rule_to_update |
|||
|
|||
- name: Delete the unused mapping rules |
|||
uri: |
|||
url: "https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/proxy/mapping_rules/{{ threescale_cicd_tmp_existing_mapping_rules[threescale_cicd_tmp_mapping_rule_to_delete] }}.json?access_token={{ threescale_cicd_access_token|urlencode }}" |
|||
validate_certs: no |
|||
method: DELETE |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 200' |
|||
with_items: '{{ threescale_cicd_tmp_mapping_rules_to_delete }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_tmp_mapping_rule_to_delete |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -1,47 +0,0 @@ |
|||
--- |
|||
|
|||
- set_fact: |
|||
threescale_cicd_api_method_definition: |
|||
system_name: '{{ threescale_cicd_tmp_operation.key }}' |
|||
friendly_name: '{{ threescale_cicd_tmp_operation.value.friendly_name|default(threescale_cicd_tmp_operation.key) }}' |
|||
description: '{{ threescale_cicd_tmp_operation.value.description|default('''') }}' |
|||
unit: 'hits' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_body_update_method: '{{ "access_token=" ~ threescale_cicd_access_token|urlencode }}' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_body_update_method: '{{ threescale_cicd_tmp_body_update_method ~ "&" ~ (threescale_cicd_tmp_param.key|urlencode) ~ "=" ~ (threescale_cicd_tmp_param.value|urlencode) }}' |
|||
with_dict: '{{ threescale_cicd_api_method_definition }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_tmp_param |
|||
|
|||
- name: Update the method |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/metrics/{{ threescale_cicd_metric_id }}/methods/{{ (threescale_cicd_existing_metrics_details|selectattr('system_name', 'equalto', threescale_cicd_tmp_operation.key)|first).id }}.json |
|||
validate_certs: no |
|||
method: PATCH |
|||
body: '{{ threescale_cicd_tmp_body_update_method }}' |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 200' |
|||
when: 'threescale_cicd_tmp_operation.key in threescale_cicd_existing_metrics' |
|||
|
|||
- name: Create the method |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/metrics/{{ threescale_cicd_metric_id }}/methods.json |
|||
validate_certs: no |
|||
method: POST |
|||
body: '{{ threescale_cicd_tmp_body_update_method }}' |
|||
status_code: 201 |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 201' |
|||
when: 'threescale_cicd_tmp_operation.key not in threescale_cicd_existing_metrics' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_existing_metrics: '{{ threescale_cicd_existing_metrics|union([ threescale_cicd_tmp_operation.key ]) }}' |
|||
threescale_cicd_existing_metrics_details: '{{ threescale_cicd_existing_metrics_details|union([ { "system_name": threescale_cicd_tmp_operation.key, "id": threescale_cicd_tmpresponse.json|json_query("method.id") } ]) }}' |
|||
when: 'threescale_cicd_tmp_operation.key not in threescale_cicd_existing_metrics' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -1,20 +0,0 @@ |
|||
--- |
|||
|
|||
- name: Retrieve existing metrics from the 3scale Admin Portal |
|||
uri: |
|||
url: "https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/metrics.json?access_token={{ threescale_cicd_access_token|urlencode }}" |
|||
validate_certs: no |
|||
register: threescale_cicd_tmp_allmetrics |
|||
|
|||
- set_fact: |
|||
threescale_cicd_existing_metrics: '{{ threescale_cicd_tmp_allmetrics.json|json_query(''metrics[*].metric.system_name'') }}' |
|||
threescale_cicd_existing_metrics_details: '{{ threescale_cicd_tmp_allmetrics.json|json_query(''metrics[].{"system_name": metric.system_name, "id": metric.id}'') }}' |
|||
|
|||
- name: Find the "hits" metric id |
|||
set_fact: |
|||
threescale_cicd_metric_id: '{{ (threescale_cicd_existing_metrics_details|selectattr(''system_name'', ''equalto'', ''hits'')|first).id }}' |
|||
|
|||
- include_tasks: "update_method.yml" |
|||
with_dict: '{{ threescale_cicd_api_operations }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_tmp_operation |
|||
@ -1,23 +0,0 @@ |
|||
--- |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_body_update_proxy: '{{ "access_token=" ~ threescale_cicd_access_token|urlencode }}' |
|||
|
|||
- set_fact: |
|||
threescale_cicd_tmp_body_update_proxy: '{{ threescale_cicd_tmp_body_update_proxy ~ "&" ~ (threescale_cicd_tmp_param.key|urlencode) ~ "=" ~ (threescale_cicd_tmp_param.value|urlencode) }}' |
|||
with_dict: '{{ threescale_cicd_api_proxy_definition }}' |
|||
loop_control: |
|||
loop_var: threescale_cicd_tmp_param |
|||
|
|||
- name: Update the proxy |
|||
uri: |
|||
url: https://{{ inventory_hostname }}/admin/api/services/{{ threescale_cicd_api_service_id }}/proxy.json |
|||
validate_certs: no |
|||
method: PATCH |
|||
body: '{{ threescale_cicd_tmp_body_update_proxy }}' |
|||
register: threescale_cicd_tmpresponse |
|||
changed_when: 'threescale_cicd_tmpresponse.status == 200' |
|||
|
|||
- name: Wait for a couple seconds |
|||
pause: |
|||
seconds: '{{ threescale_cicd_throttling }}' |
|||
@ -0,0 +1,11 @@ |
|||
{% |
|||
set payload = [ |
|||
'access_token=' ~ threescale_cicd_access_token|urlencode, |
|||
'name=' ~ threescale_cicd_api_name|urlencode, |
|||
'description=' ~ threescale_cicd_api_description|urlencode, |
|||
'system_name=' ~ threescale_cicd_api_system_name|urlencode, |
|||
'body=' ~ threescale_cicd_openapi_rewritten|to_nice_json|urlencode, |
|||
'published=true', |
|||
] |
|||
%} |
|||
{{ payload|join("&") }} |
|||
@ -0,0 +1,16 @@ |
|||
{% |
|||
set payload = [ |
|||
'access_token=' ~ threescale_cicd_access_token|urlencode, |
|||
'plan_id=' ~ threescale_cicd_default_application_plan_id|urlencode, |
|||
'name=' ~ threescale_cicd_default_application_name|urlencode, |
|||
'description=' ~ threescale_cicd_default_application_description|urlencode |
|||
] |
|||
%} |
|||
{% if threescale_cicd_api_security_scheme.type == 'oauth2' %} |
|||
{% do payload.append("application_id=" ~ threescale_cicd_default_application_appid|urlencode) %} |
|||
{% do payload.append("application_key=" ~ threescale_cicd_default_application_appsecret|urlencode) %} |
|||
{% endif %} |
|||
{% if threescale_cicd_api_security_scheme.type == 'apiKey' %} |
|||
{% do payload.append("user_key=" ~ threescale_cicd_default_application_appid|urlencode) %} |
|||
{% endif %} |
|||
{{ payload|join("&") }} |
|||
@ -0,0 +1,9 @@ |
|||
{% |
|||
set payload = [ |
|||
'access_token=' ~ threescale_cicd_access_token|urlencode |
|||
] |
|||
%} |
|||
{% for key, value in threescale_cicd_application_plan.items() %} |
|||
{% do payload.append(key ~ "=" ~ value|urlencode) %} |
|||
{% endfor %} |
|||
{{ payload|join("&") }} |
|||
@ -0,0 +1,10 @@ |
|||
{% |
|||
set payload = [ |
|||
'access_token=' ~ threescale_cicd_access_token|urlencode, |
|||
'metric_id=' ~ ((threescale_cicd_existing_metrics_details|selectattr("system_name", "equalto", threescale_cicd_mapping_rule)|first).id|urlencode) |
|||
] |
|||
%} |
|||
{% for key, value in threescale_cicd_wanted_mapping_rules[threescale_cicd_mapping_rule].items() %} |
|||
{% do payload.append(key ~ "=" ~ value|urlencode) %} |
|||
{% endfor %} |
|||
{{ payload|join("&") }} |
|||
@ -0,0 +1,10 @@ |
|||
{% |
|||
set payload = [ |
|||
'access_token=' ~ threescale_cicd_access_token|urlencode, |
|||
'friendly_name=' ~ threescale_cicd_api_operation.value.friendly_name|default(threescale_cicd_api_operation.key)|urlencode, |
|||
'description=' ~ threescale_cicd_api_operation.value.description|default('')|urlencode, |
|||
'system_name=' ~ threescale_cicd_api_operation.key|urlencode, |
|||
'unit=hits' |
|||
] |
|||
%} |
|||
{{ payload|join("&") }} |
|||
@ -0,0 +1,15 @@ |
|||
{% if threescale_cicd_apicast_sandbox_endpoint|default("")|length > 0 or threescale_cicd_apicast_production_endpoint|default("")|length > 0 %} |
|||
{% set deployment_type = "self_managed" %} |
|||
{% else %} |
|||
{% set deployment_type = "hosted" %} |
|||
{% endif %} |
|||
{% |
|||
set payload = [ |
|||
'access_token=' ~ threescale_cicd_access_token|urlencode, |
|||
'name=' ~ threescale_cicd_api_name|urlencode, |
|||
'deployment_option=' ~ deployment_type|urlencode, |
|||
'system_name=' ~ threescale_cicd_api_system_name|urlencode, |
|||
'backend_version=' ~ threescale_cicd_api_backend_version|urlencode |
|||
] |
|||
%} |
|||
{{ payload|join("&") }} |
|||
@ -0,0 +1,7 @@ |
|||
access_token={{ threescale_cicd_access_token|urlencode }} |
|||
{%- if threescale_cicd_api_security_scheme.type == 'oauth2' -%} |
|||
&app_id={{ threescale_cicd_default_application_appid|urlencode }} |
|||
{%- endif -%} |
|||
{%- if threescale_cicd_api_security_scheme.type == 'apiKey' -%} |
|||
&user_key={{ threescale_cicd_default_application_appid|urlencode }} |
|||
{%- endif -%} |
|||
@ -0,0 +1,5 @@ |
|||
{% set payload = [ ] %} |
|||
{% for key, value in oauth_payload.items() %} |
|||
{% do payload.append(key ~ "=" ~ value|urlencode) %} |
|||
{% endfor %} |
|||
{{ payload|join("&") }} |
|||
@ -0,0 +1 @@ |
|||
{{ threescale_cicd_default_application_sso_body|combine({ 'serviceAccountsEnabled': true, 'standardFlowEnabled': false, 'implicitFlowEnabled': false, 'directAccessGrantsEnabled': true }) }} |
|||
@ -0,0 +1 @@ |
|||
access_token={{ threescale_cicd_access_token|urlencode }}&to={{ threescale_cicd_production_environment_name|urlencode }} |
|||
@ -0,0 +1,8 @@ |
|||
{% set headers = {} %} |
|||
{% if threescale_cicd_api_security_scheme.type == "apiKey" and threescale_cicd_api_credentials_location == "headers" %} |
|||
{% do headers.update({ threescale_cicd_api_security_scheme.name|urlencode: threescale_cicd_default_application_details.user_key }) %} |
|||
{% endif %} |
|||
{% if threescale_cicd_api_security_scheme.type == "oauth2" and threescale_cicd_api_credentials_location == "headers" %} |
|||
{% do headers.update({ 'Authorization': 'Bearer ' ~ threescale_cicd_keycloak_access_token }) %} |
|||
{% endif %} |
|||
{{ headers }} |
|||
@ -0,0 +1,10 @@ |
|||
{%- if threescale_cicd_smoke_test_env == "staging" -%} |
|||
{{ threescale_cicd_apicast_discovered_sandbox_endpoint }} |
|||
{%- endif -%} |
|||
{%- if threescale_cicd_smoke_test_env == "production" -%} |
|||
{{ threescale_cicd_apicast_discovered_production_endpoint }} |
|||
{%- endif -%} |
|||
{{ threescale_cicd_openapi_smoketest_path }} |
|||
{%- if threescale_cicd_api_security_scheme.type == "apiKey" and threescale_cicd_api_credentials_location == "query" -%} |
|||
?{{ threescale_cicd_api_security_scheme.name|urlencode }}={{ threescale_cicd_default_application_details.user_key }} |
|||
{%- endif -%} |
|||
@ -0,0 +1 @@ |
|||
create_activedoc.j2 |
|||
@ -0,0 +1 @@ |
|||
create_application.j2 |
|||
@ -0,0 +1 @@ |
|||
create_application_plan.j2 |
|||
@ -0,0 +1 @@ |
|||
create_mapping_rule.j2 |
|||
@ -0,0 +1 @@ |
|||
create_method.j2 |
|||
@ -0,0 +1,20 @@ |
|||
{% |
|||
set payload = [ |
|||
'access_token=' ~ threescale_cicd_access_token|urlencode, |
|||
'credentials_location=' ~ threescale_cicd_api_credentials_location|urlencode, |
|||
'api_backend=' ~ threescale_cicd_private_base_url|urlencode |
|||
] |
|||
%} |
|||
{% if threescale_cicd_api_security_scheme.type == 'apiKey' %} |
|||
{% do payload.append('auth_user_key=' ~ threescale_cicd_api_security_scheme.name|urlencode) %} |
|||
{% endif %} |
|||
{% if threescale_cicd_api_security_scheme.type == 'oauth2' %} |
|||
{% do payload.append('oidc_issuer_endpoint=' ~ threescale_cicd_sso_issuer_endpoint|urlencode) %} |
|||
{% endif %} |
|||
{% if threescale_cicd_apicast_sandbox_endpoint|default("")|length > 0 %} |
|||
{% do payload.append('sandbox_endpoint=' ~ threescale_cicd_apicast_sandbox_endpoint|urlencode) %} |
|||
{% endif %} |
|||
{% if threescale_cicd_apicast_production_endpoint|default("")|length > 0 %} |
|||
{% do payload.append('endpoint=' ~ threescale_cicd_apicast_production_endpoint|urlencode) %} |
|||
{% endif %} |
|||
{{ payload|join("&") }} |
|||
@ -0,0 +1 @@ |
|||
create_service.j2 |
|||
@ -0,0 +1,5 @@ |
|||
{% set mapping_rules = {} %} |
|||
{% for value in threescale_cicd_existing_mapping_rules_details %} |
|||
{% do mapping_rules.update({ (threescale_cicd_existing_metrics_details|selectattr("id", "equalto", value.metric_id)|first).system_name: value.id }) %} |
|||
{% endfor %} |
|||
{{ mapping_rules }} |
|||
@ -0,0 +1,7 @@ |
|||
{% set to_delete = [] %} |
|||
{% for metric in threescale_cicd_existing_metrics_details %} |
|||
{% if metric.system_name != "hits" and metric.system_name not in threescale_cicd_api_operations %} |
|||
{% do to_delete.append(metric) %} |
|||
{% endif %} |
|||
{% endfor %} |
|||
{{ to_delete }} |
|||
@ -0,0 +1,5 @@ |
|||
{%- if threescale_cicd_wildcard_domain is defined -%} |
|||
{{ 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 }}.{{ threescale_cicd_wildcard_domain }} |
|||
{%- elif 'apicast-production' in groups and groups['apicast-production'] > 0 -%} |
|||
{{ (hostvars[groups['apicast-production'][0]].scheme|default('https')) ~ '://' ~ groups['apicast-production'][0] }} |
|||
{%- endif -%} |
|||
@ -0,0 +1,5 @@ |
|||
{%- if threescale_cicd_wildcard_domain is defined -%} |
|||
{{ 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 }}.{{ threescale_cicd_wildcard_domain }} |
|||
{%- elif 'apicast-sandbox' in groups and groups['apicast-sandbox'] > 0 -%} |
|||
{{ (hostvars[groups['apicast-sandbox'][0]].scheme|default('https')) ~ '://' ~ groups['apicast-sandbox'][0] }} |
|||
{%- endif -%} |
|||
@ -0,0 +1,6 @@ |
|||
{% if 'x-threescale-system-name' in threescale_cicd_openapi_file_content.info %} |
|||
{% set extracted_system_name = threescale_cicd_openapi_file_content.info['x-threescale-system-name']|regex_replace('[^a-zA-Z0-9_]+', '_')|lower %} |
|||
{% else %} |
|||
{% set extracted_system_name = threescale_cicd_openapi_file_content.info['title']|default('api')|regex_replace('[^a-zA-Z0-9_]+', '_')|lower %} |
|||
{% endif %} |
|||
{{ extracted_system_name }} |
|||
@ -0,0 +1,4 @@ |
|||
{%- if threescale_cicd_api_environment_name is defined -%} |
|||
{%- set system_name_prefix = threescale_cicd_api_environment_name|default("")|regex_replace('[^a-zA-Z0-9_]+', '_') ~ "_" -%} |
|||
{%- endif -%} |
|||
{{ system_name_prefix|default("") }}{{ threescale_cicd_api_base_system_name }}_{{ threescale_cicd_api_version_major|regex_replace('[^a-zA-Z0-9_]+', '_') }} |
|||
@ -0,0 +1,26 @@ |
|||
{% set operations = {} -%} |
|||
{% if 'paths' in threescale_cicd_openapi_file_content -%} |
|||
{% for path, verbs in threescale_cicd_openapi_file_content['paths'].items() -%} |
|||
{% if path.startswith('/') -%} |
|||
{% for verb, method_description in verbs.items() -%} |
|||
{% if verb != '$ref' and verb != 'parameters' -%} |
|||
{% if 'operationId' in method_description -%} |
|||
{% set operation_id = method_description['operationId'] -%} |
|||
{% else -%} |
|||
{% set operation_id = verb.upper() + path -%} |
|||
{% endif -%} |
|||
{% set operation_id = operation_id|regex_replace('[^0-9a-zA-Z_]+', '_') -%} |
|||
{% set operation = { operation_id: { 'path': path, 'verb': verb } } -%} |
|||
{% if 'summary' in method_description -%} |
|||
{% do operation[operation_id].update({ 'friendly_name': method_description.summary }) -%} |
|||
{% endif -%} |
|||
{% if 'description' in method_description -%} |
|||
{% do operation[operation_id].update({ 'description': method_description.description }) -%} |
|||
{% endif -%} |
|||
{% do operations.update(operation) -%} |
|||
{% endif -%} |
|||
{% endfor -%} |
|||
{% endif -%} |
|||
{% endfor -%} |
|||
{% endif -%} |
|||
{{ operations }} |
|||
@ -0,0 +1,11 @@ |
|||
{%- if threescale_cicd_api_backend_hostname is not defined and 'host' in threescale_cicd_openapi_file_content -%} |
|||
{%- set backend_hostname = threescale_cicd_openapi_file_content.host -%} |
|||
{%- else -%} |
|||
{%- set backend_hostname = threescale_cicd_api_backend_hostname -%} |
|||
{%- endif -%} |
|||
{%- if threescale_cicd_api_backend_scheme is not defined -%} |
|||
{%- set backend_scheme = threescale_cicd_openapi_file_content.schemes|default(["http"])|first -%} |
|||
{%- else -%} |
|||
{%- set backend_scheme = threescale_cicd_api_backend_scheme -%} |
|||
{%- endif -%} |
|||
{{ backend_scheme }}://{{ backend_hostname }} |
|||
@ -0,0 +1,5 @@ |
|||
{%- if threescale_cicd_api_environment_name is defined -%} |
|||
{{ threescale_cicd_api_default_name }} ({{ threescale_cicd_api_environment_name|upper }}, v{{ threescale_cicd_api_version }}) |
|||
{%- else -%} |
|||
{{ threescale_cicd_api_default_name }} (v{{ threescale_cicd_api_version }}) |
|||
{%- endif -%} |
|||
@ -0,0 +1,3 @@ |
|||
{%- if 'sso' in groups and groups['sso'] > 0 -%} |
|||
{{ (hostvars[groups['sso'][0]].scheme|default('https')) ~ '://' ~ hostvars[groups['sso'][0]].client_id ~ ':' ~ hostvars[groups['sso'][0]].client_secret ~ '@' ~ groups['sso'][0] ~ '/auth/realms/' ~ hostvars[groups['sso'][0]].realm }} |
|||
{%- endif -%} |
|||
@ -0,0 +1,22 @@ |
|||
{% set security_definitions = threescale_cicd_api_security_definitions %} |
|||
{% set new_openapi = threescale_cicd_openapi_file_content %} |
|||
{# Add the RH-SSO endpoints to the OpenAPI securityDefinitions #} |
|||
{% if threescale_cicd_api_security_scheme.type == "oauth2" %} |
|||
{% do security_definitions[threescale_cicd_api_security_scheme_name].update({ "authorizationUrl": threescale_cicd_sso_realm_endpoint ~ "/protocol/openid-connect/auth", "tokenUrl": threescale_cicd_sso_realm_endpoint ~ "/protocol/openid-connect/token" }) %} |
|||
{% endif %} |
|||
{# Add the RH-SSO default scope to the OpenAPI securityDefinitions #} |
|||
{% if threescale_cicd_api_security_scheme.type == "oauth2" and "scopes" not in threescale_cicd_api_security_scheme %} |
|||
{% do security_definitions[threescale_cicd_api_security_scheme_name].update({ "scopes": threescale_cicd_default_oauth_scopes }) %} |
|||
{% endif %} |
|||
{# Update the security definitions #} |
|||
{% do new_openapi.update({ "securityDefinitions": security_definitions }) %} |
|||
{# Update the "schemes" and "hostname" fields with the public apicast production URL #} |
|||
{% set apicast_production_scheme = threescale_cicd_apicast_discovered_production_endpoint|urlsplit('scheme') %} |
|||
{% set apicast_production_hostname = threescale_cicd_apicast_discovered_production_endpoint|urlsplit('hostname') %} |
|||
{% do new_openapi.update({ |
|||
"schemes": [ apicast_production_scheme ], |
|||
"host": apicast_production_hostname |
|||
}) %} |
|||
{# Make sure the swagger version is a string and not a number #} |
|||
{% do new_openapi.update({ "swagger": new_openapi.swagger ~ "" }) %} |
|||
{{ new_openapi }} |
|||
@ -0,0 +1,5 @@ |
|||
{% set mapping_rules = {} %} |
|||
{% for key, value in threescale_cicd_api_operations.items() %} |
|||
{% do mapping_rules.update({ key: { "http_method": value.verb.upper(), "pattern": threescale_cicd_api_basepath ~ value.path ~ "$", "delta": 1 } }) %} |
|||
{% endfor %} |
|||
{{ mapping_rules }} |
|||
@ -0,0 +1,45 @@ |
|||
--- |
|||
|
|||
- 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 |
|||
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 |
|||
@ -0,0 +1,92 @@ |
|||
--- |
|||
# Credentials are expected to be passed in HTTP headers unless stated otherwise |
|||
# and only for API Keys |
|||
threescale_cicd_api_credentials_location: '{{ ''headers'' if threescale_cicd_api_security_scheme.in|default(''header'') == ''header'' or threescale_cicd_api_security_scheme.type == ''oauth2'' else ''query'' }}' |
|||
|
|||
# A list of unused metrics to delete |
|||
threescale_cicd_metrics_to_delete: '{{ lookup(''template'', ''metrics_to_delete.j2'') }}' |
|||
|
|||
# The OpenAPI file to be pushed to 3scale as an ActiveDocs |
|||
threescale_cicd_openapi_rewritten: '{{ lookup(''template'', ''rewritten_openapi.j2'') }}' |
|||
|
|||
# Compute the Keycloak Realm endpoint from the threescale_cicd_sso_issuer_endpoint |
|||
threescale_cicd_sso_realm_endpoint: '{{ (threescale_cicd_sso_issuer_endpoint|urlsplit(''scheme'')) ~ ''://'' ~ (threescale_cicd_sso_issuer_endpoint|urlsplit(''hostname'')) ~ (threescale_cicd_sso_issuer_endpoint|urlsplit(''path'')) }}' |
|||
|
|||
# Compute the Keycloak REST Admin Endpoint from the threescale_cicd_sso_realm_endpoint |
|||
threescale_cicd_sso_admin_endpoint: '{{ threescale_cicd_sso_realm_endpoint|replace(''/auth/realms/'', ''/auth/admin/realms/'') }}' |
|||
|
|||
## |
|||
## OpenAPI Specification File parsing |
|||
## |
|||
threescale_cicd_openapi_file_content: '{{ lookup(''file'', threescale_cicd_openapi_file)|from_json if threescale_cicd_openapi_file_format|upper == ''JSON'' else lookup(''file'', threescale_cicd_openapi_file)|from_yaml }}' |
|||
threescale_cicd_openapi_file_version: '{{ threescale_cicd_openapi_file_content.swagger }}' |
|||
threescale_cicd_api_default_name: '{{ threescale_cicd_openapi_file_content.info.title|default("API") }}' |
|||
threescale_cicd_api_name: '{{ lookup(''template'', ''openapi/service_name.j2'') }}' |
|||
threescale_cicd_api_description: '{{ threescale_cicd_openapi_file_content.info.description|default("") }}' |
|||
threescale_cicd_api_version: '{{ threescale_cicd_openapi_file_content.info.version|default("0.0.1") }}' |
|||
threescale_cicd_api_basepath: '{{ threescale_cicd_openapi_file_content.basePath|default("") }}' |
|||
threescale_cicd_api_operations: '{{ lookup(''template'', ''openapi/openapi_operations.j2'') }}' |
|||
threescale_cicd_api_version_components: '{{ threescale_cicd_api_version.split(".") }}' |
|||
threescale_cicd_api_version_major: '{{ threescale_cicd_api_version_components|first }}' |
|||
threescale_cicd_api_security_requirements: '{{ threescale_cicd_openapi_file_content.security|default([]) }}' |
|||
threescale_cicd_api_security_definitions: '{{ threescale_cicd_openapi_file_content.securityDefinitions|default({}) }}' |
|||
threescale_cicd_api_security_scheme_name: '{{ threescale_cicd_api_security_requirements[0].keys()[0]|default(''none'') }}' |
|||
threescale_cicd_api_security_scheme: '{{ threescale_cicd_api_security_definitions[threescale_cicd_api_security_scheme_name] if threescale_cicd_api_security_scheme_name in threescale_cicd_api_security_definitions else {} }}' |
|||
threescale_cicd_api_backend_version: '{{ threescale_cicd_backend_version_mapping[threescale_cicd_api_security_scheme.type] }}' |
|||
threescale_cicd_backend_version_mapping: |
|||
apiKey: '1' |
|||
oauth2: 'oidc' |
|||
threescale_cicd_openapi_smoketest_path: '{{ threescale_cicd_api_basepath }}{{ threescale_cicd_api_operations[threescale_cicd_openapi_smoketest_operation].path }}' |
|||
|
|||
## |
|||
## ID Lookup Variables |
|||
## |
|||
|
|||
# The id of the current service is fetched from the threescale_cicd_existing_services_details fact |
|||
threescale_cicd_api_service_id: '{{ (threescale_cicd_existing_services_details|selectattr(''system_name'', ''equalto'', threescale_cicd_api_system_name)|first)[''id''] }}' |
|||
|
|||
# The id of the 'hits' metric is fetched from the threescale_cicd_existing_metrics_details fact |
|||
threescale_cicd_metric_id: '{{ (threescale_cicd_existing_metrics_details|selectattr(''system_name'', ''equalto'', ''hits'')|first).id }}' |
|||
|
|||
# Find the default application plan id from its system name |
|||
threescale_cicd_default_application_plan_id: '{{ (threescale_cicd_existing_application_plans_details|selectattr("system_name", "equalto", threescale_cicd_default_application_plan)|first).id }}' |
|||
|
|||
# Find the id of the existing activedocs from the threescale_cicd_existing_activedocs_details fact |
|||
threescale_cicd_api_activedocs_id: '{{ (threescale_cicd_existing_activedocs_details|selectattr(''system_name'', ''equalto'', threescale_cicd_api_system_name)|first).id }}' |
|||
|
|||
## |
|||
## Mapping Rules computation |
|||
## |
|||
# what we want |
|||
threescale_cicd_wanted_mapping_rules: '{{ lookup(''template'', ''wanted_mapping_rules.j2'') }}' |
|||
# what we have |
|||
threescale_cicd_existing_mapping_rules: '{{ lookup(''template'', ''existing_mapping_rules.j2'') }}' |
|||
# create the items that we want but don't have yet |
|||
threescale_cicd_mapping_rules_to_create: '{{ threescale_cicd_wanted_mapping_rules.keys()|difference(threescale_cicd_existing_mapping_rules.keys()) }}' |
|||
# delete the items that we don't want but we have |
|||
threescale_cicd_mapping_rules_to_delete: '{{ threescale_cicd_existing_mapping_rules.keys()|difference(threescale_cicd_wanted_mapping_rules.keys()) }}' |
|||
# update the items that we want and we have |
|||
threescale_cicd_mapping_rules_to_update: '{{ threescale_cicd_existing_mapping_rules.keys()|intersect(threescale_cicd_wanted_mapping_rules.keys()) }}' |
|||
|
|||
## |
|||
## 3scale API Payload definition |
|||
## |
|||
threescale_cicd_update_proxy_payload: '{{ lookup(''template'', ''api-calls/update_proxy.j2'') }}' |
|||
threescale_cicd_update_service_payload: '{{ lookup(''template'', ''api-calls/update_service.j2'') }}' |
|||
threescale_cicd_create_service_payload: '{{ lookup(''template'', ''api-calls/create_service.j2'') }}' |
|||
threescale_cicd_update_method_payload: '{{ lookup(''template'', ''api-calls/update_method.j2'') }}' |
|||
threescale_cicd_create_method_payload: '{{ lookup(''template'', ''api-calls/create_method.j2'') }}' |
|||
threescale_cicd_update_mapping_rule_payload: '{{ lookup(''template'', ''api-calls/update_mapping_rule.j2'') }}' |
|||
threescale_cicd_create_mapping_rule_payload: '{{ lookup(''template'', ''api-calls/create_mapping_rule.j2'') }}' |
|||
threescale_cicd_update_application_plan_payload: '{{ lookup(''template'', ''api-calls/update_application_plan.j2'') }}' |
|||
threescale_cicd_create_application_plan_payload: '{{ lookup(''template'', ''api-calls/create_application_plan.j2'') }}' |
|||
threescale_cicd_find_application_payload: '{{ lookup(''template'', ''api-calls/find_application.j2'') }}' |
|||
threescale_cicd_update_application_payload: '{{ lookup(''template'', ''api-calls/update_application.j2'') }}' |
|||
threescale_cicd_create_application_payload: '{{ lookup(''template'', ''api-calls/create_application.j2'') }}' |
|||
threescale_cicd_authenticate_to_keycloak_payload: '{{ lookup(''template'', ''api-calls/keycloak/authenticate.j2'') }}' |
|||
threescale_cicd_patch_keycloak_client_payload: '{{ lookup(''template'', ''api-calls/keycloak/patch_client.j2'') }}' |
|||
threescale_cicd_smoke_test_headers: '{{ lookup(''template'', ''api-calls/smoke-test/headers.j2'') }}' |
|||
threescale_cicd_smoke_test_url: '{{ lookup(''template'', ''api-calls/smoke-test/url.j2'') }}' |
|||
threescale_cicd_promote_proxy_payload: '{{ lookup(''template'', ''api-calls/promote_proxy.j2'') }}' |
|||
threescale_cicd_update_activedoc_payload: '{{ lookup(''template'', ''api-calls/update_activedoc.j2'') }}' |
|||
threescale_cicd_create_activedoc_payload: '{{ lookup(''template'', ''api-calls/create_activedoc.j2'') }}' |
|||
Loading…
Reference in new issue