1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

removing zabbix modules and their references due to migration to a dedicated collection (#11)

This commit is contained in:
Dusan Matejka 2020-03-16 11:55:34 +01:00 committed by GitHub
parent 2728cfe59d
commit 24405289fe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
51 changed files with 2 additions and 12729 deletions

66
.github/BOTMETA.yml vendored
View file

@ -160,7 +160,6 @@ files:
$doc_fragments/xenserver.py: $doc_fragments/xenserver.py:
maintainers: bvitnik maintainers: bvitnik
labels: xenserver labels: xenserver
$doc_fragments/zabbix.py:
$filters/gcp_kms_filters.py: $filters/gcp_kms_filters.py:
$filters/json_query.py: $filters/json_query.py:
$filters/random_mac.py: $filters/random_mac.py:
@ -1181,70 +1180,6 @@ files:
authors: bhcopeland authors: bhcopeland
$modules/monitoring/uptimerobot.py: $modules/monitoring/uptimerobot.py:
authors: nate-kingsley authors: nate-kingsley
$modules/monitoring/zabbix/:
authors: sky-joker
maintainers: D3DeFi rubentsirunyan
ignore: ryansb
$modules/monitoring/zabbix/zabbix_action.py:
authors: K-DOT rubentsirunyan
maintainers: D3DeFi sky-joker
ignore: ryansb
$modules/monitoring/zabbix/zabbix_group.py:
authors: cove harrisongu
maintainers: $team_zabbix
ignore: cove
$modules/monitoring/zabbix/zabbix_group_info.py:
authors: RedWhiteMiko
maintainers: $team_zabbix
ignore: ryansb
$modules/monitoring/zabbix/zabbix_host.py:
authors: cove dj-wasabi eikef harrisongu
maintainers: $team_zabbix
ignore: cove
$modules/monitoring/zabbix/zabbix_host_events_info.py:
authors: stravassac
maintainers: $team_zabbix
ignore: ryansb
$modules/monitoring/zabbix/zabbix_host_info.py:
authors: RedWhiteMiko
maintainers: $team_zabbix
ignore: ryansb
$modules/monitoring/zabbix/zabbix_hostmacro.py:
authors: cove
maintainers: $team_zabbix
ignore: cove
$modules/monitoring/zabbix/zabbix_maintenance.py:
authors: abulimov
maintainers: $team_zabbix
ignore: ryansb
$modules/monitoring/zabbix/zabbix_map.py:
authors: Akint
maintainers: $team_zabbix
ignore: ryansb
$modules/monitoring/zabbix/zabbix_mediatype.py:
authors: rubentsirunyan
maintainers: D3DeFi sky-joker
ignore: ryansb
$modules/monitoring/zabbix/zabbix_proxy.py:
authors: akomic
maintainers: $team_zabbix
ignore: ryansb
$modules/monitoring/zabbix/zabbix_screen.py:
authors: cove harrisongu
maintainers: $team_zabbix
ignore: cove
$modules/monitoring/zabbix/zabbix_service.py:
authors: emriver
maintainers: $team_zabbix
ignore: ryansb
$modules/monitoring/zabbix/zabbix_template.py:
authors: D3DeFi logan2211 sookido
maintainers: rubentsirunyan sky-joker
ignore: ryansb
$modules/monitoring/zabbix/zabbix_valuemap.py:
authors: rubentsirunyan
maintainers: D3DeFi sky-joker
ignore: ryansb
$modules/net_tools/cloudflare_dns.py: $modules/net_tools/cloudflare_dns.py:
authors: mgruener authors: mgruener
maintainers: andreaso maintainers: andreaso
@ -2302,4 +2237,3 @@ macros:
team_suse: commel dcermak evrardjp lrupp toabctl team_suse: commel dcermak evrardjp lrupp toabctl
team_virt: joshainglis karmab team_virt: joshainglis karmab
team_vultr: Spredzy resmo team_vultr: Spredzy resmo
team_zabbix: D3DeFi rubentsirunyan sky-joker

View file

@ -608,14 +608,6 @@ plugin_routing:
deprecation: deprecation:
removal_date: TBD removal_date: TBD
warning_text: see plugin documentation for details warning_text: see plugin documentation for details
zabbix_group_facts:
deprecation:
removal_date: TBD
warning_text: see plugin documentation for details
zabbix_host_facts:
deprecation:
removal_date: TBD
warning_text: see plugin documentation for details
ldap_attr: ldap_attr:
deprecation: deprecation:
removal_date: TBD removal_date: TBD

View file

@ -1,50 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2017, Ansible, Inc
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
class ModuleDocFragment(object):
# Standard documentation fragment
DOCUMENTATION = r'''
options:
server_url:
description:
- URL of Zabbix server, with protocol (http or https).
C(url) is an alias for C(server_url).
required: true
type: str
aliases: [ url ]
login_user:
description:
- Zabbix user name.
type: str
required: true
login_password:
description:
- Zabbix user password.
type: str
required: true
http_login_user:
description:
- Basic Auth login
type: str
http_login_password:
description:
- Basic Auth password
type: str
timeout:
description:
- The timeout of API request (seconds).
type: int
default: 10
validate_certs:
description:
- If set to False, SSL certificates will not be validated. This should only be used on personally controlled sites using self-signed certificates.
type: bool
default: yes
notes:
- If you use I(login_password=zabbix), the word "zabbix" is replaced by "********" in all module output, because I(login_password) uses C(no_log).
See L(this FAQ,https://docs.ansible.com/ansible/latest/network/user_guide/faq.html#why-is-my-output-sometimes-replaced-with) for more information.
'''

File diff suppressed because it is too large Load diff

View file

@ -1,208 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# (c) 2013-2014, Epic Games, Inc.
# 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
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = r'''
---
module: zabbix_group
short_description: Create/delete Zabbix host groups
description:
- Create host groups if they do not exist.
- Delete existing host groups if they exist.
author:
- "Cove (@cove)"
- "Tony Minfei Ding (!UNKNOWN)"
- "Harrison Gu (@harrisongu)"
requirements:
- "python >= 2.6"
- "zabbix-api >= 0.5.4"
options:
state:
description:
- Create or delete host group.
required: false
type: str
default: "present"
choices: [ "present", "absent" ]
host_groups:
description:
- List of host groups to create or delete.
required: true
type: list
elements: str
aliases: [ "host_group" ]
extends_documentation_fragment:
- community.general.zabbix
notes:
- Too many concurrent updates to the same group may cause Zabbix to return errors, see examples for a workaround if needed.
'''
EXAMPLES = r'''
# Base create host groups example
- name: Create host groups
local_action:
module: zabbix_group
server_url: http://monitor.example.com
login_user: username
login_password: password
state: present
host_groups:
- Example group1
- Example group2
# Limit the Zabbix group creations to one host since Zabbix can return an error when doing concurrent updates
- name: Create host groups
local_action:
module: zabbix_group
server_url: http://monitor.example.com
login_user: username
login_password: password
state: present
host_groups:
- Example group1
- Example group2
when: inventory_hostname==groups['group_name'][0]
'''
import atexit
import traceback
try:
from zabbix_api import ZabbixAPI
from zabbix_api import Already_Exists
HAS_ZABBIX_API = True
except ImportError:
ZBX_IMP_ERR = traceback.format_exc()
HAS_ZABBIX_API = False
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
class HostGroup(object):
def __init__(self, module, zbx):
self._module = module
self._zapi = zbx
# create host group(s) if not exists
def create_host_group(self, group_names):
try:
group_add_list = []
for group_name in group_names:
result = self._zapi.hostgroup.get({'filter': {'name': group_name}})
if not result:
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
self._zapi.hostgroup.create({'name': group_name})
group_add_list.append(group_name)
except Already_Exists:
return group_add_list
return group_add_list
except Exception as e:
self._module.fail_json(msg="Failed to create host group(s): %s" % e)
# delete host group(s)
def delete_host_group(self, group_ids):
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
self._zapi.hostgroup.delete(group_ids)
except Exception as e:
self._module.fail_json(msg="Failed to delete host group(s), Exception: %s" % e)
# get group ids by name
def get_group_ids(self, host_groups):
group_ids = []
group_list = self._zapi.hostgroup.get({'output': 'extend', 'filter': {'name': host_groups}})
for group in group_list:
group_id = group['groupid']
group_ids.append(group_id)
return group_ids, group_list
def main():
module = AnsibleModule(
argument_spec=dict(
server_url=dict(type='str', required=True, aliases=['url']),
login_user=dict(type='str', required=True),
login_password=dict(type='str', required=True, no_log=True),
http_login_user=dict(type='str', required=False, default=None),
http_login_password=dict(type='str', required=False, default=None, no_log=True),
validate_certs=dict(type='bool', required=False, default=True),
host_groups=dict(type='list', required=True, aliases=['host_group']),
state=dict(type='str', default="present", choices=['present', 'absent']),
timeout=dict(type='int', default=10)
),
supports_check_mode=True
)
if not HAS_ZABBIX_API:
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
server_url = module.params['server_url']
login_user = module.params['login_user']
login_password = module.params['login_password']
http_login_user = module.params['http_login_user']
http_login_password = module.params['http_login_password']
validate_certs = module.params['validate_certs']
host_groups = module.params['host_groups']
state = module.params['state']
timeout = module.params['timeout']
zbx = None
# login to zabbix
try:
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
validate_certs=validate_certs)
zbx.login(login_user, login_password)
atexit.register(zbx.logout)
except Exception as e:
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
hostGroup = HostGroup(module, zbx)
group_ids = []
group_list = []
if host_groups:
group_ids, group_list = hostGroup.get_group_ids(host_groups)
if state == "absent":
# delete host groups
if group_ids:
delete_group_names = []
hostGroup.delete_host_group(group_ids)
for group in group_list:
delete_group_names.append(group['name'])
module.exit_json(changed=True,
result="Successfully deleted host group(s): %s." % ",".join(delete_group_names))
else:
module.exit_json(changed=False, result="No host group(s) to delete.")
else:
# create host groups
group_add_list = hostGroup.create_host_group(host_groups)
if len(group_add_list) > 0:
module.exit_json(changed=True, result="Successfully created host group(s): %s" % group_add_list)
else:
module.exit_json(changed=False)
if __name__ == '__main__':
main()

View file

@ -1 +0,0 @@
zabbix_group_info.py

View file

@ -1,132 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) me@mimiko.me
# 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
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
RETURN = r'''
---
host_groups:
description: List of Zabbix groups.
returned: success
type: dict
sample: [ { "flags": "0", "groupid": "33", "internal": "0", "name": "Hostgruup A" } ]
'''
DOCUMENTATION = r'''
---
module: zabbix_group_info
short_description: Gather information about Zabbix hostgroup
description:
- This module allows you to search for Zabbix hostgroup entries.
- This module was called C(zabbix_group_facts) before Ansible 2.9. The usage did not change.
author:
- "Michael Miko (@RedWhiteMiko)"
requirements:
- "python >= 2.6"
- "zabbix-api >= 0.5.4"
options:
hostgroup_name:
description:
- Name of the hostgroup in Zabbix.
- hostgroup is the unique identifier used and cannot be updated using this module.
required: true
type: list
elements: str
extends_documentation_fragment:
- community.general.zabbix
'''
EXAMPLES = r'''
- name: Get hostgroup info
local_action:
module: zabbix_group_info
server_url: http://monitor.example.com
login_user: username
login_password: password
hostgroup_name:
- ExampleHostgroup
timeout: 10
'''
import atexit
import traceback
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
try:
from zabbix_api import ZabbixAPI
HAS_ZABBIX_API = True
except ImportError:
ZBX_IMP_ERR = traceback.format_exc()
HAS_ZABBIX_API = False
class Host(object):
def __init__(self, module, zbx):
self._module = module
self._zapi = zbx
def get_group_ids_by_group_names(self, group_names):
group_list = self._zapi.hostgroup.get({'output': 'extend', 'filter': {'name': group_names}})
if len(group_list) < 1:
self._module.fail_json(msg="Hostgroup not found: %s" % group_names)
return group_list
def main():
module = AnsibleModule(
argument_spec=dict(
server_url=dict(type='str', required=True, aliases=['url']),
login_user=dict(type='str', required=True),
login_password=dict(type='str', required=True, no_log=True),
hostgroup_name=dict(type='list', required=True),
http_login_user=dict(type='str', required=False, default=None),
http_login_password=dict(type='str', required=False, default=None, no_log=True),
validate_certs=dict(type='bool', required=False, default=True),
timeout=dict(type='int', default=10)
),
supports_check_mode=True
)
if module._name == 'zabbix_group_facts':
module.deprecate("The 'zabbix_group_facts' module has been renamed to 'zabbix_group_info'", version='2.13')
if not HAS_ZABBIX_API:
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
server_url = module.params['server_url']
login_user = module.params['login_user']
login_password = module.params['login_password']
http_login_user = module.params['http_login_user']
http_login_password = module.params['http_login_password']
validate_certs = module.params['validate_certs']
hostgroup_name = module.params['hostgroup_name']
timeout = module.params['timeout']
zbx = None
# login to zabbix
try:
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
validate_certs=validate_certs)
zbx.login(login_user, login_password)
atexit.register(zbx.logout)
except Exception as e:
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
host = Host(module, zbx)
host_groups = host.get_group_ids_by_group_names(hostgroup_name)
module.exit_json(host_groups=host_groups)
if __name__ == '__main__':
main()

File diff suppressed because it is too large Load diff

View file

@ -1,336 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) stephane.travassac@fr.clara.net
# 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
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
RETURN = '''
---
triggers_ok:
description: Host Zabbix Triggers in OK state
returned: On success
type: complex
contains:
comments:
description: Additional description of the trigger
type: str
description:
description: Name of the trigger
type: str
error:
description: Error text if there have been any problems when updating the state of the trigger
type: str
expression:
description: Reduced trigger expression
type: str
flags:
description: Origin of the trigger
type: int
lastchange:
description: Time when the trigger last changed its state (timestamp)
type: int
priority:
description: Severity of the trigger
type: int
state:
description: State of the trigger
type: int
status:
description: Whether the trigger is enabled or disabled
type: int
templateid:
description: ID of the parent template trigger
type: int
triggerid:
description: ID of the trigger
type: int
type:
description: Whether the trigger can generate multiple problem events
type: int
url:
description: URL associated with the trigger
type: str
value:
description: Whether the trigger is in OK or problem state
type: int
triggers_problem:
description: Host Zabbix Triggers in problem state. See trigger and event objects in API documentation of your zabbix version for more
returned: On success
type: complex
contains:
comments:
description: Additional description of the trigger
type: str
description:
description: Name of the trigger
type: str
error:
description: Error text if there have been any problems when updating the state of the trigger
type: str
expression:
description: Reduced trigger expression
type: str
flags:
description: Origin of the trigger
type: int
last_event:
description: last event informations
type: complex
contains:
acknowledged:
description: If set to true return only acknowledged events
type: int
acknowledges:
description: acknowledges informations
type: complex
contains:
alias:
description: Account who acknowledge
type: str
clock:
description: Time when the event was created (timestamp)
type: int
message:
description: Text of the acknowledgement message
type: str
clock:
description: Time when the event was created (timestamp)
type: int
eventid:
description: ID of the event
type: int
value:
description: State of the related object
type: int
lastchange:
description: Time when the trigger last changed its state (timestamp)
type: int
priority:
description: Severity of the trigger
type: int
state:
description: State of the trigger
type: int
status:
description: Whether the trigger is enabled or disabled
type: int
templateid:
description: ID of the parent template trigger
type: int
triggerid:
description: ID of the trigger
type: int
type:
description: Whether the trigger can generate multiple problem events
type: int
url:
description: URL associated with the trigger
type: str
value:
description: Whether the trigger is in OK or problem state
type: int
'''
DOCUMENTATION = '''
---
module: zabbix_host_events_info
short_description: Get all triggers about a Zabbix host
description:
- This module allows you to see if a Zabbix host have no active alert to make actions on it.
For this case use module Ansible 'fail' to exclude host in trouble.
- Length of "triggers_ok" allow if template's triggers exist for Zabbix Host
author:
- "Stéphane Travassac (@stravassac)"
requirements:
- "python >= 2.7"
- "zabbix-api >= 0.5.3"
options:
host_identifier:
description:
- Identifier of Zabbix Host
required: true
type: str
host_id_type:
description:
- Type of host_identifier
choices:
- hostname
- visible_name
- hostid
required: false
default: hostname
type: str
trigger_severity:
description:
- Zabbix severity for search filter
default: average
required: false
choices:
- not_classified
- information
- warning
- average
- high
- disaster
type: str
extends_documentation_fragment:
- community.general.zabbix
'''
EXAMPLES = '''
- name: exclude machine if alert active on it
zabbix_host_events_info:
server_url: "{{ zabbix_url }}"
login_user: "{{ lookup('env','ZABBIX_USER') }}"
login_password: "{{ lookup('env','ZABBIX_PASSWORD') }}"
host_identifier: "{{inventory_hostname}}"
host_id_type: "hostname"
timeout: 120
register: zbx_host
delegate_to: localhost
- fail:
msg: "machine alert in zabbix"
when: zbx_host['triggers_problem']|length > 0
'''
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
import atexit
import traceback
try:
from zabbix_api import ZabbixAPI
HAS_ZABBIX_API = True
except ImportError:
ZBX_IMP_ERR = traceback.format_exc()
HAS_ZABBIX_API = False
class Host(object):
def __init__(self, module, zbx):
self._module = module
self._zapi = zbx
def get_host(self, host_identifier, host_inventory, search_key):
""" Get host by hostname|visible_name|hostid """
host = self._zapi.host.get(
{'output': 'extend', 'selectParentTemplates': ['name'], 'filter': {search_key: host_identifier},
'selectInventory': host_inventory})
if len(host) < 1:
self._module.fail_json(msg="Host not found: %s" % host_identifier)
else:
return host[0]
def get_triggers_by_host_id_in_problem_state(self, host_id, trigger_severity):
""" Get triggers in problem state from a hostid"""
# https://www.zabbix.com/documentation/3.4/manual/api/reference/trigger/get
output = 'extend'
triggers_list = self._zapi.trigger.get({'output': output, 'hostids': host_id,
'min_severity': trigger_severity})
return triggers_list
def get_last_event_by_trigger_id(self, triggers_id):
""" Get the last event from triggerid"""
output = ['eventid', 'clock', 'acknowledged', 'value']
select_acknowledges = ['clock', 'alias', 'message']
event = self._zapi.event.get({'output': output, 'objectids': triggers_id,
'select_acknowledges': select_acknowledges, "limit": 1, "sortfield": "clock",
"sortorder": "DESC"})
return event[0]
def main():
module = AnsibleModule(
argument_spec=dict(
server_url=dict(type='str', required=True, aliases=['url']),
login_user=dict(type='str', required=True),
login_password=dict(type='str', required=True, no_log=True),
http_login_user=dict(type='str', required=False, default=None),
http_login_password=dict(type='str', required=False, default=None, no_log=True),
host_identifier=dict(type='str', required=True),
host_id_type=dict(
default='hostname',
type='str',
choices=['hostname', 'visible_name', 'hostid']),
trigger_severity=dict(
type='str',
required=False,
default='average',
choices=['not_classified', 'information', 'warning', 'average', 'high', 'disaster']),
validate_certs=dict(type='bool', required=False, default=True),
timeout=dict(type='int', default=10),
),
supports_check_mode=True
)
if not HAS_ZABBIX_API:
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'),
exception=ZBX_IMP_ERR)
trigger_severity_map = {'not_classified': 0, 'information': 1, 'warning': 2, 'average': 3, 'high': 4, 'disaster': 5}
server_url = module.params['server_url']
login_user = module.params['login_user']
login_password = module.params['login_password']
http_login_user = module.params['http_login_user']
http_login_password = module.params['http_login_password']
validate_certs = module.params['validate_certs']
host_id = module.params['host_identifier']
host_id_type = module.params['host_id_type']
trigger_severity = trigger_severity_map[module.params['trigger_severity']]
timeout = module.params['timeout']
host_inventory = 'hostid'
zbx = None
# login to zabbix
try:
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
validate_certs=validate_certs)
zbx.login(login_user, login_password)
atexit.register(zbx.logout)
except Exception as e:
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
host = Host(module, zbx)
if host_id_type == 'hostname':
zabbix_host = host.get_host(host_id, host_inventory, 'host')
host_id = zabbix_host['hostid']
elif host_id_type == 'visible_name':
zabbix_host = host.get_host(host_id, host_inventory, 'name')
host_id = zabbix_host['hostid']
elif host_id_type == 'hostid':
''' check hostid exist'''
zabbix_host = host.get_host(host_id, host_inventory, 'hostid')
triggers = host.get_triggers_by_host_id_in_problem_state(host_id, trigger_severity)
triggers_ok = []
triggers_problem = []
for trigger in triggers:
# tGet last event for trigger with problem value = 1
# https://www.zabbix.com/documentation/3.4/manual/api/reference/trigger/object
if int(trigger['value']) == 1:
event = host.get_last_event_by_trigger_id(trigger['triggerid'])
trigger['last_event'] = event
triggers_problem.append(trigger)
else:
triggers_ok.append(trigger)
module.exit_json(ok=True, triggers_ok=triggers_ok, triggers_problem=triggers_problem)
if __name__ == '__main__':
main()

View file

@ -1 +0,0 @@
zabbix_host_info.py

View file

@ -1,252 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) me@mimiko.me
# 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
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
RETURN = r'''
---
hosts:
description: List of Zabbix hosts. See https://www.zabbix.com/documentation/4.0/manual/api/reference/host/get for list of host values.
returned: success
type: dict
sample: [ { "available": "1", "description": "", "disable_until": "0", "error": "", "flags": "0", "groups": ["1"], "host": "Host A", ... } ]
'''
DOCUMENTATION = r'''
---
module: zabbix_host_info
short_description: Gather information about Zabbix host
description:
- This module allows you to search for Zabbix host entries.
- This module was called C(zabbix_host_facts) before Ansible 2.9. The usage did not change.
author:
- "Michael Miko (@RedWhiteMiko)"
requirements:
- "python >= 2.6"
- "zabbix-api >= 0.5.4"
options:
host_name:
description:
- Name of the host in Zabbix.
- host_name is the unique identifier used and cannot be updated using this module.
- Required when I(host_ip) is not used.
required: false
type: str
host_ip:
description:
- Host interface IP of the host in Zabbix.
- Required when I(host_name) is not used.
required: false
type: list
elements: str
exact_match:
description:
- Find the exact match
type: bool
default: no
remove_duplicate:
description:
- Remove duplicate host from host result
type: bool
default: yes
host_inventory:
description:
- List of host inventory keys to display in result.
- Whole host inventory is retrieved if keys are not specified.
type: list
elements: str
required: false
extends_documentation_fragment:
- community.general.zabbix
'''
EXAMPLES = r'''
- name: Get host info
local_action:
module: zabbix_host_info
server_url: http://monitor.example.com
login_user: username
login_password: password
host_name: ExampleHost
host_ip: 127.0.0.1
timeout: 10
exact_match: no
remove_duplicate: yes
- name: Reduce host inventory information to provided keys
local_action:
module: zabbix_host_info
server_url: http://monitor.example.com
login_user: username
login_password: password
host_name: ExampleHost
host_inventory:
- os
- tag
host_ip: 127.0.0.1
timeout: 10
exact_match: no
remove_duplicate: yes
'''
import atexit
import traceback
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
try:
from zabbix_api import ZabbixAPI
HAS_ZABBIX_API = True
except ImportError:
ZBX_IMP_ERR = traceback.format_exc()
HAS_ZABBIX_API = False
class Host(object):
def __init__(self, module, zbx):
self._module = module
self._zapi = zbx
def get_hosts_by_host_name(self, host_name, exact_match, host_inventory):
""" Get host by host name """
search_key = 'search'
if exact_match:
search_key = 'filter'
host_list = self._zapi.host.get({
'output': 'extend',
'selectParentTemplates': ['name'],
search_key: {'host': [host_name]},
'selectInventory': host_inventory,
'selectGroups': 'extend',
'selectTags': 'extend',
'selectMacros': 'extend'
})
if len(host_list) < 1:
self._module.fail_json(msg="Host not found: %s" % host_name)
else:
return host_list
def get_hosts_by_ip(self, host_ips, host_inventory):
""" Get host by host ip(s) """
hostinterfaces = self._zapi.hostinterface.get({
'output': 'extend',
'filter': {
'ip': host_ips
}
})
if len(hostinterfaces) < 1:
self._module.fail_json(msg="Host not found: %s" % host_ips)
host_list = []
for hostinterface in hostinterfaces:
host = self._zapi.host.get({
'output': 'extend',
'selectGroups': 'extend',
'selectParentTemplates': ['name'],
'hostids': hostinterface['hostid'],
'selectInventory': host_inventory,
'selectTags': 'extend',
'selectMacros': 'extend'
})
host[0]['hostinterfaces'] = hostinterface
host_list.append(host[0])
return host_list
def delete_duplicate_hosts(self, hosts):
""" Delete duplicated hosts """
unique_hosts = []
listed_hostnames = []
for zabbix_host in hosts:
if zabbix_host['name'] in listed_hostnames:
continue
unique_hosts.append(zabbix_host)
listed_hostnames.append(zabbix_host['name'])
return unique_hosts
def main():
module = AnsibleModule(
argument_spec=dict(
server_url=dict(type='str', required=True, aliases=['url']),
login_user=dict(type='str', required=True),
login_password=dict(type='str', required=True, no_log=True),
host_name=dict(type='str', default='', required=False),
host_ip=dict(type='list', default=[], required=False),
http_login_user=dict(type='str', required=False, default=None),
http_login_password=dict(type='str', required=False, default=None, no_log=True),
validate_certs=dict(type='bool', required=False, default=True),
timeout=dict(type='int', default=10),
exact_match=dict(type='bool', required=False, default=False),
remove_duplicate=dict(type='bool', required=False, default=True),
host_inventory=dict(type='list', default=[], required=False)
),
supports_check_mode=True
)
if module._name == 'zabbix_host_facts':
module.deprecate("The 'zabbix_host_facts' module has been renamed to 'zabbix_host_info'", version='2.13')
if not HAS_ZABBIX_API:
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
server_url = module.params['server_url']
login_user = module.params['login_user']
login_password = module.params['login_password']
http_login_user = module.params['http_login_user']
http_login_password = module.params['http_login_password']
validate_certs = module.params['validate_certs']
host_name = module.params['host_name']
host_ips = module.params['host_ip']
timeout = module.params['timeout']
exact_match = module.params['exact_match']
is_remove_duplicate = module.params['remove_duplicate']
host_inventory = module.params['host_inventory']
if not host_inventory:
host_inventory = 'extend'
zbx = None
# login to zabbix
try:
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
validate_certs=validate_certs)
zbx.login(login_user, login_password)
atexit.register(zbx.logout)
except Exception as e:
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
host = Host(module, zbx)
if host_name:
hosts = host.get_hosts_by_host_name(host_name, exact_match, host_inventory)
if is_remove_duplicate:
hosts = host.delete_duplicate_hosts(hosts)
extended_hosts = []
for zabbix_host in hosts:
zabbix_host['hostinterfaces'] = host._zapi.hostinterface.get({
'output': 'extend', 'hostids': zabbix_host['hostid']
})
extended_hosts.append(zabbix_host)
module.exit_json(ok=True, hosts=extended_hosts)
elif host_ips:
extended_hosts = host.get_hosts_by_ip(host_ips, host_inventory)
if is_remove_duplicate:
hosts = host.delete_duplicate_hosts(extended_hosts)
module.exit_json(ok=True, hosts=extended_hosts)
else:
module.exit_json(ok=False, hosts=[], result="No Host present")
if __name__ == '__main__':
main()

View file

