Skip to content

Commit

Permalink
Add Lookup Plugins all_folders and folder
Browse files Browse the repository at this point in the history
  • Loading branch information
lgetwan committed Aug 18, 2023
1 parent d84144f commit 83292ba
Show file tree
Hide file tree
Showing 7 changed files with 352 additions and 0 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/lookup_all_folders.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
major_changes:
+ - all_folders lookup plugin - Add a lookup plugin that exposes the REST API endpoint /domain-types/folder_config/collections/all
2 changes: 2 additions & 0 deletions changelogs/fragments/lookup_folder.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
major_changes:
+ - folder lookup plugin - Add a lookup plugin that exposes the REST API endpoint /objects/folder_config/<folder>
2 changes: 2 additions & 0 deletions playbooks/demo/full.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
---
- name: "Lookup Plugins."
ansible.builtin.import_playbook: lookup.yml
- name: "Hosts and Folders."
ansible.builtin.import_playbook: hosts-and-folders.yml
- name: "Groups."
Expand Down
72 changes: 72 additions & 0 deletions playbooks/demo/lookup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
- name: "Showcase Lookup Plugins."
hosts: test
strategy: linear
gather_facts: false
vars_files:
- ../vars/auth.yml # This vars file provides details about your site
tasks:

- name: "Get Checkmk version."
debug:
msg: "Version is {{ version }}"
vars:
version: "{{ lookup('checkmk.general.version',
server_url + '/' + site,
validate_certs=False,
automation_user=automation_user,
automation_secret=automation_secret
)}}"

delegate_to: localhost
run_once: 'true'

- name: "Get all subfolders of the main folder recursively"
ansible.builtin.debug:
msg: "Folder tree: {{ item.id }}"
loop: "{{
lookup('checkmk.general.all_folders',
'~',
show_hosts=False,
recursive=True,
site_url=server_url + '/' + site,
automation_user=automation_user,
automation_secret=automation_secret,
validate_certs=False
)
}}"
loop_control:
label: "{{ item.id }}"

- name: "Get all hosts of the folder /test recursively"
ansible.builtin.debug:
msg: "Host found in {{ item.0.id }}: {{ item.1.title }}"
vars:
looping: "{{
lookup('checkmk.general.all_folders',
'~tests',
show_hosts=True,
recursive=True,
site_url=server_url + '/' + site,
automation_user=automation_user,
automation_secret=automation_secret,
validate_certs=False
)
}}"
loop: "{{ looping|subelements('members.hosts.value') }}"
loop_control:
label: "{{ item.0.id }}"

