From 245a56f38472c2ccaf7465c811c52a548d1dfd45 Mon Sep 17 00:00:00 2001 From: Lars Getwan Date: Wed, 11 Sep 2024 15:11:29 +0200 Subject: [PATCH] Created Lookup Modules 'site' and 'sites'. --- .github/workflows/ans-int-test-lkp-site.yml | 75 ++++++++ .github/workflows/ans-int-test-lkp-sites.yml | 75 ++++++++ plugins/lookup/site.py | 170 ++++++++++++++++++ plugins/lookup/sites.py | 153 ++++++++++++++++ .../lookup_site/lookup_site/tasks/main.yml | 13 ++ .../lookup_site/lookup_site/tasks/test.yml | 31 ++++ .../lookup_site/lookup_site/vars/main.yml | 11 ++ .../targets/lookup_site/tasks/main.yml | 13 ++ .../targets/lookup_site/tasks/test.yml | 31 ++++ .../targets/lookup_site/vars/main.yml | 11 ++ .../targets/lookup_sites/tasks/main.yml | 13 ++ .../targets/lookup_sites/tasks/test.yml | 29 +++ .../targets/lookup_sites/vars/main.yml | 11 ++ 13 files changed, 636 insertions(+) create mode 100644 .github/workflows/ans-int-test-lkp-site.yml create mode 100644 .github/workflows/ans-int-test-lkp-sites.yml create mode 100644 plugins/lookup/site.py create mode 100644 plugins/lookup/sites.py create mode 100644 tests/integration/targets/lookup_site/lookup_site/tasks/main.yml create mode 100644 tests/integration/targets/lookup_site/lookup_site/tasks/test.yml create mode 100644 tests/integration/targets/lookup_site/lookup_site/vars/main.yml create mode 100644 tests/integration/targets/lookup_site/tasks/main.yml create mode 100644 tests/integration/targets/lookup_site/tasks/test.yml create mode 100644 tests/integration/targets/lookup_site/vars/main.yml create mode 100644 tests/integration/targets/lookup_sites/tasks/main.yml create mode 100644 tests/integration/targets/lookup_sites/tasks/test.yml create mode 100644 tests/integration/targets/lookup_sites/vars/main.yml diff --git a/.github/workflows/ans-int-test-lkp-site.yml b/.github/workflows/ans-int-test-lkp-site.yml new file mode 100644 index 000000000..ecb5979e2 --- /dev/null +++ b/.github/workflows/ans-int-test-lkp-site.yml @@ -0,0 +1,75 @@ +# README: +# - When changing the module name, it needs to be changed in 'env:MODULE_NAME' and in 'on:pull_requests:path'! +# +# Resources: +# - Template for this file: https://github.com/ansible-collections/collection_template/blob/main/.github/workflows/ansible-test.yml +# - About Ansible integration tests: https://docs.ansible.com/ansible/latest/dev_guide/testing_integration.html + +env: + NAMESPACE: checkmk + COLLECTION_NAME: general + MODULE_NAME: lookup_site + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +name: Ansible Integration Tests for Site Lookup Module +on: + workflow_dispatch: + pull_request: + branches: + - main + - devel + paths: + - 'plugins/lookup/site.py' + push: + paths: + - 'plugins/lookup/site.py' + +jobs: + + integration: + runs-on: ubuntu-22.04 + name: Ⓐ${{ matrix.ansible }}+py${{ matrix.python }} + strategy: + fail-fast: false + matrix: + ansible: + - stable-2.15 + - stable-2.16 + - stable-2.17 + - devel + python: + - '3.9' + - '3.10' + - '3.11' + - '3.12' + exclude: + # Exclude unsupported sets. + - ansible: stable-2.15 + python: '3.12' + + steps: + - name: Check out code + uses: actions/checkout@v4 + with: + path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install ansible-base (${{ matrix.ansible }}) + run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check + + - name: Provide secrets file + run: echo "${{ secrets.CHECKMK_DOWNLOAD_PW }}" > ./tests/integration/files/.dl-secret + working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + env: + CHECKMK_DOWNLOAD_PW: ${{ secrets.CHECKMK_DOWNLOAD_PW }} + + - name: Run integration test + run: ansible-test integration ${{env.MODULE_NAME}} -v --color --retry-on-error --continue-on-error --diff --python ${{ matrix.python }} --docker default + working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} diff --git a/.github/workflows/ans-int-test-lkp-sites.yml b/.github/workflows/ans-int-test-lkp-sites.yml new file mode 100644 index 000000000..94f4df785 --- /dev/null +++ b/.github/workflows/ans-int-test-lkp-sites.yml @@ -0,0 +1,75 @@ +# README: +# - When changing the module name, it needs to be changed in 'env:MODULE_NAME' and in 'on:pull_requests:path'! +# +# Resources: +# - Template for this file: https://github.com/ansible-collections/collection_template/blob/main/.github/workflows/ansible-test.yml +# - About Ansible integration tests: https://docs.ansible.com/ansible/latest/dev_guide/testing_integration.html + +env: + NAMESPACE: checkmk + COLLECTION_NAME: general + MODULE_NAME: lookup_sites + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +name: Ansible Integration Tests for Sites Lookup Module +on: + workflow_dispatch: + pull_request: + branches: + - main + - devel + paths: + - 'plugins/lookup/site.py' + push: + paths: + - 'plugins/lookup/site.py' + +jobs: + + integration: + runs-on: ubuntu-22.04 + name: Ⓐ${{ matrix.ansible }}+py${{ matrix.python }} + strategy: + fail-fast: false + matrix: + ansible: + - stable-2.15 + - stable-2.16 + - stable-2.17 + - devel + python: + - '3.9' + - '3.10' + - '3.11' + - '3.12' + exclude: + # Exclude unsupported sets. + - ansible: stable-2.15 + python: '3.12' + + steps: + - name: Check out code + uses: actions/checkout@v4 + with: + path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install ansible-base (${{ matrix.ansible }}) + run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check + + - name: Provide secrets file + run: echo "${{ secrets.CHECKMK_DOWNLOAD_PW }}" > ./tests/integration/files/.dl-secret + working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + env: + CHECKMK_DOWNLOAD_PW: ${{ secrets.CHECKMK_DOWNLOAD_PW }} + + - name: Run integration test + run: ansible-test integration ${{env.MODULE_NAME}} -v --color --retry-on-error --continue-on-error --diff --python ${{ matrix.python }} --docker default + working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} diff --git a/plugins/lookup/site.py b/plugins/lookup/site.py new file mode 100644 index 000000000..962000cff --- /dev/null +++ b/plugins/lookup/site.py @@ -0,0 +1,170 @@ +# Copyright: (c) 2023, Lars Getwan +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = """ + name: site + author: Lars Getwan (@lgetwan) + version_added: "5.3.0" + + short_description: Show the configuration of a site + + description: + - Returns the configuration of a distributed monitoring site + + options: + + _terms: + description: site ID + required: True + + server_url: + description: URL of the Checkmk server. + required: True + vars: + - name: ansible_lookup_checkmk_server_url + env: + - name: ANSIBLE_LOOKUP_CHECKMK_SERVER_URL + ini: + - section: checkmk_lookup + key: server_url + + site: + description: Site name for REST API access. + required: True + vars: + - name: ansible_lookup_checkmk_site + env: + - name: ANSIBLE_LOOKUP_CHECKMK_SITE + ini: + - section: checkmk_lookup + key: site + + automation_user: + description: Automation user for the REST API access. + required: True + vars: + - name: ansible_lookup_checkmk_automation_user + env: + - name: ANSIBLE_LOOKUP_CHECKMK_AUTOMATION_USER + ini: + - section: checkmk_lookup + key: automation_user + + automation_secret: + description: Automation secret for the REST API access. + required: True + vars: + - name: ansible_lookup_checkmk_automation_secret + env: + - name: ANSIBLE_LOOKUP_CHECKMK_AUTOMATION_SECRET + ini: + - section: checkmk_lookup + key: automation_secret + + validate_certs: + description: Whether or not to validate TLS certificates. + type: boolean + required: False + default: True + vars: + - name: ansible_lookup_checkmk_validate_certs + env: + - name: ANSIBLE_LOOKUP_CHECKMK_VALIDATE_CERTS + ini: + - section: checkmk_lookup + key: validate_certs + + notes: + - Like all lookups, this runs on the Ansible controller and is unaffected by other keywords such as 'become'. + If you need to use different permissions, you must change the command or run Ansible as another user. + - Alternatively, you can use a shell/command task that runs against localhost and registers the result. + - The directory of the play is used as the current working directory. + - It is B(NOT) possible to assign other variables to the variables mentioned in the C(vars) section! + This is a limitation of Ansible itself. +""" + +EXAMPLES = """ +- name: Get a site with a particular site id + ansible.builtin.debug: + msg: "site: {{ extensions }}" + vars: + extensions: "{{ + lookup('checkmk.general.site', + 'my_remote_site', + server_url=server_url, + site=site, + automation_user=automation_user, + automation_secret=automation_secret, + validate_certs=False + ) + }}" + +- name: "Use variables outside the module call." + ansible.builtin.debug: + msg: "site: {{ extensions }}" + vars: + ansible_lookup_checkmk_server_url: "http://myserver/" + ansible_lookup_checkmk_site: "mysite" + ansible_lookup_checkmk_automation_user: "myuser" + ansible_lookup_checkmk_automation_secret: "mysecret" + ansible_lookup_checkmk_validate_certs: false + attributes: "{{ lookup('checkmk.general.site', 'my_remote_site') }}" +""" + +RETURN = """ + _list: + description: + - The details of a particular site + type: list + elements: str +""" + +import json + +from ansible.errors import AnsibleError +from ansible.plugins.lookup import LookupBase +from ansible_collections.checkmk.general.plugins.module_utils.lookup_api import ( + CheckMKLookupAPI, +) + + +class LookupModule(LookupBase): + def run(self, terms, variables, **kwargs): + self.set_options(var_options=variables, direct=kwargs) + server_url = self.get_option("server_url") + site = self.get_option("site") + user = self.get_option("automation_user") + secret = self.get_option("automation_secret") + validate_certs = self.get_option("validate_certs") + + site_url = server_url + "/" + site + + api = CheckMKLookupAPI( + site_url=site_url, + user=user, + secret=secret, + validate_certs=validate_certs, + ) + + ret = [] + + for term in terms: + response = json.loads(api.get("/objects/site_connection/" + term)) + + if "code" in response: + raise AnsibleError( + "Received error for %s - %s: %s" + % ( + response.get("url", ""), + response.get("code", ""), + response.get("msg", ""), + ) + ) + + ret.append(response.get("extensions", {})) + + return ret diff --git a/plugins/lookup/sites.py b/plugins/lookup/sites.py new file mode 100644 index 000000000..2c51feb54 --- /dev/null +++ b/plugins/lookup/sites.py @@ -0,0 +1,153 @@ +# Copyright: (c) 2023, Lars Getwan +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = """ + name: sites + author: Lars Getwan (@lgetwan) + version_added: "5.3.0" + + short_description: Get a list of all sites + + description: + - Returns a list of all sites and their configuration. + + options: + + server_url: + description: URL of the Checkmk server. + required: True + vars: + - name: ansible_lookup_checkmk_server_url + env: + - name: ANSIBLE_LOOKUP_CHECKMK_SERVER_URL + ini: + - section: checkmk_lookup + key: server_url + + site: + description: Site name for REST API access. + required: True + vars: + - name: ansible_lookup_checkmk_site + env: + - name: ANSIBLE_LOOKUP_CHECKMK_SITE + ini: + - section: checkmk_lookup + key: site + + automation_user: + description: Automation user for the REST API access. + required: True + vars: + - name: ansible_lookup_checkmk_automation_user + env: + - name: ANSIBLE_LOOKUP_CHECKMK_AUTOMATION_USER + ini: + - section: checkmk_lookup + key: automation_user + + automation_secret: + description: Automation secret for the REST API access. + required: True + vars: + - name: ansible_lookup_checkmk_automation_secret + env: + - name: ANSIBLE_LOOKUP_CHECKMK_AUTOMATION_SECRET + ini: + - section: checkmk_lookup + key: automation_secret + + validate_certs: + description: Whether or not to validate TLS certificates. + type: boolean + required: False + default: True + vars: + - name: ansible_lookup_checkmk_validate_certs + env: + - name: ANSIBLE_LOOKUP_CHECKMK_VALIDATE_CERTS + ini: + - section: checkmk_lookup + key: validate_certs + + notes: + - Like all lookups, this runs on the Ansible controller and is unaffected by other keywords such as 'become'. + If you need to use different permissions, you must change the command or run Ansible as another user. + - Alternatively, you can use a shell/command task that runs against localhost and registers the result. + - The directory of the play is used as the current working directory. + - It is B(NOT) possible to assign other variables to the variables mentioned in the C(vars) section! + This is a limitation of Ansible itself. +""" + +EXAMPLES = """ +- name: Get all sites defined in the environment. + ansible.builtin.debug: + msg: "Site: {{ item.extensions }}" + loop: "{{ + lookup('checkmk.general.sites', + server_url=server_url, + site=site, + automation_user=automation_user, + automation_secret=automation_secret, + validate_certs=False + ) + }}" + loop_control: + label: "{{ item.id }}" +""" + +RETURN = """ + _list: + description: + - A list of all sites + type: list + elements: str +""" + +import json + +from ansible.errors import AnsibleError +from ansible.plugins.lookup import LookupBase +from ansible_collections.checkmk.general.plugins.module_utils.lookup_api import ( + CheckMKLookupAPI, +) + + +class LookupModule(LookupBase): + def run(self, terms, variables, **kwargs): + regex_params = {} + self.set_options(var_options=variables, direct=kwargs) + server_url = self.get_option("server_url") + site = self.get_option("site") + user = self.get_option("automation_user") + secret = self.get_option("automation_secret") + validate_certs = self.get_option("validate_certs") + + site_url = server_url + "/" + site + + api = CheckMKLookupAPI( + site_url=site_url, + user=user, + secret=secret, + validate_certs=validate_certs, + ) + + response = json.loads(api.get("/domain-types/site_connection/collections/all")) + + if "code" in response: + raise AnsibleError( + "Received error for %s - %s: %s" + % ( + response.get("url", ""), + response.get("code", ""), + response.get("msg", ""), + ) + ) + + site_list = response.get("value") + + return [site_list] diff --git a/tests/integration/targets/lookup_site/lookup_site/tasks/main.yml b/tests/integration/targets/lookup_site/lookup_site/tasks/main.yml new file mode 100644 index 000000000..bbb3963bc --- /dev/null +++ b/tests/integration/targets/lookup_site/lookup_site/tasks/main.yml @@ -0,0 +1,13 @@ +--- +- name: "Include Global Variables." + ansible.builtin.include_vars: /root/ansible_collections/checkmk/general/tests/integration/files/includes/vars/global.yml + +- name: "Run Preparations." + ansible.builtin.include_tasks: /root/ansible_collections/checkmk/general/tests/integration/files/includes/tasks/prep.yml + +- name: "Testing." + ansible.builtin.include_tasks: test.yml + loop: "{{ test_sites }}" + loop_control: + loop_var: outer_item + when: (download_pass is defined and download_pass | length) or outer_item.edition == "cre" diff --git a/tests/integration/targets/lookup_site/lookup_site/tasks/test.yml b/tests/integration/targets/lookup_site/lookup_site/tasks/test.yml new file mode 100644 index 000000000..086c1f325 --- /dev/null +++ b/tests/integration/targets/lookup_site/lookup_site/tasks/test.yml @@ -0,0 +1,31 @@ +--- +- name: " {{ outer_item.version }} - {{ outer_item.edition | upper }} - Get config of the site." + ansible.builtin.debug: + msg: "Config of site {{ site.id }} is {{ site.extensions }}" + vars: + site: "{{ lookup('checkmk.general.site', + outer_item.site, + server_url=checkmk_var_server_url, + site=outer_item.site, + validate_certs=False, + automation_user=checkmk_var_automation_user, + automation_secret=checkmk_var_automation_secret) + }}[0]" + delegate_to: localhost + run_once: true # noqa run-once[task] + +- name: "{{ outer_item.version }} - {{ outer_item.edition | upper }} - Verify local connection." + ansible.builtin.assert: + that: "extensions.status_connection.connection.socket_type == 'local'" + vars: + extensions: "{{ lookup('checkmk.general.site', + outer_item.site, + server_url=checkmk_var_server_url, + site=outer_item.site, + validate_certs=False, + automation_user=checkmk_var_automation_user, + automation_secret=checkmk_var_automation_secret) + }}" + delegate_to: localhost + run_once: true # noqa run-once[task] + diff --git a/tests/integration/targets/lookup_site/lookup_site/vars/main.yml b/tests/integration/targets/lookup_site/lookup_site/vars/main.yml new file mode 100644 index 000000000..d5c692f5c --- /dev/null +++ b/tests/integration/targets/lookup_site/lookup_site/vars/main.yml @@ -0,0 +1,11 @@ +--- +test_sites: + - version: "2.3.0p13" + edition: "cee" + site: "stable_cee" + - version: "2.3.0p13" + edition: "cre" + site: "stable_cre" + - version: "2.2.0p32" + edition: "cre" + site: "old_cre" diff --git a/tests/integration/targets/lookup_site/tasks/main.yml b/tests/integration/targets/lookup_site/tasks/main.yml new file mode 100644 index 000000000..bbb3963bc --- /dev/null +++ b/tests/integration/targets/lookup_site/tasks/main.yml @@ -0,0 +1,13 @@ +--- +- name: "Include Global Variables." + ansible.builtin.include_vars: /root/ansible_collections/checkmk/general/tests/integration/files/includes/vars/global.yml + +- name: "Run Preparations." + ansible.builtin.include_tasks: /root/ansible_collections/checkmk/general/tests/integration/files/includes/tasks/prep.yml + +- name: "Testing." + ansible.builtin.include_tasks: test.yml + loop: "{{ test_sites }}" + loop_control: + loop_var: outer_item + when: (download_pass is defined and download_pass | length) or outer_item.edition == "cre" diff --git a/tests/integration/targets/lookup_site/tasks/test.yml b/tests/integration/targets/lookup_site/tasks/test.yml new file mode 100644 index 000000000..086c1f325 --- /dev/null +++ b/tests/integration/targets/lookup_site/tasks/test.yml @@ -0,0 +1,31 @@ +--- +- name: " {{ outer_item.version }} - {{ outer_item.edition | upper }} - Get config of the site." + ansible.builtin.debug: + msg: "Config of site {{ site.id }} is {{ site.extensions }}" + vars: + site: "{{ lookup('checkmk.general.site', + outer_item.site, + server_url=checkmk_var_server_url, + site=outer_item.site, + validate_certs=False, + automation_user=checkmk_var_automation_user, + automation_secret=checkmk_var_automation_secret) + }}[0]" + delegate_to: localhost + run_once: true # noqa run-once[task] + +- name: "{{ outer_item.version }} - {{ outer_item.edition | upper }} - Verify local connection." + ansible.builtin.assert: + that: "extensions.status_connection.connection.socket_type == 'local'" + vars: + extensions: "{{ lookup('checkmk.general.site', + outer_item.site, + server_url=checkmk_var_server_url, + site=outer_item.site, + validate_certs=False, + automation_user=checkmk_var_automation_user, + automation_secret=checkmk_var_automation_secret) + }}" + delegate_to: localhost + run_once: true # noqa run-once[task] + diff --git a/tests/integration/targets/lookup_site/vars/main.yml b/tests/integration/targets/lookup_site/vars/main.yml new file mode 100644 index 000000000..d5c692f5c --- /dev/null +++ b/tests/integration/targets/lookup_site/vars/main.yml @@ -0,0 +1,11 @@ +--- +test_sites: + - version: "2.3.0p13" + edition: "cee" + site: "stable_cee" + - version: "2.3.0p13" + edition: "cre" + site: "stable_cre" + - version: "2.2.0p32" + edition: "cre" + site: "old_cre" diff --git a/tests/integration/targets/lookup_sites/tasks/main.yml b/tests/integration/targets/lookup_sites/tasks/main.yml new file mode 100644 index 000000000..bbb3963bc --- /dev/null +++ b/tests/integration/targets/lookup_sites/tasks/main.yml @@ -0,0 +1,13 @@ +--- +- name: "Include Global Variables." + ansible.builtin.include_vars: /root/ansible_collections/checkmk/general/tests/integration/files/includes/vars/global.yml + +- name: "Run Preparations." + ansible.builtin.include_tasks: /root/ansible_collections/checkmk/general/tests/integration/files/includes/tasks/prep.yml + +- name: "Testing." + ansible.builtin.include_tasks: test.yml + loop: "{{ test_sites }}" + loop_control: + loop_var: outer_item + when: (download_pass is defined and download_pass | length) or outer_item.edition == "cre" diff --git a/tests/integration/targets/lookup_sites/tasks/test.yml b/tests/integration/targets/lookup_sites/tasks/test.yml new file mode 100644 index 000000000..045e00bff --- /dev/null +++ b/tests/integration/targets/lookup_sites/tasks/test.yml @@ -0,0 +1,29 @@ +--- +- name: " {{ outer_item.version }} - {{ outer_item.edition | upper }} - Get config of the site." + ansible.builtin.debug: + msg: "Config of site {{ site.id }} is {{ site.extensions }}" + vars: + site: "{{ lookup('checkmk.general.sites', + server_url=checkmk_var_server_url, + site=outer_item.site, + validate_certs=False, + automation_user=checkmk_var_automation_user, + automation_secret=checkmk_var_automation_secret) + }}[0]" + delegate_to: localhost + run_once: true # noqa run-once[task] + +- name: "{{ outer_item.version }} - {{ outer_item.edition | upper }} - Verify local connection." + ansible.builtin.assert: + that: "extensions.status_connection.connection.socket_type == 'local'" + vars: + extensions: "{{ lookup('checkmk.general.sites', + server_url=checkmk_var_server_url, + site=outer_item.site, + validate_certs=False, + automation_user=checkmk_var_automation_user, + automation_secret=checkmk_var_automation_secret) + }}[0]" + delegate_to: localhost + run_once: true # noqa run-once[task] + diff --git a/tests/integration/targets/lookup_sites/vars/main.yml b/tests/integration/targets/lookup_sites/vars/main.yml new file mode 100644 index 000000000..d5c692f5c --- /dev/null +++ b/tests/integration/targets/lookup_sites/vars/main.yml @@ -0,0 +1,11 @@ +--- +test_sites: + - version: "2.3.0p13" + edition: "cee" + site: "stable_cee" + - version: "2.3.0p13" + edition: "cre" + site: "stable_cre" + - version: "2.2.0p32" + edition: "cre" + site: "old_cre"