1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
|
#!/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
DOCUMENTATION = r"""
---
module: zabbix_globalmacro
short_description: Create/update/delete Zabbix Global macros
version_added: 1.4.0
description:
- manages Zabbix Global macros, it can create, update or delete them.
- For macro_type Secret the value field cannot be validated and will always be overwritten due to the secret nature of the Text.
author:
- "Cove (@cove)"
- Dean Hailin Song (!UNKNOWN)
- Timothy Test (@ttestscripting)
requirements:
- "python >= 3.9"
options:
macro_name:
description:
- Name of the global macro in zabbix native format C({$MACRO}) or simple format C(MACRO).
required: true
type: str
macro_value:
description:
- Value of the global macro.
- Required if I(state=present).
type: str
macro_type:
description:
- Type of the global macro Text or Secret Text.
- Required if I(state=present).
- text
- secret - Secret Text Works only with Zabbix >= 5.0 and will default to Text in lower versions
- vault - Vault Secret Works only with Zabbix >= 5.2 and will default to Text in lower versions
type: str
choices: [text, secret, vault]
default: text
macro_description:
description:
- Text Description of the global macro.
type: str
default: ""
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
notes:
- This module returns changed=true when I(macro_type=secret).
extends_documentation_fragment:
- community.zabbix.zabbix
"""
EXAMPLES = r"""
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
ansible.builtin.set_fact:
ansible_user: Admin
ansible_httpapi_pass: zabbix
# If you want to use API token to be authenticated by Zabbix Server
# https://www.zabbix.com/documentation/current/en/manual/web_interface/frontend_sections/administration/general#api-tokens
- name: Set API token
ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: Create new global macro or update an existing macro's value
# set task level variables as we change ansible_connection plugin here
vars:
ansible_network_os: community.zabbix.zabbix
ansible_connection: httpapi
ansible_httpapi_port: 443
ansible_httpapi_use_ssl: true
ansible_httpapi_validate_certs: false
ansible_zabbix_url_path: "zabbixeu" # If Zabbix WebUI runs on non-default (zabbix) path ,e.g. http://<FQDN>/zabbixeu
ansible_host: zabbix-example-fqdn.org
community.zabbix.zabbix_globalmacro:
macro_name: EXAMPLE.MACRO
macro_value: Example value
macro_type: 0
macro_description: Example description
state: present
# Values with curly brackets need to be quoted otherwise they will be interpreted as a dictionary
- name: Create new global macro in Zabbix native format with Secret Type
# set task level variables as we change ansible_connection plugin here
vars:
ansible_network_os: community.zabbix.zabbix
ansible_connection: httpapi
ansible_httpapi_port: 443
ansible_httpapi_use_ssl: true
ansible_httpapi_validate_certs: false
ansible_zabbix_url_path: "zabbixeu" # If Zabbix WebUI runs on non-default (zabbix) path ,e.g. http://<FQDN>/zabbixeu
ansible_host: zabbix-example-fqdn.org
community.zabbix.zabbix_globalmacro:
macro_name: "{$EXAMPLE.MACRO}"
macro_value: Example value
macro_type: 1
macro_description: Example description
state: present
- name: Delete existing global macro
community.zabbix.zabbix_globalmacro:
macro_name: "{$EXAMPLE.MACRO}"
state: absent
"""
RETURN = r"""
"""
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.zabbix.plugins.module_utils.base import ZabbixBase
import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabbix_utils
class GlobalMacro(ZabbixBase):
# get global macro
def get_global_macro(self, macro_name):
try:
all_global_macro_list = self._zapi.usermacro.get({"globalmacro": "true"})
global_macro_list = [d for d in all_global_macro_list if d["macro"] == macro_name]
if len(global_macro_list) > 0:
return global_macro_list[0]
return None
except Exception as e:
self._module.fail_json(msg="Failed to get global macro %s: %s" % (macro_name, e))
# create global macro
def create_global_macro(self, macro_name, macro_value, macro_type, macro_description):
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
self._zapi.usermacro.createglobal({"macro": macro_name, "value": macro_value, "type": macro_type, "description": macro_description})
self._module.exit_json(changed=True, result="Successfully added global macro %s" % macro_name)
except Exception as e:
self._module.fail_json(msg="Failed to create global macro %s: %s" % (macro_name, e))
# update global macro
def update_global_macro(self, global_macro_obj, macro_name, macro_value, macro_type, macro_description):
global_macro_id = global_macro_obj["globalmacroid"]
try:
if global_macro_obj["type"] == "0" or global_macro_obj["type"] == "2":
if (global_macro_obj["macro"] == macro_name and global_macro_obj["value"] == macro_value
and global_macro_obj["type"] == macro_type and global_macro_obj["description"] == macro_description):
self._module.exit_json(changed=False, result="Global macro %s already up to date" % macro_name)
if self._module.check_mode:
self._module.exit_json(changed=True)
self._zapi.usermacro.updateglobal({"globalmacroid": global_macro_id, "macro": macro_name,
"value": macro_value, "type": macro_type, "description": macro_description})
self._module.exit_json(changed=True, result="Successfully updated global macro %s" % macro_name)
except Exception as e:
self._module.fail_json(msg="Failed to update global macro %s: %s" % (macro_name, e))
# delete global macro
def delete_global_macro(self, global_macro_obj, macro_name):
global_macro_id = global_macro_obj["globalmacroid"]
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
self._zapi.usermacro.deleteglobal([global_macro_id])
self._module.exit_json(changed=True, result="Successfully deleted global macro %s" % macro_name)
except Exception as e:
self._module.fail_json(msg="Failed to delete global 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():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
macro_name=dict(type="str", required=True),
macro_value=dict(type="str", required=False, no_log=True),
macro_type=dict(type="str", default="text", choices=["text", "secret", "vault"]),
macro_description=dict(type="str", default=""),
state=dict(type="str", default="present", choices=["present", "absent"]),
force=dict(type="bool", default=True)
))
module = AnsibleModule(
argument_spec=argument_spec,
required_if=[
["state", "present", ["macro_value"]]
],
supports_check_mode=True
)
macro_name = normalize_macro_name(module.params["macro_name"])
macro_value = module.params["macro_value"]
macro_type = module.params["macro_type"]
macro_value = module.params["macro_value"]
macro_description = module.params["macro_description"]
state = module.params["state"]
force = module.params["force"]
if macro_type == "text":
macro_type = "0"
elif macro_type == "secret":
macro_type = "1"
elif macro_type == "vault":
macro_type = "2"
global_macro_class_obj = GlobalMacro(module)
if macro_name:
global_macro_obj = global_macro_class_obj.get_global_macro(macro_name)
if state == "absent":
if not global_macro_obj:
module.exit_json(changed=False, msg="Global Macro %s does not exist" % macro_name)
else:
# delete a macro
global_macro_class_obj.delete_global_macro(global_macro_obj, macro_name)
else:
if not global_macro_obj:
# create global macro
global_macro_class_obj.create_global_macro(macro_name, macro_value, macro_type, macro_description)
elif force:
# update global macro
global_macro_class_obj.update_global_macro(global_macro_obj, macro_name, macro_value, macro_type, macro_description)
else:
module.exit_json(changed=False, result="Global macro %s already exists and force is set to no" % macro_name)
if __name__ == "__main__":
main()
|