@ -1,264 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2013-2014, Epic Games, Inc.
# 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
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = r'''
---
module: zabbix_hostmacro
short_description: Create/update/delete Zabbix host macros
description:
- manages Zabbix host macros, it can create, update or delete them.
author:
- "Cove (@cove)"
- Dean Hailin Song (!UNKNOWN)
requirements:
- "python >= 2.6"
- "zabbix-api >= 0.5.4"
options:
host_name:
description:
- Name of the host.
required: true
type: str
macro_name:
description:
- Name of the host macro in zabbix native format C({$MACRO}) or simple format C(MACRO).
required: true
type: str
macro_value:
description:
- Value of the host macro.
- Required if I(state=present).
type: str
state:
description:
- State of the macro.
- On C(present), it will create if macro does not exist or update the macro if the associated data is different.
- On C(absent) will remove a macro if it exists.
required: false
choices: ['present', 'absent']
type: str
default: "present"
force:
description:
- Only updates an existing macro if set to C(yes).
default: 'yes'
type: bool
extends_documentation_fragment:
- community.general.zabbix
'''
EXAMPLES = r'''
- name: Create new host macro or update an existing macro's value
local_action:
module: zabbix_hostmacro
server_url: http://monitor.example.com
login_user: username
login_password: password
host_name: ExampleHost
macro_name: EXAMPLE.MACRO
macro_value: Example value
state: present
# Values with curly brackets need to be quoted otherwise they will be interpreted as a dictionary
- name: Create new host macro in Zabbix native format
local_action:
module: zabbix_hostmacro
server_url: http://monitor.example.com
login_user: username
login_password: password
host_name: ExampleHost
macro_name: "{$EXAMPLE.MACRO}"
macro_value: Example value
state: present
- name: Delete existing host macro
local_action:
module: zabbix_hostmacro
server_url: http://monitor.example.com
login_user: username
login_password: password
host_name: ExampleHost
macro_name: "{$EXAMPLE.MACRO}"
state: absent
'''
import atexit
import traceback
try:
from zabbix_api import ZabbixAPI
HAS_ZABBIX_API = True
except ImportError:
ZBX_IMP_ERR = traceback.format_exc()
HAS_ZABBIX_API = False
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
class HostMacro(object):
def __init__(self, module, zbx):
self._module = module
self._zapi = zbx
# get host id by host name
def get_host_id(self, host_name):
try:
host_list = self._zapi.host.get({'output': 'extend', 'filter': {'host': host_name}})
if len(host_list) < 1:
self._module.fail_json(msg="Host not found: %s" % host_name)
else:
host_id = host_list[0]['hostid']
return host_id
except Exception as e:
self._module.fail_json(msg="Failed to get the host %s id: %s." % (host_name, e))
# get host macro
def get_host_macro(self, macro_name, host_id):
try:
host_macro_list = self._zapi.usermacro.get(
{"output": "extend", "selectSteps": "extend", 'hostids': [host_id], 'filter': {'macro': macro_name}})
if len(host_macro_list) > 0:
return host_macro_list[0]
return None
except Exception as e:
self._module.fail_json(msg="Failed to get host macro %s: %s" % (macro_name, e))
# create host macro
def create_host_macro(self, macro_name, macro_value, host_id):
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
self._zapi.usermacro.create({'hostid': host_id, 'macro': macro_name, 'value': macro_value})
self._module.exit_json(changed=True, result="Successfully added host macro %s" % macro_name)
except Exception as e:
self._module.fail_json(msg="Failed to create host macro %s: %s" % (macro_name, e))
# update host macro
def update_host_macro(self, host_macro_obj, macro_name, macro_value):
host_macro_id = host_macro_obj['hostmacroid']
if host_macro_obj['macro'] == macro_name and host_macro_obj['value'] == macro_value:
self._module.exit_json(changed=False, result="Host macro %s already up to date" % macro_name)
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
self._zapi.usermacro.update({'hostmacroid': host_macro_id, 'value': macro_value})
self._module.exit_json(changed=True, result="Successfully updated host macro %s" % macro_name)
except Exception as e:
self._module.fail_json(msg="Failed to update host macro %s: %s" % (macro_name, e))
# delete host macro
def delete_host_macro(self, host_macro_obj, macro_name):
host_macro_id = host_macro_obj['hostmacroid']
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
self._zapi.usermacro.delete([host_macro_id])
self._module.exit_json(changed=True, result="Successfully deleted host macro %s" % macro_name)
except Exception as e:
self._module.fail_json(msg="Failed to delete host macro %s: %s" % (macro_name, e))
def normalize_macro_name(macro_name):
# Zabbix handles macro names in upper case characters
if ':' in macro_name:
macro_name = ':'.join([macro_name.split(':')[0].upper(), ':'.join(macro_name.split(':')[1:])])
else:
macro_name = macro_name.upper()
# Valid format for macro is {$MACRO}
if not macro_name.startswith('{$'):
macro_name = '{$' + macro_name
if not macro_name.endswith('}'):
macro_name = macro_name + '}'
return macro_name
def main():
module = AnsibleModule(
argument_spec=dict(
server_url=dict(type='str', required=True, aliases=['url']),
login_user=dict(type='str', required=True),
login_password=dict(type='str', required=True, no_log=True),
http_login_user=dict(type='str', required=False, default=None),
http_login_password=dict(type='str', required=False, default=None, no_log=True),
validate_certs=dict(type='bool', required=False, default=True),
host_name=dict(type='str', required=True),
macro_name=dict(type='str', required=True),
macro_value=dict(type='str', required=False),
state=dict(type='str', default='present', choices=['present', 'absent']),
timeout=dict(type='int', default=10),
force=dict(type='bool', default=True)
),
required_if=[
['state', 'present', ['macro_value']]
],
supports_check_mode=True
)
if not HAS_ZABBIX_API:
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
server_url = module.params['server_url']
login_user = module.params['login_user']
login_password = module.params['login_password']
http_login_user = module.params['http_login_user']
http_login_password = module.params['http_login_password']
validate_certs = module.params['validate_certs']
host_name = module.params['host_name']
macro_name = normalize_macro_name(module.params['macro_name'])
macro_value = module.params['macro_value']
state = module.params['state']
timeout = module.params['timeout']
force = module.params['force']
zbx = None
# login to zabbix
try:
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
validate_certs=validate_certs)
zbx.login(login_user, login_password)
atexit.register(zbx.logout)
except Exception as e:
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
host_macro_class_obj = HostMacro(module, zbx)
if host_name:
host_id = host_macro_class_obj.get_host_id(host_name)
host_macro_obj = host_macro_class_obj.get_host_macro(macro_name, host_id)
if state == 'absent':
if not host_macro_obj:
module.exit_json(changed=False, msg="Host Macro %s does not exist" % macro_name)
else:
# delete a macro
host_macro_class_obj.delete_host_macro(host_macro_obj, macro_name)
else:
if not host_macro_obj:
# create host macro
host_macro_class_obj.create_host_macro(macro_name, macro_value, host_id)
elif force:
# update host macro
host_macro_class_obj.update_host_macro(host_macro_obj, macro_name, macro_value)
else:
module.exit_json(changed=False, result="Host macro %s already exists and force is set to no" % macro_name)
if __name__ == '__main__':
main()

View file

@ -1,402 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2013, Alexander Bulimov <lazywolf0@gmail.com>
# 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
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = r'''
module: zabbix_maintenance
short_description: Create Zabbix maintenance windows
description:
- This module will let you create Zabbix maintenance windows.
author: "Alexander Bulimov (@abulimov)"
requirements:
- "python >= 2.6"
- "zabbix-api >= 0.5.4"
options:
state:
description:
- Create or remove a maintenance window. Maintenance window to remove is identified by name.
default: present
choices: [ "present", "absent" ]
type: str
host_names:
description:
- Hosts to manage maintenance window for.
- B(Required) option when I(state=present) and I(host_groups) is not used.
aliases: [ "host_name" ]
type: list
elements: str
host_groups:
description:
- Host groups to manage maintenance window for.
- B(Required) option when I(state=present) and I(host_names) is not used.
aliases: [ "host_group" ]
type: list
elements: str
minutes:
description:
- Length of maintenance window in minutes.
default: 10
type: int
name:
description:
- Unique name of maintenance window.
required: true
type: str
desc:
description:
- Short description of maintenance window.
default: Created by Ansible
type: str
collect_data:
description:
- Type of maintenance. With data collection, or without.
type: bool
default: 'yes'
extends_documentation_fragment:
- community.general.zabbix
notes:
- Useful for setting hosts in maintenance mode before big update,
and removing maintenance window after update.
- Module creates maintenance window from now() to now() + minutes,
so if Zabbix server's time and host's time are not synchronized,
you will get strange results.
- Install required module with 'pip install zabbix-api' command.
'''
EXAMPLES = r'''
- name: Create a named maintenance window for host www1 for 90 minutes
zabbix_maintenance:
name: Update of www1
host_name: www1.example.com
state: present
minutes: 90
server_url: https://monitoring.example.com
login_user: ansible
login_password: pAsSwOrD
- name: Create a named maintenance window for host www1 and host groups Office and Dev
zabbix_maintenance:
name: Update of www1
host_name: www1.example.com
host_groups:
- Office
- Dev
state: present
server_url: https://monitoring.example.com
login_user: ansible
login_password: pAsSwOrD
- name: Create a named maintenance window for hosts www1 and db1, without data collection.
zabbix_maintenance:
name: update
host_names:
- www1.example.com
- db1.example.com
state: present
collect_data: False
server_url: https://monitoring.example.com
login_user: ansible
login_password: pAsSwOrD
- name: Remove maintenance window by name
zabbix_maintenance:
name: Test1
state: absent
server_url: https://monitoring.example.com
login_user: ansible
login_password: pAsSwOrD
'''
import atexit
import datetime
import time
import traceback
try:
from zabbix_api import ZabbixAPI
HAS_ZABBIX_API = True
except ImportError:
ZBX_IMP_ERR = traceback.format_exc()
HAS_ZABBIX_API = False
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
def create_maintenance(zbx, group_ids, host_ids, start_time, maintenance_type, period, name, desc):
end_time = start_time + period
try:
zbx.maintenance.create(
{
"groupids": group_ids,
"hostids": host_ids,
"name": name,
"maintenance_type": maintenance_type,
"active_since": str(start_time),
"active_till": str(end_time),
"description": desc,
"timeperiods": [{
"timeperiod_type": "0",
"start_date": str(start_time),
"period": str(period),
}]
}
)
# zabbix_api can call sys.exit() so we need to catch SystemExit here
except (Exception, SystemExit) as e:
return 1, None, str(e)
return 0, None, None
def update_maintenance(zbx, maintenance_id, group_ids, host_ids, start_time, maintenance_type, period, desc):
end_time = start_time + period
try:
zbx.maintenance.update(
{
"maintenanceid": maintenance_id,
"groupids": group_ids,
"hostids": host_ids,
"maintenance_type": maintenance_type,
"active_since": str(start_time),
"active_till": str(end_time),
"description": desc,
"timeperiods": [{
"timeperiod_type": "0",
"start_date": str(start_time),
"period": str(period),
}]
}
)
# zabbix_api can call sys.exit() so we need to catch SystemExit here
except (Exception, SystemExit) as e:
return 1, None, str(e)
return 0, None, None
def get_maintenance(zbx, name):
try:
maintenances = zbx.maintenance.get(
{
"filter":
{
"name": name,
},
"selectGroups": "extend",
"selectHosts": "extend"
}
)
# zabbix_api can call sys.exit() so we need to catch SystemExit here
except (Exception, SystemExit) as e:
return 1, None, str(e)
for maintenance in maintenances:
maintenance["groupids"] = [group["groupid"] for group in maintenance["groups"]] if "groups" in maintenance else []
maintenance["hostids"] = [host["hostid"] for host in maintenance["hosts"]] if "hosts" in maintenance else []
return 0, maintenance, None
return 0, None, None
def delete_maintenance(zbx, maintenance_id):
try:
zbx.maintenance.delete([maintenance_id])
# zabbix_api can call sys.exit() so we need to catch SystemExit here
except (Exception, SystemExit) as e:
return 1, None, str(e)
return 0, None, None
def get_group_ids(zbx, host_groups):
group_ids = []
for group in host_groups:
try:
result = zbx.hostgroup.get(
{
"output": "extend",
"filter":
{
"name": group
}
}
)
# zabbix_api can call sys.exit() so we need to catch SystemExit here
except (Exception, SystemExit) as e:
return 1, None, str(e)
if not result:
return 1, None, "Group id for group %s not found" % group
group_ids.append(result[0]["groupid"])
return 0, group_ids, None
def get_host_ids(zbx, host_names):
host_ids = []
for host in host_names:
try:
result = zbx.host.get(
{
"output": "extend",
"filter":
{
"name": host
}
}
)
# zabbix_api can call sys.exit() so we need to catch SystemExit here
except (Exception, SystemExit) as e:
return 1, None, str(e)
if not result:
return 1, None, "Host id for host %s not found" % host
host_ids.append(result[0]["hostid"])
return 0, host_ids, None
def main():
module = AnsibleModule(
argument_spec=dict(
state=dict(type='str', required=False, default='present', choices=['present', 'absent']),
server_url=dict(type='str', required=True, aliases=['url']),
host_names=dict(type='list', required=False, default=None, aliases=['host_name']),
minutes=dict(type='int', required=False, default=10),
host_groups=dict(type='list', required=False, default=None, aliases=['host_group']),
login_user=dict(type='str', required=True),
login_password=dict(type='str', required=True, no_log=True),
validate_certs=dict(type='bool', required=False, default=True),
http_login_user=dict(type='str', required=False, default=None),
http_login_password=dict(type='str', required=False, default=None, no_log=True),
name=dict(type='str', required=True),
desc=dict(type='str', required=False, default="Created by Ansible"),
collect_data=dict(type='bool', required=False, default=True),
timeout=dict(type='int', default=10),
),
supports_check_mode=True,
)
if not HAS_ZABBIX_API:
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
host_names = module.params['host_names']
host_groups = module.params['host_groups']
state = module.params['state']
login_user = module.params['login_user']
login_password = module.params['login_password']
http_login_user = module.params['http_login_user']
http_login_password = module.params['http_login_password']
validate_certs = module.params['validate_certs']
minutes = module.params['minutes']
name = module.params['name']
desc = module.params['desc']
server_url = module.params['server_url']
collect_data = module.params['collect_data']
timeout = module.params['timeout']
if collect_data:
maintenance_type = 0
else:
maintenance_type = 1
try:
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
validate_certs=validate_certs)
zbx.login(login_user, login_password)
atexit.register(zbx.logout)
# zabbix_api can call sys.exit() so we need to catch SystemExit here
except (Exception, SystemExit) as e:
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
changed = False
if state == "present":
if not host_names and not host_groups:
module.fail_json(msg="At least one host_name or host_group must be defined for each created maintenance.")
now = datetime.datetime.now().replace(second=0)
start_time = time.mktime(now.timetuple())
period = 60 * int(minutes) # N * 60 seconds
if host_groups:
(rc, group_ids, error) = get_group_ids(zbx, host_groups)
if rc != 0:
module.fail_json(msg="Failed to get group_ids: %s" % error)
else:
group_ids = []
if host_names:
(rc, host_ids, error) = get_host_ids(zbx, host_names)
if rc != 0:
module.fail_json(msg="Failed to get host_ids: %s" % error)
else:
host_ids = []
(rc, maintenance, error) = get_maintenance(zbx, name)
if rc != 0:
module.fail_json(msg="Failed to check maintenance %s existence: %s" % (name, error))
if maintenance and (
sorted(group_ids) != sorted(maintenance["groupids"]) or
sorted(host_ids) != sorted(maintenance["hostids"]) or
str(maintenance_type) != maintenance["maintenance_type"] or
str(int(start_time)) != maintenance["active_since"] or
str(int(start_time + period)) != maintenance["active_till"]
):
if module.check_mode:
changed = True
else:
(rc, data, error) = update_maintenance(zbx, maintenance["maintenanceid"], group_ids, host_ids, start_time, maintenance_type, period, desc)
if rc == 0:
changed = True
else:
module.fail_json(msg="Failed to update maintenance: %s" % error)
if not maintenance:
if module.check_mode:
changed = True
else:
(rc, data, error) = create_maintenance(zbx, group_ids, host_ids, start_time, maintenance_type, period, name, desc)
if rc == 0:
changed = True
else:
module.fail_json(msg="Failed to create maintenance: %s" % error)
if state == "absent":
(rc, maintenance, error) = get_maintenance(zbx, name)
if rc != 0:
module.fail_json(msg="Failed to check maintenance %s existence: %s" % (name, error))
if maintenance:
if module.check_mode:
changed = True
else:
(rc, data, error) = delete_maintenance(zbx, maintenance["maintenanceid"])
if rc == 0:
changed = True
else:
module.fail_json(msg="Failed to remove maintenance: %s" % error)
module.exit_json(changed=changed)
if __name__ == '__main__':
main()

View file

