telekom-mms/ansible-collection-icinga-director

Provide modules to get information from Icinga Director

Closed this issue · 9 comments

Our existing modules are focused on creating, modifying and deleting objects in Icinga Director. The configuration of these objects has to be specified in Ansible. We want to extend the functionality to gather information about objects and configurations from Icinga Director into Ansible.

The behaviour should be similar to the existing Ansible *_info modules.

These should be our first targets

  • Hosts
  • Hostgroups
  • Services
  • Servicegroups
  • Service Apply Rules
  • Users
  • Notifications
  • Commands
  • * Templates

I have started to implement these and I have arrived at an descisionpint, which I want to discuss.

Getting this information from Director is doable, but we have to decide, if we want to limit the API of our module to getting single objects or if we want to query a list of objects from Director. Both implementations have good arguments standing for them, but they are mutually exclusive.

getting single objects

Pro

  • we either return the object or an error

Con

  • user has to know the name of the object to get it
  • multiple obejcts need to be traversed with Ansible code

getting a list of objects

Pro

  • user can discover objects

Con

  • we always return a list consisting of zero, one or multiple elements
  • errors ened to be handled by the user
  • hard to tell, if we have found one specific object

Example

Here are some examples on how this would behave with hosts.

Example Playbook:

- hosts: localhost
  gather_facts: False
  tasks:
  - name: Find a host in icinga
    t_systems_mms.icinga_director.icinga_host_info_list:
      url: "<url>"
      url_username: "<user>"
      url_password: "<pass>"
      object_name: "srv-qa1-web"
    register: result

  - name: print result
    debug:
      msg: "{{ result.data }}"

Getting one specific host "srv-qa1-web01"

PLAY [localhost] ***************************************
TASK [Find a host in icinga - list query] ***************************************
ok: [localhost]
TASK [print result] ***************************************
ok: [localhost] => {
    "msg": {
        "objects": [
             {
                "address": "192.168.0.199",
                "display_name": "srv-qa1-web01",
                "imports": [
                    "Standardserver"
                ],
                "object_name": "srv-qa1-web01",
                "object_type": "object",
                "vars": {
                    "httpd_processes": [
                        "httpd"
                    ],
                    "openfiles_user": "apache",
                    "processes_rb_unrelevant": [
                        "atop",
                        "filebeat"
                    ]
                },
                "zone": "master"
            }
        ]
    }
}
TASK [Find a host in icinga - single query] ***************************************
ok: [localhost]
TASK [print result] ***************************************
ok: [localhost] => {
    "msg": {
        "address": "192.168.0.199",
        "display_name": "srv-qa1-web01",
        "imports": [
            "Standardserver"
        ],
        "object_name": "srv-qa1-web01",
        "object_type": "object",
        "vars": {
            "httpd_processes": [
                "httpd"
            ],
            "openfiles_user": "apache",
            "processes_rb_unrelevant": [
                "atop",
                "filebeat"
            ]
        },
        "zone": "master"
    }
}

Getting multiple hosts "qa1-web011"

PLAY [localhost] ***************************************
TASK [Find a host in icinga - list query] ***************************************
ok: [localhost]
TASK [print result] ***************************************
ok: [localhost] => {
    "msg": {
        "objects": [
             {
                "address": "192.168.0.199",
                "display_name": "srv-qa1-web01",
                "imports": [
                    "Standardserver"
                ],
                "object_name": "srv-qa1-web01",
                "object_type": "object",
                "vars": {
                    "httpd_processes": [
                        "httpd"
                    ],
                    "openfiles_user": "apache",
                    "processes_rb_unrelevant": [
                        "atop",
                        "filebeat"
                    ]
                },
                "zone": "master"
            },
            {
                "address": "192.168.0.200",
                "display_name": "srv-qa1-web02",
                "imports": [
                    "Standardserver"
                ],
                "object_name": "srv-qa1-web02",
                "object_type": "object",
                "vars": {
                    "httpd_processes": [
                        "httpd"
                    ],
                    "openfiles_user": "apache",
                    "processes_rb_unrelevant": [
                        "atop",
                        "filebeat"
                    ]
                },
                "zone": "master"
            }
        ]
    }
}
TASK [Find a host in icinga - single query] ***************************************
ok: [localhost]
TASK [print result] ***************************************
ok: [localhost] => {
    "msg": {
        "error": "Failed to load icinga_host \"qa1-web\""
    }
}

Getting a nonexistant host "srv-qa1-web011"

PLAY [localhost] ***************************************
TASK [Find a host in icinga - list query] ***************************************
ok: [localhost]
TASK [print result] ***************************************
ok: [localhost] => {
    "msg": {
        "objects": []
    }
}
TASK [Find a host in icinga - single query] ***************************************
ok: [localhost]
TASK [print result] ***************************************
ok: [localhost] => {
    "msg": {
        "error": "Failed to load icinga_host \"srv-qa1-web011\""
    }
}

cc @mmslkr @rndmh3ro @neubi4 for discussion

I would prefer to get the list and let the user decide if an result langth of zero or one is an error to handle or not. Getting a list also makes the Ansible code simpler in my oppinion.

Additionally, there shoud be a parameter to get the fully resolved object or not. https://github.com/Icinga/icingaweb2-module-director/blob/master/doc/70-REST-API.md#resolve-object-properties

I want to use the same module to gather all hosts or single hosts if I provide the name:

Optional: use regex-searching for the objects.

get all hosts:

- hosts: localhost
  gather_facts: False
  tasks:
  - name: Get all Hosts
    t_systems_mms.icinga_director.icinga_host_info_list:
      url: "<url>"
      url_username: "<user>"
      url_password: "<pass>"
    register: result

get one specific host:

- hosts: localhost
  gather_facts: False
  tasks:
  - name: Get Host
    t_systems_mms.icinga_director.icinga_host_info_list:
      url: "<url>"
      url_username: "<user>"
      url_password: "<pass>"
      object_name: "srv-qa1-web"
    register: result

Additionally, there shoud be a parameter to get the fully resolved object or not. https://github.com/Icinga/icingaweb2-module-director/blob/master/doc/70-REST-API.md#resolve-object-properties

Yes!

I want to use the same module to gather all hosts or single hosts if I provide the name:

Optional: use regex-searching for the objects.

get all hosts:

- hosts: localhost
  gather_facts: False
  tasks:
  - name: Get all Hosts
    t_systems_mms.icinga_director.icinga_host_info_list:
      url: "<url>"
      url_username: "<user>"
      url_password: "<pass>"
    register: result

get one specific host:

- hosts: localhost
  gather_facts: False
  tasks:
  - name: Get Host
    t_systems_mms.icinga_director.icinga_host_info_list:
      url: "<url>"
      url_username: "<user>"
      url_password: "<pass>"
      object_name: "srv-qa1-web"
    register: result

With this I see the issue, that we would return an array when we use list context and we would return an object when wie use the specific context. I really want to avoid having two different return formats.

we would return an object when wie use the specific context. I really want to avoid having two different return formats.

Why? We can return a list with one item.

Why? We can return a list with one item.

sure, I take this as a vote for general list returns.

so I did an example implementation in #98 what do you guys think?

Implemented by @schurzi!