diff --git a/content/blog/cleanup-playbook-3scale.md b/content/blog/cleanup-playbook-3scale.md new file mode 100644 index 0000000..52220cc --- /dev/null +++ b/content/blog/cleanup-playbook-3scale.md @@ -0,0 +1,82 @@ +--- +title: "A cleanup playbook for 3scale" +date: 2020-04-28T00:00:00+02:00 +opensource: +- 3scale +--- + +If you are running integration tests embedding 3scale or are doing a lot of 3scale demos, you might sooner or later **have plenty of services declared in the 3scale Admin console**, which could reveal difficult to work with. +And with the new feature named *API-as-a-Product*, there are now **Backends and Products** to delete, making the cleanup by hand a bit tedious. + +This article explains how to cleanup a 3scale tenant using Ansible. + +## Pre-requisites + +Make sure Ansible is installed locally and is a fairly recent version. + +``` +$ ansible --version +ansible 2.8.10 + config file = /etc/ansible/ansible.cfg + configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] + ansible python module location = /usr/lib/python3.6/site-packages/ansible + executable location = /usr/bin/ansible + python version = 3.6.8 (default, Oct 11 2019, 15:04:54) [GCC 8.3.1 20190507 (Red Hat 8.3.1-4)] +``` + +Find the name of your 3scale Admin Portal and set it as a environment variable. + +For 3scale SaaS tenants, it will be something like this: + +```sh +export ADMIN_PORTAL_HOSTNAME="-admin.3scale.net" +``` + +For 3scale 2.8 installed on-premises, you can find the default admin portal hostname by querying OpenShift. + +```sh +export ADMIN_PORTAL_HOSTNAME="$(oc get route -l zync.3scale.net/route-to=system-provider -o go-template='{{(index .items 0).spec.host}}')" +``` + +Now, generate an Access Token with read/write privileges over the **Account Management API** and set it as a shell variable. + +```sh +export THREESCALE_TOKEN="123...456" +``` + +For 3scale 2.8 installed on-premises, there is a default token that you can use if you wish. + +```sh +export THREESCALE_TOKEN="$(oc get secret system-seed -o go-template --template='{{.data.ADMIN_ACCESS_TOKEN|base64decode}}')" +``` + +Fetch the cleanup playbook. + +```sh +curl -Lo cleanup.yaml https://www.itix.fr/blog/cleanup-playbook-3scale/cleanup.yaml +``` + +## Cleanup 3scale + +The cleanup playbook uses the environment variables set previously to connect to the 3scale Admin Portal and get a list of the Products, Backends and ActiveDocs objects that makes up a 3scale service. +This list is filtered to exclude the default service **api** (*Echo API*). +The list is then filtered using the **systemname_filter** parameter to include only Products, Backends and ActiveDocs that have the given string in their system_name. + +Then all the matching Products, Backends and ActiveDocs are removed. + +For instance, to remove all objects related to the **dev_library_1** and **prod_library_1** services, you could run the playbook like this: + +```sh +ansible-playbook cleanup.yaml -e systemname_filter=library +``` + +And to remove the **dev_library_1** and **dev_petstore_1** services, you could run the playbook like this: + +```sh +ansible-playbook cleanup.yaml -e systemname_filter=dev_ +``` + +## Conclusion + +This article explained how to cleanup a 3scale tenant using Ansible, by deleting all *Products*, *Backends* and *ActiveDocs* matching a given criterion. +Now, you can reset your development environment or demo environment easily! diff --git a/static/blog/cleanup-playbook-3scale/cleanup.yaml b/static/blog/cleanup-playbook-3scale/cleanup.yaml new file mode 100644 index 0000000..9131153 --- /dev/null +++ b/static/blog/cleanup-playbook-3scale/cleanup.yaml @@ -0,0 +1,118 @@ +--- + +- name: Delete all services of a 3scale tenant + hosts: localhost + gather_facts: no + vars: + ansible_connection: local + threescale_api: https://{{ admin_portal_hostname }}/admin/api + validate_certs: no + threescale_token: "{{ lookup('env', 'THREESCALE_TOKEN' )}}" + admin_portal_hostname: "{{ lookup('env', 'ADMIN_PORTAL_HOSTNAME' )}}" + tasks: + - assert: + that: + - threescale_token|length > 0 + msg: > + Please pass your 3scale Access Token in the 'threescale_token' extra var + or in the THREESCALE_TOKEN environment variable. + + - assert: + that: + - admin_portal_hostname|length > 0 + msg: > + Please pass your 3scale Admin Portal hostname in the 'admin_portal_hostname' + extra var or in the ADMIN_PORTAL_HOSTNAME environment variable. + + - assert: + that: + - systemname_filter is defined + msg: > + Please pass a string common to all the system_name you would like to delete + in the 'systemname_filter' extra var. + For instance: systemname_filter=library would delete 'dev_library_v1', + 'my_library_service' but not 'echo_api'. + + - name: Check if jmespath is available locally + debug: msg={{ dummy|json_query('@') }} + register: check_jmespath + ignore_errors: yes + vars: + dummy: Hello World + + - name: Ensure JMESPath is installed + assert: + that: + - 'check_jmespath is success' + msg: > + The JMESPath library is required by this playbook. + Please install the JMESPath library with 'pip install jmespath'. + + - name: Find Services + uri: + url: '{{ threescale_api }}/services.json?access_token={{ threescale_token }}' + validate_certs: '{{ validate_certs }}' + register: find_services_response + changed_when: false + + - name: Delete all matching services + uri: + url: '{{ threescale_api }}/services/{{ item.id }}.json?access_token={{ threescale_token }}' + method: DELETE + status_code: "200,404" + validate_certs: '{{ validate_certs }}' + register: delete_service_response + changed_when: delete_service_response.status == 200 + with_items: '{{ services }}' + when: > + systemname_filter in item.system_name + vars: + services: '{{ find_services_response.json|json_query(query) }}' + query: > + services[?service.system_name != `api`].{"id": service.id, "system_name": service.system_name} + + - name: Find API Backends + uri: + url: '{{ threescale_api }}/backend_apis.json?access_token={{ threescale_token }}' + validate_certs: '{{ validate_certs }}' + register: find_backends_response + changed_when: false + + - name: Delete all matching API Backends + uri: + url: '{{ threescale_api }}/backend_apis/{{ item.id }}.json?access_token={{ threescale_token }}' + method: DELETE + status_code: "200,404" + validate_certs: '{{ validate_certs }}' + register: delete_service_response + changed_when: delete_service_response.status == 200 + with_items: '{{ services }}' + when: > + systemname_filter in item.system_name + vars: + services: '{{ find_backends_response.json|json_query(query) }}' + query: > + backend_apis[?backend_api.system_name != `api`].{"id": backend_api.id, "system_name": backend_api.system_name} + + - name: Find ActiveDocs + uri: + url: '{{ threescale_api }}/active_docs.json?access_token={{ threescale_token }}' + validate_certs: '{{ validate_certs }}' + register: find_active_docs_response + changed_when: false + + - name: Delete all matching ActiveDocs + uri: + url: '{{ threescale_api }}/active_docs/{{ item.id }}.json?access_token={{ threescale_token }}' + method: DELETE + status_code: "200,404" + validate_certs: '{{ validate_certs }}' + register: delete_active_docs_response + changed_when: delete_active_docs_response.status == 200 + with_items: '{{ active_docs }}' + when: > + systemname_filter in item.system_name + vars: + active_docs: '{{ find_active_docs_response.json|json_query(query) }}' + query: > + api_docs[?api_doc.system_name != `echo`].{"id": api_doc.id, "system_name": api_doc.system_name} \ No newline at end of file