@ -1,829 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2017-2018, Antony Alekseyev <antony.alekseyev@gmail.com>
# 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 = r'''
---
module: zabbix_map
author:
- "Antony Alekseyev (@Akint)"
short_description: Create/update/delete Zabbix maps
description:
- "This module allows you to create, modify and delete Zabbix map entries,
using Graphviz binaries and text description written in DOT language.
Nodes of the graph will become map elements and edges will become links between map elements.
See U(https://en.wikipedia.org/wiki/DOT_(graph_description_language)) and U(https://www.graphviz.org/) for details.
Inspired by U(http://blog.zabbix.com/maps-for-the-lazy/)."
- "The following extra node attributes are supported:
C(zbx_host) contains name of the host in Zabbix. Use this if desired type of map element is C(host).
C(zbx_group) contains name of the host group in Zabbix. Use this if desired type of map element is C(host group).
C(zbx_map) contains name of the map in Zabbix. Use this if desired type of map element is C(map).
C(zbx_label) contains label of map element.
C(zbx_image) contains name of the image used to display the element in default state.
C(zbx_image_disabled) contains name of the image used to display disabled map element.
C(zbx_image_maintenance) contains name of the image used to display map element in maintenance.
C(zbx_image_problem) contains name of the image used to display map element with problems.
C(zbx_url) contains map element URL in C(name:url) format.
More than one URL could be specified by adding a postfix (e.g., C(zbx_url1), C(zbx_url2))."
- "The following extra link attributes are supported:
C(zbx_draw_style) contains link line draw style. Possible values: C(line), C(bold), C(dotted), C(dashed).
C(zbx_trigger) contains name of the trigger used as a link indicator in C(host_name:trigger_name) format.
More than one trigger could be specified by adding a postfix (e.g., C(zbx_trigger1), C(zbx_trigger2)).
C(zbx_trigger_color) contains indicator color specified either as CSS3 name or as a hexadecimal code starting with C(#).
C(zbx_trigger_draw_style) contains indicator draw style. Possible values are the same as for C(zbx_draw_style)."
requirements:
- "python >= 2.6"
- "zabbix-api >= 0.5.4"
- pydotplus
- webcolors
- Pillow
- Graphviz
options:
name:
description:
- Name of the map.
required: true
aliases: [ "map_name" ]
type: str
data:
description:
- Graph written in DOT language.
required: false
aliases: [ "dot_data" ]
type: str
state:
description:
- State of the map.
- On C(present), it will create if map does not exist or update the map if the associated data is different.
- On C(absent) will remove the map if it exists.
required: false
choices: ['present', 'absent']
default: "present"
type: str
width:
description:
- Width of the map.
required: false
default: 800
type: int
height:
description:
- Height of the map.
required: false
default: 600
type: int
margin:
description:
- Size of white space between map's borders and its elements.
required: false
default: 40
type: int
expand_problem:
description:
- Whether the problem trigger will be displayed for elements with a single problem.
required: false
type: bool
default: true
highlight:
description:
- Whether icon highlighting is enabled.
required: false
type: bool
default: true
label_type:
description:
- Map element label type.
required: false
choices: ['label', 'ip', 'name', 'status', 'nothing', 'custom']
default: "name"
type: str
default_image:
description:
- Name of the Zabbix image used to display the element if this element doesn't have the C(zbx_image) attribute defined.
required: false
aliases: [ "image" ]
type: str
extends_documentation_fragment:
- community.general.zabbix
'''
RETURN = r''' # '''
EXAMPLES = r'''
###
### Example inventory:
# [web]
# web[01:03].example.com ansible_host=127.0.0.1
# [db]
# db.example.com ansible_host=127.0.0.1
# [backup]
# backup.example.com ansible_host=127.0.0.1
###
### Each inventory host is present in Zabbix with a matching name.
###
### Contents of 'map.j2':
# digraph G {
# graph [layout=dot splines=false overlap=scale]
# INTERNET [zbx_url="Google:https://google.com" zbx_image="Cloud_(96)"]
# {% for web_host in groups.web %}
# {% set web_loop = loop %}
# web{{ '%03d' % web_loop.index }} [zbx_host="{{ web_host }}"]
# INTERNET -> web{{ '%03d' % web_loop.index }} [zbx_trigger="{{ web_host }}:Zabbix agent on {HOST.NAME} is unreachable for 5 minutes"]
# {% for db_host in groups.db %}
# {% set db_loop = loop %}
# web{{ '%03d' % web_loop.index }} -> db{{ '%03d' % db_loop.index }}
# {% endfor %}
# {% endfor %}
# { rank=same
# {% for db_host in groups.db %}
# {% set db_loop = loop %}
# db{{ '%03d' % db_loop.index }} [zbx_host="{{ db_host }}"]
# {% for backup_host in groups.backup %}
# {% set backup_loop = loop %}
# db{{ '%03d' % db_loop.index }} -> backup{{ '%03d' % backup_loop.index }} [color="blue"]
# {% endfor %}
# {% endfor %}
# {% for backup_host in groups.backup %}
# {% set backup_loop = loop %}
# backup{{ '%03d' % backup_loop.index }} [zbx_host="{{ backup_host }}"]
# {% endfor %}
# }
# }
###
### Create Zabbix map "Demo Map" made of template 'map.j2'
- name: Create Zabbix map
zabbix_map:
server_url: http://zabbix.example.com
login_user: username
login_password: password
name: Demo map
state: present
data: "{{ lookup('template', 'map.j2') }}"
default_image: Server_(64)
expand_problem: no
highlight: no
label_type: label
delegate_to: localhost
run_once: yes
'''
ANSIBLE_METADATA = {
'metadata_version': '1.1',
'supported_by': 'community',
'status': ['preview']
}
import atexit
import base64
import traceback
from io import BytesIO
from operator import itemgetter
from distutils.version import StrictVersion
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
try:
import pydotplus
HAS_PYDOTPLUS = True
except ImportError:
PYDOT_IMP_ERR = traceback.format_exc()
HAS_PYDOTPLUS = False
try:
import webcolors
HAS_WEBCOLORS = True
except ImportError:
WEBCOLORS_IMP_ERR = traceback.format_exc()
HAS_WEBCOLORS = False
try:
from zabbix_api import ZabbixAPI
HAS_ZABBIX_API = True
except ImportError:
ZBX_IMP_ERR = traceback.format_exc()
HAS_ZABBIX_API = False
try:
from PIL import Image
HAS_PIL = True
except ImportError:
PIL_IMP_ERR = traceback.format_exc()
HAS_PIL = False
class Map():
def __init__(self, module, zbx):
self._module = module
self._zapi = zbx
self.map_name = module.params['name']
self.dot_data = module.params['data']
self.width = module.params['width']
self.height = module.params['height']
self.state = module.params['state']
self.default_image = module.params['default_image']
self.map_id = self._get_sysmap_id(self.map_name)
self.margin = module.params['margin']
self.expand_problem = module.params['expand_problem']
self.highlight = module.params['highlight']
self.label_type = module.params['label_type']
self.api_version = self._zapi.api_version()
self.selements_sort_keys = self._get_selements_sort_keys()
def _build_graph(self):
try:
graph_without_positions = pydotplus.graph_from_dot_data(self.dot_data)
dot_data_with_positions = graph_without_positions.create_dot()
graph_with_positions = pydotplus.graph_from_dot_data(dot_data_with_positions)
if graph_with_positions:
return graph_with_positions
except Exception as e:
self._module.fail_json(msg="Failed to build graph from DOT data: %s" % e)
def get_map_config(self):
if not self.dot_data:
self._module.fail_json(msg="'data' is mandatory with state 'present'")
graph = self._build_graph()
nodes = self._get_graph_nodes(graph)
edges = self._get_graph_edges(graph)
icon_ids = self._get_icon_ids()
map_config = {
'name': self.map_name,
'label_type': self._get_label_type_id(self.label_type),
'expandproblem': int(self.expand_problem),
'highlight': int(self.highlight),
'width': self.width,
'height': self.height,
'selements': self._get_selements(graph, nodes, icon_ids),
'links': self._get_links(nodes, edges),
}
return map_config
def _get_label_type_id(self, label_type):
label_type_ids = {
'label': 0,
'ip': 1,
'name': 2,
'status': 3,
'nothing': 4,
'custom': 5,
}
try:
label_type_id = label_type_ids[label_type]
except Exception as e:
self._module.fail_json(msg="Failed to find id for label type '%s': %s" % (label_type, e))
return label_type_id
def _get_images_info(self, data, icon_ids):
images = [
{
'dot_tag': 'zbx_image',
'zbx_property': 'iconid_off',
'mandatory': True
},
{
'dot_tag': 'zbx_image_disabled',
'zbx_property': 'iconid_disabled',
'mandatory': False
},
{
'dot_tag': 'zbx_image_maintenance',
'zbx_property': 'iconid_maintenance',
'mandatory': False
},
{
'dot_tag': 'zbx_image_problem',
'zbx_property': 'iconid_on',
'mandatory': False
}
]
images_info = {}
default_image = self.default_image if self.default_image else sorted(icon_ids.items())[0][0]
for image in images:
image_name = data.get(image['dot_tag'], None)
if not image_name:
if image['mandatory']:
image_name = default_image
else:
continue
image_name = remove_quotes(image_name)
if image_name in icon_ids:
images_info[image['zbx_property']] = icon_ids[image_name]
if not image['mandatory']:
images_info['use_iconmap'] = 0
else:
self._module.fail_json(msg="Failed to find id for image '%s'" % image_name)
return images_info
def _get_element_type(self, data):
types = {
'host': 0,
'sysmap': 1,
'trigger': 2,
'group': 3,
'image': 4
}
element_type = {
'elementtype': types['image'],
}
if StrictVersion(self.api_version) < StrictVersion('3.4'):
element_type.update({
'elementid': "0",
})
for type_name, type_id in sorted(types.items()):
field_name = 'zbx_' + type_name
if field_name in data:
method_name = '_get_' + type_name + '_id'
element_name = remove_quotes(data[field_name])
get_element_id = getattr(self, method_name, None)
if get_element_id:
elementid = get_element_id(element_name)
if elementid and int(elementid) > 0:
element_type.update({
'elementtype': type_id,
'label': element_name
})
if StrictVersion(self.api_version) < StrictVersion('3.4'):
element_type.update({
'elementid': elementid,
})
else:
element_type.update({
'elements': [{
type_name + 'id': elementid,
}],
})
break
else:
self._module.fail_json(msg="Failed to find id for %s '%s'" % (type_name, element_name))
return element_type
# get list of map elements (nodes)
def _get_selements(self, graph, nodes, icon_ids):
selements = []
icon_sizes = {}
scales = self._get_scales(graph)
for selementid, (node, data) in enumerate(nodes.items(), start=1):
selement = {
'selementid': selementid
}
data['selementid'] = selementid
images_info = self._get_images_info(data, icon_ids)
selement.update(images_info)
image_id = images_info['iconid_off']
if image_id not in icon_sizes:
icon_sizes[image_id] = self._get_icon_size(image_id)
pos = self._convert_coordinates(data['pos'], scales, icon_sizes[image_id])
selement.update(pos)
selement['label'] = remove_quotes(node)
element_type = self._get_element_type(data)
selement.update(element_type)
label = self._get_label(data)
if label:
selement['label'] = label
urls = self._get_urls(data)
if urls:
selement['urls'] = urls
selements.append(selement)
return selements
def _get_links(self, nodes, edges):
links = {}
for edge in edges:
link_id = tuple(sorted(edge.obj_dict['points']))
node1, node2 = link_id
data = edge.obj_dict['attributes']
if "style" in data and data['style'] == "invis":
continue
if link_id not in links:
links[link_id] = {
'selementid1': min(nodes[node1]['selementid'], nodes[node2]['selementid']),
'selementid2': max(nodes[node1]['selementid'], nodes[node2]['selementid']),
}
link = links[link_id]
if "color" not in link:
link['color'] = self._get_color_hex(remove_quotes(data.get('color', 'green')))
if "zbx_draw_style" not in link:
link['drawtype'] = self._get_link_draw_style_id(remove_quotes(data.get('zbx_draw_style', 'line')))
label = self._get_label(data)
if label and "label" not in link:
link['label'] = label
triggers = self._get_triggers(data)
if triggers:
if "linktriggers" not in link:
link['linktriggers'] = []
link['linktriggers'] += triggers
return list(links.values())
def _get_urls(self, data):
urls = []
for url_raw in [remove_quotes(value) for key, value in data.items() if key.startswith("zbx_url")]:
try:
name, url = url_raw.split(':', 1)
except Exception as e:
self._module.fail_json(msg="Failed to parse zbx_url='%s': %s" % (url_raw, e))
urls.append({
'name': name,
'url': url,
})
return urls
def _get_triggers(self, data):
triggers = []
for trigger_definition in [remove_quotes(value) for key, value in data.items() if key.startswith("zbx_trigger")]:
triggerid = self._get_trigger_id(trigger_definition)
if triggerid:
triggers.append({
'triggerid': triggerid,
'color': self._get_color_hex(remove_quotes(data.get('zbx_trigger_color', 'red'))),
'drawtype': self._get_link_draw_style_id(remove_quotes(data.get('zbx_trigger_draw_style', 'bold'))),
})
else:
self._module.fail_json(msg="Failed to find trigger '%s'" % (trigger_definition))
return triggers
@staticmethod
def _get_label(data, default=None):
if "zbx_label" in data:
label = remove_quotes(data['zbx_label']).replace('\\n', '\n')
elif "label" in data:
label = remove_quotes(data['label'])
else:
label = default
return label
def _get_sysmap_id(self, map_name):
exist_map = self._zapi.map.get({'filter': {'name': map_name}})
if exist_map:
return exist_map[0]['sysmapid']
return None
def _get_group_id(self, group_name):
exist_group = self._zapi.hostgroup.get({'filter': {'name': group_name}})
if exist_group:
return exist_group[0]['groupid']
return None
def map_exists(self):
return bool(self.map_id)
def create_map(self, map_config):
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
result = self._zapi.map.create(map_config)
if result:
return result
except Exception as e:
self._module.fail_json(msg="Failed to create map: %s" % e)
def update_map(self, map_config):
if not self.map_id:
self._module.fail_json(msg="Failed to update map: map_id is unknown. Try to create_map instead.")
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
map_config['sysmapid'] = self.map_id
result = self._zapi.map.update(map_config)
if result:
return result
except Exception as e:
self._module.fail_json(msg="Failed to update map: %s" % e)
def delete_map(self):
if not self.map_id:
self._module.fail_json(msg="Failed to delete map: map_id is unknown.")
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
self._zapi.map.delete([self.map_id])
except Exception as e:
self._module.fail_json(msg="Failed to delete map, Exception: %s" % e)
def is_exist_map_correct(self, generated_map_config):
exist_map_configs = self._zapi.map.get({
'sysmapids': self.map_id,
'selectLinks': 'extend',
'selectSelements': 'extend'
})
exist_map_config = exist_map_configs[0]
if not self._is_dicts_equal(generated_map_config, exist_map_config):
return False
if not self._is_selements_equal(generated_map_config['selements'], exist_map_config['selements']):
return False
self._update_ids(generated_map_config, exist_map_config)
if not self._is_links_equal(generated_map_config['links'], exist_map_config['links']):
return False
return True
def _get_selements_sort_keys(self):
keys_to_sort = ['label']
if StrictVersion(self.api_version) < StrictVersion('3.4'):
keys_to_sort.insert(0, 'elementid')
return keys_to_sort
def _is_selements_equal(self, generated_selements, exist_selements):
if len(generated_selements) != len(exist_selements):
return False
generated_selements_sorted = sorted(generated_selements, key=itemgetter(*self.selements_sort_keys))
exist_selements_sorted = sorted(exist_selements, key=itemgetter(*self.selements_sort_keys))
for (generated_selement, exist_selement) in zip(generated_selements_sorted, exist_selements_sorted):
if StrictVersion(self.api_version) >= StrictVersion("3.4"):
if not self._is_elements_equal(generated_selement.get('elements', []), exist_selement.get('elements', [])):
return False
if not self._is_dicts_equal(generated_selement, exist_selement, ['selementid']):
return False
if not self._is_urls_equal(generated_selement.get('urls', []), exist_selement.get('urls', [])):
return False
return True
def _is_urls_equal(self, generated_urls, exist_urls):
if len(generated_urls) != len(exist_urls):
return False
generated_urls_sorted = sorted(generated_urls, key=itemgetter('name', 'url'))
exist_urls_sorted = sorted(exist_urls, key=itemgetter('name', 'url'))
for (generated_url, exist_url) in zip(generated_urls_sorted, exist_urls_sorted):
if not self._is_dicts_equal(generated_url, exist_url, ['selementid']):
return False
return True
def _is_elements_equal(self, generated_elements, exist_elements):
if len(generated_elements) != len(exist_elements):
return False
generated_elements_sorted = sorted(generated_elements, key=lambda k: k.values()[0])
exist_elements_sorted = sorted(exist_elements, key=lambda k: k.values()[0])
for (generated_element, exist_element) in zip(generated_elements_sorted, exist_elements_sorted):
if not self._is_dicts_equal(generated_element, exist_element, ['selementid']):
return False
return True
# since generated IDs differ from real Zabbix ones, make real IDs match generated ones
def _update_ids(self, generated_map_config, exist_map_config):
generated_selements_sorted = sorted(generated_map_config['selements'], key=itemgetter(*self.selements_sort_keys))
exist_selements_sorted = sorted(exist_map_config['selements'], key=itemgetter(*self.selements_sort_keys))
id_mapping = {}
for (generated_selement, exist_selement) in zip(generated_selements_sorted, exist_selements_sorted):
id_mapping[exist_selement['selementid']] = generated_selement['selementid']
for link in exist_map_config['links']:
link['selementid1'] = id_mapping[link['selementid1']]
link['selementid2'] = id_mapping[link['selementid2']]
if link['selementid2'] < link['selementid1']:
link['selementid1'], link['selementid2'] = link['selementid2'], link['selementid1']
def _is_links_equal(self, generated_links, exist_links):
if len(generated_links) != len(exist_links):
return False
generated_links_sorted = sorted(generated_links, key=itemgetter('selementid1', 'selementid2', 'color', 'drawtype'))
exist_links_sorted = sorted(exist_links, key=itemgetter('selementid1', 'selementid2', 'color', 'drawtype'))
for (generated_link, exist_link) in zip(generated_links_sorted, exist_links_sorted):
if not self._is_dicts_equal(generated_link, exist_link, ['selementid1', 'selementid2']):
return False
if not self._is_triggers_equal(generated_link.get('linktriggers', []), exist_link.get('linktriggers', [])):
return False
return True
def _is_triggers_equal(self, generated_triggers, exist_triggers):
if len(generated_triggers) != len(exist_triggers):
return False
generated_triggers_sorted = sorted(generated_triggers, key=itemgetter('triggerid'))
exist_triggers_sorted = sorted(exist_triggers, key=itemgetter('triggerid'))
for (generated_trigger, exist_trigger) in zip(generated_triggers_sorted, exist_triggers_sorted):
if not self._is_dicts_equal(generated_trigger, exist_trigger):
return False
return True
@staticmethod
def _is_dicts_equal(d1, d2, exclude_keys=None):
if exclude_keys is None:
exclude_keys = []
for key in d1.keys():
if isinstance(d1[key], dict) or isinstance(d1[key], list):
continue
if key in exclude_keys:
continue
# compare as strings since Zabbix API returns everything as strings
if key not in d2 or str(d2[key]) != str(d1[key]):
return False
return True
def _get_host_id(self, hostname):
hostid = self._zapi.host.get({'filter': {'host': hostname}})
if hostid:
return str(hostid[0]['hostid'])
def _get_trigger_id(self, trigger_definition):
try:
host, trigger = trigger_definition.split(':', 1)
except Exception as e:
self._module.fail_json(msg="Failed to parse zbx_trigger='%s': %s" % (trigger_definition, e))
triggerid = self._zapi.trigger.get({
'host': host,
'filter': {
'description': trigger
}
})
if triggerid:
return str(triggerid[0]['triggerid'])
def _get_icon_ids(self):
icons_list = self._zapi.image.get({})
icon_ids = {}
for icon in icons_list:
icon_ids[icon['name']] = icon['imageid']
return icon_ids
def _get_icon_size(self, icon_id):
icons_list = self._zapi.image.get({
'imageids': [
icon_id
],
'select_image': True
})
if len(icons_list) > 0:
icon_base64 = icons_list[0]['image']
else:
self._module.fail_json(msg="Failed to find image with id %s" % icon_id)
image = Image.open(BytesIO(base64.b64decode(icon_base64)))
icon_width, icon_height = image.size
return icon_width, icon_height
@staticmethod
def _get_node_attributes(node):
attr = {}
if "attributes" in node.obj_dict:
attr.update(node.obj_dict['attributes'])
pos = node.get_pos()
if pos is not None:
pos = remove_quotes(pos)
xx, yy = pos.split(",")
attr['pos'] = (float(xx), float(yy))
return attr
def _get_graph_nodes(self, parent):
nodes = {}
for node in parent.get_nodes():
node_name = node.get_name()
if node_name in ('node', 'graph', 'edge'):
continue
nodes[node_name] = self._get_node_attributes(node)
for subgraph in parent.get_subgraphs():
nodes.update(self._get_graph_nodes(subgraph))
return nodes
def _get_graph_edges(self, parent):
edges = []
for edge in parent.get_edges():
edges.append(edge)
for subgraph in parent.get_subgraphs():
edges += self._get_graph_edges(subgraph)
return edges
def _get_scales(self, graph):
bb = remove_quotes(graph.get_bb())
min_x, min_y, max_x, max_y = bb.split(",")
scale_x = (self.width - self.margin * 2) / (float(max_x) - float(min_x)) if float(max_x) != float(min_x) else 0
scale_y = (self.height - self.margin * 2) / (float(max_y) - float(min_y)) if float(max_y) != float(min_y) else 0
return {
'min_x': float(min_x),
'min_y': float(min_y),
'max_x': float(max_x),
'max_y': float(max_y),
'scale_x': float(scale_x),
'scale_y': float(scale_y),
}
# transform Graphviz coordinates to Zabbix's ones
def _convert_coordinates(self, pos, scales, icon_size):
return {
'x': int((pos[0] - scales['min_x']) * scales['scale_x'] - icon_size[0] / 2 + self.margin),
'y': int((scales['max_y'] - pos[1] + scales['min_y']) * scales['scale_y'] - icon_size[1] / 2 + self.margin),
}
def _get_color_hex(self, color_name):
if color_name.startswith('#'):
color_hex = color_name
else:
try:
color_hex = webcolors.name_to_hex(color_name)
except Exception as e:
self._module.fail_json(msg="Failed to get RGB hex for color '%s': %s" % (color_name, e))
color_hex = color_hex.strip('#').upper()
return color_hex
def _get_link_draw_style_id(self, draw_style):
draw_style_ids = {
'line': 0,
'bold': 2,
'dotted': 3,
'dashed': 4
}
try:
draw_style_id = draw_style_ids[draw_style]
except Exception as e:
self._module.fail_json(msg="Failed to find id for draw type '%s': %s" % (draw_style, e))
return draw_style_id
# If a string has single or double quotes around it, remove them.
def remove_quotes(s):
if (s[0] == s[-1]) and s.startswith(("'", '"')):
s = s[1:-1]
return s
def main():
module = AnsibleModule(
argument_spec=dict(
server_url=dict(type='str', required=True, aliases=['url']),
login_user=dict(type='str', required=True),
login_password=dict(type='str', required=True, no_log=True),
http_login_user=dict(type='str', required=False, default=None),
http_login_password=dict(type='str', required=False, default=None, no_log=True),
timeout=dict(type='int', default=10),
validate_certs=dict(type='bool', required=False, default=True),
name=dict(type='str', required=True, aliases=['map_name']),
data=dict(type='str', required=False, aliases=['dot_data']),
width=dict(type='int', default=800),
height=dict(type='int', default=600),
state=dict(type='str', default="present", choices=['present', 'absent']),
default_image=dict(type='str', required=False, aliases=['image']),
margin=dict(type='int', default=40),
expand_problem=dict(type='bool', default=True),
highlight=dict(type='bool', default=True),
label_type=dict(type='str', default='name', choices=['label', 'ip', 'name', 'status', 'nothing', 'custom']),
),
supports_check_mode=True
)
if not HAS_ZABBIX_API:
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
if not HAS_PYDOTPLUS:
module.fail_json(msg=missing_required_lib('pydotplus', url='https://pypi.org/project/pydotplus/'), exception=PYDOT_IMP_ERR)
if not HAS_WEBCOLORS:
module.fail_json(msg=missing_required_lib('webcolors', url='https://pypi.org/project/webcolors/'), exception=WEBCOLORS_IMP_ERR)
if not HAS_PIL:
module.fail_json(msg=missing_required_lib('Pillow', url='https://pypi.org/project/Pillow/'), exception=PIL_IMP_ERR)
server_url = module.params['server_url']
login_user = module.params['login_user']
login_password = module.params['login_password']
http_login_user = module.params['http_login_user']
http_login_password = module.params['http_login_password']
timeout = module.params['timeout']
validate_certs = module.params['validate_certs']
zbx = None
# login to zabbix
try:
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
validate_certs=validate_certs)
zbx.login(login_user, login_password)
atexit.register(zbx.logout)
except Exception as e:
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
sysmap = Map(module, zbx)
if sysmap.state == "absent":
if sysmap.map_exists():
sysmap.delete_map()
module.exit_json(changed=True, result="Successfully deleted map: %s" % sysmap.map_name)
else:
module.exit_json(changed=False)
else:
map_config = sysmap.get_map_config()
if sysmap.map_exists():
if sysmap.is_exist_map_correct(map_config):
module.exit_json(changed=False)
else:
sysmap.update_map(map_config)
module.exit_json(changed=True, result="Successfully updated map: %s" % sysmap.map_name)
else:
sysmap.create_map(map_config)
module.exit_json(changed=True, result="Successfully created map: %s" % sysmap.map_name)
if __name__ == '__main__':
main()

View file

@ -1,705 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# 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
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = r'''
---
module: zabbix_mediatype
short_description: Create/Update/Delete Zabbix media types
description:
- This module allows you to create, modify and delete Zabbix media types.
author:
- Ruben Tsirunyan (@rubentsirunyan)
requirements:
- "zabbix-api >= 0.5.4"
options:
name:
type: 'str'
description:
- Name of the media type.
required: true
state:
type: 'str'
description:
- Desired state of the mediatype.
- On C(present), it will create a mediatype if it does not exist or update the mediatype if the associated data is different.
- On C(absent), it will remove the mediatype if it exists.
choices:
- present
- absent
default: 'present'
type:
type: 'str'
description:
- Type of the media type.
- Media types I(jabber) and I(ez_texting) workable only with Zabbix 4.2 or less.
choices:
- email
- script
- sms
- jabber
- ez_texting
required: true
status:
type: 'str'
description:
- Whether the media type is enabled or no.
choices:
- enabled
- disabled
default: 'enabled'
max_sessions:
type: 'int'
description:
- The maximum number of alerts that can be processed in parallel.
- Possible value is 1 when I(type=sms) and 0-100 otherwise.
default: 1
max_attempts:
type: 'int'
description:
- The maximum number of attempts to send an alert.
- Possible range is 0-10
default: 3
attempt_interval:
type: 'int'
description:
- The interval between retry attempts.
- Possible range is 0-60
default: 10
script_name:
type: 'str'
description:
- The name of the executed script.
- Required when I(type=script).
script_params:
type: 'list'
elements: str
description:
- List of script parameters.
- Required when I(type=script).
gsm_modem:
type: 'str'
description:
- Serial device name of the gsm modem.
- Required when I(type=sms).
username:
type: 'str'
description:
- Username or Jabber identifier.
- Required when I(type=jabber) or I(type=ez_texting).
- Required when I(type=email) and I(smtp_authentication=true).
password:
type: 'str'
description:
- Authentication password.
- Required when I(type=jabber) or I(type=ez_texting).
- Required when I(type=email) and I(smtp_authentication=true).
smtp_server:
type: 'str'
description:
- SMTP server host.
- Required when I(type=email).
default: 'localhost'
smtp_server_port:
type: 'int'
description:
- SMTP server port.
- Required when I(type=email).
default: 25
smtp_helo:
type: 'str'
description:
- SMTP HELO.
- Required when I(type=email).
default: 'localhost'
smtp_email:
type: 'str'
description:
- Email address from which notifications will be sent.
- Required when I(type=email).
smtp_authentication:
type: 'bool'
description:
- Whether SMTP authentication with username and password should be enabled or not.
- If set to C(true), C(username) and C(password) should be specified.
default: false
smtp_security:
type: 'str'
description:
- SMTP connection security level to use.
choices:
- None
- STARTTLS
- SSL/TLS
smtp_verify_host:
type: 'bool'
description:
- SSL verify host for SMTP.
- Can be specified when I(smtp_security=STARTTLS) or I(smtp_security=SSL/TLS)
default: false
smtp_verify_peer:
type: 'bool'
description:
- SSL verify peer for SMTP.
- Can be specified when I(smtp_security=STARTTLS) or I(smtp_security=SSL/TLS)
default: false
message_text_limit:
type: 'str'
description:
- The message text limit.
- Required when I(type=ez_texting).
- 160 characters for USA and 136 characters for Canada.
choices:
- USA
- Canada
extends_documentation_fragment:
- community.general.zabbix
'''
RETURN = r''' # '''
EXAMPLES = r'''
- name: 'Create an email mediatype with SMTP authentication'
zabbix_mediatype:
name: "Ops email"
server_url: "http://example.com/zabbix/"
login_user: Admin
login_password: "zabbix"
type: 'email'
smtp_server: 'example.com'
smtp_server_port: 2000
smtp_email: 'ops@example.com'
smtp_authentication: true
username: 'smtp_user'
password: 'smtp_pass'
- name: 'Create a script mediatype'
zabbix_mediatype:
name: "my script"
server_url: "http://example.com/zabbix/"
login_user: Admin
login_password: "zabbix"
type: 'script'
script_name: 'my_script.py'
script_params:
- 'arg1'
- 'arg2'
- name: 'Create a jabber mediatype'
zabbix_mediatype:
name: "My jabber"
server_url: "http://example.com/zabbix/"
login_user: Admin
login_password: "zabbix"
type: 'jabber'
username: 'jabber_id'
password: 'jabber_pass'
- name: 'Create an SMS mediatype'
zabbix_mediatype:
name: "My SMS Mediatype"
server_url: "http://example.com/zabbix/"
login_user: Admin
login_password: "zabbix"
type: 'sms'
gsm_modem: '/dev/ttyS0'
'''
import atexit
import traceback
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from distutils.version import LooseVersion
try:
from zabbix_api import ZabbixAPI
HAS_ZABBIX_API = True
except ImportError:
ZBX_IMP_ERR = traceback.format_exc()
HAS_ZABBIX_API = False
def to_numeric_value(value, strs):
return strs.get(value)
def validate_params(module, params):
"""Validates arguments that are required together.
Fails the module with the message that shows the missing
requirements if there are some.
Args:
module: AnsibleModule object.
params (list): Each element of this list
is a list like
['argument_key', 'argument_value', ['required_arg_1',
'required_arg_2']].
Format is the same as `required_if` parameter of AnsibleModule.
"""
for param in params:
if module.params[param[0]] == param[1]:
if None in [module.params[i] for i in param[2]]:
module.fail_json(
msg="Following arguments are required when {key} is {value}: {arguments}".format(
key=param[0],
value=param[1],
arguments=', '.join(param[2])
)
)
def construct_parameters(**kwargs):
"""Translates data to a format suitable for Zabbix API and filters
the ones that are related to the specified mediatype type.
Args:
**kwargs: Arguments passed to the module.
Returns:
A dictionary of arguments that are related to kwargs['transport_type'],
and are in a format that is understandable by Zabbix API.
"""
if kwargs['transport_type'] == 'email':
return dict(
description=kwargs['name'],
status=to_numeric_value(kwargs['status'],
{'enabled': '0',
'disabled': '1'}),
type=to_numeric_value(kwargs['transport_type'],
{'email': '0',
'script': '1',
'sms': '2',
'jabber': '3',
'ez_texting': '100'}),
maxsessions=str(kwargs['max_sessions']),
maxattempts=str(kwargs['max_attempts']),
attempt_interval=str(kwargs['attempt_interval']),
smtp_server=kwargs['smtp_server'],
smtp_port=str(kwargs['smtp_server_port']),
smtp_helo=kwargs['smtp_helo'],
smtp_email=kwargs['smtp_email'],
smtp_security=to_numeric_value(str(kwargs['smtp_security']),
{'None': '0',
'STARTTLS': '1',
'SSL/TLS': '2'}),
smtp_authentication=to_numeric_value(str(kwargs['smtp_authentication']),
{'False': '0',
'True': '1'}),
smtp_verify_host=to_numeric_value(str(kwargs['smtp_verify_host']),
{'False': '0',
'True': '1'}),
smtp_verify_peer=to_numeric_value(str(kwargs['smtp_verify_peer']),
{'False': '0',
'True': '1'}),
username=kwargs['username'],
passwd=kwargs['password']
)
elif kwargs['transport_type'] == 'script':
if kwargs['script_params'] is None:
_script_params = '' # ZBX-15706
else:
_script_params = '\n'.join(str(i) for i in kwargs['script_params']) + '\n'
return dict(
description=kwargs['name'],
status=to_numeric_value(kwargs['status'],
{'enabled': '0',
'disabled': '1'}),
type=to_numeric_value(kwargs['transport_type'],
{'email': '0',
'script': '1',
'sms': '2',
'jabber': '3',
'ez_texting': '100'}),
maxsessions=str(kwargs['max_sessions']),
maxattempts=str(kwargs['max_attempts']),
attempt_interval=str(kwargs['attempt_interval']),
exec_path=kwargs['script_name'],
exec_params=_script_params
)
elif kwargs['transport_type'] == 'sms':
return dict(
description=kwargs['name'],
status=to_numeric_value(kwargs['status'],
{'enabled': '0',
'disabled': '1'}),
type=to_numeric_value(kwargs['transport_type'],
{'email': '0',
'script': '1',
'sms': '2',
'jabber': '3',
'ez_texting': '100'}),
maxsessions=str(kwargs['max_sessions']),
maxattempts=str(kwargs['max_attempts']),
attempt_interval=str(kwargs['attempt_interval']),
gsm_modem=kwargs['gsm_modem']
)
elif kwargs['transport_type'] == 'jabber' and LooseVersion(kwargs['zbx_api_version']) <= LooseVersion('4.2'):
return dict(
description=kwargs['name'],
status=to_numeric_value(kwargs['status'],
{'enabled': '0',
'disabled': '1'}),
type=to_numeric_value(kwargs['transport_type'],
{'email': '0',
'script': '1',
'sms': '2',
'jabber': '3',
'ez_texting': '100'}),
maxsessions=str(kwargs['max_sessions']),
maxattempts=str(kwargs['max_attempts']),
attempt_interval=str(kwargs['attempt_interval']),
username=kwargs['username'],
passwd=kwargs['password']
)
elif kwargs['transport_type'] == 'ez_texting' and LooseVersion(kwargs['zbx_api_version']) <= LooseVersion('4.2'):
return dict(
description=kwargs['name'],
status=to_numeric_value(kwargs['status'],
{'enabled': '0',
'disabled': '1'}),
type=to_numeric_value(kwargs['transport_type'],
{'email': '0',
'script': '1',
'sms': '2',
'jabber': '3',
'ez_texting': '100'}),
maxsessions=str(kwargs['max_sessions']),
maxattempts=str(kwargs['max_attempts']),
attempt_interval=str(kwargs['attempt_interval']),
username=kwargs['username'],
passwd=kwargs['password'],
exec_path=to_numeric_value(kwargs['message_text_limit'],
{'USA': '0',
'Canada': '1'}),
)
return {'unsupported_parameter': kwargs['transport_type'], 'zbx_api_version': kwargs['zbx_api_version']}
def check_if_mediatype_exists(module, zbx, name, zbx_api_version):
"""Checks if mediatype exists.
Args:
module: AnsibleModule object
zbx: ZabbixAPI object
name: Zabbix mediatype name
Returns:
Tuple of (True, `id of the mediatype`) if mediatype exists, (False, None) otherwise
"""
filter_key_name = 'description'
if LooseVersion(zbx_api_version) >= LooseVersion('4.4'):
# description key changed to name key from zabbix 4.4
filter_key_name = 'name'
try:
mediatype_list = zbx.mediatype.get({
'output': 'extend',
'filter': {filter_key_name: [name]}
})
if len(mediatype_list) < 1:
return False, None
else:
return True, mediatype_list[0]['mediatypeid']
except Exception as e:
module.fail_json(msg="Failed to get ID of the mediatype '{name}': {e}".format(name=name, e=e))
def diff(existing, new):
"""Constructs the diff for Ansible's --diff option.
Args:
existing (dict): Existing mediatype data.
new (dict): New mediatype data.
Returns:
A dictionary like {'before': existing, 'after': new}
with filtered empty values.
"""
before = {}
after = {}
for key in new:
before[key] = existing[key]
if new[key] is None:
after[key] = ''
else:
after[key] = new[key]
return {'before': before, 'after': after}
def get_update_params(module, zbx, mediatype_id, **kwargs):
"""Filters only the parameters that are different and need to be updated.
Args:
module: AnsibleModule object.
zbx: ZabbixAPI object.
mediatype_id (int): ID of the mediatype to be updated.
**kwargs: Parameters for the new mediatype.
Returns:
A tuple where the first element is a dictionary of parameters
that need to be updated and the second one is a dictionary
returned by diff() function with
existing mediatype data and new params passed to it.
"""
existing_mediatype = zbx.mediatype.get({
'output': 'extend',
'mediatypeids': [mediatype_id]
})[0]
if existing_mediatype['type'] != kwargs['type']:
return kwargs, diff(existing_mediatype, kwargs)
else:
params_to_update = {}
for key in kwargs:
if (not (kwargs[key] is None and existing_mediatype[key] == '')) and kwargs[key] != existing_mediatype[key]:
params_to_update[key] = kwargs[key]
return params_to_update, diff(existing_mediatype, kwargs)
def delete_mediatype(module, zbx, mediatype_id):
try:
return zbx.mediatype.delete([mediatype_id])
except Exception as e:
module.fail_json(msg="Failed to delete mediatype '{_id}': {e}".format(_id=mediatype_id, e=e))
def update_mediatype(module, zbx, **kwargs):
try:
mediatype_id = zbx.mediatype.update(kwargs)
except Exception as e:
module.fail_json(msg="Failed to update mediatype '{_id}': {e}".format(_id=kwargs['mediatypeid'], e=e))
def create_mediatype(module, zbx, **kwargs):
try:
mediatype_id = zbx.mediatype.create(kwargs)
except Exception as e:
module.fail_json(msg="Failed to create mediatype '{name}': {e}".format(name=kwargs['description'], e=e))
def main():
argument_spec = dict(
server_url=dict(type='str', required=True, aliases=['url']),
login_user=dict(type='str', required=True),
login_password=dict(type='str', required=True, no_log=True),
http_login_user=dict(type='str', required=False, default=None),
http_login_password=dict(type='str', required=False, default=None, no_log=True),
validate_certs=dict(type='bool', required=False, default=True), timeout=dict(type='int', default=10),
name=dict(type='str', required=True),
state=dict(type='str', default='present', choices=['present', 'absent']),
type=dict(type='str', choices=['email', 'script', 'sms', 'jabber', 'ez_texting'], required=True),
status=dict(type='str', default='enabled', choices=['enabled', 'disabled'], required=False),
max_sessions=dict(type='int', default=1, required=False),
max_attempts=dict(type='int', default=3, required=False),
attempt_interval=dict(type='int', default=10, required=False),
# Script
script_name=dict(type='str', required=False),
script_params=dict(type='list', required=False),
# SMS
gsm_modem=dict(type='str', required=False),
# Jabber
username=dict(type='str', required=False),
password=dict(type='str', required=False, no_log=True),
# Email
smtp_server=dict(type='str', default='localhost', required=False),
smtp_server_port=dict(type='int', default=25, required=False),
smtp_helo=dict(type='str', default='localhost', required=False),
smtp_email=dict(type='str', required=False),
smtp_security=dict(type='str', required=False, choices=['None', 'STARTTLS', 'SSL/TLS']),
smtp_authentication=dict(type='bool', default=False, required=False),
smtp_verify_host=dict(type='bool', default=False, required=False),
smtp_verify_peer=dict(type='bool', default=False, required=False),
# EZ Text
message_text_limit=dict(type='str', required=False, choices=['USA', 'Canada'])
)
required_params = [
['type', 'email', ['smtp_email']],
['type', 'script', ['script_name']],
['type', 'sms', ['gsm_modem']],
['type', 'jabber', ['username', 'password']],
['type', 'ez_texting', ['username', 'password', 'message_text_limit']],
['smtp_authentication', True, ['username', 'password']]
]
module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=True
)
if module.params['state'] == 'present':
validate_params(module, required_params)
if not HAS_ZABBIX_API:
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
server_url = module.params['server_url']
login_user = module.params['login_user']
login_password = module.params['login_password']
http_login_user = module.params['http_login_user']
http_login_password = module.params['http_login_password']
validate_certs = module.params['validate_certs']
state = module.params['state']
timeout = module.params['timeout']
name = module.params['name']
transport_type = module.params['type']
status = module.params['status']
max_sessions = module.params['max_sessions']
max_attempts = module.params['max_attempts']
attempt_interval = module.params['attempt_interval']
# Script
script_name = module.params['script_name']
script_params = module.params['script_params']
# SMS
gsm_modem = module.params['gsm_modem']
# Jabber
username = module.params['username']
password = module.params['password']
# Email
smtp_server = module.params['smtp_server']
smtp_server_port = module.params['smtp_server_port']
smtp_helo = module.params['smtp_helo']
smtp_email = module.params['smtp_email']
smtp_security = module.params['smtp_security']
smtp_authentication = module.params['smtp_authentication']
smtp_verify_host = module.params['smtp_verify_host']
smtp_verify_peer = module.params['smtp_verify_peer']
# EZ Text
message_text_limit = module.params['message_text_limit']
zbx = None
# login to zabbix
try:
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
validate_certs=validate_certs)
zbx.login(login_user, login_password)
atexit.register(zbx.logout)
except Exception as e:
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
zbx_api_version = zbx.api_version()[:3]
mediatype_exists, mediatype_id = check_if_mediatype_exists(module, zbx, name, zbx_api_version)
parameters = construct_parameters(
name=name,
transport_type=transport_type,
status=status,
max_sessions=max_sessions,
max_attempts=max_attempts,
attempt_interval=attempt_interval,
script_name=script_name,
script_params=script_params,
gsm_modem=gsm_modem,
username=username,
password=password,
smtp_server=smtp_server,
smtp_server_port=smtp_server_port,
smtp_helo=smtp_helo,
smtp_email=smtp_email,
smtp_security=smtp_security,
smtp_authentication=smtp_authentication,
smtp_verify_host=smtp_verify_host,
smtp_verify_peer=smtp_verify_peer,
message_text_limit=message_text_limit,
zbx_api_version=zbx_api_version
)
if 'unsupported_parameter' in parameters:
module.fail_json(msg="%s is unsupported for Zabbix version %s" % (parameters['unsupported_parameter'], parameters['zbx_api_version']))
if LooseVersion(zbx_api_version) >= LooseVersion('4.4'):
# description key changed to name key from zabbix 4.4
parameters['name'] = parameters.pop('description')
if mediatype_exists:
if state == 'absent':
if module.check_mode:
module.exit_json(
changed=True,
msg="Mediatype would have been deleted. Name: {name}, ID: {_id}".format(
name=name,
_id=mediatype_id
)
)
mediatype_id = delete_mediatype(module, zbx, mediatype_id)
module.exit_json(
changed=True,
msg="Mediatype deleted. Name: {name}, ID: {_id}".format(
name=name,
_id=mediatype_id
)
)
else:
params_to_update, diff = get_update_params(module, zbx, mediatype_id, **parameters)
if params_to_update == {}:
module.exit_json(
changed=False,
msg="Mediatype is up to date: {name}".format(name=name)
)
else:
if module.check_mode:
module.exit_json(
changed=True,
diff=diff,
msg="Mediatype would have been updated. Name: {name}, ID: {_id}".format(
name=name,
_id=mediatype_id
)
)
mediatype_id = update_mediatype(
module, zbx,
mediatypeid=mediatype_id,
**params_to_update
)
module.exit_json(
changed=True,
diff=diff,
msg="Mediatype updated. Name: {name}, ID: {_id}".format(
name=name,
_id=mediatype_id
)
)
else:
if state == "absent":
module.exit_json(changed=False)
else:
if module.check_mode:
module.exit_json(
changed=True,
msg="Mediatype would have been created. Name: {name}, ID: {_id}".format(
name=name,
_id=mediatype_id
)
)
mediatype_id = create_mediatype(module, zbx, **parameters)
module.exit_json(
changed=True,
msg="Mediatype created: {name}, ID: {_id}".format(
name=name,
_id=mediatype_id
)
)
if __name__ == '__main__':
main()