- name: "Get the attributes of folder /tests"
ansible.builtin.debug:
msg: "Attributes of folder /network: {{ attributes }}"
vars:
attributes: "{{
lookup('checkmk.general.folder',
'~tests',
site_url=server_url + '/' + site,
automation_user=automation_user,
automation_secret=automation_secret,
validate_certs=False
)
}}"
128 changes: 128 additions & 0 deletions plugins/lookup/all_folders.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Copyright: (c) 2023, Lars Getwan <[email protected]>
# 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: all_folders
author: Lars Getwan (@lgetwan)
version_added: "3.1.0"
short_description: Get various information about a folder
description:
- Returns a list of subfolders
- Returns a list of hosts of the folder
options:
_terms:
description: complete folder path using tilde as a delimiter
required: True
show_hosts:
description: Also show the hosts of the folder(s) found
type: boolean
required: False
default: False
recursive:
description: Do a recursive query
type: boolean
required: False
default: False
site_url:
description: site url
required: True
automation_user:
description: automation user for the REST API access
required: True
automation_secret:
description: automation secret for the REST API access
required: True
validate_certs:
description: Wether or not to validate TLS cerificates
type: boolean
required: False
default: True
"""

EXAMPLES = """
- name: Get all subfolders of the main folder recursively
ansible.builtin.debug:
msg: "Folder tree: {{ item.id }}"
loop: "{{
lookup('checkmk.general.all_folders',
'~',
show_hosts=False,
recursive=True,
site_url=server_url + '/' + site,
automation_user=automation_user,
automation_secret=automation_secret,
validate_certs=False
)
}}"
loop_control:
label: "{{ item.id }}"
- name: Get all hosts of the folder /test recursively
ansible.builtin.debug:
msg: "Host found in {{ item.0.id }}: {{ item.1.title }}"
vars:
looping: "{{
lookup('checkmk.general.all_folders',
'~tests',
show_hosts=True,
recursive=True,
site_url=server_url + '/' + site,
automation_user=automation_user,
automation_secret=automation_secret,
validate_certs=False
)
}}"
loop: "{{ looping|subelements('members.hosts.value') }}"
loop_control:
label: "{{ item.0.id }}"
"""

RETURN = """
_list:
description:
- A list of folders and, optionally, hosts of a folder
type: list
elements: str
"""

import json

from ansible.plugins.lookup import LookupBase
from .api import CheckMKLookupAPI


class LookupModule(LookupBase):
def run(self, terms, variables, **kwargs):
self.set_options(var_options=variables, direct=kwargs)
show_hosts = self.get_option("show_hosts")
recursive = self.get_option("recursive")
site_url = self.get_option("site_url")
user = self.get_option("automation_user")
secret = self.get_option("automation_secret")
validate_certs = self.get_option("validate_certs")

api = CheckMKLookupAPI(
site_url=site_url,
user=user,
secret=secret,
validate_certs=validate_certs,
)

ret = []
for term in terms:
parameters = {
"parent": term,
"recursive": recursive,
"show_hosts": show_hosts,
}

response = json.loads(
api.get("/domain-types/folder_config/collections/all", parameters)
)
ret.append(response.get("value"))

return ret
59 changes: 59 additions & 0 deletions plugins/lookup/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env python
# -*- encoding: utf-8; py-indent-offset: 4 -*-

# Copyright: (c) 2023, Lars Getwan <[email protected]>
# 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

from urllib.error import HTTPError, URLError
from urllib.parse import urlencode

from ansible.errors import AnsibleError
from ansible.module_utils.common.text.converters import to_native, to_text
from ansible.module_utils.urls import ConnectionError, SSLValidationError, open_url


class CheckMKLookupAPI:
"""Base class to contact a Checkmk server for ~Lookup calls"""

def __init__(self, site_url, user, secret, validate_certs=True):
self.site_url = site_url
self.user = user
self.secret = secret
self.validate_certs = validate_certs
self.url = "%s/check_mk/api/1.0" % site_url
self.headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer %s %s" % (user, secret),
}

def get(self, endpoint="", parameters={}):
url = self.url + endpoint

if parameters:
url = "%s?%s" % (url, urlencode(parameters))

response = ""
try:
raw_response = open_url(
url, headers=self.headers, validate_certs=self.validate_certs
)
response = to_text(raw_response.read())

except HTTPError as e:
raise AnsibleError("Received HTTP error for %s : %s" % (url, to_native(e)))
except URLError as e:
raise AnsibleError("Failed lookup url for %s : %s" % (url, to_native(e)))
except SSLValidationError as e:
raise AnsibleError(
"Error validating the server's certificate for %s: %s"
% (url, to_native(e))
)
except ConnectionError as e:
raise AnsibleError("Error connecting to %s: %s" % (url, to_native(e)))

return response
87 changes: 87 additions & 0 deletions plugins/lookup/folder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Copyright: (c) 2023, Lars Getwan <[email protected]>
# 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: folder
author: Lars Getwan (@lgetwan)
version_added: "3.1.0"
short_description: Get folder attributes
description:
- Returns the attributes of a folder
options:
_terms:
description: complete folder path using tilde as a delimiter
required: True
site_url:
description: site url
required: True
automation_user:
description: automation user for the REST API access
required: True
automation_secret:
description: automation secret for the REST API access
required: True
validate_certs:
description: Wether or not to validate TLS cerificates
type: boolean
required: False
default: True
"""

EXAMPLES = """
- name: Get the attributes of folder /tests
ansible.builtin.debug:
msg: "Attributes of folder /network: {{ attributes }}"
vars:
attributes: "{{
lookup('checkmk.general.folder',
'~tests',
site_url=server_url + '/' + site,
automation_user=automation_user,
automation_secret=automation_secret,
validate_certs=False
)
}}"
"""

RETURN = """
_list:
description:
- A list of dicts of attributes of the folder(s)
type: list
elements: str
"""

import json

from ansible.plugins.lookup import LookupBase
from .api import CheckMKLookupAPI


class LookupModule(LookupBase):
def run(self, terms, variables, **kwargs):
self.set_options(var_options=variables, direct=kwargs)
site_url = self.get_option("site_url")
user = self.get_option("automation_user")
secret = self.get_option("automation_secret")
validate_certs = self.get_option("validate_certs")

api = CheckMKLookupAPI(
site_url=site_url,
user=user,
secret=secret,
validate_certs=validate_certs,
)

ret = []
for term in terms:
api_endpoint = "/objects/folder_config/" + term

response = json.loads(api.get("/objects/folder_config/" + term))
ret.append(response.get("extensions", {}).get("attributes"))

return ret

0 comments on commit 83292ba

Please sign in to comment.