@ -28,12 +28,13 @@ ANSIBLE_METADATA = {'metadata_version': '1.1',
DOCUMENTATION = '''
module : zabbix_template
short_description : create / delete zabbix template
short_description : create / delete / dump zabbix template
description :
- create / delete zabbix template
- create / delete / dump zabbix template
version_added : " 2.5 "
author :
- " @sookido "
- " Logan Vig (@logan2211) "
requirements :
- " python >= 2.6 "
- " zabbix-api >= 0.5.3 "
@ -42,10 +43,14 @@ options:
description :
- Name of zabbix template
required : true
template_json :
description :
- JSON dump of template to import
required : false
template_groups :
description :
- List of template groups to create or delete .
required : true
required : fals e
link_templates :
description :
- List of templates linked to the template .
@ -63,7 +68,7 @@ options:
description :
- state present create / update template , absent delete template
required : false
choices : [ present , absent ]
choices : [ present , absent , dump ]
default : " present "
extends_documentation_fragment :
@ -72,13 +77,15 @@ extends_documentation_fragment:
EXAMPLES = '''
- - -
- name : create templates
# Creates a new zabbix template from linked template
- name : Create Zabbix template using linked template
local_action :
module : zabbix_template
server_url : http : / / 127.0 .0 .1
login_user : username
login_password : password
template_name : ExampleHost
template_json : " { ' zabbix_export ' : {} } "
template_groups :
- Role
- Role2
@ -96,16 +103,114 @@ EXAMPLES = '''
- macro : ' { $EXAMPLE_MACRO3} '
value : ' Example '
state : present
# Create a new template from a json config definition
- name : Import Zabbix json template configuration
local_action :
module : zabbix_template
server_url : http : / / 127.0 .0 .1
login_user : username
login_password : password
template_name : Apache2
template_json : " {{ lookup( ' file ' , ' zabbix_apache2.json ' ) }} "
template_groups :
- Webservers
state : present
# Import a template from Ansible variable dict
- name : Import Zabbix Template
zabbix_template :
login_user : username
login_password : password
server_url : http : / / 127.0 .0 .1
template_name : Test Template
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
template_groups : Templates
state : present
# Add a macro to a template
- name : Set a macro on the 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
# Remove a template
- 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
# Export template json definition
- name : Dump Zabbix template
local_action :
module : zabbix_template
server_url : http : / / 127.0 .0 .1
login_user : username
login_password : password
template_name : Template
state : dump
register : template_dump
'''
RETURN = '''
#defaults
template_json :
description : The JSON dump of the template
returned : when state is dump
type : string
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 "
} ]
}
}
'''
from ansible . module_utils . basic import AnsibleModule
from ansible . module_utils . _text import to_native
import json
import traceback
try :
from zabbix_api import ZabbixAPI
from zabbix_api import ZabbixAPI , ZabbixAPIException
HAS_ZABBIX_API = True
except ImportError :
@ -129,6 +234,8 @@ class Template(object):
# 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 ' ,
@ -153,7 +260,7 @@ class Template(object):
template_ids . append ( template_id )
return template_ids
def add_template ( self , template_name , group_ids,
def add_template ( self , template_name , template_json, group_ids,
child_template_ids , macros ) :
if self . _module . check_mode :
self . _module . exit_json ( changed = True )
@ -161,23 +268,162 @@ class Template(object):
' groups ' : group_ids ,
' templates ' : child_template_ids ,
' macros ' : macros } )
if template_json :
self . import_template ( template_json , template_name )
def update_template ( self , templateids ,
def update_template ( self , templateids , template_json ,
group_ids , child_template_ids ,
clear_template_ids , macros ) :
clear_template_ids , macros ,
existing_template_json = None ) :
changed = False
template_changes = { }
if group_ids is not None :
template_changes . update ( { ' groups ' : group_ids } )
changed = True
if child_template_ids is not None :
template_changes . update ( { ' templates ' : child_template_ids } )
changed = True
if macros is not None :
template_changes . update ( { ' macros ' : macros } )
changed = True
do_import = False
if template_json :
parsed_template_json = self . load_json_template ( template_json )
if self . diff_template ( parsed_template_json ,
existing_template_json ) :
do_import = True
changed = True
if self . _module . check_mode :
self . _module . exit_json ( changed = True )
self . _zapi . template . update (
{ ' templateid ' : templateids , ' groups ' : group_ids ,
' templates ' : child_template_ids ,
' templates_clear ' : clear_template_ids ,
' macros ' : macros } )
self . _module . exit_json ( changed = changed )
if template_changes :
template_changes . update ( {
' templateid ' : templateids ,
' templates_clear ' : clear_template_ids
} )
self . _zapi . template . update ( template_changes )
if do_import :
self . import_template ( template_json ,
existing_template_json [ ' zabbix_export ' ] [ ' templates ' ] [ 0 ] [ ' template ' ] )
return changed
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 ) :
if self . _module . check_mode :
self . _module . exit_json ( changed = True )
try :
dump = self . _zapi . configuration . export ( {
' format ' : ' json ' ,
' options ' : { ' templates ' : template_ids }
} )
return self . load_json_template ( dump )
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 ]
return template_json
def load_json_template ( self , template_json ) :
try :
return json . loads ( template_json )
except ValueError as e :
self . _module . fail_json (
msg = ' Invalid JSON provided ' ,
details = to_native ( e ) ,
exception = traceback . format_exc ( )
)
def import_template ( self , template_json , template_name = None ) :
parsed_template_json = self . load_json_template ( template_json )
if template_name != parsed_template_json [ ' zabbix_export ' ] [ ' templates ' ] [ 0 ] [ ' template ' ] :
self . _module . fail_json ( msg = ' JSON template name does not match presented name ' )
try :
self . _zapi . configuration . import_ ( {
' format ' : ' json ' ,
' source ' : template_json ,
' rules ' : {
' applications ' : {
' createMissing ' : True ,
' updateExisting ' : True ,
' deleteMissing ' : True
} ,
' discoveryRules ' : {
' createMissing ' : True ,
' updateExisting ' : True ,
' deleteMissing ' : True
} ,
' graphs ' : {
' createMissing ' : True ,
' updateExisting ' : True ,
' deleteMissing ' : True
} ,
' httptests ' : {
' createMissing ' : True ,
' updateExisting ' : True ,
' deleteMissing ' : True
} ,
' items ' : {
' createMissing ' : True ,
' updateExisting ' : True ,
' deleteMissing ' : True
} ,
' templates ' : {
' createMissing ' : True ,
' updateExisting ' : True
} ,
' templateScreens ' : {
' createMissing ' : True ,
' updateExisting ' : True ,
' deleteMissing ' : True
} ,
' triggers ' : {
' createMissing ' : True ,
' updateExisting ' : True ,
' deleteMissing ' : True
} ,
' valueMaps ' : {
' createMissing ' : True ,
' updateExisting ' : True
}
}
} )
except ZabbixAPIException as e :
self . _module . fail_json (
msg = ' Unable to import JSON template ' ,
details = to_native ( e ) ,
exception = traceback . format_exc ( )
)
def main ( ) :
module = AnsibleModule (
@ -190,11 +436,13 @@ def main():
default = None , no_log = True ) ,
validate_certs = dict ( type = ' bool ' , required = False , default = True ) ,
template_name = dict ( type = ' str ' , required = True ) ,
template_groups = dict ( type = ' list ' , required = True ) ,
template_json = dict ( type = ' json ' , 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 ) ,
state = dict ( default = " present " , choices = [ ' present ' , ' absent ' ] ) ,
state = dict ( default = " present " , choices = [ ' present ' , ' absent ' ,
' dump ' ] ) ,
timeout = dict ( type = ' int ' , default = 10 )
) ,
supports_check_mode = True
@ -212,10 +460,11 @@ def main():
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_groups = module . params [ ' template_groups ' ]
link_templates = module . params [ ' link_templates ' ]
clear_templates = module . params [ ' clear_templates ' ]
macros = module . params [ ' macros ' ]
template_ macros = module . params [ ' macros ' ]
state = module . params [ ' state ' ]
timeout = module . params [ ' timeout ' ]
@ -226,11 +475,14 @@ def main():
zbx = ZabbixAPI ( server_url , timeout = timeout ,
user = http_login_user , passwd = http_login_password , validate_certs = validate_certs )
zbx . login ( login_user , login_password )
except Exception as e :
except ZabbixAPI Exception as e :
module . fail_json ( msg = " Failed to connect to Zabbix server: %s " % e )
template = Template ( module , zbx )
template_ids = template . get_template_ids ( [ template_name ] )
existing_template_json = None
if template_ids :
existing_template_json = template . dump_template ( template_ids )
# delete template
if state == " absent " :
@ -244,32 +496,51 @@ def main():
result = " Successfully delete template %s " %
template_name )
child_template_ids = [ ]
if link_templates :
child_template_ids = template . get_template_ids ( link_templates )
clear_template_ids = [ ]
if clear_templates :
clear_template_ids = template . get_template_ids ( clear_templates )
group_ids = template . get_group_ids_by_group_names ( template_groups )
if not group_ids :
module . fail_json ( msg = ' Template groups not found: %s ' %
str ( template_groups ) )
elif state == " dump " :
if not template_ids :
module . fail_json ( msg = ' Template not found: %s ' % template_name )
module . exit_json ( changed = False , template_json = existing_template_json )
elif state == " present " :
child_template_ids = None
if link_templates is not None :
child_template_ids = template . get_template_ids ( link_templates )
clear_template_ids = [ ]
if clear_templates is not None :
clear_template_ids = template . get_template_ids ( clear_templates )
group_ids = None
if template_groups is not None :
# If the template exists, compare the already set groups
existing_groups = None
if existing_template_json :
existing_groups = set ( list ( group [ ' name ' ] for group in existing_template_json [ ' zabbix_export ' ] [ ' groups ' ] ) )
if not existing_groups or set ( template_groups ) != existing_groups :
group_ids = template . get_group_ids_by_group_names ( template_groups )
macros = None
if template_macros is not None :
existing_macros = None
if existing_template_json :
existing_macros = set ( existing_template_json [ ' zabbix_export ' ] [ ' templates ' ] [ 0 ] [ ' macros ' ] )
if not existing_macros or set ( template_macros ) != existing_macros :
macros = template_macros
if not template_ids :
template . add_template ( template_name , group_ids ,
child_template_ids , macros )
module . exit_json ( changed = True ,
result = " Successfully added template: %s " %
template_name )
else :
template . update_template ( template_ids [ 0 ] , group_ids ,
child_template_ids , clear_template_ids ,
macros )
module . exit_json ( changed = True ,
result = " Successfully updateed template: %s " %
template_name )
if not template_ids :
template . add_template ( template_name , template_json , group_ids ,
child_template_ids , macros )
module . exit_json ( changed = True ,
result = " Successfully added template: %s " %
template_name )
else :
changed = template . update_template ( template_ids [ 0 ] , template_json ,
group_ids , child_template_ids ,
clear_template_ids , macros ,
existing_template_json )
module . exit_json ( changed = changed ,
result = " Successfully updateed template: %s " %
template_name )
if __name__ == ' __main__ ' :