View file

@ -1,471 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2017, Alen Komic
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = r'''
---
module: zabbix_proxy
short_description: Create/delete/get/update Zabbix proxies
description:
- This module allows you to create, modify, get and delete Zabbix proxy entries.
author:
- "Alen Komic (@akomic)"
requirements:
- "python >= 2.6"
- "zabbix-api >= 0.5.4"
options:
proxy_name:
description:
- Name of the proxy in Zabbix.
required: true
type: str
proxy_address:
description:
- Comma-delimited list of IP/CIDR addresses or DNS names to accept active proxy requests from.
- Requires I(status=active).
- Works only with >= Zabbix 4.0. ( remove option for <= 4.0 )
required: false
type: str
description:
description:
- Description of the proxy.
required: false
type: str
status:
description:
- Type of proxy. (4 - active, 5 - passive)
required: false
choices: ['active', 'passive']
default: "active"
type: str
tls_connect:
description:
- Connections to proxy.
required: false
choices: ['no_encryption','PSK','certificate']
default: 'no_encryption'
type: str
tls_accept:
description:
- Connections from proxy.
required: false
choices: ['no_encryption','PSK','certificate']
default: 'no_encryption'
type: str
ca_cert:
description:
- Certificate issuer.
required: false
aliases: [ tls_issuer ]
type: str
tls_subject:
description:
- Certificate subject.
required: false
type: str
tls_psk_identity:
description:
- PSK identity. Required if either I(tls_connect) or I(tls_accept) has PSK enabled.
required: false
type: str
tls_psk:
description:
- The preshared key, at least 32 hex digits. Required if either I(tls_connect) or I(tls_accept) has PSK enabled.
required: false
type: str
state:
description:
- State of the proxy.
- On C(present), it will create if proxy does not exist or update the proxy if the associated data is different.
- On C(absent) will remove a proxy if it exists.
required: false
choices: ['present', 'absent']
default: "present"
type: str
interface:
description:
- Dictionary with params for the interface when proxy is in passive mode.
- For more information, review proxy interface documentation at
- U(https://www.zabbix.com/documentation/4.0/manual/api/reference/proxy/object#proxy_interface).
required: false
suboptions:
useip:
type: int
description:
- Connect to proxy interface with IP address instead of DNS name.
- 0 (don't use ip), 1 (use ip).
default: 0
choices: [0, 1]
ip:
type: str
description:
- IP address used by proxy interface.
- Required if I(useip=1).
default: ''
dns:
type: str
description:
- DNS name of the proxy interface.
- Required if I(useip=0).
default: ''
port:
type: str
description:
- Port used by proxy interface.
default: '10051'
type:
type: int
description:
- Interface type to add.
- This suboption is currently ignored for Zabbix proxy.
- This suboption is deprecated since Ansible 2.10 and will eventually be removed in 2.14.
required: false
default: 0
main:
type: int
description:
- Whether the interface is used as default.
- This suboption is currently ignored for Zabbix proxy.
- This suboption is deprecated since Ansible 2.10 and will eventually be removed in 2.14.
required: false
default: 0
default: {}
type: dict
extends_documentation_fragment:
- community.general.zabbix
'''
EXAMPLES = r'''
- name: Create or update a proxy with proxy type active
local_action:
module: zabbix_proxy
server_url: http://monitor.example.com
login_user: username
login_password: password
proxy_name: ExampleProxy
description: ExampleProxy
status: active
state: present
proxy_address: ExampleProxy.local
- name: Create a new passive proxy using only it's IP
local_action:
module: zabbix_proxy
server_url: http://monitor.example.com
login_user: username
login_password: password
proxy_name: ExampleProxy
description: ExampleProxy
status: passive
state: present
interface:
useip: 1
ip: 10.1.1.2
port: 10051
- name: Create a new passive proxy using only it's DNS
local_action:
module: zabbix_proxy
server_url: http://monitor.example.com
login_user: username
login_password: password
proxy_name: ExampleProxy
description: ExampleProxy
status: passive
state: present
interface:
dns: proxy.example.com
port: 10051
'''
RETURN = r''' # '''
import traceback
import atexit
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
try:
from zabbix_api import ZabbixAPI
HAS_ZABBIX_API = True
except ImportError:
ZBX_IMP_ERR = traceback.format_exc()
HAS_ZABBIX_API = False
class Proxy(object):
def __init__(self, module, zbx):
self._module = module
self._zapi = zbx
self.existing_data = None
def proxy_exists(self, proxy_name):
result = self._zapi.proxy.get({
'output': 'extend', 'selectInterface': 'extend',
'filter': {'host': proxy_name}})
if len(result) > 0 and 'proxyid' in result[0]:
self.existing_data = result[0]
return result[0]['proxyid']
else:
return result
def add_proxy(self, data):
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
parameters = {}
for item in data:
if data[item]:
parameters[item] = data[item]
if 'proxy_address' in data and data['status'] != '5':
parameters.pop('proxy_address', False)
if 'interface' in data and data['status'] != '6':
parameters.pop('interface', False)
proxy_ids_list = self._zapi.proxy.create(parameters)
self._module.exit_json(changed=True,
result="Successfully added proxy %s (%s)" %
(data['host'], data['status']))
if len(proxy_ids_list) >= 1:
return proxy_ids_list['proxyids'][0]
except Exception as e:
self._module.fail_json(msg="Failed to create proxy %s: %s" %
(data['host'], e))
def delete_proxy(self, proxy_id, proxy_name):
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
self._zapi.proxy.delete([proxy_id])
self._module.exit_json(changed=True,
result="Successfully deleted"
+ " proxy %s" % proxy_name)
except Exception as e:
self._module.fail_json(msg="Failed to delete proxy %s: %s" %
(proxy_name, str(e)))
def compile_interface_params(self, new_interface):
old_interface = {}
if 'interface' in self.existing_data and \
len(self.existing_data['interface']) > 0:
old_interface = self.existing_data['interface']
for item in ['type', 'main']:
new_interface.pop(item, False)
final_interface = old_interface.copy()
final_interface.update(new_interface)
final_interface = dict((k, str(v)) for k, v in final_interface.items())
if final_interface != old_interface:
return final_interface
else:
return {}
def update_proxy(self, proxy_id, data):
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
parameters = {'proxyid': proxy_id}
for item in data:
if data[item] and item in self.existing_data and \
self.existing_data[item] != data[item]:
parameters[item] = data[item]
if 'interface' in parameters:
parameters.pop('interface')
if 'proxy_address' in data and data['status'] != '5':
parameters.pop('proxy_address', False)
if 'interface' in data and data['status'] != '6':
parameters.pop('interface', False)
if 'interface' in data and data['status'] == '6':
new_interface = self.compile_interface_params(data['interface'])
if len(new_interface) > 0:
parameters['interface'] = new_interface
if len(parameters) > 1:
self._zapi.proxy.update(parameters)
self._module.exit_json(
changed=True,
result="Successfully updated proxy %s (%s)" %
(data['host'], proxy_id)
)
else:
self._module.exit_json(changed=False)
except Exception as e:
self._module.fail_json(msg="Failed to update proxy %s: %s" %
(data['host'], e))
def main():
module = AnsibleModule(
argument_spec=dict(
server_url=dict(type='str', required=True, aliases=['url']),
login_user=dict(type='str', required=True),
login_password=dict(type='str', required=True, no_log=True),
proxy_name=dict(type='str', required=True),
proxy_address=dict(type='str', required=False),
http_login_user=dict(type='str', required=False, default=None),
http_login_password=dict(type='str', required=False,
default=None, no_log=True),
validate_certs=dict(type='bool', required=False, default=True),
status=dict(type='str', default="active", choices=['active', 'passive']),
state=dict(type='str', default="present", choices=['present', 'absent']),
description=dict(type='str', required=False),
tls_connect=dict(type='str', default='no_encryption',
choices=['no_encryption', 'PSK', 'certificate']),
tls_accept=dict(type='str', default='no_encryption',
choices=['no_encryption', 'PSK', 'certificate']),
ca_cert=dict(type='str', required=False, default=None, aliases=['tls_issuer']),
tls_subject=dict(type='str', required=False, default=None),
tls_psk_identity=dict(type='str', required=False, default=None),
tls_psk=dict(type='str', required=False, default=None),
timeout=dict(type='int', default=10),
interface=dict(
type='dict',
required=False,
default={},
options=dict(
useip=dict(type='int', choices=[0, 1], default=0),
ip=dict(type='str', default=''),
dns=dict(type='str', default=''),
port=dict(type='str', default='10051'),
type=dict(type='int', default=0, removed_in_version='2.14'),
main=dict(type='int', default=0, removed_in_version='2.14')
),
)
),
supports_check_mode=True
)
if not HAS_ZABBIX_API:
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
server_url = module.params['server_url']
login_user = module.params['login_user']
login_password = module.params['login_password']
http_login_user = module.params['http_login_user']
http_login_password = module.params['http_login_password']
validate_certs = module.params['validate_certs']
proxy_name = module.params['proxy_name']
proxy_address = module.params['proxy_address']
description = module.params['description']
status = module.params['status']
tls_connect = module.params['tls_connect']
tls_accept = module.params['tls_accept']
tls_issuer = module.params['ca_cert']
tls_subject = module.params['tls_subject']
tls_psk_identity = module.params['tls_psk_identity']
tls_psk = module.params['tls_psk']
state = module.params['state']
timeout = module.params['timeout']
interface = module.params['interface']
# convert enabled to 0; disabled to 1
status = 6 if status == "passive" else 5
if tls_connect == 'certificate':
tls_connect = 4
elif tls_connect == 'PSK':
tls_connect = 2
else:
tls_connect = 1
if tls_accept == 'certificate':
tls_accept = 4
elif tls_accept == 'PSK':
tls_accept = 2
else:
tls_accept = 1
zbx = None
# login to zabbix
try:
zbx = ZabbixAPI(server_url, timeout=timeout,
user=http_login_user,
passwd=http_login_password,
validate_certs=validate_certs)
zbx.login(login_user, login_password)
atexit.register(zbx.logout)
except Exception as e:
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
proxy = Proxy(module, zbx)
# check if proxy already exists
proxy_id = proxy.proxy_exists(proxy_name)
if proxy_id:
if state == "absent":
# remove proxy
proxy.delete_proxy(proxy_id, proxy_name)
else:
proxy.update_proxy(proxy_id, {
'host': proxy_name,
'description': description,
'status': str(status),
'tls_connect': str(tls_connect),
'tls_accept': str(tls_accept),
'tls_issuer': tls_issuer,
'tls_subject': tls_subject,
'tls_psk_identity': tls_psk_identity,
'tls_psk': tls_psk,
'interface': interface,
'proxy_address': proxy_address
})
else:
if state == "absent":
# the proxy is already deleted.
module.exit_json(changed=False)
proxy_id = proxy.add_proxy(data={
'host': proxy_name,
'description': description,
'status': str(status),
'tls_connect': str(tls_connect),
'tls_accept': str(tls_accept),
'tls_issuer': tls_issuer,
'tls_subject': tls_subject,
'tls_psk_identity': tls_psk_identity,
'tls_psk': tls_psk,
'interface': interface,
'proxy_address': proxy_address
})
if __name__ == '__main__':
main()

View file

