diff --git a/.github/labels-issues.yml b/.github/labels-issues.yml index b1517633a..2abebe934 100644 --- a/.github/labels-issues.yml +++ b/.github/labels-issues.yml @@ -23,6 +23,9 @@ module:bakery: module:contact_group: - 'Component Name: contact_group' +module:dcd: + - 'Component Name: dcd' + module:discovery: - 'Component Name: discovery' diff --git a/.github/labels-prs.yml b/.github/labels-prs.yml index 3dc75767c..c5bcfcf07 100644 --- a/.github/labels-prs.yml +++ b/.github/labels-prs.yml @@ -34,6 +34,11 @@ module:contact_group: - changed-files: - any-glob-to-any-file: 'plugins/modules/contact_group.py' +module:dcd: + - any: + - changed-files: + - any-glob-to-any-file: 'plugins/modules/dcd.py' + module:discovery: - any: - changed-files: diff --git a/.github/workflows/ans-int-test-dcd.yaml b/.github/workflows/ans-int-test-dcd.yaml new file mode 100644 index 000000000..551eed48d --- /dev/null +++ b/.github/workflows/ans-int-test-dcd.yaml @@ -0,0 +1,95 @@ +# 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: dcd + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +name: Ansible Integration Tests for DCD Module +on: + workflow_dispatch: + schedule: + - cron: '0 0 * * 0' + pull_request: + branches: + - main + - devel + paths: + - 'plugins/modules/dcd.py' + push: + paths: + - '.github/workflows/ans-int-test-dcd.yaml' + - 'plugins/modules/dcd.py' + - 'tests/integration/files/includes/' + - 'tests/integration/targets/activation/' + +jobs: + + integration: + runs-on: ubuntu-24.04 + name: Ⓐ${{ matrix.ansible }}+py${{ matrix.python }} + strategy: + fail-fast: false + matrix: + ansible: + - stable-2.17 + - stable-2.18 + - stable-2.19 + - devel + python: + - '3.11' + - '3.12' + exclude: + # Exclude unsupported sets. + - ansible: devel + python: '3.11' + + services: + old_cme: + image: checkmk/check-mk-managed:2.3.0p38 + ports: + - 5323:5000 + env: + CMK_SITE_ID: "old_cme" + CMK_PASSWORD: "Sup3rSec4et!" + stable_cme: + image: checkmk/check-mk-managed:2.4.0p13 + ports: + - 5324:5000 + env: + CMK_SITE_ID: "stable_cme" + CMK_PASSWORD: "Sup3rSec4et!" + + steps: + - name: Check out code + uses: actions/checkout@v5 + with: + path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + + - name: "Install uv and set the python version." + uses: astral-sh/setup-uv@v7 + with: + python-version: ${{ matrix.python }} + enable-cache: true + working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}}/ + + - name: "Setup uv venv." + run: uv venv + working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + + - name: Install ansible-base (${{ matrix.ansible }}) + run: uv pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz + working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + + - name: Run integration test + run: uv run ansible-test integration ${{env.MODULE_NAME}} -v --color --continue-on-error --diff --python ${{ matrix.python }} + working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} diff --git a/changelogs/fragments/dcd.yml b/changelogs/fragments/dcd.yml new file mode 100644 index 000000000..2b39d8fe3 --- /dev/null +++ b/changelogs/fragments/dcd.yml @@ -0,0 +1,2 @@ +minor_changes: + - DCD module - Add DCD module. diff --git a/meta/runtime.yml b/meta/runtime.yml index 3a11d53cd..6b19911df 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -5,6 +5,7 @@ action_groups: - activation - bakery - contact_group + - dcd - discovery - downtime - folder diff --git a/playbooks/demo/dcd.yml b/playbooks/demo/dcd.yml new file mode 100644 index 000000000..aaee9a715 --- /dev/null +++ b/playbooks/demo/dcd.yml @@ -0,0 +1,129 @@ +--- +- name: "Showcase dcd module." + hosts: test + strategy: linear + gather_facts: false + vars_files: + - ../vars/auth.yml # This vars file provides details about your site + - ../vars/folders.yml # This vars file contains the folders to manage + - ../vars/dcd.yml # This vars file contains the groups to manage + tasks: + # - name: "Gather Date and Time Facts on localhost." + # ansible.builtin.setup: + # gather_subset: + # - date_time + # delegate_to: localhost + # run_once: true # noqa run-once[task] + + - name: "Create folders." + folder: + server_url: "{{ checkmk_var_server_url }}" + site: "{{ checkmk_var_site }}" + automation_user: "{{ checkmk_var_automation_user }}" + automation_secret: "{{ checkmk_var_automation_secret }}" + path: "{{ item.path }}" + name: "{{ item.name }}" + state: "present" + delegate_to: localhost + run_once: true # noqa run-once[task] + loop: "{{ checkmk_var_folders }}" + + - name: "Create hosts." + host: + server_url: "{{ checkmk_var_server_url }}" + site: "{{ checkmk_var_site }}" + automation_user: "{{ checkmk_var_automation_user }}" + automation_secret: "{{ checkmk_var_automation_secret }}" + name: "{{ inventory_hostname }}" + folder: "{{ checkmk_var_folder_path }}" + attributes: + site: "{{ checkmk_var_site }}" + ipaddress: 127.0.0.1 + state: "present" + delegate_to: localhost + + - name: "Create DCD Configuration." + dcd: + server_url: "{{ checkmk_var_server_url }}" + site: "{{ checkmk_var_site }}" + automation_user: "{{ checkmk_var_automation_user }}" + automation_secret: "{{ checkmk_var_automation_secret }}" + dcd_config: "{{ item }}" + state: "present" + loop: "{{ checkmk_var_dcd }}" + run_once: true # noqa run-once[task] + delegate_to: localhost + + - name: "Pause to review changes." # noqa name[unique] + ansible.builtin.pause: + prompt: | + "Feel free to review the changes in your Checkmk site: {{ checkmk_var_site }}." + "Press to continue." + when: not checkmk_var_run_unattended | bool + + - name: "Activate changes on site." # noqa name[unique] + activation: + server_url: "{{ checkmk_var_server_url }}" + site: "{{ checkmk_var_site }}" + automation_user: "{{ checkmk_var_automation_user }}" + automation_secret: "{{ checkmk_var_automation_secret }}" + force_foreign_changes: 'true' + sites: + - "{{ checkmk_var_site }}" + delegate_to: localhost + run_once: true # noqa run-once[task] + + - name: "Delete DCD Configuration." + dcd: + server_url: "{{ checkmk_var_server_url }}" + site: "{{ checkmk_var_site }}" + automation_user: "{{ checkmk_var_automation_user }}" + automation_secret: "{{ checkmk_var_automation_secret }}" + dcd_config: "{{ item }}" + state: "absent" + loop: "{{ checkmk_var_dcd }}" + run_once: true # noqa run-once[task] + delegate_to: localhost + + - name: "Delete Hosts." + host: + server_url: "{{ checkmk_var_server_url }}" + site: "{{ checkmk_var_site }}" + automation_user: "{{ checkmk_var_automation_user }}" + automation_secret: "{{ checkmk_var_automation_secret }}" + name: "{{ inventory_hostname }}" + folder: "{{ checkmk_var_folder_path }}" + state: "absent" + delegate_to: localhost + + - name: "Delete folders." + folder: + server_url: "{{ checkmk_var_server_url }}" + site: "{{ checkmk_var_site }}" + automation_user: "{{ checkmk_var_automation_user }}" + automation_secret: "{{ checkmk_var_automation_secret }}" + path: "{{ item.path }}" + name: "{{ item.name }}" + state: "absent" + delegate_to: localhost + run_once: true # noqa run-once[task] + loop: "{{ checkmk_var_folders }}" + + - name: "Pause to review changes." # noqa name[unique] + ansible.builtin.pause: + prompt: | + "Feel free to review the changes in your Checkmk site: {{ checkmk_var_site }}." + "Press to continue." + when: not checkmk_var_run_unattended | bool + + - name: "Activate changes on site." # noqa name[unique] + activation: + server_url: "{{ checkmk_var_server_url }}" + site: "{{ checkmk_var_site }}" + automation_user: "{{ checkmk_var_automation_user }}" + automation_secret: "{{ checkmk_var_automation_secret }}" + force_foreign_changes: 'true' + sites: + - "{{ checkmk_var_site }}" + delegate_to: localhost + run_once: true # noqa run-once[task] diff --git a/playbooks/vars/dcd.yml b/playbooks/vars/dcd.yml new file mode 100644 index 000000000..c6f5b3fe3 --- /dev/null +++ b/playbooks/vars/dcd.yml @@ -0,0 +1,20 @@ +--- +checkmk_var_dcd: + + - title: "vSphere" + dcd_id: "vsphere" + comment: "Main vSphere Connector" + # site: "mysite" + connector: + connector_type: "piggyback" + interval: 60 + creation_rules: + - folder_path: "/" + delete_hosts: false + host_attributes: + tag_address_family: "no-ip" + tag_agent: "special-agents" + tag_piggyback: "piggyback" + tag_snmp_ds: "no-snmp" + discover_on_creation: true + restrict_source_hosts: "localhost" diff --git a/plugins/modules/dcd.py b/plugins/modules/dcd.py new file mode 100644 index 000000000..4fc32f2c8 --- /dev/null +++ b/plugins/modules/dcd.py @@ -0,0 +1,529 @@ +#!/usr/bin/python +# -*- encoding: utf-8; py-indent-offset: 4 -*- + +# Copyright: (c) 2025, Lars Getwan +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# This code was originally authored by Atruvia AG (https://atruvia.de/) +# and subsequently modified by Checkmk. +# Thank you so much for donating this code! + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = r""" +--- +module: dcd +short_description: Manage Dynamic Host Management. +version_added: "6.3.0" +description: + - Manage Dynamic Host Management (DCD), including creation, updating, and deletion. +extends_documentation_fragment: [checkmk.general.common] +options: + dcd_config: + description: Configuration parameters for the DCD. + type: dict + required: true + suboptions: + dcd_id: + description: Identifier for the DCD configuration. + type: str + required: true + title: + description: Title of the DCD. + type: str + required: false + comment: + description: Description or comment for the DCD. + type: str + default: "" + site: + description: Name of the Checkmk site for the DCD configuration. + type: str + required: false + connector: + description: DCD Connector configuration. + type: dict + required: false + suboptions: + connector_type: + description: Type of connector (e.g., "piggyback"). + type: str + default: piggyback + interval: + description: Interval in seconds for DCD polling. + type: int + default: 60 + creation_rules: + description: Rules for creating hosts. + type: list + elements: dict + suboptions: + folder_path: + description: Folder path for host creation. + type: str + required: true + delete_hosts: + description: Whether to delete hosts that no longer exist. + type: bool + default: false + matching_hosts: + description: Restrict host creation using regular expressions. + type: list + elements: str + default: [] + host_attributes: + description: Additional host attributes to set on created hosts. + type: dict + discover_on_creation: + description: Discover services on host creation. + type: bool + default: true + restrict_source_hosts: + description: List of hosts to consider as piggyback sources for the DCD connection. + type: list + elements: str + default: [] + no_deletion_time_after_init: + description: Seconds to prevent host deletion after site startup. + type: int + default: 600 + max_cache_age: + description: Seconds to keep hosts when piggyback source only sends piggyback data for other hosts. + type: int + default: 3600 + validity_period: + description: Seconds before piggyback data is considered outdated. + type: int + default: 60 + state: + description: Desired state of the DCD connection. + type: str + choices: + - present + - absent + default: present +author: + - Lars Getwan (@lgetwan) +""" + +EXAMPLES = r""" +- name: Create a DCD configuration + checkmk.general.dcd: + server_url: "http://myserver/" + site: "mysite" + automation_auth_type: "bearer" + automation_user: "myuser" + automation_secret: "mysecret" + dcd_config: + dcd_id: "PiggybackCluster1" + title: "Piggyback Configuration for Cluster1" + comment: "Piggyback config for Cluster1 host" + site: "mysite" + connector_type: "piggyback" + interval: 60 + creation_rules: + - folder_path: "/cluster1" + delete_hosts: false + host_attributes: + tag_address_family: "no-ip" + tag_agent: "special-agents" + tag_piggyback: "piggyback" + tag_snmp_ds: "no-snmp" + discover_on_creation: true + restrict_source_hosts: + - "cluster1" + state: "present" +- name: Delete a DCD configuration + checkmk.general.dcd: + server_url: "http://myserver/" + site: "mysite" + automation_auth_type: "bearer" + automation_user: "myuser" + automation_secret: "mysecret" + dcd_config: + dcd_id: "PiggybackCluster1" + site: "mysite" + state: "absent" +""" + +RETURN = r""" +msg: + description: + - The output message that the module generates. + type: str + returned: always +http_code: + description: + - HTTP code returned by the Checkmk API. + type: int + returned: always +content: + description: + - Content of the DCD object. + returned: when state is present and DCD created or updated. + type: dict +diff: + description: + - The diff between the current and desired state. + type: dict + returned: when differences are detected or in diff mode +""" + +import json + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.checkmk.general.plugins.module_utils.api import ( + CheckmkAPI, +) +from ansible_collections.checkmk.general.plugins.module_utils.differ import ConfigDiffer +from ansible_collections.checkmk.general.plugins.module_utils.logger import Logger +from ansible_collections.checkmk.general.plugins.module_utils.utils import ( + base_argument_spec, + exit_module, +) + +logger = Logger() + + +class DCDHTTPCodes: + """ + DCDHTTPCodes defines the HTTP status codes and corresponding messages + for DCD operations such as GET, CREATE, EDIT, and DELETE. + """ + + get = { + 200: (False, False, "DCD configuration found, nothing changed"), + 404: (False, False, "DCD configuration not found"), + } + create = { + 200: (True, False, "DCD configuration created"), + 201: (True, False, "DCD configuration created"), + 204: (True, False, "DCD configuration created"), + 405: (False, True, "Method Not Allowed"), + } + edit = { + 200: (True, False, "DCD configuration modified"), + 405: (False, True, "Method Not Allowed"), + } + delete = { + 204: (True, False, "DCD configuration deleted"), + 405: (False, True, "Method Not Allowed"), + } + + +class DCDAPI(CheckmkAPI): + """ + Manages DCD operations via the Checkmk API. + """ + + def __init__(self, module): + """ + Initializes the DCDAPI class, retrieves the current state of the DCD configuration. + Args: + module (AnsibleModule): The Ansible module object. + """ + super().__init__(module) + dcd_config = self.params.get("dcd_config") + if not dcd_config or "dcd_id" not in dcd_config: + exit_module( + self.module, + msg="Missing 'dcd_id' in dcd_config dictionary", + failed=True, + logger=logger, + ) + + self.dcd_id = dcd_config["dcd_id"] + self.desired = dcd_config.copy() + + # Ensure 'site' is present in the desired state + if "site" not in self.desired or self.desired["site"] is None: + self.desired["site"] = self.params.get("site") + if self.desired["site"] is None: + exit_module( + self.module, + msg="`site` is required in dcd_config.", + failed=True, + logger=logger, + ) + + # Ensure 'comment' is not null + if "comment" not in self.desired or self.desired["comment"] is None: + self.desired["comment"] = "" + + # Completely remove parameters that contain empty lists + if "connector" in self.desired and isinstance(self.desired["connector"], dict): + for rule in self.desired["connector"].get("creation_rules", []): + if len(rule.get("matching_hosts", [])) == 0: + del rule["matching_hosts"] + + if len(self.desired["connector"].get("restrict_source_hosts", [])) == 0: + del self.desired["connector"]["restrict_source_hosts"] + + self.state = None + + self._get_current() + + # Initialize the ConfigDiffer with desired and current configurations + self.differ = ConfigDiffer(self.desired, self.current) + + def _get_current(self): + """ + Retrieves the current state of the DCD configuration from the Checkmk API. + """ + endpoint = self._build_endpoint(action="get") + result = self._fetch( + code_mapping=DCDHTTPCodes.get, + endpoint=endpoint, + logger=logger, + method="GET", + ) + + if result.http_code == 200: + self.state = "present" + try: + current_raw = json.loads(result.content) + self.current = current_raw.get("extensions", {}) + self.current["dcd_id"] = current_raw.get("id") + + except json.JSONDecodeError: + exit_module( + self.module, + msg="Failed to decode JSON response from API.", + content=result.content, + failed=True, + logger=logger, + ) + else: + self.state = "absent" + self.current = {} + + def _build_endpoint(self, action="get"): + """ + Builds the API endpoint URL for the DCD configuration. + Args: + action (str): The action for which to build the endpoint. Options are 'create', 'get', 'edit', 'delete'. + Returns: + str: API endpoint URL. + """ + if action == "create": + return "/domain-types/dcd/collections/all" + elif action in ["get", "edit", "delete"]: + return "/objects/dcd/%s" % self.dcd_id + else: + exit_module( + self.module, + msg="Unsupported action '%s' for building endpoint." % action, + failed=True, + logger=logger, + ) + + def needs_update(self): + """ + Determines whether an update to the DCD configuration is needed. + Returns: + bool: True if changes are needed, False otherwise. + """ + return self.differ.needs_update() + + def generate_diff(self, deletion=False): + """ + Generates a diff between the current and desired state. + Args: + deletion (bool): Whether the diff is for a deletion. + Returns: + dict: Dictionary containing 'before' and 'after' states. + """ + return self.differ.generate_diff(deletion) + + def _perform_action(self, action, method, data=None): + """ + Helper method to perform CRUD actions. + Args: + action (str): The action being performed ('create', 'edit', 'delete'). + method (str): The HTTP method. + data (dict, optional): The data to send with the request. + Returns: + dict: The result dictionary. + """ + endpoint = self._build_endpoint(action=action) + + diff = None + if self.module._diff: + deletion_flag = action == "delete" + diff = self.generate_diff(deletion=deletion_flag) + + if self.module.check_mode: + action_msgs = { + "create": "would be created", + "edit": "would be modified", + "delete": "would be deleted", + } + return dict( + msg="DCD configuration %s." % action_msgs.get(action, action), + changed=True, # Indicate that changes would occur + diff=diff, + ) + + return self._fetch( + code_mapping=getattr(DCDHTTPCodes, action), + endpoint=endpoint, + data=data, + logger=logger, + method=method, + ) + + def create(self): + """ + Creates a new DCD configuration via the Checkmk API. + Returns: + dict: The result of the creation operation. + """ + filtered_data = {k: v for k, v in self.desired.items() if v is not None} + return self._perform_action(action="create", method="POST", data=filtered_data) + + def edit(self): + """ + Updates an existing DCD configuration via the Checkmk API. + Returns: + dict: The result of the update operation. + """ + filtered_data = {k: v for k, v in self.desired.items() if v is not None} + return self._perform_action(action="edit", method="PUT", data=filtered_data) + + def delete(self): + """ + Deletes an existing DCD configuration via the Checkmk API. + Returns: + dict: The result of the deletion operation. + """ + return self._perform_action(action="delete", method="DELETE") + + +def run_module(): + """ + The main logic for the Ansible module. + This function defines the module parameters, initializes the DCDAPI, and performs + the appropriate action (create or delete) based on the state of the DCD configuration. + Note: Update functionality is currently disabled due to the lack of a REST API endpoint for updates. + Returns: + None: The result is returned to Ansible via module.exit_json(). + """ + + argument_spec = base_argument_spec() + argument_spec.update( + server_url=dict(type="str", required=True), + site=dict(type="str", required=True), + dcd_config=dict( + type="dict", + required=True, + options={ + "dcd_id": dict(type="str", required=True), + "title": dict(type="str", required=False), + "comment": dict(type="str", default=""), + "site": dict(type="str", required=False), + "connector": dict( + type="dict", + options={ + "connector_type": dict(type="str", default="piggyback"), + "interval": dict(type="int", default=60), + "creation_rules": dict( + type="list", + elements="dict", + options={ + "folder_path": dict(type="str", required=True), + "delete_hosts": dict(type="bool", default=False), + "matching_hosts": dict( + type="list", + elements="str", + required=False, + default=[], + ), + "host_attributes": dict(type="dict", required=False), + }, + ), + "discover_on_creation": dict(type="bool", default=True), + "restrict_source_hosts": dict( + type="list", elements="str", required=False, default=[] + ), + "no_deletion_time_after_init": dict( + type="int", required=False, default=600 + ), + "max_cache_age": dict(type="int", required=False, default=3600), + "validity_period": dict(type="int", required=False, default=60), + }, + ), + }, + ), + state=dict(type="str", default="present", choices=["present", "absent"]), + ) + + required_if = [ + ("api_auth_type", "bearer", ["automation_user", "automation_secret"]), + ("api_auth_type", "basic", ["automation_user", "automation_secret"]), + ("api_auth_type", "cookie", ["api_auth_cookie"]), + ] + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=required_if, + ) + + logger.set_loglevel(module._verbosity) + logger.set_loglevel(2) + + desired_state = module.params["state"] + dcd_api = DCDAPI(module) + + try: + if desired_state == "present": + if dcd_api.state == "absent": + result = dcd_api.create() + exit_module(module, result=result, logger=logger) + elif dcd_api.needs_update(): + exit_module( + module, + msg="DCD object cannot be updated. No REST API endpoint available for updates. Diff: %s" + % str(dcd_api.generate_diff()), + failed=True, + logger=logger, + ) + + else: + exit_module( + module, + msg="DCD configuration is already in the desired state.", + logger=logger, + ) + + elif desired_state == "absent": + if dcd_api.state == "present": + result = dcd_api.delete() + exit_module(module, result=result, logger=logger) + else: + exit_module( + module, + msg="DCD configuration is already absent.", + logger=logger, + ) + + except Exception as e: + exit_module( + module, msg="Error managing the DCD configuration: %s" % e, logger=logger + ) + + +def main(): + """ + Main entry point for the module. + This function is invoked when the module is executed directly. + Returns: + None: Calls run_module() to handle the logic. + """ + run_module() + + +if __name__ == "__main__": + main() diff --git a/tests/integration/targets/dcd/tasks/main.yml b/tests/integration/targets/dcd/tasks/main.yml new file mode 100644 index 000000000..238480fa2 --- /dev/null +++ b/tests/integration/targets/dcd/tasks/main.yml @@ -0,0 +1,35 @@ +--- +- name: "Include Global Variables." + ansible.builtin.include_vars: "{{ lookup('ansible.builtin.first_found', checkmk_var_params) }}" + vars: + checkmk_var_params: + files: + - global.yml + paths: + - /home/runner/work/ansible-collection-checkmk.general/ansible-collection-checkmk.general/ansible_collections/checkmk/general/tests/integration/files/includes/vars/ + - /root/ansible_collections/checkmk/general/tests/integration/files/includes/vars/ + - tests/integration/files/includes/vars/ + +- name: "Print Identifier." + ansible.builtin.debug: + msg: "{{ ansible_facts.system_vendor }} {{ ansible_facts.product_name }} running {{ ansible_facts.virtualization_type }}" + +- name: "Run preparations." + ansible.builtin.include_tasks: "{{ lookup('ansible.builtin.first_found', checkmk_var_params) }}" + vars: + checkmk_var_params: + files: + - prep.yml + paths: + - /home/runner/work/ansible-collection-checkmk.general/ansible-collection-checkmk.general/ansible_collections/checkmk/general/tests/integration/files/includes/tasks/ + - /root/ansible_collections/checkmk/general/tests/integration/files/includes/tasks/ + - tests/integration/files/includes/tasks/ + when: | + (ansible_facts.system_vendor == "Dell Inc." and 'Latitude' in ansible_facts.product_name and ansible_facts.virtualization_type == "container") + or (ansible_facts.system_vendor == "QEMU" and 'Ubuntu' in ansible_facts.product_name and ansible_facts.virtualization_type == "container") + +- name: "Testing." + ansible.builtin.include_tasks: test.yml + loop: "{{ checkmk_var_test_sites }}" + loop_control: + loop_var: outer_item diff --git a/tests/integration/targets/dcd/tasks/test.yml b/tests/integration/targets/dcd/tasks/test.yml new file mode 100644 index 000000000..76896c769 --- /dev/null +++ b/tests/integration/targets/dcd/tasks/test.yml @@ -0,0 +1,83 @@ +--- +- name: "{{ outer_item.version }} - {{ outer_item.edition | upper }} - Set customer when needed." + ansible.builtin.set_fact: + checkmk_var_customer: "provider" + when: (outer_item.edition == "cme") or (outer_item.edition == "cce") + +- name: "{{ outer_item.version }} - {{ outer_item.edition | upper }} - Unset customer when needed." + ansible.builtin.set_fact: + checkmk_var_customer: null + when: not ((outer_item.edition == "cme") or (outer_item.edition == "cce")) + +- name: "{{ outer_item.version }} - {{ outer_item.edition | upper }} - Create a DCD configuration." + dcd: + server_url: "{{ checkmk_var_server_url }}" + site: "{{ outer_item.site }}" + automation_user: "{{ checkmk_var_automation_user }}" + automation_secret: "{{ checkmk_var_automation_secret }}" + api_auth_type: "bearer" + dcd_config: + dcd_id: "PiggybackBoar" + title: "Piggyback Configuration for Boar" + comment: "Piggyback config for Boar host" + site: "{{ outer_item.site }}" + connector: + connector_type: "piggyback" + interval: 5 + creation_rules: + - folder_path: "/" + delete_hosts: false + host_attributes: + tag_address_family: "no-ip" + tag_agent: "special-agents" + tag_piggyback: "piggyback" + tag_snmp_ds: "no-snmp" + discover_on_creation: true + restrict_source_hosts: + - "boar" + state: "present" + delegate_to: localhost + +- name: "{{ outer_item.version }} - {{ outer_item.edition | upper }} - Create a DCD conf. Again!" + dcd: + server_url: "{{ checkmk_var_server_url }}" + site: "{{ outer_item.site }}" + automation_user: "{{ checkmk_var_automation_user }}" + automation_secret: "{{ checkmk_var_automation_secret }}" + api_auth_type: "bearer" + dcd_config: + dcd_id: "PiggybackBoar" + title: "Piggyback Configuration for Boar" + comment: "Piggyback config for Boar host" + site: "{{ outer_item.site }}" + connector: + connector_type: "piggyback" + interval: 5 + creation_rules: + - folder_path: "/" + delete_hosts: false + host_attributes: + tag_address_family: "no-ip" + tag_agent: "special-agents" + tag_piggyback: "piggyback" + tag_snmp_ds: "no-snmp" + discover_on_creation: true + restrict_source_hosts: + - "boar" + state: "present" + delegate_to: localhost + register: __checkmk_var_result_dcd_create + failed_when: __checkmk_var_result_dcd_create.changed + +- name: "{{ outer_item.version }} - {{ outer_item.edition | upper }} - Delete a DCD configuration." + dcd: + server_url: "{{ checkmk_var_server_url }}" + site: "{{ outer_item.site }}" + automation_user: "{{ checkmk_var_automation_user }}" + automation_secret: "{{ checkmk_var_automation_secret }}" + api_auth_type: "bearer" + dcd_config: + dcd_id: "PiggybackBoar" + site: "{{ outer_item.site }}" + state: "absent" + delegate_to: localhost diff --git a/tests/integration/targets/dcd/vars/main.yml b/tests/integration/targets/dcd/vars/main.yml new file mode 100644 index 000000000..72e464b34 --- /dev/null +++ b/tests/integration/targets/dcd/vars/main.yml @@ -0,0 +1,10 @@ +--- +checkmk_var_test_sites: + - version: "2.3.0p36" + edition: "cme" + site: "old_cme" + port: "5323" + - version: "2.4.0p10" + edition: "cme" + site: "stable_cme" + port: "5324"