@ -1,471 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2013-2014, Epic Games, Inc.
# 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
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = r'''
---
module: zabbix_screen
short_description: Create/update/delete Zabbix screens
description:
- This module allows you to create, modify and delete Zabbix screens and associated graph data.
author:
- "Cove (@cove)"
- "Tony Minfei Ding (!UNKNOWN)"
- "Harrison Gu (@harrisongu)"
requirements:
- "python >= 2.6"
- "zabbix-api >= 0.5.4"
options:
screens:
description:
- List of screens to be created/updated/deleted (see example).
type: list
elements: dict
required: true
suboptions:
screen_name:
description:
- Screen name will be used.
- If a screen has already been added, the screen name won't be updated.
type: str
required: true
host_group:
description:
- Host group will be used for searching hosts.
- Required if I(state=present).
type: str
state:
description:
- I(present) - Create a screen if it doesn't exist. If the screen already exists, the screen will be updated as needed.
- I(absent) - If a screen exists, the screen will be deleted.
type: str
default: present
choices:
- absent
- present
graph_names:
description:
- Graph names will be added to a screen. Case insensitive.
- Required if I(state=present).
type: list
elements: str
graph_width:
description:
- Graph width will be set in graph settings.
type: int
graph_height:
description:
- Graph height will be set in graph settings.
type: int
graphs_in_row:
description:
- Limit columns of a screen and make multiple rows.
type: int
default: 3
sort:
description:
- Sort hosts alphabetically.
- If there are numbers in hostnames, leading zero should be used.
type: bool
default: no
extends_documentation_fragment:
- community.general.zabbix
notes:
- Too many concurrent updates to the same screen may cause Zabbix to return errors, see examples for a workaround if needed.
'''
EXAMPLES = r'''
# Create/update a screen.
- name: Create a new screen or update an existing screen's items 5 in a row
local_action:
module: zabbix_screen
server_url: http://monitor.example.com
login_user: username
login_password: password
screens:
- screen_name: ExampleScreen1
host_group: Example group1
state: present
graph_names:
- Example graph1
- Example graph2
graph_width: 200
graph_height: 100
graphs_in_row: 5
# Create/update multi-screen
- name: Create two of new screens or update the existing screens' items
local_action:
module: zabbix_screen
server_url: http://monitor.example.com
login_user: username
login_password: password
screens:
- screen_name: ExampleScreen1
host_group: Example group1
state: present
graph_names:
- Example graph1
- Example graph2
graph_width: 200
graph_height: 100
- screen_name: ExampleScreen2
host_group: Example group2
state: present
graph_names:
- Example graph1
- Example graph2
graph_width: 200
graph_height: 100
# Limit the Zabbix screen creations to one host since Zabbix can return an error when doing concurrent updates
- name: Create a new screen or update an existing screen's items
local_action:
module: zabbix_screen
server_url: http://monitor.example.com
login_user: username
login_password: password
state: present
screens:
- screen_name: ExampleScreen
host_group: Example group
state: present
graph_names:
- Example graph1
- Example graph2
graph_width: 200
graph_height: 100
when: inventory_hostname==groups['group_name'][0]
'''
import atexit
import traceback
try:
from zabbix_api import ZabbixAPI
from zabbix_api import ZabbixAPIException
from zabbix_api import Already_Exists
HAS_ZABBIX_API = True
except ImportError:
ZBX_IMP_ERR = traceback.format_exc()
HAS_ZABBIX_API = False
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
class Screen(object):
def __init__(self, module, zbx):
self._module = module
self._zapi = zbx
# get group id by group name
def get_host_group_id(self, group_name):
if group_name == "":
self._module.fail_json(msg="group_name is required")
hostGroup_list = self._zapi.hostgroup.get({'output': 'extend', 'filter': {'name': group_name}})
if len(hostGroup_list) < 1:
self._module.fail_json(msg="Host group not found: %s" % group_name)
else:
hostGroup_id = hostGroup_list[0]['groupid']
return hostGroup_id
# get monitored host_id by host_group_id
def get_host_ids_by_group_id(self, group_id, sort):
host_list = self._zapi.host.get({'output': 'extend', 'groupids': group_id, 'monitored_hosts': 1})
if len(host_list) < 1:
self._module.fail_json(msg="No host in the group.")
else:
if sort:
host_list = sorted(host_list, key=lambda name: name['name'])
host_ids = []
for i in host_list:
host_id = i['hostid']
host_ids.append(host_id)
return host_ids
# get screen
def get_screen_id(self, screen_name):
if screen_name == "":
self._module.fail_json(msg="screen_name is required")
try:
screen_id_list = self._zapi.screen.get({'output': 'extend', 'search': {"name": screen_name}})
if len(screen_id_list) >= 1:
screen_id = screen_id_list[0]['screenid']
return screen_id
return None
except Exception as e:
self._module.fail_json(msg="Failed to get screen %s from Zabbix: %s" % (screen_name, e))
# create screen
def create_screen(self, screen_name, h_size, v_size):
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
screen = self._zapi.screen.create({'name': screen_name, 'hsize': h_size, 'vsize': v_size})
return screen['screenids'][0]
except Exception as e:
self._module.fail_json(msg="Failed to create screen %s: %s" % (screen_name, e))
# update screen
def update_screen(self, screen_id, screen_name, h_size, v_size):
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
self._zapi.screen.update({'screenid': screen_id, 'hsize': h_size, 'vsize': v_size})
except Exception as e:
self._module.fail_json(msg="Failed to update screen %s: %s" % (screen_name, e))
# delete screen
def delete_screen(self, screen_id, screen_name):
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
self._zapi.screen.delete([screen_id])
except Exception as e:
self._module.fail_json(msg="Failed to delete screen %s: %s" % (screen_name, e))
# get graph ids
def get_graph_ids(self, hosts, graph_name_list):
graph_id_lists = []
vsize = 1
for host in hosts:
graph_id_list = self.get_graphs_by_host_id(graph_name_list, host)
size = len(graph_id_list)
if size > 0:
graph_id_lists.extend(graph_id_list)
if vsize < size:
vsize = size
return graph_id_lists, vsize
# getGraphs
def get_graphs_by_host_id(self, graph_name_list, host_id):
graph_ids = []
for graph_name in graph_name_list:
graphs_list = self._zapi.graph.get({'output': 'extend', 'search': {'name': graph_name}, 'hostids': host_id})
graph_id_list = []
if len(graphs_list) > 0:
for graph in graphs_list:
graph_id = graph['graphid']
graph_id_list.append(graph_id)
if len(graph_id_list) > 0:
graph_ids.extend(graph_id_list)
return graph_ids
# get screen items
def get_screen_items(self, screen_id):
screen_item_list = self._zapi.screenitem.get({'output': 'extend', 'screenids': screen_id})
return screen_item_list
# delete screen items
def delete_screen_items(self, screen_id, screen_item_id_list):
try:
if len(screen_item_id_list) == 0:
return True
screen_item_list = self.get_screen_items(screen_id)
if len(screen_item_list) > 0:
if self._module.check_mode:
self._module.exit_json(changed=True)
self._zapi.screenitem.delete(screen_item_id_list)
return True
return False
except ZabbixAPIException:
pass
# get screen's hsize and vsize
def get_hsize_vsize(self, hosts, v_size, graphs_in_row):
h_size = len(hosts)
# when there is only one host, put all graphs in a row
if h_size == 1:
if v_size <= graphs_in_row:
h_size = v_size
else:
h_size = graphs_in_row
v_size = (v_size - 1) // h_size + 1
# when len(hosts) is more then graphs_in_row
elif len(hosts) > graphs_in_row:
h_size = graphs_in_row
v_size = (len(hosts) // graphs_in_row + 1) * v_size
return h_size, v_size
# create screen_items
def create_screen_items(self, screen_id, hosts, graph_name_list, width, height, h_size, graphs_in_row):
if len(hosts) < 4:
if width is None or width < 0:
width = 500
else:
if width is None or width < 0:
width = 200
if height is None or height < 0:
height = 100
try:
# when there're only one host, only one row is not good.
if len(hosts) == 1:
graph_id_list = self.get_graphs_by_host_id(graph_name_list, hosts[0])
for i, graph_id in enumerate(graph_id_list):
if graph_id is not None:
self._zapi.screenitem.create({'screenid': screen_id, 'resourcetype': 0, 'resourceid': graph_id,
'width': width, 'height': height,
'x': i % h_size, 'y': i // h_size, 'colspan': 1, 'rowspan': 1,
'elements': 0, 'valign': 0, 'halign': 0,
'style': 0, 'dynamic': 0, 'sort_triggers': 0})
else:
for i, host in enumerate(hosts):
graph_id_list = self.get_graphs_by_host_id(graph_name_list, host)
for j, graph_id in enumerate(graph_id_list):
if graph_id is not None:
self._zapi.screenitem.create({'screenid': screen_id, 'resourcetype': 0, 'resourceid': graph_id,
'width': width, 'height': height,
'x': i % graphs_in_row, 'y': len(graph_id_list) * (i // graphs_in_row) + j,
'colspan': 1, 'rowspan': 1,
'elements': 0, 'valign': 0, 'halign': 0,
'style': 0, 'dynamic': 0, 'sort_triggers': 0})
except Already_Exists:
pass
def main():
module = AnsibleModule(
argument_spec=dict(
server_url=dict(type='str', required=True, aliases=['url']),
login_user=dict(type='str', required=True),
login_password=dict(type='str', required=True, no_log=True),
http_login_user=dict(type='str', required=False, default=None),
http_login_password=dict(type='str', required=False, default=None, no_log=True),
validate_certs=dict(type='bool', required=False, default=True),
timeout=dict(type='int', default=10),
screens=dict(
type='list',
elements='dict',
required=True,
options=dict(
screen_name=dict(type='str', required=True),
host_group=dict(type='str'),
state=dict(type='str', default='present', choices=['absent', 'present']),
graph_names=dict(type='list', elements='str'),
graph_width=dict(type='int', default=None),
graph_height=dict(type='int', default=None),
graphs_in_row=dict(type='int', default=3),
sort=dict(default=False, type='bool'),
),
required_if=[
['state', 'present', ['host_group']]
]
)
),
supports_check_mode=True
)
if not HAS_ZABBIX_API:
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
server_url = module.params['server_url']
login_user = module.params['login_user']
login_password = module.params['login_password']
http_login_user = module.params['http_login_user']
http_login_password = module.params['http_login_password']
validate_certs = module.params['validate_certs']
timeout = module.params['timeout']
screens = module.params['screens']
zbx = None
# login to zabbix
try:
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
validate_certs=validate_certs)
zbx.login(login_user, login_password)
atexit.register(zbx.logout)
except Exception as e:
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
screen = Screen(module, zbx)
created_screens = []
changed_screens = []
deleted_screens = []
for zabbix_screen in screens:
screen_name = zabbix_screen['screen_name']
screen_id = screen.get_screen_id(screen_name)
state = zabbix_screen['state']
sort = zabbix_screen['sort']
if state == "absent":
if screen_id:
screen_item_list = screen.get_screen_items(screen_id)
screen_item_id_list = []
for screen_item in screen_item_list:
screen_item_id = screen_item['screenitemid']
screen_item_id_list.append(screen_item_id)
screen.delete_screen_items(screen_id, screen_item_id_list)
screen.delete_screen(screen_id, screen_name)
deleted_screens.append(screen_name)
else:
host_group = zabbix_screen['host_group']
graph_names = zabbix_screen['graph_names']
graphs_in_row = zabbix_screen['graphs_in_row']
graph_width = zabbix_screen['graph_width']
graph_height = zabbix_screen['graph_height']
host_group_id = screen.get_host_group_id(host_group)
hosts = screen.get_host_ids_by_group_id(host_group_id, sort)
screen_item_id_list = []
resource_id_list = []
graph_ids, v_size = screen.get_graph_ids(hosts, graph_names)
h_size, v_size = screen.get_hsize_vsize(hosts, v_size, graphs_in_row)
if not screen_id:
# create screen
screen_id = screen.create_screen(screen_name, h_size, v_size)
screen.create_screen_items(screen_id, hosts, graph_names, graph_width, graph_height, h_size, graphs_in_row)
created_screens.append(screen_name)
else:
screen_item_list = screen.get_screen_items(screen_id)
for screen_item in screen_item_list:
screen_item_id = screen_item['screenitemid']
resource_id = screen_item['resourceid']
screen_item_id_list.append(screen_item_id)
resource_id_list.append(resource_id)
# when the screen items changed, then update
if graph_ids != resource_id_list:
deleted = screen.delete_screen_items(screen_id, screen_item_id_list)
if deleted:
screen.update_screen(screen_id, screen_name, h_size, v_size)
screen.create_screen_items(screen_id, hosts, graph_names, graph_width, graph_height, h_size, graphs_in_row)
changed_screens.append(screen_name)
if created_screens and changed_screens:
module.exit_json(changed=True, result="Successfully created screen(s): %s, and updated screen(s): %s" % (",".join(created_screens),
",".join(changed_screens)))
elif created_screens:
module.exit_json(changed=True, result="Successfully created screen(s): %s" % ",".join(created_screens))
elif changed_screens:
module.exit_json(changed=True, result="Successfully updated screen(s): %s" % ",".join(changed_screens))
elif deleted_screens:
module.exit_json(changed=True, result="Successfully deleted screen(s): %s" % ",".join(deleted_screens))
else:
module.exit_json(changed=False)
if __name__ == '__main__':
main()

View file

@ -1,291 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2019, OVH SAS
# 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
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: zabbix_service
short_description: Create/update/delete Zabbix service
description:
- Create/update/delete Zabbix service.
author:
- "Emmanuel Riviere (@emriver)"
requirements:
- "python >= 2.7"
- "zabbix-api >= 0.5.4"
options:
name:
description:
- Name of Zabbix service
required: true
type: str
parent:
description:
- Name of Zabbix service parent
required: false
type: str
sla:
description:
- Sla value (i.e 99.99), goodsla in Zabbix API
required: false
type: float
calculate_sla:
description:
- If yes, calculate the SLA value for this service, showsla in Zabbix API
required: false
type: bool
algorithm:
description:
- Algorithm used to calculate the sla
- C(no), sla is not calculated
- C(one_child), problem if at least one child has a problem
- C(all_children), problem if all children have problems
required: false
type: str
choices: ["no", "one_child", "all_children"]
default: one_child
trigger_name:
description:
- Name of trigger linked to the service
required: false
type: str
trigger_host:
description:
- Name of host linked to the service
required: false
type: str
state:
description:
- 'State: present - create/update service; absent - delete service'
required: false
choices: [present, absent]
default: "present"
type: str
extends_documentation_fragment:
- community.general.zabbix
'''
EXAMPLES = '''
---
# Creates a new Zabbix service
- name: Manage services
local_action:
module: zabbix_service
server_url: "https://192.168.1.1"
login_user: username
login_password: password
name: apache2 service
sla: 99.99
calculate_sla: yes
algorithm: one_child
trigger_name: apache2 service status
trigger_host: webserver01
state: present
'''
RETURN = '''
---
'''
import atexit
import traceback
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
try:
from zabbix_api import ZabbixAPI, ZabbixAPIException
HAS_ZABBIX_API = True
except ImportError:
ZBX_IMP_ERR = traceback.format_exc()
HAS_ZABBIX_API = False
class Service(object):
def __init__(self, module, zbx):
self._module = module
self._zapi = zbx
def get_service_ids(self, service_name):
service_ids = []
services = self._zapi.service.get({'filter': {'name': service_name}})
for service in services:
service_ids.append(service['serviceid'])
return service_ids
def delete_service(self, service_ids):
if self._module.check_mode:
self._module.exit_json(changed=True)
self._zapi.service.delete(service_ids)
def dump_services(self, service_ids):
services = self._zapi.service.get({'output': 'extend', 'filter': {'serviceid': service_ids}, 'selectParent': '1'})
return services
def generate_service_config(self, name, parent, sla, calculate_sla, trigger_name, trigger_host, algorithm):
algorithms = {'no': '0', 'one_child': '1', 'all_children': '2'}
algorithm = algorithms[algorithm]
if calculate_sla:
calculate_sla = 1
else:
calculate_sla = 0
# Zabbix api return when no trigger
trigger_id = 0
if trigger_host and trigger_name:
# Retrieving the host to get the trigger
hosts = self._zapi.host.get({'filter': {'host': trigger_host}})
if not hosts:
self._module.fail_json(msg="Target host %s not found" % trigger_host)
host_id = hosts[0]['hostid']
triggers = self._zapi.trigger.get({'filter': {'description': trigger_name}, 'hostids': [host_id]})
if not triggers:
self._module.fail_json(msg="Trigger %s not found on host %s" % (trigger_name, trigger_host))
trigger_id = triggers[0]['triggerid']
request = {
'name': name,
'algorithm': algorithm,
'showsla': calculate_sla,
'sortorder': 1,
'goodsla': format(sla, '.4f'), # Sla has 4 decimals
'triggerid': trigger_id
}
if parent:
parent_ids = self.get_service_ids(parent)
if not parent_ids:
self._module.fail_json(msg="Parent %s not found" % parent)
request['parentid'] = parent_ids[0]
return request
def create_service(self, name, parent, sla, calculate_sla, trigger_name, trigger_host, algorithm):
if self._module.check_mode:
self._module.exit_json(changed=True)
self._zapi.service.create(self.generate_service_config(name, parent, sla, calculate_sla, trigger_name, trigger_host, algorithm))
def update_service(self, service_id, name, parent, sla, calculate_sla, trigger_name, trigger_host, algorithm):
generated_config = self.generate_service_config(name, parent, sla, calculate_sla, trigger_name, trigger_host, algorithm)
live_config = self.dump_services(service_id)[0]
item_to_check = ['name', 'showsla', 'algorithm', 'triggerid', 'sortorder', 'goodsla']
change = False
for item in item_to_check:
if str(generated_config[item]) != str(live_config[item]):
change = True
# In Zabbix 4.0
# No parent returns : "parent": []
# A parent returns : "parent": { "serviceid": 12 }
if 'parentid' in generated_config:
if 'serviceid' in live_config['parent']:
if generated_config['parentid'] != live_config['parent']['serviceid']:
change = True
else:
change = True
elif 'serviceid' in live_config['parent']:
change = True
if not change:
self._module.exit_json(changed=False, msg="Service %s up to date" % name)
if self._module.check_mode:
self._module.exit_json(changed=True)
generated_config['serviceid'] = service_id
self._zapi.service.update(generated_config)
self._module.exit_json(changed=True, msg="Service %s updated" % name)
def main():
module = AnsibleModule(
argument_spec=dict(
server_url=dict(type='str', required=True, aliases=['url']),
login_user=dict(type='str', required=True),
login_password=dict(type='str', required=True, no_log=True),
http_login_user=dict(type='str', required=False, default=None),
http_login_password=dict(type='str', required=False, default=None, no_log=True),
validate_certs=dict(type='bool', required=False, default=True),
name=dict(type='str', required=True),
parent=dict(type='str', required=False),
sla=dict(type='float', required=False),
calculate_sla=dict(type='bool', required=False, default=False),
algorithm=dict(default='one_child', required=False, choices=['no', 'one_child', 'all_children']),
trigger_name=dict(type='str', required=False),
trigger_host=dict(type='str', required=False),
state=dict(default="present", choices=['present', 'absent']),
timeout=dict(type='int', default=10)
),
supports_check_mode=True
)
if not HAS_ZABBIX_API:
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
server_url = module.params['server_url']
login_user = module.params['login_user']
login_password = module.params['login_password']
http_login_user = module.params['http_login_user']
http_login_password = module.params['http_login_password']
validate_certs = module.params['validate_certs']
name = module.params['name']
parent = module.params['parent']
sla = module.params['sla']
calculate_sla = module.params['calculate_sla']
algorithm = module.params['algorithm']
trigger_name = module.params['trigger_name']
trigger_host = module.params['trigger_host']
state = module.params['state']
timeout = module.params['timeout']
zbx = None
# Login to zabbix
try:
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password, validate_certs=validate_certs)
zbx.login(login_user, login_password)
atexit.register(zbx.logout)
except ZabbixAPIException as error:
module.fail_json(msg="Failed to connect to Zabbix server: %s" % error)
# Load service module
service = Service(module, zbx)
service_ids = service.get_service_ids(name)
if service_ids:
service_json = service.dump_services(service_ids)
# Delete service
if state == "absent":
if not service_ids:
module.exit_json(changed=False, msg="Service not found, no change: %s" % name)
service.delete_service(service_ids)
module.exit_json(changed=True, result="Successfully deleted service(s) %s" % name)
elif state == "present":
if (trigger_name and not trigger_host) or (trigger_host and not trigger_name):
module.fail_json(msg="Specify either both trigger_host and trigger_name or none to create or update a service")
# Does not exists going to create it
if not service_ids:
service.create_service(name, parent, sla, calculate_sla, trigger_name, trigger_host, algorithm)
module.exit_json(changed=True, msg="Service %s created" % name)
# Else we update it if needed
else:
service.update_service(service_ids[0], name, parent, sla, calculate_sla, trigger_name, trigger_host, algorithm)
if __name__ == '__main__':
main()

View file

@ -1,795 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2017, sookido
# 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
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = r'''
---
module: zabbix_template
short_description: Create/update/delete/dump Zabbix template
description:
- This module allows you to create, modify, delete and dump Zabbix templates.
- Multiple templates can be created or modified at once if passing JSON or XML to module.
author:
- "sookido (@sookido)"
- "Logan Vig (@logan2211)"
- "Dusan Matejka (@D3DeFi)"
requirements:
- "python >= 2.6"
- "zabbix-api >= 0.5.4"
options:
template_name:
description:
- Name of Zabbix template.
- Required when I(template_json) or I(template_xml) are not used.
- Mutually exclusive with I(template_json) and I(template_xml).
required: false
type: str
template_json:
description:
- JSON dump of templates to import.
- Multiple templates can be imported this way.
- Mutually exclusive with I(template_name) and I(template_xml).
required: false
type: json
template_xml:
description:
- XML dump of templates to import.
- Multiple templates can be imported this way.
- You are advised to pass XML structure matching the structure used by your version of Zabbix server.
- Custom XML structure can be imported as long as it is valid, but may not yield consistent idempotent
results on subsequent runs.
- Mutually exclusive with I(template_name) and I(template_json).
required: false
type: str
template_groups:
description:
- List of host groups to add template to when template is created.
- Replaces the current host groups the template belongs to if the template is already present.
- Required when creating a new template with C(state=present) and I(template_name) is used.
Not required when updating an existing template.
required: false
type: list
elements: str
link_templates:
description:
- List of template names to be linked to the template.
- Templates that are not specified and are linked to the existing template will be only unlinked and not
cleared from the template.
required: false
type: list
elements: str
clear_templates:
description:
- List of template names to be unlinked and cleared from the template.
- This option is ignored if template is being created for the first time.
required: false
type: list
elements: str
macros:
description:
- List of user macros to create for the template.
- Macros that are not specified and are present on the existing template will be replaced.
- See examples on how to pass macros.
required: false
type: list
elements: dict
suboptions:
name:
description:
- Name of the macro.
- Must be specified in {$NAME} format.
type: str
value:
description:
- Value of the macro.
type: str
dump_format:
description:
- Format to use when dumping template with C(state=dump).
- This option is deprecated and will eventually be removed in 2.14.
required: false
choices: [json, xml]
default: "json"
type: str
omit_date:
description:
- Removes the date field for the exported/dumped template
- Requires C(state=dump)
required: false
type: bool
default: false
state:
description:
- Required state of the template.
- On C(state=present) template will be created/imported or updated depending if it is already present.
- On C(state=dump) template content will get dumped into required format specified in I(dump_format).
- On C(state=absent) template will be deleted.
- The C(state=dump) is deprecated and will eventually be removed in 2.14. The M(zabbix_template_info) module should be used instead.
required: false
choices: [present, absent, dump]
default: "present"
type: str
extends_documentation_fragment:
- community.general.zabbix
'''
EXAMPLES = r'''
---
- name: Create a new Zabbix template linked to groups, macros and templates
local_action:
module: zabbix_template
server_url: http://127.0.0.1
login_user: username
login_password: password
template_name: ExampleHost
template_groups:
- Role
- Role2
link_templates:
- Example template1
- Example template2
macros:
- macro: '{$EXAMPLE_MACRO1}'
value: 30000
- macro: '{$EXAMPLE_MACRO2}'
value: 3
- macro: '{$EXAMPLE_MACRO3}'
value: 'Example'
state: present
- name: Unlink and clear templates from the existing Zabbix template
local_action:
module: zabbix_template
server_url: http://127.0.0.1
login_user: username
login_password: password
template_name: ExampleHost
clear_templates:
- Example template3
- Example template4
state: present
- name: Import Zabbix templates from JSON
local_action:
module: zabbix_template
server_url: http://127.0.0.1
login_user: username
login_password: password
template_json: "{{ lookup('file', 'zabbix_apache2.json') }}"
state: present
- name: Import Zabbix templates from XML
local_action:
module: zabbix_template
server_url: http://127.0.0.1
login_user: username
login_password: password
template_xml: "{{ lookup('file', 'zabbix_apache2.json') }}"
state: present
- name: Import Zabbix template from Ansible dict variable
zabbix_template:
login_user: username
login_password: password
server_url: http://127.0.0.1
template_json:
zabbix_export:
version: '3.2'
templates:
- name: Template for Testing
description: 'Testing template import'
template: Test Template
groups:
- name: Templates
applications:
- name: Test Application
state: present
- name: Configure macros on the existing Zabbix template
local_action:
module: zabbix_template
server_url: http://127.0.0.1
login_user: username
login_password: password
template_name: Template
macros:
- macro: '{$TEST_MACRO}'
value: 'Example'
state: present
- name: Delete Zabbix template
local_action:
module: zabbix_template
server_url: http://127.0.0.1
login_user: username
login_password: password
template_name: Template
state: absent
- name: Dump Zabbix template as JSON
local_action:
module: zabbix_template
server_url: http://127.0.0.1
login_user: username
login_password: password
template_name: Template
omit_date: yes
state: dump
register: template_dump
- name: Dump Zabbix template as XML
local_action:
module: zabbix_template
server_url: http://127.0.0.1
login_user: username
login_password: password
template_name: Template
dump_format: xml
omit_date: false
state: dump
register: template_dump
'''
RETURN = r'''
---
template_json:
description: The JSON dump of the template
returned: when state is dump and omit_date is no
type: str
sample: {
"zabbix_export":{
"date":"2017-11-29T16:37:24Z",
"templates":[{
"templates":[],
"description":"",
"httptests":[],
"screens":[],
"applications":[],
"discovery_rules":[],
"groups":[{"name":"Templates"}],
"name":"Test Template",
"items":[],
"macros":[],
"template":"test"
}],
"version":"3.2",
"groups":[{
"name":"Templates"
}]
}
}
template_xml:
description: dump of the template in XML representation
returned: when state is dump, dump_format is xml and omit_date is yes
type: str
sample: |-
<?xml version="1.0" ?>
<zabbix_export>
<version>4.2</version>
<groups>
<group>
<name>Templates</name>
</group>
</groups>
<templates>
<template>
<template>test</template>
<name>Test Template</name>
<description/>
<groups>
<group>
<name>Templates</name>
</group>
</groups>
<applications/>
<items/>
<discovery_rules/>
<httptests/>
<macros/>
<templates/>
<screens/>
<tags/>
</template>
</templates>
</zabbix_export>
'''
import atexit
import json
import traceback
import xml.etree.ElementTree as ET
from distutils.version import LooseVersion
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from ansible.module_utils._text import to_native
try:
from zabbix_api import ZabbixAPI, ZabbixAPIException
HAS_ZABBIX_API = True
except ImportError:
ZBX_IMP_ERR = traceback.format_exc()
HAS_ZABBIX_API = False
class Template(object):
def __init__(self, module, zbx):
self._module = module
self._zapi = zbx
# check if host group exists
def check_host_group_exist(self, group_names):
for group_name in group_names:
result = self._zapi.hostgroup.get({'filter': {'name': group_name}})
if not result:
self._module.fail_json(msg="Hostgroup not found: %s" %
group_name)
return True
# get group ids by group names
def get_group_ids_by_group_names(self, group_names):
group_ids = []
if group_names is None or len(group_names) == 0:
return group_ids
if self.check_host_group_exist(group_names):
group_list = self._zapi.hostgroup.get(
{'output': 'extend',
'filter': {'name': group_names}})
for group in group_list:
group_id = group['groupid']
group_ids.append({'groupid': group_id})
return group_ids
def get_template_ids(self, template_list):
template_ids = []
if template_list is None or len(template_list) == 0:
return template_ids
for template in template_list:
template_list = self._zapi.template.get(
{'output': 'extend',
'filter': {'host': template}})
if len(template_list) < 1:
continue
else:
template_id = template_list[0]['templateid']
template_ids.append(template_id)
return template_ids
def add_template(self, template_name, group_ids, link_template_ids, macros):
if self._module.check_mode:
self._module.exit_json(changed=True)
self._zapi.template.create({'host': template_name, 'groups': group_ids, 'templates': link_template_ids,
'macros': macros})
def check_template_changed(self, template_ids, template_groups, link_templates, clear_templates,
template_macros, template_content, template_type):
"""Compares template parameters to already existing values if any are found.
template_json - JSON structures are compared as deep sorted dictionaries,
template_xml - XML structures are compared as strings, but filtered and formatted first,
If none above is used, all the other arguments are compared to their existing counterparts
retrieved from Zabbix API."""
changed = False
# Compare filtered and formatted XMLs strings for any changes. It is expected that provided
# XML has same structure as Zabbix uses (e.g. it was optimally exported via Zabbix GUI or API)
if template_content is not None and template_type == 'xml':
existing_template = self.dump_template(template_ids, template_type='xml')
if self.filter_xml_template(template_content) != self.filter_xml_template(existing_template):
changed = True
return changed
existing_template = self.dump_template(template_ids, template_type='json')
# Compare JSON objects as deep sorted python dictionaries
if template_content is not None and template_type == 'json':
parsed_template_json = self.load_json_template(template_content)
if self.diff_template(parsed_template_json, existing_template):
changed = True
return changed
# If neither template_json or template_xml were used, user provided all parameters via module options
if template_groups is not None:
existing_groups = [g['name'] for g in existing_template['zabbix_export']['groups']]
if set(template_groups) != set(existing_groups):
changed = True
if 'templates' not in existing_template['zabbix_export']['templates'][0]:
existing_template['zabbix_export']['templates'][0]['templates'] = []
# Check if any new templates would be linked or any existing would be unlinked
exist_child_templates = [t['name'] for t in existing_template['zabbix_export']['templates'][0]['templates']]
if link_templates is not None:
if set(link_templates) != set(exist_child_templates):
changed = True
else:
if set([]) != set(exist_child_templates):
changed = True
# Mark that there will be changes when at least one existing template will be unlinked
if clear_templates is not None:
for t in clear_templates:
if t in exist_child_templates:
changed = True
break
if 'macros' not in existing_template['zabbix_export']['templates'][0]:
existing_template['zabbix_export']['templates'][0]['macros'] = []
if template_macros is not None:
existing_macros = existing_template['zabbix_export']['templates'][0]['macros']
if template_macros != existing_macros:
changed = True
return changed
def update_template(self, template_ids, group_ids, link_template_ids, clear_template_ids, template_macros):
template_changes = {}
if group_ids is not None:
template_changes.update({'groups': group_ids})
if link_template_ids is not None:
template_changes.update({'templates': link_template_ids})
else:
template_changes.update({'templates': []})
if clear_template_ids is not None:
template_changes.update({'templates_clear': clear_template_ids})
if template_macros is not None:
template_changes.update({'macros': template_macros})
if template_changes:
# If we got here we know that only one template was provided via template_name
template_changes.update({'templateid': template_ids[0]})
self._zapi.template.update(template_changes)
def delete_template(self, templateids):
if self._module.check_mode:
self._module.exit_json(changed=True)
self._zapi.template.delete(templateids)
def ordered_json(self, obj):
# Deep sort json dicts for comparison
if isinstance(obj, dict):
return sorted((k, self.ordered_json(v)) for k, v in obj.items())
if isinstance(obj, list):
return sorted(self.ordered_json(x) for x in obj)
else:
return obj
def dump_template(self, template_ids, template_type='json', omit_date=False):
if self._module.check_mode:
self._module.exit_json(changed=True)
try:
dump = self._zapi.configuration.export({'format': template_type, 'options': {'templates': template_ids}})
if template_type == 'xml':
xmlroot = ET.fromstring(dump.encode('utf-8'))
# remove date field if requested
if omit_date:
date = xmlroot.find(".date")
if date is not None:
xmlroot.remove(date)
return str(ET.tostring(xmlroot, encoding='utf-8').decode('utf-8'))
else:
return self.load_json_template(dump, omit_date=omit_date)
except ZabbixAPIException as e:
self._module.fail_json(msg='Unable to export template: %s' % e)
def diff_template(self, template_json_a, template_json_b):
# Compare 2 zabbix templates and return True if they differ.
template_json_a = self.filter_template(template_json_a)
template_json_b = self.filter_template(template_json_b)
if self.ordered_json(template_json_a) == self.ordered_json(template_json_b):
return False
return True
def filter_template(self, template_json):
# Filter the template json to contain only the keys we will update
keep_keys = set(['graphs', 'templates', 'triggers', 'value_maps'])
unwanted_keys = set(template_json['zabbix_export']) - keep_keys
for unwanted_key in unwanted_keys:
del template_json['zabbix_export'][unwanted_key]
# Versions older than 2.4 do not support description field within template
desc_not_supported = False
if LooseVersion(self._zapi.api_version()).version[:2] < LooseVersion('2.4').version:
desc_not_supported = True
# Filter empty attributes from template object to allow accurate comparison
for template in template_json['zabbix_export']['templates']:
for key in list(template.keys()):
if not template[key] or (key == 'description' and desc_not_supported):
template.pop(key)
return template_json
def filter_xml_template(self, template_xml):
"""Filters out keys from XML template that may wary between exports (e.g date or version) and
keys that are not imported via this module.
It is advised that provided XML template exactly matches XML structure used by Zabbix"""
# Strip last new line and convert string to ElementTree
parsed_xml_root = self.load_xml_template(template_xml.strip())
keep_keys = ['graphs', 'templates', 'triggers', 'value_maps']
# Remove unwanted XML nodes
for node in list(parsed_xml_root):
if node.tag not in keep_keys:
parsed_xml_root.remove(node)
# Filter empty attributes from template objects to allow accurate comparison
for template in list(parsed_xml_root.find('templates')):
for element in list(template):
if element.text is None and len(list(element)) == 0:
template.remove(element)
# Filter new lines and indentation
xml_root_text = list(line.strip() for line in ET.tostring(parsed_xml_root, encoding='utf8', method='xml').decode().split('\n'))
return ''.join(xml_root_text)
def load_json_template(self, template_json, omit_date=False):
try:
jsondoc = json.loads(template_json)
if omit_date and 'date' in jsondoc['zabbix_export']:
del jsondoc['zabbix_export']['date']
return jsondoc
except ValueError as e:
self._module.fail_json(msg='Invalid JSON provided', details=to_native(e), exception=traceback.format_exc())
def load_xml_template(self, template_xml):
try:
return ET.fromstring(template_xml)
except ET.ParseError as e:
self._module.fail_json(msg='Invalid XML provided', details=to_native(e), exception=traceback.format_exc())
def import_template(self, template_content, template_type='json'):
# rules schema latest version
update_rules = {
'applications': {
'createMissing': True,
'deleteMissing': True
},
'discoveryRules': {
'createMissing': True,
'updateExisting': True,
'deleteMissing': True
},
'graphs': {
'createMissing': True,
'updateExisting': True,
'deleteMissing': True
},
'groups': {
'createMissing': True
},
'httptests': {
'createMissing': True,
'updateExisting': True,
'deleteMissing': True
},
'items': {
'createMissing': True,
'updateExisting': True,
'deleteMissing': True
},
'templates': {
'createMissing': True,
'updateExisting': True
},
'templateLinkage': {
'createMissing': True
},
'templateScreens': {
'createMissing': True,
'updateExisting': True,
'deleteMissing': True
},
'triggers': {
'createMissing': True,
'updateExisting': True,
'deleteMissing': True
},
'valueMaps': {
'createMissing': True,
'updateExisting': True
}
}
try:
# old api version support here
api_version = self._zapi.api_version()
# updateExisting for application removed from zabbix api after 3.2
if LooseVersion(api_version).version[:2] <= LooseVersion('3.2').version:
update_rules['applications']['updateExisting'] = True
# templateLinkage.deleteMissing only available in 4.0 branch higher .16 and higher 4.4.4
# it's not available in 4.2 branches or lower 4.0.16
if LooseVersion(api_version).version[:2] == LooseVersion('4.0').version and \
LooseVersion(api_version).version[:3] >= LooseVersion('4.0.16').version:
update_rules['templateLinkage']['deleteMissing'] = True
if LooseVersion(api_version).version[:3] >= LooseVersion('4.4.4').version:
update_rules['templateLinkage']['deleteMissing'] = True
import_data = {'format': template_type, 'source': template_content, 'rules': update_rules}
self._zapi.configuration.import_(import_data)
except ZabbixAPIException as e:
self._module.fail_json(msg='Unable to import template', details=to_native(e),
exception=traceback.format_exc())
def main():
module = AnsibleModule(
argument_spec=dict(
server_url=dict(type='str', required=True, aliases=['url']),
login_user=dict(type='str', required=True),
login_password=dict(type='str', required=True, no_log=True),
http_login_user=dict(type='str', required=False, default=None),
http_login_password=dict(type='str', required=False, default=None, no_log=True),
validate_certs=dict(type='bool', required=False, default=True),
template_name=dict(type='str', required=False),
template_json=dict(type='json', required=False),
template_xml=dict(type='str', required=False),
template_groups=dict(type='list', required=False),
link_templates=dict(type='list', required=False),
clear_templates=dict(type='list', required=False),
macros=dict(type='list', required=False),
omit_date=dict(type='bool', required=False, default=False),
dump_format=dict(type='str', required=False, default='json', choices=['json', 'xml']),
state=dict(type='str', default="present", choices=['present', 'absent', 'dump']),
timeout=dict(type='int', default=10)
),
required_one_of=[
['template_name', 'template_json', 'template_xml']
],
mutually_exclusive=[
['template_name', 'template_json', 'template_xml']
],
required_if=[
['state', 'absent', ['template_name']],
['state', 'dump', ['template_name']]
],
supports_check_mode=True
)
if not HAS_ZABBIX_API:
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
server_url = module.params['server_url']
login_user = module.params['login_user']
login_password = module.params['login_password']
http_login_user = module.params['http_login_user']
http_login_password = module.params['http_login_password']
validate_certs = module.params['validate_certs']
template_name = module.params['template_name']
template_json = module.params['template_json']
template_xml = module.params['template_xml']
template_groups = module.params['template_groups']
link_templates = module.params['link_templates']
clear_templates = module.params['clear_templates']
template_macros = module.params['macros']
omit_date = module.params['omit_date']
dump_format = module.params['dump_format']
state = module.params['state']
timeout = module.params['timeout']
zbx = None
try:
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
validate_certs=validate_certs)
zbx.login(login_user, login_password)
atexit.register(zbx.logout)
except ZabbixAPIException as e:
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
template = Template(module, zbx)
# Identify template names for IDs retrieval
# Template names are expected to reside in ['zabbix_export']['templates'][*]['template'] for both data types
template_content, template_type = None, None
if template_json is not None:
template_type = 'json'
template_content = template_json
json_parsed = template.load_json_template(template_content)
template_names = list(t['template'] for t in json_parsed['zabbix_export']['templates'])
elif template_xml is not None:
template_type = 'xml'
template_content = template_xml
xml_parsed = template.load_xml_template(template_content)
template_names = list(t.find('template').text for t in list(xml_parsed.find('templates')))
else:
template_names = [template_name]
template_ids = template.get_template_ids(template_names)
if state == "absent":
if not template_ids:
module.exit_json(changed=False, msg="Template not found. No changed: %s" % template_name)
template.delete_template(template_ids)
module.exit_json(changed=True, result="Successfully deleted template %s" % template_name)
elif state == "dump":
module.deprecate("The 'dump' state has been deprecated and will be removed, use 'zabbix_template_info' module instead.", version='2.14')
if not template_ids:
module.fail_json(msg='Template not found: %s' % template_name)
if dump_format == 'json':
module.exit_json(changed=False, template_json=template.dump_template(template_ids, template_type='json', omit_date=omit_date))
elif dump_format == 'xml':
module.exit_json(changed=False, template_xml=template.dump_template(template_ids, template_type='xml', omit_date=omit_date))
elif state == "present":
# Load all subelements for template that were provided by user
group_ids = None
if template_groups is not None:
group_ids = template.get_group_ids_by_group_names(template_groups)
link_template_ids = None
if link_templates is not None:
link_template_ids = template.get_template_ids(link_templates)
clear_template_ids = None
if clear_templates is not None:
clear_template_ids = template.get_template_ids(clear_templates)
if template_macros is not None:
# Zabbix configuration.export does not differentiate python types (numbers are returned as strings)
for macroitem in template_macros:
for key in macroitem:
macroitem[key] = str(macroitem[key])
if not template_ids:
# Assume new templates are being added when no ID's were found
if template_content is not None:
template.import_template(template_content, template_type)
module.exit_json(changed=True, result="Template import successful")
else:
if group_ids is None:
module.fail_json(msg='template_groups are required when creating a new Zabbix template')
template.add_template(template_name, group_ids, link_template_ids, template_macros)
module.exit_json(changed=True, result="Successfully added template: %s" % template_name)
else:
changed = template.check_template_changed(template_ids, template_groups, link_templates, clear_templates,
template_macros, template_content, template_type)
if module.check_mode:
module.exit_json(changed=changed)
if changed:
if template_type is not None:
template.import_template(template_content, template_type)
else:
template.update_template(template_ids, group_ids, link_template_ids, clear_template_ids,
template_macros)
module.exit_json(changed=changed, result="Template successfully updated")
if __name__ == '__main__':
main()

View file

@ -1,273 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2019, sky-joker
# 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
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
module: zabbix_template_info
short_description: Gather information about Zabbix template
author:
- sky-joker (@sky-joker)
description:
- This module allows you to search for Zabbix template.
requirements:
- "python >= 2.6"
- "zabbix-api >= 0.5.4"
options:
template_name:
description:
- Name of the template in Zabbix.
required: true
type: str
format:
description:
- Format to use when dumping template.
choices: ['json', 'xml']
default: json
type: str
omit_date:
description:
- Removes the date field for the dumped template
required: false
type: bool
default: false
extends_documentation_fragment:
- community.general.zabbix
'''
EXAMPLES = '''
- name: Get Zabbix template as JSON
zabbix_template_info:
server_url: "http://zabbix.example.com/zabbix/"
login_user: admin
login_password: secret
template_name: Template
format: json
omit_date: yes
register: template_json
- name: Get Zabbix template as XML
zabbix_template_info:
server_url: "http://zabbix.example.com/zabbix/"
login_user: admin
login_password: secret
template_name: Template
format: xml
omit_date: no
register: template_json
'''
RETURN = '''
---
template_json:
description: The JSON of the template
returned: when format is json and omit_date is true
type: str
sample: {
"zabbix_export": {
"version": "4.0",
"groups": [
{
"name": "Templates"
}
],
"templates": [
{
"template": "Test Template",
"name": "Template for Testing",
"description": "Testing template import",
"groups": [
{
"name": "Templates"
}
],
"applications": [
{
"name": "Test Application"
}
],
"items": [],
"discovery_rules": [],
"httptests": [],
"macros": [],
"templates": [],
"screens": []
}
]
}
}
template_xml:
description: The XML of the template
returned: when format is xml and omit_date is false
type: str
sample: >-
<zabbix_export>
<version>4.0</version>
<date>2019-10-27T14:49:57Z</date>
<groups>
<group>
<name>Templates</name>
</group>
</groups>
<templates>
<template>
<template>Test Template</template>
<name>Template for Testing</name>
<description>Testing template import</description>
<groups>
<group>
<name>Templates</name>
</group>
</groups>
<applications>
<application>
<name>Test Application</name>
</application>
</applications>
<items />
<discovery_rules />
<httptests />
<macros />
<templates />
<screens />
</template>
</templates>
</zabbix_export>
'''
import atexit
import traceback
import json
import xml.etree.ElementTree as ET
try:
from zabbix_api import ZabbixAPI
from zabbix_api import Already_Exists
from zabbix_api import ZabbixAPIException
HAS_ZABBIX_API = True
except ImportError:
ZBX_IMP_ERR = traceback.format_exc()
HAS_ZABBIX_API = False
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from ansible.module_utils._text import to_native
class TemplateInfo(object):
def __init__(self, module, zbx):
self._module = module
self._zapi = zbx
def get_template_id(self, template_name):
template_id = []
try:
template_list = self._zapi.template.get(
{
'output': 'extend',
'filter': {
'host': template_name
}
}
)
except ZabbixAPIException as e:
self._module.fail_json(msg='Failed to get template: %s' % e)
if template_list:
template_id.append(template_list[0]['templateid'])
return template_id
def load_json_template(self, template_json, omit_date=False):
try:
jsondoc = json.loads(template_json)
# remove date field if requested
if omit_date and 'date' in jsondoc['zabbix_export']:
del jsondoc['zabbix_export']['date']
return jsondoc
except ValueError as e:
self._module.fail_json(msg='Invalid JSON provided', details=to_native(e), exception=traceback.format_exc())
def dump_template(self, template_id, template_type='json', omit_date=False):
try:
dump = self._zapi.configuration.export({'format': template_type, 'options': {'templates': template_id}})
if template_type == 'xml':
xmlroot = ET.fromstring(dump.encode('utf-8'))
# remove date field if requested
if omit_date:
date = xmlroot.find(".date")
if date is not None:
xmlroot.remove(date)
return str(ET.tostring(xmlroot, encoding='utf-8').decode('utf-8'))
else:
return self.load_json_template(dump, omit_date)
except ZabbixAPIException as e:
self._module.fail_json(msg='Unable to export template: %s' % e)
def main():
module = AnsibleModule(
argument_spec=dict(
server_url=dict(type='str', required=True, aliases=['url']),
login_user=dict(type='str', required=True),
login_password=dict(type='str', required=True, no_log=True),
http_login_user=dict(type='str', required=False, default=None),
http_login_password=dict(type='str', required=False, default=None, no_log=True),
validate_certs=dict(type='bool', required=False, default=True),
timeout=dict(type='int', default=10),
template_name=dict(type='str', required=True),
omit_date=dict(type='bool', required=False, default=False),
format=dict(type='str', choices=['json', 'xml'], default='json')
),
supports_check_mode=False
)
if not HAS_ZABBIX_API:
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'),
exception=ZBX_IMP_ERR)
server_url = module.params['server_url']
login_user = module.params['login_user']
login_password = module.params['login_password']
http_login_user = module.params['http_login_user']
http_login_password = module.params['http_login_password']
validate_certs = module.params['validate_certs']
timeout = module.params['timeout']
template_name = module.params['template_name']
omit_date = module.params['omit_date']
format = module.params['format']
try:
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
validate_certs=validate_certs)
zbx.login(login_user, login_password)
atexit.register(zbx.logout)
except Exception as e:
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
template_info = TemplateInfo(module, zbx)
template_id = template_info.get_template_id(template_name)
if not template_id:
module.fail_json(msg='Template not found: %s' % template_name)
if format == 'json':
module.exit_json(changed=False, template_json=template_info.dump_template(template_id, template_type='json', omit_date=omit_date))
elif format == 'xml':
module.exit_json(changed=False, template_xml=template_info.dump_template(template_id, template_type='xml', omit_date=omit_date))
if __name__ == "__main__":
main()

View file

@ -1,663 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2019, sky-joker
# 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
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = r'''
module: zabbix_user
short_description: Create/update/delete Zabbix users
author:
- sky-joker (@sky-joker)
description:
- This module allows you to create, modify and delete Zabbix users.
requirements:
- "python >= 2.6"
- "zabbix-api >= 0.5.4"
options:
alias:
description:
- Name of the user alias in Zabbix.
- alias is the unique identifier used and cannot be updated using this module.
required: true
type: str
name:
description:
- Name of the user.
default: ''
type: str
surname:
description:
- Surname of the user.
default: ''
type: str
usrgrps:
description:
- User groups to add the user to.
required: true
type: list
elements: str
passwd:
description:
- User's password.
required: true
type: str
override_passwd:
description:
- Override password.
default: no
type: bool
lang:
description:
- Language code of the user's language.
default: 'en_GB'
choices:
- 'en_GB'
- 'en_US'
- 'zh_CN'
- 'cs_CZ'
- 'fr_FR'
- 'he_IL'
- 'it_IT'
- 'ko_KR'
- 'ja_JP'
- 'nb_NO'
- 'pl_PL'
- 'pt_BR'
- 'pt_PT'
- 'ru_RU'
- 'sk_SK'
- 'tr_TR'
- 'uk_UA'
type: str
theme:
description:
- User's theme.
default: 'default'
choices:
- 'default'
- 'blue-theme'
- 'dark-theme'
type: str
autologin:
description:
- Whether to enable auto-login.
- If enable autologin, cannot enable autologout.
default: false
type: bool
autologout:
description:
- User session life time in seconds. If set to 0, the session will never expire.
- If enable autologout, cannot enable autologin.
default: '0'
type: str
refresh:
description:
- Automatic refresh period in seconds.
default: '30'
type: str
rows_per_page:
description:
- Amount of object rows to show per page.
default: '50'
type: str
after_login_url:
description:
- URL of the page to redirect the user to after logging in.
default: ''
type: str
user_medias:
description:
- Set the user's media.
default: []
suboptions:
mediatype:
description:
- Media type name to set.
default: 'Email'
type: str
sendto:
description:
- Address, user name or other identifier of the recipient.
required: true
type: str
period:
description:
- Time when the notifications can be sent as a time period or user macros separated by a semicolon.
- Please review the documentation for more information on the supported time period.
- https://www.zabbix.com/documentation/4.0/manual/appendix/time_period
default: '1-7,00:00-24:00'
type: str
severity:
description:
- Trigger severities to send notifications about.
suboptions:
not_classified:
description:
- severity not_classified enable/disable.
default: True
type: bool
information:
description:
- severity information enable/disable.
default: True
type: bool
warning:
description:
- severity warning enable/disable.
default: True
type: bool
average:
description:
- severity average enable/disable.
default: True
type: bool
high:
description:
- severity high enable/disable.
default: True
type: bool
disaster:
description:
- severity disaster enable/disable.
default: True
type: bool
default:
not_classified: True
information: True
warning: True
average: True
high: True
disaster: True
type: dict
active:
description:
- Whether the media is enabled.
default: true
type: bool
type: list
elements: dict
type:
description:
- Type of the user.
default: 'Zabbix user'
choices:
- 'Zabbix user'
- 'Zabbix admin'
- 'Zabbix super admin'
type: str
state:
description:
- State of the user.
- On C(present), it will create if user does not exist or update the user if the associated data is different.
- On C(absent) will remove a user if it exists.
default: 'present'
choices: ['present', 'absent']
type: str
extends_documentation_fragment:
- community.general.zabbix
'''
EXAMPLES = r'''
- name: create of zabbix user.
zabbix_user:
server_url: "http://zabbix.example.com/zabbix/"
login_user: Admin
login_password: secret
alias: example
name: user name
surname: user surname
usrgrps:
- Guests
- Disabled
passwd: password
lang: en_GB
theme: blue-theme
autologin: no
autologout: '0'
refresh: '30'
rows_per_page: '200'
after_login_url: ''
user_medias:
- mediatype: Email
sendto: example@example.com
period: 1-7,00:00-24:00
severity:
not_classified: no
information: yes
warning: yes
average: yes
high: yes
disaster: yes
active: no
type: Zabbix super admin
state: present
- name: delete of zabbix user.
zabbix_user:
server_url: "http://zabbix.example.com/zabbix/"
login_user: admin
login_password: secret
alias: example
usrgrps:
- Guests
passwd: password
user_medias:
- sendto: example@example.com
state: absent
'''
RETURN = r'''
user_ids:
description: User id created or changed
returned: success
type: dict
sample: { "userids": [ "5" ] }
'''
import atexit
import traceback
try:
from zabbix_api import ZabbixAPI
from zabbix_api import Already_Exists
HAS_ZABBIX_API = True
except ImportError:
ZBX_IMP_ERR = traceback.format_exc()
HAS_ZABBIX_API = False
from distutils.version import LooseVersion
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
import copy
class User(object):
def __init__(self, module, zbx):
self._module = module
self._zapi = zbx
self._zbx_api_version = zbx.api_version()[:3]
def get_usergroupid_by_user_group_name(self, usrgrps):
user_group_ids = []
for user_group_name in usrgrps:
user_group = self._zapi.usergroup.get({'output': 'extend', 'filter': {'name': user_group_name}})
if user_group:
user_group_ids.append({'usrgrpid': user_group[0]['usrgrpid']})
else:
self._module.fail_json(msg="User group not found: %s" % user_group_name)
return user_group_ids
def check_user_exist(self, alias):
zbx_user = self._zapi.user.get({'output': 'extend', 'filter': {'alias': alias},
'getAccess': True, 'selectMedias': 'extend',
'selectUsrgrps': 'extend'})
return zbx_user
def convert_user_medias_parameter_types(self, user_medias):
copy_user_medias = copy.deepcopy(user_medias)
for user_media in copy_user_medias:
media_types = self._zapi.mediatype.get({'output': 'extend'})
for media_type in media_types:
if LooseVersion(self._zbx_api_version) < LooseVersion('4.4'):
if media_type['description'] == user_media['mediatype']:
user_media['mediatypeid'] = media_type['mediatypeid']
break
else:
if media_type['name'] == user_media['mediatype']:
user_media['mediatypeid'] = media_type['mediatypeid']
break
if 'mediatypeid' not in user_media:
self._module.fail_json(msg="Media type not found: %s" % user_media['mediatype'])
else:
del user_media['mediatype']
severity_binary_number = ''
for severity_key in 'disaster', 'high', 'average', 'warning', 'information', 'not_classified':
if user_media['severity'][severity_key]:
severity_binary_number = severity_binary_number + '1'
else:
severity_binary_number = severity_binary_number + '0'
user_media['severity'] = str(int(severity_binary_number, 2))
if user_media['active']:
user_media['active'] = '0'
else:
user_media['active'] = '1'
return copy_user_medias
def user_parameter_difference_check(self, zbx_user, alias, name, surname, user_group_ids, passwd, lang, theme,
autologin, autologout, refresh, rows_per_page, url, user_medias, user_type,
override_passwd):
user_medias = self.convert_user_medias_parameter_types(user_medias)
# existing data
existing_data = copy.deepcopy(zbx_user[0])
usrgrpids = []
for usrgrp in existing_data['usrgrps']:
usrgrpids.append({'usrgrpid': usrgrp['usrgrpid']})
existing_data['usrgrps'] = sorted(usrgrpids, key=lambda x: x['usrgrpid'])
# Processing for zabbix 4.0 and above.
# In zabbix 4.0 and above, Email sendto is of type list.
# This module, one media supports only one Email sendto.
# Therefore following processing extract one Email from list.
if LooseVersion(self._zbx_api_version) >= LooseVersion('4.0'):
for media in existing_data['medias']:
if isinstance(media['sendto'], list):
media['sendto'] = media['sendto'][0]
existing_data['user_medias'] = sorted(existing_data['medias'], key=lambda x: x['sendto'])
for del_key in ['medias', 'attempt_clock', 'attempt_failed', 'attempt_ip', 'debug_mode', 'users_status',
'gui_access']:
del existing_data[del_key]
for user_media in existing_data['user_medias']:
for del_key in ['mediaid', 'userid']:
del user_media[del_key]
# request data
request_data = {
'userid': zbx_user[0]['userid'],
'alias': alias,
'name': name,
'surname': surname,
'usrgrps': sorted(user_group_ids, key=lambda x: x['usrgrpid']),
'lang': lang,
'theme': theme,
'autologin': autologin,
'autologout': autologout,
'refresh': refresh,
'rows_per_page': rows_per_page,
'url': url,
'user_medias': sorted(user_medias, key=lambda x: x['sendto']),
'type': user_type
}
if override_passwd:
request_data['passwd'] = passwd
user_parameter_difference_check_result = True
if existing_data == request_data:
user_parameter_difference_check_result = False
diff_params = {
"before": existing_data,
"after": request_data
}
return user_parameter_difference_check_result, diff_params
def add_user(self, alias, name, surname, user_group_ids, passwd, lang, theme, autologin, autologout, refresh,
rows_per_page, url, user_medias, user_type):
user_medias = self.convert_user_medias_parameter_types(user_medias)
user_ids = {}
request_data = {
'alias': alias,
'name': name,
'surname': surname,
'usrgrps': user_group_ids,
'passwd': passwd,
'lang': lang,
'theme': theme,
'autologin': autologin,
'autologout': autologout,
'refresh': refresh,
'rows_per_page': rows_per_page,
'url': url,
'user_medias': user_medias,
'type': user_type
}
diff_params = {}
if not self._module.check_mode:
try:
user_ids = self._zapi.user.create(request_data)
except Exception as e:
self._module.fail_json(msg="Failed to create user %s: %s" % (alias, e))
else:
diff_params = {
"before": "",
"after": request_data
}
return user_ids, diff_params
def update_user(self, zbx_user, alias, name, surname, user_group_ids, passwd, lang, theme, autologin, autologout,
refresh, rows_per_page, url, user_medias, user_type, override_passwd):
user_medias = self.convert_user_medias_parameter_types(user_medias)
user_ids = {}
request_data = {
'userid': zbx_user[0]['userid'],
'alias': alias,
'name': name,
'surname': surname,
'usrgrps': user_group_ids,
'lang': lang,
'theme': theme,
'autologin': autologin,
'autologout': autologout,
'refresh': refresh,
'rows_per_page': rows_per_page,
'url': url,
'type': user_type
}
if override_passwd:
request_data['passwd'] = passwd
# In the case of zabbix 3.2 or less, it is necessary to use updatemedia method to update media.
if LooseVersion(self._zbx_api_version) <= LooseVersion('3.2'):
try:
user_ids = self._zapi.user.update(request_data)
except Exception as e:
self._module.fail_json(msg="Failed to update user %s: %s" % (alias, e))
try:
user_ids = self._zapi.user.updatemedia({
'users': [{'userid': zbx_user[0]['userid']}],
'medias': user_medias
})
except Exception as e:
self._module.fail_json(msg="Failed to update user medias %s: %s" % (alias, e))
if LooseVersion(self._zbx_api_version) >= LooseVersion('3.4'):
try:
request_data['user_medias'] = user_medias
user_ids = self._zapi.user.update(request_data)
except Exception as e:
self._module.fail_json(msg="Failed to update user %s: %s" % (alias, e))
return user_ids
def delete_user(self, zbx_user, alias):
user_ids = {}
diff_params = {}
if not self._module.check_mode:
try:
user_ids = self._zapi.user.delete([zbx_user[0]['userid']])
except Exception as e:
self._module.fail_json(msg="Failed to delete user %s: %s" % (alias, e))
else:
diff_params = {
"before": zbx_user[0],
"after": ""
}
return user_ids, diff_params
def main():
module = AnsibleModule(
argument_spec=dict(
server_url=dict(type='str', required=True, aliases=['url']),
login_user=dict(type='str', required=True),
login_password=dict(type='str', required=True, no_log=True),
http_login_user=dict(type='str', required=False, default=None),
http_login_password=dict(type='str', required=False, default=None, no_log=True),
validate_certs=dict(type='bool', required=False, default=True),
alias=dict(type='str', required=True),
name=dict(type='str', default=''),
surname=dict(type='str', default=''),
usrgrps=dict(type='list', required=True),
passwd=dict(type='str', required=True, no_log=True),
override_passwd=dict(type='bool', required=False, default=False),
lang=dict(type='str', default='en_GB', choices=['en_GB', 'en_US', 'zh_CN', 'cs_CZ', 'fr_FR',
'he_IL', 'it_IT', 'ko_KR', 'ja_JP', 'nb_NO',
'pl_PL', 'pt_BR', 'pt_PT', 'ru_RU', 'sk_SK',
'tr_TR', 'uk_UA']),
theme=dict(type='str', default='default', choices=['default', 'blue-theme', 'dark-theme']),
autologin=dict(type='bool', default=False),
autologout=dict(type='str', default='0'),
refresh=dict(type='str', default='30'),
rows_per_page=dict(type='str', default='50'),
after_login_url=dict(type='str', default=''),
user_medias=dict(type='list', default=[],
elements='dict',
options=dict(
mediatype=dict(type='str', default='Email'),
sendto=dict(type='str', required=True),
period=dict(type='str', default='1-7,00:00-24:00'),
severity=dict(type='dict',
options=dict(
not_classified=dict(type='bool', default=True),
information=dict(type='bool', default=True),
warning=dict(type='bool', default=True),
average=dict(type='bool', default=True),
high=dict(type='bool', default=True),
disaster=dict(type='bool', default=True)),
default=dict(
not_classified=True,
information=True,
warning=True,
average=True,
high=True,
disaster=True
)),
active=dict(type='bool', default=True)
)),
type=dict(type='str', default='Zabbix user', choices=['Zabbix user', 'Zabbix admin', 'Zabbix super admin']),
state=dict(type='str', default="present", choices=['present', 'absent']),
timeout=dict(type='int', default=10)
),
supports_check_mode=True
)
if not HAS_ZABBIX_API:
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'),
exception=ZBX_IMP_ERR)
server_url = module.params['server_url']
login_user = module.params['login_user']
login_password = module.params['login_password']
http_login_user = module.params['http_login_user']
http_login_password = module.params['http_login_password']
validate_certs = module.params['validate_certs']
alias = module.params['alias']
name = module.params['name']
surname = module.params['surname']
usrgrps = module.params['usrgrps']
passwd = module.params['passwd']
override_passwd = module.params['override_passwd']
lang = module.params['lang']
theme = module.params['theme']
autologin = module.params['autologin']
autologout = module.params['autologout']
refresh = module.params['refresh']
rows_per_page = module.params['rows_per_page']
after_login_url = module.params['after_login_url']
user_medias = module.params['user_medias']
user_type = module.params['type']
state = module.params['state']
timeout = module.params['timeout']
if autologin:
autologin = '1'
else:
autologin = '0'
user_type_dict = {
'Zabbix user': '1',
'Zabbix admin': '2',
'Zabbix super admin': '3'
}
user_type = user_type_dict[user_type]
zbx = None
# login to zabbix
try:
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
validate_certs=validate_certs)
zbx.login(login_user, login_password)
atexit.register(zbx.logout)
except Exception as e:
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
user = User(module, zbx)
user_ids = {}
zbx_user = user.check_user_exist(alias)
if state == 'present':
user_group_ids = user.get_usergroupid_by_user_group_name(usrgrps)
if zbx_user:
diff_check_result, diff_params = user.user_parameter_difference_check(zbx_user, alias, name, surname,
user_group_ids, passwd, lang, theme,
autologin, autologout, refresh,
rows_per_page, after_login_url,
user_medias, user_type,
override_passwd)
if not module.check_mode and diff_check_result:
user_ids = user.update_user(zbx_user, alias, name, surname, user_group_ids, passwd, lang,
theme, autologin, autologout, refresh, rows_per_page, after_login_url,
user_medias, user_type, override_passwd)
else:
diff_check_result = True
user_ids, diff_params = user.add_user(alias, name, surname, user_group_ids, passwd, lang, theme, autologin,
autologout, refresh, rows_per_page, after_login_url, user_medias,
user_type)
if state == 'absent':
if zbx_user:
diff_check_result = True
user_ids, diff_params = user.delete_user(zbx_user, alias)
else:
diff_check_result = False
diff_params = {}
if not module.check_mode:
if user_ids:
module.exit_json(changed=True, user_ids=user_ids)
else:
module.exit_json(changed=False)
else:
if diff_check_result:
module.exit_json(changed=True, diff=diff_params)
else:
module.exit_json(changed=False, diff=diff_params)
if __name__ == "__main__":
main()

View file

@ -1,175 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2019, sky-joker
# 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
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
module: zabbix_user_info
short_description: Gather information about Zabbix user
author:
- sky-joker (@sky-joker)
description:
- This module allows you to search for Zabbix user entries.
requirements:
- "python >= 2.6"
- "zabbix-api >= 0.5.4"
options:
alias:
description:
- Name of the user alias in Zabbix.
required: true
type: str
extends_documentation_fragment:
- community.general.zabbix
'''
EXAMPLES = '''
- name: Get zabbix user info
zabbix_user_info:
server_url: "http://zabbix.example.com/zabbix/"
login_user: admin
login_password: secret
alias: example
'''
RETURN = '''
zabbix_user:
description: example
returned: always
type: dict
sample: {
"alias": "example",
"attempt_clock": "0",
"attempt_failed": "0",
"attempt_ip": "",
"autologin": "0",
"autologout": "0",
"debug_mode": "0",
"gui_access": "0",
"lang": "en_GB",
"medias": [
{
"active": "0",
"mediaid": "668",
"mediatypeid": "1",
"period": "1-7,00:00-24:00",
"sendto": "example@example.com",
"severity": "63",
"userid": "660"
}
],
"name": "user",
"refresh": "30s",
"rows_per_page": "50",
"surname": "example",
"theme": "default",
"type": "1",
"url": "",
"userid": "660",
"users_status": "0",
"usrgrps": [
{
"debug_mode": "0",
"gui_access": "0",
"name": "Guests",
"users_status": "0",
"usrgrpid": "8"
}
]
}
'''
import atexit
import traceback
try:
from zabbix_api import ZabbixAPI
HAS_ZABBIX_API = True
except ImportError:
ZBX_IMP_ERR = traceback.format_exc()
HAS_ZABBIX_API = False
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
class User(object):
def __init__(self, module, zbx):
self._module = module
self._zapi = zbx
def get_user_by_user_alias(self, alias):
zabbix_user = ""
try:
zabbix_user = self._zapi.user.get({'output': 'extend', 'filter': {'alias': alias},
'getAccess': True, 'selectMedias': 'extend',
'selectUsrgrps': 'extend'})
except Exception as e:
self._zapi.logout()
self._module.fail_json(msg="Failed to get user information: %s" % e)
if not zabbix_user:
zabbix_user = {}
else:
zabbix_user = zabbix_user[0]
return zabbix_user
def main():
module = AnsibleModule(
argument_spec=dict(
server_url=dict(type='str', required=True, aliases=['url']),
login_user=dict(type='str', required=True),
login_password=dict(type='str', required=True, no_log=True),
http_login_user=dict(type='str', required=False, default=None),
http_login_password=dict(type='str', required=False, default=None, no_log=True),
validate_certs=dict(type='bool', required=False, default=True),
alias=dict(type='str', required=True),
timeout=dict(type='int', default=10)
),
supports_check_mode=True
)
if not HAS_ZABBIX_API:
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'),
exception=ZBX_IMP_ERR)
server_url = module.params['server_url']
login_user = module.params['login_user']
login_password = module.params['login_password']
http_login_user = module.params['http_login_user']
http_login_password = module.params['http_login_password']
validate_certs = module.params['validate_certs']
alias = module.params['alias']
timeout = module.params['timeout']
zbx = None
# login to zabbix
try:
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
validate_certs=validate_certs)
zbx.login(login_user, login_password)
atexit.register(zbx.logout)
except Exception as e:
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
user = User(module, zbx)
zabbix_user = user.get_user_by_user_alias(alias)
zbx.logout()
module.exit_json(changed=False, zabbix_user=zabbix_user)
if __name__ == "__main__":
main()

View file

@ -1,339 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2019, Ruben Tsirunyan <rubentsirunyan@gmail.com>
# 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
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = r'''
---
module: zabbix_valuemap
short_description: Create/update/delete Zabbix value maps
description:
- This module allows you to create, modify and delete Zabbix value maps.
author:
- "Ruben Tsirunyan (@rubentsirunyan)"
requirements:
- "zabbix-api >= 0.5.4"
options:
name:
type: 'str'
description:
- Name of the value map.
required: true
state:
type: 'str'
description:
- State of the value map.
- On C(present), it will create a value map if it does not exist or update the value map if the associated data is different.
- On C(absent), it will remove the value map if it exists.
choices: ['present', 'absent']
default: 'present'
mappings:
type: 'list'
elements: dict
description:
- List of value mappings for the value map.
- Required when I(state=present).
suboptions:
value:
type: 'str'
description: Original value.
required: true
map_to:
type: 'str'
description: Value to which the original value is mapped to.
required: true
extends_documentation_fragment:
- community.general.zabbix
'''
RETURN = r'''
'''
EXAMPLES = r'''
- name: Create a value map
local_action:
module: zabbix_valuemap
server_url: http://zabbix.example.com
login_user: username
login_password: password
name: Numbers
mappings:
- value: 1
map_to: one
- value: 2
map_to: two
state: present
'''
import atexit
import traceback
try:
from zabbix_api import ZabbixAPI
HAS_ZABBIX_API = True
except ImportError:
ZBX_IMP_ERR = traceback.format_exc()
HAS_ZABBIX_API = False
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
def construct_parameters(**kwargs):
"""Translates data to a format suitable for Zabbix API
Args:
**kwargs: Arguments passed to the module.
Returns:
A dictionary of arguments in a format that is understandable by Zabbix API.
"""
if kwargs['mappings'] is None:
return dict(
name=kwargs['name']
)
return dict(
name=kwargs['name'],
mappings=[
dict(
value=mapping['value'],
newvalue=mapping['map_to']
) for mapping in kwargs['mappings']
]
)
def check_if_valuemap_exists(module, zbx, name):
"""Checks if value map exists.
Args:
module: AnsibleModule object
zbx: ZabbixAPI object
name: Zabbix valuemap name
Returns:
tuple: First element is True if valuemap exists and False otherwise.
Second element is a dictionary of valuemap object if it exists.
"""
try:
valuemap_list = zbx.valuemap.get({
'output': 'extend',
'selectMappings': 'extend',
'filter': {'name': [name]}
})
if len(valuemap_list) < 1:
return False, None
else:
return True, valuemap_list[0]
except Exception as e:
module.fail_json(msg="Failed to get ID of the valuemap '{name}': {e}".format(name=name, e=e))
def diff(existing, new):
"""Constructs the diff for Ansible's --diff option.
Args:
existing (dict): Existing valuemap data.
new (dict): New valuemap data.
Returns:
A dictionary like {'before': existing, 'after': new}
with filtered empty values.
"""
before = {}
after = {}
for key in new:
before[key] = existing[key]
if new[key] is None:
after[key] = ''
else:
after[key] = new[key]
return {'before': before, 'after': after}
def get_update_params(module, zbx, existing_valuemap, **kwargs):
"""Filters only the parameters that are different and need to be updated.
Args:
module: AnsibleModule object.
zbx: ZabbixAPI object.
existing_valuemap (dict): Existing valuemap.
**kwargs: Parameters for the new valuemap.
Returns:
A tuple where the first element is a dictionary of parameters
that need to be updated and the second one is a dictionary
returned by diff() function with
existing valuemap data and new params passed to it.
"""
params_to_update = {}
if sorted(existing_valuemap['mappings'], key=lambda k: k['value']) != sorted(kwargs['mappings'], key=lambda k: k['value']):
params_to_update['mappings'] = kwargs['mappings']
return params_to_update, diff(existing_valuemap, kwargs)
def delete_valuemap(module, zbx, valuemap_id):
try:
return zbx.valuemap.delete([valuemap_id])
except Exception as e:
module.fail_json(msg="Failed to delete valuemap '{_id}': {e}".format(_id=valuemap_id, e=e))
def update_valuemap(module, zbx, **kwargs):
try:
valuemap_id = zbx.valuemap.update(kwargs)
except Exception as e:
module.fail_json(msg="Failed to update valuemap '{_id}': {e}".format(_id=kwargs['valuemapid'], e=e))
def create_valuemap(module, zbx, **kwargs):
try:
valuemap_id = zbx.valuemap.create(kwargs)
except Exception as e:
module.fail_json(msg="Failed to create valuemap '{name}': {e}".format(name=kwargs['description'], e=e))
def main():
module = AnsibleModule(
argument_spec=dict(
server_url=dict(type='str', required=True, aliases=['url']),
login_user=dict(type='str', required=True),
login_password=dict(type='str', required=True, no_log=True),
http_login_user=dict(type='str', required=False, default=None),
http_login_password=dict(type='str', required=False, default=None, no_log=True),
validate_certs=dict(type='bool', required=False, default=True),
name=dict(type='str', required=True),
state=dict(type='str', default='present', choices=['present', 'absent']),
mappings=dict(
type='list',
elements='dict',
options=dict(
value=dict(type='str', required=True),
map_to=dict(type='str', required=True)
)
),
timeout=dict(type='int', default=10)
),
supports_check_mode=True,
required_if=[
['state', 'present', ['mappings']],
]
)
if not HAS_ZABBIX_API:
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
server_url = module.params['server_url']
login_user = module.params['login_user']
login_password = module.params['login_password']
http_login_user = module.params['http_login_user']
http_login_password = module.params['http_login_password']
validate_certs = module.params['validate_certs']
name = module.params['name']
state = module.params['state']
mappings = module.params['mappings']
timeout = module.params['timeout']
zbx = None
# login to zabbix
try:
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
validate_certs=validate_certs)
zbx.login(login_user, login_password)
atexit.register(zbx.logout)
except Exception as e:
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
valuemap_exists, valuemap_object = check_if_valuemap_exists(module, zbx, name)
parameters = construct_parameters(
name=name,
mappings=mappings
)
if valuemap_exists:
valuemap_id = valuemap_object['valuemapid']
if state == 'absent':
if module.check_mode:
module.exit_json(
changed=True,
msg="Value map would have been deleted. Name: {name}, ID: {_id}".format(
name=name,
_id=valuemap_id
)
)
valuemap_id = delete_valuemap(module, zbx, valuemap_id)
module.exit_json(
changed=True,
msg="Value map deleted. Name: {name}, ID: {_id}".format(
name=name,
_id=valuemap_id
)
)
else:
params_to_update, diff = get_update_params(module, zbx, valuemap_object, **parameters)
if params_to_update == {}:
module.exit_json(
changed=False,
msg="Value map is up to date: {name}".format(name=name)
)
else:
if module.check_mode:
module.exit_json(
changed=True,
diff=diff,
msg="Value map would have been updated. Name: {name}, ID: {_id}".format(
name=name,
_id=valuemap_id
)
)
valuemap_id = update_valuemap(
module, zbx,
valuemapid=valuemap_id,
**params_to_update
)
module.exit_json(
changed=True,
diff=diff,
msg="Value map updated. Name: {name}, ID: {_id}".format(
name=name,
_id=valuemap_id
)
)
else:
if state == "absent":
module.exit_json(changed=False)
else:
if module.check_mode:
module.exit_json(
changed=True,
msg="Value map would have been created. Name: {name}, ID: {_id}".format(
name=name,
_id=valuemap_id
)
)
valuemap_id = create_valuemap(module, zbx, **parameters)
module.exit_json(
changed=True,
msg="Value map created: {name}, ID: {_id}".format(
name=name,
_id=valuemap_id
)
)
if __name__ == '__main__':
main()

View file

@ -1,20 +0,0 @@
# Ansible Zabbix external inventory script settings
#
[zabbix]
# Server location
server = http://zabbix.example.com/zabbix
# Login
username = admin
password = zabbix
# Verify the server's SSL certificate
validate_certs = True
# Read zabbix inventory per host
read_host_inventory = True
# Set ansible_ssh_host based on first interface settings
use_host_interface = True

View file

@ -1,196 +0,0 @@
#!/usr/bin/env python
# (c) 2013, Greg Buehler
# (c) 2018, Filippo Ferrazini
#
# This file is part of Ansible,
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
######################################################################
"""
Zabbix Server external inventory script.
========================================
Returns hosts and hostgroups from Zabbix Server.
If you want to run with --limit against a host group with space in the
name, use asterisk. For example --limit="Linux*servers".
Configuration is read from `zabbix.ini`.
Tested with Zabbix Server 2.0.6, 3.2.3 and 3.4.
"""
from __future__ import print_function
import os
import sys
import argparse
from ansible.module_utils.six.moves import configparser
try:
from zabbix_api import ZabbixAPI
except Exception:
print("Error: Zabbix API library must be installed: pip install zabbix-api.",
file=sys.stderr)
sys.exit(1)
import json
class ZabbixInventory(object):
def read_settings(self):
config = configparser.SafeConfigParser()
conf_path = './zabbix.ini'
if not os.path.exists(conf_path):
conf_path = os.path.dirname(os.path.realpath(__file__)) + '/zabbix.ini'
if os.path.exists(conf_path):
config.read(conf_path)
# server
if config.has_option('zabbix', 'server'):
self.zabbix_server = config.get('zabbix', 'server')
# login
if config.has_option('zabbix', 'username'):
self.zabbix_username = config.get('zabbix', 'username')
if config.has_option('zabbix', 'password'):
self.zabbix_password = config.get('zabbix', 'password')
# ssl certs
if config.has_option('zabbix', 'validate_certs'):
if config.get('zabbix', 'validate_certs') in ['false', 'False', False]:
self.validate_certs = False
# host inventory
if config.has_option('zabbix', 'read_host_inventory'):
if config.get('zabbix', 'read_host_inventory') in ['true', 'True', True]:
self.read_host_inventory = True
# host interface
if config.has_option('zabbix', 'use_host_interface'):
if config.get('zabbix', 'use_host_interface') in ['false', 'False', False]:
self.use_host_interface = False
def read_cli(self):
parser = argparse.ArgumentParser()
parser.add_argument('--host')
parser.add_argument('--list', action='store_true')
self.options = parser.parse_args()
def hoststub(self):
return {
'hosts': []
}
def get_host(self, api, name):
api_query = {'output': 'extend', 'selectGroups': 'extend', "filter": {"host": [name]}}
if self.use_host_interface:
api_query['selectInterfaces'] = ['useip', 'ip', 'dns']
if self.read_host_inventory:
api_query['selectInventory'] = "extend"
data = {'ansible_ssh_host': name}
if self.use_host_interface or self.read_host_inventory:
try:
hosts_data = api.host.get(api_query)[0]
if 'interfaces' in hosts_data:
# use first interface only
if hosts_data['interfaces'][0]['useip'] == 0:
data['ansible_ssh_host'] = hosts_data['interfaces'][0]['dns']
else:
data['ansible_ssh_host'] = hosts_data['interfaces'][0]['ip']
if ('inventory' in hosts_data) and (hosts_data['inventory']):
data.update(hosts_data['inventory'])
except IndexError:
# Host not found in zabbix
pass
return data
def get_list(self, api):
api_query = {'output': 'extend', 'selectGroups': 'extend'}
if self.use_host_interface:
api_query['selectInterfaces'] = ['useip', 'ip', 'dns']
if self.read_host_inventory:
api_query['selectInventory'] = "extend"
hosts_data = api.host.get(api_query)
data = {'_meta': {'hostvars': {}}}
data[self.defaultgroup] = self.hoststub()
for host in hosts_data:
hostname = host['name']
hostvars = dict()
data[self.defaultgroup]['hosts'].append(hostname)
for group in host['groups']:
groupname = group['name']
if groupname not in data:
data[groupname] = self.hoststub()
data[groupname]['hosts'].append(hostname)
if 'interfaces' in host:
# use first interface only
if host['interfaces'][0]['useip'] == 0:
hostvars['ansible_ssh_host'] = host['interfaces'][0]['dns']
else:
hostvars['ansible_ssh_host'] = host['interfaces'][0]['ip']
if ('inventory' in host) and (host['inventory']):
hostvars.update(host['inventory'])
data['_meta']['hostvars'][hostname] = hostvars
return data
def __init__(self):
self.defaultgroup = 'group_all'
self.zabbix_server = None
self.zabbix_username = None
self.zabbix_password = None
self.validate_certs = True
self.read_host_inventory = False
self.use_host_interface = True
self.meta = {}
self.read_settings()
self.read_cli()
if self.zabbix_server and self.zabbix_username:
try:
api = ZabbixAPI(server=self.zabbix_server, validate_certs=self.validate_certs)
api.login(user=self.zabbix_username, password=self.zabbix_password)
# zabbix_api tries to exit if it cannot parse what the zabbix server returned
# so we have to use SystemExit here
except (Exception, SystemExit) as e:
print("Error: Could not login to Zabbix server. Check your zabbix.ini.", file=sys.stderr)
sys.exit(1)
if self.options.host:
data = self.get_host(api, self.options.host)
print(json.dumps(data, indent=2))
elif self.options.list:
data = self.get_list(api)
print(json.dumps(data, indent=2))
else:
print("usage: --list ..OR.. --host <hostname>", file=sys.stderr)
sys.exit(1)
else:
print("Error: Configuration of server and credentials are required. See zabbix.ini.", file=sys.stderr)
sys.exit(1)
ZabbixInventory()

View file

@ -1,5 +0,0 @@
destructive
shippable/posix/group1
skip/osx
skip/freebsd
skip/rhel

View file

@ -1,13 +0,0 @@
---
db_name: 'zabbix'
db_user: 'zabbix'
db_password: 'fLhijUs3PgekNhwJ'
zabbix_version: 4.4
zabbix_apt_repository: 'deb http://repo.zabbix.com/zabbix/{{ zabbix_version }}/{{ ansible_distribution.lower() }}/ {{ ansible_distribution_release }} main'
zabbix_apt_repository_key: 'http://repo.zabbix.com/zabbix-official-repo.key'
zabbix_packages:
- zabbix-server-mysql
- zabbix-frontend-php
- zabbix-apache-conf

View file

@ -1,15 +0,0 @@
- name: remove zabbix repository
apt_repository:
repo: "{{ zabbix_apt_repository }}"
filename: zabbix
state: absent
- name: remove zabbix packages
apt:
name: "{{ zabbix_packages }}"
state: absent
- name: remove zabbix pip packages
pip:
name: zabbix-api
state: absent

View file

@ -1,2 +0,0 @@
dependencies:
- setup_mysql_db

View file

@ -1,3 +0,0 @@
---
- include: setup.yml
when: ansible_os_family == 'Debian'

View file

@ -1,75 +0,0 @@
- name: install zabbix repository key
apt_key:
url: '{{ zabbix_apt_repository_key }}'
state: present
- name: install zabbix repository
apt_repository:
repo: '{{ zabbix_apt_repository }}'
filename: zabbix
state: present
notify: remove zabbix repository
- name: check if dpkg is set to exclude specific destinations
stat:
path: /etc/dpkg/dpkg.cfg.d/excludes
register: dpkg_excludes
- name: ensure documentation installations are allowed for zabbix
lineinfile:
path: /etc/dpkg/dpkg.cfg.d/excludes
regexp: ^path-include=/usr/share/doc/zabbix*$
line: path-include=/usr/share/doc/zabbix*
state: present
when: dpkg_excludes.stat.exists
- name: install zabbix apt dependencies
apt:
name: '{{ zabbix_packages }}'
state: latest
update_cache: true
notify: remove zabbix packages
- name: install zabbix-api python package
pip:
name: zabbix-api
state: latest
notify: remove zabbix pip packages
- name: create mysql user {{ db_user }}
mysql_user:
name: '{{ db_user }}'
password: '{{ db_password }}'
state: present
priv: '{{ db_name }}.*:ALL'
login_unix_socket: '{{ mysql_socket }}'
- name: import initial zabbix database
mysql_db:
name: '{{ db_name }}'
login_user: '{{ db_user }}'
login_password: '{{ db_password }}'
state: import
target: /usr/share/doc/zabbix-server-mysql/create.sql.gz
- name: deploy zabbix-server configuration
template:
src: zabbix_server.conf.j2
dest: /etc/zabbix/zabbix_server.conf
owner: root
group: zabbix
mode: '0640'
- name: deploy zabbix web frontend configuration
template:
src: zabbix.conf.php.j2
dest: /etc/zabbix/web/zabbix.conf.php
mode: '0644'
- name: Create proper run directory for zabbix-server
file:
path: /var/run/zabbix
state: directory
owner: zabbix
group: zabbix
mode: '0775'
- name: restart zabbix-server
service:
name: zabbix-server
state: restarted
enabled: true
- name: restart apache2
service:
name: apache2
state: restarted
enabled: true

View file

@ -1,20 +0,0 @@
<?php
// Zabbix GUI configuration file
global $DB;
$DB['TYPE'] = 'MYSQL';
$DB['SERVER'] = 'localhost';
$DB['PORT'] = '0';
$DB['DATABASE'] = '{{ db_name }}';
$DB['USER'] = '{{ db_user }}';
$DB['PASSWORD'] = '{{ db_password }}';
// SCHEMA is relevant only for IBM_DB2 database
$DB['SCHEMA'] = '';
$ZBX_SERVER = 'localhost';
$ZBX_SERVER_PORT = '10051';
$ZBX_SERVER_NAME = '';
$IMAGE_FORMAT_DEFAULT = IMAGE_FORMAT_PNG;
?>

View file

@ -1,7 +0,0 @@
PidFile=/var/run/zabbix/zabbix_server.pid
LogFile=/tmp/zabbix_server.log
DBName={{ db_name }}
DBUser={{ db_user }}
DBPassword={{ db_password }}
Timeout=4
LogSlowQueries=3000

View file

@ -1,6 +0,0 @@
destructive
shippable/posix/group1
skip/aix
skip/osx
skip/freebsd
skip/rhel

View file

@ -1,5 +0,0 @@
---
zabbix_server_url: http://127.0.0.1/zabbix/
zabbix_login_user: Admin
zabbix_login_password: zabbix

View file

@ -1,2 +0,0 @@
dependencies:
- setup_zabbix

View file

@ -1,16 +0,0 @@
---
# setup stuff not testing zabbix_host
- block:
- include: zabbix_host_setup.yml
# zabbix_host module tests
- include: zabbix_host_tests.yml
# documentation example tests
- include: zabbix_host_doc.yml
# tear down stuff set up earlier
- include: zabbix_host_teardown.yml
when:
- ansible_distribution == 'Ubuntu'

View file

@ -1,83 +0,0 @@
---
# These two tests are close to documentation example
- name: Create a new host or update an existing host's info
zabbix_host:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
host_name: ExampleHost1
visible_name: ExampleName
description: My ExampleHost Description
host_groups:
- Linux servers
- Zabbix servers
link_templates:
- Template App IMAP Service
- Template App NTP Service
status: enabled
state: present
inventory_mode: manual
inventory_zabbix:
tag: test-tag
alias: test-alias
notes: "Special Informations: test-info"
location: test-location
site_rack: test-rack
os: test-os
hardware: test-hw
ipmi_authtype: 2
ipmi_privilege: 4
ipmi_username: username
ipmi_password: password
interfaces:
- type: 1
main: 1
useip: 1
ip: 10.1.1.1
dns: ""
port: "10050"
- type: 4
main: 1
useip: 1
ip: 10.1.1.1
dns: ""
port: "12345"
macros:
- macro: '{$EXAMPLEMACRO}'
value: ExampleMacroValue
- macro: EXAMPLEMACRO2
value: ExampleMacroValue2
description: Example desc that work only with Zabbix 4.4 and higher
tags:
- tag: ExampleHostsTag
- tag: ExampleHostsTag2
value: ExampleTagValue
register: zabbix_host1
- name: Update an existing host's tls settings
zabbix_host:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
host_name: ExampleHost2
visible_name: ExampleName2
interfaces:
- type: 1
main: 1
useip: 1
ip: 10.1.1.2
dns: ""
port: "10050"
host_groups:
- Linux servers
tls_psk_identity: test
tls_connect: 2
tls_psk: 123456789abcdef123456789abcdef12
register: zabbix_host2
- name: expect both to succeed
assert:
that:
- "zabbix_host1 is changed"
- "zabbix_host2 is changed"

View file

@ -1,20 +0,0 @@
---
# set up a zabbix proxy to test zabbix_host with
- name: Create a new proxy
zabbix_proxy:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
proxy_name: ExampleProxy
description: ExampleProxy
status: active
state: present
interface:
type: 0
main: 1
useip: 1
ip: 10.5.6.7
dns: ""
port: 10050
register: zabbix_proxy

View file

@ -1,10 +0,0 @@
---
# remove zabbix_proxy (hopefully) created earlier
- name: remove proxy
zabbix_proxy:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
proxy_name: ExampleProxy
state: absent

View file

@ -1,6 +0,0 @@
destructive
shippable/posix/group1
skip/aix
skip/osx
skip/freebsd
skip/rhel

View file

@ -1,5 +0,0 @@
---
zabbix_server_url: http://127.0.0.1/zabbix/
zabbix_login_user: Admin
zabbix_login_password: zabbix

View file

@ -1,2 +0,0 @@
dependencies:
- setup_zabbix

View file

@ -1,159 +0,0 @@
---
- when:
- ansible_distribution == 'Ubuntu'
block:
- name: Create a new Zabbix template.
zabbix_template:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
template_name: ExampleHost
template_groups:
- 'Linux servers'
- 'Templates'
state: present
register: create_zabbix_template_result
- assert:
that:
- create_zabbix_template_result.changed is sameas true
- name: Gather Zabbix template infomation.
zabbix_template_info:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
template_name: ExampleHost
format: json
register: gather_template_result
- assert:
that:
- gather_template_result.template_json.zabbix_export.groups.0.name == 'Linux servers'
- gather_template_result.template_json.zabbix_export.groups.1.name == 'Templates'
- name: Add link_templates to Zabbix template.
zabbix_template:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
template_name: ExampleHost
template_groups:
- 'Linux servers'
- 'Templates'
link_templates:
- 'Template App Zabbix Proxy'
- 'Template Module Zabbix agent'
state: present
register: update_zabbix_template_result
- assert:
that:
- create_zabbix_template_result.changed is sameas true
- name: Gather Zabbix template infomation.
zabbix_template_info:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
template_name: ExampleHost
format: json
register: gather_template_result
- assert:
that:
- gather_template_result.template_json.zabbix_export.groups.0.name == 'Linux servers'
- gather_template_result.template_json.zabbix_export.groups.1.name == 'Templates'
- gather_template_result.template_json.zabbix_export.templates.0.templates.0.name == 'Template App Zabbix Proxy'
- gather_template_result.template_json.zabbix_export.templates.0.templates.1.name == 'Template Module Zabbix agent'
- name: Add macros to Zabbix template.
zabbix_template:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
template_name: ExampleHost
template_groups:
- 'Linux servers'
- 'Templates'
link_templates:
- 'Template App Zabbix Proxy'
- 'Template Module Zabbix agent'
macros:
- macro: '{$EXAMPLE_MACRO1}'
value: 1000
- macro: '{$EXAMPLE_MACRO2}'
value: 'text'
state: present
register: update_zabbix_template_result
- assert:
that:
- create_zabbix_template_result.changed is sameas true
- name: Gather Zabbix template infomation.
zabbix_template_info:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
template_name: ExampleHost
format: json
register: gather_template_result
- assert:
that:
- gather_template_result.template_json.zabbix_export.groups.0.name == 'Linux servers'
- gather_template_result.template_json.zabbix_export.groups.1.name == 'Templates'
- gather_template_result.template_json.zabbix_export.templates.0.templates.0.name == 'Template App Zabbix Proxy'
- gather_template_result.template_json.zabbix_export.templates.0.templates.1.name == 'Template Module Zabbix agent'
- gather_template_result.template_json.zabbix_export.templates.0.macros.0.macro == '{$EXAMPLE_MACRO1}'
- gather_template_result.template_json.zabbix_export.templates.0.macros.0.value == '1000'
- gather_template_result.template_json.zabbix_export.templates.0.macros.1.macro == '{$EXAMPLE_MACRO2}'
- gather_template_result.template_json.zabbix_export.templates.0.macros.1.value == 'text'
- name: Dump Zabbix template to XML format.
zabbix_template:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
template_name: ExampleHost
dump_format: xml
state: dump
register: template_dump_result
- debug: var=template_dump_result
- assert:
that:
- template_dump_result.deprecations is defined
- template_dump_result.deprecations.0.version == '2.14'
- name: Dump Zabbix template to JSON format.
zabbix_template:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
template_name: ExampleHost
dump_format: json
state: dump
register: template_dump_result
- debug: var=template_dump_result
- assert:
that:
- template_dump_result.deprecations is defined
- template_dump_result.deprecations.0.version == '2.14'
- name: Delete Zabbix template.
zabbix_template:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
template_name: ExampleHost
state: absent
register: delete_zabbix_template_result
- assert:
that:
- delete_zabbix_template_result.changed is sameas true

View file

@ -1,6 +0,0 @@
destructive
shippable/posix/group1
skip/osx
skip/freebsd
skip/rhel
skip/aix

View file

@ -1,5 +0,0 @@
---
zabbix_server_url: http://127.0.0.1/zabbix/
zabbix_login_user: Admin
zabbix_login_password: zabbix

View file

@ -1,2 +0,0 @@
dependencies:
- setup_zabbix

View file

@ -1,912 +0,0 @@
---
- when:
- ansible_distribution == 'Ubuntu'
block:
# New user create test from here
- name: test - Create a new Zabbix user with check_mode and diff
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example
surname: test
usrgrps:
- Guests
passwd: password
check_mode: yes
diff: yes
register: create_zabbix_user_result
- assert:
that:
- create_zabbix_user_result.changed is sameas true
- name: test - Create a new Zabbix user
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example
surname: test
usrgrps:
- Guests
passwd: password
register: create_zabbix_user_result
- assert:
that:
- create_zabbix_user_result.changed is sameas true
- name: test - Create a new Zabbix user(again)
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example
surname: test
usrgrps:
- Guests
passwd: password
register: create_zabbix_user_result
- assert:
that:
- not create_zabbix_user_result.changed is sameas true
# Parameter add test from here to existing user
- name: test - Add user group to existing user
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example
surname: test
usrgrps:
- Guests
- Zabbix administrators
passwd: password
register: add_usergroup_to_existing_user_result
- assert:
that:
- add_usergroup_to_existing_user_result.changed is sameas true
- name: test - Add user medias(Email) to existing user
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example
surname: test
usrgrps:
- Guests
- Zabbix administrators
passwd: password
user_medias:
- mediatype: Email
sendto: example@example.com
period: 1-7,00:00-24:00
severity:
not_classified: no
information: yes
warning: yes
average: yes
high: yes
disaster: yes
active: yes
register: add_user_medias_to_existing_user_result
- assert:
that:
- add_user_medias_to_existing_user_result.changed is sameas true
- name: test - Add multiple user medias(Email and SMS) to existing user
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example
surname: test
usrgrps:
- Guests
- Zabbix administrators
passwd: password
user_medias:
- mediatype: Email
sendto: example@example.com
period: 1-7,00:00-24:00
severity:
not_classified: no
information: yes
warning: yes
average: yes
high: yes
disaster: yes
active: yes
- mediatype: SMS
sendto: example@example.com
period: 1-5,01:00-23:00
severity:
not_classified: no
information: yes
warning: yes
average: no
high: yes
disaster: yes
active: yes
register: add_user_medias_to_existing_user_result
- assert:
that:
- add_user_medias_to_existing_user_result.changed is sameas true
# Existing parameter updates test from here
- name: test - Update password parameter for existing user
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example
surname: test
usrgrps:
- Guests
- Zabbix administrators
passwd: update_password
override_passwd: yes
user_medias:
- mediatype: Email
sendto: example@example.com
period: 1-7,00:00-24:00
severity:
not_classified: no
information: yes
warning: yes
average: yes
high: yes
disaster: yes
active: yes
- mediatype: SMS
sendto: example@example.com
period: 1-5,01:00-23:00
severity:
not_classified: no
information: yes
warning: yes
average: no
high: yes
disaster: yes
active: yes
register: update_password_parameter_existing_user_result
- assert:
that:
- update_password_parameter_existing_user_result.changed is sameas true
- name: test - Update autologin parameter for existing user
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example
surname: test
usrgrps:
- Guests
- Zabbix administrators
passwd: update_password
autologin: yes
user_medias:
- mediatype: Email
sendto: example@example.com
period: 1-7,00:00-24:00
severity:
not_classified: no
information: yes
warning: yes
average: yes
high: yes
disaster: yes
active: yes
- mediatype: SMS
sendto: example@example.com
period: 1-5,01:00-23:00
severity:
not_classified: no
information: yes
warning: yes
average: no
high: yes
disaster: yes
active: yes
register: update_autologin_parameter_existing_user_result
- assert:
that:
- update_autologin_parameter_existing_user_result.changed is sameas true
- name: test - Update autologout parameter for existing user
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example
surname: test
usrgrps:
- Guests
- Zabbix administrators
passwd: update_password
autologout: 500
user_medias:
- mediatype: Email
sendto: example@example.com
period: 1-7,00:00-24:00
severity:
not_classified: no
information: yes
warning: yes
average: yes
high: yes
disaster: yes
active: yes
- mediatype: SMS
sendto: example@example.com
period: 1-5,01:00-23:00
severity:
not_classified: no
information: yes
warning: yes
average: no
high: yes
disaster: yes
active: yes
register: update_autologout_parameter_existing_user_result
- assert:
that:
- update_autologout_parameter_existing_user_result.changed is sameas true
- name: test - Update refresh parameter for existing user
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example
surname: test
usrgrps:
- Guests
- Zabbix administrators
passwd: update_password
autologout: 500
refresh: 60
user_medias:
- mediatype: Email
sendto: example@example.com
period: 1-7,00:00-24:00
severity:
not_classified: no
information: yes
warning: yes
average: yes
high: yes
disaster: yes
active: yes
- mediatype: SMS
sendto: example@example.com
period: 1-5,01:00-23:00
severity:
not_classified: no
information: yes
warning: yes
average: no
high: yes
disaster: yes
active: yes
register: update_refresh_parameter_existing_user_result
- assert:
that:
- update_refresh_parameter_existing_user_result.changed is sameas true
- name: test - Update rows_per_page parameter for existing user
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example
surname: test
usrgrps:
- Guests
- Zabbix administrators
passwd: update_password
autologout: 500
refresh: 60
rows_per_page: 300
user_medias:
- mediatype: Email
sendto: example@example.com
period: 1-7,00:00-24:00
severity:
not_classified: no
information: yes
warning: yes
average: yes
high: yes
disaster: yes
active: yes
- mediatype: SMS
sendto: example@example.com
period: 1-5,01:00-23:00
severity:
not_classified: no
information: yes
warning: yes
average: no
high: yes
disaster: yes
active: yes
register: update_rows_per_page_parameter_existing_user_result
- assert:
that:
- update_rows_per_page_parameter_existing_user_result.changed is sameas true
- name: test - Update after_login_url parameter for existing user
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example
surname: test
usrgrps:
- Guests
- Zabbix administrators
passwd: update_password
autologout: 500
refresh: 60
rows_per_page: 300
after_login_url: http://example.com
user_medias:
- mediatype: Email
sendto: example@example.com
period: 1-7,00:00-24:00
severity:
not_classified: no
information: yes
warning: yes
average: yes
high: yes
disaster: yes
active: yes
- mediatype: SMS
sendto: example@example.com
period: 1-5,01:00-23:00
severity:
not_classified: no
information: yes
warning: yes
average: no
high: yes
disaster: yes
active: yes
register: update_after_login_url_parameter_existing_user_result
- assert:
that:
- update_after_login_url_parameter_existing_user_result.changed is sameas true
- name: test - Update theme parameter for existing user
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example
surname: test
usrgrps:
- Guests
- Zabbix administrators
passwd: update_password
autologout: 500
refresh: 60
rows_per_page: 300
after_login_url: http://example.com
theme: "{{ item }}"
user_medias:
- mediatype: Email
sendto: example@example.com
period: 1-7,00:00-24:00
severity:
not_classified: no
information: yes
warning: yes
average: yes
high: yes
disaster: yes
active: yes
- mediatype: SMS
sendto: example@example.com
period: 1-5,01:00-23:00
severity:
not_classified: no
information: yes
warning: yes
average: no
high: yes
disaster: yes
active: yes
loop:
- blue-theme
- dark-theme
register: update_theme_parameter_existing_user_result
- assert:
that:
- item.changed is sameas true
loop: "{{ update_theme_parameter_existing_user_result.results }}"
- name: test - Update type parameter for existing user
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example
surname: test
usrgrps:
- Guests
- Zabbix administrators
passwd: update_password
autologout: 500
refresh: 60
rows_per_page: 300
after_login_url: http://example.com
theme: dark-theme
type: "{{ item }}"
user_medias:
- mediatype: Email
sendto: example@example.com
period: 1-7,00:00-24:00
severity:
not_classified: no
information: yes
warning: yes
average: yes
high: yes
disaster: yes
active: yes
- mediatype: SMS
sendto: example@example.com
period: 1-5,01:00-23:00
severity:
not_classified: no
information: yes
warning: yes
average: no
high: yes
disaster: yes
active: yes
loop:
- Zabbix admin
- Zabbix super admin
register: update_type_parameter_existing_user_result
- assert:
that:
- item.changed is sameas true
loop: "{{ update_type_parameter_existing_user_result.results }}"
- name: test - Update lang parameter for existing user
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example
surname: test
usrgrps:
- Guests
- Zabbix administrators
passwd: update_password
autologout: 500
refresh: 60
rows_per_page: 300
after_login_url: http://example.com
theme: dark-theme
type: Zabbix super admin
lang: en_US
user_medias:
- mediatype: Email
sendto: example@example.com
period: 1-7,00:00-24:00
severity:
not_classified: no
information: yes
warning: yes
average: yes
high: yes
disaster: yes
active: yes
- mediatype: SMS
sendto: example@example.com
period: 1-5,01:00-23:00
severity:
not_classified: no
information: yes
warning: yes
average: no
high: yes
disaster: yes
active: yes
register: update_lang_parameter_existing_user_result
- assert:
that:
- update_lang_parameter_existing_user_result.changed is sameas true
- name: test - Update name and surname parameter for existing user
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example2
surname: test2
usrgrps:
- Guests
- Zabbix administrators
passwd: update_password
autologout: 500
refresh: 60
rows_per_page: 300
after_login_url: http://example.com
theme: dark-theme
type: Zabbix super admin
lang: en_US
user_medias:
- mediatype: Email
sendto: example@example.com
period: 1-7,00:00-24:00
severity:
not_classified: no
information: yes
warning: yes
average: yes
high: yes
disaster: yes
active: yes
- mediatype: SMS
sendto: example@example.com
period: 1-5,01:00-23:00
severity:
not_classified: no
information: yes
warning: yes
average: no
high: yes
disaster: yes
active: yes
register: update_name_and_surname_parameter_existing_user_result
- assert:
that:
- update_name_and_surname_parameter_existing_user_result.changed is sameas true
- name: test - Update lang parameter for existing user with check_mode and diff
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example2
surname: test2
usrgrps:
- Guests
- Zabbix administrators
passwd: update_password
autologout: 500
refresh: 60
rows_per_page: 300
after_login_url: http://example.com
theme: dark-theme
type: Zabbix super admin
lang: en_GB
user_medias:
- mediatype: Email
sendto: example@example.com
period: 1-7,00:00-24:00
severity:
not_classified: no
information: yes
warning: yes
average: yes
high: yes
disaster: yes
active: yes
- mediatype: SMS
sendto: example@example.com
period: 1-5,01:00-23:00
severity:
not_classified: no
information: yes
warning: yes
average: no
high: yes
disaster: yes
active: yes
check_mode: yes
diff: yes
register: update_lang_parameter_existing_user_with_check_mode_diff_result
- assert:
that:
- update_lang_parameter_existing_user_with_check_mode_diff_result.changed is sameas true
- name: test - Update lang parameter for existing user
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example2
surname: test2
usrgrps:
- Guests
- Zabbix administrators
passwd: update_password
autologout: 500
refresh: 60
rows_per_page: 300
after_login_url: http://example.com
theme: dark-theme
type: Zabbix super admin
lang: en_GB
user_medias:
- mediatype: Email
sendto: example@example.com
period: 1-7,00:00-24:00
severity:
not_classified: no
information: yes
warning: yes
average: yes
high: yes
disaster: yes
active: yes
- mediatype: SMS
sendto: example@example.com
period: 1-5,01:00-23:00
severity:
not_classified: no
information: yes
warning: yes
average: no
high: yes
disaster: yes
active: yes
register: update_lang_parameter_existing_user_result
- assert:
that:
- update_lang_parameter_existing_user_result.changed is sameas true
- name: test - Update lang parameter for existing user(again)
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example2
surname: test2
usrgrps:
- Guests
- Zabbix administrators
passwd: update_password
autologout: 500
refresh: 60
rows_per_page: 300
after_login_url: http://example.com
theme: dark-theme
type: Zabbix super admin
lang: en_GB
user_medias:
- mediatype: Email
sendto: example@example.com
period: 1-7,00:00-24:00
severity:
not_classified: no
information: yes
warning: yes
average: yes
high: yes
disaster: yes
active: yes
- mediatype: SMS
sendto: example@example.com
period: 1-5,01:00-23:00
severity:
not_classified: no
information: yes
warning: yes
average: no
high: yes
disaster: yes
active: yes
register: update_lang_parameter_existing_user_result
- assert:
that:
- not update_lang_parameter_existing_user_result.changed is sameas true
# Parameter delete test from here from existing user
- name: test - Delete user medias(SNS) for existing user with check_mode and diff
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example2
surname: test2
usrgrps:
- Guests
- Zabbix administrators
passwd: update_password
autologout: 500
refresh: 60
rows_per_page: 300
after_login_url: http://example.com
theme: dark-theme
type: Zabbix super admin
lang: en_GB
user_medias:
- mediatype: Email
sendto: example@example.com
period: 1-7,00:00-24:00
severity:
not_classified: no
information: yes
warning: yes
average: yes
high: yes
disaster: yes
active: yes
check_mode: yes
diff: yes
register: delete_user_medias_existing_user_result
- assert:
that:
- delete_user_medias_existing_user_result.changed is sameas true
- name: test - Delete user medias(SNS) for existing user
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example2
surname: test2
usrgrps:
- Guests
- Zabbix administrators
passwd: update_password
autologout: 500
refresh: 60
rows_per_page: 300
after_login_url: http://example.com
theme: dark-theme
type: Zabbix super admin
lang: en_GB
user_medias:
- mediatype: Email
sendto: example@example.com
period: 1-7,00:00-24:00
severity:
not_classified: no
information: yes
warning: yes
average: yes
high: yes
disaster: yes
active: yes
register: delete_user_medias_existing_user_result
- assert:
that:
- delete_user_medias_existing_user_result.changed is sameas true
- name: test - Delete user group for existing user
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
name: example2
surname: test2
usrgrps:
- Zabbix administrators
passwd: update_password
autologout: 500
refresh: 60
rows_per_page: 300
after_login_url: http://example.com
theme: dark-theme
type: Zabbix super admin
lang: en_GB
user_medias:
- mediatype: Email
sendto: example@example.com
period: 1-7,00:00-24:00
severity:
not_classified: no
information: yes
warning: yes
average: yes
high: yes
disaster: yes
active: yes
register: delete_user_group_existing_user_result
- assert:
that:
- delete_user_group_existing_user_result.changed is sameas true
- name: test - Delete existing user with check_mode and diff
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
usrgrps:
- Zabbix administrators
passwd: update_password
state: absent
check_mode: yes
diff: yes
register: delete_existing_user_result
- assert:
that:
- delete_existing_user_result.changed is sameas true
- name: test - Delete existing user
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
usrgrps:
- Zabbix administrators
passwd: update_password
state: absent
register: delete_existing_user_result
- assert:
that:
- delete_existing_user_result.changed is sameas true
- name: test - Delete existing user(again)
zabbix_user:
server_url: "{{ zabbix_server_url }}"
login_user: "{{ zabbix_login_user }}"
login_password: "{{ zabbix_login_password }}"
alias: example1
usrgrps:
- Zabbix administrators
passwd: update_password
state: absent
register: delete_existing_user_result
- assert:
that:
- not delete_existing_user_result.changed is sameas true

View file

@ -85,8 +85,6 @@ scripts/inventory/vagrant.py future-import-boilerplate
scripts/inventory/vagrant.py metaclass-boilerplate scripts/inventory/vagrant.py metaclass-boilerplate
scripts/inventory/vbox.py future-import-boilerplate scripts/inventory/vbox.py future-import-boilerplate
scripts/inventory/vbox.py metaclass-boilerplate scripts/inventory/vbox.py metaclass-boilerplate
scripts/inventory/zabbix.py future-import-boilerplate
scripts/inventory/zabbix.py metaclass-boilerplate
scripts/inventory/zone.py future-import-boilerplate scripts/inventory/zone.py future-import-boilerplate
scripts/inventory/zone.py metaclass-boilerplate scripts/inventory/zone.py metaclass-boilerplate
scripts/vault/azure_vault.py future-import-boilerplate scripts/vault/azure_vault.py future-import-boilerplate
@ -1106,32 +1104,6 @@ plugins/modules/monitoring/statusio_maintenance.py validate-modules:doc-missing-
plugins/modules/monitoring/statusio_maintenance.py validate-modules:parameter-list-no-elements plugins/modules/monitoring/statusio_maintenance.py validate-modules:parameter-list-no-elements
plugins/modules/monitoring/statusio_maintenance.py validate-modules:parameter-type-not-in-doc plugins/modules/monitoring/statusio_maintenance.py validate-modules:parameter-type-not-in-doc
plugins/modules/monitoring/uptimerobot.py validate-modules:doc-missing-type plugins/modules/monitoring/uptimerobot.py validate-modules:doc-missing-type
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:doc-choices-do-not-match-spec
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:doc-default-does-not-match-spec
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:doc-elements-mismatch
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:doc-required-mismatch
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:invalid-argument-name
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:missing-suboption-docs
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:nonexistent-parameter-documented
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:parameter-list-no-elements
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:parameter-type-not-in-doc
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:undocumented-parameter
plugins/modules/monitoring/zabbix/zabbix_group.py validate-modules:doc-elements-mismatch
plugins/modules/monitoring/zabbix/zabbix_group.py validate-modules:parameter-list-no-elements
plugins/modules/monitoring/zabbix/zabbix_group_info.py validate-modules:doc-elements-mismatch
plugins/modules/monitoring/zabbix/zabbix_group_info.py validate-modules:parameter-list-no-elements
plugins/modules/monitoring/zabbix/zabbix_host.py validate-modules:doc-elements-mismatch
plugins/modules/monitoring/zabbix/zabbix_host.py validate-modules:parameter-list-no-elements
plugins/modules/monitoring/zabbix/zabbix_host_info.py validate-modules:doc-elements-mismatch
plugins/modules/monitoring/zabbix/zabbix_host_info.py validate-modules:parameter-list-no-elements
plugins/modules/monitoring/zabbix/zabbix_maintenance.py validate-modules:doc-elements-mismatch
plugins/modules/monitoring/zabbix/zabbix_maintenance.py validate-modules:parameter-list-no-elements
plugins/modules/monitoring/zabbix/zabbix_mediatype.py validate-modules:doc-elements-mismatch
plugins/modules/monitoring/zabbix/zabbix_mediatype.py validate-modules:parameter-list-no-elements
plugins/modules/monitoring/zabbix/zabbix_template.py validate-modules:doc-elements-mismatch
plugins/modules/monitoring/zabbix/zabbix_template.py validate-modules:parameter-list-no-elements
plugins/modules/monitoring/zabbix/zabbix_user.py validate-modules:doc-elements-mismatch
plugins/modules/monitoring/zabbix/zabbix_user.py validate-modules:parameter-list-no-elements
plugins/modules/net_tools/cloudflare_dns.py validate-modules:parameter-type-not-in-doc plugins/modules/net_tools/cloudflare_dns.py validate-modules:parameter-type-not-in-doc
plugins/modules/net_tools/dnsimple.py validate-modules:parameter-list-no-elements plugins/modules/net_tools/dnsimple.py validate-modules:parameter-list-no-elements
plugins/modules/net_tools/dnsmadeeasy.py validate-modules:doc-missing-type plugins/modules/net_tools/dnsmadeeasy.py validate-modules:doc-missing-type
@ -3543,8 +3515,6 @@ plugins/doc_fragments/vultr.py future-import-boilerplate
plugins/doc_fragments/vultr.py metaclass-boilerplate plugins/doc_fragments/vultr.py metaclass-boilerplate
plugins/doc_fragments/xenserver.py future-import-boilerplate plugins/doc_fragments/xenserver.py future-import-boilerplate
plugins/doc_fragments/xenserver.py metaclass-boilerplate plugins/doc_fragments/xenserver.py metaclass-boilerplate
plugins/doc_fragments/zabbix.py future-import-boilerplate
plugins/doc_fragments/zabbix.py metaclass-boilerplate
tests/integration/targets/inventory_kubevirt/inventory_diff.py future-import-boilerplate tests/integration/targets/inventory_kubevirt/inventory_diff.py future-import-boilerplate
tests/integration/targets/inventory_kubevirt/inventory_diff.py metaclass-boilerplate tests/integration/targets/inventory_kubevirt/inventory_diff.py metaclass-boilerplate
tests/integration/targets/inventory_kubevirt/server.py future-import-boilerplate tests/integration/targets/inventory_kubevirt/server.py future-import-boilerplate
@ -3814,4 +3784,4 @@ tests/unit/modules/web_infrastructure/test_apache2_module.py metaclass-boilerpla
tests/unit/modules/web_infrastructure/test_jenkins_plugin.py future-import-boilerplate tests/unit/modules/web_infrastructure/test_jenkins_plugin.py future-import-boilerplate
tests/unit/modules/web_infrastructure/test_jenkins_plugin.py metaclass-boilerplate tests/unit/modules/web_infrastructure/test_jenkins_plugin.py metaclass-boilerplate
tests/unit/plugins/httpapi/test_ftd.py future-import-boilerplate tests/unit/plugins/httpapi/test_ftd.py future-import-boilerplate
tests/unit/plugins/httpapi/test_ftd.py metaclass-boilerplate tests/unit/plugins/httpapi/test_ftd.py metaclass-boilerplate

View file

@ -85,8 +85,6 @@ scripts/inventory/vagrant.py future-import-boilerplate
scripts/inventory/vagrant.py metaclass-boilerplate scripts/inventory/vagrant.py metaclass-boilerplate
scripts/inventory/vbox.py future-import-boilerplate scripts/inventory/vbox.py future-import-boilerplate
scripts/inventory/vbox.py metaclass-boilerplate scripts/inventory/vbox.py metaclass-boilerplate
scripts/inventory/zabbix.py future-import-boilerplate
scripts/inventory/zabbix.py metaclass-boilerplate
scripts/inventory/zone.py future-import-boilerplate scripts/inventory/zone.py future-import-boilerplate
scripts/inventory/zone.py metaclass-boilerplate scripts/inventory/zone.py metaclass-boilerplate
scripts/vault/azure_vault.py future-import-boilerplate scripts/vault/azure_vault.py future-import-boilerplate
@ -1106,32 +1104,6 @@ plugins/modules/monitoring/statusio_maintenance.py validate-modules:doc-missing-
plugins/modules/monitoring/statusio_maintenance.py validate-modules:parameter-list-no-elements plugins/modules/monitoring/statusio_maintenance.py validate-modules:parameter-list-no-elements
plugins/modules/monitoring/statusio_maintenance.py validate-modules:parameter-type-not-in-doc plugins/modules/monitoring/statusio_maintenance.py validate-modules:parameter-type-not-in-doc
plugins/modules/monitoring/uptimerobot.py validate-modules:doc-missing-type plugins/modules/monitoring/uptimerobot.py validate-modules:doc-missing-type
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:doc-choices-do-not-match-spec
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:doc-default-does-not-match-spec
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:doc-elements-mismatch
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:doc-required-mismatch
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:invalid-argument-name
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:missing-suboption-docs
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:nonexistent-parameter-documented
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:parameter-list-no-elements
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:parameter-type-not-in-doc
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:undocumented-parameter
plugins/modules/monitoring/zabbix/zabbix_group.py validate-modules:doc-elements-mismatch
plugins/modules/monitoring/zabbix/zabbix_group.py validate-modules:parameter-list-no-elements
plugins/modules/monitoring/zabbix/zabbix_group_info.py validate-modules:doc-elements-mismatch
plugins/modules/monitoring/zabbix/zabbix_group_info.py validate-modules:parameter-list-no-elements
plugins/modules/monitoring/zabbix/zabbix_host.py validate-modules:doc-elements-mismatch
plugins/modules/monitoring/zabbix/zabbix_host.py validate-modules:parameter-list-no-elements
plugins/modules/monitoring/zabbix/zabbix_host_info.py validate-modules:doc-elements-mismatch
plugins/modules/monitoring/zabbix/zabbix_host_info.py validate-modules:parameter-list-no-elements
plugins/modules/monitoring/zabbix/zabbix_maintenance.py validate-modules:doc-elements-mismatch
plugins/modules/monitoring/zabbix/zabbix_maintenance.py validate-modules:parameter-list-no-elements
plugins/modules/monitoring/zabbix/zabbix_mediatype.py validate-modules:doc-elements-mismatch
plugins/modules/monitoring/zabbix/zabbix_mediatype.py validate-modules:parameter-list-no-elements
plugins/modules/monitoring/zabbix/zabbix_template.py validate-modules:doc-elements-mismatch
plugins/modules/monitoring/zabbix/zabbix_template.py validate-modules:parameter-list-no-elements
plugins/modules/monitoring/zabbix/zabbix_user.py validate-modules:doc-elements-mismatch
plugins/modules/monitoring/zabbix/zabbix_user.py validate-modules:parameter-list-no-elements
plugins/modules/net_tools/cloudflare_dns.py validate-modules:parameter-type-not-in-doc plugins/modules/net_tools/cloudflare_dns.py validate-modules:parameter-type-not-in-doc
plugins/modules/net_tools/dnsimple.py validate-modules:parameter-list-no-elements plugins/modules/net_tools/dnsimple.py validate-modules:parameter-list-no-elements
plugins/modules/net_tools/dnsmadeeasy.py validate-modules:doc-missing-type plugins/modules/net_tools/dnsmadeeasy.py validate-modules:doc-missing-type
@ -3543,8 +3515,6 @@ plugins/doc_fragments/vultr.py future-import-boilerplate
plugins/doc_fragments/vultr.py metaclass-boilerplate plugins/doc_fragments/vultr.py metaclass-boilerplate
plugins/doc_fragments/xenserver.py future-import-boilerplate plugins/doc_fragments/xenserver.py future-import-boilerplate
plugins/doc_fragments/xenserver.py metaclass-boilerplate plugins/doc_fragments/xenserver.py metaclass-boilerplate
plugins/doc_fragments/zabbix.py future-import-boilerplate
plugins/doc_fragments/zabbix.py metaclass-boilerplate
tests/integration/targets/inventory_kubevirt/inventory_diff.py future-import-boilerplate tests/integration/targets/inventory_kubevirt/inventory_diff.py future-import-boilerplate
tests/integration/targets/inventory_kubevirt/inventory_diff.py metaclass-boilerplate tests/integration/targets/inventory_kubevirt/inventory_diff.py metaclass-boilerplate
tests/integration/targets/inventory_kubevirt/server.py future-import-boilerplate tests/integration/targets/inventory_kubevirt/server.py future-import-boilerplate
@ -3814,4 +3784,4 @@ tests/unit/modules/web_infrastructure/test_apache2_module.py metaclass-boilerpla
tests/unit/modules/web_infrastructure/test_jenkins_plugin.py future-import-boilerplate tests/unit/modules/web_infrastructure/test_jenkins_plugin.py future-import-boilerplate
tests/unit/modules/web_infrastructure/test_jenkins_plugin.py metaclass-boilerplate tests/unit/modules/web_infrastructure/test_jenkins_plugin.py metaclass-boilerplate
tests/unit/plugins/httpapi/test_ftd.py future-import-boilerplate tests/unit/plugins/httpapi/test_ftd.py future-import-boilerplate
tests/unit/plugins/httpapi/test_ftd.py metaclass-boilerplate tests/unit/plugins/httpapi/test_ftd.py metaclass-boilerplate