summaryrefslogtreecommitdiffstats
path: root/ansible_collections/community/zabbix/plugins/modules
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-18 05:52:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-18 05:52:35 +0000
commit7fec0b69a082aaeec72fee0612766aa42f6b1b4d (patch)
treeefb569b86ca4da888717f5433e757145fa322e08 /ansible_collections/community/zabbix/plugins/modules
parentReleasing progress-linux version 7.7.0+dfsg-3~progress7.99u1. (diff)
downloadansible-7fec0b69a082aaeec72fee0612766aa42f6b1b4d.tar.xz
ansible-7fec0b69a082aaeec72fee0612766aa42f6b1b4d.zip
Merging upstream version 9.4.0+dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/community/zabbix/plugins/modules')
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_action.py1576
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_api_info.py108
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_authentication.py570
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_autoregister.py86
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_discovery_rule.py445
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_globalmacro.py151
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_group.py34
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_group_events_info.py283
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_group_facts.py115
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_group_info.py39
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_host.py748
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_host_events_info.py100
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_host_facts.py239
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_host_info.py106
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_hostmacro.py137
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_housekeeping.py187
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_maintenance.py239
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_map.py357
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_mediatype.py506
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_proxy.py241
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_proxy_info.py47
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_regexp.py345
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_screen.py496
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_script.py316
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_service.py566
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_settings.py1112
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_template.py511
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_template_info.py187
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_templategroup.py180
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_token.py288
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_user.py799
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_user_directory.py444
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_user_info.py48
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_user_role.py63
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_usergroup.py456
-rw-r--r--ansible_collections/community/zabbix/plugins/modules/zabbix_valuemap.py99
36 files changed, 6712 insertions, 5512 deletions
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_action.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_action.py
index 8e130de69..c0123ae1f 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_action.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_action.py
@@ -8,7 +8,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
module: zabbix_action
@@ -23,41 +23,51 @@ author:
- Ruben Harutyunov (@K-DOT)
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
options:
name:
+ type: str
description:
- Name of the action
required: true
event_source:
+ type: str
description:
- Type of events that the action will handle.
- Required when C(state=present).
required: false
- choices: ['trigger', 'discovery', 'auto_registration', 'internal']
+ choices: ["trigger", "discovery", "auto_registration", "internal"]
state:
+ type: str
description:
- State of the action.
- On C(present), it will create an action if it does not exist or update the action if the associated data is different.
- On C(absent), it will remove the action if it exists.
- choices: ['present', 'absent']
- default: 'present'
+ choices: ["present", "absent"]
+ default: "present"
status:
+ type: str
description:
- Status of the action.
- choices: ['enabled', 'disabled']
- default: 'enabled'
+ choices: ["enabled", "disabled"]
+ default: "enabled"
pause_in_maintenance:
description:
- Whether to pause escalation during maintenance periods or not.
- Can be used when I(event_source=trigger).
- type: 'bool'
+ type: "bool"
+ default: true
+ notify_if_canceled:
+ description:
+ - Weather to notify when escalation is canceled.
+ - Can be used when I(event_source=trigger).
+ type: "bool"
default: true
esc_period:
+ type: str
description:
- Default operation step duration. Must be greater than 60 seconds.
- - Accepts only seconds in int for <= Zabbix 3.2
- Accepts seconds, time unit with suffix and user macro since => Zabbix 3.4
- Required when C(state=present).
required: false
@@ -68,112 +78,123 @@ options:
- List of conditions to use for filtering results.
- For more information about suboptions of this option please
check out Zabbix API documentation U(https://www.zabbix.com/documentation/5.0/manual/api/reference/action/object#action_filter_condition)
+ default: []
suboptions:
type:
+ type: str
description:
- Type (label) of the condition.
- - C(application) is available only with <= Zabbix 5.2.
- - 'Possible values when I(event_source=trigger):'
- - ' - C(host_group)'
- - ' - C(host)'
- - ' - C(trigger)'
- - ' - C(trigger_name)'
- - ' - C(trigger_severity)'
- - ' - C(time_period)'
- - ' - C(host_template)'
- - ' - C(application)'
- - ' - C(maintenance_status) known in Zabbix 4.0 and above as "Problem is suppressed"'
- - ' - C(event_tag)'
- - ' - C(event_tag_value)'
- - 'Possible values when I(event_source=discovery):'
- - ' - C(host_IP)'
- - ' - C(discovered_service_type)'
- - ' - C(discovered_service_port)'
- - ' - C(discovery_status)'
- - ' - C(uptime_or_downtime_duration)'
- - ' - C(received_value)'
- - ' - C(discovery_rule)'
- - ' - C(discovery_check)'
- - ' - C(proxy)'
- - ' - C(discovery_object)'
- - 'Possible values when I(event_source=auto_registration):'
- - ' - C(proxy)'
- - ' - C(host_name)'
- - ' - C(host_metadata)'
- - 'Possible values when I(event_source=internal):'
- - ' - C(host_group)'
- - ' - C(host)'
- - ' - C(host_template)'
- - ' - C(application)'
- - ' - C(event_type)'
+ - "Possible values when I(event_source=trigger):"
+ - " - C(host_group)"
+ - " - C(host)"
+ - " - C(trigger)"
+ - " - C(trigger_name)"
+ - " - C(trigger_severity)"
+ - " - C(time_period)"
+ - " - C(host_template)"
+ - " - C(maintenance_status) known in Zabbix 4.0 and above as 'Problem is suppressed'"
+ - " - C(event_tag)"
+ - " - C(event_tag_value)"
+ - "Possible values when I(event_source=discovery):"
+ - " - C(host_IP)"
+ - " - C(discovered_service_type)"
+ - " - C(discovered_service_port)"
+ - " - C(discovery_status)"
+ - " - C(uptime_or_downtime_duration)"
+ - " - C(received_value)"
+ - " - C(discovery_rule)"
+ - " - C(discovery_check)"
+ - " - C(proxy)"
+ - " - C(discovery_object)"
+ - "Possible values when I(event_source=auto_registration):"
+ - " - C(proxy)"
+ - " - C(host_name)"
+ - " - C(host_metadata)"
+ - "Possible values when I(event_source=internal):"
+ - " - C(host_group)"
+ - " - C(host)"
+ - " - C(host_template)"
+ - " - C(event_type)"
+ required: true
value:
+ type: str
description:
- Value to compare with.
- - 'When I(type=discovery_status), the choices are:'
- - ' - C(up)'
- - ' - C(down)'
- - ' - C(discovered)'
- - ' - C(lost)'
- - 'When I(type=discovery_object), the choices are:'
- - ' - C(host)'
- - ' - C(service)'
- - 'When I(type=event_type), the choices are:'
- - ' - C(item in not supported state)'
- - ' - C(item in normal state)'
- - ' - C(LLD rule in not supported state)'
- - ' - C(LLD rule in normal state)'
- - ' - C(trigger in unknown state)'
- - ' - C(trigger in normal state)'
- - 'When I(type=trigger_severity), the choices are (case-insensitive):'
- - ' - C(not classified)'
- - ' - C(information)'
- - ' - C(warning)'
- - ' - C(average)'
- - ' - C(high)'
- - ' - C(disaster)'
+ - "When I(type=discovery_status), the choices are:"
+ - " - C(up)"
+ - " - C(down)"
+ - " - C(discovered)"
+ - " - C(lost)"
+ - "When I(type=discovery_object), the choices are:"
+ - " - C(host)"
+ - " - C(service)"
+ - "When I(type=event_type), the choices are:"
+ - " - C(item in not supported state)"
+ - " - C(item in normal state)"
+ - " - C(LLD rule in not supported state)"
+ - " - C(LLD rule in normal state)"
+ - " - C(trigger in unknown state)"
+ - " - C(trigger in normal state)"
+ - "When I(type=trigger_severity), the choices are (case-insensitive):"
+ - " - C(not classified)"
+ - " - C(information)"
+ - " - C(warning)"
+ - " - C(average)"
+ - " - C(high)"
+ - " - C(disaster)"
- Irrespective of user-visible names being changed in Zabbix. Defaults to C(not classified) if omitted.
- Besides the above options, this is usually either the name
of the object or a string to compare with.
value2:
+ type: str
description:
- Secondary value to compare with.
- Required for trigger actions when condition I(type=event_tag_value).
operator:
+ type: str
description:
- Condition operator.
- When I(type) is set to C(time_period), the choices are C(in), C(not in).
- - C(matches), C(does not match), C(Yes) and C(No) condition operators work only with >= Zabbix 4.0
- - When I(type) is set to C(maintenance_status), the choices are C(Yes) and C(No) for Zabbix >= 6.0
choices:
- - C(equals) or C(=)
- - C(does not equal) or C(<>)
- - C(contains) or C(like)
- - C(does not contain) or C(not like)
- - C(in)
- - C(is greater than or equals) or C(>=)
- - C(is less than or equals) or C(<=)
- - C(not in)
- - C(matches)
- - C(does not match)
- - C(Yes)
- - C(No)
+ - "equals"
+ - "="
+ - "does not equal"
+ - "<>"
+ - "contains"
+ - "like"
+ - "does not contain"
+ - "not like"
+ - "in"
+ - "is greater than or equals"
+ - ">="
+ - "is less than or equals"
+ - "<="
+ - "not in"
+ - "matches"
+ - "does not match"
+ - "Yes"
+ - "No"
+ required: true
formulaid:
+ type: str
description:
- Arbitrary unique ID that is used to reference the condition from a custom expression.
- Can only contain upper-case letters.
- Required for custom expression filters and ignored otherwise.
eval_type:
+ type: str
description:
- Filter condition evaluation method.
- Defaults to C(andor) if conditions are less then 2 or if
I(formula) is not specified.
- Defaults to C(custom_expression) when formula is specified.
choices:
- - 'andor'
- - 'and'
- - 'or'
- - 'custom_expression'
+ - "andor"
+ - "and"
+ - "or"
+ - "custom_expression"
formula:
+ type: str
description:
- User-defined expression to be used for evaluating conditions with a custom expression.
- The expression must contain IDs that reference each condition by its formulaid.
@@ -182,48 +203,21 @@ options:
- Required when I(eval_type=custom_expression).
- Use sequential IDs that start at "A". If non-sequential IDs are used, Zabbix re-indexes them.
This makes each module run notice the difference in IDs and update the action.
- default_message:
- description:
- - Problem message default text.
- - With >= Zabbix 5.0 this field is removed from the API and is dropped silently by module.
- - Works only with < Zabbix 5.0
- default_subject:
- description:
- - Problem message default subject.
- - With >= Zabbix 5.0 this field is removed from the API and is dropped silently by module.
- - Works only with < Zabbix 5.0
- recovery_default_message:
- description:
- - Recovery message text.
- - With >= Zabbix 5.0 this field is removed from the API and is dropped silently by module.
- - Works only with >= Zabbix 3.2 and < Zabbix 5.0
- recovery_default_subject:
- description:
- - Recovery message subject.
- - With >= Zabbix 5.0 this field is removed from the API and is dropped silently by module.
- - Works only with >= Zabbix 3.2 and < Zabbix 5.0
- acknowledge_default_message:
- description:
- - Update operation (known as "Acknowledge operation" before Zabbix 4.0) message text.
- - With >= Zabbix 5.0 this field is removed from the API and is dropped silently by module.
- - Works only with >= Zabbix 3.4 and < Zabbix 5.0
- acknowledge_default_subject:
- description:
- - Update operation (known as "Acknowledge operation" before Zabbix 4.0) message subject.
- - With >= Zabbix 5.0 this field is removed from the API and is dropped silently by module.
- - Works only with >= Zabbix 3.4 and < Zabbix 5.0
operations:
type: list
+ elements: dict
description:
- List of action operations
+ default: []
suboptions:
type:
+ type: str
description:
- Type of operation.
- - 'Valid choices when setting type for I(recovery_operations) and I(acknowledge_operations):'
- - ' - C(send_message)'
- - ' - C(remote_command)'
- - ' - C(notify_all_involved)'
+ - "Valid choices when setting type for I(recovery_operations) and I(acknowledge_operations):"
+ - " - C(send_message)"
+ - " - C(remote_command)"
+ - " - C(notify_all_involved)"
- Choice C(notify_all_involved) only supported in I(recovery_operations) and I(acknowledge_operations).
choices:
- send_message
@@ -238,47 +232,55 @@ options:
- disable_host
- set_host_inventory_mode
- notify_all_involved
+ required: true
esc_period:
+ type: str
description:
- Duration of an escalation step in seconds.
- Must be greater than 60 seconds.
- - Accepts only seconds in int for <= Zabbix 3.2
- - Accepts seconds, time unit with suffix and user macro since => Zabbix 3.4
+ - Accepts seconds, time unit with suffix and user macro.
- If set to 0 or 0s, the default action escalation period will be used.
default: 0s
esc_step_from:
+ type: int
description:
- Step to start escalation from.
default: 1
esc_step_to:
+ type: int
description:
- Step to end escalation at.
- Specify 0 for infinitely.
default: 1
send_to_groups:
type: list
+ elements: str
description:
- User groups to send messages to.
send_to_users:
type: list
+ elements: str
description:
- Users (usernames or aliases) to send messages to.
- message:
+ op_message:
+ type: str
description:
- Operation message text.
- - Will check the 'default message' and use the text from I(default_message) if this and I(default_subject) are not specified
+ - If I(op_message) and I(subject) not defined then "default message" from media type will be used
subject:
+ type: str
description:
- Operation message subject.
- - Will check the 'default message' and use the text from I(default_subject) if this and I(default_subject) are not specified
+ - If I(op_message) and I(subject) not defined then "default message" from media type will be used
media_type:
+ type: str
description:
- Media type that will be used to send the message.
- Can be used with I(type=send_message) or I(type=notify_all_involved) inside I(acknowledge_operations).
- Set to C(all) for all media types
- default: 'all'
+ default: "all"
operation_condition:
- type: 'str'
+ type: "str"
description:
- The action operation condition object defines a condition that must be met to perform the current operation.
choices:
@@ -286,15 +288,18 @@ options:
- not_acknowledged
host_groups:
type: list
+ elements: str
description:
- List of host groups host should be added to.
- Required when I(type=add_to_host_group) or I(type=remove_from_host_group).
templates:
type: list
+ elements: str
description:
- List of templates host should be linked to.
- Required when I(type=link_to_template) or I(type=unlink_from_template).
inventory:
+ type: str
description:
- Host inventory mode.
- Required when I(type=set_host_inventory_mode).
@@ -302,6 +307,7 @@ options:
- manual
- automatic
command_type:
+ type: str
description:
- Type of operation command.
- Required when I(type=remote_command).
@@ -312,10 +318,12 @@ options:
- telnet
- global_script
command:
+ type: str
description:
- Command to run.
- Required when I(type=remote_command) and I(command_type!=global_script).
execute_on:
+ type: str
description:
- Target on which the custom script operation command will be executed.
- Required when I(type=remote_command) and I(command_type=custom_script).
@@ -324,15 +332,20 @@ options:
- server
- proxy
run_on_groups:
+ type: list
+ elements: str
description:
- Host groups to run remote commands on.
- Required when I(type=remote_command) and I(run_on_hosts) is not set.
run_on_hosts:
+ type: list
+ elements: str
description:
- Hosts to run remote commands on.
- Required when I(type=remote_command) and I(run_on_groups) is not set.
- If set to 0 the command will be run on the current host.
ssh_auth_type:
+ type: str
description:
- Authentication method used for SSH commands.
- Required when I(type=remote_command) and I(command_type=ssh).
@@ -340,48 +353,292 @@ options:
- password
- public_key
ssh_privatekey_file:
+ type: str
description:
- Name of the private key file used for SSH commands with public key authentication.
- Required when I(ssh_auth_type=public_key).
- Can be used when I(type=remote_command).
ssh_publickey_file:
+ type: str
description:
- Name of the public key file used for SSH commands with public key authentication.
- Required when I(ssh_auth_type=public_key).
- Can be used when I(type=remote_command).
username:
+ type: str
description:
- User name used for authentication.
- Required when I(ssh_auth_type in [public_key, password]) or I(command_type=telnet).
- Can be used when I(type=remote_command).
password:
+ type: str
description:
- Password used for authentication.
- Required when I(ssh_auth_type=password) or I(command_type=telnet).
- Can be used when I(type=remote_command).
port:
+ type: int
description:
- Port number used for authentication.
- Can be used when I(command_type in [ssh, telnet]) and I(type=remote_command).
script_name:
+ type: str
description:
- The name of script used for global script commands.
- Required when I(command_type=global_script).
- Can be used when I(type=remote_command).
recovery_operations:
type: list
+ elements: dict
description:
- List of recovery operations.
- C(Suboptions) are the same as for I(operations).
- - Works only with >= Zabbix 3.2
+ default: []
+ suboptions:
+ type:
+ type: str
+ description:
+ - Type of operation.
+ choices:
+ - send_message
+ - remote_command
+ - notify_all_involved
+ required: true
+ command_type:
+ type: str
+ required: false
+ description:
+ - Type of operation command.
+ choices:
+ - custom_script
+ - ipmi
+ - ssh
+ - telnet
+ - global_script
+ command:
+ type: str
+ required: false
+ description:
+ - Command to run.
+ execute_on:
+ type: str
+ required: false
+ description:
+ - Target on which the custom script operation command will be executed.
+ choices:
+ - agent
+ - server
+ - proxy
+ ssh_auth_type:
+ type: str
+ description:
+ - Authentication method used for SSH commands.
+ - Required when I(type=remote_command) and I(command_type=ssh).
+ choices:
+ - password
+ - public_key
+ ssh_privatekey_file:
+ type: str
+ description:
+ - Name of the private key file used for SSH commands with public key authentication.
+ - Required when I(ssh_auth_type=public_key).
+ - Can be used when I(type=remote_command).
+ ssh_publickey_file:
+ type: str
+ description:
+ - Name of the public key file used for SSH commands with public key authentication.
+ - Required when I(ssh_auth_type=public_key).
+ - Can be used when I(type=remote_command).
+ run_on_groups:
+ type: list
+ elements: str
+ description:
+ - Host groups to run remote commands on.
+ - Required when I(type=remote_command) and I(run_on_hosts) is not set.
+ run_on_hosts:
+ type: list
+ elements: str
+ description:
+ - Hosts to run remote commands on.
+ - Required when I(type=remote_command) and I(run_on_groups) is not set.
+ - If set to 0 the command will be run on the current host.
+ send_to_groups:
+ type: list
+ elements: str
+ description:
+ - User groups to send messages to.
+ send_to_users:
+ type: list
+ elements: str
+ description:
+ - Users (usernames or aliases) to send messages to.
+ media_type:
+ type: str
+ description:
+ - Media type that will be used to send the message.
+ - Can be used with I(type=send_message) or I(type=notify_all_involved) inside I(acknowledge_operations).
+ - Set to C(all) for all media types
+ default: "all"
+ op_message:
+ type: str
+ description:
+ - Operation message text.
+ - If I(op_message) and I(subject) not defined then "default message" from media type will be used
+ subject:
+ type: str
+ description:
+ - Operation message subject.
+ - If I(op_message) and I(subject) not defined then "default message" from media type will be used
+ username:
+ type: str
+ description:
+ - User name used for authentication.
+ - Required when I(ssh_auth_type in [public_key, password]) or I(command_type=telnet).
+ - Can be used when I(type=remote_command).
+ password:
+ type: str
+ description:
+ - Password used for authentication.
+ - Required when I(ssh_auth_type=password) or I(command_type=telnet).
+ - Can be used when I(type=remote_command).
+ port:
+ type: int
+ description:
+ - Port number used for authentication.
+ - Can be used when I(command_type in [ssh, telnet]) and I(type=remote_command).
+ script_name:
+ type: str
+ description:
+ - The name of script used for global script commands.
+ - Required when I(command_type=global_script).
+ - Can be used when I(type=remote_command).
acknowledge_operations:
type: list
+ elements: dict
description:
- List of acknowledge operations.
- Action acknowledge operations are known as update operations since Zabbix 4.0.
- C(Suboptions) are the same as for I(operations).
- - Works only with >= Zabbix 3.4
+ suboptions:
+ type:
+ type: str
+ description:
+ - Type of operation.
+ choices:
+ - send_message
+ - remote_command
+ - notify_all_involved
+ required: true
+ command_type:
+ type: str
+ description:
+ - Type of operation command.
+ required: false
+ choices:
+ - custom_script
+ - ipmi
+ - ssh
+ - telnet
+ - global_script
+ execute_on:
+ type: str
+ required: false
+ description:
+ - Target on which the custom script operation command will be executed.
+ choices:
+ - agent
+ - server
+ - proxy
+ command:
+ type: str
+ required: false
+ description:
+ - Command to run.
+ ssh_auth_type:
+ type: str
+ description:
+ - Authentication method used for SSH commands.
+ - Required when I(type=remote_command) and I(command_type=ssh).
+ choices:
+ - password
+ - public_key
+ ssh_privatekey_file:
+ type: str
+ description:
+ - Name of the private key file used for SSH commands with public key authentication.
+ - Required when I(ssh_auth_type=public_key).
+ - Can be used when I(type=remote_command).
+ ssh_publickey_file:
+ type: str
+ description:
+ - Name of the public key file used for SSH commands with public key authentication.
+ - Required when I(ssh_auth_type=public_key).
+ - Can be used when I(type=remote_command).
+ run_on_groups:
+ type: list
+ elements: str
+ description:
+ - Host groups to run remote commands on.
+ - Required when I(type=remote_command) and I(run_on_hosts) is not set.
+ run_on_hosts:
+ type: list
+ elements: str
+ description:
+ - Hosts to run remote commands on.
+ - Required when I(type=remote_command) and I(run_on_groups) is not set.
+ - If set to 0 the command will be run on the current host.
+ send_to_groups:
+ type: list
+ elements: str
+ description:
+ - User groups to send messages to.
+ send_to_users:
+ type: list
+ elements: str
+ description:
+ - Users (usernames or aliases) to send messages to.
+ media_type:
+ type: str
+ description:
+ - Media type that will be used to send the message.
+ - Can be used with I(type=send_message) or I(type=notify_all_involved) inside I(acknowledge_operations).
+ - Set to C(all) for all media types
+ default: "all"
+ op_message:
+ type: str
+ description:
+ - Operation message text.
+ - If I(op_message) and I(subject) not defined then "default message" from media type will be used
+ subject:
+ type: str
+ description:
+ - Operation message subject.
+ - If I(op_message) and I(subject) not defined then "default message" from media type will be used
+ username:
+ type: str
+ description:
+ - User name used for authentication.
+ - Required when I(ssh_auth_type in [public_key, password]) or I(command_type=telnet).
+ - Can be used when I(type=remote_command).
+ password:
+ type: str
+ description:
+ - Password used for authentication.
+ - Required when I(ssh_auth_type=password) or I(command_type=telnet).
+ - Can be used when I(type=remote_command).
+ port:
+ type: int
+ description:
+ - Port number used for authentication.
+ - Can be used when I(command_type in [ssh, telnet]) and I(type=remote_command).
+ script_name:
+ type: str
+ description:
+ - The name of script used for global script commands.
+ - Required when I(command_type=global_script).
+ - Can be used when I(type=remote_command).
aliases: [ update_operations ]
+ default: []
pause_symptoms:
type: bool
description:
@@ -390,26 +647,23 @@ options:
- Works only with >= Zabbix 6.4
default: true
-notes:
- - Only Zabbix >= 3.0 is supported.
-
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = '''
+EXAMPLES = """
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
# Trigger action with only one condition
@@ -421,25 +675,25 @@ EXAMPLES = '''
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_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_action:
name: "Send alerts to Admin"
- event_source: 'trigger'
+ event_source: "trigger"
state: present
status: enabled
esc_period: 60
conditions:
- - type: 'trigger_severity'
- operator: '>='
- value: 'Information'
+ - type: "trigger_severity"
+ operator: ">="
+ value: "Information"
operations:
- type: send_message
subject: "Something bad is happening"
- message: "Come on, guys do something"
- media_type: 'Email'
+ op_message: "Come on, guys do something"
+ media_type: "Email"
send_to_users:
- - 'Admin'
+ - "Admin"
# Trigger action with multiple conditions and operations
- name: Deploy trigger action
@@ -450,31 +704,31 @@ EXAMPLES = '''
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_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_action:
name: "Send alerts to Admin"
- event_source: 'trigger'
+ event_source: "trigger"
state: present
status: enabled
esc_period: 1m
conditions:
- - type: 'trigger_name'
- operator: 'like'
- value: 'Zabbix agent is unreachable'
+ - type: "trigger_name"
+ operator: "like"
+ value: "Zabbix agent is unreachable"
formulaid: A
- - type: 'trigger_severity'
- operator: '>='
- value: 'disaster'
+ - type: "trigger_severity"
+ operator: ">="
+ value: "disaster"
formulaid: B
formula: A or B
operations:
- type: send_message
- media_type: 'Email'
+ media_type: "Email"
send_to_users:
- - 'Admin'
+ - "Admin"
- type: remote_command
- command: 'systemctl restart zabbix-agent'
+ command: "systemctl restart zabbix-agent"
command_type: custom_script
execute_on: server
run_on_hosts:
@@ -489,46 +743,46 @@ EXAMPLES = '''
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_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_action:
name: "Send alerts to Admin"
- event_source: 'trigger'
+ event_source: "trigger"
state: present
status: enabled
esc_period: 1h
conditions:
- - type: 'trigger_severity'
- operator: '>='
- value: 'Information'
+ - type: "trigger_severity"
+ operator: ">="
+ value: "Information"
operations:
- type: send_message
subject: "Something bad is happening"
- message: "Come on, guys do something"
- media_type: 'Email'
+ op_message: "Come on, guys do something"
+ media_type: "Email"
send_to_users:
- - 'Admin'
+ - "Admin"
recovery_operations:
- type: send_message
subject: "Host is down"
- message: "Come on, guys do something"
- media_type: 'Email'
+ op_message: "Come on, guys do something"
+ media_type: "Email"
send_to_users:
- - 'Admin'
+ - "Admin"
acknowledge_operations:
- type: send_message
- media_type: 'Email'
+ media_type: "Email"
send_to_users:
- - 'Admin'
-'''
+ - "Admin"
+"""
-RETURN = '''
+RETURN = """
msg:
description: The result of the operation
returned: success
type: str
- sample: 'Action Deleted: Register webservers, ID: 0001'
-'''
+ sample: "Action Deleted: Register webservers, ID: 0001"
+"""
from ansible.module_utils.basic import AnsibleModule
@@ -558,16 +812,11 @@ class Zapi(ZabbixBase):
_params = {
"selectOperations": "extend",
"selectRecoveryOperations": "extend",
- "selectAcknowledgeOperations": "extend",
+ "selectUpdateOperations": "extend",
"selectFilter": "extend",
- 'filter': {'name': [name]}
+ "filter": {"name": [name]}
}
- if LooseVersion(self._zbx_api_version) >= LooseVersion('6.0'):
- _params['selectUpdateOperations'] = _params.pop('selectAcknowledgeOperations', 'extend')
_action = self._zapi.action.get(_params)
- if len(_action) > 0 and LooseVersion(self._zbx_api_version) < LooseVersion('6.0'):
- _action[0]['recovery_operations'] = _action[0].pop('recoveryOperations', [])
- _action[0]['acknowledge_operations'] = _action[0].pop('acknowledgeOperations', [])
return _action
except Exception as e:
self._module.fail_json(msg="Failed to check if action '%s' exists: %s" % (name, e))
@@ -584,8 +833,8 @@ class Zapi(ZabbixBase):
"""
try:
action_list = self._zapi.action.get({
- 'output': 'extend',
- 'filter': {'name': [name]}
+ "output": "extend",
+ "filter": {"name": [name]}
})
if len(action_list) < 1:
self._module.fail_json(msg="Action not found: %s" % name)
@@ -606,9 +855,9 @@ class Zapi(ZabbixBase):
"""
try:
host_list = self._zapi.host.get({
- 'output': 'extend',
- 'selectInventory': 'extend',
- 'filter': {'host': [host_name]}
+ "output": "extend",
+ "selectInventory": "extend",
+ "filter": {"host": [host_name]}
})
if len(host_list) < 1:
self._module.fail_json(msg="Host not found: %s" % host_name)
@@ -629,8 +878,8 @@ class Zapi(ZabbixBase):
"""
try:
hostgroup_list = self._zapi.hostgroup.get({
- 'output': 'extend',
- 'filter': {'name': [hostgroup_name]}
+ "output": "extend",
+ "filter": {"name": [hostgroup_name]}
})
if len(hostgroup_list) < 1:
self._module.fail_json(msg="Host group not found: %s" % hostgroup_name)
@@ -651,8 +900,8 @@ class Zapi(ZabbixBase):
"""
try:
template_list = self._zapi.template.get({
- 'output': 'extend',
- 'filter': {'host': [template_name]}
+ "output": "extend",
+ "filter": {"host": [template_name]}
})
if len(template_list) < 1:
self._module.fail_json(msg="Template not found: %s" % template_name)
@@ -673,8 +922,8 @@ class Zapi(ZabbixBase):
"""
try:
trigger_list = self._zapi.trigger.get({
- 'output': 'extend',
- 'filter': {'description': [trigger_name]}
+ "output": "extend",
+ "filter": {"description": [trigger_name]}
})
if len(trigger_list) < 1:
self._module.fail_json(msg="Trigger not found: %s" % trigger_name)
@@ -695,8 +944,8 @@ class Zapi(ZabbixBase):
"""
try:
discovery_rule_list = self._zapi.drule.get({
- 'output': 'extend',
- 'filter': {'name': [discovery_rule_name]}
+ "output": "extend",
+ "filter": {"name": [discovery_rule_name]}
})
if len(discovery_rule_list) < 1:
self._module.fail_json(msg="Discovery rule not found: %s" % discovery_rule_name)
@@ -716,38 +965,38 @@ class Zapi(ZabbixBase):
"""
try:
- discovery_rule_name, dcheck_type = discovery_check_name.split(': ')
+ discovery_rule_name, dcheck_type = discovery_check_name.split(": ")
dcheck_type_to_number = {
- 'SSH': '0',
- 'LDAP': '1',
- 'SMTP': '2',
- 'FTP': '3',
- 'HTTP': '4',
- 'POP': '5',
- 'NNTP': '6',
- 'IMAP': '7',
- 'TCP': '8',
- 'Zabbix agent': '9',
- 'SNMPv1 agent': '10',
- 'SNMPv2 agent': '11',
- 'ICMP ping': '12',
- 'SNMPv3 agent': '13',
- 'HTTPS': '14',
- 'Telnet': '15'
+ "SSH": "0",
+ "LDAP": "1",
+ "SMTP": "2",
+ "FTP": "3",
+ "HTTP": "4",
+ "POP": "5",
+ "NNTP": "6",
+ "IMAP": "7",
+ "TCP": "8",
+ "Zabbix agent": "9",
+ "SNMPv1 agent": "10",
+ "SNMPv2 agent": "11",
+ "ICMP ping": "12",
+ "SNMPv3 agent": "13",
+ "HTTPS": "14",
+ "Telnet": "15"
}
if dcheck_type not in dcheck_type_to_number:
self._module.fail_json(msg="Discovery check type: %s does not exist" % dcheck_type)
discovery_rule_list = self._zapi.drule.get({
- 'output': ['dchecks'],
- 'filter': {'name': [discovery_rule_name]},
- 'selectDChecks': 'extend'
+ "output": ["dchecks"],
+ "filter": {"name": [discovery_rule_name]},
+ "selectDChecks": "extend"
})
if len(discovery_rule_list) < 1:
self._module.fail_json(msg="Discovery check not found: %s" % discovery_check_name)
- for dcheck in discovery_rule_list[0]['dchecks']:
- if dcheck_type_to_number[dcheck_type] == dcheck['type']:
+ for dcheck in discovery_rule_list[0]["dchecks"]:
+ if dcheck_type_to_number[dcheck_type] == dcheck["type"]:
return dcheck
self._module.fail_json(msg="Discovery check not found: %s" % discovery_check_name)
except Exception as e:
@@ -765,8 +1014,8 @@ class Zapi(ZabbixBase):
"""
try:
proxy_list = self._zapi.proxy.get({
- 'output': 'extend',
- 'filter': {'host': [proxy_name]}
+ "output": "extend",
+ "filter": {"host": [proxy_name]}
})
if len(proxy_list) < 1:
self._module.fail_json(msg="Proxy not found: %s" % proxy_name)
@@ -785,22 +1034,19 @@ class Zapi(ZabbixBase):
mediatype matching mediatype name
"""
- if LooseVersion(self._zbx_api_version) >= LooseVersion('4.4'):
- filter = {'name': [mediatype_name]}
- else:
- filter = {'description': [mediatype_name]}
+ filter = {"name": [mediatype_name]}
try:
- if str(mediatype_name).lower() == 'all':
- return '0'
+ if str(mediatype_name).lower() == "all":
+ return "0"
mediatype_list = self._zapi.mediatype.get({
- 'output': 'extend',
- 'filter': filter
+ "output": "extend",
+ "filter": filter
})
if len(mediatype_list) < 1:
self._module.fail_json(msg="Media type not found: %s" % mediatype_name)
else:
- return mediatype_list[0]['mediatypeid']
+ return mediatype_list[0]["mediatypeid"]
except Exception as e:
self._module.fail_json(msg="Failed to get mediatype '%s': %s" % (mediatype_name, e))
@@ -815,13 +1061,10 @@ class Zapi(ZabbixBase):
"""
try:
- if LooseVersion(self._zbx_api_version) >= LooseVersion('5.4'):
- filter = {'username': [user_name]}
- else:
- filter = {'alias': [user_name]}
+ filter = {"username": [user_name]}
user_list = self._zapi.user.get({
- 'output': 'extend',
- 'filter': filter,
+ "output": "extend",
+ "filter": filter,
})
if len(user_list) < 1:
self._module.fail_json(msg="User not found: %s" % user_name)
@@ -842,8 +1085,8 @@ class Zapi(ZabbixBase):
"""
try:
usergroup_list = self._zapi.usergroup.get({
- 'output': 'extend',
- 'filter': {'name': [usergroup_name]}
+ "output": "extend",
+ "filter": {"name": [usergroup_name]}
})
if len(usergroup_list) < 1:
self._module.fail_json(msg="User group not found: %s" % usergroup_name)
@@ -867,8 +1110,8 @@ class Zapi(ZabbixBase):
if script_name is None:
return {}
script_list = self._zapi.script.get({
- 'output': 'extend',
- 'filter': {'name': [script_name]}
+ "output": "extend",
+ "filter": {"name": [script_name]}
})
if len(script_list) < 1:
self._module.fail_json(msg="Script not found: %s" % script_name)
@@ -894,72 +1137,50 @@ class Action(Zapi):
"""
_params = {
- 'name': kwargs['name'],
- 'eventsource': zabbix_utils.helper_to_numeric_value([
- 'trigger',
- 'discovery',
- 'auto_registration',
- 'internal'], kwargs['event_source']),
- 'esc_period': kwargs.get('esc_period'),
- 'filter': kwargs['conditions'],
- 'def_longdata': kwargs['default_message'],
- 'def_shortdata': kwargs['default_subject'],
- 'r_longdata': kwargs['recovery_default_message'],
- 'r_shortdata': kwargs['recovery_default_subject'],
- 'ack_longdata': kwargs['acknowledge_default_message'],
- 'ack_shortdata': kwargs['acknowledge_default_subject'],
- 'operations': kwargs['operations'],
- 'recovery_operations': kwargs.get('recovery_operations'),
- 'acknowledge_operations': kwargs.get('acknowledge_operations'),
- 'status': zabbix_utils.helper_to_numeric_value([
- 'enabled',
- 'disabled'], kwargs['status'])
+ "name": kwargs["name"],
+ "eventsource": zabbix_utils.helper_to_numeric_value([
+ "trigger",
+ "discovery",
+ "auto_registration",
+ "internal"], kwargs["event_source"]),
+ "esc_period": kwargs.get("esc_period"),
+ "filter": kwargs["conditions"],
+ "operations": kwargs["operations"],
+ "recovery_operations": kwargs.get("recovery_operations"),
+ "acknowledge_operations": kwargs.get("acknowledge_operations"),
+ "status": zabbix_utils.helper_to_numeric_value([
+ "enabled",
+ "disabled"], kwargs["status"])
}
- if kwargs['event_source'] == 'trigger':
- if LooseVersion(self._zbx_api_version) >= LooseVersion('4.0'):
- _params['pause_suppressed'] = '1' if kwargs['pause_in_maintenance'] else '0'
- else:
- _params['maintenance_mode'] = '1' if kwargs['pause_in_maintenance'] else '0'
- if LooseVersion(self._zbx_api_version) >= LooseVersion('6.4'):
- _params['pause_symptoms'] = '1' if kwargs['pause_symptoms'] else '0'
-
- if LooseVersion(self._zbx_api_version) >= LooseVersion('5.0'):
- # remove some fields regarding
- # https://www.zabbix.com/documentation/5.0/manual/api/reference/action/object
- _params.pop('def_longdata', None)
- _params.pop('def_shortdata', None)
- _params.pop('r_longdata', None)
- _params.pop('r_shortdata', None)
-
- if (LooseVersion(self._zbx_api_version) < LooseVersion('3.4')
- or LooseVersion(self._zbx_api_version) >= LooseVersion('5.0')):
- _params.pop('ack_longdata', None)
- _params.pop('ack_shortdata', None)
-
- if LooseVersion(self._zbx_api_version) >= LooseVersion('6.0'):
- _params['update_operations'] = kwargs.get('update_operations')
- if 'update_operations' in _params and not isinstance(_params.get('update_operations', None), type(None)):
- _params.pop('acknowledge_operations', None)
- elif isinstance(_params.get('acknowledge_operations', None), list):
- _params['update_operations'] = _params.pop('acknowledge_operations', [])
- else:
- _params['update_operations'] = []
- _params.pop('acknowledge_operations', None)
+ if kwargs["event_source"] == "trigger":
+ _params["pause_suppressed"] = "1" if kwargs["pause_in_maintenance"] else "0"
+ if LooseVersion(self._zbx_api_version) >= LooseVersion("6.4"):
+ _params["pause_symptoms"] = "1" if kwargs["pause_symptoms"] else "0"
+ _params["notify_if_canceled"] = "1" if kwargs["notify_if_canceled"] else "0"
+
+ _params["update_operations"] = kwargs.get("update_operations")
+ if "update_operations" in _params and not isinstance(_params.get("update_operations", None), type(None)):
+ _params.pop("acknowledge_operations", None)
+ elif isinstance(_params.get("acknowledge_operations", None), list):
+ _params["update_operations"] = _params.pop("acknowledge_operations", [])
+ else:
+ _params["update_operations"] = []
+ _params.pop("acknowledge_operations", None)
- if 'esc_period' in _params and isinstance(_params.get('esc_period', None), type(None)):
- _params.pop('esc_period')
+ if "esc_period" in _params and isinstance(_params.get("esc_period", None), type(None)):
+ _params.pop("esc_period")
- if 'recovery_operations' in _params:
- if isinstance(_params.get('recovery_operations', None), type(None)) or len(_params.get('recovery_operations', [])) == 0:
- _params.pop('recovery_operations')
+ if "recovery_operations" in _params:
+ if isinstance(_params.get("recovery_operations", None), type(None)) or len(_params.get("recovery_operations", [])) == 0:
+ _params.pop("recovery_operations")
- if 'update_operations' in _params:
- if isinstance(_params.get('update_operations', None), type(None)) or len(_params.get('update_operations', [])) == 0:
- _params.pop('update_operations')
+ if "update_operations" in _params:
+ if isinstance(_params.get("update_operations", None), type(None)) or len(_params.get("update_operations", [])) == 0:
+ _params.pop("update_operations")
- if _params['eventsource'] not in [0, 3]:
- _params.pop('esc_period')
+ if _params["eventsource"] not in [0, 3]:
+ _params.pop("esc_period")
return _params
@@ -972,7 +1193,7 @@ class Action(Zapi):
Returns:
dict: dictionary of differences
"""
- existing_action = zabbix_utils.helper_convert_unicode_to_str(self.check_if_action_exists(kwargs['name'])[0])
+ existing_action = zabbix_utils.helper_convert_unicode_to_str(self.check_if_action_exists(kwargs["name"])[0])
parameters = zabbix_utils.helper_convert_unicode_to_str(self._construct_parameters(**kwargs))
change_parameters = {}
_diff = zabbix_utils.helper_cleanup_data(zabbix_utils.helper_compare_dictionaries(parameters, existing_action, change_parameters))
@@ -990,10 +1211,10 @@ class Action(Zapi):
try:
if self._module.check_mode:
self._module.exit_json(msg="Action would be updated if check mode was not specified: %s" % kwargs, changed=True)
- kwargs['actionid'] = kwargs.pop('action_id')
+ kwargs["actionid"] = kwargs.pop("action_id")
return self._zapi.action.update(kwargs)
except Exception as e:
- self._module.fail_json(msg="Failed to update action '%s': %s" % (kwargs['actionid'], e))
+ self._module.fail_json(msg="Failed to update action '%s': %s" % (kwargs["actionid"], e))
def add_action(self, **kwargs):
"""Add action.
@@ -1009,9 +1230,9 @@ class Action(Zapi):
self._module.exit_json(msg="Action would be added if check mode was not specified", changed=True)
parameters = self._construct_parameters(**kwargs)
action_list = self._zapi.action.create(parameters)
- return action_list['actionids'][0]
+ return action_list["actionids"][0]
except Exception as e:
- self._module.fail_json(msg="Failed to create action '%s': %s" % (kwargs['name'], e))
+ self._module.fail_json(msg="Failed to create action '%s': %s" % (kwargs["name"], e))
def delete_action(self, action_id):
"""Delete action.
@@ -1052,10 +1273,11 @@ class Operations(Zapi):
"unlink_from_template",
"enable_host",
"disable_host",
- "set_host_inventory_mode"], operation['type']
+ "set_host_inventory_mode"],
+ operation["type"]
)
except Exception:
- self._module.fail_json(msg="Unsupported value '%s' for operation type." % operation['type'])
+ self._module.fail_json(msg="Unsupported value '%s' for operation type." % operation["type"])
def _construct_opmessage(self, operation):
"""Construct operation message.
@@ -1068,12 +1290,12 @@ class Operations(Zapi):
"""
try:
return {
- 'default_msg': '0' if operation.get('message') is not None or operation.get('subject') is not None else '1',
- 'mediatypeid': self._zapi_wrapper.get_mediatype_by_mediatype_name(
- operation.get('media_type')
- ) if operation.get('media_type') is not None else '0',
- 'message': operation.get('message'),
- 'subject': operation.get('subject'),
+ "default_msg": "0" if operation.get("op_message") is not None or operation.get("subject") is not None else "1",
+ "mediatypeid": self._zapi_wrapper.get_mediatype_by_mediatype_name(
+ operation.get("media_type")
+ ) if operation.get("media_type") is not None else "0",
+ "message": operation.get("op_message"),
+ "subject": operation.get("subject"),
}
except Exception as e:
self._module.fail_json(msg="Failed to construct operation message. The error was: %s" % e)
@@ -1087,11 +1309,11 @@ class Operations(Zapi):
Returns:
list: constructed operation message user or None if operation not found
"""
- if operation.get('send_to_users') is None:
+ if operation.get("send_to_users") is None:
return None
return [{
- 'userid': self._zapi_wrapper.get_user_by_user_name(_user)['userid']
- } for _user in operation.get('send_to_users')]
+ "userid": self._zapi_wrapper.get_user_by_user_name(_user)["userid"]
+ } for _user in operation.get("send_to_users")]
def _construct_opmessage_grp(self, operation):
"""Construct operation message group.
@@ -1102,11 +1324,11 @@ class Operations(Zapi):
Returns:
list: constructed operation message group or None if operation not found
"""
- if operation.get('send_to_groups') is None:
+ if operation.get("send_to_groups") is None:
return None
return [{
- 'usrgrpid': self._zapi_wrapper.get_usergroup_by_usergroup_name(_group)['usrgrpid']
- } for _group in operation.get('send_to_groups')]
+ "usrgrpid": self._zapi_wrapper.get_usergroup_by_usergroup_name(_group)["usrgrpid"]
+ } for _group in operation.get("send_to_groups")]
def _construct_opcommand(self, operation):
"""Construct operation command.
@@ -1118,39 +1340,11 @@ class Operations(Zapi):
list: constructed operation command
"""
try:
- if LooseVersion(self._zbx_api_version) < LooseVersion('6.0'):
- opcommand = {
- 'type': zabbix_utils.helper_to_numeric_value([
- 'custom_script',
- 'ipmi',
- 'ssh',
- 'telnet',
- 'global_script'], operation.get('command_type', 'custom_script')),
- 'command': operation.get('command'),
- 'execute_on': zabbix_utils.helper_to_numeric_value([
- 'agent',
- 'server',
- 'proxy'], operation.get('execute_on', 'server')),
- 'scriptid': self._zapi_wrapper.get_script_by_script_name(
- operation.get('script_name')
- ).get('scriptid'),
- 'authtype': zabbix_utils.helper_to_numeric_value([
- 'password',
- 'public_key'
- ], operation.get('ssh_auth_type')),
- 'privatekey': operation.get('ssh_privatekey_file'),
- 'publickey': operation.get('ssh_publickey_file'),
- 'username': operation.get('username'),
- 'password': operation.get('password'),
- 'port': operation.get('port')
- }
- else:
- # In 6.0 opcommand is an opbject with just one key 'scriptid'
- opcommand = {
- 'scriptid': self._zapi_wrapper.get_script_by_script_name(
- operation.get('script_name')
- ).get('scriptid')
- }
+ opcommand = {
+ "scriptid": self._zapi_wrapper.get_script_by_script_name(
+ operation.get("script_name")
+ ).get("scriptid")
+ }
return opcommand
@@ -1166,11 +1360,11 @@ class Operations(Zapi):
Returns:
list: constructed operation command host
"""
- if operation.get('run_on_hosts') is None:
+ if operation.get("run_on_hosts") is None:
return None
return [{
- 'hostid': self._zapi_wrapper.get_host_by_host_name(_host)['hostid']
- } if str(_host) != '0' else {'hostid': '0'} for _host in operation.get('run_on_hosts')]
+ "hostid": self._zapi_wrapper.get_host_by_host_name(_host)["hostid"]
+ } if str(_host) != "0" else {"hostid": "0"} for _host in operation.get("run_on_hosts")]
def _construct_opcommand_grp(self, operation):
"""Construct operation command group.
@@ -1181,11 +1375,11 @@ class Operations(Zapi):
Returns:
list: constructed operation command group
"""
- if operation.get('run_on_groups') is None:
+ if operation.get("run_on_groups") is None:
return None
return [{
- 'groupid': self._zapi_wrapper.get_hostgroup_by_hostgroup_name(_group)['groupid']
- } for _group in operation.get('run_on_groups')]
+ "groupid": self._zapi_wrapper.get_hostgroup_by_hostgroup_name(_group)["groupid"]
+ } for _group in operation.get("run_on_groups")]
def _construct_opgroup(self, operation):
"""Construct operation group.
@@ -1197,8 +1391,8 @@ class Operations(Zapi):
list: constructed operation group
"""
return [{
- 'groupid': self._zapi_wrapper.get_hostgroup_by_hostgroup_name(_group)['groupid']
- } for _group in operation.get('host_groups', [])]
+ "groupid": self._zapi_wrapper.get_hostgroup_by_hostgroup_name(_group)["groupid"]
+ } for _group in operation.get("host_groups", [])]
def _construct_optemplate(self, operation):
"""Construct operation template.
@@ -1210,8 +1404,8 @@ class Operations(Zapi):
list: constructed operation template
"""
return [{
- 'templateid': self._zapi_wrapper.get_template_by_template_name(_template)['templateid']
- } for _template in operation.get('templates', [])]
+ "templateid": self._zapi_wrapper.get_template_by_template_name(_template)["templateid"]
+ } for _template in operation.get("templates", [])]
def _construct_opinventory(self, operation):
"""Construct operation inventory.
@@ -1223,10 +1417,10 @@ class Operations(Zapi):
dict: constructed operation inventory
"""
return {
- 'inventory_mode': zabbix_utils.helper_to_numeric_value([
- 'manual',
- 'automatic'
- ], operation.get('inventory'))
+ "inventory_mode": zabbix_utils.helper_to_numeric_value([
+ "manual",
+ "automatic"
+ ], operation.get("inventory"))
}
def _construct_opconditions(self, operation):
@@ -1238,16 +1432,16 @@ class Operations(Zapi):
Returns:
list: constructed operation conditions
"""
- _opcond = operation.get('operation_condition')
+ _opcond = operation.get("operation_condition")
if _opcond is not None:
- if _opcond == 'acknowledged':
- _value = '1'
- elif _opcond == 'not_acknowledged':
- _value = '0'
+ if _opcond == "acknowledged":
+ _value = "1"
+ elif _opcond == "not_acknowledged":
+ _value = "0"
return [{
- 'conditiontype': '14',
- 'operator': '0',
- 'value': _value
+ "conditiontype": "14",
+ "operator": "0",
+ "value": _value
}]
return []
@@ -1264,49 +1458,49 @@ class Operations(Zapi):
for op in operations:
operation_type = self._construct_operationtype(op)
constructed_operation = {
- 'operationtype': operation_type,
- 'esc_period': op.get('esc_period'),
- 'esc_step_from': op.get('esc_step_from'),
- 'esc_step_to': op.get('esc_step_to')
+ "operationtype": operation_type,
+ "esc_period": op.get("esc_period"),
+ "esc_step_from": op.get("esc_step_from"),
+ "esc_step_to": op.get("esc_step_to")
}
# Send Message type
- if constructed_operation['operationtype'] == 0:
- constructed_operation['opmessage'] = self._construct_opmessage(op)
- constructed_operation['opmessage_usr'] = self._construct_opmessage_usr(op)
- constructed_operation['opmessage_grp'] = self._construct_opmessage_grp(op)
- if event_source == 'trigger':
- # opconditions valid only for 'trigger' action
- constructed_operation['opconditions'] = self._construct_opconditions(op)
+ if constructed_operation["operationtype"] == 0:
+ constructed_operation["opmessage"] = self._construct_opmessage(op)
+ constructed_operation["opmessage_usr"] = self._construct_opmessage_usr(op)
+ constructed_operation["opmessage_grp"] = self._construct_opmessage_grp(op)
+ if event_source == "trigger":
+ # opconditions valid only for "trigger" action
+ constructed_operation["opconditions"] = self._construct_opconditions(op)
# Send Command type
- if constructed_operation['operationtype'] == 1:
- constructed_operation['opcommand'] = self._construct_opcommand(op)
- constructed_operation['opcommand_hst'] = self._construct_opcommand_hst(op)
- constructed_operation['opcommand_grp'] = self._construct_opcommand_grp(op)
- if event_source == 'trigger':
- # opconditions valid only for 'trigger' action
- constructed_operation['opconditions'] = self._construct_opconditions(op)
+ if constructed_operation["operationtype"] == 1:
+ constructed_operation["opcommand"] = self._construct_opcommand(op)
+ constructed_operation["opcommand_hst"] = self._construct_opcommand_hst(op)
+ constructed_operation["opcommand_grp"] = self._construct_opcommand_grp(op)
+ if event_source == "trigger":
+ # opconditions valid only for "trigger" action
+ constructed_operation["opconditions"] = self._construct_opconditions(op)
# Add to/Remove from host group
- if constructed_operation['operationtype'] in (4, 5):
- constructed_operation['opgroup'] = self._construct_opgroup(op)
+ if constructed_operation["operationtype"] in (4, 5):
+ constructed_operation["opgroup"] = self._construct_opgroup(op)
# Link/Unlink template
- if constructed_operation['operationtype'] in (6, 7):
- constructed_operation['optemplate'] = self._construct_optemplate(op)
+ if constructed_operation["operationtype"] in (6, 7):
+ constructed_operation["optemplate"] = self._construct_optemplate(op)
# Set inventory mode
- if constructed_operation['operationtype'] == 10:
- constructed_operation['opinventory'] = self._construct_opinventory(op)
+ if constructed_operation["operationtype"] == 10:
+ constructed_operation["opinventory"] = self._construct_opinventory(op)
# Remove escalation params when for event sources where they are not applicable
- if event_source in ['trigger', 'internal']:
- if isinstance(constructed_operation.get('esc_period'), type(None)):
- constructed_operation['esc_period'] = 0
+ if event_source in ["trigger", "internal"]:
+ if isinstance(constructed_operation.get("esc_period"), type(None)):
+ constructed_operation["esc_period"] = 0
else:
- constructed_operation.pop('esc_period')
- constructed_operation.pop('esc_step_from')
- constructed_operation.pop('esc_step_to')
+ constructed_operation.pop("esc_period")
+ constructed_operation.pop("esc_step_from")
+ constructed_operation.pop("esc_step_to")
constructed_data.append(constructed_operation)
@@ -1317,6 +1511,7 @@ class RecoveryOperations(Operations):
"""
Restructures the user defined recovery operations data to fit the Zabbix API requirements
"""
+
def _construct_operationtype(self, operation):
"""Construct operation type.
@@ -1339,10 +1534,10 @@ class RecoveryOperations(Operations):
None,
None,
None,
- "notify_all_involved"], operation['type']
+ "notify_all_involved"], operation["type"]
)
except Exception:
- self._module.fail_json(msg="Unsupported value '%s' for recovery operation type." % operation['type'])
+ self._module.fail_json(msg="Unsupported value '%s' for recovery operation type." % operation["type"])
def construct_the_data(self, operations):
"""Construct the recovery operations data using helper methods.
@@ -1357,25 +1552,24 @@ class RecoveryOperations(Operations):
for op in operations:
operation_type = self._construct_operationtype(op)
constructed_operation = {
- 'operationtype': operation_type,
+ "operationtype": operation_type,
}
# Send Message type
- if constructed_operation['operationtype'] == 0:
- constructed_operation['opmessage'] = self._construct_opmessage(op)
- constructed_operation['opmessage_usr'] = self._construct_opmessage_usr(op)
- constructed_operation['opmessage_grp'] = self._construct_opmessage_grp(op)
+ if constructed_operation["operationtype"] == 0:
+ constructed_operation["opmessage"] = self._construct_opmessage(op)
+ constructed_operation["opmessage_usr"] = self._construct_opmessage_usr(op)
+ constructed_operation["opmessage_grp"] = self._construct_opmessage_grp(op)
- if constructed_operation['operationtype'] == 11:
- constructed_operation['opmessage'] = self._construct_opmessage(op)
- if LooseVersion(self._zbx_api_version) >= LooseVersion('6.0'):
- constructed_operation['opmessage'].pop('mediatypeid')
+ if constructed_operation["operationtype"] == 11:
+ constructed_operation["opmessage"] = self._construct_opmessage(op)
+ constructed_operation["opmessage"].pop("mediatypeid")
# Send Command type
- if constructed_operation['operationtype'] == 1:
- constructed_operation['opcommand'] = self._construct_opcommand(op)
- constructed_operation['opcommand_hst'] = self._construct_opcommand_hst(op)
- constructed_operation['opcommand_grp'] = self._construct_opcommand_grp(op)
+ if constructed_operation["operationtype"] == 1:
+ constructed_operation["opcommand"] = self._construct_opcommand(op)
+ constructed_operation["opcommand_hst"] = self._construct_opcommand_hst(op)
+ constructed_operation["opcommand_grp"] = self._construct_opcommand_grp(op)
constructed_data.append(constructed_operation)
@@ -1386,6 +1580,7 @@ class AcknowledgeOperations(Operations):
"""
Restructures the user defined acknowledge operations data to fit the Zabbix API requirements
"""
+
def _construct_operationtype(self, operation):
"""Construct operation type.
@@ -1409,10 +1604,10 @@ class AcknowledgeOperations(Operations):
None,
None,
None,
- "notify_all_involved"], operation['type']
+ "notify_all_involved"], operation["type"]
)
except Exception:
- self._module.fail_json(msg="Unsupported value '%s' for acknowledge operation type." % operation['type'])
+ self._module.fail_json(msg="Unsupported value '%s' for acknowledge operation type." % operation["type"])
def construct_the_data(self, operations):
"""Construct the acknowledge operations data using helper methods.
@@ -1427,25 +1622,24 @@ class AcknowledgeOperations(Operations):
for op in operations:
operation_type = self._construct_operationtype(op)
constructed_operation = {
- 'operationtype': operation_type,
+ "operationtype": operation_type,
}
# Send Message type
- if constructed_operation['operationtype'] == 0:
- constructed_operation['opmessage'] = self._construct_opmessage(op)
- constructed_operation['opmessage_usr'] = self._construct_opmessage_usr(op)
- constructed_operation['opmessage_grp'] = self._construct_opmessage_grp(op)
+ if constructed_operation["operationtype"] == 0:
+ constructed_operation["opmessage"] = self._construct_opmessage(op)
+ constructed_operation["opmessage_usr"] = self._construct_opmessage_usr(op)
+ constructed_operation["opmessage_grp"] = self._construct_opmessage_grp(op)
- if constructed_operation['operationtype'] == 12:
- constructed_operation['opmessage'] = self._construct_opmessage(op)
- if LooseVersion(self._zbx_api_version) >= LooseVersion('6.0'):
- constructed_operation['opmessage'].pop('mediatypeid')
+ if constructed_operation["operationtype"] == 12:
+ constructed_operation["opmessage"] = self._construct_opmessage(op)
+ constructed_operation["opmessage"].pop("mediatypeid")
# Send Command type
- if constructed_operation['operationtype'] == 1:
- constructed_operation['opcommand'] = self._construct_opcommand(op)
- constructed_operation['opcommand_hst'] = self._construct_opcommand_hst(op)
- constructed_operation['opcommand_grp'] = self._construct_opcommand_grp(op)
+ if constructed_operation["operationtype"] == 1:
+ constructed_operation["opcommand"] = self._construct_opcommand(op)
+ constructed_operation["opcommand_hst"] = self._construct_opcommand_hst(op)
+ constructed_operation["opcommand_grp"] = self._construct_opcommand_grp(op)
constructed_data.append(constructed_operation)
@@ -1465,40 +1659,40 @@ class Filter(Zapi):
"""
if len(_conditions) <= 1:
return {
- 'evaltype': '0',
- 'formula': None
+ "evaltype": "0",
+ "formula": None
}
- if _eval_type == 'andor':
+ if _eval_type == "andor":
return {
- 'evaltype': '0',
- 'formula': None
+ "evaltype": "0",
+ "formula": None
}
- if _eval_type == 'and':
+ if _eval_type == "and":
return {
- 'evaltype': '1',
- 'formula': None
+ "evaltype": "1",
+ "formula": None
}
- if _eval_type == 'or':
+ if _eval_type == "or":
return {
- 'evaltype': '2',
- 'formula': None
+ "evaltype": "2",
+ "formula": None
}
- if _eval_type == 'custom_expression':
+ if _eval_type == "custom_expression":
if _formula is not None:
return {
- 'evaltype': '3',
- 'formula': _formula
+ "evaltype": "3",
+ "formula": _formula
}
else:
self._module.fail_json(msg="'formula' is required when 'eval_type' is set to 'custom_expression'")
if _formula is not None:
return {
- 'evaltype': '3',
- 'formula': _formula
+ "evaltype": "3",
+ "formula": _formula
}
return {
- 'evaltype': '0',
- 'formula': None
+ "evaltype": "0",
+ "formula": None
}
def _construct_conditiontype(self, _condition):
@@ -1510,11 +1704,6 @@ class Filter(Zapi):
Returns:
str: constructed condition type data
"""
- # application is disabled is disabled for condition type since 5.4 version.
- if (LooseVersion(self._zbx_api_version) >= LooseVersion('5.4')
- and _condition['type'] == 'application'):
- self._module.fail_json(msg="'%s' is disabled for condition type since 5.4 version." % _condition['type'])
-
try:
return zabbix_utils.helper_to_numeric_value([
"host_group",
@@ -1532,7 +1721,7 @@ class Filter(Zapi):
"received_value",
"host_template",
None,
- "application",
+ None,
"maintenance_status",
None,
"discovery_rule",
@@ -1543,10 +1732,10 @@ class Filter(Zapi):
"event_type",
"host_metadata",
"event_tag",
- "event_tag_value"], _condition['type']
+ "event_tag_value"], _condition["type"]
)
except Exception:
- self._module.fail_json(msg="Unsupported value '%s' for condition type." % _condition['type'])
+ self._module.fail_json(msg="Unsupported value '%s' for condition type." % _condition["type"])
def _construct_operator(self, _condition):
"""Construct operator
@@ -1570,10 +1759,10 @@ class Filter(Zapi):
"matches",
"does not match",
"Yes",
- "No"], _condition['operator']
+ "No"], _condition["operator"]
)
except Exception:
- self._module.fail_json(msg="Unsupported value '%s' for operator." % _condition['operator'])
+ self._module.fail_json(msg="Unsupported value '%s' for operator." % _condition["operator"])
def _construct_value(self, conditiontype, value):
"""Construct operator
@@ -1588,13 +1777,13 @@ class Filter(Zapi):
try:
# Host group
if conditiontype == 0:
- return self._zapi_wrapper.get_hostgroup_by_hostgroup_name(value)['groupid']
+ return self._zapi_wrapper.get_hostgroup_by_hostgroup_name(value)["groupid"]
# Host
if conditiontype == 1:
- return self._zapi_wrapper.get_host_by_host_name(value)['hostid']
+ return self._zapi_wrapper.get_host_by_host_name(value)["hostid"]
# Trigger
if conditiontype == 2:
- return self._zapi_wrapper.get_trigger_by_trigger_name(value)['triggerid']
+ return self._zapi_wrapper.get_trigger_by_trigger_name(value)["triggerid"]
# Trigger name: return as is
# Trigger severity
if conditiontype == 4:
@@ -1645,20 +1834,19 @@ class Filter(Zapi):
"lost"], value
)
if conditiontype == 13:
- return self._zapi_wrapper.get_template_by_template_name(value)['templateid']
- if LooseVersion(self._zapi_wrapper._zbx_api_version) >= LooseVersion('6.0'):
- # maintenance_status
- if conditiontype == 16:
- return zabbix_utils.helper_to_numeric_value([
- "Yes",
- "No"], value
- )
+ return self._zapi_wrapper.get_template_by_template_name(value)["templateid"]
+ # maintenance_status
+ if conditiontype == 16:
+ return zabbix_utils.helper_to_numeric_value([
+ "Yes",
+ "No"], value
+ )
if conditiontype == 18:
- return self._zapi_wrapper.get_discovery_rule_by_discovery_rule_name(value)['druleid']
+ return self._zapi_wrapper.get_discovery_rule_by_discovery_rule_name(value)["druleid"]
if conditiontype == 19:
- return self._zapi_wrapper.get_discovery_check_by_discovery_check_name(value)['dcheckid']
+ return self._zapi_wrapper.get_discovery_check_by_discovery_check_name(value)["dcheckid"]
if conditiontype == 20:
- return self._zapi_wrapper.get_proxy_by_proxy_name(value)['proxyid']
+ return self._zapi_wrapper.get_proxy_by_proxy_name(value)["proxyid"]
if conditiontype == 21:
return zabbix_utils.helper_to_numeric_value([
"pchldrfor0",
@@ -1697,10 +1885,10 @@ class Filter(Zapi):
if _conditions is None:
return None
constructed_data = {}
- constructed_data['conditions'] = []
+ constructed_data["conditions"] = []
for cond in _conditions:
condition_type = self._construct_conditiontype(cond)
- constructed_data['conditions'].append({
+ constructed_data["conditions"].append({
"conditiontype": condition_type,
"value": self._construct_value(condition_type, cond.get("value")),
"value2": cond.get("value2"),
@@ -1710,10 +1898,10 @@ class Filter(Zapi):
_constructed_evaltype = self._construct_evaltype(
_eval_type,
_formula,
- constructed_data['conditions']
+ constructed_data["conditions"]
)
- constructed_data['evaltype'] = _constructed_evaltype['evaltype']
- constructed_data['formula'] = _constructed_evaltype['formula']
+ constructed_data["evaltype"] = _constructed_evaltype["evaltype"]
+ constructed_data["formula"] = _constructed_evaltype["formula"]
return zabbix_utils.helper_cleanup_data(constructed_data)
@@ -1723,300 +1911,308 @@ def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- esc_period=dict(type='str', required=False),
- name=dict(type='str', required=True),
- event_source=dict(type='str', required=False, choices=['trigger', 'discovery', 'auto_registration', 'internal']),
- state=dict(type='str', required=False, default='present', choices=['present', 'absent']),
- status=dict(type='str', required=False, default='enabled', choices=['enabled', 'disabled']),
- pause_in_maintenance=dict(type='bool', required=False, default=True),
- default_message=dict(type='str', required=False, default=''),
- default_subject=dict(type='str', required=False, default=''),
- recovery_default_message=dict(type='str', required=False, default=''),
- recovery_default_subject=dict(type='str', required=False, default=''),
- acknowledge_default_message=dict(type='str', required=False, default=''),
- acknowledge_default_subject=dict(type='str', required=False, default=''),
+ esc_period=dict(type="str", required=False),
+ name=dict(type="str", required=True),
+ event_source=dict(type="str", required=False, choices=["trigger", "discovery", "auto_registration", "internal"]),
+ state=dict(type="str", required=False, default="present", choices=["present", "absent"]),
+ status=dict(type="str", required=False, default="enabled", choices=["enabled", "disabled"]),
+ pause_in_maintenance=dict(type="bool", required=False, default=True),
conditions=dict(
- type='list',
+ type="list",
required=False,
default=[],
- elements='dict',
+ elements="dict",
options=dict(
- formulaid=dict(type='str', required=False),
- operator=dict(type='str', required=True),
- type=dict(type='str', required=True),
- value=dict(type='str', required=False),
- value2=dict(type='str', required=False)
+ formulaid=dict(type="str", required=False),
+ operator=dict(
+ type="str",
+ required=True,
+ choices=[
+ "equals",
+ "=",
+ "does not equal",
+ "<>",
+ "contains",
+ "like",
+ "does not contain",
+ "not like",
+ "in",
+ "is greater than or equals",
+ ">=",
+ "is less than or equals",
+ "<=",
+ "not in",
+ "matches",
+ "does not match",
+ "Yes",
+ "No"
+ ]
+ ),
+ type=dict(type="str", required=True),
+ value=dict(type="str", required=False),
+ value2=dict(type="str", required=False)
),
required_if=[
- ['type', 'event_tag_value', ['value2']],
+ ["type", "event_tag_value", ["value2"]],
]
),
- formula=dict(type='str', required=False, default=None),
- eval_type=dict(type='str', required=False, default=None, choices=['andor', 'and', 'or', 'custom_expression']),
+ formula=dict(type="str", required=False, default=None),
+ eval_type=dict(type="str", required=False, default=None, choices=["andor", "and", "or", "custom_expression"]),
operations=dict(
- type='list',
+ type="list",
required=False,
default=[],
- elements='dict',
+ elements="dict",
options=dict(
type=dict(
- type='str',
+ type="str",
required=True,
choices=[
- 'send_message',
- 'remote_command',
- 'add_host',
- 'remove_host',
- 'add_to_host_group',
- 'remove_from_host_group',
- 'link_to_template',
- 'unlink_from_template',
- 'enable_host',
- 'disable_host',
- 'set_host_inventory_mode',
+ "send_message",
+ "remote_command",
+ "add_host",
+ "remove_host",
+ "add_to_host_group",
+ "remove_from_host_group",
+ "link_to_template",
+ "unlink_from_template",
+ "enable_host",
+ "disable_host",
+ "set_host_inventory_mode",
+ "notify_all_involved"
]
),
- esc_period=dict(type='str', required=False),
- esc_step_from=dict(type='int', required=False, default=1),
- esc_step_to=dict(type='int', required=False, default=1),
+ esc_period=dict(type="str", required=False, default="0s"),
+ esc_step_from=dict(type="int", required=False, default=1),
+ esc_step_to=dict(type="int", required=False, default=1),
operation_condition=dict(
- type='str',
+ type="str",
required=False,
default=None,
- choices=['acknowledged', 'not_acknowledged']
+ choices=["acknowledged", "not_acknowledged"]
),
# when type is remote_command
command_type=dict(
- type='str',
+ type="str",
required=False,
choices=[
- 'custom_script',
- 'ipmi',
- 'ssh',
- 'telnet',
- 'global_script'
+ "custom_script",
+ "ipmi",
+ "ssh",
+ "telnet",
+ "global_script"
]
),
- command=dict(type='str', required=False),
+ command=dict(type="str", required=False),
execute_on=dict(
- type='str',
+ type="str",
required=False,
- choices=['agent', 'server', 'proxy']
+ choices=["agent", "server", "proxy"]
),
- password=dict(type='str', required=False, no_log=True),
- port=dict(type='int', required=False),
- run_on_groups=dict(type='list', required=False),
- run_on_hosts=dict(type='list', required=False),
- script_name=dict(type='str', required=False),
- ssh_auth_type=dict(type='str', required=False, choices=['password', 'public_key']),
- ssh_privatekey_file=dict(type='str', required=False),
- ssh_publickey_file=dict(type='str', required=False),
- username=dict(type='str', required=False),
+ password=dict(type="str", required=False, no_log=True),
+ port=dict(type="int", required=False),
+ run_on_groups=dict(type="list", required=False, elements="str"),
+ run_on_hosts=dict(type="list", required=False, elements="str"),
+ script_name=dict(type="str", required=False),
+ ssh_auth_type=dict(type="str", required=False, choices=["password", "public_key"]),
+ ssh_privatekey_file=dict(type="str", required=False),
+ ssh_publickey_file=dict(type="str", required=False),
+ username=dict(type="str", required=False),
# when type is send_message
- media_type=dict(type='str', required=False),
- subject=dict(type='str', required=False),
- message=dict(type='str', required=False),
- send_to_groups=dict(type='list', required=False),
- send_to_users=dict(type='list', required=False),
+ media_type=dict(type="str", required=False, default="all"),
+ subject=dict(type="str", required=False),
+ op_message=dict(type="str", required=False),
+ send_to_groups=dict(type="list", required=False, elements="str"),
+ send_to_users=dict(type="list", required=False, elements="str"),
# when type is add_to_host_group or remove_from_host_group
- host_groups=dict(type='list', required=False),
+ host_groups=dict(type="list", required=False, elements="str"),
# when type is set_host_inventory_mode
- inventory=dict(type='str', required=False, choices=['manual', 'automatic']),
+ inventory=dict(type="str", required=False, choices=["manual", "automatic"]),
# when type is link_to_template or unlink_from_template
- templates=dict(type='list', required=False)
+ templates=dict(type="list", required=False, elements="str")
),
required_if=[
- ['type', 'remote_command', ['command_type']],
- ['type', 'remote_command', ['run_on_groups', 'run_on_hosts'], True],
- ['command_type', 'custom_script', ['command', 'execute_on']],
- ['command_type', 'ipmi', ['command']],
- ['command_type', 'ssh', ['command', 'ssh_auth_type']],
- ['ssh_auth_type', 'password', ['username', 'password']],
- ['ssh_auth_type', 'public_key', ['username', 'ssh_privatekey_file', 'ssh_publickey_file']],
- ['command_type', 'telnet', ['command', 'username', 'password']],
- ['command_type', 'global_script', ['script_name']],
- ['type', 'add_to_host_group', ['host_groups']],
- ['type', 'remove_from_host_group', ['host_groups']],
- ['type', 'link_to_template', ['templates']],
- ['type', 'unlink_from_template', ['templates']],
- ['type', 'set_host_inventory_mode', ['inventory']],
- ['type', 'send_message', ['send_to_users', 'send_to_groups'], True]
+ ["type", "remote_command", ["command_type"]],
+ ["type", "remote_command", ["run_on_groups", "run_on_hosts"], True],
+ ["command_type", "custom_script", ["command", "execute_on"]],
+ ["command_type", "ipmi", ["command"]],
+ ["command_type", "ssh", ["command", "ssh_auth_type"]],
+ ["ssh_auth_type", "password", ["username", "password"]],
+ ["ssh_auth_type", "public_key", ["username", "ssh_privatekey_file", "ssh_publickey_file"]],
+ ["command_type", "telnet", ["command", "username", "password"]],
+ ["command_type", "global_script", ["script_name"]],
+ ["type", "add_to_host_group", ["host_groups"]],
+ ["type", "remove_from_host_group", ["host_groups"]],
+ ["type", "link_to_template", ["templates"]],
+ ["type", "unlink_from_template", ["templates"]],
+ ["type", "set_host_inventory_mode", ["inventory"]],
+ ["type", "send_message", ["send_to_users", "send_to_groups"], True]
]
),
recovery_operations=dict(
- type='list',
+ type="list",
required=False,
default=[],
- elements='dict',
+ elements="dict",
options=dict(
type=dict(
- type='str',
+ type="str",
required=True,
choices=[
- 'send_message',
- 'remote_command',
- 'notify_all_involved'
+ "send_message",
+ "remote_command",
+ "notify_all_involved"
]
),
# when type is remote_command
command_type=dict(
- type='str',
+ type="str",
required=False,
choices=[
- 'custom_script',
- 'ipmi',
- 'ssh',
- 'telnet',
- 'global_script'
+ "custom_script",
+ "ipmi",
+ "ssh",
+ "telnet",
+ "global_script"
]
),
- command=dict(type='str', required=False),
+ command=dict(type="str", required=False),
execute_on=dict(
- type='str',
+ type="str",
required=False,
- choices=['agent', 'server', 'proxy']
+ choices=["agent", "server", "proxy"]
),
- password=dict(type='str', required=False, no_log=True),
- port=dict(type='int', required=False),
- run_on_groups=dict(type='list', required=False),
- run_on_hosts=dict(type='list', required=False),
- script_name=dict(type='str', required=False),
- ssh_auth_type=dict(type='str', required=False, choices=['password', 'public_key']),
- ssh_privatekey_file=dict(type='str', required=False),
- ssh_publickey_file=dict(type='str', required=False),
- username=dict(type='str', required=False),
+ password=dict(type="str", required=False, no_log=True),
+ port=dict(type="int", required=False),
+ run_on_groups=dict(type="list", required=False, elements="str"),
+ run_on_hosts=dict(type="list", required=False, elements="str"),
+ script_name=dict(type="str", required=False),
+ ssh_auth_type=dict(type="str", required=False, choices=["password", "public_key"]),
+ ssh_privatekey_file=dict(type="str", required=False),
+ ssh_publickey_file=dict(type="str", required=False),
+ username=dict(type="str", required=False),
# when type is send_message
- media_type=dict(type='str', required=False),
- subject=dict(type='str', required=False),
- message=dict(type='str', required=False),
- send_to_groups=dict(type='list', required=False),
- send_to_users=dict(type='list', required=False),
+ media_type=dict(type="str", required=False, default="all"),
+ subject=dict(type="str", required=False),
+ op_message=dict(type="str", required=False),
+ send_to_groups=dict(type="list", required=False, elements="str"),
+ send_to_users=dict(type="list", required=False, elements="str"),
),
required_if=[
- ['type', 'remote_command', ['command_type']],
- ['type', 'remote_command', [
- 'run_on_groups',
- 'run_on_hosts'
+ ["type", "remote_command", ["command_type"]],
+ ["type", "remote_command", [
+ "run_on_groups",
+ "run_on_hosts"
], True],
- ['command_type', 'custom_script', [
- 'command',
- 'execute_on'
+ ["command_type", "custom_script", [
+ "command",
+ "execute_on"
]],
- ['command_type', 'ipmi', ['command']],
- ['command_type', 'ssh', ['command', 'ssh_auth_type']],
- ['ssh_auth_type', 'password', ['username', 'password']],
- ['ssh_auth_type', 'public_key', ['username', 'ssh_privatekey_file', 'ssh_publickey_file']],
- ['command_type', 'telnet', ['command', 'username', 'password']],
- ['command_type', 'global_script', ['script_name']],
- ['type', 'send_message', ['send_to_users', 'send_to_groups'], True]
+ ["command_type", "ipmi", ["command"]],
+ ["command_type", "ssh", ["command", "ssh_auth_type"]],
+ ["ssh_auth_type", "password", ["username", "password"]],
+ ["ssh_auth_type", "public_key", ["username", "ssh_privatekey_file", "ssh_publickey_file"]],
+ ["command_type", "telnet", ["command", "username", "password"]],
+ ["command_type", "global_script", ["script_name"]],
+ ["type", "send_message", ["send_to_users", "send_to_groups"], True]
]
),
acknowledge_operations=dict(
- type='list',
+ type="list",
required=False,
default=[],
- elements='dict',
- aliases=['update_operations'],
+ elements="dict",
+ aliases=["update_operations"],
options=dict(
type=dict(
- type='str',
+ type="str",
required=True,
choices=[
- 'send_message',
- 'remote_command',
- 'notify_all_involved'
+ "send_message",
+ "remote_command",
+ "notify_all_involved"
]
),
# when type is remote_command
command_type=dict(
- type='str',
+ type="str",
required=False,
choices=[
- 'custom_script',
- 'ipmi',
- 'ssh',
- 'telnet',
- 'global_script'
+ "custom_script",
+ "ipmi",
+ "ssh",
+ "telnet",
+ "global_script"
]
),
- command=dict(type='str', required=False),
+ command=dict(type="str", required=False),
execute_on=dict(
- type='str',
+ type="str",
required=False,
- choices=['agent', 'server', 'proxy']
+ choices=["agent", "server", "proxy"]
),
- password=dict(type='str', required=False, no_log=True),
- port=dict(type='int', required=False),
- run_on_groups=dict(type='list', required=False),
- run_on_hosts=dict(type='list', required=False),
- script_name=dict(type='str', required=False),
- ssh_auth_type=dict(type='str', required=False, choices=['password', 'public_key']),
- ssh_privatekey_file=dict(type='str', required=False),
- ssh_publickey_file=dict(type='str', required=False),
- username=dict(type='str', required=False),
+ password=dict(type="str", required=False, no_log=True),
+ port=dict(type="int", required=False),
+ run_on_groups=dict(type="list", required=False, elements="str"),
+ run_on_hosts=dict(type="list", required=False, elements="str"),
+ script_name=dict(type="str", required=False),
+ ssh_auth_type=dict(type="str", required=False, choices=["password", "public_key"]),
+ ssh_privatekey_file=dict(type="str", required=False),
+ ssh_publickey_file=dict(type="str", required=False),
+ username=dict(type="str", required=False),
# when type is send_message
- media_type=dict(type='str', required=False),
- subject=dict(type='str', required=False),
- message=dict(type='str', required=False),
- send_to_groups=dict(type='list', required=False),
- send_to_users=dict(type='list', required=False),
+ media_type=dict(type="str", required=False, default="all"),
+ subject=dict(type="str", required=False),
+ op_message=dict(type="str", required=False),
+ send_to_groups=dict(type="list", required=False, elements="str"),
+ send_to_users=dict(type="list", required=False, elements="str"),
),
required_if=[
- ['type', 'remote_command', ['command_type']],
- ['type', 'remote_command', [
- 'run_on_groups',
- 'run_on_hosts'
+ ["type", "remote_command", ["command_type"]],
+ ["type", "remote_command", [
+ "run_on_groups",
+ "run_on_hosts"
], True],
- ['command_type', 'custom_script', [
- 'command',
- 'execute_on'
+ ["command_type", "custom_script", [
+ "command",
+ "execute_on"
]],
- ['command_type', 'ipmi', ['command']],
- ['command_type', 'ssh', ['command', 'ssh_auth_type']],
- ['ssh_auth_type', 'password', ['username', 'password']],
- ['ssh_auth_type', 'public_key', ['username', 'ssh_privatekey_file', 'ssh_publickey_file']],
- ['command_type', 'telnet', ['command', 'username', 'password']],
- ['command_type', 'global_script', ['script_name']],
- ['type', 'send_message', ['send_to_users', 'send_to_groups'], True]
+ ["command_type", "ipmi", ["command"]],
+ ["command_type", "ssh", ["command", "ssh_auth_type"]],
+ ["ssh_auth_type", "password", ["username", "password"]],
+ ["ssh_auth_type", "public_key", ["username", "ssh_privatekey_file", "ssh_publickey_file"]],
+ ["command_type", "telnet", ["command", "username", "password"]],
+ ["command_type", "global_script", ["script_name"]],
+ ["type", "send_message", ["send_to_users", "send_to_groups"], True]
]
),
- pause_symptoms=dict(type='bool', required=False, default=True)
+ pause_symptoms=dict(type="bool", required=False, default=True),
+ notify_if_canceled=dict(type="bool", required=False, default=True)
))
module = AnsibleModule(
argument_spec=argument_spec,
required_if=[
- ['state', 'present', [
- 'event_source'
+ ["state", "present", [
+ "event_source"
]]
],
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- name = module.params['name']
- esc_period = module.params['esc_period']
- event_source = module.params['event_source']
- state = module.params['state']
- status = module.params['status']
- pause_in_maintenance = module.params['pause_in_maintenance']
- default_message = module.params['default_message']
- default_subject = module.params['default_subject']
- recovery_default_message = module.params['recovery_default_message']
- recovery_default_subject = module.params['recovery_default_subject']
- acknowledge_default_message = module.params['acknowledge_default_message']
- acknowledge_default_subject = module.params['acknowledge_default_subject']
- conditions = module.params['conditions']
- formula = module.params['formula']
- eval_type = module.params['eval_type']
- operations = module.params['operations']
- recovery_operations = module.params['recovery_operations']
- acknowledge_operations = module.params['acknowledge_operations']
- pause_symptoms = module.params['pause_symptoms']
+ name = module.params["name"]
+ esc_period = module.params["esc_period"]
+ event_source = module.params["event_source"]
+ state = module.params["state"]
+ status = module.params["status"]
+ pause_in_maintenance = module.params["pause_in_maintenance"]
+ conditions = module.params["conditions"]
+ formula = module.params["formula"]
+ eval_type = module.params["eval_type"]
+ operations = module.params["operations"]
+ recovery_operations = module.params["recovery_operations"]
+ acknowledge_operations = module.params["acknowledge_operations"]
+ pause_symptoms = module.params["pause_symptoms"]
+ notify_if_canceled = module.params["notify_if_canceled"]
zapi_wrapper = Zapi(module)
action = Action(module)
@@ -2028,7 +2224,7 @@ def main():
fltr = Filter(module, zapi_wrapper)
if action_exists:
- action_id = zapi_wrapper.get_action_by_name(name)['actionid']
+ action_id = zapi_wrapper.get_action_by_name(name)["actionid"]
if state == "absent":
result = action.delete_action(action_id)
module.exit_json(changed=True, msg="Action Deleted: %s, ID: %s" % (name, result))
@@ -2040,24 +2236,16 @@ def main():
esc_period=esc_period,
status=status,
pause_in_maintenance=pause_in_maintenance,
- default_message=default_message,
- default_subject=default_subject,
- recovery_default_message=recovery_default_message,
- recovery_default_subject=recovery_default_subject,
- acknowledge_default_message=acknowledge_default_message,
- acknowledge_default_subject=acknowledge_default_subject,
operations=ops.construct_the_data(operations, event_source),
recovery_operations=recovery_ops.construct_the_data(recovery_operations),
- conditions=fltr.construct_the_data(eval_type, formula, conditions)
+ conditions=fltr.construct_the_data(eval_type, formula, conditions),
+ notify_if_canceled=notify_if_canceled
)
- if LooseVersion(zapi_wrapper._zbx_api_version) >= LooseVersion('6.4'):
- kwargs['pause_symptoms'] = pause_symptoms
+ if LooseVersion(zapi_wrapper._zbx_api_version) >= LooseVersion("6.4"):
+ kwargs["pause_symptoms"] = pause_symptoms
- if LooseVersion(zapi_wrapper._zbx_api_version) >= LooseVersion('6.0'):
- kwargs[argument_spec['acknowledge_operations']['aliases'][0]] = acknowledge_ops.construct_the_data(acknowledge_operations)
- else:
- kwargs['acknowledge_operations'] = acknowledge_ops.construct_the_data(acknowledge_operations)
+ kwargs[argument_spec["acknowledge_operations"]["aliases"][0]] = acknowledge_ops.construct_the_data(acknowledge_operations)
difference = action.check_difference(**kwargs)
@@ -2079,28 +2267,20 @@ def main():
esc_period=esc_period,
status=status,
pause_in_maintenance=pause_in_maintenance,
- default_message=default_message,
- default_subject=default_subject,
- recovery_default_message=recovery_default_message,
- recovery_default_subject=recovery_default_subject,
- acknowledge_default_message=acknowledge_default_message,
- acknowledge_default_subject=acknowledge_default_subject,
operations=ops.construct_the_data(operations, event_source),
recovery_operations=recovery_ops.construct_the_data(recovery_operations),
- conditions=fltr.construct_the_data(eval_type, formula, conditions)
+ conditions=fltr.construct_the_data(eval_type, formula, conditions),
+ notify_if_canceled=notify_if_canceled
)
- if LooseVersion(zapi_wrapper._zbx_api_version) >= LooseVersion('6.0'):
- kwargs[argument_spec['acknowledge_operations']['aliases'][0]] = acknowledge_ops.construct_the_data(acknowledge_operations)
- else:
- kwargs['acknowledge_operations'] = acknowledge_ops.construct_the_data(acknowledge_operations)
+ kwargs[argument_spec["acknowledge_operations"]["aliases"][0]] = acknowledge_ops.construct_the_data(acknowledge_operations)
- if LooseVersion(zapi_wrapper._zbx_api_version) >= LooseVersion('6.4'):
- kwargs['pause_symptoms'] = pause_symptoms
+ if LooseVersion(zapi_wrapper._zbx_api_version) >= LooseVersion("6.4"):
+ kwargs["pause_symptoms"] = pause_symptoms
action_id = action.add_action(**kwargs)
module.exit_json(changed=True, msg="Action created: %s, ID: %s" % (name, action_id))
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_api_info.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_api_info.py
new file mode 100644
index 000000000..5941408e9
--- /dev/null
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_api_info.py
@@ -0,0 +1,108 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright: (c) 2022, ONODERA Masaru <masaru-onodera@ieee.org>
+# 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 = '''
+---
+module: zabbix_api_info
+
+short_description: Retrieve Zabbix API info
+
+description:
+ - This module allows you to retrieve Zabbix api info.
+
+author:
+ - ONODERA Masaru(@masa-orca)
+
+requirements:
+ - "python >= 3.9"
+
+version_added: 2.1.0
+
+extends_documentation_fragment:
+ - community.zabbix.zabbix
+'''
+
+EXAMPLES = '''
+# 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: Retrieve API information
+ # 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_api_info:
+ register: zbx_api_info
+'''
+
+RETURN = '''
+api:
+ description: Summaries of Zabbix API info
+ returned: success
+ type: dict
+ contains:
+ version:
+ description: API version
+ type: str
+ sample: 6.0.18
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.compat.version import LooseVersion
+
+from ansible_collections.community.zabbix.plugins.module_utils.base import ZabbixBase
+import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabbix_utils
+
+
+class ApiInfo(ZabbixBase):
+ def __init__(self, module, zbx=None, zapi_wrapper=None):
+ super(ApiInfo, self).__init__(module, zbx, zapi_wrapper)
+ if LooseVersion(self._zbx_api_version) < LooseVersion('2.2.0'):
+ module.fail_json(msg="This module doesn't support Zabbix versions lower than 2.2.0")
+
+ def get_api_info(self):
+ if self._module.check_mode:
+ self._module.exit_json(changed=False)
+ try:
+ api = {
+ 'version': self._zbx_api_version
+ }
+ self._module.exit_json(api=api)
+ except Exception as e:
+ self._module.fail_json(msg="Failed to retrieve API info: %s" % e)
+
+
+def main():
+ argument_spec = zabbix_utils.zabbix_common_argument_spec()
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True
+ )
+
+ api_info = ApiInfo(module)
+ api_info.get_api_info()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_authentication.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_authentication.py
index 51fb3e5b9..f8eaf8e19 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_authentication.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_authentication.py
@@ -5,10 +5,11 @@
# 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 = '''
+DOCUMENTATION = """
---
module: zabbix_authentication
@@ -21,7 +22,7 @@ author:
- ONODERA Masaru(@masa-orca)
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
version_added: 1.6.0
@@ -257,24 +258,21 @@ options:
type: list
elements: str
-notes:
- - Zabbix 5.4 version and higher are supported.
-
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = '''
+EXAMPLES = """
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: Update all authentication setting (Zabbix <= 6.0)
@@ -285,9 +283,9 @@ EXAMPLES = '''
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_zabbix_url_path: "zabbixeu" # If Zabbix WebUI runs on non-default (zabbix) path ,e.g. http://<FQDN>/zabbixeu
ansible_host: zabbix-example-fqdn.org
- zabbix_authentication:
+ community.zabbix.zabbix_authentication:
authentication_type: internal
http_auth_enabled: true
http_login_form: zabbix_login_form
@@ -296,20 +294,20 @@ EXAMPLES = '''
- any
http_case_sensitive: true
ldap_configured: true
- ldap_host: 'ldap://localhost'
+ ldap_host: "ldap://localhost"
ldap_port: 389
- ldap_base_dn: 'ou=Users,ou=system'
- ldap_search_attribute: 'uid'
- ldap_bind_dn: 'uid=ldap_search,ou=system'
+ ldap_base_dn: "ou=Users,ou=system"
+ ldap_search_attribute: "uid"
+ ldap_bind_dn: "uid=ldap_search,ou=system"
ldap_case_sensitive: true
- ldap_bind_password: 'password'
+ ldap_bind_password: "password"
saml_auth_enabled: true
- saml_idp_entityid: ''
- saml_sso_url: 'https://localhost/SAML2/SSO'
- saml_slo_url: 'https://localhost/SAML2/SLO'
- saml_username_attribute: 'uid'
- saml_sp_entityid: 'https://localhost'
- saml_nameid_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:entity'
+ saml_idp_entityid: ""
+ saml_sso_url: "https://localhost/SAML2/SSO"
+ saml_slo_url: "https://localhost/SAML2/SLO"
+ saml_username_attribute: "uid"
+ saml_sp_entityid: "https://localhost"
+ saml_nameid_format: "urn:oasis:names:tc:SAML:2.0:nameid-format:entity"
saml_sign_messages: true
saml_sign_assertions: true
saml_sign_authn_requests: true
@@ -333,9 +331,9 @@ EXAMPLES = '''
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_zabbix_url_path: "zabbixeu" # If Zabbix WebUI runs on non-default (zabbix) path ,e.g. http://<FQDN>/zabbixeu
ansible_host: zabbix-example-fqdn.org
- zabbix_authentication:
+ community.zabbix.zabbix_authentication:
authentication_type: internal
http_auth_enabled: true
http_login_form: zabbix_login_form
@@ -346,12 +344,12 @@ EXAMPLES = '''
ldap_configured: true
ldap_case_sensitive: true
saml_auth_enabled: true
- saml_idp_entityid: ''
- saml_sso_url: 'https://localhost/SAML2/SSO'
- saml_slo_url: 'https://localhost/SAML2/SLO'
- saml_username_attribute: 'uid'
- saml_sp_entityid: 'https://localhost'
- saml_nameid_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:entity'
+ saml_idp_entityid: ""
+ saml_sso_url: "https://localhost/SAML2/SSO"
+ saml_slo_url: "https://localhost/SAML2/SLO"
+ saml_username_attribute: "uid"
+ saml_sp_entityid: "https://localhost"
+ saml_nameid_format: "urn:oasis:names:tc:SAML:2.0:nameid-format:entity"
saml_sign_messages: true
saml_sign_assertions: true
saml_sign_authn_requests: true
@@ -375,9 +373,9 @@ EXAMPLES = '''
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_zabbix_url_path: "zabbixeu" # If Zabbix WebUI runs on non-default (zabbix) path ,e.g. http://<FQDN>/zabbixeu
ansible_host: zabbix-example-fqdn.org
- zabbix_authentication:
+ community.zabbix.zabbix_authentication:
authentication_type: internal
http_auth_enabled: true
http_login_form: zabbix_login_form
@@ -386,6 +384,7 @@ EXAMPLES = '''
- any
http_case_sensitive: true
ldap_auth_enabled: true
+ ldap_userdirectory: TestUserDirectory
ldap_case_sensitive: true
saml_auth_enabled: true
saml_case_sensitive: true
@@ -399,15 +398,15 @@ EXAMPLES = '''
- contain_digits
- contain_special_characters
- avoid_easy_to_guess
-'''
+"""
-RETURN = '''
+RETURN = """
msg:
description: The result of the operation
returned: success
type: str
- sample: 'Successfully update authentication setting'
-'''
+ sample: "Successfully update authentication setting"
+"""
from ansible.module_utils.basic import AnsibleModule
@@ -417,251 +416,291 @@ import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabb
class Authentication(ZabbixBase):
- def __init__(self, module, zbx=None, zapi_wrapper=None):
- super(Authentication, self).__init__(module, zbx, zapi_wrapper)
- if LooseVersion(self._zbx_api_version) < LooseVersion('5.4.0'):
- module.fail_json(msg="This module doesn't support Zabbix versions lower than 5.4.0")
# get authentication setting
def get_authentication(self):
try:
- return self._zapi.authentication.get({'output': 'extend'})
+ return self._zapi.authentication.get({"output": "extend"})
except Exception as e:
self._module.fail_json(msg="Failed to get authentication setting: %s" % e)
# update authentication setting
def update_authentication(
- self,
- current_authentication,
- authentication_type,
- http_auth_enabled,
- http_login_form,
- http_strip_domains,
- http_case_sensitive,
- ldap_configured,
- ldap_auth_enabled,
- ldap_host,
- ldap_port,
- ldap_base_dn,
- ldap_search_attribute,
- ldap_bind_dn,
- ldap_case_sensitive,
- ldap_bind_password,
- ldap_userdirectory,
- saml_auth_enabled,
- saml_idp_entityid,
- saml_sso_url,
- saml_slo_url,
- saml_username_attribute,
- saml_sp_entityid,
- saml_nameid_format,
- saml_sign_messages,
- saml_sign_assertions,
- saml_sign_authn_requests,
- saml_sign_logout_requests,
- saml_sign_logout_responses,
- saml_encrypt_nameid,
- saml_encrypt_assertions,
- saml_case_sensitive,
- passwd_min_length,
- passwd_check_rules,
- ldap_jit_status,
- saml_jit_status,
- jit_provision_interval,
- disabled_usrgroup):
+ self,
+ current_authentication,
+ authentication_type,
+ http_auth_enabled,
+ http_login_form,
+ http_strip_domains,
+ http_case_sensitive,
+ ldap_configured,
+ ldap_auth_enabled,
+ ldap_host,
+ ldap_port,
+ ldap_base_dn,
+ ldap_search_attribute,
+ ldap_bind_dn,
+ ldap_case_sensitive,
+ ldap_bind_password,
+ ldap_userdirectory,
+ saml_auth_enabled,
+ saml_idp_entityid,
+ saml_sso_url,
+ saml_slo_url,
+ saml_username_attribute,
+ saml_sp_entityid,
+ saml_nameid_format,
+ saml_sign_messages,
+ saml_sign_assertions,
+ saml_sign_authn_requests,
+ saml_sign_logout_requests,
+ saml_sign_logout_responses,
+ saml_encrypt_nameid,
+ saml_encrypt_assertions,
+ saml_case_sensitive,
+ passwd_min_length,
+ passwd_check_rules,
+ ldap_jit_status,
+ saml_jit_status,
+ jit_provision_interval,
+ disabled_usrgroup,
+ ):
try:
params = {}
if authentication_type:
- params['authentication_type'] = str(zabbix_utils.helper_to_numeric_value(
- ['internal', 'ldap'],
- authentication_type
- ))
+ params["authentication_type"] = str(
+ zabbix_utils.helper_to_numeric_value(
+ ["internal", "ldap"], authentication_type
+ )
+ )
if isinstance(http_auth_enabled, bool):
- params['http_auth_enabled'] = str(int(http_auth_enabled))
+ params["http_auth_enabled"] = str(int(http_auth_enabled))
if http_login_form:
- params['http_login_form'] = str(zabbix_utils.helper_to_numeric_value(
- ['zabbix_login_form', 'http_login_form'],
- http_login_form
- ))
+ params["http_login_form"] = str(
+ zabbix_utils.helper_to_numeric_value(
+ ["zabbix_login_form", "http_login_form"], http_login_form
+ )
+ )
if http_strip_domains:
- params['http_strip_domains'] = ','.join(http_strip_domains)
+ params["http_strip_domains"] = ",".join(http_strip_domains)
if isinstance(http_case_sensitive, bool):
- params['http_case_sensitive'] = str(int(http_case_sensitive))
+ params["http_case_sensitive"] = str(int(http_case_sensitive))
- if LooseVersion(self._zbx_api_version) < LooseVersion('6.4'):
+ if LooseVersion(self._zbx_api_version) < LooseVersion("6.4"):
if isinstance(ldap_configured, bool):
- params['ldap_configured'] = str(int(ldap_configured))
+ params["ldap_configured"] = str(int(ldap_configured))
else:
if isinstance(ldap_auth_enabled, bool):
- params['ldap_auth_enabled'] = str(int(ldap_auth_enabled))
+ params["ldap_auth_enabled"] = str(int(ldap_auth_enabled))
- if LooseVersion(self._zbx_api_version) < LooseVersion('6.2.0'):
+ if LooseVersion(self._zbx_api_version) < LooseVersion("6.2"):
if ldap_host:
- params['ldap_host'] = ldap_host
+ params["ldap_host"] = ldap_host
if ldap_port:
- params['ldap_port'] = str(ldap_port)
+ params["ldap_port"] = str(ldap_port)
if ldap_base_dn:
- params['ldap_base_dn'] = ldap_base_dn
+ params["ldap_base_dn"] = ldap_base_dn
if ldap_search_attribute:
- params['ldap_search_attribute'] = ldap_search_attribute
+ params["ldap_search_attribute"] = ldap_search_attribute
if ldap_bind_dn:
- params['ldap_bind_dn'] = ldap_bind_dn
+ params["ldap_bind_dn"] = ldap_bind_dn
if ldap_bind_password:
- params['ldap_bind_password'] = ldap_bind_password
+ params["ldap_bind_password"] = ldap_bind_password
else:
if ldap_userdirectory:
- directory = self._zapi.userdirectory.get({'search': {'name': ldap_userdirectory}})
+ directory = self._zapi.userdirectory.get(
+ {"search": {"name": ldap_userdirectory}}
+ )
if not directory:
- self._module.fail_json(msg="Canot find user directory with name: %s" % ldap_userdirectory)
- params['ldap_userdirectoryid'] = directory[0]['userdirectoryid']
+ self._module.fail_json(
+ msg="Canot find user directory with name: %s"
+ % ldap_userdirectory
+ )
+ params["ldap_userdirectoryid"] = directory[0]["userdirectoryid"]
if isinstance(ldap_case_sensitive, bool):
- params['ldap_case_sensitive'] = str(int(ldap_case_sensitive))
+ params["ldap_case_sensitive"] = str(int(ldap_case_sensitive))
if isinstance(saml_auth_enabled, bool):
- params['saml_auth_enabled'] = str(int(saml_auth_enabled))
+ params["saml_auth_enabled"] = str(int(saml_auth_enabled))
- if LooseVersion(self._zbx_api_version) < LooseVersion('6.4'):
+ if LooseVersion(self._zbx_api_version) < LooseVersion("6.4"):
if saml_idp_entityid:
- params['saml_idp_entityid'] = saml_idp_entityid
+ params["saml_idp_entityid"] = saml_idp_entityid
if saml_sso_url:
- params['saml_sso_url'] = saml_sso_url
+ params["saml_sso_url"] = saml_sso_url
if saml_slo_url:
- params['saml_slo_url'] = saml_slo_url
+ params["saml_slo_url"] = saml_slo_url
if saml_username_attribute:
- params['saml_username_attribute'] = saml_username_attribute
+ params["saml_username_attribute"] = saml_username_attribute
if saml_sp_entityid:
- params['saml_sp_entityid'] = saml_sp_entityid
+ params["saml_sp_entityid"] = saml_sp_entityid
if saml_nameid_format:
- params['saml_nameid_format'] = saml_nameid_format
+ params["saml_nameid_format"] = saml_nameid_format
if isinstance(saml_sign_messages, bool):
- params['saml_sign_messages'] = str(int(saml_sign_messages))
+ params["saml_sign_messages"] = str(int(saml_sign_messages))
if isinstance(saml_sign_assertions, bool):
- params['saml_sign_assertions'] = str(int(saml_sign_assertions))
+ params["saml_sign_assertions"] = str(int(saml_sign_assertions))
if isinstance(saml_sign_authn_requests, bool):
- params['saml_sign_authn_requests'] = str(int(saml_sign_authn_requests))
+ params["saml_sign_authn_requests"] = str(
+ int(saml_sign_authn_requests)
+ )
if isinstance(saml_sign_logout_requests, bool):
- params['saml_sign_logout_requests'] = str(int(saml_sign_logout_requests))
+ params["saml_sign_logout_requests"] = str(
+ int(saml_sign_logout_requests)
+ )
if isinstance(saml_sign_logout_responses, bool):
- params['saml_sign_logout_responses'] = str(int(saml_sign_logout_responses))
+ params["saml_sign_logout_responses"] = str(
+ int(saml_sign_logout_responses)
+ )
if isinstance(saml_encrypt_nameid, bool):
- params['saml_encrypt_nameid'] = str(int(saml_encrypt_nameid))
+ params["saml_encrypt_nameid"] = str(int(saml_encrypt_nameid))
if isinstance(saml_encrypt_assertions, bool):
- params['saml_encrypt_assertions'] = str(int(saml_encrypt_assertions))
+ params["saml_encrypt_assertions"] = str(
+ int(saml_encrypt_assertions)
+ )
if isinstance(saml_case_sensitive, bool):
- params['saml_case_sensitive'] = str(int(saml_case_sensitive))
+ params["saml_case_sensitive"] = str(int(saml_case_sensitive))
else:
if isinstance(ldap_jit_status, bool):
- params['ldap_jit_status'] = str(int(ldap_jit_status))
+ params["ldap_jit_status"] = str(int(ldap_jit_status))
if isinstance(saml_jit_status, bool):
- params['saml_jit_status'] = str(int(saml_jit_status))
+ params["saml_jit_status"] = str(int(saml_jit_status))
if isinstance(jit_provision_interval, str):
- params['jit_provision_interval'] = jit_provision_interval
+ params["jit_provision_interval"] = jit_provision_interval
if isinstance(disabled_usrgroup, str):
- usrgrpids = self._zapi.usergroup.get({'filter': {'name': disabled_usrgroup}})
+ usrgrpids = self._zapi.usergroup.get(
+ {"filter": {"name": disabled_usrgroup}}
+ )
if not usrgrpids:
- self._module.fail_json('User group "%s" cannot be found' % disabled_usrgroup)
- params['disabled_usrgrpid'] = str(int(usrgrpids[0]['usrgrpid']))
+ self._module.fail_json(
+ "User group '%s' cannot be found" % disabled_usrgroup
+ )
+ params["disabled_usrgrpid"] = str(int(usrgrpids[0]["usrgrpid"]))
if (ldap_jit_status or saml_jit_status) and not disabled_usrgroup:
- self._module.fail_json('"disabled_usrgroup" must be provided if "ldap_jit_status" or "saml_jit_status" enabled')
+ self._module.fail_json(
+ "'disabled_usrgroup' must be provided if 'ldap_jit_status' or 'saml_jit_status' enabled"
+ )
if passwd_min_length:
- if LooseVersion(self._zbx_api_version) < LooseVersion('6.0'):
- self._module.warn('passwd_min_length is ignored with Zabbix 5.4.')
- elif passwd_min_length < 1 or passwd_min_length > 70:
+ if passwd_min_length < 1 or passwd_min_length > 70:
self._module.fail_json(msg="Please set 0-70 to passwd_min_length.")
else:
- params['passwd_min_length'] = str(passwd_min_length)
+ params["passwd_min_length"] = str(passwd_min_length)
if passwd_check_rules:
- if LooseVersion(self._zbx_api_version) < LooseVersion('6.0'):
- self._module.warn('passwd_check_rules is ignored with Zabbix 5.4.')
- else:
- passwd_check_rules_values = [
- 'contain_uppercase_and_lowercase_letters',
- 'contain_digits',
- 'contain_special_characters',
- 'avoid_easy_to_guess'
- ]
- params['passwd_check_rules'] = 0
- if isinstance(passwd_check_rules, str):
- if passwd_check_rules not in passwd_check_rules_values:
- self._module.fail_json(msg="%s is invalid value for passwd_check_rules." % passwd_check_rules)
- params['passwd_check_rules'] += 2 ** zabbix_utils.helper_to_numeric_value(
- passwd_check_rules_values, passwd_check_rules
+ passwd_check_rules_values = [
+ "contain_uppercase_and_lowercase_letters",
+ "contain_digits",
+ "contain_special_characters",
+ "avoid_easy_to_guess",
+ ]
+ params["passwd_check_rules"] = 0
+ if isinstance(passwd_check_rules, str):
+ if passwd_check_rules not in passwd_check_rules_values:
+ self._module.fail_json(
+ msg="%s is invalid value for passwd_check_rules."
+ % passwd_check_rules
)
- elif isinstance(passwd_check_rules, list):
- for _passwd_check_rules_value in passwd_check_rules:
- if _passwd_check_rules_value not in passwd_check_rules_values:
- self._module.fail_json(msg="%s is invalid value for passwd_check_rules." % _passwd_check_rules_value)
- params['passwd_check_rules'] += 2 ** zabbix_utils.helper_to_numeric_value(
+ params[
+ "passwd_check_rules"
+ ] += 2 ** zabbix_utils.helper_to_numeric_value(
+ passwd_check_rules_values, passwd_check_rules
+ )
+ elif isinstance(passwd_check_rules, list):
+ for _passwd_check_rules_value in passwd_check_rules:
+ if (
+ _passwd_check_rules_value
+ not in passwd_check_rules_values
+ ):
+ self._module.fail_json(
+ msg="%s is invalid value for passwd_check_rules."
+ % _passwd_check_rules_value
+ )
+ params[
+ "passwd_check_rules"
+ ] += 2 ** zabbix_utils.helper_to_numeric_value(
passwd_check_rules_values, _passwd_check_rules_value
)
- params['passwd_check_rules'] = str(params['passwd_check_rules'])
+ params["passwd_check_rules"] = str(params["passwd_check_rules"])
future_authentication = current_authentication.copy()
future_authentication.update(params)
- if LooseVersion(self._zbx_api_version) < LooseVersion('6.4'):
- if (current_authentication['ldap_configured'] == '0'
- and future_authentication['ldap_configured'] == '1'):
- if LooseVersion(self._zbx_api_version) < LooseVersion('6.2.0'):
- if (not ldap_host
- or not ldap_port
- or not ldap_search_attribute
- or not ldap_base_dn):
+ if LooseVersion(self._zbx_api_version) < LooseVersion("6.4"):
+ if (
+ current_authentication["ldap_configured"] == "0"
+ and future_authentication["ldap_configured"] == "1"
+ ):
+ if LooseVersion(self._zbx_api_version) < LooseVersion("6.2"):
+ if (
+ not ldap_host
+ or not ldap_port
+ or not ldap_search_attribute
+ or not ldap_base_dn
+ ):
self._module.fail_json(
msg="Please set ldap_host, ldap_search_attribute and ldap_base_dn when you change a value of ldap_configured to true."
)
else:
if not ldap_userdirectory:
- self._module.fail_json(msg="Please set ldap_userdirectory when you change a value of ldap_configured to true.")
+ self._module.fail_json(
+ msg="Please set ldap_userdirectory when you change a value of ldap_configured to true."
+ )
else:
- if (current_authentication['ldap_auth_enabled'] == "0"
- and future_authentication['ldap_auth_enabled'] == "1"):
+ if (
+ current_authentication["ldap_auth_enabled"] == "0"
+ and future_authentication["ldap_auth_enabled"] == "1"
+ ):
if not ldap_userdirectory:
- self._module.fail_json(msg="Please set ldap_userdirectory when you change a value of ldap_auth_enabled to true.")
-
- if LooseVersion(self._zbx_api_version) < LooseVersion('6.4'):
- if (current_authentication['saml_auth_enabled'] == '0'
- and future_authentication['saml_auth_enabled'] == '1'
- and not saml_idp_entityid
- and not saml_sso_url
- and not saml_username_attribute
- and not saml_sp_entityid):
+ self._module.fail_json(
+ msg="Please set ldap_userdirectory when you change a value of ldap_auth_enabled to true."
+ )
+
+ if LooseVersion(self._zbx_api_version) < LooseVersion("6.4"):
+ if (
+ current_authentication["saml_auth_enabled"] == "0"
+ and future_authentication["saml_auth_enabled"] == "1"
+ and not saml_idp_entityid
+ and not saml_sso_url
+ and not saml_username_attribute
+ and not saml_sp_entityid
+ ):
self._module.fail_json(
- msg=' '.join([
- "Please set saml_idp_entityid, saml_sso_url, saml_username_attribute and saml_sp_entityid",
- "when you change a value of saml_auth_enabled to true."
- ])
+ msg=" ".join(
+ [
+ "Please set saml_idp_entityid, saml_sso_url, saml_username_attribute and saml_sp_entityid",
+ "when you change a value of saml_auth_enabled to true.",
+ ]
+ )
)
if future_authentication != current_authentication:
@@ -669,100 +708,101 @@ class Authentication(ZabbixBase):
self._module.exit_json(changed=True)
self._zapi.authentication.update(params)
- self._module.exit_json(changed=True, result="Successfully update authentication setting")
+ self._module.exit_json(
+ changed=True, result="Successfully update authentication setting"
+ )
else:
- self._module.exit_json(changed=False, result="Authentication setting is already up to date")
+ self._module.exit_json(
+ changed=False, result="Authentication setting is already up to date"
+ )
except Exception as e:
- self._module.fail_json(msg="Failed to update authentication setting, Exception: %s" % e)
+ self._module.fail_json(
+ msg="Failed to update authentication setting, Exception: %s" % e
+ )
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
- argument_spec.update(dict(
- authentication_type=dict(type='str', choices=['internal', 'ldap']),
- http_auth_enabled=dict(type='bool'),
- http_login_form=dict(type='str', choices=['zabbix_login_form', 'http_login_form']),
- http_strip_domains=dict(type='list', elements='str'),
- http_case_sensitive=dict(type='bool'),
- ldap_configured=dict(type='bool'),
- ldap_auth_enabled=dict(type='bool'),
- ldap_host=dict(type='str'),
- ldap_port=dict(type='int'),
- ldap_base_dn=dict(type='str'),
- ldap_search_attribute=dict(type='str'),
- ldap_bind_dn=dict(type='str'),
- ldap_case_sensitive=dict(type='bool'),
- ldap_bind_password=dict(type='str', no_log=True),
- ldap_userdirectory=dict(type='str'),
- ldap_jit_status=dict(type='bool'),
- saml_auth_enabled=dict(type='bool'),
- saml_idp_entityid=dict(type='str'),
- saml_sso_url=dict(type='str'),
- saml_slo_url=dict(type='str'),
- saml_username_attribute=dict(type='str'),
- saml_sp_entityid=dict(type='str'),
- saml_nameid_format=dict(type='str'),
- saml_sign_messages=dict(type='bool'),
- saml_sign_assertions=dict(type='bool'),
- saml_sign_authn_requests=dict(type='bool'),
- saml_sign_logout_requests=dict(type='bool'),
- saml_sign_logout_responses=dict(type='bool'),
- saml_encrypt_nameid=dict(type='bool'),
- saml_encrypt_assertions=dict(type='bool'),
- saml_case_sensitive=dict(type='bool'),
- saml_jit_status=dict(type='bool'),
- jit_provision_interval=dict(type='str', default='1h'),
- disabled_usrgroup=dict(type='str'),
- passwd_min_length=dict(type='int', no_log=False),
- passwd_check_rules=dict(type='list', elements='str', no_log=False)
- ))
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True
+ argument_spec.update(
+ dict(
+ authentication_type=dict(type="str", choices=["internal", "ldap"]),
+ http_auth_enabled=dict(type="bool"),
+ http_login_form=dict(
+ type="str", choices=["zabbix_login_form", "http_login_form"]
+ ),
+ http_strip_domains=dict(type="list", elements="str"),
+ http_case_sensitive=dict(type="bool"),
+ ldap_configured=dict(type="bool"),
+ ldap_auth_enabled=dict(type="bool"),
+ ldap_host=dict(type="str"),
+ ldap_port=dict(type="int"),
+ ldap_base_dn=dict(type="str"),
+ ldap_search_attribute=dict(type="str"),
+ ldap_bind_dn=dict(type="str"),
+ ldap_case_sensitive=dict(type="bool"),
+ ldap_bind_password=dict(type="str", no_log=True),
+ ldap_userdirectory=dict(type="str"),
+ ldap_jit_status=dict(type="bool"),
+ saml_auth_enabled=dict(type="bool"),
+ saml_idp_entityid=dict(type="str"),
+ saml_sso_url=dict(type="str"),
+ saml_slo_url=dict(type="str"),
+ saml_username_attribute=dict(type="str"),
+ saml_sp_entityid=dict(type="str"),
+ saml_nameid_format=dict(type="str"),
+ saml_sign_messages=dict(type="bool"),
+ saml_sign_assertions=dict(type="bool"),
+ saml_sign_authn_requests=dict(type="bool"),
+ saml_sign_logout_requests=dict(type="bool"),
+ saml_sign_logout_responses=dict(type="bool"),
+ saml_encrypt_nameid=dict(type="bool"),
+ saml_encrypt_assertions=dict(type="bool"),
+ saml_case_sensitive=dict(type="bool"),
+ saml_jit_status=dict(type="bool"),
+ jit_provision_interval=dict(type="str", default="1h"),
+ disabled_usrgroup=dict(type="str"),
+ passwd_min_length=dict(type="int", no_log=False),
+ passwd_check_rules=dict(type="list", elements="str", no_log=False),
+ )
)
-
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- authentication_type = module.params['authentication_type']
- http_auth_enabled = module.params['http_auth_enabled']
- http_login_form = module.params['http_login_form']
- http_strip_domains = module.params['http_strip_domains']
- http_case_sensitive = module.params['http_case_sensitive']
- ldap_configured = module.params['ldap_configured']
- ldap_auth_enabled = module.params['ldap_auth_enabled']
- ldap_host = module.params['ldap_host']
- ldap_port = module.params['ldap_port']
- ldap_base_dn = module.params['ldap_base_dn']
- ldap_search_attribute = module.params['ldap_search_attribute']
- ldap_bind_dn = module.params['ldap_bind_dn']
- ldap_case_sensitive = module.params['ldap_case_sensitive']
- ldap_bind_password = module.params['ldap_bind_password']
- ldap_userdirectory = module.params['ldap_userdirectory']
- saml_auth_enabled = module.params['saml_auth_enabled']
- saml_idp_entityid = module.params['saml_idp_entityid']
- saml_sso_url = module.params['saml_sso_url']
- saml_slo_url = module.params['saml_slo_url']
- saml_username_attribute = module.params['saml_username_attribute']
- saml_sp_entityid = module.params['saml_sp_entityid']
- saml_nameid_format = module.params['saml_nameid_format']
- saml_sign_messages = module.params['saml_sign_messages']
- saml_sign_assertions = module.params['saml_sign_assertions']
- saml_sign_authn_requests = module.params['saml_sign_authn_requests']
- saml_sign_logout_requests = module.params['saml_sign_logout_requests']
- saml_sign_logout_responses = module.params['saml_sign_logout_responses']
- saml_encrypt_nameid = module.params['saml_encrypt_nameid']
- saml_encrypt_assertions = module.params['saml_encrypt_assertions']
- saml_case_sensitive = module.params['saml_case_sensitive']
- passwd_min_length = module.params['passwd_min_length']
- passwd_check_rules = module.params['passwd_check_rules']
- ldap_jit_status = module.params['ldap_jit_status']
- saml_jit_status = module.params['saml_jit_status']
- jit_provision_interval = module.params['jit_provision_interval']
- disabled_usrgroup = module.params['disabled_usrgroup']
+ module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
+
+ authentication_type = module.params["authentication_type"]
+ http_auth_enabled = module.params["http_auth_enabled"]
+ http_login_form = module.params["http_login_form"]
+ http_strip_domains = module.params["http_strip_domains"]
+ http_case_sensitive = module.params["http_case_sensitive"]
+ ldap_configured = module.params["ldap_configured"]
+ ldap_auth_enabled = module.params["ldap_auth_enabled"]
+ ldap_host = module.params["ldap_host"]
+ ldap_port = module.params["ldap_port"]
+ ldap_base_dn = module.params["ldap_base_dn"]
+ ldap_search_attribute = module.params["ldap_search_attribute"]
+ ldap_bind_dn = module.params["ldap_bind_dn"]
+ ldap_case_sensitive = module.params["ldap_case_sensitive"]
+ ldap_bind_password = module.params["ldap_bind_password"]
+ ldap_userdirectory = module.params["ldap_userdirectory"]
+ saml_auth_enabled = module.params["saml_auth_enabled"]
+ saml_idp_entityid = module.params["saml_idp_entityid"]
+ saml_sso_url = module.params["saml_sso_url"]
+ saml_slo_url = module.params["saml_slo_url"]
+ saml_username_attribute = module.params["saml_username_attribute"]
+ saml_sp_entityid = module.params["saml_sp_entityid"]
+ saml_nameid_format = module.params["saml_nameid_format"]
+ saml_sign_messages = module.params["saml_sign_messages"]
+ saml_sign_assertions = module.params["saml_sign_assertions"]
+ saml_sign_authn_requests = module.params["saml_sign_authn_requests"]
+ saml_sign_logout_requests = module.params["saml_sign_logout_requests"]
+ saml_sign_logout_responses = module.params["saml_sign_logout_responses"]
+ saml_encrypt_nameid = module.params["saml_encrypt_nameid"]
+ saml_encrypt_assertions = module.params["saml_encrypt_assertions"]
+ saml_case_sensitive = module.params["saml_case_sensitive"]
+ passwd_min_length = module.params["passwd_min_length"]
+ passwd_check_rules = module.params["passwd_check_rules"]
+ ldap_jit_status = module.params["ldap_jit_status"]
+ saml_jit_status = module.params["saml_jit_status"]
+ jit_provision_interval = module.params["jit_provision_interval"]
+ disabled_usrgroup = module.params["disabled_usrgroup"]
authentication = Authentication(module)
@@ -804,9 +844,9 @@ def main():
ldap_jit_status,
saml_jit_status,
jit_provision_interval,
- disabled_usrgroup
+ disabled_usrgroup,
)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_autoregister.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_autoregister.py
index c8bf35538..c00f52cbe 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_autoregister.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_autoregister.py
@@ -8,7 +8,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
module: zabbix_autoregister
@@ -22,7 +22,7 @@ author:
- ONODERA Masaru(@masa-orca)
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
version_added: 1.6.0
@@ -47,7 +47,6 @@ options:
type: str
notes:
- - Only Zabbix >= 4.4 is supported.
- This module returns changed=true when any value is set in I(tls_psk_identity) or I(tls_psk) as Zabbix API
will not return any sensitive information back for module to compare.
- Please note that this module configures B(global Zabbix Server settings).
@@ -57,19 +56,19 @@ notes:
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = '''
+EXAMPLES = """
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: Update autoregistration
@@ -80,16 +79,13 @@ EXAMPLES = '''
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_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_autoregister:
- server_url: "http://zabbix.example.com/zabbix/"
- login_user: Admin
- login_password: secret
tls_accept:
- unsecure
- tls_with_psk
- tls_psk_identity: 'PSK 001'
+ tls_psk_identity: "PSK 001"
tls_psk: "11111595725ac58dd977beef14b97461a7c1045b9a1c923453302c5473193478"
- name: Set unsecure to tls_accept
@@ -100,42 +96,32 @@ EXAMPLES = '''
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_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_autoregister:
- server_url: "http://zabbix.example.com/zabbix/"
- login_user: Admin
- login_password: secret
tls_accept: unsecure
-'''
+"""
-RETURN = '''
+RETURN = """
msg:
description: The result of the operation
returned: success
type: str
- sample: 'Successfully updated global autoregistration setting'
-'''
+ sample: "Successfully updated global autoregistration setting"
+"""
from ansible.module_utils.basic import AnsibleModule
-
from ansible_collections.community.zabbix.plugins.module_utils.base import ZabbixBase
-from ansible.module_utils.compat.version import LooseVersion
-
import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabbix_utils
class Autoregistration(ZabbixBase):
- def __init__(self, module, zbx=None, zapi_wrapper=None):
- super(Autoregistration, self).__init__(module, zbx, zapi_wrapper)
- if LooseVersion(self._zbx_api_version) < LooseVersion('4.4.0'):
- module.fail_json(msg="This module doesn't support Zabbix versions lower than 4.4.0")
# get autoregistration
def get_autoregistration(self):
try:
- return self._zapi.autoregistration.get({"output": 'extend'})
+ return self._zapi.autoregistration.get({"output": "extend"})
except Exception as e:
self._module.fail_json(msg="Failed to get autoregistration: %s" % e)
@@ -143,38 +129,38 @@ class Autoregistration(ZabbixBase):
def update_autoregistration(self, current_setting, tls_accept, tls_psk_identity, tls_psk):
tls_accept_values = [
None,
- 'unsecure',
- 'tls_with_psk'
+ "unsecure",
+ "tls_with_psk"
]
params = {}
try:
if isinstance(tls_accept, str):
- params['tls_accept'] = zabbix_utils.helper_to_numeric_value(
+ params["tls_accept"] = zabbix_utils.helper_to_numeric_value(
tls_accept_values, tls_accept
)
elif isinstance(tls_accept, list):
- params['tls_accept'] = 0
+ params["tls_accept"] = 0
for _tls_accept_value in tls_accept:
- params['tls_accept'] += zabbix_utils.helper_to_numeric_value(
+ params["tls_accept"] += zabbix_utils.helper_to_numeric_value(
tls_accept_values, _tls_accept_value
)
else:
self._module.fail_json(msg="Value of tls_accept must be list or string.")
if tls_psk_identity:
- params['tls_psk_identity'] = tls_psk_identity
+ params["tls_psk_identity"] = tls_psk_identity
if tls_psk:
- params['tls_psk'] = tls_psk
+ params["tls_psk"] = tls_psk
- current_tls_accept = int(current_setting['tls_accept'])
- if (current_tls_accept == tls_accept_values.index('unsecure')
- and params['tls_accept'] >= tls_accept_values.index('tls_with_psk')):
+ current_tls_accept = int(current_setting["tls_accept"])
+ if (current_tls_accept == tls_accept_values.index("unsecure")
+ and params["tls_accept"] >= tls_accept_values.index("tls_with_psk")):
if not tls_psk_identity or not tls_psk:
self._module.fail_json(msg="Please set tls_psk_identity and tls_psk.")
if (not tls_psk_identity and not tls_psk
- and params['tls_accept'] == current_tls_accept):
+ and params["tls_accept"] == current_tls_accept):
self._module.exit_json(changed=False, result="Autoregistration is already up to date")
if self._module.check_mode:
@@ -192,32 +178,26 @@ def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
tls_accept=dict(
- type='list',
- elements='str',
+ type="list",
+ elements="str",
required=True
),
- tls_psk_identity=dict(type='str', required=False, no_log=True),
- tls_psk=dict(type='str', required=False, no_log=True),
+ tls_psk_identity=dict(type="str", required=False, no_log=True),
+ tls_psk=dict(type="str", required=False, no_log=True),
))
module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- tls_accept = module.params['tls_accept']
- tls_psk_identity = module.params['tls_psk_identity']
- tls_psk = module.params['tls_psk']
+ tls_accept = module.params["tls_accept"]
+ tls_psk_identity = module.params["tls_psk_identity"]
+ tls_psk = module.params["tls_psk"]
autoregistration_class_obj = Autoregistration(module)
current_setting = autoregistration_class_obj.get_autoregistration()
autoregistration_class_obj.update_autoregistration(current_setting, tls_accept, tls_psk_identity, tls_psk)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_discovery_rule.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_discovery_rule.py
index 11b2f7c7f..2296f3db8 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_discovery_rule.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_discovery_rule.py
@@ -7,7 +7,7 @@
from __future__ import absolute_import, division, print_function
__metaclass__ = type
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
---
module: zabbix_discovery_rule
short_description: Create/delete/update Zabbix discovery rules
@@ -18,7 +18,7 @@ description:
author:
- "Tobias Birkefeld (@tcraxs)"
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
options:
state:
description:
@@ -46,22 +46,22 @@ options:
description:
- Type of check.
type: str
- choices: ['SSH',
- 'LDAP',
- 'SMTP',
- 'FTP',
- 'HTTP',
- 'POP',
- 'NNTP',
- 'IMAP',
- 'TCP',
- 'Zabbix',
- 'SNMPv1',
- 'SNMPv2',
- 'ICMP',
- 'SNMPv3',
- 'HTTPS',
- 'Telnet']
+ choices: ["SSH",
+ "LDAP",
+ "SMTP",
+ "FTP",
+ "HTTP",
+ "POP",
+ "NNTP",
+ "IMAP",
+ "TCP",
+ "Zabbix",
+ "SNMPv1",
+ "SNMPv2",
+ "ICMP",
+ "SNMPv3",
+ "HTTPS",
+ "Telnet"]
ports:
description:
- One or several port ranges to check separated by commas. Used for all checks except for ICMP.
@@ -173,23 +173,22 @@ options:
type: str
default: "enabled"
choices: ["enabled", "disabled"]
-notes:
- - Only Zabbix >= 4.0 is supported.
+
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
# Base create discovery rule example
@@ -201,7 +200,7 @@ EXAMPLES = r'''
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_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_discovery_rule:
name: ACME
@@ -224,7 +223,7 @@ EXAMPLES = r'''
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_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_discovery_rule:
name: ACME
@@ -255,35 +254,35 @@ EXAMPLES = r'''
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_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_discovery_rule:
name: ACME
state: absent
-'''
+"""
-RETURN = r'''
+RETURN = r"""
state:
description: Discovery rule state at the end of execution.
returned: on success
type: str
- sample: 'present'
+ sample: "present"
drule:
description: Discovery rule name.
returned: on success
type: str
- sample: 'ACME'
+ sample: "ACME"
druleid:
description: Discovery rule id.
returned: on success
type: str
- sample: '42'
+ sample: "42"
msg:
description: The result of the operation
returned: always
type: str
- sample: 'Discovery rule created: ACME, ID: 42'
-'''
+ sample: "Discovery rule created: ACME, ID: 42"
+"""
from ansible.module_utils.basic import AnsibleModule
@@ -312,72 +311,71 @@ class Dchecks(ZabbixBase):
constructed_data = []
for check in _dchecks:
constructed_check = {
- 'type': zabbix_utils.helper_to_numeric_value([
- 'SSH',
- 'LDAP',
- 'SMTP',
- 'FTP',
- 'HTTP',
- 'POP',
- 'NNTP',
- 'IMAP',
- 'TCP',
- 'Zabbix',
- 'SNMPv1',
- 'SNMPv2',
- 'ICMP',
- 'SNMPv3',
- 'HTTPS',
- 'Telnet'], check.get('type')
+ "type": zabbix_utils.helper_to_numeric_value([
+ "SSH",
+ "LDAP",
+ "SMTP",
+ "FTP",
+ "HTTP",
+ "POP",
+ "NNTP",
+ "IMAP",
+ "TCP",
+ "Zabbix",
+ "SNMPv1",
+ "SNMPv2",
+ "ICMP",
+ "SNMPv3",
+ "HTTPS",
+ "Telnet"], check.get("type")
),
- 'uniq': int(check.get('uniq'))
+ "uniq": int(check.get("uniq"))
}
- if LooseVersion(self._zbx_api_version) >= LooseVersion('4.4'):
- constructed_check.update({
- 'host_source': zabbix_utils.helper_to_numeric_value([
- 'None',
- 'DNS',
- 'IP',
- 'discovery'], check.get('host_source')
- ),
- 'name_source': zabbix_utils.helper_to_numeric_value([
- 'None',
- 'DNS',
- 'IP',
- 'discovery'], check.get('name_source')
- )
- })
- if constructed_check['type'] in (0, 1, 2, 3, 4, 5, 6, 7, 8, 14, 15):
- constructed_check['ports'] = check.get('ports')
- if constructed_check['type'] == 9:
- constructed_check['ports'] = check.get('ports')
- constructed_check['key_'] = check.get('key')
- if constructed_check['type'] in (10, 11):
- constructed_check['ports'] = check.get('ports')
- constructed_check['snmp_community'] = check.get('snmp_community')
- constructed_check['key_'] = check.get('key')
- if constructed_check['type'] == 13:
- constructed_check['ports'] = check.get('ports')
- constructed_check['key_'] = check.get('key')
- constructed_check['snmpv3_contextname'] = check.get('snmpv3_contextname')
- constructed_check['snmpv3_securityname'] = check.get('snmpv3_securityname')
- constructed_check['snmpv3_securitylevel'] = zabbix_utils.helper_to_numeric_value([
- 'noAuthNoPriv',
- 'authNoPriv',
- 'authPriv'], check.get('snmpv3_securitylevel')
+ constructed_check.update({
+ "host_source": zabbix_utils.helper_to_numeric_value([
+ "None",
+ "DNS",
+ "IP",
+ "discovery"], check.get("host_source")
+ ),
+ "name_source": zabbix_utils.helper_to_numeric_value([
+ "None",
+ "DNS",
+ "IP",
+ "discovery"], check.get("name_source")
+ )
+ })
+ if constructed_check["type"] in (0, 1, 2, 3, 4, 5, 6, 7, 8, 14, 15):
+ constructed_check["ports"] = check.get("ports")
+ if constructed_check["type"] == 9:
+ constructed_check["ports"] = check.get("ports")
+ constructed_check["key_"] = check.get("key")
+ if constructed_check["type"] in (10, 11):
+ constructed_check["ports"] = check.get("ports")
+ constructed_check["snmp_community"] = check.get("snmp_community")
+ constructed_check["key_"] = check.get("key")
+ if constructed_check["type"] == 13:
+ constructed_check["ports"] = check.get("ports")
+ constructed_check["key_"] = check.get("key")
+ constructed_check["snmpv3_contextname"] = check.get("snmpv3_contextname")
+ constructed_check["snmpv3_securityname"] = check.get("snmpv3_securityname")
+ constructed_check["snmpv3_securitylevel"] = zabbix_utils.helper_to_numeric_value([
+ "noAuthNoPriv",
+ "authNoPriv",
+ "authPriv"], check.get("snmpv3_securitylevel")
)
- if constructed_check['snmpv3_securitylevel'] in (1, 2):
- constructed_check['snmpv3_authprotocol'] = zabbix_utils.helper_to_numeric_value([
- 'MD5',
- 'SHA'], check.get('snmpv3_authprotocol')
+ if constructed_check["snmpv3_securitylevel"] in (1, 2):
+ constructed_check["snmpv3_authprotocol"] = zabbix_utils.helper_to_numeric_value([
+ "MD5",
+ "SHA"], check.get("snmpv3_authprotocol")
)
- constructed_check['snmpv3_authpassphrase'] = check.get('snmpv3_authpassphrase')
- if constructed_check['snmpv3_securitylevel'] == 2:
- constructed_check['snmpv3_privprotocol'] = zabbix_utils.helper_to_numeric_value([
- 'DES',
- 'AES'], check.get('snmpv3_privprotocol')
+ constructed_check["snmpv3_authpassphrase"] = check.get("snmpv3_authpassphrase")
+ if constructed_check["snmpv3_securitylevel"] == 2:
+ constructed_check["snmpv3_privprotocol"] = zabbix_utils.helper_to_numeric_value([
+ "DES",
+ "AES"], check.get("snmpv3_privprotocol")
)
- constructed_check['snmpv3_privpassphrase'] = check.get('snmpv3_privpassphrase')
+ constructed_check["snmpv3_privpassphrase"] = check.get("snmpv3_privpassphrase")
constructed_data.append(constructed_check)
return zabbix_utils.helper_cleanup_data(constructed_data)
@@ -392,9 +390,9 @@ class DiscoveryRule(ZabbixBase):
"""
try:
_drule = self._zapi.drule.get({
- 'output': 'extend',
- 'selectDChecks': 'extend',
- 'filter': {'name': [name]}
+ "output": "extend",
+ "selectDChecks": "extend",
+ "filter": {"name": [name]}
})
if len(_drule) > 0:
return _drule
@@ -411,9 +409,9 @@ class DiscoveryRule(ZabbixBase):
"""
try:
drule_list = self._zapi.drule.get({
- 'output': 'extend',
- 'selectDChecks': 'extend',
- 'filter': {'name': [name]}
+ "output": "extend",
+ "selectDChecks": "extend",
+ "filter": {"name": [name]}
})
if len(drule_list) < 1:
self._module.fail_json(msg="Discovery rule not found: %s" % name)
@@ -431,9 +429,9 @@ class DiscoveryRule(ZabbixBase):
"""
try:
proxy_list = self._zapi.proxy.get({
- 'output': 'extend',
- 'selectInterface': 'extend',
- 'filter': {'host': [proxy_name]}
+ "output": "extend",
+ "selectInterface": "extend",
+ "filter": {"host": [proxy_name]}
})
if len(proxy_list) < 1:
self._module.fail_json(msg="Proxy not found: %s" % proxy_name)
@@ -450,17 +448,17 @@ class DiscoveryRule(ZabbixBase):
dict: dictionary of specified parameters
"""
_params = {
- 'name': kwargs['name'],
- 'iprange': ','.join(kwargs['iprange']),
- 'delay': kwargs['delay'],
- 'status': zabbix_utils.helper_to_numeric_value([
- 'enabled',
- 'disabled'], kwargs['status']
+ "name": kwargs["name"],
+ "iprange": ",".join(kwargs["iprange"]),
+ "delay": kwargs["delay"],
+ "status": zabbix_utils.helper_to_numeric_value([
+ "enabled",
+ "disabled"], kwargs["status"]
),
- 'dchecks': kwargs['dchecks']
+ "dchecks": kwargs["dchecks"]
}
- if kwargs['proxy']:
- _params['proxy_hostid'] = self.get_proxy_by_proxy_name(kwargs['proxy'])['proxyid']
+ if kwargs["proxy"]:
+ _params["proxy_hostid"] = self.get_proxy_by_proxy_name(kwargs["proxy"])["proxyid"]
return _params
def check_difference(self, **kwargs):
@@ -470,13 +468,13 @@ class DiscoveryRule(ZabbixBase):
Returns:
dict: dictionary of differences
"""
- existing_drule = zabbix_utils.helper_convert_unicode_to_str(self.check_if_drule_exists(kwargs['name'])[0])
+ existing_drule = zabbix_utils.helper_convert_unicode_to_str(self.check_if_drule_exists(kwargs["name"])[0])
parameters = zabbix_utils.helper_convert_unicode_to_str(self._construct_parameters(**kwargs))
change_parameters = {}
- if LooseVersion(self._zbx_api_version) < LooseVersion('6.4'):
- if existing_drule['nextcheck']:
- existing_drule.pop('nextcheck')
- _diff = zabbix_utils.helper_cleanup_data(compare_dictionaries(parameters, existing_drule, change_parameters))
+ if LooseVersion(self._zbx_api_version) < LooseVersion("6.4"):
+ if existing_drule["nextcheck"]:
+ existing_drule.pop("nextcheck")
+ _diff = zabbix_utils.helper_cleanup_data(zabbix_utils.helper_compare_dictionaries(parameters, existing_drule, change_parameters))
return _diff
def update_drule(self, **kwargs):
@@ -488,11 +486,11 @@ class DiscoveryRule(ZabbixBase):
"""
try:
if self._module.check_mode:
- self._module.exit_json(msg="Discovery rule would be updated if check mode was not specified: ID %s" % kwargs['drule_id'], changed=True)
- kwargs['druleid'] = kwargs.pop('drule_id')
+ self._module.exit_json(msg="Discovery rule would be updated if check mode was not specified: ID %s" % kwargs["drule_id"], changed=True)
+ kwargs["druleid"] = kwargs.pop("drule_id")
return self._zapi.drule.update(kwargs)
except Exception as e:
- self._module.fail_json(msg="Failed to update discovery rule ID '%s': %s" % (kwargs['drule_id'], e))
+ self._module.fail_json(msg="Failed to update discovery rule ID '%s': %s" % (kwargs["drule_id"], e))
def add_drule(self, **kwargs):
"""Add discovery rule
@@ -506,9 +504,9 @@ class DiscoveryRule(ZabbixBase):
self._module.exit_json(msg="Discovery rule would be added if check mode was not specified", changed=True)
parameters = self._construct_parameters(**kwargs)
drule_list = self._zapi.drule.create(parameters)
- return drule_list['druleids'][0]
+ return drule_list["druleids"][0]
except Exception as e:
- self._module.fail_json(msg="Failed to create discovery rule %s: %s" % (kwargs['name'], e))
+ self._module.fail_json(msg="Failed to create discovery rule %s: %s" % (kwargs["name"], e))
def delete_drule(self, drule_id):
"""Delete discovery rule.
@@ -525,159 +523,90 @@ class DiscoveryRule(ZabbixBase):
self._module.fail_json(msg="Failed to delete discovery rule '%s': %s" % (drule_id, e))
-def compare_lists(l1, l2, diff_dict):
- """
- Compares l1 and l2 lists and adds the items that are different
- to the diff_dict dictionary.
- Used in recursion with compare_dictionaries() function.
- Args:
- l1: first list to compare
- l2: second list to compare
- diff_dict: dictionary to store the difference
- Returns:
- dict: items that are different
- """
- if len(l1) != len(l2):
- diff_dict.append(l1)
- return diff_dict
- for i, item in enumerate(l1):
- if isinstance(item, dict):
- diff_dict.insert(i, {})
- diff_dict[i] = compare_dictionaries(item, l2[i], diff_dict[i])
- else:
- if item != l2[i]:
- diff_dict.append(item)
- while {} in diff_dict:
- diff_dict.remove({})
- return diff_dict
-
-
-def compare_dictionaries(d1, d2, diff_dict):
- """
- Compares d1 and d2 dictionaries and adds the items that are different
- to the diff_dict dictionary.
- Used in recursion with compare_lists() function.
- Args:
- d1: first dictionary to compare
- d2: second dictionary to compare
- diff_dict: dictionary to store the difference
- Returns:
- dict: items that are different
- """
- for k, v in d1.items():
- if k not in d2:
- diff_dict[k] = v
- continue
- if isinstance(v, dict):
- diff_dict[k] = {}
- compare_dictionaries(v, d2[k], diff_dict[k])
- if diff_dict[k] == {}:
- del diff_dict[k]
- else:
- diff_dict[k] = v
- elif isinstance(v, list):
- diff_dict[k] = []
- compare_lists(v, d2[k], diff_dict[k])
- if diff_dict[k] == []:
- del diff_dict[k]
- else:
- diff_dict[k] = v
- else:
- if v != d2[k]:
- diff_dict[k] = v
- return diff_dict
-
-
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(
- name=dict(type='str', required=True),
- iprange=dict(type='list', required=False, elements='str'),
+ name=dict(type="str", required=True),
+ iprange=dict(type="list", required=False, elements="str"),
dchecks=dict(
- type='list',
+ type="list",
required=False,
- aliases=['dcheck'],
- elements='dict',
+ aliases=["dcheck"],
+ elements="dict",
options=dict(
- type=dict(type='str', choices=[
- 'SSH',
- 'LDAP',
- 'SMTP',
- 'FTP',
- 'HTTP',
- 'POP',
- 'NNTP',
- 'IMAP',
- 'TCP',
- 'Zabbix',
- 'SNMPv1',
- 'SNMPv2',
- 'ICMP',
- 'SNMPv3',
- 'HTTPS',
- 'Telnet']
+ type=dict(type="str", choices=[
+ "SSH",
+ "LDAP",
+ "SMTP",
+ "FTP",
+ "HTTP",
+ "POP",
+ "NNTP",
+ "IMAP",
+ "TCP",
+ "Zabbix",
+ "SNMPv1",
+ "SNMPv2",
+ "ICMP",
+ "SNMPv3",
+ "HTTPS",
+ "Telnet"]
),
- ports=dict(type='str'),
- key=dict(type='str', no_log=False),
- snmp_community=dict(type='str'),
- snmpv3_authpassphrase=dict(type='str', no_log=True),
- snmpv3_authprotocol=dict(type='str', choices=['MD5', 'SHA']),
- snmpv3_contextname=dict(type='str'),
- snmpv3_privpassphrase=dict(type='str', no_log=True),
- snmpv3_privprotocol=dict(type='str', choices=['DES', 'AES']),
- snmpv3_securitylevel=dict(type='str', choices=['noAuthNoPriv', 'authNoPriv', 'authPriv']),
- snmpv3_securityname=dict(type='str'),
- uniq=dict(type='bool', default=False),
- host_source=dict(type='str', choices=['DNS', 'IP', 'discovery'], default='DNS'),
- name_source=dict(type='str', choices=['None', 'DNS', 'IP', 'discovery'], default='None')
+ ports=dict(type="str"),
+ key=dict(type="str", no_log=False),
+ snmp_community=dict(type="str"),
+ snmpv3_authpassphrase=dict(type="str", no_log=True),
+ snmpv3_authprotocol=dict(type="str", choices=["MD5", "SHA"]),
+ snmpv3_contextname=dict(type="str"),
+ snmpv3_privpassphrase=dict(type="str", no_log=True),
+ snmpv3_privprotocol=dict(type="str", choices=["DES", "AES"]),
+ snmpv3_securitylevel=dict(type="str", choices=["noAuthNoPriv", "authNoPriv", "authPriv"]),
+ snmpv3_securityname=dict(type="str"),
+ uniq=dict(type="bool", default=False),
+ host_source=dict(type="str", choices=["DNS", "IP", "discovery"], default="DNS"),
+ name_source=dict(type="str", choices=["None", "DNS", "IP", "discovery"], default="None")
),
required_if=[
- ['type', 'SSH', ['ports']],
- ['type', 'LDAP', ['ports']],
- ['type', 'SMTP', ['ports']],
- ['type', 'FTP', ['ports']],
- ['type', 'HTTP', ['ports']],
- ['type', 'POP', ['ports']],
- ['type', 'NNTP', ['ports']],
- ['type', 'IMAP', ['ports']],
- ['type', 'TCP', ['ports']],
- ['type', 'Zabbix', ['ports', 'key']],
- ['type', 'SNMPv1', ['ports', 'key', 'snmp_community']],
- ['type', 'SNMPv2', ['ports', 'key', 'snmp_community']],
- ['type', 'SNMPv3', ['ports', 'key']],
- ['type', 'HTTPS', ['ports']],
- ['type', 'Telnet', ['ports']],
- ['snmpv3_securitylevel', 'authPriv', ['snmpv3_privpassphrase']]
+ ["type", "SSH", ["ports"]],
+ ["type", "LDAP", ["ports"]],
+ ["type", "SMTP", ["ports"]],
+ ["type", "FTP", ["ports"]],
+ ["type", "HTTP", ["ports"]],
+ ["type", "POP", ["ports"]],
+ ["type", "NNTP", ["ports"]],
+ ["type", "IMAP", ["ports"]],
+ ["type", "TCP", ["ports"]],
+ ["type", "Zabbix", ["ports", "key"]],
+ ["type", "SNMPv1", ["ports", "key", "snmp_community"]],
+ ["type", "SNMPv2", ["ports", "key", "snmp_community"]],
+ ["type", "SNMPv3", ["ports", "key"]],
+ ["type", "HTTPS", ["ports"]],
+ ["type", "Telnet", ["ports"]],
+ ["snmpv3_securitylevel", "authPriv", ["snmpv3_privpassphrase"]]
]
),
- delay=dict(type='str', required=False, default='1h'),
- proxy=dict(type='str', required=False, default=None),
- status=dict(type='str', default="enabled", choices=["enabled", "disabled"]),
- state=dict(type='str', default='present', choices=['present', 'absent'])
+ delay=dict(type="str", required=False, default="1h"),
+ proxy=dict(type="str", required=False, default=None),
+ status=dict(type="str", default="enabled", choices=["enabled", "disabled"]),
+ state=dict(type="str", default="present", choices=["present", "absent"])
)
module = AnsibleModule(
argument_spec=argument_spec,
required_if=[
- ['state', 'present', ['name', 'iprange', 'dchecks']],
- ['state', 'absent', ['name']],
+ ["state", "present", ["name", "iprange", "dchecks"]],
+ ["state", "absent", ["name"]],
],
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- state = module.params['state']
- name = module.params['name']
- iprange = module.params['iprange']
- dchecks = module.params['dchecks']
- delay = module.params['delay']
- proxy = module.params['proxy']
- status = module.params['status']
+ state = module.params["state"]
+ name = module.params["name"]
+ iprange = module.params["iprange"]
+ dchecks = module.params["dchecks"]
+ delay = module.params["delay"]
+ proxy = module.params["proxy"]
+ status = module.params["status"]
drule = DiscoveryRule(module)
zbx = drule._zapi
@@ -686,7 +615,7 @@ def main():
drule_exists = drule.check_if_drule_exists(name)
if drule_exists:
- drule_id = drule.get_drule_by_drule_name(name)['druleid']
+ drule_id = drule.get_drule_by_drule_name(name)["druleid"]
if state == "absent":
drule.delete_drule(drule_id)
module.exit_json(changed=True, state=state, drule=name, druleid=drule_id, msg="Discovery Rule deleted: %s, ID: %s" % (name, drule_id))
@@ -724,5 +653,5 @@ def main():
module.exit_json(changed=True, state=state, drule=name, druleid=drule_id, msg="Discovery Rule created: %s, ID: %s" % (name, drule_id))
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_globalmacro.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_globalmacro.py
index d0221223b..111c80c55 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_globalmacro.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_globalmacro.py
@@ -8,7 +8,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
---
module: zabbix_globalmacro
short_description: Create/update/delete Zabbix Global macros
@@ -21,7 +21,7 @@ author:
- Dean Hailin Song (!UNKNOWN)
- Timothy Test (@ttestscripting)
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
options:
macro_name:
description:
@@ -46,42 +46,41 @@ options:
macro_description:
description:
- Text Description of the global macro.
- - Works only with Zabbix >= 4.4 and is silently ignored in lower versions
type: str
- default: ''
+ 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']
+ choices: ["present", "absent"]
type: str
default: "present"
force:
description:
- Only updates an existing macro if set to C(yes).
- default: 'yes'
+ default: "yes"
type: bool
notes:
- - This module returns changed=true when I(macro_type=secret) with Zabbix >= 5.0.
+ - This module returns changed=true when I(macro_type=secret).
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: Create new global macro or update an existing macro's value
@@ -92,7 +91,7 @@ EXAMPLES = r'''
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_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
@@ -109,7 +108,7 @@ EXAMPLES = r'''
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_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}"
@@ -121,7 +120,7 @@ EXAMPLES = r'''
community.zabbix.zabbix_globalmacro:
macro_name: "{$EXAMPLE.MACRO}"
state: absent
-'''
+"""
RETURN = r"""
"""
@@ -130,7 +129,6 @@ RETURN = r"""
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.zabbix.plugins.module_utils.base import ZabbixBase
-from ansible.module_utils.compat.version import LooseVersion
import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabbix_utils
@@ -139,8 +137,8 @@ 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]
+ 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
@@ -152,61 +150,30 @@ class GlobalMacro(ZabbixBase):
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
- if LooseVersion(self._zbx_api_version) < LooseVersion('4.4.0'):
- self._zapi.usermacro.createglobal({'macro': macro_name, 'value': macro_value})
- self._module.exit_json(changed=True, result="Successfully added global macro %s" % macro_name)
- if LooseVersion(self._zbx_api_version) >= LooseVersion('4.4.0'):
- if LooseVersion(self._zbx_api_version) >= LooseVersion('5.0.0'):
- if LooseVersion(self._zbx_api_version) < LooseVersion('5.2.0'):
- if macro_type == '2':
- macro_type = '0'
- 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)
- else:
- self._zapi.usermacro.createglobal({'macro': macro_name, 'value': macro_value, 'description': macro_description})
- self._module.exit_json(changed=True, result="Successfully added global macro %s" % macro_name)
+ 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']
+ global_macro_id = global_macro_obj["globalmacroid"]
try:
- if LooseVersion(self._zbx_api_version) < LooseVersion('4.4.0'):
- if global_macro_obj['macro'] == macro_name and global_macro_obj['value'] == macro_value:
+ 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})
- self._module.exit_json(changed=True, result="Successfully updated global macro %s" % macro_name)
- elif LooseVersion(self._zbx_api_version) >= LooseVersion('5.0.0'):
- if LooseVersion(self._zbx_api_version) < LooseVersion('5.2.0'):
- if macro_type == '2':
- macro_type = '0'
- 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)
- else:
- if (global_macro_obj['macro'] == macro_name and global_macro_obj['value'] == macro_value
- 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, 'description': macro_description})
- self._module.exit_json(changed=True, result="Successfully updated global macro %s" % 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']
+ global_macro_id = global_macro_obj["globalmacroid"]
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
@@ -218,16 +185,16 @@ class GlobalMacro(ZabbixBase):
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:])])
+ 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 + '}'
+ if not macro_name.startswith("{$"):
+ macro_name = "{$" + macro_name
+ if not macro_name.endswith("}"):
+ macro_name = macro_name + "}"
return macro_name
@@ -235,48 +202,42 @@ def normalize_macro_name(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)
+ 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']]
+ ["state", "present", ["macro_value"]]
],
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- 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'
+ 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 state == "absent":
if not global_macro_obj:
module.exit_json(changed=False, msg="Global Macro %s does not exist" % macro_name)
else:
@@ -293,5 +254,5 @@ def main():
module.exit_json(changed=False, result="Global macro %s already exists and force is set to no" % macro_name)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_group.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_group.py
index 0426f9336..3eb39ab24 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_group.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_group.py
@@ -47,14 +47,14 @@ notes:
EXAMPLES = r'''
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
# Base create host groups example
@@ -94,17 +94,6 @@ EXAMPLES = r'''
'''
-import traceback
-
-try:
- from zabbix_api import Already_Exists
-
- HAS_ZABBIX_API = True
- ZBX_IMP_ERR = Exception()
-except ImportError:
- ZBX_IMP_ERR = traceback.format_exc()
- HAS_ZABBIX_API = False
-
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.zabbix.plugins.module_utils.base import ZabbixBase
@@ -119,13 +108,10 @@ class HostGroup(ZabbixBase):
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
+ if self._module.check_mode:
+ self._module.exit_json(changed=True)
+ self._zapi.hostgroup.create({'name': group_name})
+ group_add_list.append(group_name)
return group_add_list
except Exception as e:
self._module.fail_json(msg="Failed to create host group(s): %s" % e)
@@ -153,7 +139,7 @@ class HostGroup(ZabbixBase):
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- host_groups=dict(type='list', required=True, aliases=['host_group']),
+ host_groups=dict(type='list', required=True, aliases=['host_group'], elements='str'),
state=dict(type='str', default="present", choices=['present', 'absent']),
))
module = AnsibleModule(
@@ -161,12 +147,6 @@ def main():
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password']:
- if p in module.params and module.params[p] and module.params[p]:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
host_groups = module.params['host_groups']
state = module.params['state']
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_group_events_info.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_group_events_info.py
new file mode 100644
index 000000000..e41cab26f
--- /dev/null
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_group_events_info.py
@@ -0,0 +1,283 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# built by Martin Eiswirth (@meis4h) on top of the work by Stéphane Travassac (@stravassac) on zabbix_host_events_info.py
+# and Michael Miko (@RedWhiteMiko) on zabbix_group_info.py
+# 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
+
+RETURN = """
+---
+triggers_ok:
+ description: 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: 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_group_events_info
+short_description: Get all triggers about a Zabbix group
+description:
+ - This module allows you to check the state of triggers of all hosts in a Zabbix hostgroup.
+author:
+ - "Martin Eiswirth (@meis4h)"
+requirements:
+ - "python >= 3.9"
+options:
+ hostgroup_name:
+ description:
+ - Name of the hostgroup in Zabbix.
+ required: true
+ type: list
+ elements: 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.zabbix.zabbix
+
+"""
+
+EXAMPLES = """
+# If you want to use Username and Password to be authenticated by Zabbix Server
+- name: Set credentials to access Zabbix Server API
+ 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
+ set_fact:
+ ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
+
+- name: Fail if alert active in hostgroup
+ # 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_group_events_info:
+ hostgroup_name: "{{ inventory_hostname }}"
+ register: zbx_hostgroup
+ delegate_to: localhost
+- fail:
+ msg: "Active alert in zabbix"
+ when: zbx_hostgroup["triggers_problem"] | length > 0
+"""
+
+
+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 Host(ZabbixBase):
+ 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 get_triggers_by_group_id_in_problem_state(self, group_id, trigger_severity):
+ """ Get triggers in problem state from a groupid"""
+ output = "extend"
+ triggers_list = self._zapi.trigger.get({"output": output, "groupids": group_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():
+ argument_spec = zabbix_utils.zabbix_common_argument_spec()
+ argument_spec.update(dict(
+ hostgroup_name=dict(type="list", required=True, elements="str"),
+ trigger_severity=dict(
+ type="str",
+ required=False,
+ default="average",
+ choices=["not_classified", "information", "warning", "average", "high", "disaster"]),
+ ))
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True
+ )
+
+ trigger_severity_map = {"not_classified": 0, "information": 1, "warning": 2, "average": 3, "high": 4, "disaster": 5}
+ trigger_severity = trigger_severity_map[module.params["trigger_severity"]]
+
+ hostgroup_name = module.params["hostgroup_name"]
+
+ host = Host(module)
+ host_groups = host.get_group_ids_by_group_names(hostgroup_name)
+ triggers = []
+
+ for host_group in host_groups:
+ host_group_id = host_group["groupid"]
+ host_group_triggers = host.get_triggers_by_group_id_in_problem_state(host_group_id, trigger_severity)
+ triggers = triggers + host_group_triggers
+
+ 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, host_groups=host_groups, triggers_ok=triggers_ok, triggers_problem=triggers_problem)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_group_facts.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_group_facts.py
deleted file mode 100644
index b3f693052..000000000
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_group_facts.py
+++ /dev/null
@@ -1,115 +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
-
-
-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"
-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.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
- 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
- set_fact:
- ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
-
-- name: Get hostgroup info
- # 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_group_info:
- hostgroup_name:
- - ExampleHostgroup
- timeout: 10
-'''
-
-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 Host(ZabbixBase):
- 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():
- argument_spec = zabbix_utils.zabbix_common_argument_spec()
- argument_spec.update(dict(
- hostgroup_name=dict(type='list', required=True),
- ))
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True
- )
-
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- if module._name == 'zabbix_group_facts':
- module.deprecate("The 'zabbix_group_facts' module has been renamed to 'zabbix_group_info'",
- collection_name="community.zabbix", version='2.0.0') # was 2.13
-
- hostgroup_name = module.params['hostgroup_name']
-
- host = Host(module)
- host_groups = host.get_group_ids_by_group_names(hostgroup_name)
- module.exit_json(host_groups=host_groups)
-
-
-if __name__ == '__main__':
- main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_group_info.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_group_info.py
index b3f693052..02784c366 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_group_info.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_group_info.py
@@ -8,16 +8,16 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
-RETURN = r'''
+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'''
+DOCUMENTATION = r"""
---
module: zabbix_group_info
short_description: Gather information about Zabbix hostgroup
@@ -27,7 +27,7 @@ description:
author:
- "Michael Miko (@RedWhiteMiko)"
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
options:
hostgroup_name:
description:
@@ -39,19 +39,19 @@ options:
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: Get hostgroup info
@@ -62,13 +62,12 @@ EXAMPLES = r'''
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_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_group_info:
hostgroup_name:
- ExampleHostgroup
- timeout: 10
-'''
+"""
from ansible.module_utils.basic import AnsibleModule
@@ -78,7 +77,7 @@ import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabb
class Host(ZabbixBase):
def get_group_ids_by_group_names(self, group_names):
- group_list = self._zapi.hostgroup.get({'output': 'extend', 'filter': {'name': 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
@@ -87,29 +86,19 @@ class Host(ZabbixBase):
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- hostgroup_name=dict(type='list', required=True),
+ hostgroup_name=dict(type="list", required=True, elements="str"),
))
module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- if module._name == 'zabbix_group_facts':
- module.deprecate("The 'zabbix_group_facts' module has been renamed to 'zabbix_group_info'",
- collection_name="community.zabbix", version='2.0.0') # was 2.13
-
- hostgroup_name = module.params['hostgroup_name']
+ hostgroup_name = module.params["hostgroup_name"]
host = Host(module)
host_groups = host.get_group_ids_by_group_names(hostgroup_name)
module.exit_json(host_groups=host_groups)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_host.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_host.py
index c43742378..22e14d17d 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_host.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_host.py
@@ -8,7 +8,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
---
module: zabbix_host
short_description: Create/update/delete Zabbix hosts
@@ -21,7 +21,7 @@ author:
- Werner Dijkerman (@dj-wasabi)
- Eike Frost (@eikef)
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
options:
host_name:
description:
@@ -51,27 +51,27 @@ options:
inventory_mode:
description:
- Configure the inventory mode.
- choices: ['automatic', 'manual', 'disabled']
+ choices: ["automatic", "manual", "disabled"]
type: str
inventory_zabbix:
description:
- Add Facts for a zabbix inventory (e.g. Tag) (see example below).
- Please review the interface documentation for more information on the supported properties
- - U(https://www.zabbix.com/documentation/3.2/manual/api/reference/host/object#host_inventory)
+ - U(https://www.zabbix.com/documentation/current/en/manual/api/reference/host/object#host-inventory)
type: dict
status:
description:
- Monitoring status of the host.
- choices: ['enabled', 'disabled']
- default: 'enabled'
+ choices: ["enabled", "disabled"]
+ default: "enabled"
type: str
state:
description:
- State of the host.
- On C(present), it will create if host does not exist or update the host if the associated data is different.
- On C(absent) will remove a host if it exists.
- choices: ['present', 'absent']
- default: 'present'
+ choices: ["present", "absent"]
+ default: "present"
type: str
proxy:
description:
@@ -83,7 +83,7 @@ options:
description:
- List of interfaces to be created for the host (see example below).
- For more information, review host interface documentation at
- - U(https://www.zabbix.com/documentation/4.0/manual/api/reference/hostinterface/object)
+ - U(https://www.zabbix.com/documentation/current/en/manual/api/reference/hostinterface/object#host-interface)
default: []
suboptions:
type:
@@ -95,7 +95,7 @@ options:
- 2 = snmp
- 3 = ipmi
- 4 = jmx
- choices: ['agent', '1', 'snmp', '2', 'ipmi', '3', 'jmx', '4']
+ choices: ["agent", "1", "snmp", "2", "ipmi", "3", "jmx", "4"]
required: true
main:
type: int
@@ -127,26 +127,15 @@ options:
description:
- Port used by host interface.
- If not specified, default port for each type of interface is used
- - 10050 if I(type='agent')
- - 161 if I(type='snmp')
- - 623 if I(type='ipmi')
- - 12345 if I(type='jmx')
- bulk:
- type: int
- description:
- - Whether to use bulk SNMP requests.
- - Only valid when interface I(type='snmp').
- - 0 (don't use bulk requests), 1 (use bulk requests)
- - Works only with Zabbix <= 4.4 and is silently ignored in higher versions.
- - Use I(details) with Zabbix >= 5.0.
- choices: [0, 1]
- default: 1
+ - 10050 if I(type="agent")
+ - 161 if I(type="snmp")
+ - 623 if I(type="ipmi")
+ - 12345 if I(type="jmx")
details:
type: dict
description:
- Additional details for SNMP host interfaces.
- - Required when I(type='snmp').
- - Works only with Zabbix >= 5.0.
+ - Required when I(type="snmp").
default: {}
suboptions:
version:
@@ -168,17 +157,17 @@ options:
description:
- SNMPv1 and SNMPv2 community string.
- Required when I(version=1) or I(version=2).
- default: ''
+ default: ""
securityname:
type: str
description:
- SNMPv3 security name.
- default: ''
+ default: ""
contextname:
type: str
description:
- SNMPv3 context name.
- default: ''
+ default: ""
securitylevel:
type: int
description:
@@ -200,7 +189,7 @@ options:
description:
- SNMPv3 authentication passphrase.
- Used when I(securitylevel=1)(authNoPriv) or I(securitylevel=2)(AuthPriv).
- default: ''
+ default: ""
privprotocol:
type: int
description:
@@ -215,12 +204,11 @@ options:
description:
- SNMPv3 privacy passphrase.
- Used when I(securitylevel=2)(AuthPriv).
- default: ''
+ default: ""
tls_connect:
description:
- Specifies what encryption to use for outgoing connections.
- Possible values, 1 (no encryption), 2 (PSK), 4 (certificate).
- - Works only with >= Zabbix 3.0
type: int
tls_accept:
description:
@@ -228,7 +216,6 @@ options:
- The tls_accept parameter accepts values of 1 to 7
- Possible values, 1 (no encryption), 2 (PSK), 4 (certificate).
- Values can be combined.
- - Works only with >= Zabbix 3.0
type: int
tls_psk_identity:
description:
@@ -241,25 +228,22 @@ options:
description:
- PSK value is a hard to guess string of hexadecimal digits.
- The preshared key, at least 32 hex digits. Required if either I(tls_connect) or I(tls_accept) has PSK enabled.
- - Works only with >= Zabbix 3.0
- - Using this parameter with Zabbix >= 5.4 makes this module non-idempotent.
+ - Using this parameter makes this module non-idempotent.
type: str
ca_cert:
description:
- Required certificate issuer.
- - Works only with >= Zabbix 3.0
aliases: [ tls_issuer ]
type: str
tls_subject:
description:
- Required certificate subject.
- - Works only with >= Zabbix 3.0
type: str
ipmi_authtype:
description:
- IPMI authentication algorithm.
- Please review the Host object documentation for more information on the supported properties
- - 'https://www.zabbix.com/documentation/3.4/manual/api/reference/host/object'
+ - "https://www.zabbix.com/documentation/3.4/manual/api/reference/host/object"
- Possible values are, C(0) (none), C(1) (MD2), C(2) (MD5), C(4) (straight), C(5) (OEM), C(6) (RMCP+),
with -1 being the API default.
- Please note that the Zabbix API will treat absent settings as default when updating
@@ -270,7 +254,7 @@ options:
description:
- IPMI privilege level.
- Please review the Host object documentation for more information on the supported properties
- - 'https://www.zabbix.com/documentation/3.4/manual/api/reference/host/object'
+ - "https://www.zabbix.com/documentation/3.4/manual/api/reference/host/object"
- Possible values are C(1) (callback), C(2) (user), C(3) (operator), C(4) (admin), C(5) (OEM), with C(2)
being the API default.
- also see the last note in the I(ipmi_authtype) documentation
@@ -289,7 +273,7 @@ options:
description:
- Overwrite the host configuration, even if already present.
type: bool
- default: 'yes'
+ default: "yes"
macros:
description:
- List of user macros to assign to the zabbix host.
@@ -311,14 +295,12 @@ options:
description:
description:
- Description of the user macro.
- - Works only with >= Zabbix 4.4.
type: str
required: false
- default: ''
+ default: ""
type:
description:
- Type of the macro.
- - Works only with >= Zabbix 5.0.
- Since value is not returned by API for secret macros, there is no reliable way to
detect changes in the content of secret macro value.
- To update secret macro value, please update description alongside it so it passes
@@ -331,7 +313,6 @@ options:
tags:
description:
- List of host tags to assign to the zabbix host.
- - Works only with >= Zabbix 4.2.
- Providing I(tags=[]) with I(force=yes) will clean all of the tags from the host.
type: list
elements: dict
@@ -345,25 +326,25 @@ options:
description:
- Value of the host tag.
type: str
- default: ''
+ default: ""
aliases: [ host_tags ]
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: Create a new host or rewrite an existing host's info
@@ -374,7 +355,7 @@ EXAMPLES = r'''
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_zabbix_url_path: "zabbixeu" # If Zabbix WebUI runs on non-default (zabbix) path ,e.g. http://<FQDN>/zabbixeu
become: false
delegate_to: zabbix-example-fqdn.org# you can use delegate_to or task level ansible_host like next example
community.zabbix.zabbix_host:
@@ -417,7 +398,7 @@ EXAMPLES = r'''
port: "12345"
proxy: a.zabbix.proxy
macros:
- - macro: '{$EXAMPLEMACRO}'
+ - macro: "{$EXAMPLEMACRO}"
value: ExampleMacroValue
- macro: EXAMPLEMACRO2
value: ExampleMacroValue2
@@ -435,7 +416,7 @@ EXAMPLES = r'''
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_zabbix_url_path: "zabbixeu" # If Zabbix WebUI runs on non-default (zabbix) path ,e.g. http://<FQDN>/zabbixeu
ansible_host: zabbix-example-fqdn.org # you can use task level ansible_host or delegate_to like in previous example
become: false
community.zabbix.zabbix_host:
@@ -447,7 +428,7 @@ EXAMPLES = r'''
tls_connect: 2
tls_psk: 123456789abcdef123456789abcdef12
force: false
-'''
+"""
import copy
@@ -455,7 +436,6 @@ import copy
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.zabbix.plugins.module_utils.base import ZabbixBase
-from ansible.module_utils.compat.version import LooseVersion
import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabbix_utils
@@ -463,13 +443,13 @@ import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabb
class Host(ZabbixBase):
# exist host
def is_host_exist(self, host_name):
- result = self._zapi.host.get({'filter': {'host': host_name}})
+ result = self._zapi.host.get({"filter": {"host": host_name}})
return result
# 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}})
+ 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
@@ -479,11 +459,11 @@ class Host(ZabbixBase):
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}})
+ template_list = self._zapi.template.get({"output": "extend", "filter": {"host": template}})
if len(template_list) < 1:
self._module.fail_json(msg="Template not found: %s" % template)
else:
- template_id = template_list[0]['templateid']
+ template_id = template_list[0]["templateid"]
template_ids.append(template_id)
return template_ids
@@ -493,83 +473,88 @@ class Host(ZabbixBase):
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
- parameters = {'host': host_name, 'interfaces': interfaces, 'groups': group_ids, 'status': status}
+ parameters = {"host": host_name, "interfaces": interfaces, "groups": group_ids, "status": status}
if proxy_id:
- parameters['proxy_hostid'] = proxy_id
+ parameters["proxy_hostid"] = proxy_id
if visible_name:
- parameters['name'] = visible_name
+ parameters["name"] = visible_name
if tls_connect:
- parameters['tls_connect'] = tls_connect
+ parameters["tls_connect"] = tls_connect
if tls_accept:
- parameters['tls_accept'] = tls_accept
+ parameters["tls_accept"] = tls_accept
if tls_psk_identity is not None:
- parameters['tls_psk_identity'] = tls_psk_identity
+ parameters["tls_psk_identity"] = tls_psk_identity
if tls_psk is not None:
- parameters['tls_psk'] = tls_psk
+ parameters["tls_psk"] = tls_psk
if tls_issuer is not None:
- parameters['tls_issuer'] = tls_issuer
+ parameters["tls_issuer"] = tls_issuer
if tls_subject is not None:
- parameters['tls_subject'] = tls_subject
+ parameters["tls_subject"] = tls_subject
if description:
- parameters['description'] = description
+ parameters["description"] = description
if ipmi_authtype is not None:
- parameters['ipmi_authtype'] = ipmi_authtype
+ parameters["ipmi_authtype"] = ipmi_authtype
if ipmi_privilege is not None:
- parameters['ipmi_privilege'] = ipmi_privilege
+ parameters["ipmi_privilege"] = ipmi_privilege
if ipmi_username is not None:
- parameters['ipmi_username'] = ipmi_username
+ parameters["ipmi_username"] = ipmi_username
if ipmi_password is not None:
- parameters['ipmi_password'] = ipmi_password
+ parameters["ipmi_password"] = ipmi_password
if macros is not None:
- parameters['macros'] = macros
+ parameters["macros"] = macros
if tags is not None:
- parameters['tags'] = tags
+ parameters["tags"] = tags
host_list = self._zapi.host.create(parameters)
if len(host_list) >= 1:
- return host_list['hostids'][0]
+ return host_list["hostids"][0]
except Exception as e:
self._module.fail_json(msg="Failed to create host %s: %s" % (host_name, e))
def update_host(self, host_name, group_ids, status, host_id, interfaces, exist_interface_list, proxy_id,
visible_name, description, tls_connect, tls_accept, tls_psk_identity, tls_psk, tls_issuer,
- tls_subject, ipmi_authtype, ipmi_privilege, ipmi_username, ipmi_password, macros, tags):
+ tls_subject, ipmi_authtype, ipmi_privilege, ipmi_username, ipmi_password, macros, tags, discovered_host):
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
- parameters = {'hostid': host_id, 'groups': group_ids, 'status': status}
- if proxy_id >= 0:
- parameters['proxy_hostid'] = proxy_id
- if visible_name:
- parameters['name'] = visible_name
- if tls_connect:
- parameters['tls_connect'] = tls_connect
- if tls_accept:
- parameters['tls_accept'] = tls_accept
- if tls_psk_identity:
- parameters['tls_psk_identity'] = tls_psk_identity
- if tls_psk:
- parameters['tls_psk'] = tls_psk
- if tls_issuer:
- parameters['tls_issuer'] = tls_issuer
- if tls_subject:
- parameters['tls_subject'] = tls_subject
- if description:
- parameters['description'] = description
- if ipmi_authtype:
- parameters['ipmi_authtype'] = ipmi_authtype
- if ipmi_privilege:
- parameters['ipmi_privilege'] = ipmi_privilege
- if ipmi_username:
- parameters['ipmi_username'] = ipmi_username
- if ipmi_password:
- parameters['ipmi_password'] = ipmi_password
+ if discovered_host:
+ # The host was discovered via Discovery Rule
+ parameters = {"hostid": host_id, "status": status}
+ else:
+ # A "plain" host
+ parameters = {"hostid": host_id, "groups": group_ids, "status": status}
+ if proxy_id >= 0:
+ parameters["proxy_hostid"] = proxy_id
+ if visible_name:
+ parameters["name"] = visible_name
+ if tls_connect:
+ parameters["tls_connect"] = tls_connect
+ if tls_accept:
+ parameters["tls_accept"] = tls_accept
+ if tls_psk_identity:
+ parameters["tls_psk_identity"] = tls_psk_identity
+ if tls_psk:
+ parameters["tls_psk"] = tls_psk
+ if tls_issuer:
+ parameters["tls_issuer"] = tls_issuer
+ if tls_subject:
+ parameters["tls_subject"] = tls_subject
+ if description:
+ parameters["description"] = description
+ if ipmi_authtype:
+ parameters["ipmi_authtype"] = ipmi_authtype
+ if ipmi_privilege:
+ parameters["ipmi_privilege"] = ipmi_privilege
+ if ipmi_username:
+ parameters["ipmi_username"] = ipmi_username
+ if ipmi_password:
+ parameters["ipmi_password"] = ipmi_password
+ if interfaces:
+ parameters["interfaces"] = interfaces
if macros is not None:
- parameters['macros'] = macros
+ parameters["macros"] = macros
if tags is not None:
- parameters['tags'] = tags
- if interfaces:
- parameters['interfaces'] = interfaces
+ parameters["tags"] = tags
self._zapi.host.update(parameters)
except Exception as e:
@@ -586,49 +571,42 @@ class Host(ZabbixBase):
# get host by host name
def get_host_by_host_name(self, host_name):
params = {
- 'output': 'extend',
- 'selectInventory': 'extend',
- 'selectMacros': 'extend',
- 'filter': {
- 'host': [host_name]
+ "output": [
+ "inventory_mode",
+ "hostid",
+ "proxy_hostid",
+ "host",
+ "status",
+ "lastaccess",
+ "ipmi_authtype",
+ "ipmi_privilege",
+ "ipmi_username",
+ "ipmi_password",
+ "maintenanceid",
+ "maintenance_status",
+ "maintenance_type",
+ "maintenance_from",
+ "name",
+ "flags",
+ "templateid",
+ "description",
+ "tls_connect",
+ "tls_accept",
+ "tls_issuer",
+ "tls_subject",
+ "proxy_address",
+ "auto_compress",
+ "custom_interfaces",
+ "uuid"
+ ],
+ "selectInventory": "extend",
+ "selectMacros": "extend",
+ "selectTags": ["tag", "value"],
+ "filter": {
+ "host": [host_name]
}
}
- if LooseVersion(self._zbx_api_version) >= LooseVersion('4.2.0'):
- params.update({'selectTags': ['tag', 'value']})
-
- if LooseVersion(self._zbx_api_version) >= LooseVersion('5.4.0'):
- params.update({
- 'output': [
- "inventory_mode",
- "hostid",
- "proxy_hostid",
- "host",
- "status",
- "lastaccess",
- "ipmi_authtype",
- "ipmi_privilege",
- "ipmi_username",
- "ipmi_password",
- "maintenanceid",
- "maintenance_status",
- "maintenance_type",
- "maintenance_from",
- "name",
- "flags",
- "templateid",
- "description",
- "tls_connect",
- "tls_accept",
- "tls_issuer",
- "tls_subject",
- "proxy_address",
- "auto_compress",
- "custom_interfaces",
- "uuid"
- ]
- })
-
host_list = self._zapi.host.get(params)
if len(host_list) < 1:
self._module.fail_json(msg="Host not found: %s" % host_name)
@@ -637,27 +615,27 @@ class Host(ZabbixBase):
# get proxyid by proxy name
def get_proxyid_by_proxy_name(self, proxy_name):
- proxy_list = self._zapi.proxy.get({'output': 'extend', 'filter': {'host': [proxy_name]}})
+ proxy_list = self._zapi.proxy.get({"output": "extend", "filter": {"host": [proxy_name]}})
if len(proxy_list) < 1:
self._module.fail_json(msg="Proxy not found: %s" % proxy_name)
else:
- return int(proxy_list[0]['proxyid'])
+ return int(proxy_list[0]["proxyid"])
# get group ids by group names
def get_group_ids_by_group_names(self, group_names):
if self.check_host_group_exist(group_names):
- return self._zapi.hostgroup.get({'output': 'extend', 'filter': {'name': group_names}})
+ return self._zapi.hostgroup.get({"output": "extend", "filter": {"name": group_names}})
# get host groups ids by host id
def get_group_ids_by_host_id(self, host_id):
- return self._zapi.hostgroup.get({'output': 'extend', 'hostids': host_id})
+ return self._zapi.hostgroup.get({"output": "extend", "hostids": host_id})
# get host templates by host id
def get_host_templates_by_host_id(self, host_id):
template_ids = []
- template_list = self._zapi.template.get({'output': 'extend', 'hostids': host_id})
+ template_list = self._zapi.template.get({"output": "extend", "hostids": host_id})
for template in template_list:
- template_ids.append(template['templateid'])
+ template_ids.append(template["templateid"])
return template_ids
def construct_host_interfaces(self, interfaces):
@@ -671,45 +649,40 @@ class Host(ZabbixBase):
and ip is any IP address found on interface of type agent (printing purposes only).
"""
ip = ""
- interface_types = {'agent': 1, 'snmp': 2, 'ipmi': 3, 'jmx': 4}
- type_to_port = {1: '10050', 2: '161', 3: '623', 4: '12345'}
+ interface_types = {"agent": 1, "snmp": 2, "ipmi": 3, "jmx": 4}
+ type_to_port = {1: "10050", 2: "161", 3: "623", 4: "12345"}
for interface in interfaces:
- if interface['type'] in list(interface_types.keys()):
- interface['type'] = interface_types[interface['type']]
+ if interface["type"] in list(interface_types.keys()):
+ interface["type"] = interface_types[interface["type"]]
else:
- interface['type'] = int(interface['type'])
+ interface["type"] = int(interface["type"])
- if interface['type'] == 1:
- ip = interface.get('ip', '')
+ if interface["type"] == 1:
+ ip = interface.get("ip", "")
- for key in ['ip', 'dns']:
+ for key in ["ip", "dns"]:
if key not in interface or interface[key] is None:
- interface[key] = ''
-
- if 'port' not in interface or interface['port'] is None:
- interface['port'] = type_to_port.get(interface['type'], '')
+ interface[key] = ""
- if LooseVersion(self._zbx_api_version) >= LooseVersion('5.0.0'):
- if 'bulk' in interface:
- del interface['bulk']
+ if "port" not in interface or interface["port"] is None:
+ interface["port"] = type_to_port.get(interface["type"], "")
- # Not handled in argument_spec with required_if since only SNMP interfaces are using details
- if interface['type'] == 2:
- if not interface['details']:
- self._module.fail_json(msg='Option "details" required for SNMP interface {0}'.format(interface))
+ if "bulk" in interface:
+ del interface["bulk"]
- i_details = interface['details']
- if i_details['version'] < 3 and not i_details.get('community', False):
- self._module.fail_json(
- msg='Option "community" is required in "details" for SNMP interface {0}'.format(interface))
+ # Not handled in argument_spec with required_if since only SNMP interfaces are using details
+ if interface["type"] == 2:
+ if not interface["details"]:
+ self._module.fail_json(msg="Option 'details' required for SNMP interface {0}".format(interface))
- else:
- interface['details'] = {}
+ i_details = interface["details"]
+ if i_details["version"] < 3 and not i_details.get("community", False):
+ self._module.fail_json(
+ msg="Option 'community' is required in 'details' for SNMP interface {0}".format(interface))
else:
- if 'details' in interface:
- del interface['details']
+ interface["details"] = {}
return (interfaces, ip)
@@ -735,7 +708,7 @@ class Host(ZabbixBase):
# get the status of host by host
def get_host_status_by_host(self, host):
- return host['status']
+ return host["status"]
# check all the properties before link or clear template
def check_all_properties(self, host_id, group_ids, status, interfaces, template_ids,
@@ -744,8 +717,8 @@ class Host(ZabbixBase):
tls_issuer, tls_subject, tls_connect, ipmi_authtype, ipmi_privilege,
ipmi_username, ipmi_password, macros, tags):
# get the existing host's groups
- exist_host_groups = sorted(self.get_group_ids_by_host_id(host_id), key=lambda k: k['groupid'])
- if sorted(group_ids, key=lambda k: k['groupid']) != exist_host_groups:
+ exist_host_groups = sorted(self.get_group_ids_by_host_id(host_id), key=lambda k: k["groupid"])
+ if sorted(group_ids, key=lambda k: k["groupid"]) != exist_host_groups:
return True
# get the existing status
@@ -762,97 +735,82 @@ class Host(ZabbixBase):
if set(list(template_ids)) != set(exist_template_ids):
return True
- if int(host['proxy_hostid']) != int(proxy_id):
+ if int(host["proxy_hostid"]) != int(proxy_id):
return True
# Check whether the visible_name has changed; Zabbix defaults to the technical hostname if not set.
if visible_name:
- if host['name'] != visible_name:
+ if host["name"] != visible_name:
return True
# Only compare description if it is given as a module parameter
if description:
- if host['description'] != description:
+ if host["description"] != description:
return True
if inventory_mode:
- if LooseVersion(self._zbx_api_version) <= LooseVersion('4.4.0'):
- if host['inventory']:
- if int(host['inventory']['inventory_mode']) != self.inventory_mode_numeric(inventory_mode):
- return True
- elif inventory_mode != 'disabled':
- return True
- else:
- if int(host['inventory_mode']) != self.inventory_mode_numeric(inventory_mode):
- return True
+ if int(host["inventory_mode"]) != self.inventory_mode_numeric(inventory_mode):
+ return True
if inventory_zabbix:
- proposed_inventory = copy.deepcopy(host['inventory'])
+ proposed_inventory = copy.deepcopy(host["inventory"])
proposed_inventory.update(inventory_zabbix)
- if proposed_inventory != host['inventory']:
+ if proposed_inventory != host["inventory"]:
return True
- if tls_accept is not None and 'tls_accept' in host:
- if int(host['tls_accept']) != tls_accept:
+ if tls_accept is not None and "tls_accept" in host:
+ if int(host["tls_accept"]) != tls_accept:
return True
- if LooseVersion(self._zbx_api_version) < LooseVersion('5.4'):
- if tls_psk_identity is not None and 'tls_psk_identity' in host:
- if host['tls_psk_identity'] != tls_psk_identity:
- return True
- if tls_psk is not None and 'tls_psk' in host:
- if host['tls_psk'] != tls_psk:
- return True
- else:
- # in Zabbix >= 5.4 these parameters are write-only and are not returned in host.get response
- if tls_psk_identity is not None or tls_psk is not None:
- return True
+ # in Zabbix >= 5.4 these parameters are write-only and are not returned in host.get response
+ if tls_psk_identity is not None or tls_psk is not None:
+ return True
- if tls_issuer is not None and 'tls_issuer' in host:
- if host['tls_issuer'] != tls_issuer:
+ if tls_issuer is not None and "tls_issuer" in host:
+ if host["tls_issuer"] != tls_issuer:
return True
- if tls_subject is not None and 'tls_subject' in host:
- if host['tls_subject'] != tls_subject:
+ if tls_subject is not None and "tls_subject" in host:
+ if host["tls_subject"] != tls_subject:
return True
- if tls_connect is not None and 'tls_connect' in host:
- if int(host['tls_connect']) != tls_connect:
+ if tls_connect is not None and "tls_connect" in host:
+ if int(host["tls_connect"]) != tls_connect:
return True
if ipmi_authtype is not None:
- if int(host['ipmi_authtype']) != ipmi_authtype:
+ if int(host["ipmi_authtype"]) != ipmi_authtype:
return True
if ipmi_privilege is not None:
- if int(host['ipmi_privilege']) != ipmi_privilege:
+ if int(host["ipmi_privilege"]) != ipmi_privilege:
return True
if ipmi_username is not None:
- if host['ipmi_username'] != ipmi_username:
+ if host["ipmi_username"] != ipmi_username:
return True
if ipmi_password is not None:
- if host['ipmi_password'] != ipmi_password:
+ if host["ipmi_password"] != ipmi_password:
return True
- # hostmacroid and hostid are present in every item of host['macros'] and need to be removed
- if macros is not None and 'macros' in host:
+ # hostmacroid and hostid are present in every item of host["macros"] and need to be removed
+ if macros is not None and "macros" in host:
t_macros = copy.deepcopy(macros) # make copy to prevent change in original data
- for macro in host['macros']:
- macro.pop('hostid', False)
- macro.pop('hostmacroid', False)
+ for macro in host["macros"]:
+ macro.pop("hostid", False)
+ macro.pop("hostmacroid", False)
diff = []
- zabbix_utils.helper_compare_lists(t_macros, host['macros'], diff)
+ zabbix_utils.helper_compare_lists(t_macros, host["macros"], diff)
if diff != []:
return True
- if tags is not None and 'tags' in host:
- if sorted(tags, key=lambda k: k['tag']) != sorted(host['tags'], key=lambda k: k['tag']):
+ if tags is not None and "tags" in host:
+ if sorted(tags, key=lambda k: k["tag"]) != sorted(host["tags"], key=lambda k: k["tag"]):
return True
return False
# link or clear template of the host
def link_or_clear_template(self, host_id, template_id_list, tls_connect, tls_accept, tls_psk_identity, tls_psk,
- tls_issuer, tls_subject, ipmi_authtype, ipmi_privilege, ipmi_username, ipmi_password):
+ tls_issuer, tls_subject, ipmi_authtype, ipmi_privilege, ipmi_username, ipmi_password, discovered_host):
# get host's exist template ids
exist_template_id_list = self.get_host_templates_by_host_id(host_id)
@@ -863,20 +821,25 @@ class Host(ZabbixBase):
# get unlink and clear templates
templates_clear = exist_template_ids.difference(template_ids)
templates_clear_list = list(templates_clear)
- request_str = {'hostid': host_id, 'templates': template_id_list, 'templates_clear': templates_clear_list,
- 'ipmi_authtype': ipmi_authtype, 'ipmi_privilege': ipmi_privilege, 'ipmi_username': ipmi_username, 'ipmi_password': ipmi_password}
- if tls_connect:
- request_str['tls_connect'] = tls_connect
- if tls_accept:
- request_str['tls_accept'] = tls_accept
- if tls_psk_identity is not None:
- request_str['tls_psk_identity'] = tls_psk_identity
- if tls_psk is not None:
- request_str['tls_psk'] = tls_psk
- if tls_issuer is not None:
- request_str['tls_issuer'] = tls_issuer
- if tls_subject is not None:
- request_str['tls_subject'] = tls_subject
+ if discovered_host:
+ # The host was discovered via Discovery Rule
+ request_str = {"hostid": host_id, "templates": template_id_list, "templates_clear": templates_clear_list}
+ else:
+ # A "plain" host
+ request_str = {"hostid": host_id, "templates": template_id_list, "templates_clear": templates_clear_list,
+ "ipmi_authtype": ipmi_authtype, "ipmi_privilege": ipmi_privilege, "ipmi_username": ipmi_username, "ipmi_password": ipmi_password}
+ if tls_connect:
+ request_str["tls_connect"] = tls_connect
+ if tls_accept:
+ request_str["tls_accept"] = tls_accept
+ if tls_psk_identity is not None:
+ request_str["tls_psk_identity"] = tls_psk_identity
+ if tls_psk is not None:
+ request_str["tls_psk"] = tls_psk
+ if tls_issuer is not None:
+ request_str["tls_issuer"] = tls_issuer
+ if tls_subject is not None:
+ request_str["tls_subject"] = tls_subject
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
@@ -903,7 +866,7 @@ class Host(ZabbixBase):
inventory_mode = self.inventory_mode_numeric(inventory_mode)
# watch for - https://support.zabbix.com/browse/ZBX-6033
- request_str = {'hostid': host_id, 'inventory_mode': inventory_mode}
+ request_str = {"hostid": host_id, "inventory_mode": inventory_mode}
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
@@ -916,7 +879,7 @@ class Host(ZabbixBase):
if not inventory:
return
- request_str = {'hostid': host_id, 'inventory': inventory}
+ request_str = {"hostid": host_id, "inventory": inventory}
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
@@ -930,30 +893,30 @@ def update_exist_interfaces_with_defaults(exist_interfaces):
new_exist_interfaces = []
default_interface = {
- 'main': '0',
- 'useip': '0',
- 'ip': '',
- 'dns': '',
- 'port': ''
+ "main": "0",
+ "useip": "0",
+ "ip": "",
+ "dns": "",
+ "port": ""
}
default_interface_details = {
- 'version': 2,
- 'bulk': 1,
- 'community': '',
- 'securityname': '',
- 'contextname': '',
- 'securitylevel': 0,
- 'authprotocol': 0,
- 'authpassphrase': '',
- 'privprotocol': 0,
- 'privpassphrase': ''
+ "version": 2,
+ "bulk": 1,
+ "community": "",
+ "securityname": "",
+ "contextname": "",
+ "securitylevel": 0,
+ "authprotocol": 0,
+ "authpassphrase": "",
+ "privprotocol": 0,
+ "privpassphrase": ""
}
for interface in exist_interfaces:
new_interface = default_interface.copy()
new_interface.update(interface)
- new_interface['details'] = default_interface_details.copy()
- if 'details' in interface:
- new_interface['details'].update(interface['details'])
+ new_interface["details"] = default_interface_details.copy()
+ if "details" in interface:
+ new_interface["details"].update(interface["details"])
new_exist_interfaces.append(new_interface)
return new_exist_interfaces
@@ -961,16 +924,16 @@ def update_exist_interfaces_with_defaults(exist_interfaces):
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:])])
+ 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 + '}'
+ if not macro_name.startswith("{$"):
+ macro_name = "{$" + macro_name
+ if not macro_name.endswith("}"):
+ macro_name = macro_name + "}"
return macro_name
@@ -978,79 +941,78 @@ def normalize_macro_name(macro_name):
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- host_name=dict(type='str', required=True),
- host_groups=dict(type='list', required=False),
- link_templates=dict(type='list', required=False),
- status=dict(type='str', default="enabled", choices=['enabled', 'disabled']),
- state=dict(type='str', default="present", choices=['present', 'absent']),
- inventory_mode=dict(type='str', required=False, choices=['automatic', 'manual', 'disabled']),
- ipmi_authtype=dict(type='int', default=None),
- ipmi_privilege=dict(type='int', default=None),
- ipmi_username=dict(type='str', required=False, default=None),
- ipmi_password=dict(type='str', required=False, default=None, no_log=True),
- tls_connect=dict(type='int', required=False),
- tls_accept=dict(type='int', required=False),
- tls_psk_identity=dict(type='str', required=False),
- tls_psk=dict(type='str', required=False, no_log=True),
- ca_cert=dict(type='str', required=False, aliases=['tls_issuer']),
- tls_subject=dict(type='str', required=False),
- inventory_zabbix=dict(type='dict', required=False),
+ host_name=dict(type="str", required=True),
+ host_groups=dict(type="list", required=False, elements="str"),
+ link_templates=dict(type="list", required=False, elements="str"),
+ status=dict(type="str", default="enabled", choices=["enabled", "disabled"]),
+ state=dict(type="str", default="present", choices=["present", "absent"]),
+ inventory_mode=dict(type="str", required=False, choices=["automatic", "manual", "disabled"]),
+ ipmi_authtype=dict(type="int", default=None),
+ ipmi_privilege=dict(type="int", default=None),
+ ipmi_username=dict(type="str", required=False, default=None),
+ ipmi_password=dict(type="str", required=False, default=None, no_log=True),
+ tls_connect=dict(type="int", required=False),
+ tls_accept=dict(type="int", required=False),
+ tls_psk_identity=dict(type="str", required=False),
+ tls_psk=dict(type="str", required=False, no_log=True),
+ ca_cert=dict(type="str", required=False, aliases=["tls_issuer"]),
+ tls_subject=dict(type="str", required=False),
+ inventory_zabbix=dict(type="dict", required=False),
interfaces=dict(
- type='list',
- elements='dict',
+ type="list",
+ elements="dict",
default=[],
options=dict(
- type=dict(type='str', required=True, choices=['agent', '1', 'snmp', '2', 'ipmi', '3', 'jmx', '4']),
- main=dict(type='int', choices=[0, 1], default=0),
- useip=dict(type='int', choices=[0, 1], default=0),
- ip=dict(type='str'),
- dns=dict(type='str'),
- port=dict(type='str'),
- bulk=dict(type='int', choices=[0, 1], default=1),
+ type=dict(type="str", required=True, choices=["agent", "1", "snmp", "2", "ipmi", "3", "jmx", "4"]),
+ main=dict(type="int", choices=[0, 1], default=0),
+ useip=dict(type="int", choices=[0, 1], default=0),
+ ip=dict(type="str"),
+ dns=dict(type="str"),
+ port=dict(type="str"),
details=dict(
- type='dict',
+ type="dict",
default={},
options=dict(
- version=dict(type='int', choices=[1, 2, 3], default=2),
- bulk=dict(type='int', choices=[0, 1], default=1),
- community=dict(type='str', default=''),
- securityname=dict(type='str', default=''),
- contextname=dict(type='str', default=''),
- securitylevel=dict(type='int', choices=[0, 1, 2], default=0),
- authprotocol=dict(type='int', choices=[0, 1, 2, 3, 4, 5], default=0),
- authpassphrase=dict(type='str', default='', no_log=True),
- privprotocol=dict(type='int', choices=[0, 1, 2, 3, 4, 5], default=0),
- privpassphrase=dict(type='str', default='', no_log=True)
+ version=dict(type="int", choices=[1, 2, 3], default=2),
+ bulk=dict(type="int", choices=[0, 1], default=1),
+ community=dict(type="str", default=""),
+ securityname=dict(type="str", default=""),
+ contextname=dict(type="str", default=""),
+ securitylevel=dict(type="int", choices=[0, 1, 2], default=0),
+ authprotocol=dict(type="int", choices=[0, 1, 2, 3, 4, 5], default=0),
+ authpassphrase=dict(type="str", default="", no_log=True),
+ privprotocol=dict(type="int", choices=[0, 1, 2, 3, 4, 5], default=0),
+ privpassphrase=dict(type="str", default="", no_log=True)
)
)
),
required_if=[
- ['useip', 0, ['dns']],
- ['useip', 1, ['ip']]
+ ["useip", 0, ["dns"]],
+ ["useip", 1, ["ip"]]
]
),
- force=dict(type='bool', default=True),
- proxy=dict(type='str', required=False),
- visible_name=dict(type='str', required=False),
- description=dict(type='str', required=False),
+ force=dict(type="bool", default=True),
+ proxy=dict(type="str", required=False),
+ visible_name=dict(type="str", required=False),
+ description=dict(type="str", required=False),
macros=dict(
- type='list',
- elements='dict',
- aliases=['user_macros'],
+ type="list",
+ elements="dict",
+ aliases=["user_macros"],
options=dict(
- macro=dict(type='str', required=True),
- value=dict(type='str', required=True),
- description=dict(type='str', default=''),
- type=dict(type='str', default='text', choices=['text', 'secret'])
+ macro=dict(type="str", required=True),
+ value=dict(type="str", required=True),
+ description=dict(type="str", default=""),
+ type=dict(type="str", default="text", choices=["text", "secret"])
)
),
tags=dict(
- type='list',
- elements='dict',
- aliases=['host_tags'],
+ type="list",
+ elements="dict",
+ aliases=["host_tags"],
options=dict(
- tag=dict(type='str', required=True),
- value=dict(type='str', default='')
+ tag=dict(type="str", required=True),
+ value=dict(type="str", default="")
)
)
))
@@ -1059,36 +1021,30 @@ def main():
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- host_name = module.params['host_name']
- visible_name = module.params['visible_name']
- description = module.params['description']
- host_groups = module.params['host_groups']
- link_templates = module.params['link_templates']
- inventory_mode = module.params['inventory_mode']
- ipmi_authtype = module.params['ipmi_authtype']
- ipmi_privilege = module.params['ipmi_privilege']
- ipmi_username = module.params['ipmi_username']
- ipmi_password = module.params['ipmi_password']
- tls_connect = module.params['tls_connect']
- tls_accept = module.params['tls_accept']
- tls_psk_identity = module.params['tls_psk_identity']
- tls_psk = module.params['tls_psk']
- tls_issuer = module.params['ca_cert']
- tls_subject = module.params['tls_subject']
- inventory_zabbix = module.params['inventory_zabbix']
- status = module.params['status']
- state = module.params['state']
- interfaces = module.params['interfaces']
- force = module.params['force']
- proxy = module.params['proxy']
- macros = module.params['macros']
- tags = module.params['tags']
+ host_name = module.params["host_name"]
+ visible_name = module.params["visible_name"]
+ description = module.params["description"]
+ host_groups = module.params["host_groups"]
+ link_templates = module.params["link_templates"]
+ inventory_mode = module.params["inventory_mode"]
+ ipmi_authtype = module.params["ipmi_authtype"]
+ ipmi_privilege = module.params["ipmi_privilege"]
+ ipmi_username = module.params["ipmi_username"]
+ ipmi_password = module.params["ipmi_password"]
+ tls_connect = module.params["tls_connect"]
+ tls_accept = module.params["tls_accept"]
+ tls_psk_identity = module.params["tls_psk_identity"]
+ tls_psk = module.params["tls_psk"]
+ tls_issuer = module.params["ca_cert"]
+ tls_subject = module.params["tls_subject"]
+ inventory_zabbix = module.params["inventory_zabbix"]
+ status = module.params["status"]
+ state = module.params["state"]
+ interfaces = module.params["interfaces"]
+ force = module.params["force"]
+ proxy = module.params["proxy"]
+ macros = module.params["macros"]
+ tags = module.params["tags"]
# convert enabled to 0; disabled to 1
status = 1 if status == "disabled" else 0
@@ -1109,20 +1065,13 @@ def main():
if macros:
# convert macros to zabbix native format - {$MACRO}
for macro in macros:
- macro['macro'] = normalize_macro_name(macro['macro'])
+ macro["macro"] = normalize_macro_name(macro["macro"])
- if LooseVersion(host._zbx_api_version) <= LooseVersion('4.4.0'):
- if 'description' in macro:
- macro.pop('description', False)
-
- if 'type' in macro:
- if LooseVersion(host._zbx_api_version) < LooseVersion('5.0.0'):
- macro.pop('type')
- else:
- if macro['type'] == 'text':
- macro['type'] = '0'
- elif macro['type'] == 'secret':
- macro['type'] = '1'
+ if "type" in macro:
+ if macro["type"] == "text":
+ macro["type"] = "0"
+ elif macro["type"] == "secret":
+ macro["type"] = "1"
# Use proxy specified, or set to 0
if proxy:
@@ -1136,11 +1085,12 @@ def main():
if is_host_exist:
# get host id by host name
zabbix_host_obj = host.get_host_by_host_name(host_name)
- host_id = zabbix_host_obj['hostid']
+ host_id = zabbix_host_obj["hostid"]
+ discovered_host = zabbix_host_obj["flags"] == '4'
# If proxy is not specified as a module parameter, use the existing setting
if proxy is None:
- proxy_id = int(zabbix_host_obj['proxy_hostid'])
+ proxy_id = int(zabbix_host_obj["proxy_hostid"])
if state == "absent":
# remove host
@@ -1153,29 +1103,29 @@ def main():
group_ids = host.get_group_ids_by_host_id(host_id)
# get existing host's interfaces
- exist_interfaces = host._zapi.hostinterface.get({'output': 'extend', 'hostids': host_id})
- exist_interfaces.sort(key=lambda x: int(x['interfaceid']))
+ exist_interfaces = host._zapi.hostinterface.get({"output": "extend", "hostids": host_id})
+ exist_interfaces.sort(key=lambda x: int(x["interfaceid"]))
exist_interfaces = update_exist_interfaces_with_defaults(exist_interfaces)
# Convert integer parameters from strings to ints
for idx, interface in enumerate(copy.deepcopy(exist_interfaces)):
for key in tuple(interface.keys()):
# fix values for properties
- if key in ['useip', 'main', 'type', 'bulk']:
+ if key in ["useip", "main", "type", "bulk"]:
exist_interfaces[idx][key] = int(interface[key])
- elif key == 'details':
+ elif key == "details":
if not interface[key]:
exist_interfaces[idx][key] = {}
else:
for d_key in interface[key].keys():
- if d_key in ['version', 'bulk', 'securitylevel', 'authprotocol', 'privprotocol']:
+ if d_key in ["version", "bulk", "securitylevel", "authprotocol", "privprotocol"]:
exist_interfaces[idx][key][d_key] = int(interface[key][d_key])
interfaces_copy = copy.deepcopy(interfaces)
found_in_interfaces = []
for idx, interface in enumerate(copy.deepcopy(exist_interfaces)):
- interfaceid = interface['interfaceid']
- hostid = interface['hostid']
+ interfaceid = interface["interfaceid"]
+ hostid = interface["hostid"]
if not interfaces_copy:
# Whe no interfaces specified, copy existing interfaces
@@ -1183,8 +1133,8 @@ def main():
continue
# Find already configured interfaces in requested interfaces and compile final list of
- # interfaces in 'interfaces' variable. Every element of the list defines one interface.
- # If an element has 'interfaceid' field then Zabbix will update existing interface otherwise
+ # interfaces in "interfaces" variable. Every element of the list defines one interface.
+ # If an element has "interfaceid" field then Zabbix will update existing interface otherwise
# a new interface will be added.
found = False
for idx1, iface in enumerate(interfaces_copy):
@@ -1193,8 +1143,8 @@ def main():
if diff_dict == {}:
found = True
found_in_interfaces.append(iface)
- interfaces[idx1]['interfaceid'] = interfaceid
- interfaces[idx1]['hostid'] = hostid
+ interfaces[idx1]["interfaceid"] = interfaceid
+ interfaces[idx1]["hostid"] = hostid
break
if not found:
@@ -1203,10 +1153,10 @@ def main():
else:
# if force == True overwrite existing interfaces with provided interfaces with the same type
for idx1, iface in enumerate(interfaces_copy):
- if interface['type'] == iface['type'] and iface not in found_in_interfaces:
+ if interface["type"] == iface["type"] and iface not in found_in_interfaces:
found_in_interfaces.append(iface)
- interfaces[idx1]['interfaceid'] = interfaceid
- interfaces[idx1]['hostid'] = hostid
+ interfaces[idx1]["interfaceid"] = interfaceid
+ interfaces[idx1]["hostid"] = hostid
break
if not force or link_templates is None:
@@ -1218,12 +1168,12 @@ def main():
group_ids.append(group_id)
# Macros not present in host.update will be removed if we dont copy them when force=no
- if macros is not None and 'macros' in zabbix_host_obj.keys():
- existing_macros = zabbix_host_obj['macros']
+ if macros is not None and "macros" in zabbix_host_obj.keys():
+ existing_macros = zabbix_host_obj["macros"]
for macro in existing_macros:
- macro.pop('hostmacroid', None)
- macro.pop('hostid', None)
- macro.pop('automatic', None)
+ macro.pop("hostmacroid", None)
+ macro.pop("hostid", None)
+ macro.pop("automatic", None)
found = False
for idx1, prov_macro in enumerate(macros):
diff_dict = {}
@@ -1237,11 +1187,11 @@ def main():
macros.append(macro)
# Tags not present in host.update will be removed if we dont copy them when force=no
- if tags is not None and 'tags' in zabbix_host_obj.keys():
- provided_tags = [t['tag'] for t in tags]
- existing_tags = zabbix_host_obj['tags']
+ if tags is not None and "tags" in zabbix_host_obj.keys():
+ provided_tags = [t["tag"] for t in tags]
+ existing_tags = zabbix_host_obj["tags"]
for tag in existing_tags:
- if tag['tag'] not in provided_tags:
+ if tag["tag"] not in provided_tags:
tags.append(tag)
# update host
@@ -1254,11 +1204,11 @@ def main():
host.update_host(
host_name, group_ids, status, host_id, interfaces, exist_interfaces, proxy_id, visible_name,
description, tls_connect, tls_accept, tls_psk_identity, tls_psk, tls_issuer, tls_subject,
- ipmi_authtype, ipmi_privilege, ipmi_username, ipmi_password, macros, tags)
+ ipmi_authtype, ipmi_privilege, ipmi_username, ipmi_password, macros, tags, discovered_host)
host.link_or_clear_template(
host_id, template_ids, tls_connect, tls_accept, tls_psk_identity, tls_psk, tls_issuer,
- tls_subject, ipmi_authtype, ipmi_privilege, ipmi_username, ipmi_password)
+ tls_subject, ipmi_authtype, ipmi_privilege, ipmi_username, ipmi_password, discovered_host)
host.update_inventory_mode(host_id, inventory_mode)
host.update_inventory_zabbix(host_id, inventory_zabbix)
@@ -1270,6 +1220,8 @@ def main():
module.exit_json(changed=False)
else:
+ discovered_host = False
+
if state == "absent":
# the host is already deleted.
module.exit_json(changed=False)
@@ -1277,10 +1229,6 @@ def main():
if not group_ids:
module.fail_json(msg="Specify at least one group for creating host '%s'." % host_name)
- if not interfaces or (interfaces and len(interfaces) == 0):
- if LooseVersion(host._zbx_api_version) < LooseVersion('5.2.0'):
- module.fail_json(msg="Specify at least one interface for creating host '%s'." % host_name)
-
# create host
host_id = host.add_host(
host_name, group_ids, status, interfaces, proxy_id, visible_name, description, tls_connect, tls_accept,
@@ -1289,7 +1237,7 @@ def main():
host.link_or_clear_template(
host_id, template_ids, tls_connect, tls_accept, tls_psk_identity, tls_psk, tls_issuer, tls_subject,
- ipmi_authtype, ipmi_privilege, ipmi_username, ipmi_password)
+ ipmi_authtype, ipmi_privilege, ipmi_username, ipmi_password, discovered_host)
host.update_inventory_mode(host_id, inventory_mode)
host.update_inventory_zabbix(host_id, inventory_zabbix)
@@ -1298,5 +1246,5 @@ def main():
host_name, ip, link_templates))
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_host_events_info.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_host_events_info.py
index eb22ce23c..fde86bc12 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_host_events_info.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_host_events_info.py
@@ -9,7 +9,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
-RETURN = '''
+RETURN = """
---
triggers_ok:
description: Host Zabbix Triggers in OK state
@@ -134,20 +134,20 @@ triggers_problem:
value:
description: Whether the trigger is in OK or problem state
type: int
-'''
+"""
-DOCUMENTATION = '''
+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.
+ 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"
+ - "python >= 3.9"
options:
host_identifier:
description:
@@ -180,19 +180,19 @@ options:
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = '''
+EXAMPLES = """
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: exclude machine if alert active on it
@@ -203,18 +203,17 @@ EXAMPLES = '''
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_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_host_events_info:
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
-'''
+ when: zbx_host["triggers_problem"]|length > 0
+"""
from ansible.module_utils.basic import AnsibleModule
@@ -227,8 +226,8 @@ class Host(ZabbixBase):
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})
+ {"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:
@@ -236,18 +235,17 @@ class Host(ZabbixBase):
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})
+ 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",
+ 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]
@@ -255,48 +253,42 @@ class Host(ZabbixBase):
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- host_identifier=dict(type='str', required=True),
+ host_identifier=dict(type="str", required=True),
host_id_type=dict(
- default='hostname',
- type='str',
- choices=['hostname', 'visible_name', 'hostid']),
+ default="hostname",
+ type="str",
+ choices=["hostname", "visible_name", "hostid"]),
trigger_severity=dict(
- type='str',
+ type="str",
required=False,
- default='average',
- choices=['not_classified', 'information', 'warning', 'average', 'high', 'disaster']),
+ default="average",
+ choices=["not_classified", "information", "warning", "average", "high", "disaster"]),
))
module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
+ trigger_severity_map = {"not_classified": 0, "information": 1, "warning": 2, "average": 3, "high": 4, "disaster": 5}
+ host_id = module.params["host_identifier"]
+ host_id_type = module.params["host_id_type"]
+ trigger_severity = trigger_severity_map[module.params["trigger_severity"]]
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- trigger_severity_map = {'not_classified': 0, 'information': 1, 'warning': 2, 'average': 3, 'high': 4, 'disaster': 5}
- host_id = module.params['host_identifier']
- host_id_type = module.params['host_id_type']
- trigger_severity = trigger_severity_map[module.params['trigger_severity']]
-
- host_inventory = 'hostid'
+ host_inventory = "hostid"
host = Host(module)
- if host_id_type == 'hostname':
- zabbix_host = host.get_host(host_id, host_inventory, 'host')
- host_id = zabbix_host['hostid']
+ 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 == "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')
+ 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)
@@ -305,9 +297,9 @@ def main():
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
+ 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)
@@ -315,5 +307,5 @@ def main():
module.exit_json(ok=True, triggers_ok=triggers_ok, triggers_problem=triggers_problem)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_host_facts.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_host_facts.py
deleted file mode 100644
index 58e3343ab..000000000
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_host_facts.py
+++ /dev/null
@@ -1,239 +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
-
-
-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"
-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
- default: ''
- 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
- default: []
- 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
- default: []
-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
- 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
- set_fact:
- ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
-
-- name: Get host info
- # 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_host_info:
- 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
- # 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_host_info:
- host_name: ExampleHost
- host_inventory:
- - os
- - tag
- host_ip: 127.0.0.1
- timeout: 10
- exact_match: no
- remove_duplicate: yes
-'''
-
-
-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 Host(ZabbixBase):
- 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():
- argument_spec = zabbix_utils.zabbix_common_argument_spec()
- argument_spec.update(dict(
- host_name=dict(type='str', default='', required=False),
- host_ip=dict(type='list', default=[], required=False),
- 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)
- ))
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True
- )
- if module._name == 'zabbix_host_facts':
- module.deprecate("The 'zabbix_host_facts' module has been renamed to 'zabbix_host_info'",
- collection_name="community.zabbix", version='2.0.0') # was 2.13
-
- zabbix_utils.require_creds_params(module)
-
- host_name = module.params['host_name']
- host_ips = module.params['host_ip']
- 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'
-
- host = Host(module)
-
- 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()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_host_info.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_host_info.py
index 58e3343ab..92c185227 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_host_info.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_host_info.py
@@ -9,16 +9,16 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
-RETURN = r'''
+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'''
+DOCUMENTATION = r"""
---
module: zabbix_host_info
short_description: Gather information about Zabbix host
@@ -28,16 +28,17 @@ description:
author:
- "Michael Miko (@RedWhiteMiko)"
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
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.
+ - If neither host_name nor host_ip specified then all the hosts configured in Zabbix returned.
required: false
type: str
- default: ''
+ default: ""
host_ip:
description:
- Host interface IP of the host in Zabbix.
@@ -67,19 +68,19 @@ options:
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: Get host info
@@ -90,12 +91,11 @@ EXAMPLES = r'''
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_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_host_info:
host_name: ExampleHost
host_ip: 127.0.0.1
- timeout: 10
exact_match: no
remove_duplicate: yes
@@ -107,7 +107,7 @@ EXAMPLES = r'''
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_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_host_info:
host_name: ExampleHost
@@ -115,10 +115,9 @@ EXAMPLES = r'''
- os
- tag
host_ip: 127.0.0.1
- timeout: 10
exact_match: no
remove_duplicate: yes
-'''
+"""
from ansible.module_utils.basic import AnsibleModule
@@ -130,17 +129,17 @@ import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabb
class Host(ZabbixBase):
def get_hosts_by_host_name(self, host_name, exact_match, host_inventory):
""" Get host by host name """
- search_key = 'search'
+ search_key = "search"
if exact_match:
- search_key = 'filter'
+ 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'
+ "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)
@@ -150,9 +149,9 @@ class Host(ZabbixBase):
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
+ "output": "extend",
+ "filter": {
+ "ip": host_ips
}
})
if len(hostinterfaces) < 1:
@@ -160,15 +159,15 @@ class Host(ZabbixBase):
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'
+ "output": "extend",
+ "selectGroups": "extend",
+ "selectParentTemplates": ["name"],
+ "hostids": hostinterface["hostid"],
+ "selectInventory": host_inventory,
+ "selectTags": "extend",
+ "selectMacros": "extend"
})
- host[0]['hostinterfaces'] = hostinterface
+ host[0]["hostinterfaces"] = hostinterface
host_list.append(host[0])
return host_list
@@ -177,51 +176,46 @@ class Host(ZabbixBase):
unique_hosts = []
listed_hostnames = []
for zabbix_host in hosts:
- if zabbix_host['name'] in listed_hostnames:
+ if zabbix_host["name"] in listed_hostnames:
continue
unique_hosts.append(zabbix_host)
- listed_hostnames.append(zabbix_host['name'])
+ listed_hostnames.append(zabbix_host["name"])
return unique_hosts
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- host_name=dict(type='str', default='', required=False),
- host_ip=dict(type='list', default=[], required=False),
- 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)
+ host_name=dict(type="str", default="", required=False),
+ host_ip=dict(type="list", default=[], required=False, elements="str"),
+ 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, elements="str")
))
module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=True
)
- if module._name == 'zabbix_host_facts':
- module.deprecate("The 'zabbix_host_facts' module has been renamed to 'zabbix_host_info'",
- collection_name="community.zabbix", version='2.0.0') # was 2.13
- zabbix_utils.require_creds_params(module)
-
- host_name = module.params['host_name']
- host_ips = module.params['host_ip']
- exact_match = module.params['exact_match']
- is_remove_duplicate = module.params['remove_duplicate']
- host_inventory = module.params['host_inventory']
+ host_name = module.params["host_name"]
+ host_ips = module.params["host_ip"]
+ 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'
+ host_inventory = "extend"
host = Host(module)
- if host_name:
+ if host_name != "" or (host_name == "" and len(host_ips) == 0):
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']
+ 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)
@@ -235,5 +229,5 @@ def main():
module.exit_json(ok=False, hosts=[], result="No Host present")
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_hostmacro.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_hostmacro.py
index 1fed5d889..802a00559 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_hostmacro.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_hostmacro.py
@@ -8,7 +8,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
---
module: zabbix_hostmacro
short_description: Create/update/delete Zabbix host macros
@@ -18,7 +18,7 @@ author:
- "Cove (@cove)"
- Dean Hailin Song (!UNKNOWN)
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
options:
host_name:
description:
@@ -40,42 +40,45 @@ options:
description:
- Type of the host macro.
- text (default)
- - secret (Works only with Zabbix >= 5.0)
- - vault (Works only with Zabbix >= 5.2)
required: false
- choices: ['text', 'secret', 'vault']
- default: 'text'
+ 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']
+ choices: ["present", "absent"]
type: str
default: "present"
force:
description:
- Only updates an existing macro if set to C(yes).
- default: 'yes'
+ default: "yes"
type: bool
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: Create new host macro or update an existing macro's value
@@ -86,12 +89,13 @@ EXAMPLES = r'''
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_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_hostmacro:
host_name: ExampleHost
macro_name: EXAMPLE.MACRO
macro_value: Example value
+ macro_description: Example description
state: present
# Values with curly brackets need to be quoted otherwise they will be interpreted as a dictionary
@@ -103,12 +107,13 @@ EXAMPLES = r'''
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_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_hostmacro:
host_name: ExampleHost
macro_name: "{$EXAMPLE.MACRO}"
macro_value: Example value
+ macro_description: Example description
state: present
- name: Delete existing host macro
@@ -119,19 +124,18 @@ EXAMPLES = r'''
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_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_hostmacro:
host_name: ExampleHost
macro_name: "{$EXAMPLE.MACRO}"
state: absent
-'''
+"""
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.zabbix.plugins.module_utils.base import ZabbixBase
-from ansible.module_utils.compat.version import LooseVersion
import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabbix_utils
@@ -140,11 +144,11 @@ class HostMacro(ZabbixBase):
# 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}})
+ 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']
+ 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))
@@ -153,7 +157,7 @@ class HostMacro(ZabbixBase):
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}})
+ {"output": "extend", "selectSteps": "extend", "hostids": [host_id], "filter": {"macro": macro_name}})
if len(host_macro_list) > 0:
return host_macro_list[0]
return None
@@ -161,43 +165,34 @@ class HostMacro(ZabbixBase):
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, macro_type, host_id):
+ def create_host_macro(self, macro_name, macro_value, macro_type, macro_description, host_id):
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
- if LooseVersion(self._zbx_api_version) >= LooseVersion('5.0'):
- self._zapi.usermacro.create({'hostid': host_id, 'macro': macro_name, 'value': macro_value, 'type': macro_type})
- else:
- self._zapi.usermacro.create({'hostid': host_id, 'macro': macro_name, 'value': macro_value})
+ self._zapi.usermacro.create({"hostid": host_id, "macro": macro_name, "value": macro_value, "type": macro_type, "description": macro_description})
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, macro_type):
- host_macro_id = host_macro_obj['hostmacroid']
- if host_macro_obj['macro'] == macro_name:
- if LooseVersion(self._zbx_api_version) >= LooseVersion('5.0'):
- # no change only when macro type == 0. when type = 1 or 2 zabbix will not output value of it.
- if host_macro_obj['type'] == '0' and macro_type == '0' and host_macro_obj['value'] == macro_value:
- self._module.exit_json(changed=False, result="Host macro %s already up to date" % macro_name)
- else:
- if host_macro_obj['value'] == macro_value:
- self._module.exit_json(changed=False, result="Host macro %s already up to date" % macro_name)
+ def update_host_macro(self, host_macro_obj, macro_name, macro_value, macro_type, macro_description):
+ host_macro_id = host_macro_obj["hostmacroid"]
+ if host_macro_obj["macro"] == macro_name:
+ # no change only when macro type == 0. when type = 1 or 2 zabbix will not output value of it.
+ if (host_macro_obj["type"] == "0" and macro_type == "0" and host_macro_obj["value"] == macro_value
+ and host_macro_obj["description"] == macro_description):
+ 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)
- if LooseVersion(self._zbx_api_version) >= LooseVersion('5.0'):
- self._zapi.usermacro.update({'hostmacroid': host_macro_id, 'value': macro_value, 'type': macro_type})
- else:
- self._zapi.usermacro.update({'hostmacroid': host_macro_id, 'value': macro_value})
+ self._zapi.usermacro.update({"hostmacroid": host_macro_id, "value": macro_value, "type": macro_type, "description": macro_description})
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']
+ host_macro_id = host_macro_obj["hostmacroid"]
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
@@ -209,16 +204,16 @@ class HostMacro(ZabbixBase):
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:])])
+ 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 + '}'
+ if not macro_name.startswith("{$"):
+ macro_name = "{$" + macro_name
+ if not macro_name.endswith("}"):
+ macro_name = macro_name + "}"
return macro_name
@@ -226,38 +221,34 @@ def normalize_macro_name(macro_name):
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- host_name=dict(type='str', required=True),
- macro_name=dict(type='str', required=True),
- macro_value=dict(type='str', required=False),
- macro_type=dict(type='str', default='text', choices=['text', 'secret', 'vault']),
- state=dict(type='str', default='present', choices=['present', 'absent']),
- force=dict(type='bool', default=True)
+ host_name=dict(type="str", required=True),
+ macro_name=dict(type="str", required=True),
+ macro_value=dict(type="str", required=False),
+ 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']]
+ ["state", "present", ["macro_value"]]
],
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- 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']
- force = module.params['force']
- if module.params['macro_type'] == 'secret':
- macro_type = '1'
- elif module.params['macro_type'] == 'vault':
- macro_type = '2'
+ host_name = module.params["host_name"]
+ macro_name = normalize_macro_name(module.params["macro_name"])
+ macro_value = module.params["macro_value"]
+ macro_description = module.params["macro_description"]
+ state = module.params["state"]
+ force = module.params["force"]
+ if module.params["macro_type"] == "secret":
+ macro_type = "1"
+ elif module.params["macro_type"] == "vault":
+ macro_type = "2"
else:
- macro_type = '0'
+ macro_type = "0"
host_macro_class_obj = HostMacro(module)
@@ -265,7 +256,7 @@ def main():
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 state == "absent":
if not host_macro_obj:
module.exit_json(changed=False, msg="Host Macro %s does not exist" % macro_name)
else:
@@ -274,13 +265,13 @@ def main():
else:
if not host_macro_obj:
# create host macro
- host_macro_class_obj.create_host_macro(macro_name, macro_value, macro_type, host_id)
+ host_macro_class_obj.create_host_macro(macro_name, macro_value, macro_type, macro_description, host_id)
elif force:
# update host macro
- host_macro_class_obj.update_host_macro(host_macro_obj, macro_name, macro_value, macro_type)
+ host_macro_class_obj.update_host_macro(host_macro_obj, macro_name, macro_value, macro_type, macro_description)
else:
module.exit_json(changed=False, result="Host macro %s already exists and force is set to no" % macro_name)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_housekeeping.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_housekeeping.py
index 901ff965a..3f6e5d733 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_housekeeping.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_housekeeping.py
@@ -8,7 +8,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
module: zabbix_housekeeping
@@ -21,7 +21,7 @@ author:
- ONODERA Masaru(@masa-orca)
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
version_added: 1.6.0
@@ -39,7 +39,6 @@ options:
hk_events_service:
description:
- Storage period of service data (e.g. 365d).
- - This parameter is available since Zabbix 6.0.
required: false
type: str
hk_events_internal:
@@ -128,24 +127,21 @@ options:
required: false
type: str
-notes:
- - Zabbix 5.2 version and higher are supported.
-
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = '''
+EXAMPLES = """
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: Update housekeeping all parameter
@@ -156,7 +152,7 @@ EXAMPLES = '''
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_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_housekeeping:
login_user: Admin
@@ -181,35 +177,29 @@ EXAMPLES = '''
hk_trends: 365d
compression_status: off
compress_older: 7d
-'''
+"""
-RETURN = '''
+RETURN = """
msg:
description: The result of the operation
returned: success
type: str
- sample: 'Successfully update housekeeping setting'
-'''
+ sample: "Successfully update housekeeping setting"
+"""
import re
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.zabbix.plugins.module_utils.base import ZabbixBase
-from ansible.module_utils.compat.version import LooseVersion
import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabbix_utils
class Housekeeping(ZabbixBase):
- def __init__(self, module, zbx=None, zapi_wrapper=None):
- super(Housekeeping, self).__init__(module, zbx, zapi_wrapper)
- if LooseVersion(self._zbx_api_version) < LooseVersion('5.2.0'):
- module.fail_json(msg="This module doesn't support Zabbix versions lower than 5.2.0")
-
# get housekeeping setting
def get_housekeeping(self):
try:
- return self._zapi.housekeeping.get({'output': 'extend'})
+ return self._zapi.housekeeping.get({"output": "extend"})
except Exception as e:
self._module.fail_json(msg="Failed to get housekeeping setting: %s" % e)
@@ -247,78 +237,75 @@ class Housekeeping(ZabbixBase):
params = {}
if isinstance(hk_events_mode, bool):
- params['hk_events_mode'] = str(int(hk_events_mode))
+ params["hk_events_mode"] = str(int(hk_events_mode))
if hk_events_trigger:
- self.check_time_parameter('hk_events_trigger', hk_events_trigger)
- params['hk_events_trigger'] = hk_events_trigger
+ self.check_time_parameter("hk_events_trigger", hk_events_trigger)
+ params["hk_events_trigger"] = hk_events_trigger
if hk_events_service:
- if LooseVersion(self._zbx_api_version) < LooseVersion('6.0'):
- self._module.warn('hk_events_service is ignored with <= Zabbix 5.4.')
- else:
- self.check_time_parameter('hk_events_service', hk_events_service)
- params['hk_events_service'] = hk_events_service
+ self.check_time_parameter("hk_events_service", hk_events_service)
+ params["hk_events_service"] = hk_events_service
if hk_events_internal:
- self.check_time_parameter('hk_events_internal', hk_events_internal)
- params['hk_events_internal'] = hk_events_internal
+ self.check_time_parameter("hk_events_internal", hk_events_internal)
+ params["hk_events_internal"] = hk_events_internal
if hk_events_discovery:
- self.check_time_parameter('hk_events_discovery', hk_events_discovery)
- params['hk_events_discovery'] = hk_events_discovery
+ self.check_time_parameter("hk_events_discovery", hk_events_discovery)
+ params["hk_events_discovery"] = hk_events_discovery
if hk_events_autoreg:
- self.check_time_parameter('hk_events_autoreg', hk_events_autoreg)
- params['hk_events_autoreg'] = hk_events_autoreg
+ self.check_time_parameter("hk_events_autoreg", hk_events_autoreg)
+ params["hk_events_autoreg"] = hk_events_autoreg
if isinstance(hk_services_mode, bool):
- params['hk_services_mode'] = str(int(hk_services_mode))
+ params["hk_services_mode"] = str(int(hk_services_mode))
if hk_services:
- self.check_time_parameter('hk_services', hk_services)
- params['hk_services'] = hk_services
+ self.check_time_parameter("hk_services", hk_services)
+ params["hk_services"] = hk_services
if isinstance(hk_audit_mode, bool):
- params['hk_audit_mode'] = str(int(hk_audit_mode))
+ params["hk_audit_mode"] = str(int(hk_audit_mode))
if hk_audit:
- self.check_time_parameter('hk_audit', hk_audit)
- params['hk_audit'] = hk_audit
+ self.check_time_parameter("hk_audit", hk_audit)
+ params["hk_audit"] = hk_audit
if isinstance(hk_sessions_mode, bool):
- params['hk_sessions_mode'] = str(int(hk_sessions_mode))
+ params["hk_sessions_mode"] = str(int(hk_sessions_mode))
if hk_sessions:
- self.check_time_parameter('hk_sessions', hk_sessions)
- params['hk_sessions'] = hk_sessions
+ self.check_time_parameter("hk_sessions", hk_sessions)
+ params["hk_sessions"] = hk_sessions
if isinstance(hk_history_mode, bool):
- params['hk_history_mode'] = str(int(hk_history_mode))
+ params["hk_history_mode"] = str(int(hk_history_mode))
if isinstance(hk_history_global, bool):
- params['hk_history_global'] = str(int(hk_history_global))
+ params["hk_history_global"] = str(int(hk_history_global))
if hk_history:
- self.check_time_parameter('hk_history', hk_history)
- params['hk_history'] = hk_history
+ self.check_time_parameter("hk_history", hk_history)
+ params["hk_history"] = hk_history
if isinstance(hk_trends_mode, bool):
- params['hk_trends_mode'] = str(int(hk_trends_mode))
+ params["hk_trends_mode"] = str(int(hk_trends_mode))
if isinstance(hk_trends_global, bool):
- params['hk_trends_global'] = str(int(hk_trends_global))
+ params["hk_trends_global"] = str(int(hk_trends_global))
if hk_trends:
- self.check_time_parameter('hk_trends', hk_trends)
- params['hk_trends'] = hk_trends
+ self.check_time_parameter("hk_trends", hk_trends)
+ params["hk_trends"] = hk_trends
if isinstance(compression_status, bool):
- params['compression_status'] = str(int(compression_status))
+ params["compression_status"] = str(int(compression_status))
if compress_older:
- self.check_time_parameter('compress_older', compress_older)
- params['compress_older'] = compress_older
+ self.check_time_parameter("compress_older", compress_older)
+ params["compress_older"] = compress_older
future_housekeeping = current_housekeeping.copy()
future_housekeeping.update(params)
@@ -338,58 +325,52 @@ class Housekeeping(ZabbixBase):
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- hk_events_mode=dict(type='bool'),
- hk_events_trigger=dict(type='str'),
- hk_events_service=dict(type='str'),
- hk_events_internal=dict(type='str'),
- hk_events_discovery=dict(type='str'),
- hk_events_autoreg=dict(type='str'),
- hk_services_mode=dict(type='bool'),
- hk_services=dict(type='str'),
- hk_audit_mode=dict(type='bool'),
- hk_audit=dict(type='str'),
- hk_sessions_mode=dict(type='bool'),
- hk_sessions=dict(type='str'),
- hk_history_mode=dict(type='bool'),
- hk_history_global=dict(type='bool'),
- hk_history=dict(type='str'),
- hk_trends_mode=dict(type='bool'),
- hk_trends_global=dict(type='bool'),
- hk_trends=dict(type='str'),
- compression_status=dict(type='bool'),
- compress_older=dict(type='str')
+ hk_events_mode=dict(type="bool"),
+ hk_events_trigger=dict(type="str"),
+ hk_events_service=dict(type="str"),
+ hk_events_internal=dict(type="str"),
+ hk_events_discovery=dict(type="str"),
+ hk_events_autoreg=dict(type="str"),
+ hk_services_mode=dict(type="bool"),
+ hk_services=dict(type="str"),
+ hk_audit_mode=dict(type="bool"),
+ hk_audit=dict(type="str"),
+ hk_sessions_mode=dict(type="bool"),
+ hk_sessions=dict(type="str"),
+ hk_history_mode=dict(type="bool"),
+ hk_history_global=dict(type="bool"),
+ hk_history=dict(type="str"),
+ hk_trends_mode=dict(type="bool"),
+ hk_trends_global=dict(type="bool"),
+ hk_trends=dict(type="str"),
+ compression_status=dict(type="bool"),
+ compress_older=dict(type="str")
))
module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- hk_events_mode = module.params['hk_events_mode']
- hk_events_trigger = module.params['hk_events_trigger']
- hk_events_service = module.params['hk_events_service']
- hk_events_internal = module.params['hk_events_internal']
- hk_events_discovery = module.params['hk_events_discovery']
- hk_events_autoreg = module.params['hk_events_autoreg']
- hk_services_mode = module.params['hk_services_mode']
- hk_services = module.params['hk_services']
- hk_audit_mode = module.params['hk_audit_mode']
- hk_audit = module.params['hk_audit']
- hk_sessions_mode = module.params['hk_sessions_mode']
- hk_sessions = module.params['hk_sessions']
- hk_history_mode = module.params['hk_history_mode']
- hk_history_global = module.params['hk_history_global']
- hk_history = module.params['hk_history']
- hk_trends_mode = module.params['hk_trends_mode']
- hk_trends_global = module.params['hk_trends_global']
- hk_trends = module.params['hk_trends']
- compression_status = module.params['compression_status']
- compress_older = module.params['compress_older']
+ hk_events_mode = module.params["hk_events_mode"]
+ hk_events_trigger = module.params["hk_events_trigger"]
+ hk_events_service = module.params["hk_events_service"]
+ hk_events_internal = module.params["hk_events_internal"]
+ hk_events_discovery = module.params["hk_events_discovery"]
+ hk_events_autoreg = module.params["hk_events_autoreg"]
+ hk_services_mode = module.params["hk_services_mode"]
+ hk_services = module.params["hk_services"]
+ hk_audit_mode = module.params["hk_audit_mode"]
+ hk_audit = module.params["hk_audit"]
+ hk_sessions_mode = module.params["hk_sessions_mode"]
+ hk_sessions = module.params["hk_sessions"]
+ hk_history_mode = module.params["hk_history_mode"]
+ hk_history_global = module.params["hk_history_global"]
+ hk_history = module.params["hk_history"]
+ hk_trends_mode = module.params["hk_trends_mode"]
+ hk_trends_global = module.params["hk_trends_global"]
+ hk_trends = module.params["hk_trends"]
+ compression_status = module.params["compression_status"]
+ compress_older = module.params["compress_older"]
housekeeping = Housekeeping(module)
@@ -419,5 +400,5 @@ def main():
)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_maintenance.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_maintenance.py
index 139db5057..a2c635eb0 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_maintenance.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_maintenance.py
@@ -8,7 +8,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
---
module: zabbix_maintenance
short_description: Create Zabbix maintenance windows
@@ -16,7 +16,7 @@ description:
- This module will let you create Zabbix maintenance windows.
author: "Alexander Bulimov (@abulimov)"
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
options:
state:
description:
@@ -57,14 +57,13 @@ options:
description:
- Type of maintenance. With data collection, or without.
type: bool
- default: 'yes'
+ default: "yes"
visible_name:
description:
- Type of zabbix host name to use for identifying hosts to include in the maintenance.
- I(visible_name=yes) to search by visible name, I(visible_name=no) to search by technical name.
type: bool
- default: 'yes'
- version_added: '2.0.0'
+ default: "yes"
tags:
description:
- List of tags to assign to the hosts in maintenance.
@@ -81,7 +80,7 @@ options:
description:
- Value of the tag.
type: str
- default: ''
+ default: ""
operator:
description:
- Condition operator.
@@ -101,19 +100,19 @@ notes:
- 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.
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: Create a named maintenance window for host www1 for 90 minutes
@@ -124,7 +123,7 @@ EXAMPLES = r'''
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_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_maintenance:
name: Update of www1
@@ -140,7 +139,7 @@ EXAMPLES = r'''
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_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_maintenance:
name: Update of www1
@@ -165,7 +164,7 @@ EXAMPLES = r'''
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_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_maintenance:
name: update
@@ -183,12 +182,12 @@ EXAMPLES = r'''
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_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_maintenance:
name: Test1
state: absent
-'''
+"""
import datetime
import time
@@ -197,81 +196,65 @@ 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
-from ansible.module_utils.compat.version import LooseVersion
class MaintenanceModule(ZabbixBase):
def create_maintenance(self, group_ids, host_ids, start_time,
maintenance_type, period, name, desc, tags):
end_time = start_time + period
- try:
- parameters = {
- "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),
- }]
- }
- if tags is not None:
- parameters['tags'] = tags
- self._zapi.maintenance.create(parameters)
- # zabbix_api can call sys.exit() so we need to catch SystemExit here
- except (Exception, SystemExit) as e:
- return 1, None, str(e)
+ parameters = {
+ "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),
+ }]
+ }
+ if tags is not None:
+ parameters["tags"] = tags
+ self._zapi.maintenance.create(parameters)
return 0, None, None
def update_maintenance(self, maintenance_id, group_ids, host_ids,
start_time, maintenance_type, period, desc, tags):
end_time = start_time + period
- try:
- parameters = {
- "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),
- }]
- }
- if tags is not None:
- parameters['tags'] = tags
- else:
- if LooseVersion(self._zbx_api_version) < LooseVersion('6.0'):
- parameters['tags'] = []
- self._zapi.maintenance.update(parameters)
- # zabbix_api can call sys.exit() so we need to catch SystemExit here
- except (Exception, SystemExit) as e:
- return 1, None, str(e)
+ parameters = {
+ "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),
+ }]
+ }
+ if tags is not None:
+ parameters["tags"] = tags
+ self._zapi.maintenance.update(parameters)
return 0, None, None
def get_maintenance(self, name):
- try:
- maintenances = self._zapi.maintenance.get(
+ maintenances = self._zapi.maintenance.get(
+ {
+ "filter":
{
- "filter":
- {
- "name": name,
- },
- "selectGroups": "extend",
- "selectHosts": "extend",
- "selectTags": "extend"
- }
- )
- # zabbix_api can call sys.exit() so we need to catch SystemExit here
- except (Exception, SystemExit) as e:
- return 1, None, str(e)
+ "name": name,
+ },
+ "selectGroups": "extend",
+ "selectHosts": "extend",
+ "selectTags": "extend"
+ }
+ )
for maintenance in maintenances:
maintenance["groupids"] = [group["groupid"] for group
@@ -283,29 +266,21 @@ class MaintenanceModule(ZabbixBase):
return 0, None, None
def delete_maintenance(self, maintenance_id):
- try:
- self._zapi.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)
+ self._zapi.maintenance.delete([maintenance_id])
return 0, None, None
def get_group_ids(self, host_groups):
group_ids = []
for group in host_groups:
- try:
- result = self._zapi.hostgroup.get(
+ result = self._zapi.hostgroup.get(
+ {
+ "output": "extend",
+ "filter":
{
- "output": "extend",
- "filter":
- {
- "name": group
- }
+ "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
@@ -317,19 +292,15 @@ class MaintenanceModule(ZabbixBase):
def get_host_ids(self, host_names, zabbix_host):
host_ids = []
for host in host_names:
- try:
- result = self._zapi.host.get(
+ result = self._zapi.host.get(
+ {
+ "output": "extend",
+ "filter":
{
- "output": "extend",
- "filter":
- {
- zabbix_host: host
- }
+ zabbix_host: 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
@@ -350,35 +321,35 @@ class MaintenanceModule(ZabbixBase):
return True
if str(int(start_time + period)) != maintenance["active_till"]:
return True
- if str(desc) != maintenance['description']:
+ if str(desc) != maintenance["description"]:
return True
- if tags is not None and 'tags' in maintenance:
- if sorted(tags, key=lambda k: k['tag']) != sorted(maintenance['tags'], key=lambda k: k['tag']):
+ if tags is not None and "tags" in maintenance:
+ if sorted(tags, key=lambda k: k["tag"]) != sorted(maintenance["tags"], key=lambda k: k["tag"]):
return True
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- state=dict(type='str', required=False, default='present',
- choices=['present', 'absent']),
- 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']),
- 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),
- visible_name=dict(type='bool', required=False, default=True),
+ state=dict(type="str", required=False, default="present",
+ choices=["present", "absent"]),
+ host_names=dict(type="list", required=False,
+ default=None, aliases=["host_name"], elements="str"),
+ minutes=dict(type="int", required=False, default=10),
+ host_groups=dict(type="list", required=False,
+ default=None, aliases=["host_group"], elements="str"),
+ 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),
+ visible_name=dict(type="bool", required=False, default=True),
tags=dict(
- type='list',
- elements='dict',
+ type="list",
+ elements="dict",
required=False,
options=dict(
- tag=dict(type='str', required=True),
- operator=dict(type='int', default=2),
- value=dict(type='str', default='')
+ tag=dict(type="str", required=True),
+ operator=dict(type="int", default=2),
+ value=dict(type="str", default="")
)
)
))
@@ -387,23 +358,17 @@ def main():
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
maint = MaintenanceModule(module)
- host_names = module.params['host_names']
- host_groups = module.params['host_groups']
- state = module.params['state']
- minutes = module.params['minutes']
- name = module.params['name']
- desc = module.params['desc']
- collect_data = module.params['collect_data']
- visible_name = module.params['visible_name']
- tags = module.params['tags']
+ host_names = module.params["host_names"]
+ host_groups = module.params["host_groups"]
+ state = module.params["state"]
+ minutes = module.params["minutes"]
+ name = module.params["name"]
+ desc = module.params["desc"]
+ collect_data = module.params["collect_data"]
+ visible_name = module.params["visible_name"]
+ tags = module.params["tags"]
if collect_data:
maintenance_type = 0
@@ -494,5 +459,5 @@ def main():
module.exit_json(changed=changed)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_map.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_map.py
index 175b96df6..a0f3cc655 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_map.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_map.py
@@ -7,7 +7,7 @@
from __future__ import absolute_import, division, print_function
__metaclass__ = type
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
---
module: zabbix_map
author:
@@ -37,7 +37,7 @@ description:
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"
+ - "python >= 3.9"
- pydotplus
- webcolors
- Pillow
@@ -61,7 +61,7 @@ options:
- 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']
+ choices: ["present", "absent"]
default: "present"
type: str
width:
@@ -98,7 +98,7 @@ options:
description:
- Map element label type.
required: false
- choices: ['label', 'ip', 'name', 'status', 'nothing', 'custom']
+ choices: ["label", "ip", "name", "status", "nothing", "custom"]
default: "name"
type: str
default_image:
@@ -111,21 +111,21 @@ options:
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-RETURN = r''' # '''
+RETURN = r""" # """
-EXAMPLES = r'''
+EXAMPLES = r"""
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
###
@@ -139,7 +139,7 @@ EXAMPLES = r'''
###
### Each inventory host is present in Zabbix with a matching name.
###
-### Contents of 'map.j2':
+### Contents of "map.j2":
# digraph G {
# graph [layout=dot splines=false overlap=scale]
# INTERNET [zbx_url="Google:https://google.com" zbx_image="Cloud_(96)"]
@@ -168,7 +168,7 @@ EXAMPLES = r'''
# }
# }
###
-### Create Zabbix map "Demo Map" made of template 'map.j2'
+### Create Zabbix map "Demo Map" made of template "map.j2"
- name: Create Zabbix map
# set task level variables as we change ansible_connection plugin here
vars:
@@ -177,7 +177,7 @@ EXAMPLES = r'''
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_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_map:
name: Demo map
@@ -189,7 +189,7 @@ EXAMPLES = r'''
label_type: label
delegate_to: localhost
run_once: yes
-'''
+"""
import base64
@@ -201,7 +201,6 @@ from operator import itemgetter
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from ansible_collections.community.zabbix.plugins.module_utils.base import ZabbixBase
-from ansible.module_utils.compat.version import LooseVersion
import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabbix_utils
@@ -234,17 +233,17 @@ except ImportError:
class Map(ZabbixBase):
def __init__(self, module, zbx=None, zapi_wrapper=None):
super(Map, self).__init__(module, zbx, zapi_wrapper)
- 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_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.margin = module.params["margin"]
+ self.expand_problem = module.params["expand_problem"]
+ self.highlight = module.params["highlight"]
+ self.label_type = module.params["label_type"]
self.selements_sort_keys = self._get_selements_sort_keys()
def _build_graph(self):
@@ -265,25 +264,25 @@ class Map(ZabbixBase):
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),
+ "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,
+ "label": 0,
+ "ip": 1,
+ "name": 2,
+ "status": 3,
+ "nothing": 4,
+ "custom": 5,
}
try:
label_type_id = label_type_ids[label_type]
@@ -294,82 +293,73 @@ class Map(ZabbixBase):
def _get_images_info(self, data, icon_ids):
images = [
{
- 'dot_tag': 'zbx_image',
- 'zbx_property': 'iconid_off',
- 'mandatory': True
+ "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_disabled",
+ "zbx_property": "iconid_disabled",
+ "mandatory": False
},
{
- 'dot_tag': 'zbx_image_maintenance',
- 'zbx_property': 'iconid_maintenance',
- 'mandatory': False
+ "dot_tag": "zbx_image_maintenance",
+ "zbx_property": "iconid_maintenance",
+ "mandatory": False
},
{
- 'dot_tag': 'zbx_image_problem',
- 'zbx_property': 'iconid_on',
- '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)
+ image_name = data.get(image["dot_tag"], None)
if not image_name:
- if image['mandatory']:
+ 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
+ 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
+ "host": 0,
+ "sysmap": 1,
+ "trigger": 2,
+ "group": 3,
+ "image": 4
}
element_type = {
- 'elementtype': types['image'],
+ "elementtype": types["image"],
}
- if LooseVersion(self._zbx_api_version) < LooseVersion('3.4'):
- element_type.update({
- 'elementid': "0",
- })
for type_name, type_id in sorted(types.items()):
- field_name = 'zbx_' + type_name
+ field_name = "zbx_" + type_name
if field_name in data:
- method_name = '_get_' + type_name + '_id'
+ 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
+ "elementtype": type_id,
+ "label": element_name
+ })
+ element_type.update({
+ "elements": [{
+ type_name + "id": elementid,
+ }],
})
- if LooseVersion(self._zbx_api_version) < LooseVersion('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))
@@ -382,30 +372,30 @@ class Map(ZabbixBase):
scales = self._get_scales(graph)
for selementid, (node, data) in enumerate(nodes.items(), start=1):
selement = {
- 'selementid': selementid
+ "selementid": selementid
}
- data['selementid'] = selementid
+ data["selementid"] = selementid
images_info = self._get_images_info(data, icon_ids)
selement.update(images_info)
- image_id = images_info['iconid_off']
+ 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])
+ pos = self._convert_coordinates(data["pos"], scales, icon_sizes[image_id])
selement.update(pos)
- selement['label'] = remove_quotes(node)
+ 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
+ selement["label"] = label
urls = self._get_urls(data)
if urls:
- selement['urls'] = urls
+ selement["urls"] = urls
selements.append(selement)
return selements
@@ -413,35 +403,35 @@ class Map(ZabbixBase):
def _get_links(self, nodes, edges):
links = {}
for edge in edges:
- link_id = tuple(sorted(edge.obj_dict['points']))
+ link_id = tuple(sorted(edge.obj_dict["points"]))
node1, node2 = link_id
- data = edge.obj_dict['attributes']
+ data = edge.obj_dict["attributes"]
- if "style" in data and data['style'] == "invis":
+ 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']),
+ "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')))
+ 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')))
+ 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
+ link["label"] = label
triggers = self._get_triggers(data)
if triggers:
if "linktriggers" not in link:
- link['linktriggers'] = []
- link['linktriggers'] += triggers
+ link["linktriggers"] = []
+ link["linktriggers"] += triggers
return list(links.values())
@@ -449,12 +439,12 @@ class Map(ZabbixBase):
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)
+ 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,
+ "name": name,
+ "url": url,
})
return urls
@@ -464,9 +454,9 @@ class Map(ZabbixBase):
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'))),
+ "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))
@@ -475,23 +465,23 @@ class Map(ZabbixBase):
@staticmethod
def _get_label(data, default=None):
if "zbx_label" in data:
- label = remove_quotes(data['zbx_label']).replace('\\n', '\n')
+ label = remove_quotes(data["zbx_label"]).replace("\\n", "\n")
elif "label" in data:
- label = remove_quotes(data['label'])
+ 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}})
+ exist_map = self._zapi.map.get({"filter": {"name": map_name}})
if exist_map:
- return exist_map[0]['sysmapid']
+ return exist_map[0]["sysmapid"]
return None
def _get_group_id(self, group_name):
- exist_group = self._zapi.hostgroup.get({'filter': {'name': group_name}})
+ exist_group = self._zapi.hostgroup.get({"filter": {"name": group_name}})
if exist_group:
- return exist_group[0]['groupid']
+ return exist_group[0]["groupid"]
return None
def map_exists(self):
@@ -513,7 +503,7 @@ class Map(ZabbixBase):
try:
if self._module.check_mode:
self._module.exit_json(changed=True)
- map_config['sysmapid'] = self.map_id
+ map_config["sysmapid"] = self.map_id
result = self._zapi.map.update(map_config)
if result:
return result
@@ -532,24 +522,22 @@ class Map(ZabbixBase):
def is_exist_map_correct(self, generated_map_config):
exist_map_configs = self._zapi.map.get({
- 'sysmapids': self.map_id,
- 'selectLinks': 'extend',
- 'selectSelements': 'extend'
+ "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']):
+ 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']):
+ 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 LooseVersion(self._zbx_api_version) < LooseVersion('3.4'):
- keys_to_sort.insert(0, 'elementid')
+ keys_to_sort = ["label"]
return keys_to_sort
def _is_selements_equal(self, generated_selements, exist_selements):
@@ -558,22 +546,21 @@ class Map(ZabbixBase):
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 LooseVersion(self._zbx_api_version) >= LooseVersion('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']):
+ if not self._is_elements_equal(generated_selement.get("elements", []), exist_selement.get("elements", [])):
return False
- if not self._is_urls_equal(generated_selement.get('urls', []), exist_selement.get('urls', [])):
+ 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'))
+ 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']):
+ if not self._is_dicts_equal(generated_url, exist_url, ["selementid"]):
return False
return True
@@ -583,40 +570,40 @@ class Map(ZabbixBase):
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']):
+ 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))
+ 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']
+ 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'))
+ 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']):
+ 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', [])):
+ 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'))
+ 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
@@ -637,40 +624,40 @@ class Map(ZabbixBase):
return True
def _get_host_id(self, hostname):
- hostid = self._zapi.host.get({'filter': {'host': hostname}})
+ hostid = self._zapi.host.get({"filter": {"host": hostname}})
if hostid:
- return str(hostid[0]['hostid'])
+ return str(hostid[0]["hostid"])
def _get_trigger_id(self, trigger_definition):
try:
- host, trigger = trigger_definition.split(':', 1)
+ 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
+ "host": host,
+ "filter": {
+ "description": trigger
}
})
if triggerid:
- return str(triggerid[0]['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']
+ icon_ids[icon["name"]] = icon["imageid"]
return icon_ids
def _get_icon_size(self, icon_id):
icons_list = self._zapi.image.get({
- 'imageids': [
+ "imageids": [
icon_id
],
- 'select_image': True
+ "select_image": True
})
if len(icons_list) > 0:
- icon_base64 = icons_list[0]['image']
+ 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)))
@@ -681,19 +668,19 @@ class Map(ZabbixBase):
def _get_node_attributes(node):
attr = {}
if "attributes" in node.obj_dict:
- attr.update(node.obj_dict['attributes'])
+ 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))
+ 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'):
+ if node_name in ("node", "graph", "edge"):
continue
nodes[node_name] = self._get_node_attributes(node)
for subgraph in parent.get_subgraphs():
@@ -714,38 +701,38 @@ class Map(ZabbixBase):
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),
+ "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),
+ "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('#'):
+ 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()
+ 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
+ "line": 0,
+ "bold": 2,
+ "dotted": 3,
+ "dashed": 4
}
try:
draw_style_id = draw_style_ids[draw_style]
@@ -764,34 +751,28 @@ def remove_quotes(s):
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- 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']),
+ 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"]),
))
module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
if not HAS_PYDOTPLUS:
- module.fail_json(msg=missing_required_lib('pydotplus', url='https://pypi.org/project/pydotplus/'), exception=PYDOT_IMP_ERR)
+ 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)
+ 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)
+ module.fail_json(msg=missing_required_lib("Pillow", url="https://pypi.org/project/Pillow/"), exception=PIL_IMP_ERR)
sysmap = Map(module)
@@ -814,5 +795,5 @@ def main():
module.exit_json(changed=True, result="Successfully created map: %s" % sysmap.map_name)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_mediatype.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_mediatype.py
index c5693f467..1e2514bf3 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_mediatype.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_mediatype.py
@@ -7,7 +7,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
---
module: zabbix_mediatype
short_description: Create/Update/Delete Zabbix media types
@@ -16,22 +16,21 @@ description:
author:
- Ruben Tsirunyan (@rubentsirunyan)
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
options:
name:
- type: 'str'
+ type: "str"
description:
- Name of the media type.
required: true
description:
- type: 'str'
+ type: "str"
description:
- Description of the media type.
- - Works only with Zabbix versions 4.4 or newer.
- default: ''
+ default: ""
state:
- type: 'str'
+ 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.
@@ -39,13 +38,12 @@ options:
choices:
- present
- absent
- default: 'present'
+ default: "present"
type:
- type: 'str'
+ type: "str"
description:
- Type of the media type.
- Media types I(jabber) and I(ez_texting) works only with Zabbix versions 4.2 or older.
- - Media type I(webhook) works only with Zabbix versions 4.4 or newer.
choices:
- email
- script
@@ -55,93 +53,90 @@ options:
- ez_texting
required: true
status:
- type: 'str'
+ type: "str"
description:
- Whether the media type is enabled or no.
choices:
- enabled
- disabled
- default: 'enabled'
+ default: "enabled"
max_sessions:
- type: 'int'
+ 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.
- - Works only with Zabbix versions 3.4 or newer.
default: 1
max_attempts:
- type: 'int'
+ type: "int"
description:
- The maximum number of attempts to send an alert.
- Possible range is 0-10.
- - Works only with Zabbix versions 3.4 or newer.
default: 3
attempt_interval:
- type: 'str'
+ type: "str"
description:
- The interval between retry attempts.
- - Possible range is 0-60s in Zabbix < 5.0 or 0-1h in Zabbix >= 5.0.
- - Works only with Zabbix versions 3.4 or newer.
+ - Possible range is 0-1h.
default: 10s
script_name:
- type: 'str'
+ type: "str"
description:
- The name of the executed script.
- Required when I(type=script).
script_params:
- type: 'list'
+ type: "list"
elements: str
description:
- List of script parameters.
- Required when I(type=script).
gsm_modem:
- type: 'str'
+ type: "str"
description:
- Serial device name of the gsm modem.
- Required when I(type=sms).
username:
- type: 'str'
+ 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'
+ 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'
+ type: "str"
description:
- SMTP server host.
- Required when I(type=email).
- default: 'localhost'
+ default: "localhost"
smtp_server_port:
- type: 'int'
+ type: "int"
description:
- SMTP server port.
- Required when I(type=email).
default: 25
smtp_helo:
- type: 'str'
+ type: "str"
description:
- SMTP HELO.
- Required when I(type=email).
- default: 'localhost'
+ default: "localhost"
smtp_email:
- type: 'str'
+ type: "str"
description:
- Email address from which notifications will be sent.
- Required when I(type=email).
smtp_authentication:
- type: 'bool'
+ 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'
+ type: "str"
description:
- SMTP connection security level to use.
choices:
@@ -149,19 +144,19 @@ options:
- STARTTLS
- SSL/TLS
smtp_verify_host:
- type: 'bool'
+ 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'
+ 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'
+ type: "str"
description:
- The message text limit.
- Required when I(type=ez_texting).
@@ -170,74 +165,72 @@ options:
- USA
- Canada
webhook_script:
- type: 'str'
+ type: "str"
description:
- Required when I(type=webhook).
- JavaScript code that will perform webhook operation.
- This code has access to all parameters in I(webhook_params).
- It may perform HTTP GET, POST, PUT and DELETE requests and has control over HTTP headers and request body.
- It may return OK status along with an optional list of tags and tag values or an error string.
- - Works only with Zabbix versions 4.4 or newer.
webhook_timeout:
- type: 'str'
+ type: "str"
description:
- Can be used when I(type=webhook).
- Execution timeout for JavaScript code in I(webhook_script).
- Possible values are 1-60s.
default: 30s
process_tags:
- type: 'bool'
+ type: "bool"
description:
- Can be used when I(type=webhook).
- Process returned JSON property values as tags.
- These tags are added to the already existing (if any) problem event tags in Zabbix.
default: false
event_menu:
- type: 'bool'
+ type: "bool"
description:
- Can be used when I(type=webhook).
- Includes entry in Event menu with link to created external ticket.
default: false
event_menu_url:
- type: 'str'
+ type: "str"
description:
- Requred when I(event_menu=true).
- Event menu entry underlying URL.
event_menu_name:
- type: 'str'
+ type: "str"
description:
- Requred when I(event_menu=true).
- Event menu entry name.
webhook_params:
- type: 'list'
- elements: 'dict'
+ type: "list"
+ elements: "dict"
description:
- Can be used when I(type=webhook).
- Webhook variables that are passed to webhook script when executed.
default: []
suboptions:
name:
- type: 'str'
+ type: "str"
description:
- Name of the parameter.
required: true
value:
- type: 'str'
+ type: "str"
description:
- Value of the parameter.
- All macros that are supported in problem notifications are supported in the parameters.
- Values are URL-encoded automatically. Values from macros are resolved and then URL-encoded automatically.
- default: ''
+ default: ""
message_templates:
- type: 'list'
- elements: 'dict'
+ type: "list"
+ elements: "dict"
description:
- Default notification messages for the event types.
- - Works only with Zabbix versions 5.0 or newer.
default: []
suboptions:
eventsource:
- type: 'str'
+ type: "str"
description:
- Event source.
- Required when I(recovery) is used.
@@ -247,7 +240,7 @@ options:
- autoregistration
- internal
recovery:
- type: 'str'
+ type: "str"
description:
- Operation mode.
- Required when I(eventsource) is used.
@@ -256,40 +249,40 @@ options:
- recovery_operations
- update_operations
subject:
- type: 'str'
+ type: "str"
description:
- Subject of the default message.
- May contain macros and is limited to 255 characters.
- default: ''
+ default: ""
body:
- type: 'str'
+ type: "str"
description:
- Body of the default message.
- May contain macros.
- default: ''
+ default: ""
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-RETURN = r''' # '''
+RETURN = r""" # """
-EXAMPLES = r'''
+EXAMPLES = r"""
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
-- name: 'Create an email mediatype with SMTP authentication'
+- name: "Create an email mediatype with SMTP authentication"
# set task level variables as we change ansible_connection plugin here
vars:
ansible_network_os: community.zabbix.zabbix
@@ -297,19 +290,19 @@ EXAMPLES = r'''
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_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_mediatype:
name: "Ops email"
- type: 'email'
- smtp_server: 'example.com'
+ type: "email"
+ smtp_server: "example.com"
smtp_server_port: 2000
- smtp_email: 'ops@example.com'
+ smtp_email: "ops@example.com"
smtp_authentication: true
- username: 'smtp_user'
- password: 'smtp_pass'
+ username: "smtp_user"
+ password: "smtp_pass"
-- name: 'Create a script mediatype'
+- name: "Create a script mediatype"
# set task level variables as we change ansible_connection plugin here
vars:
ansible_network_os: community.zabbix.zabbix
@@ -317,17 +310,17 @@ EXAMPLES = r'''
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_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_mediatype:
name: "my script"
- type: 'script'
- script_name: 'my_script.py'
+ type: "script"
+ script_name: "my_script.py"
script_params:
- - 'arg1'
- - 'arg2'
+ - "arg1"
+ - "arg2"
-- name: 'Create a jabber mediatype'
+- name: "Create a jabber mediatype"
# set task level variables as we change ansible_connection plugin here
vars:
ansible_network_os: community.zabbix.zabbix
@@ -335,15 +328,15 @@ EXAMPLES = r'''
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_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_mediatype:
name: "My jabber"
- type: 'jabber'
- username: 'jabber_id'
- password: 'jabber_pass'
+ type: "jabber"
+ username: "jabber_id"
+ password: "jabber_pass"
-- name: 'Create a SMS mediatype'
+- name: "Create a SMS mediatype"
# set task level variables as we change ansible_connection plugin here
vars:
ansible_network_os: community.zabbix.zabbix
@@ -351,15 +344,14 @@ EXAMPLES = r'''
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_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_mediatype:
name: "My SMS Mediatype"
- type: 'sms'
- gsm_modem: '/dev/ttyS0'
+ type: "sms"
+ gsm_modem: "/dev/ttyS0"
-# Supported since Zabbix 4.4
-- name: 'Create a webhook mediatype'
+- name: "Create a webhook mediatype"
# set task level variables as we change ansible_connection plugin here
vars:
ansible_network_os: community.zabbix.zabbix
@@ -367,24 +359,23 @@ EXAMPLES = r'''
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_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_mediatype:
name: "My webhook Mediatype"
- type: 'webhook'
+ type: "webhook"
webhook_script: "{{ lookup('file', 'slack.js') }}"
webhook_params:
- name: alert_message
- value: '{ALERT.MESSAGE}'
+ value: "{ALERT.MESSAGE}"
- name: zabbix_url
- value: '{$ZABBIX.URL}'
+ value: "{$ZABBIX.URL}"
process_tags: true
event_menu: true
event_menu_name: "Open in Slack: '{EVENT.TAGS.__channel_name}'"
- event_menu_url: '{EVENT.TAGS.__message_link}'
+ event_menu_url: "{EVENT.TAGS.__message_link}"
-# Supported since Zabbix 5.0
-- name: 'Create an email mediatype with message templates'
+- name: "Create an email mediatype with message templates"
# set task level variables as we change ansible_connection plugin here
vars:
ansible_network_os: community.zabbix.zabbix
@@ -392,12 +383,12 @@ EXAMPLES = r'''
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_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_mediatype:
name: "Ops email"
- type: 'email'
- smtp_email: 'ops@example.com'
+ type: "email"
+ smtp_email: "ops@example.com"
message_templates:
- eventsource: triggers
recovery: operations
@@ -419,7 +410,7 @@ EXAMPLES = r'''
recovery: operations
subject: "Autoregistration: {HOST.HOST}"
body: "Host name: {HOST.HOST}\r\nHost IP: {HOST.IP}\r\nAgent port: {HOST.PORT}"
-'''
+"""
from ansible.module_utils.basic import AnsibleModule
@@ -446,10 +437,10 @@ def diff(existing, new):
for key in new:
before[key] = existing[key]
if new[key] is None:
- after[key] = ''
+ after[key] = ""
else:
after[key] = new[key]
- return {'before': before, 'after': after}
+ return {"before": before, "after": after}
class MediaTypeModule(ZabbixBase):
@@ -462,20 +453,18 @@ class MediaTypeModule(ZabbixBase):
Returns:
Tuple of (True, `id of the mediatype`) if mediatype exists, (False, None) otherwise
"""
- filter_key_name = 'description'
- if LooseVersion(self._zbx_api_version) >= LooseVersion('4.4'):
- # description key changed to name key from zabbix 4.4
- filter_key_name = 'name'
+ filter_key_name = "description"
+ filter_key_name = "name"
try:
mediatype_list = self._zapi.mediatype.get({
- 'output': 'extend',
- 'filter': {filter_key_name: [name]}
+ "output": "extend",
+ "filter": {filter_key_name: [name]}
})
if len(mediatype_list) < 1:
return False, None
else:
- return True, mediatype_list[0]['mediatypeid']
+ return True, mediatype_list[0]["mediatypeid"]
except Exception as e:
self._module.fail_json(msg="Failed to get ID of the mediatype '{name}': {e}".format(name=name, e=e))
@@ -487,127 +476,104 @@ class MediaTypeModule(ZabbixBase):
A dictionary of arguments that are related to transport type,
and are in a format that is understandable by Zabbix API.
"""
- truths = {'False': '0', 'True': '1'}
+ truths = {"False": "0", "True": "1"}
parameters = dict(
- status='0' if self._module.params['status'] == 'enabled' else '1',
+ status="0" if self._module.params["status"] == "enabled" else "1",
type={
- 'email': '0',
- 'script': '1',
- 'sms': '2',
- 'jabber': '3',
- 'webhook': '4',
- 'ez_texting': '100'
- }.get(self._module.params['type']),
+ "email": "0",
+ "script": "1",
+ "sms": "2",
+ "jabber": "3",
+ "webhook": "4",
+ "ez_texting": "100"
+ }.get(self._module.params["type"]),
)
- if LooseVersion(self._zbx_api_version) >= LooseVersion('4.4'):
- parameters.update(dict(
- name=self._module.params['name'],
- description=self._module.params['description'],
- ))
- else:
- parameters.update(dict(description=self._module.params['name']))
+ parameters.update(dict(
+ name=self._module.params["name"],
+ description=self._module.params["description"],
+ maxsessions=str(self._module.params["max_sessions"]),
+ maxattempts=str(self._module.params["max_attempts"]),
+ attempt_interval=str(self._module.params["attempt_interval"])
+ ))
- if LooseVersion(self._zbx_api_version) >= LooseVersion('3.4'):
- parameters.update(dict(
- maxsessions=str(self._module.params['max_sessions']),
- maxattempts=str(self._module.params['max_attempts']),
- attempt_interval=str(self._module.params['attempt_interval'])
- ))
-
- if self._module.params['message_templates'] and LooseVersion(self._zbx_api_version) >= LooseVersion('5.0'):
+ if self._module.params["message_templates"]:
msg_templates = []
- for template in self._module.params['message_templates']:
+ for template in self._module.params["message_templates"]:
msg_templates.append(dict(
eventsource={
- 'triggers': '0',
- 'discovery': '1',
- 'autoregistration': '2',
- 'internal': '3'}.get(template['eventsource']),
+ "triggers": "0",
+ "discovery": "1",
+ "autoregistration": "2",
+ "internal": "3"}.get(template["eventsource"]),
recovery={
- 'operations': '0',
- 'recovery_operations': '1',
- 'update_operations': '2'}.get(template['recovery']),
- subject=template['subject'],
- message=template['body']
+ "operations": "0",
+ "recovery_operations": "1",
+ "update_operations": "2"}.get(template["recovery"]),
+ subject=template["subject"],
+ message=template["body"]
))
parameters.update(dict(message_templates=msg_templates))
- if self._module.params['type'] == 'email':
+ if self._module.params["type"] == "email":
parameters.update(dict(
- smtp_server=self._module.params['smtp_server'],
- smtp_port=str(self._module.params['smtp_server_port']),
- smtp_helo=self._module.params['smtp_helo'],
- smtp_email=self._module.params['smtp_email'],
- smtp_security={'None': '0', 'STARTTLS': '1', 'SSL/TLS': '2'}.get(str(self._module.params['smtp_security'])),
- smtp_authentication=truths.get(str(self._module.params['smtp_authentication'])),
- smtp_verify_host=truths.get(str(self._module.params['smtp_verify_host'])),
- smtp_verify_peer=truths.get(str(self._module.params['smtp_verify_peer'])),
- username=self._module.params['username'],
- passwd=self._module.params['password']
+ smtp_server=self._module.params["smtp_server"],
+ smtp_port=str(self._module.params["smtp_server_port"]),
+ smtp_helo=self._module.params["smtp_helo"],
+ smtp_email=self._module.params["smtp_email"],
+ smtp_security={"None": "0", "STARTTLS": "1", "SSL/TLS": "2"}.get(str(self._module.params["smtp_security"])),
+ smtp_authentication=truths.get(str(self._module.params["smtp_authentication"])),
+ smtp_verify_host=truths.get(str(self._module.params["smtp_verify_host"])),
+ smtp_verify_peer=truths.get(str(self._module.params["smtp_verify_peer"])),
+ username=self._module.params["username"],
+ passwd=self._module.params["password"]
))
- if LooseVersion(self._zbx_api_version) >= LooseVersion('6.0'):
- if parameters['smtp_authentication'] == '0':
- parameters.pop('username')
- parameters.pop('passwd')
+ if parameters["smtp_authentication"] == "0":
+ parameters.pop("username")
+ parameters.pop("passwd")
return parameters
- elif self._module.params['type'] == 'script':
- if LooseVersion(self._zbx_api_version) < LooseVersion('6.4'):
- if self._module.params['script_params'] is None:
- _script_params = '' # ZBX-15706
+ elif self._module.params["type"] == "script":
+ if LooseVersion(self._zbx_api_version) < LooseVersion("6.4"):
+ if self._module.params["script_params"] is None:
+ _script_params = "" # ZBX-15706
else:
- _script_params = '\n'.join(str(i) for i in self._module.params['script_params']) + '\n'
+ _script_params = "\n".join(str(i) for i in self._module.params["script_params"]) + "\n"
parameters.update(dict(
- exec_path=self._module.params['script_name'],
+ exec_path=self._module.params["script_name"],
exec_params=_script_params
))
else:
_script_params = []
- if self._module.params['script_params']:
- for i, val in enumerate(self._module.params['script_params']):
- _script_params.append({'sortorder': str(i), 'value': val})
+ if self._module.params["script_params"]:
+ for i, val in enumerate(self._module.params["script_params"]):
+ _script_params.append({"sortorder": str(i), "value": val})
parameters.update(dict(
- exec_path=self._module.params['script_name'],
+ exec_path=self._module.params["script_name"],
parameters=_script_params
))
return parameters
- elif self._module.params['type'] == 'sms':
- parameters.update(dict(gsm_modem=self._module.params['gsm_modem']))
+ elif self._module.params["type"] == "sms":
+ parameters.update(dict(gsm_modem=self._module.params["gsm_modem"]))
return parameters
- elif self._module.params['type'] == 'webhook' and LooseVersion(self._zbx_api_version) >= LooseVersion('4.4'):
+ elif self._module.params["type"] == "webhook":
parameters.update(dict(
- script=self._module.params['webhook_script'],
- timeout=self._module.params['webhook_timeout'],
- process_tags=truths.get(str(self._module.params['process_tags'])),
- show_event_menu=truths.get(str(self._module.params['event_menu'])),
- parameters=self._module.params['webhook_params']
+ script=self._module.params["webhook_script"],
+ timeout=self._module.params["webhook_timeout"],
+ process_tags=truths.get(str(self._module.params["process_tags"])),
+ show_event_menu=truths.get(str(self._module.params["event_menu"])),
+ parameters=self._module.params["webhook_params"]
))
- if self._module.params['event_menu']:
+ if self._module.params["event_menu"]:
parameters.update(dict(
- event_menu_url=self._module.params['event_menu_url'],
- event_menu_name=self._module.params['event_menu_name']
+ event_menu_url=self._module.params["event_menu_url"],
+ event_menu_name=self._module.params["event_menu_name"]
))
return parameters
- elif self._module.params['type'] == 'jabber' and LooseVersion(self._zbx_api_version) <= LooseVersion('4.2'):
- parameters.update(dict(
- username=self._module.params['username'],
- passwd=self._module.params['password']
- ))
- return parameters
-
- elif self._module.params['type'] == 'ez_texting' and LooseVersion(self._zbx_api_version) <= LooseVersion('4.2'):
- parameters.update(dict(
- username=self._module.params['username'],
- passwd=self._module.params['password'],
- exec_path={'USA': '0', 'Canada': '1'}.get(self._module.params['message_text_limit']),
- ))
- return parameters
-
- self._module.fail_json(msg="%s is unsupported for Zabbix version %s" % (parameters['unsupported_parameter'], parameters['zbx_api_version']))
+ self._module.fail_json(msg="%s is unsupported for Zabbix version %s" % (self._module.params["type"], self._zbx_api_version))
def validate_params(self, params):
"""Validates arguments that are required together.
@@ -629,7 +595,7 @@ class MediaTypeModule(ZabbixBase):
msg="Following arguments are required when {key} is {value}: {arguments}".format(
key=param[0],
value=param[1],
- arguments=', '.join(param[2])
+ arguments=", ".join(param[2])
)
)
@@ -646,35 +612,37 @@ class MediaTypeModule(ZabbixBase):
returned by diff() function with
existing mediatype data and new params passed to it.
"""
- get_params = {'output': 'extend', 'mediatypeids': [mediatype_id]}
- if LooseVersion(self._zbx_api_version) >= LooseVersion('5.0'):
- get_params.update({'selectMessageTemplates': 'extend'})
+ get_params = {
+ "output": "extend",
+ "mediatypeids": [mediatype_id],
+ "selectMessageTemplates": "extend"
+ }
existing_mediatype = self._zapi.mediatype.get(get_params)[0]
- if existing_mediatype['type'] != kwargs['type']:
+ if existing_mediatype["type"] != kwargs["type"]:
return kwargs, diff(existing_mediatype, kwargs)
else:
params_to_update = {}
for key in kwargs:
# sort list of parameters to prevent mismatch due to reordering
- if key == 'parameters' and (kwargs[key] != [] or existing_mediatype[key] != []):
- if LooseVersion(self._zbx_api_version) < LooseVersion('6.4'):
- kwargs[key] = sorted(kwargs[key], key=lambda x: x['name'])
- existing_mediatype[key] = sorted(existing_mediatype[key], key=lambda x: x['name'])
+ if key == "parameters" and (kwargs[key] != [] or existing_mediatype[key] != []):
+ if LooseVersion(self._zbx_api_version) < LooseVersion("6.4"):
+ kwargs[key] = sorted(kwargs[key], key=lambda x: x["name"])
+ existing_mediatype[key] = sorted(existing_mediatype[key], key=lambda x: x["name"])
else:
- if kwargs['type'] == '1': # script
- kwargs[key] = sorted(kwargs[key], key=lambda x: x['sortorder'])
- existing_mediatype[key] = sorted(existing_mediatype[key], key=lambda x: x['sortorder'])
- elif kwargs['type'] == '4': # webhook
- kwargs[key] = sorted(kwargs[key], key=lambda x: x['name'])
- existing_mediatype[key] = sorted(existing_mediatype[key], key=lambda x: x['name'])
-
- if key == 'message_templates' and (kwargs[key] != [] or existing_mediatype[key] != []):
- kwargs[key] = sorted(kwargs[key], key=lambda x: x['subject'])
- existing_mediatype[key] = sorted(existing_mediatype[key], key=lambda x: x['subject'])
-
- if (not (kwargs[key] is None and existing_mediatype[key] == '')) and kwargs[key] != existing_mediatype[key]:
+ if kwargs["type"] == "1": # script
+ kwargs[key] = sorted(kwargs[key], key=lambda x: x["sortorder"])
+ existing_mediatype[key] = sorted(existing_mediatype[key], key=lambda x: x["sortorder"])
+ elif kwargs["type"] == "4": # webhook
+ kwargs[key] = sorted(kwargs[key], key=lambda x: x["name"])
+ existing_mediatype[key] = sorted(existing_mediatype[key], key=lambda x: x["name"])
+
+ if key == "message_templates" and (kwargs[key] != [] or existing_mediatype[key] != []):
+ kwargs[key] = sorted(kwargs[key], key=lambda x: x["subject"])
+ existing_mediatype[key] = sorted(existing_mediatype[key], key=lambda x: x["subject"])
+
+ 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)
@@ -688,89 +656,89 @@ class MediaTypeModule(ZabbixBase):
try:
self._zapi.mediatype.update(kwargs)
except Exception as e:
- self._module.fail_json(msg="Failed to update mediatype '{_id}': {e}".format(_id=kwargs['mediatypeid'], e=e))
+ self._module.fail_json(msg="Failed to update mediatype '{_id}': {e}".format(_id=kwargs["mediatypeid"], e=e))
def create_mediatype(self, **kwargs):
try:
self._zapi.mediatype.create(kwargs)
except Exception as e:
- self._module.fail_json(msg="Failed to create mediatype '{name}': {e}".format(name=kwargs['name'], e=e))
+ self._module.fail_json(msg="Failed to create mediatype '{name}': {e}".format(name=kwargs["name"], e=e))
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- name=dict(type='str', required=True),
- description=dict(type='str', required=False, default=''),
- state=dict(type='str', default='present', choices=['present', 'absent']),
- type=dict(type='str', choices=['email', 'script', 'sms', 'webhook', '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='str', default='10s', required=False),
+ name=dict(type="str", required=True),
+ description=dict(type="str", required=False, default=""),
+ state=dict(type="str", default="present", choices=["present", "absent"]),
+ type=dict(type="str", choices=["email", "script", "sms", "webhook", "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="str", default="10s", required=False),
# Script
- script_name=dict(type='str', required=False),
- script_params=dict(type='list', required=False),
+ script_name=dict(type="str", required=False),
+ script_params=dict(type="list", required=False, elements="str"),
# SMS
- gsm_modem=dict(type='str', required=False),
+ gsm_modem=dict(type="str", required=False),
# Jabber
- username=dict(type='str', required=False),
- password=dict(type='str', required=False, no_log=True),
+ 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),
+ 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']),
+ message_text_limit=dict(type="str", required=False, choices=["USA", "Canada"]),
# Webhook
- webhook_script=dict(type='str'),
- webhook_timeout=dict(type='str', default='30s'),
- process_tags=dict(type='bool', default=False),
- event_menu=dict(type='bool', default=False),
- event_menu_url=dict(type='str'),
- event_menu_name=dict(type='str'),
+ webhook_script=dict(type="str"),
+ webhook_timeout=dict(type="str", default="30s"),
+ process_tags=dict(type="bool", default=False),
+ event_menu=dict(type="bool", default=False),
+ event_menu_url=dict(type="str"),
+ event_menu_name=dict(type="str"),
webhook_params=dict(
- type='list',
- elements='dict',
+ type="list",
+ elements="dict",
default=[],
required=False,
options=dict(
- name=dict(type='str', required=True),
- value=dict(type='str', default='')
+ name=dict(type="str", required=True),
+ value=dict(type="str", default="")
)
),
message_templates=dict(
- type='list',
- elements='dict',
+ type="list",
+ elements="dict",
default=[],
required=False,
options=dict(
- eventsource=dict(type='str', choices=['triggers', 'discovery', 'autoregistration', 'internal']),
- recovery=dict(type='str', choices=['operations', 'recovery_operations', 'update_operations']),
- subject=dict(type='str', default=''),
- body=dict(type='str', default='')
+ eventsource=dict(type="str", choices=["triggers", "discovery", "autoregistration", "internal"]),
+ recovery=dict(type="str", choices=["operations", "recovery_operations", "update_operations"]),
+ subject=dict(type="str", default=""),
+ body=dict(type="str", default="")
),
required_together=[
- ['eventsource', 'recovery']
+ ["eventsource", "recovery"]
],
)
))
# this is used to simulate `required_if` of `AnsibleModule`, but only when state=present
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']],
- ['type', 'webhook', ['webhook_script']],
- ['event_menu', True, ['event_menu_url', 'event_menu_name']],
- ['smtp_authentication', True, ['username', 'password']]
+ ["type", "email", ["smtp_email"]],
+ ["type", "script", ["script_name"]],
+ ["type", "sms", ["gsm_modem"]],
+ ["type", "jabber", ["username", "password"]],
+ ["type", "ez_texting", ["username", "password", "message_text_limit"]],
+ ["type", "webhook", ["webhook_script"]],
+ ["event_menu", True, ["event_menu_url", "event_menu_name"]],
+ ["smtp_authentication", True, ["username", "password"]]
]
module = AnsibleModule(
@@ -778,24 +746,18 @@ def main():
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- state = module.params['state']
- name = module.params['name']
+ state = module.params["state"]
+ name = module.params["name"]
mediatype = MediaTypeModule(module)
- if module.params['state'] == 'present':
+ if module.params["state"] == "present":
mediatype.validate_params(required_params)
mediatype_exists, mediatype_id = mediatype.check_if_mediatype_exists(name)
parameters = mediatype.construct_parameters()
if mediatype_exists:
- if state == 'absent':
+ if state == "absent":
if module.check_mode:
module.exit_json(
changed=True,
@@ -860,5 +822,5 @@ def main():
)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_proxy.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_proxy.py
index 3fdfe42c1..a5ddbe137 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_proxy.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_proxy.py
@@ -22,7 +22,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
---
module: zabbix_proxy
short_description: Create/delete/get/update Zabbix proxies
@@ -31,7 +31,7 @@ description:
author:
- "Alen Komic (@akomic)"
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
options:
proxy_name:
description:
@@ -42,7 +42,6 @@ options:
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:
@@ -54,22 +53,22 @@ options:
description:
- Type of proxy. (4 - active, 5 - passive)
required: false
- choices: ['active', 'passive']
+ choices: ["active", "passive"]
default: "active"
type: str
tls_connect:
description:
- Connections to proxy.
required: false
- choices: ['no_encryption','PSK','certificate']
- default: 'no_encryption'
+ 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'
+ choices: ["no_encryption","PSK","certificate"]
+ default: "no_encryption"
type: str
ca_cert:
description:
@@ -98,14 +97,14 @@ options:
- 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']
+ 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).
+ - U(https://www.zabbix.com/documentation/current/en/manual/api/reference/proxy/object#proxy-interface).
required: false
suboptions:
useip:
@@ -120,53 +119,37 @@ options:
description:
- IP address used by proxy interface.
- Required if I(useip=1).
- default: ''
+ default: ""
dns:
type: str
description:
- DNS name of the proxy interface.
- Required if I(useip=0).
- default: ''
+ 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: "10051"
default: {}
type: dict
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: Create or update a proxy with proxy type active
@@ -177,7 +160,7 @@ EXAMPLES = r'''
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_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_proxy:
proxy_name: ExampleProxy
@@ -194,7 +177,7 @@ EXAMPLES = r'''
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_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_proxy:
proxy_name: ExampleProxy
@@ -214,7 +197,7 @@ EXAMPLES = r'''
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_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_proxy:
proxy_name: ExampleProxy
@@ -224,15 +207,14 @@ EXAMPLES = r'''
interface:
dns: proxy.example.com
port: 10051
-'''
+"""
-RETURN = r''' # '''
+RETURN = r""" # """
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.zabbix.plugins.module_utils.base import ZabbixBase
-from ansible.module_utils.compat.version import LooseVersion
import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabbix_utils
@@ -243,13 +225,13 @@ class Proxy(ZabbixBase):
self.existing_data = None
def proxy_exists(self, proxy_name):
- result = self._zapi.proxy.get({'output': 'extend',
- 'selectInterface': 'extend',
- 'filter': {'host': proxy_name}})
+ result = self._zapi.proxy.get({"output": "extend",
+ "selectInterface": "extend",
+ "filter": {"host": proxy_name}})
- if len(result) > 0 and 'proxyid' in result[0]:
+ if len(result) > 0 and "proxyid" in result[0]:
self.existing_data = result[0]
- return result[0]['proxyid']
+ return result[0]["proxyid"]
else:
return result
@@ -263,23 +245,19 @@ class Proxy(ZabbixBase):
if data[item]:
parameters[item] = data[item]
- if 'proxy_address' in data and data['status'] != '5':
- parameters.pop('proxy_address', False)
+ 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)
- else:
- if LooseVersion(self._zbx_api_version) >= LooseVersion('6.0'):
- parameters['interface'].pop('type')
- parameters['interface'].pop('main')
+ 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']))
+ result="Successfully added proxy %s (%s)" % (data["host"], data["status"]))
if len(proxy_ids_list) >= 1:
- return proxy_ids_list['proxyids'][0]
+ return proxy_ids_list["proxyids"][0]
except Exception as e:
- self._module.fail_json(msg="Failed to create proxy %s: %s" % (data['host'], e))
+ self._module.fail_json(msg="Failed to create proxy %s: %s" % (data["host"], e))
def delete_proxy(self, proxy_id, proxy_name):
try:
@@ -299,33 +277,22 @@ class Proxy(ZabbixBase):
for key in data:
if data[key]:
parameters[key] = data[key]
- if 'interface' in parameters:
- if parameters['status'] == '5':
+ if "interface" in parameters:
+ if parameters["status"] == "5":
# Active proxy
- parameters.pop('interface', False)
+ parameters.pop("interface", False)
else:
# Passive proxy
- parameters['interface']['useip'] = str(parameters['interface']['useip'])
- if LooseVersion(self._zbx_api_version) >= LooseVersion('6.0.0'):
- parameters['interface'].pop('type', False)
- parameters['interface'].pop('main', False)
- else:
- parameters['interface']['type'] = '0'
- parameters['interface']['main'] = '1'
- if ('interface' in self.existing_data
- and isinstance(self.existing_data['interface'], dict)):
- new_interface = self.existing_data['interface'].copy()
- new_interface.update(parameters['interface'])
- parameters['interface'] = new_interface
-
- if parameters['status'] == '5':
+ parameters["interface"]["useip"] = str(parameters["interface"]["useip"])
+
+ if parameters["status"] == "5":
# Active proxy
- parameters.pop('tls_connect', False)
+ parameters.pop("tls_connect", False)
else:
# Passive proxy
- parameters.pop('tls_accept', False)
+ parameters.pop("tls_accept", False)
- parameters['proxyid'] = proxy_id
+ parameters["proxyid"] = proxy_id
change_parameters = {}
difference = zabbix_utils.helper_cleanup_data(zabbix_utils.helper_compare_dictionaries(parameters, self.existing_data, change_parameters))
@@ -333,43 +300,41 @@ class Proxy(ZabbixBase):
if difference == {}:
self._module.exit_json(changed=False)
else:
- difference['proxyid'] = proxy_id
+ difference["proxyid"] = proxy_id
self._zapi.proxy.update(parameters)
self._module.exit_json(
changed=True,
result="Successfully updated proxy %s (%s)" %
- (data['host'], proxy_id)
+ (data["host"], proxy_id)
)
except Exception as e:
self._module.fail_json(msg="Failed to update proxy %s: %s" %
- (data['host'], e))
+ (data["host"], e))
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- proxy_name=dict(type='str', required=True),
- proxy_address=dict(type='str', required=False),
- 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, no_log=True),
+ proxy_name=dict(type="str", required=True),
+ proxy_address=dict(type="str", required=False),
+ 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, no_log=True),
interface=dict(
- type='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="3.0.0", removed_from_collection='community.zabbix'), # was Ansible 2.14
- main=dict(type='int', default=0, removed_in_version="3.0.0", removed_from_collection='community.zabbix'), # was Ansible 2.14
+ 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")
),
)
))
@@ -378,38 +343,32 @@ def main():
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- 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']
- interface = module.params['interface']
+ 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"]
+ interface = module.params["interface"]
# convert enabled to 0; disabled to 1
status = 6 if status == "passive" else 5
- if tls_connect == 'certificate':
+ if tls_connect == "certificate":
tls_connect = 4
- elif tls_connect == 'PSK':
+ elif tls_connect == "PSK":
tls_connect = 2
else:
tls_connect = 1
- if tls_accept == 'certificate':
+ if tls_accept == "certificate":
tls_accept = 4
- elif tls_accept == 'PSK':
+ elif tls_accept == "PSK":
tls_accept = 2
else:
tls_accept = 1
@@ -425,17 +384,17 @@ def main():
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
+ "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":
@@ -443,19 +402,19 @@ def main():
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
+ "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__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_proxy_info.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_proxy_info.py
index b40022883..c82112609 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_proxy_info.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_proxy_info.py
@@ -8,7 +8,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
-DOCUMENTATION = '''
+DOCUMENTATION = """
module: zabbix_proxy_info
short_description: Gather information about Zabbix proxy
version_added: 1.5.0
@@ -17,7 +17,7 @@ author:
description:
- This module allows you to obtain detailed information about configured zabbix proxies.
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
options:
proxy_name:
description:
@@ -33,19 +33,19 @@ options:
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = '''
+EXAMPLES = """
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: Get zabbix proxy info alongside the list of hosts monitored by the proxy
@@ -56,17 +56,14 @@ EXAMPLES = '''
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_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_proxy_info:
- server_url: "http://zabbix.example.com/zabbix/"
- login_user: admin
- login_password: secret
proxy_name: zbx01.example.com
proxy_hosts: true
-'''
+"""
-RETURN = '''
+RETURN = """
zabbix_proxy:
description: example
returned: always
@@ -120,7 +117,7 @@ zabbix_proxy:
"tls_subject": "",
"uuid": ""
}
-'''
+"""
from ansible.module_utils.basic import AnsibleModule
@@ -134,15 +131,15 @@ class Proxy(ZabbixBase):
def get_proxy(self, name, hosts=False):
result = {}
params = {
- 'filter': {
- 'host': name
+ "filter": {
+ "host": name
},
- 'output': 'extend',
- 'selectInterface': 'extend',
+ "output": "extend",
+ "selectInterface": "extend",
}
if hosts:
- params['selectHosts'] = ['host', 'hostid']
+ params["selectHosts"] = ["host", "hostid"]
try:
result = self._zapi.proxy.get(params)
@@ -155,8 +152,8 @@ class Proxy(ZabbixBase):
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- proxy_name=dict(type='str', required=True),
- proxy_hosts=dict(type='bool', required=False, default=False),
+ proxy_name=dict(type="str", required=True),
+ proxy_hosts=dict(type="bool", required=False, default=False),
))
module = AnsibleModule(
@@ -164,14 +161,8 @@ def main():
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- name = module.params['proxy_name']
- hosts = module.params['proxy_hosts']
+ name = module.params["proxy_name"]
+ hosts = module.params["proxy_hosts"]
proxy = Proxy(module)
result = proxy.get_proxy(name, hosts)
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_regexp.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_regexp.py
new file mode 100644
index 000000000..fc3ccedee
--- /dev/null
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_regexp.py
@@ -0,0 +1,345 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright: (c) 2022, ONODERA Masaru <masaru-onodera@ieee.org>
+# 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 = """
+---
+module: zabbix_regexp
+
+short_description: Create/update/delete Zabbix regular expression
+
+
+description:
+ - This module allows you to create, update and delete Zabbix regular expression.
+
+author:
+ - ONODERA Masaru(@masa-orca)
+
+requirements:
+ - "python >= 3.9"
+
+version_added: 2.1.0
+
+options:
+ name:
+ description:
+ - Name of this regular expression
+ type: str
+ required: true
+ test_string:
+ description:
+ - A test string for this regular expression
+ type: str
+ expressions:
+ description:
+ - List of expressions.
+ - The regular expression returns true when all expressions return true.
+ - Required when C(state=present).
+ type: list
+ elements: dict
+ suboptions:
+ expression:
+ description:
+ - A expression string
+ type: str
+ required: true
+ expression_type:
+ description:
+ - A expression string
+ type: str
+ required: true
+ choices:
+ - "character_string_included"
+ - "any_character_string_included"
+ - "character_string_not_included"
+ - "result_is_true"
+ - "result_is_false"
+ exp_delimiter:
+ description:
+ - Delimiter for expression.
+ - Used if expression_type is C(any_character_string_included).
+ - Default values is C(,)
+ type: str
+ choices: [",", ".", "/"]
+ case_sensitive:
+ description:
+ - If true, the expression will be case sensitive.
+ type: bool
+ default: false
+ state:
+ description:
+ - State of the regular expression.
+ type: str
+ choices: ['present', 'absent']
+ default: 'present'
+
+
+notes:
+ - Only Zabbix >= 6.0 is supported.
+
+extends_documentation_fragment:
+ - community.zabbix.zabbix
+
+"""
+
+EXAMPLES = """
+# 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: Update regexp of 'File systems for discovery'
+ # 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_regexp:
+ name: File systems for discovery
+ test_string: ext2
+ expressions:
+ - expression: "^(btrfs|ext2|ext3|ext4|reiser|xfs|ffs|ufs|jfs|jfs2|vxfs|hfs|apfs|refs|ntfs|fat32|zfs)$"
+ expression_type: result_is_true
+"""
+
+RETURN = """
+msg:
+ description: The result of the operation
+ returned: success
+ type: str
+ sample: 'Successfully updated regular expression setting'
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.community.zabbix.plugins.module_utils.base import ZabbixBase
+from ansible.module_utils.compat.version import LooseVersion
+
+import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabbix_utils
+
+
+class RegularExpression(ZabbixBase):
+ def __init__(self, module, zbx=None, zapi_wrapper=None):
+ super(RegularExpression, self).__init__(module, zbx, zapi_wrapper)
+ if LooseVersion(self._zbx_api_version) < LooseVersion("6.0"):
+ module.fail_json(
+ msg="This module doesn't support Zabbix versions lower than 6.0"
+ )
+
+ def get_regexps(self, regexp_name):
+ try:
+ regexps = self._zapi.regexp.get(
+ {
+ "output": "extend",
+ "selectExpressions": [
+ "expression",
+ "expression_type",
+ "exp_delimiter",
+ "case_sensitive",
+ ],
+ "filter": {"name": regexp_name},
+ }
+ )
+ if len(regexps) >= 2:
+ self._module.fail_json("Too many regexps are matched.")
+ return regexps
+ except Exception as e:
+ self._module.fail_json(
+ msg="Failed to get regular expression setting: %s" % e
+ )
+
+ def delete_regexp(self, regexp):
+ try:
+ parameter = [regexp["regexpid"]]
+ if self._module.check_mode:
+ self._module.exit_json(changed=True)
+ self._zapi.regexp.delete(parameter)
+ self._module.exit_json(
+ changed=True, msg="Successfully deleted regular expression setting."
+ )
+ except Exception as e:
+ self._module.fail_json(
+ msg="Failed to delete regular expression setting: %s" % e
+ )
+
+ def _convert_expressions_to_json(self, expressions):
+ expression_type_values = [
+ "character_string_included",
+ "any_character_string_included",
+ "character_string_not_included",
+ "result_is_true",
+ "result_is_false",
+ ]
+
+ expression_jsons = []
+ for expression in expressions:
+ expression_json = {}
+
+ expression_json["expression"] = expression["expression"]
+ expression_type = zabbix_utils.helper_to_numeric_value(
+ expression_type_values, expression["expression_type"]
+ )
+ expression_json["expression_type"] = str(expression_type)
+ if expression["expression_type"] == "any_character_string_included":
+ if expression["exp_delimiter"]:
+ expression_json["exp_delimiter"] = expression["exp_delimiter"]
+ else:
+ expression_json["exp_delimiter"] = ","
+ elif expression["exp_delimiter"]:
+ self._module.warn(
+ "A value of exp_delimiter will be ignored because expression_type is not 'any_character_string_included'."
+ )
+ case_sensitive = "0"
+ if expression["case_sensitive"]:
+ case_sensitive = "1"
+ expression_json["case_sensitive"] = case_sensitive
+
+ expression_jsons.append(expression_json)
+ return expression_jsons
+
+ def create_regexp(self, name, test_string, expressions):
+ try:
+ if self._module.check_mode:
+ self._module.exit_json(changed=True)
+ self._zapi.regexp.create(
+ {
+ "name": name,
+ "test_string": test_string,
+ "expressions": self._convert_expressions_to_json(expressions),
+ }
+ )
+ self._module.exit_json(
+ changed=True, msg="Successfully created regular expression setting."
+ )
+ except Exception as e:
+ self._module.fail_json(
+ msg="Failed to create regular expression setting: %s" % e
+ )
+
+ def update_regexp(self, current_regexp, name, test_string, expressions):
+ try:
+ current_expressions = []
+ for expression in current_regexp["expressions"]:
+ if expression["expression_type"] != "1":
+ expression = zabbix_utils.helper_normalize_data(
+ expression, del_keys=["exp_delimiter"]
+ )[0]
+ current_expressions.append(expression)
+ future_expressions = self._convert_expressions_to_json(expressions)
+ diff_expressions = []
+ zabbix_utils.helper_compare_lists(
+ current_expressions, future_expressions, diff_expressions
+ )
+ if (
+ current_regexp["name"] == name
+ and current_regexp["test_string"] == test_string
+ and len(diff_expressions) == 0
+ ):
+ self._module.exit_json(changed=False)
+ else:
+ if self._module.check_mode:
+ self._module.exit_json(changed=True)
+ self._zapi.regexp.update(
+ {
+ "regexpid": current_regexp["regexpid"],
+ "name": name,
+ "test_string": test_string,
+ "expressions": future_expressions,
+ }
+ )
+ self._module.exit_json(
+ changed=True, msg="Successfully updated regular expression setting."
+ )
+ except Exception as e:
+ self._module.fail_json(
+ msg="Failed to update regular expression setting: %s" % e
+ )
+
+
+def main():
+ """Main ansible module function"""
+
+ argument_spec = zabbix_utils.zabbix_common_argument_spec()
+ argument_spec.update(
+ dict(
+ name=dict(type="str", required=True),
+ test_string=dict(
+ type="str",
+ ),
+ expressions=dict(
+ type="list",
+ elements="dict",
+ options=dict(
+ expression=dict(type="str", required=True),
+ expression_type=dict(
+ type="str",
+ required=True,
+ choices=[
+ "character_string_included",
+ "any_character_string_included",
+ "character_string_not_included",
+ "result_is_true",
+ "result_is_false",
+ ],
+ ),
+ exp_delimiter=dict(type="str", choices=[",", ".", "/"]),
+ case_sensitive=dict(type="bool", default=False),
+ ),
+ ),
+ state=dict(
+ type="str",
+ required=False,
+ default="present",
+ choices=["present", "absent"],
+ ),
+ )
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ required_if=[["state", "present", ["expressions"]]],
+ supports_check_mode=True,
+ )
+
+ name = module.params["name"]
+ test_string = module.params["test_string"]
+ expressions = module.params["expressions"]
+ state = module.params["state"]
+
+ regexp_class_obj = RegularExpression(module)
+ regexps = regexp_class_obj.get_regexps(name)
+
+ if state == "absent":
+ if len(regexps) == 1:
+ regexp_class_obj.delete_regexp(regexps[0])
+ else:
+ module.exit_json(changed=False)
+ else:
+ if len(regexps) == 1:
+ regexp_class_obj.update_regexp(regexps[0], name, test_string, expressions)
+ else:
+ regexp_class_obj.create_regexp(name, test_string, expressions)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_screen.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_screen.py
deleted file mode 100644
index 5e350fc80..000000000
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_screen.py
+++ /dev/null
@@ -1,496 +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
-
-
-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 <= 5.2"
-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(s) will be used for searching hosts.
- - Required if I(state=present).
- type: list
- elements: str
- aliases: [ 'host_groups' ]
- 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.zabbix.zabbix
-
-
-notes:
- - Too many concurrent updates to the same screen may cause Zabbix to return errors, see examples for a workaround if needed.
- - Screens where removed from Zabbix with Version 5.4
-'''
-
-EXAMPLES = r'''
-# If you want to use Username and Password to be authenticated by Zabbix Server
-- name: Set credentials to access Zabbix Server API
- 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
- set_fact:
- ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
-
-# Screens where removed from Zabbix with Version 5.4
-
-# Create/update a screen.
-- name: Create a new screen or update an existing screen's items 5 in a row
- # 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_screen:
- 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
- # 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_screen:
- 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
- # 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_screen:
- 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]
-
-# Create/update using multiple hosts_groups. Hosts NOT present in all listed host_groups will be skipped.
-- name: Create new screen or update the existing screen's items for hosts in both given groups
- # 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_screen:
- screens:
- - screen_name: ExampleScreen1
- host_group:
- - Example group1
- - Example group2
- state: present
- graph_names:
- - Example graph1
- - Example graph2
- graph_width: 200
- graph_height: 100
-'''
-
-
-from ansible.module_utils.basic import AnsibleModule
-
-from ansible_collections.community.zabbix.plugins.module_utils.base import ZabbixBase
-from ansible_collections.community.zabbix.plugins.module_utils.wrappers import ScreenItem
-from ansible.module_utils.compat.version import LooseVersion
-
-import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabbix_utils
-
-
-class Screen(ZabbixBase):
- # get list of group ids by list of group names
- def get_host_group_ids(self, group_names):
- if not group_names:
- self._module.fail_json(msg="group_name is required")
- hostGroup_list = self._zapi.hostgroup.get({'output': 'extend', 'filter': {'name': group_names}})
- if not hostGroup_list:
- self._module.fail_json(msg="Host group not found: {0}".format(group_names))
- else:
- hostGroup_ids = [g['groupid'] for g in hostGroup_list]
- return hostGroup_ids
-
- # get monitored host_ids by host_group_ids
- # (the hosts belonging to all given groups)
- def get_host_ids_by_group_ids(self, group_ids, sort):
- host_list = self._zapi.host.get({'output': 'extend', 'selectGroups': 'groupid', 'groupids': group_ids, 'monitored_hosts': 1})
- if not host_list:
- self._module.fail_json(msg="No hosts in the all group(s) with ids {0}".format(group_ids))
- else:
- if sort:
- host_list = sorted(host_list, key=lambda name: name['name'])
- host_ids = []
- for host in host_list:
- host_group_ids = [g['groupid'] for g in host['groups']]
- # Check if all search group ids are in hosts group ids
- if set(group_ids).issubset(host_group_ids):
- host_id = host['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):
- 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)
- ScreenItem.delete(self, screen_item_id_list)
- return True
- return False
-
- # 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
-
- # 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:
- ScreenItem.create(self, ignoreExists=True, data={'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:
- ScreenItem.create(self, ignoreExists=True, data={'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})
-
-
-def main():
- argument_spec = zabbix_utils.zabbix_common_argument_spec()
- argument_spec.update(dict(
- screens=dict(
- type='list',
- elements='dict',
- required=True,
- options=dict(
- screen_name=dict(type='str', required=True),
- host_group=dict(type='list', aliases=['host_groups'], elements='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']]
- ]
- )
- ))
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True
- )
-
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- screens = module.params['screens']
-
- screen = Screen(module)
- if LooseVersion(screen._zbx_api_version) >= LooseVersion('5.4'):
- module.fail_json(msg="Zabbix 5.4 removed the Screens feature see (%s)." % (
- "https://www.zabbix.com/documentation/current/en/manual/api/changes_5.2_-_5.4"
- ))
-
- 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_ids = screen.get_host_group_ids(host_group)
- hosts = screen.get_host_ids_by_group_ids(host_group_ids, sort)
- if not hosts:
- module.fail_json(msg="No hosts found belongin to all given groups: %s" % host_group)
- 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()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_script.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_script.py
index 15277b0fa..643851885 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_script.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_script.py
@@ -8,7 +8,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
-DOCUMENTATION = '''
+DOCUMENTATION = """
module: zabbix_script
short_description: Create/update/delete Zabbix scripts
version_added: 1.7.0
@@ -17,7 +17,7 @@ author:
description:
- This module allows you to create, update and delete scripts.
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
options:
name:
description:
@@ -27,10 +27,9 @@ options:
script_type:
description:
- Script type.
- - Types C(ssh), C(telnet) and C(webhook) works only with Zabbix >= 5.4.
type: str
required: true
- choices: ['script', 'ipmi', 'ssh', 'telnet', 'webhook']
+ choices: ["script", "ipmi", "ssh", "telnet", "webhook"]
command:
description:
- Command to run.
@@ -39,24 +38,22 @@ options:
scope:
description:
- Script scope.
- - Works only with Zabbix >= 5.4. For lower versions is silently ignored which is equivalent of C(manual_host_action).
type: str
required: false
- choices: ['action_operation', 'manual_host_action', 'manual_event_action']
- default: 'action_operation'
+ choices: ["action_operation", "manual_host_action", "manual_event_action"]
+ default: "action_operation"
execute_on:
description:
- Where to run the script.
- Used if type is C(script).
type: str
required: false
- choices: ['zabbix_agent', 'zabbix_server', 'zabbix_server_proxy']
- default: 'zabbix_server_proxy'
+ choices: ["zabbix_agent", "zabbix_server", "zabbix_server_proxy"]
+ default: "zabbix_server_proxy"
menu_path:
description:
- Folders separated by slash that form a menu like navigation in frontend when clicked on host or event.
- Used if scope is C(manual_host_action) or C(manual_event_action).
- - Works only with Zabbix >= 5.4. For lower versions is silently ignored. Prepend menu path to name instead.
type: str
required: false
authtype:
@@ -65,7 +62,7 @@ options:
- Used if type is C(ssh).
type: str
required: false
- choices: ['password', 'public_key']
+ choices: ["password", "public_key"]
username:
description:
- User name used for authentication.
@@ -98,25 +95,25 @@ options:
required: false
host_group:
description:
- - host group name that the script can be run on. If set to 'all', the script will be available on all host groups.
+ - host group name that the script can be run on. If set to "all", the script will be available on all host groups.
type: str
required: false
- default: 'all'
+ default: "all"
user_group:
description:
- - user group name that will be allowed to run the script. If set to 'all', the script will be available for all user groups.
+ - user group name that will be allowed to run the script. If set to "all", the script will be available for all user groups.
- Used if scope is C(manual_host_action) or C(manual_event_action).
type: str
required: false
- default: 'all'
+ default: "all"
host_access:
description:
- Host permissions needed to run the script.
- Used if scope is C(manual_host_action) or C(manual_event_action).
type: str
required: false
- choices: ['read', 'write']
- default: 'read'
+ choices: ["read", "write"]
+ default: "read"
confirmation:
description:
- Confirmation pop up text. The pop up will appear when trying to run the script from the Zabbix frontend.
@@ -127,9 +124,9 @@ options:
description:
- Webhook script execution timeout in seconds. Time suffixes are supported, e.g. 30s, 1m.
- Required if type is C(webhook).
- - 'Possible values: 1-60s.'
+ - "Possible values: 1-60s."
type: str
- default: '30s'
+ default: "30s"
required: false
parameters:
description:
@@ -148,7 +145,7 @@ options:
- Parameter value. Supports macros.
type: str
required: false
- default: ''
+ default: ""
description:
description:
- Description of the script.
@@ -159,24 +156,24 @@ options:
- State of the script.
type: str
required: false
- choices: ['present', 'absent']
- default: 'present'
+ choices: ["present", "absent"]
+ default: "present"
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = '''
+EXAMPLES = """
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: test - Create new action operation script to execute webhook
@@ -187,34 +184,33 @@ EXAMPLES = '''
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_zabbix_url_path: "zabbixeu" # If Zabbix WebUI runs on non-default (zabbix) path ,e.g. http://<FQDN>/zabbixeu
ansible_host: zabbix-example-fqdn.org
- zabbix_script:
+ community.zabbix.zabbix_script:
name: Test action operation script
scope: action_operation
script_type: webhook
- command: 'return 0'
+ command: "return 0"
description: "Test action operation script"
state: present
-'''
+"""
-RETURN = '''
-'''
+RETURN = """
+"""
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.zabbix.plugins.module_utils.base import ZabbixBase
-from ansible.module_utils.compat.version import LooseVersion
import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabbix_utils
class Script(ZabbixBase):
def get_script_ids(self, script_name):
script_ids = []
- scripts = self._zapi.script.get({'filter': {'name': script_name}})
+ scripts = self._zapi.script.get({"filter": {"name": script_name}})
for script in scripts:
- script_ids.append(script['scriptid'])
+ script_ids.append(script["scriptid"])
return script_ids
def create_script(self, name, script_type, command, scope, execute_on, menu_path, authtype, username, password,
@@ -233,103 +229,95 @@ class Script(ZabbixBase):
def generate_script_config(self, name, script_type, command, scope, execute_on, menu_path, authtype, username, password,
publickey, privatekey, port, host_group, user_group, host_access, confirmation, script_timeout, parameters, description):
- if host_group == 'all':
- groupid = '0'
+ if host_group == "all":
+ groupid = "0"
else:
- groups = self._zapi.hostgroup.get({'filter': {'name': host_group}})
+ groups = self._zapi.hostgroup.get({"filter": {"name": host_group}})
if not groups:
- self._module.fail_json(changed=False, msg='Host group "%s" not found' % host_group)
- groupid = groups[0]['groupid']
+ self._module.fail_json(changed=False, msg="Host group '%s' not found" % host_group)
+ groupid = groups[0]["groupid"]
- if user_group == 'all':
- usrgrpid = '0'
+ if user_group == "all":
+ usrgrpid = "0"
else:
- user_groups = self._zapi.usergroup.get({'filter': {'name': user_group}})
+ user_groups = self._zapi.usergroup.get({"filter": {"name": user_group}})
if not user_groups:
- self._module.fail_json(changed=False, msg='User group "%s" not found' % user_group)
- usrgrpid = user_groups[0]['usrgrpid']
+ self._module.fail_json(changed=False, msg="User group '%s' not found" % user_group)
+ usrgrpid = user_groups[0]["usrgrpid"]
request = {
- 'name': name,
- 'type': str(zabbix_utils.helper_to_numeric_value([
- 'script',
- 'ipmi',
- 'ssh',
- 'telnet',
- '',
- 'webhook'], script_type)),
- 'command': command,
- 'scope': str(zabbix_utils.helper_to_numeric_value([
- '',
- 'action_operation',
- 'manual_host_action',
- '',
- 'manual_event_action'], scope)),
- 'groupid': groupid
+ "name": name,
+ "type": str(zabbix_utils.helper_to_numeric_value([
+ "script",
+ "ipmi",
+ "ssh",
+ "telnet",
+ "",
+ "webhook"], script_type)),
+ "command": command,
+ "scope": str(zabbix_utils.helper_to_numeric_value([
+ "",
+ "action_operation",
+ "manual_host_action",
+ "",
+ "manual_event_action"], scope)),
+ "groupid": groupid
}
if description is not None:
- request['description'] = description
+ request["description"] = description
- if script_type == 'script':
+ if script_type == "script":
if execute_on is None:
- execute_on = 'zabbix_server_proxy'
- request['execute_on'] = str(zabbix_utils.helper_to_numeric_value([
- 'zabbix_agent',
- 'zabbix_server',
- 'zabbix_server_proxy'], execute_on))
+ execute_on = "zabbix_server_proxy"
+ request["execute_on"] = str(zabbix_utils.helper_to_numeric_value([
+ "zabbix_agent",
+ "zabbix_server",
+ "zabbix_server_proxy"], execute_on))
- if scope in ['manual_host_action', 'manual_event_action']:
+ if scope in ["manual_host_action", "manual_event_action"]:
if menu_path is None:
- request['menu_path'] = ''
+ request["menu_path"] = ""
else:
- request['menu_path'] = menu_path
- request['usrgrpid'] = usrgrpid
- request['host_access'] = str(zabbix_utils.helper_to_numeric_value([
- '',
- '',
- 'read',
- 'write'], host_access))
+ request["menu_path"] = menu_path
+ request["usrgrpid"] = usrgrpid
+ request["host_access"] = str(zabbix_utils.helper_to_numeric_value([
+ "",
+ "",
+ "read",
+ "write"], host_access))
if confirmation is None:
- request['confirmation'] = ''
+ request["confirmation"] = ""
else:
- request['confirmation'] = confirmation
+ request["confirmation"] = confirmation
- if script_type == 'ssh':
+ if script_type == "ssh":
if authtype is None:
- self._module.fail_json(changed=False, msg='authtype must be provided for ssh script type')
- request['authtype'] = str(zabbix_utils.helper_to_numeric_value([
- 'password',
- 'public_key'], authtype))
- if authtype == 'public_key':
+ self._module.fail_json(changed=False, msg="authtype must be provided for ssh script type")
+ request["authtype"] = str(zabbix_utils.helper_to_numeric_value([
+ "password",
+ "public_key"], authtype))
+ if authtype == "public_key":
if publickey is None or privatekey is None:
- self._module.fail_json(changed=False, msg='publickey and privatekey must be provided for ssh script type with publickey authtype')
- request['publickey'] = publickey
- request['privatekey'] = privatekey
+ self._module.fail_json(changed=False, msg="publickey and privatekey must be provided for ssh script type with publickey authtype")
+ request["publickey"] = publickey
+ request["privatekey"] = privatekey
- if script_type in ['ssh', 'telnet']:
+ if script_type in ["ssh", "telnet"]:
if username is None:
- self._module.fail_json(changed=False, msg='username must be provided for "ssh" and "telnet" script types')
- request['username'] = username
- if (script_type == 'ssh' and authtype == 'password') or script_type == 'telnet':
+ self._module.fail_json(changed=False, msg="username must be provided for 'ssh' and 'telnet' script types")
+ request["username"] = username
+ if (script_type == "ssh" and authtype == "password") or script_type == "telnet":
if password is None:
- self._module.fail_json(changed=False, msg='password must be provided for telnet script type or ssh script type with password autheype')
- request['password'] = password
+ self._module.fail_json(changed=False, msg="password must be provided for telnet script type or ssh script type with password autheype")
+ request["password"] = password
if port is not None:
- request['port'] = port
+ request["port"] = port
- if script_type == 'webhook':
- request['timeout'] = script_timeout
+ if script_type == "webhook":
+ request["timeout"] = script_timeout
if parameters:
- request['parameters'] = parameters
-
- if LooseVersion(self._zbx_api_version) < LooseVersion('5.4'):
- if script_type not in ['script', 'ipmi']:
- self._module.fail_json(changed=False, msg='script_type must be script or ipmi in version <5.4')
- if 'scope' in request:
- del request['scope']
- if 'menu_path' in request:
- del request['menu_path']
+ request["parameters"] = parameters
return request
@@ -338,7 +326,7 @@ class Script(ZabbixBase):
generated_config = self.generate_script_config(name, script_type, command, scope, execute_on, menu_path, authtype, username,
password, publickey, privatekey, port, host_group, user_group, host_access,
confirmation, script_timeout, parameters, description)
- live_config = self._zapi.script.get({'filter': {'name': name}})[0]
+ live_config = self._zapi.script.get({"filter": {"name": name}})[0]
change_parameters = {}
difference = zabbix_utils.helper_cleanup_data(zabbix_utils.helper_compare_dictionaries(generated_config, live_config, change_parameters))
@@ -348,7 +336,7 @@ class Script(ZabbixBase):
if self._module.check_mode:
self._module.exit_json(changed=True)
- generated_config['scriptid'] = live_config['scriptid']
+ generated_config["scriptid"] = live_config["scriptid"]
self._zapi.script.update(generated_config)
self._module.exit_json(changed=True, msg="Script %s updated" % name)
@@ -356,55 +344,55 @@ class Script(ZabbixBase):
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- name=dict(type='str', required=True),
+ name=dict(type="str", required=True),
script_type=dict(
- type='str',
+ type="str",
required=True,
- choices=['script', 'ipmi', 'ssh', 'telnet', 'webhook']),
- command=dict(type='str', required=True),
+ choices=["script", "ipmi", "ssh", "telnet", "webhook"]),
+ command=dict(type="str", required=True),
scope=dict(
- type='str',
+ type="str",
required=False,
- choices=['action_operation', 'manual_host_action', 'manual_event_action'],
- default='action_operation'),
+ choices=["action_operation", "manual_host_action", "manual_event_action"],
+ default="action_operation"),
execute_on=dict(
- type='str',
+ type="str",
required=False,
- choices=['zabbix_agent', 'zabbix_server', 'zabbix_server_proxy'],
- default='zabbix_server_proxy'),
- menu_path=dict(type='str', required=False),
+ choices=["zabbix_agent", "zabbix_server", "zabbix_server_proxy"],
+ default="zabbix_server_proxy"),
+ menu_path=dict(type="str", required=False),
authtype=dict(
- type='str',
+ type="str",
required=False,
- choices=['password', 'public_key']),
- username=dict(type='str', required=False),
- password=dict(type='str', required=False, no_log=True),
- publickey=dict(type='str', required=False),
- privatekey=dict(type='str', required=False, no_log=True),
- port=dict(type='str', required=False),
- host_group=dict(type='str', required=False, default='all'),
- user_group=dict(type='str', required=False, default='all'),
+ choices=["password", "public_key"]),
+ username=dict(type="str", required=False),
+ password=dict(type="str", required=False, no_log=True),
+ publickey=dict(type="str", required=False),
+ privatekey=dict(type="str", required=False, no_log=True),
+ port=dict(type="str", required=False),
+ host_group=dict(type="str", required=False, default="all"),
+ user_group=dict(type="str", required=False, default="all"),
host_access=dict(
- type='str',
+ type="str",
required=False,
- choices=['read', 'write'],
- default='read'),
- confirmation=dict(type='str', required=False),
- script_timeout=dict(type='str', default='30s', required=False),
+ choices=["read", "write"],
+ default="read"),
+ confirmation=dict(type="str", required=False),
+ script_timeout=dict(type="str", default="30s", required=False),
parameters=dict(
- type='list',
- elements='dict',
+ type="list",
+ elements="dict",
options=dict(
- name=dict(type='str', required=True),
- value=dict(type='str', required=False, default='')
+ name=dict(type="str", required=True),
+ value=dict(type="str", required=False, default="")
)
),
- description=dict(type='str', required=False),
+ description=dict(type="str", required=False),
state=dict(
- type='str',
+ type="str",
required=False,
- default='present',
- choices=['present', 'absent'])
+ default="present",
+ choices=["present", "absent"])
))
module = AnsibleModule(
@@ -412,32 +400,26 @@ def main():
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- name = module.params['name']
- script_type = module.params['script_type']
- command = module.params['command']
- scope = module.params['scope']
- execute_on = module.params['execute_on']
- menu_path = module.params['menu_path']
- authtype = module.params['authtype']
- username = module.params['username']
- password = module.params['password']
- publickey = module.params['publickey']
- privatekey = module.params['privatekey']
- port = module.params['port']
- host_group = module.params['host_group']
- user_group = module.params['user_group']
- host_access = module.params['host_access']
- confirmation = module.params['confirmation']
- script_timeout = module.params['script_timeout']
- parameters = module.params['parameters']
- description = module.params['description']
- state = module.params['state']
+ name = module.params["name"]
+ script_type = module.params["script_type"]
+ command = module.params["command"]
+ scope = module.params["scope"]
+ execute_on = module.params["execute_on"]
+ menu_path = module.params["menu_path"]
+ authtype = module.params["authtype"]
+ username = module.params["username"]
+ password = module.params["password"]
+ publickey = module.params["publickey"]
+ privatekey = module.params["privatekey"]
+ port = module.params["port"]
+ host_group = module.params["host_group"]
+ user_group = module.params["user_group"]
+ host_access = module.params["host_access"]
+ confirmation = module.params["confirmation"]
+ script_timeout = module.params["script_timeout"]
+ parameters = module.params["parameters"]
+ description = module.params["description"]
+ state = module.params["state"]
script = Script(module)
script_ids = script.get_script_ids(name)
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_service.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_service.py
index 9468ee49a..8a7b9b605 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_service.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_service.py
@@ -8,7 +8,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
module: zabbix_service
short_description: Create/update/delete Zabbix service
@@ -18,61 +18,26 @@ author:
- "Emmanuel Riviere (@emriver)"
- "Evgeny Yurchenko (@BGmot)"
requirements:
- - "python >= 2.7"
+ - "python >= 3.9"
options:
name:
description:
- Name of Zabbix service
required: true
type: str
- parent:
- description:
- - Name of Zabbix service parent
- - With >= Zabbix 6.0 this field is removed from the API and is dropped silently by module.
- required: false
- type: str
- sla:
- description:
- - Sla value (i.e 99.99), goodsla in Zabbix API
- - With >= Zabbix 6.0 this field is removed from the API and is dropped silently by module.
- required: false
- type: float
- calculate_sla:
- description:
- - If yes, calculate the SLA value for this service, showsla in Zabbix API
- - With >= Zabbix 6.0 this field is removed from the API and is dropped silently by module.
- required: false
- default: false
- type: bool
algorithm:
description:
- - Algorithm used to calculate the sla with < Zabbix 6.0
- - ' - 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'
- - Status calculation rule. Only applicable if child services exists with >= Zabbix 6.0
- - ' - C(status_to_ok), set status to OK with'
- - ' - C(most_crit_if_all_children), most critical if all children have problems'
- - ' - C(most_crit_of_child_serv), most critical of child services with'
- required: false
- type: str
- choices: ["no", "one_child", "all_children", "status_to_ok", "most_crit_if_all_children", "most_crit_of_child_serv"]
- default: one_child
- trigger_name:
- description:
- - Name of trigger linked to the service.
- - With >= Zabbix 6.0 this field is removed from the API and is dropped silently by module.
- required: false
- type: str
- trigger_host:
- description:
- - Name of host linked to the service.
- - With >= Zabbix 6.0 this field is removed from the API and is dropped silently by module.
+ - Status calculation rule. Only applicable if child services exists.
+ - " - C(status_to_ok), set status to OK with"
+ - " - C(most_crit_if_all_children), most critical if all children have problems"
+ - " - C(most_crit_of_child_serv), most critical of child services with"
required: false
type: str
+ choices: ["status_to_ok", "most_crit_if_all_children", "most_crit_of_child_serv"]
+ default: status_to_ok
state:
description:
- - 'State: present - create/update service; absent - delete service.'
+ - "State: present - create/update service; absent - delete service."
required: false
choices: [present, absent]
default: "present"
@@ -85,20 +50,17 @@ options:
weight:
description:
- Service weight.
- - New field with >= Zabbix 6.0.
required: false
- default: '0'
+ default: "0"
type: str
description:
description:
- Description of the service.
- - New field with >= Zabbix 6.0.
required: false
type: str
tags:
description:
- Service tags to be created for the service.
- - New field with >= Zabbix 6.0.
required: false
type: list
elements: dict
@@ -116,7 +78,6 @@ options:
problem_tags:
description:
- Problem tags to be created for the service.
- - New field with >= Zabbix 6.0.
required: false
type: list
elements: dict
@@ -131,7 +92,7 @@ options:
- Mapping condition operator.
- C(equals)
- C(like)
- choices: ['equals', 'like']
+ choices: ["equals", "like"]
required: false
default: "equals"
type: str
@@ -144,21 +105,18 @@ options:
parents:
description:
- Parent services to be linked to the service.
- - New field with >= Zabbix 6.0.
required: false
type: list
elements: str
children:
description:
- Child services to be linked to the service.
- - New field with >= Zabbix 6.0.
required: false
type: list
elements: str
propagation_rule:
description:
- Status propagation value. Must be set together with propagation_rule.
- - New field with >= Zabbix 6.0.
- C(as_is) propagate service status as is - without any changes
- C(increase) increase the propagated status by a given propagation_value (by 1 to 5 severities)
- C(decrease) decrease the propagated status by a given propagation_value (by 1 to 5 severities)
@@ -171,30 +129,28 @@ options:
propagation_value:
description:
- Status propagation value. Must be set together with propagation_rule.
- - New field with >= Zabbix 6.0.
- - 'Possible values when I(propagation_rule=as_is or ignore):'
- - ' - C(not_classified)'
- - 'Possible values when I(propagation_rule=increase or decrease):'
- - ' - C(information)'
- - ' - C(warning)'
- - ' - C(average)'
- - ' - C(high)'
- - ' - C(disaster)'
- - 'Possible values when I(propagation_rule=fixed):'
- - ' - C(ok)'
- - ' - C(not_classified)'
- - ' - C(information)'
- - ' - C(warning)'
- - ' - C(average)'
- - ' - C(high)'
- - ' - C(disaster)'
+ - "Possible values when I(propagation_rule=as_is or ignore):"
+ - " - C(not_classified)"
+ - "Possible values when I(propagation_rule=increase or decrease):"
+ - " - C(information)"
+ - " - C(warning)"
+ - " - C(average)"
+ - " - C(high)"
+ - " - C(disaster)"
+ - "Possible values when I(propagation_rule=fixed):"
+ - " - C(ok)"
+ - " - C(not_classified)"
+ - " - C(information)"
+ - " - C(warning)"
+ - " - C(average)"
+ - " - C(high)"
+ - " - C(disaster)"
- Required with C(propagation_rule)
required: false
type: str
status_rules:
description:
- Status rules for the service.
- - New field with >= Zabbix 6.0.
required: false
type: list
elements: dict
@@ -214,8 +170,8 @@ options:
type: str
limit_value:
description:
- - 'Limit value: N, N% or W'
- - 'Possible values: 1-100000 for N and W, 1-100 for N%'
+ - "Limit value: N, N% or W"
+ - "Possible values: 1-100000 for N and W, 1-100 for N%"
required: true
type: int
limit_status:
@@ -245,43 +201,23 @@ options:
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = '''
+EXAMPLES = """
---
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
-# Creates a new Zabbix service with Zabbix < 6.0
-- name: Manage services
- # set task level variables
- 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_service:
- name: apache2 service
- sla: 99.99
- calculate_sla: yes
- algorithm: one_child
- trigger_name: apache2 service status
- trigger_host: webserver01
- state: present
-
-# Creates a new Zabbix service with Zabbix >= 6.0
+# Creates a new Zabbix service
- name: Create Zabbix service monitoring Apache2 in DCs in Toronto area
# set task level variables
vars:
@@ -290,10 +226,10 @@ EXAMPLES = '''
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_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_service:
- name: 'apache2 service Toronto'
+ name: "apache2 service Toronto"
description: Apache2 services in Toronto area
sortorder: 0
propagation_rule: increase
@@ -325,7 +261,7 @@ EXAMPLES = '''
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_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_service:
name: apache2 service
@@ -336,27 +272,26 @@ EXAMPLES = '''
- tag: area
value: global
children:
- - 'apache2 service Toronto'
-'''
+ - "apache2 service Toronto"
+"""
-RETURN = '''
+RETURN = """
---
-'''
+"""
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
-from ansible.module_utils.compat.version import LooseVersion
class Service(ZabbixBase):
def get_service_ids(self, service_name):
service_ids = []
- services = self._zapi.service.get({'filter': {'name': service_name}})
+ services = self._zapi.service.get({"filter": {"name": service_name}})
for service in services:
- service_ids.append(service['serviceid'])
+ service_ids.append(service["serviceid"])
return service_ids
def delete_service(self, service_ids):
@@ -365,208 +300,160 @@ class Service(ZabbixBase):
self._zapi.service.delete(service_ids)
def dump_services(self, service_ids):
- if LooseVersion(self._zbx_api_version) < LooseVersion('6.0'):
- services = self._zapi.service.get({'output': 'extend', 'filter': {'serviceid': service_ids}, 'selectParent': '1'})
- else:
- services = self._zapi.service.get({'output': 'extend', 'filter': {'serviceid': service_ids}, 'selectParents': 'extend',
- 'selectTags': 'extend', 'selectProblemTags': 'extend', 'selectChildren': 'extend',
- 'selectStatusRules': 'extend'})
+ services = self._zapi.service.get({"output": "extend", "filter": {"serviceid": service_ids}, "selectParents": "extend",
+ "selectTags": "extend", "selectProblemTags": "extend", "selectChildren": "extend",
+ "selectStatusRules": "extend"})
return services
- def generate_service_config(self, name, parent, sla, calculate_sla, trigger_name, trigger_host, sortorder, weight,
+ def generate_service_config(self, name, sortorder, weight,
algorithm, description, tags, problem_tags, parents, children, propagation_rule, propagation_value, status_rules):
- algorithms = {'no': '0', 'one_child': '1', 'all_children': '2',
- 'status_to_ok': '0', 'most_crit_if_all_children': '1', 'most_crit_of_child_serv': '2'}
+ algorithms = {"status_to_ok": "0", "most_crit_if_all_children": "1", "most_crit_of_child_serv": "2"}
algorithm = algorithms[algorithm]
- if LooseVersion(self._zbx_api_version) < LooseVersion('6.0'):
- if calculate_sla:
- calculate_sla = 1
- else:
- calculate_sla = 0
- else:
- sla = 0 # Parameter does not exist in >= 6.0 but we needed for format() function constructing request
-
- # 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': str(calculate_sla),
- 'sortorder': sortorder,
- 'goodsla': format(sla, '.4f'), # Sla has 4 decimals
- 'triggerid': str(trigger_id)
+ "name": name,
+ "algorithm": algorithm,
+ "sortorder": sortorder,
+ "description": description,
+ "weight": weight
}
- if LooseVersion(self._zbx_api_version) >= LooseVersion('6.0'):
- request.pop('showsla')
- request.pop('triggerid')
- request.pop('goodsla')
- request['description'] = description
- request['weight'] = weight
+ if tags:
+ request["tags"] = tags
+ else:
+ request["tags"] = []
+
+ request["problem_tags"] = []
+ if problem_tags:
+ p_operators = {"equals": "0", "like": "2"}
+ for p_tag in problem_tags:
+ pt = {"tag": p_tag["tag"], "operator": "0", "value": ""}
+ if "operator" in p_tag:
+ pt["operator"] = p_operators[p_tag["operator"]]
+ if "value" in p_tag:
+ pt["value"] = p_tag["value"]
+ request["problem_tags"].append(pt)
+
+ if parents:
+ p_service_ids = []
+ p_services = self._zapi.service.get({"filter": {"name": parents}})
+ for p_service in p_services:
+ p_service_ids.append({"serviceid": p_service["serviceid"]})
+ request["parents"] = p_service_ids
+ else:
+ request["parents"] = []
+
+ if children:
+ c_service_ids = []
+ c_services = self._zapi.service.get({"filter": {"name": children}})
+ for c_service in c_services:
+ c_service_ids.append({"serviceid": c_service["serviceid"]})
+ request["children"] = c_service_ids
+ else:
+ request["children"] = []
+
+ request["status_rules"] = []
+ if status_rules:
+ for s_rule in status_rules:
+ status_rule = {}
+ if "type" in s_rule:
+ sr_type_map = {"at_least_n_child_services_have_status_or_above": "0",
+ "at_least_npct_child_services_have_status_or_above": "1",
+ "less_than_n_child_services_have_status_or_below": "2",
+ "less_than_npct_child_services_have_status_or_below": "3",
+ "weight_child_services_with_status_or_above_at_least_w": "4",
+ "weight_child_services_with_status_or_above_at_least_npct": "5",
+ "weight_child_services_with_status_or_below_less_w": "6",
+ "weight_child_services_with_status_or_below_less_npct": "7"}
+ if s_rule["type"] not in sr_type_map:
+ self._module.fail_json(msg="Wrong value for 'type' parameter in status rule.")
+ status_rule["type"] = sr_type_map[s_rule["type"]]
+ else:
+ self._module.fail_json(msg="'type' is mandatory paremeter for status rule.")
- if tags:
- request['tags'] = tags
- else:
- request['tags'] = []
-
- request['problem_tags'] = []
- if problem_tags:
- p_operators = {'equals': '0', 'like': '2'}
- for p_tag in problem_tags:
- pt = {'tag': p_tag['tag'], 'operator': '0', 'value': ''}
- if 'operator' in p_tag:
- pt['operator'] = p_operators[p_tag['operator']]
- if 'value' in p_tag:
- pt['value'] = p_tag['value']
- request['problem_tags'].append(pt)
-
- if parents:
- p_service_ids = []
- p_services = self._zapi.service.get({'filter': {'name': parents}})
- for p_service in p_services:
- p_service_ids.append({'serviceid': p_service['serviceid']})
- request['parents'] = p_service_ids
- else:
- request['parents'] = []
-
- if children:
- c_service_ids = []
- c_services = self._zapi.service.get({'filter': {'name': children}})
- for c_service in c_services:
- c_service_ids.append({'serviceid': c_service['serviceid']})
- request['children'] = c_service_ids
- else:
- request['children'] = []
-
- request['status_rules'] = []
- if status_rules:
- for s_rule in status_rules:
- status_rule = {}
- if 'type' in s_rule:
- sr_type_map = {'at_least_n_child_services_have_status_or_above': '0',
- 'at_least_npct_child_services_have_status_or_above': '1',
- 'less_than_n_child_services_have_status_or_below': '2',
- 'less_than_npct_child_services_have_status_or_below': '3',
- 'weight_child_services_with_status_or_above_at_least_w': '4',
- 'weight_child_services_with_status_or_above_at_least_npct': '5',
- 'weight_child_services_with_status_or_below_less_w': '6',
- 'weight_child_services_with_status_or_below_less_npct': '7'}
- if s_rule['type'] not in sr_type_map:
- self._module.fail_json(msg="Wrong value for 'type' parameter in status rule.")
- status_rule['type'] = sr_type_map[s_rule['type']]
- else:
- self._module.fail_json(msg="'type' is mandatory paremeter for status rule.")
-
- if 'limit_value' in s_rule:
- lv = s_rule['limit_value']
- if status_rule['type'] in ['0', '2', '4', '6']:
- if int(lv) < 1 or int(lv) > 100000:
- self._module.fail_json(msg="'limit_value' for N and W must be between 1 and 100000 but provided %s" % lv)
- else:
- if int(lv) < 1 or int(lv) > 100:
- self._module.fail_json(msg="'limit_value' for N%% must be between 1 and 100 but provided %s" % lv)
- status_rule['limit_value'] = str(lv)
- else:
- self._module.fail_json(msg="'limit_value' is mandatory paremeter for status rule.")
-
- if 'limit_status' in s_rule:
- sr_ls_map = {'ok': '-1', 'not_classified': '0', 'information': '1', 'warning': '2',
- 'average': '3', 'high': '4', 'disaster': 5}
- if s_rule['limit_status'] not in sr_ls_map:
- self._module.fail_json(msg="Wrong value for 'limit_status' parameter in status rule.")
- status_rule['limit_status'] = sr_ls_map[s_rule['limit_status']]
+ if "limit_value" in s_rule:
+ lv = s_rule["limit_value"]
+ if status_rule["type"] in ["0", "2", "4", "6"]:
+ if int(lv) < 1 or int(lv) > 100000:
+ self._module.fail_json(msg="'limit_value' for N and W must be between 1 and 100000 but provided %s" % lv)
else:
- self._module.fail_json(msg="'limit_status' is mandatory paremeter for status rule.")
-
- if 'new_status' in s_rule:
- sr_ns_map = {'not_classified': '0', 'information': '1', 'warning': '2',
- 'average': '3', 'high': '4', 'disaster': '5'}
- if s_rule['new_status'] not in sr_ns_map:
- self._module.fail_json(msg="Wrong value for 'new_status' parameter in status rule.")
- status_rule['new_status'] = sr_ns_map[s_rule['new_status']]
- else:
- self._module.fail_json(msg="'new_status' is mandatory paremeter for status rule.")
-
- request['status_rules'].append(status_rule)
-
- request['propagation_rule'] = '0'
- if propagation_rule:
- if propagation_value is None:
- self._module.fail_json(msg="If 'propagation_rule' is provided then 'propagation_value' must be provided too.")
- pr_map = {'as_is': '0', 'increase': '1', 'decrease': '2', 'ignore': '3', 'fixed': '4'}
- if propagation_rule not in pr_map:
- self._module.fail_json(msg="Wrong value for 'propagation_rule' parameter.")
+ if int(lv) < 1 or int(lv) > 100:
+ self._module.fail_json(msg="'limit_value' for N%% must be between 1 and 100 but provided %s" % lv)
+ status_rule["limit_value"] = str(lv)
else:
- request['propagation_rule'] = pr_map[propagation_rule]
-
- request['propagation_value'] = '0'
- if propagation_value:
- if propagation_rule is None:
- self._module.fail_json(msg="If 'propagation_value' is provided then 'propagation_rule' must be provided too.")
- pv_map = {'ok': '-1', 'not_classified': '0', 'information': '1', 'warning': '2',
- 'average': '3', 'high': '4', 'disaster': '5'}
- if propagation_value not in pv_map:
- self._module.fail_json(msg="Wrong value for 'propagation_value' parameter.")
+ self._module.fail_json(msg="'limit_value' is mandatory paremeter for status rule.")
+
+ if "limit_status" in s_rule:
+ sr_ls_map = {"ok": "-1", "not_classified": "0", "information": "1", "warning": "2",
+ "average": "3", "high": "4", "disaster": 5}
+ if s_rule["limit_status"] not in sr_ls_map:
+ self._module.fail_json(msg="Wrong value for 'limit_status' parameter in status rule.")
+ status_rule["limit_status"] = sr_ls_map[s_rule["limit_status"]]
else:
- request['propagation_value'] = pv_map[propagation_value]
- else:
- 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]
+ self._module.fail_json(msg="'limit_status' is mandatory paremeter for status rule.")
+
+ if "new_status" in s_rule:
+ sr_ns_map = {"not_classified": "0", "information": "1", "warning": "2",
+ "average": "3", "high": "4", "disaster": "5"}
+ if s_rule["new_status"] not in sr_ns_map:
+ self._module.fail_json(msg="Wrong value for 'new_status' parameter in status rule.")
+ status_rule["new_status"] = sr_ns_map[s_rule["new_status"]]
+ else:
+ self._module.fail_json(msg="'new_status' is mandatory paremeter for status rule.")
+
+ request["status_rules"].append(status_rule)
+
+ request["propagation_rule"] = "0"
+ if propagation_rule:
+ if propagation_value is None:
+ self._module.fail_json(msg="If 'propagation_rule' is provided then 'propagation_value' must be provided too.")
+ pr_map = {"as_is": "0", "increase": "1", "decrease": "2", "ignore": "3", "fixed": "4"}
+ if propagation_rule not in pr_map:
+ self._module.fail_json(msg="Wrong value for 'propagation_rule' parameter.")
+ else:
+ request["propagation_rule"] = pr_map[propagation_rule]
+
+ request["propagation_value"] = "0"
+ if propagation_value:
+ if propagation_rule is None:
+ self._module.fail_json(msg="If 'propagation_value' is provided then 'propagation_rule' must be provided too.")
+ pv_map = {"ok": "-1", "not_classified": "0", "information": "1", "warning": "2",
+ "average": "3", "high": "4", "disaster": "5"}
+ if propagation_value not in pv_map:
+ self._module.fail_json(msg="Wrong value for 'propagation_value' parameter.")
+ else:
+ request["propagation_value"] = pv_map[propagation_value]
+
return request
- def create_service(self, name, parent, sla, calculate_sla, trigger_name, trigger_host, sortorder, weight, algorithm,
+ def create_service(self, name, sortorder, weight, algorithm,
description, tags, problem_tags, parents, children, propagation_rule, propagation_value, status_rules):
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, sortorder, weight,
+ self._zapi.service.create(self.generate_service_config(name, sortorder, weight,
algorithm, description, tags, problem_tags, parents, children, propagation_rule, propagation_value, status_rules))
- def update_service(self, service_id, name, parent, sla, calculate_sla, trigger_name, trigger_host, sortorder, weight, algorithm,
+ def update_service(self, service_id, name, sortorder, weight, algorithm,
description, tags, problem_tags, parents, children, propagation_rule, propagation_value, status_rules):
- generated_config = self.generate_service_config(name, parent, sla, calculate_sla, trigger_name, trigger_host, sortorder, weight, algorithm,
+ generated_config = self.generate_service_config(name, sortorder, weight, algorithm,
description, tags, problem_tags, parents, children, propagation_rule, propagation_value, status_rules)
live_config = self.dump_services(service_id)[0]
- if LooseVersion(self._zbx_api_version) >= LooseVersion('6.0'):
- if len(live_config['parents']) > 0:
- # Need to rewrite parents list to only service ids
- new_parents = []
- for parent in live_config['parents']:
- new_parents.append({'serviceid': parent['serviceid']})
- live_config['parents'] = new_parents
-
- if len(live_config['children']) > 0:
- # Need to rewrite children list to only service ids
- new_children = []
- for child in live_config['children']:
- new_children.append({'serviceid': child['serviceid']})
- live_config['children'] = new_children
-
- else:
- if 'goodsla' in live_config:
- live_config['goodsla'] = format(float(live_config['goodsla']), '.4f')
+ if len(live_config["parents"]) > 0:
+ # Need to rewrite parents list to only service ids
+ new_parents = []
+ for parent in live_config["parents"]:
+ new_parents.append({"serviceid": parent["serviceid"]})
+ live_config["parents"] = new_parents
- if 'parentid' in generated_config:
- if 'serviceid' in live_config['parent']:
- live_config['parentid'] = live_config['parent']['serviceid']
+ if len(live_config["children"]) > 0:
+ # Need to rewrite children list to only service ids
+ new_children = []
+ for child in live_config["children"]:
+ new_children.append({"serviceid": child["serviceid"]})
+ live_config["children"] = new_children
change_parameters = {}
difference = zabbix_utils.helper_cleanup_data(zabbix_utils.helper_compare_dictionaries(generated_config, live_config, change_parameters))
@@ -576,7 +463,7 @@ class Service(ZabbixBase):
if self._module.check_mode:
self._module.exit_json(changed=True)
- generated_config['serviceid'] = service_id
+ generated_config["serviceid"] = service_id
self._zapi.service.update(generated_config)
self._module.exit_json(changed=True, msg="Service %s updated" % name)
@@ -584,81 +471,75 @@ class Service(ZabbixBase):
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- 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',
- 'status_to_ok', 'most_crit_if_all_children', 'most_crit_of_child_serv']),
- trigger_name=dict(type='str', required=False),
- trigger_host=dict(type='str', required=False),
- sortorder=dict(type='str', required=True),
- weight=dict(default='0', type='str', required=False),
- state=dict(default="present", choices=['present', 'absent']),
- description=dict(type='str', required=False),
+ name=dict(type="str", required=True),
+ algorithm=dict(default="status_to_ok", required=False, choices=["status_to_ok", "most_crit_if_all_children", "most_crit_of_child_serv"]),
+ sortorder=dict(type="str", required=True),
+ weight=dict(default="0", type="str", required=False),
+ state=dict(default="present", choices=["present", "absent"]),
+ description=dict(type="str", required=False),
tags=dict(
- type='list',
+ type="list",
required=False,
- elements='dict',
+ elements="dict",
options=dict(
tag=dict(
- type='str',
+ type="str",
required=True
),
value=dict(
- type='str',
+ type="str",
required=False
)
)
),
problem_tags=dict(
- type='list',
+ type="list",
required=False,
- elements='dict',
+ elements="dict",
options=dict(
tag=dict(
- type='str',
+ type="str",
required=True
),
operator=dict(
- type='str',
+ type="str",
required=False,
choices=[
- 'equals',
- 'like'
+ "equals",
+ "like"
],
- default='equals'
+ default="equals"
),
value=dict(
- type='str',
+ type="str",
required=False,
- default=''
+ default=""
)
)
),
- parents=dict(type='list', required=False, elements='str'),
- children=dict(type='list', required=False, elements='str'),
- propagation_rule=dict(default='as_is', type='str', required=False),
- propagation_value=dict(type='str', required=False),
+ parents=dict(type="list", required=False, elements="str"),
+ children=dict(type="list", required=False, elements="str"),
+ propagation_rule=dict(default="as_is", type="str", required=False),
+ propagation_value=dict(type="str", required=False),
status_rules=dict(
- type='list',
+ type="list",
required=False,
- elements='dict',
+ elements="dict",
options=dict(
type=dict(
- type='str',
+ type="str",
required=True
),
limit_value=dict(
- type='int',
+ type="int",
required=True
),
limit_status=dict(
- type='str',
+ type="str",
required=True
),
new_status=dict(
- type='str',
+ type="str",
required=True
)
)
@@ -669,30 +550,19 @@ def main():
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- 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']
- sortorder = module.params['sortorder']
- weight = module.params['weight']
- state = module.params['state']
- description = module.params['description']
- tags = module.params['tags']
- problem_tags = module.params['problem_tags']
- parents = module.params['parents']
- children = module.params['children']
- propagation_rule = module.params['propagation_rule']
- propagation_value = module.params['propagation_value']
- status_rules = module.params['status_rules']
+ name = module.params["name"]
+ algorithm = module.params["algorithm"]
+ sortorder = module.params["sortorder"]
+ weight = module.params["weight"]
+ state = module.params["state"]
+ description = module.params["description"]
+ tags = module.params["tags"]
+ problem_tags = module.params["problem_tags"]
+ parents = module.params["parents"]
+ children = module.params["children"]
+ propagation_rule = module.params["propagation_rule"]
+ propagation_value = module.params["propagation_value"]
+ status_rules = module.params["status_rules"]
# Load service module
service = Service(module)
@@ -706,18 +576,16 @@ def main():
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, sortorder, weight, algorithm, description,
+ service.create_service(name, sortorder, weight, algorithm, description,
tags, problem_tags, parents, children, propagation_rule, propagation_value, status_rules)
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, sortorder, weight,
+ service.update_service(service_ids[0], name, sortorder, weight,
algorithm, description, tags, problem_tags, parents, children, propagation_rule, propagation_value, status_rules)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_settings.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_settings.py
new file mode 100644
index 000000000..de8ec6886
--- /dev/null
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_settings.py
@@ -0,0 +1,1112 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright: (c) 2023, ONODERA Masaru <masaru-onodera@ieee.org>
+# 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 = """
+---
+module: zabbix_settings
+
+short_description: Update Zabbix global settings.
+
+description:
+ - This module allows you to update Zabbix global settings.
+
+author:
+ - ONODERA Masaru(@masa-orca)
+
+requirements:
+ - "python >= 3.9"
+
+version_added: 2.1.0
+
+options:
+ default_lang:
+ description:
+ - Default language for users.
+ required: false
+ type: str
+ default_timezone:
+ description:
+ - Default time zone for users.
+ - Please set C(system) if you want to use system time zone.
+ required: false
+ type: str
+ default_theme:
+ description:
+ - Default theme for users.
+ required: false
+ type: str
+ choices:
+ - blue-theme
+ - dark-theme
+ - hc-light
+ - hc-dark
+ search_limit:
+ description:
+ - A number of search and filter results limit.
+ required: false
+ type: int
+ max_overview_table_size:
+ description:
+ - Max number of columns and rows in overview tables
+ required: false
+ type: int
+ max_in_table:
+ description:
+ - Max count of elements to show inside table cell
+ required: false
+ type: int
+ server_check_interval:
+ description:
+ - The Zabbix shows "Zabbix server is down" warning if C(true).
+ required: false
+ type: bool
+ work_period:
+ description:
+ - Working time setting.
+ - U(https://www.zabbix.com/documentation/current/en/manual/appendix/time_period)
+ required: false
+ type: str
+ show_technical_errors:
+ description:
+ - The Zabbix shows PHP and SQL technical errors to users who are non-Super admin or belong to user groups with debug mode not enabled if C(true).
+ required: false
+ type: bool
+ history_period:
+ description:
+ - Max period of displaying history data.
+ - Accepts seconds and time unit with suffix (e.g. 24h).
+ required: false
+ type: str
+ period_default:
+ description:
+ - Default period value for time filter.
+ - Accepts seconds and time unit with suffix (e.g. 1h).
+ required: false
+ type: str
+ max_period:
+ description:
+ - Max period for time filter.
+ - Accepts seconds and time unit with suffix (e.g. 1y).
+ required: false
+ type: str
+ severity_color_0:
+ description:
+ - A custom color for not classified severity.
+ - Please set hexadecimal color code (e.g. 00FF00).
+ required: false
+ type: str
+ severity_color_1:
+ description:
+ - A custom color for information severity.
+ - Please set hexadecimal color code (e.g. 00FF00).
+ required: false
+ type: str
+ severity_color_2:
+ description:
+ - A custom color for warning severity.
+ - Please set hexadecimal color code (e.g. 00FF00).
+ required: false
+ type: str
+ severity_color_3:
+ description:
+ - A custom color for average severity.
+ - Please set hexadecimal color code (e.g. 00FF00).
+ required: false
+ type: str
+ severity_color_4:
+ description:
+ - A custom color for high severity.
+ - Please set hexadecimal color code (e.g. 00FF00).
+ required: false
+ type: str
+ severity_color_5:
+ description:
+ - A custom color for disaster severity.
+ - Please set hexadecimal color code (e.g. 00FF00).
+ required: false
+ type: str
+ severity_name_0:
+ description:
+ - A custom name for not classified severity.
+ required: false
+ type: str
+ severity_name_1:
+ description:
+ - A custom name for information severity.
+ required: false
+ type: str
+ severity_name_2:
+ description:
+ - A custom name for warning severity.
+ required: false
+ type: str
+ severity_name_3:
+ description:
+ - A custom name for average severity.
+ required: false
+ type: str
+ severity_name_4:
+ description:
+ - A custom name for high severity.
+ required: false
+ type: str
+ severity_name_5:
+ description:
+ - A custom name for disaster severity.
+ required: false
+ type: str
+ custom_color:
+ description:
+ - Custom event color settings will be activated if C(true).
+ required: false
+ type: bool
+ ok_period:
+ description:
+ - A time of period for displaying OK triggers.
+ - Accepts seconds and time unit with suffix (e.g. 5m).
+ required: false
+ type: str
+ blink_period:
+ description:
+ - A time of period for blinking status changed triggers.
+ - Accepts seconds and time unit with suffix (e.g. 5m).
+ required: false
+ type: str
+ problem_unack_color:
+ description:
+ - A custom color for unacknowledged PROBLEM events.
+ - This setting will be activated if I(custom_color=true).
+ - Please set hexadecimal color code (e.g. 00FF00).
+ required: false
+ type: str
+ problem_ack_color:
+ description:
+ - A custom color for acknowledged PROBLEM events.
+ - This setting will be activated if I(custom_color=true).
+ - Please set hexadecimal color code (e.g. 00FF00).
+ required: false
+ type: str
+ ok_unack_color:
+ description:
+ - A custom color for unacknowledged RESOLVED events.
+ - This setting will be activated if I(custom_color=true).
+ - Please set hexadecimal color code (e.g. 00FF00).
+ required: false
+ type: str
+ ok_ack_color:
+ description:
+ - A custom color for acknowledged RESOLVED events.
+ - This setting will be activated if I(custom_color=true).
+ - Please set hexadecimal color code (e.g. 00FF00).
+ required: false
+ type: str
+ problem_unack_style:
+ description:
+ - Unacknowledged PROBLEM events blink if C(true).
+ required: false
+ type: bool
+ problem_ack_style:
+ description:
+ - Acknowledged PROBLEM events blink if C(true).
+ required: false
+ type: bool
+ ok_unack_style:
+ description:
+ - Unacknowledged RESOLVED events blink if C(true).
+ required: false
+ type: bool
+ ok_ack_style:
+ description:
+ - Acknowledged RESOLVED events blink if C(true).
+ required: false
+ type: bool
+ frontend_url:
+ description:
+ - A URL of frontend.
+ - This parameter is used for url parameter of settings API.
+ required: false
+ type: str
+ discovery_group:
+ description:
+ - A hostgroup which discovered hosts will belong to.
+ required: false
+ type: str
+ default_inventory_mode:
+ description:
+ - A default value for host inventory mode.
+ required: false
+ type: str
+ choices:
+ - disabled
+ - manual
+ - automatic
+ alert_usrgrp:
+ description:
+ - A name of user group which user belongs to receive an alerm message when database down.
+ required: false
+ type: str
+ snmptrap_logging:
+ description:
+ - Logging unmatched SNMP traps will be ebabled if C(true).
+ required: false
+ type: bool
+ login_attempts:
+ description:
+ - A number of login attempts you can try with non blocked.
+ required: false
+ type: int
+ login_block:
+ description:
+ - A time of interval to reset login attempts when the user is blocked.
+ - Accepts seconds and time unit with suffix (e.g. 5m).
+ required: false
+ type: str
+ validate_uri_schemes:
+ description:
+ - Validate URI schemes if C(true).
+ required: false
+ type: bool
+ uri_valid_schemes:
+ description:
+ - A list of valid URI scheme.
+ required: false
+ type: list
+ elements: str
+ x_frame_options:
+ description:
+ - A text of X-Frame-Options of HTTP header.
+ required: false
+ type: str
+ iframe_sandboxing_enabled:
+ description:
+ - The Zabbix uses iframe sandboxing if C(true).
+ required: false
+ type: bool
+ iframe_sandboxing_exceptions:
+ description:
+ - A text of iframe sandboxing exceptions.
+ required: false
+ type: str
+ connect_timeout:
+ description:
+ - A time of connection timeout with Zabbix server.
+ required: false
+ type: str
+ socket_timeout:
+ description:
+ - A time of network default timeout.
+ required: false
+ type: str
+ media_type_test_timeout:
+ description:
+ - A time of network timeout for media type test.
+ required: false
+ type: str
+ item_test_timeout:
+ description:
+ - A time of network timeout for item tests.
+ required: false
+ type: str
+ script_timeout:
+ description:
+ - A time of network timeout for script execution.
+ required: false
+ type: str
+ report_test_timeout:
+ description:
+ - A time of network timeout for scheduled report test.
+ required: false
+ type: str
+ auditlog_enabled:
+ description:
+ - Enable audit logging if C(true).
+ required: false
+ type: bool
+ geomaps_tile_provider:
+ description:
+ - A provider of Geomap tile.
+ - Please set C(another) if you want use non default provider
+ required: false
+ type: str
+ choices:
+ - OpenStreetMap.Mapnik
+ - OpenTopoMap
+ - Stamen.TonerLite
+ - Stamen.Terrain
+ - USGS.USTopo
+ - USGS.USImagery
+ - another
+ geomaps_tile_url:
+ description:
+ - A URL of geomap tile.
+ required: false
+ type: str
+ geomaps_max_zoom:
+ description:
+ - Max zoom level of geomap.
+ required: false
+ type: str
+ geomaps_attribution:
+ description:
+ - A text of Geomap attribution.
+ required: false
+ type: str
+ vault_provider:
+ description:
+ - A name of vault provider.
+ - This parameter is available since Zabbix 6.2.
+ required: false
+ type: str
+ choices:
+ - HashiCorp_Vault
+ - CyberArk_Vault
+
+notes:
+ - This module manages settings related with settings api except ha_failover_delay.
+
+extends_documentation_fragment:
+ - community.zabbix.zabbix
+"""
+
+EXAMPLES = """
+# 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: Update settings
+ # 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_settings:
+ alert_usrgrp: "0"
+ auditlog_enabled: false
+ blink_period: "10m"
+ connect_timeout: "30s"
+ custom_color: false
+ default_inventory_mode: automatic
+"""
+
+RETURN = """
+msg:
+ description: The result of the operation
+ returned: success
+ type: str
+ sample: "Successfully update global settings"
+"""
+
+import re
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.community.zabbix.plugins.module_utils.base import ZabbixBase
+from ansible.module_utils.compat.version import LooseVersion
+import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabbix_utils
+
+
+class Settings(ZabbixBase):
+ # get setting setting
+ def get_settings(self):
+ try:
+ return self._zapi.settings.get({"output": "extend"})
+ except Exception as e:
+ self._module.fail_json(msg="Failed to get settings: %s" % e)
+
+ def _is_time(self, time):
+ pattern = re.compile(r"^(\d+)([smhdwMy]?)$")
+ search_result = pattern.search(time)
+ if search_result is None:
+ self._module.fail_json(msg="{0} is invalid value.".format(time))
+ return True
+
+ def _is_color(self, color):
+ pattern = re.compile(r"^[0-9a-fA-F]{6}$")
+ search_result = pattern.search(color)
+ if search_result is None:
+ self._module.fail_json(msg="{0} is invalid value.".format(color))
+ return True
+
+ def get_usrgrpid_from_name(self, usrgrp):
+ usrgrpids = self._zapi.usergroup.get({"filter": {"name": usrgrp}})
+ if not usrgrpids or len(usrgrpids) > 1:
+ self._module.fail_json("User group '%s' cannot be found" % usrgrp)
+ return usrgrpids[0]["usrgrpid"]
+
+ def get_groupid_from_name(self, hostgroup):
+ groupid = self._zapi.hostgroup.get({"filter": {"name": hostgroup}})
+ if not groupid or len(groupid) > 1:
+ self._module.fail_json("Host group '%s' cannot be found" % hostgroup)
+ return groupid[0]["groupid"]
+
+ def update_settings(
+ self,
+ current_settings,
+ default_lang,
+ default_timezone,
+ default_theme,
+ search_limit,
+ max_overview_table_size,
+ max_in_table,
+ server_check_interval,
+ work_period,
+ show_technical_errors,
+ history_period,
+ period_default,
+ max_period,
+ severity_color_0,
+ severity_color_1,
+ severity_color_2,
+ severity_color_3,
+ severity_color_4,
+ severity_color_5,
+ severity_name_0,
+ severity_name_1,
+ severity_name_2,
+ severity_name_3,
+ severity_name_4,
+ severity_name_5,
+ custom_color,
+ ok_period,
+ blink_period,
+ problem_unack_color,
+ problem_ack_color,
+ ok_unack_color,
+ ok_ack_color,
+ problem_unack_style,
+ problem_ack_style,
+ ok_unack_style,
+ ok_ack_style,
+ frontend_url,
+ discovery_group,
+ default_inventory_mode,
+ alert_usrgrp,
+ snmptrap_logging,
+ login_attempts,
+ login_block,
+ validate_uri_schemes,
+ uri_valid_schemes,
+ x_frame_options,
+ iframe_sandboxing_enabled,
+ iframe_sandboxing_exceptions,
+ connect_timeout,
+ socket_timeout,
+ media_type_test_timeout,
+ item_test_timeout,
+ script_timeout,
+ report_test_timeout,
+ auditlog_enabled,
+ geomaps_tile_provider,
+ geomaps_tile_url,
+ geomaps_max_zoom,
+ geomaps_attribution,
+ vault_provider,
+ ):
+ try:
+ params = {}
+
+ if isinstance(default_lang, str):
+ if default_lang != current_settings["default_lang"]:
+ params["default_lang"] = default_lang
+
+ if isinstance(default_timezone, str):
+ if default_timezone != current_settings["default_timezone"]:
+ params["default_timezone"] = default_timezone
+
+ if isinstance(default_theme, str):
+ if default_theme != current_settings["default_theme"]:
+ params["default_theme"] = default_theme
+
+ if isinstance(search_limit, int):
+ if str(search_limit) != current_settings["search_limit"]:
+ params["search_limit"] = str(search_limit)
+
+ if isinstance(max_overview_table_size, int):
+ if (
+ str(max_overview_table_size)
+ != current_settings["max_overview_table_size"]
+ ):
+ params["max_overview_table_size"] = str(max_overview_table_size)
+
+ if isinstance(max_in_table, int):
+ if str(max_in_table) != current_settings["max_in_table"]:
+ params["max_in_table"] = str(max_in_table)
+
+ if isinstance(server_check_interval, bool):
+ if server_check_interval:
+ if current_settings["server_check_interval"] != "10":
+ params["server_check_interval"] = "10"
+ else:
+ if current_settings["server_check_interval"] != "0":
+ params["server_check_interval"] = "0"
+
+ if isinstance(work_period, str):
+ if work_period != current_settings["work_period"]:
+ params["work_period"] = work_period
+
+ if isinstance(show_technical_errors, bool):
+ if show_technical_errors:
+ if current_settings["show_technical_errors"] != "1":
+ params["show_technical_errors"] = "1"
+ else:
+ if current_settings["show_technical_errors"] != "0":
+ params["show_technical_errors"] = "0"
+
+ if isinstance(history_period, str):
+ if self._is_time(history_period):
+ if history_period != current_settings["history_period"]:
+ params["history_period"] = history_period
+
+ if isinstance(period_default, str):
+ if self._is_time(period_default):
+ if period_default != current_settings["period_default"]:
+ params["period_default"] = period_default
+
+ if isinstance(max_period, str):
+ if self._is_time(max_period):
+ if max_period != current_settings["max_period"]:
+ params["max_period"] = max_period
+
+ if isinstance(severity_color_0, str):
+ if self._is_color(severity_color_0):
+ if severity_color_0 != current_settings["severity_color_0"]:
+ params["severity_color_0"] = severity_color_0
+
+ if isinstance(severity_color_1, str):
+ if self._is_color(severity_color_1):
+ if severity_color_1 != current_settings["severity_color_1"]:
+ params["severity_color_1"] = severity_color_1
+
+ if isinstance(severity_color_2, str):
+ if self._is_color(severity_color_2):
+ if severity_color_2 != current_settings["severity_color_2"]:
+ params["severity_color_2"] = severity_color_2
+
+ if isinstance(severity_color_3, str):
+ if self._is_color(severity_color_3):
+ if severity_color_3 != current_settings["severity_color_3"]:
+ params["severity_color_3"] = severity_color_3
+
+ if isinstance(severity_color_4, str):
+ if self._is_color(severity_color_4):
+ if severity_color_4 != current_settings["severity_color_4"]:
+ params["severity_color_4"] = severity_color_4
+
+ if isinstance(severity_color_5, str):
+ if self._is_color(severity_color_5):
+ if severity_color_5 != current_settings["severity_color_5"]:
+ params["severity_color_5"] = severity_color_5
+
+ if isinstance(severity_name_0, str):
+ if severity_name_0 != current_settings["severity_name_0"]:
+ params["severity_name_0"] = severity_name_0
+
+ if isinstance(severity_name_1, str):
+ if severity_name_1 != current_settings["severity_name_1"]:
+ params["severity_name_1"] = severity_name_1
+
+ if isinstance(severity_name_2, str):
+ if severity_name_2 != current_settings["severity_name_2"]:
+ params["severity_name_2"] = severity_name_2
+
+ if isinstance(severity_name_3, str):
+ if severity_name_3 != current_settings["severity_name_3"]:
+ params["severity_name_3"] = severity_name_3
+
+ if isinstance(severity_name_4, str):
+ if severity_name_4 != current_settings["severity_name_4"]:
+ params["severity_name_4"] = severity_name_4
+
+ if isinstance(severity_name_5, str):
+ if severity_name_5 != current_settings["severity_name_5"]:
+ params["severity_name_5"] = severity_name_5
+
+ if isinstance(custom_color, bool):
+ if custom_color:
+ if current_settings["custom_color"] != "1":
+ params["custom_color"] = "1"
+ else:
+ if current_settings["custom_color"] != "0":
+ params["custom_color"] = "0"
+
+ if isinstance(ok_period, str):
+ if self._is_time(ok_period):
+ if ok_period != current_settings["ok_period"]:
+ params["ok_period"] = ok_period
+
+ if isinstance(blink_period, str):
+ if self._is_time(blink_period):
+ if blink_period != current_settings["blink_period"]:
+ params["blink_period"] = blink_period
+
+ if isinstance(problem_unack_color, str):
+ if self._is_color(problem_unack_color):
+ if problem_unack_color != current_settings["problem_unack_color"]:
+ params["problem_unack_color"] = problem_unack_color
+
+ if isinstance(problem_ack_color, str):
+ if self._is_color(problem_ack_color):
+ if problem_ack_color != current_settings["problem_ack_color"]:
+ params["problem_ack_color"] = problem_ack_color
+
+ if isinstance(ok_unack_color, str):
+ if self._is_color(ok_unack_color):
+ if ok_unack_color != current_settings["ok_unack_color"]:
+ params["ok_unack_color"] = ok_unack_color
+
+ if isinstance(ok_ack_color, str):
+ if self._is_color(ok_ack_color):
+ if ok_ack_color != current_settings["ok_ack_color"]:
+ params["ok_ack_color"] = ok_ack_color
+
+ if isinstance(problem_unack_style, bool):
+ if problem_unack_style:
+ if current_settings["problem_unack_style"] != "1":
+ params["problem_unack_style"] = "1"
+ else:
+ if current_settings["problem_unack_style"] != "0":
+ params["problem_unack_style"] = "0"
+
+ if isinstance(problem_ack_style, bool):
+ if problem_ack_style:
+ if current_settings["problem_ack_style"] != "1":
+ params["problem_ack_style"] = "1"
+ else:
+ if current_settings["problem_ack_style"] != "0":
+ params["problem_ack_style"] = "0"
+
+ if isinstance(ok_unack_style, bool):
+ if ok_unack_style:
+ if current_settings["ok_unack_style"] != "1":
+ params["ok_unack_style"] = "1"
+ else:
+ if current_settings["ok_unack_style"] != "0":
+ params["ok_unack_style"] = "0"
+
+ if isinstance(ok_ack_style, bool):
+ if ok_ack_style:
+ if current_settings["ok_ack_style"] != "1":
+ params["ok_ack_style"] = "1"
+ else:
+ if current_settings["ok_ack_style"] != "0":
+ params["ok_ack_style"] = "0"
+
+ if isinstance(frontend_url, str):
+ if frontend_url != current_settings["url"]:
+ params["url"] = frontend_url
+
+ if isinstance(discovery_group, str):
+ discovery_groupid = self.get_groupid_from_name(discovery_group)
+ if current_settings["discovery_groupid"] != discovery_groupid:
+ params["discovery_groupid"] = discovery_groupid
+
+ if isinstance(default_inventory_mode, str):
+ _default_inventory_mode = str(
+ zabbix_utils.helper_to_numeric_value(
+ ["disabled", "manual", "automatic"], default_inventory_mode
+ )
+ - 1
+ )
+ if (
+ _default_inventory_mode
+ != current_settings["default_inventory_mode"]
+ ):
+ params["default_inventory_mode"] = _default_inventory_mode
+
+ if isinstance(alert_usrgrp, str):
+ if alert_usrgrp != "0":
+ alert_usrgrpid = self.get_usrgrpid_from_name(alert_usrgrp)
+ else:
+ alert_usrgrpid = alert_usrgrp
+ if current_settings["alert_usrgrpid"] != alert_usrgrpid:
+ params["alert_usrgrpid"] = alert_usrgrpid
+
+ if isinstance(snmptrap_logging, bool):
+ if snmptrap_logging:
+ if current_settings["snmptrap_logging"] != "1":
+ params["snmptrap_logging"] = "1"
+ else:
+ if current_settings["snmptrap_logging"] != "0":
+ params["snmptrap_logging"] = "0"
+
+ if isinstance(login_attempts, int):
+ if str(login_attempts) != current_settings["login_attempts"]:
+ params["login_attempts"] = str(login_attempts)
+
+ if isinstance(login_block, str):
+ if self._is_time(login_block):
+ if login_block != current_settings["login_block"]:
+ params["login_block"] = login_block
+
+ if isinstance(validate_uri_schemes, bool):
+ if validate_uri_schemes:
+ if current_settings["validate_uri_schemes"] != "1":
+ params["validate_uri_schemes"] = "1"
+ else:
+ if current_settings["validate_uri_schemes"] != "0":
+ params["validate_uri_schemes"] = "0"
+
+ if isinstance(uri_valid_schemes, list):
+ current_uri_valid_schemes = current_settings["uri_valid_schemes"].split(
+ ","
+ )
+ uri_valid_schemes.sort()
+ current_uri_valid_schemes.sort()
+ compare_result = []
+ zabbix_utils.helper_compare_lists(
+ uri_valid_schemes, current_uri_valid_schemes, compare_result
+ )
+ if len(compare_result) != 0:
+ params["uri_valid_schemes"] = ",".join(uri_valid_schemes)
+
+ if isinstance(x_frame_options, str):
+ if x_frame_options != current_settings["x_frame_options"]:
+ params["x_frame_options"] = x_frame_options
+
+ if isinstance(iframe_sandboxing_enabled, bool):
+ if iframe_sandboxing_enabled:
+ if current_settings["iframe_sandboxing_enabled"] != "1":
+ params["iframe_sandboxing_enabled"] = "1"
+ else:
+ if current_settings["iframe_sandboxing_enabled"] != "0":
+ params["iframe_sandboxing_enabled"] = "0"
+
+ if isinstance(iframe_sandboxing_exceptions, str):
+ if (
+ iframe_sandboxing_exceptions
+ != current_settings["iframe_sandboxing_exceptions"]
+ ):
+ params[
+ "iframe_sandboxing_exceptions"
+ ] = iframe_sandboxing_exceptions
+
+ if isinstance(connect_timeout, str):
+ if self._is_time(connect_timeout):
+ if connect_timeout != current_settings["connect_timeout"]:
+ params["connect_timeout"] = connect_timeout
+
+ if isinstance(socket_timeout, str):
+ if self._is_time(socket_timeout):
+ if socket_timeout != current_settings["socket_timeout"]:
+ params["socket_timeout"] = socket_timeout
+
+ if isinstance(media_type_test_timeout, str):
+ if self._is_time(media_type_test_timeout):
+ if (
+ media_type_test_timeout
+ != current_settings["media_type_test_timeout"]
+ ):
+ params["media_type_test_timeout"] = media_type_test_timeout
+
+ if isinstance(item_test_timeout, str):
+ if self._is_time(item_test_timeout):
+ if item_test_timeout != current_settings["item_test_timeout"]:
+ params["item_test_timeout"] = item_test_timeout
+
+ if isinstance(script_timeout, str):
+ if self._is_time(script_timeout):
+ if script_timeout != current_settings["script_timeout"]:
+ params["script_timeout"] = script_timeout
+
+ if isinstance(report_test_timeout, str):
+ if self._is_time(report_test_timeout):
+ if report_test_timeout != current_settings["report_test_timeout"]:
+ params["report_test_timeout"] = report_test_timeout
+
+ if isinstance(auditlog_enabled, bool):
+ if auditlog_enabled:
+ if current_settings["auditlog_enabled"] != "1":
+ params["auditlog_enabled"] = "1"
+ else:
+ if current_settings["auditlog_enabled"] != "0":
+ params["auditlog_enabled"] = "0"
+
+ if isinstance(geomaps_tile_provider, str):
+ _geomaps_tile_provider = geomaps_tile_provider
+ if geomaps_tile_provider == "another":
+ _geomaps_tile_provider = ""
+ if _geomaps_tile_provider != current_settings["geomaps_tile_provider"]:
+ params["geomaps_tile_provider"] = _geomaps_tile_provider
+
+ if isinstance(geomaps_tile_url, str):
+ if geomaps_tile_url != current_settings["geomaps_tile_url"]:
+ params["geomaps_tile_url"] = geomaps_tile_url
+
+ if isinstance(geomaps_max_zoom, int):
+ if str(geomaps_max_zoom) != current_settings["geomaps_max_zoom"]:
+ params["geomaps_max_zoom"] = str(geomaps_max_zoom)
+
+ if isinstance(geomaps_attribution, str):
+ if geomaps_attribution != current_settings["geomaps_attribution"]:
+ params["geomaps_attribution"] = geomaps_attribution
+
+ if LooseVersion("6.2") <= LooseVersion(self._zbx_api_version):
+ if isinstance(vault_provider, str):
+ _vault_provider = str(
+ zabbix_utils.helper_to_numeric_value(
+ ["HashiCorp_Vault", "CyberArk_Vault"], vault_provider
+ )
+ )
+ if _vault_provider != current_settings["vault_provider"]:
+ params["vault_provider"] = _vault_provider
+
+ if params != {}:
+ if self._module.check_mode:
+ self._module.exit_json(changed=True)
+ self._zapi.settings.update(params)
+ self._module.exit_json(
+ changed=True, result="Successfully updated global settings"
+ )
+ else:
+ if self._module.check_mode:
+ self._module.exit_json(changed=False)
+ self._module.exit_json(
+ changed=False, result="Settings are already up to date"
+ )
+ except Exception as e:
+ self._module.fail_json(msg="Failed to update global settings: %s" % e)
+
+
+def main():
+ argument_spec = zabbix_utils.zabbix_common_argument_spec()
+ argument_spec.update(
+ dict(
+ default_lang=dict(type="str"),
+ default_timezone=dict(type="str"),
+ default_theme=dict(
+ type="str", choices=["blue-theme", "dark-theme", "hc-light", "hc-dark"]
+ ),
+ search_limit=dict(type="int"),
+ max_overview_table_size=dict(type="int"),
+ max_in_table=dict(type="int"),
+ server_check_interval=dict(type="bool"),
+ work_period=dict(type="str"),
+ show_technical_errors=dict(type="bool"),
+ history_period=dict(type="str"),
+ period_default=dict(type="str"),
+ max_period=dict(type="str"),
+ severity_color_0=dict(type="str"),
+ severity_color_1=dict(type="str"),
+ severity_color_2=dict(type="str"),
+ severity_color_3=dict(type="str"),
+ severity_color_4=dict(type="str"),
+ severity_color_5=dict(type="str"),
+ severity_name_0=dict(type="str"),
+ severity_name_1=dict(type="str"),
+ severity_name_2=dict(type="str"),
+ severity_name_3=dict(type="str"),
+ severity_name_4=dict(type="str"),
+ severity_name_5=dict(type="str"),
+ custom_color=dict(type="bool"),
+ ok_period=dict(type="str"),
+ blink_period=dict(type="str"),
+ problem_unack_color=dict(type="str"),
+ problem_ack_color=dict(type="str"),
+ ok_unack_color=dict(type="str"),
+ ok_ack_color=dict(type="str"),
+ problem_unack_style=dict(type="bool"),
+ problem_ack_style=dict(type="bool"),
+ ok_unack_style=dict(type="bool"),
+ ok_ack_style=dict(type="bool"),
+ frontend_url=dict(type="str"),
+ discovery_group=dict(type="str"),
+ default_inventory_mode=dict(
+ type="str", choices=["disabled", "manual", "automatic"]
+ ),
+ alert_usrgrp=dict(type="str"),
+ snmptrap_logging=dict(type="bool"),
+ login_attempts=dict(type="int"),
+ login_block=dict(type="str"),
+ validate_uri_schemes=dict(type="bool"),
+ uri_valid_schemes=dict(type="list", elements="str"),
+ x_frame_options=dict(type="str"),
+ iframe_sandboxing_enabled=dict(type="bool"),
+ iframe_sandboxing_exceptions=dict(type="str"),
+ connect_timeout=dict(type="str"),
+ socket_timeout=dict(type="str"),
+ media_type_test_timeout=dict(type="str"),
+ item_test_timeout=dict(type="str"),
+ script_timeout=dict(type="str"),
+ report_test_timeout=dict(type="str"),
+ auditlog_enabled=dict(type="bool"),
+ geomaps_tile_provider=dict(
+ type="str",
+ choices=[
+ "OpenStreetMap.Mapnik",
+ "OpenTopoMap",
+ "Stamen.TonerLite",
+ "Stamen.Terrain",
+ "USGS.USTopo",
+ "USGS.USImagery",
+ "another",
+ ],
+ ),
+ geomaps_tile_url=dict(type="str"),
+ geomaps_max_zoom=dict(type="str"),
+ geomaps_attribution=dict(type="str"),
+ vault_provider=dict(
+ type="str", choices=["HashiCorp_Vault", "CyberArk_Vault"]
+ ),
+ )
+ )
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ required_if=[
+ [
+ "geomaps_tile_provider",
+ "another",
+ ["geomaps_tile_url", "geomaps_max_zoom", "geomaps_attribution"],
+ ],
+ ],
+ supports_check_mode=True,
+ )
+
+ default_lang = module.params["default_lang"]
+ default_timezone = module.params["default_timezone"]
+ default_theme = module.params["default_theme"]
+ search_limit = module.params["search_limit"]
+ max_overview_table_size = module.params["max_overview_table_size"]
+ max_in_table = module.params["max_in_table"]
+ server_check_interval = module.params["server_check_interval"]
+ work_period = module.params["work_period"]
+ show_technical_errors = module.params["show_technical_errors"]
+ history_period = module.params["history_period"]
+ period_default = module.params["period_default"]
+ max_period = module.params["max_period"]
+ severity_color_0 = module.params["severity_color_0"]
+ severity_color_1 = module.params["severity_color_1"]
+ severity_color_2 = module.params["severity_color_2"]
+ severity_color_3 = module.params["severity_color_3"]
+ severity_color_4 = module.params["severity_color_4"]
+ severity_color_5 = module.params["severity_color_5"]
+ severity_name_0 = module.params["severity_name_0"]
+ severity_name_1 = module.params["severity_name_1"]
+ severity_name_2 = module.params["severity_name_2"]
+ severity_name_3 = module.params["severity_name_3"]
+ severity_name_4 = module.params["severity_name_4"]
+ severity_name_5 = module.params["severity_name_5"]
+ custom_color = module.params["custom_color"]
+ ok_period = module.params["ok_period"]
+ blink_period = module.params["blink_period"]
+ problem_unack_color = module.params["problem_unack_color"]
+ problem_ack_color = module.params["problem_ack_color"]
+ ok_unack_color = module.params["ok_unack_color"]
+ ok_ack_color = module.params["ok_ack_color"]
+ problem_unack_style = module.params["problem_unack_style"]
+ problem_ack_style = module.params["problem_ack_style"]
+ ok_unack_style = module.params["ok_unack_style"]
+ ok_ack_style = module.params["ok_ack_style"]
+ frontend_url = module.params["frontend_url"]
+ discovery_group = module.params["discovery_group"]
+ default_inventory_mode = module.params["default_inventory_mode"]
+ alert_usrgrp = module.params["alert_usrgrp"]
+ snmptrap_logging = module.params["snmptrap_logging"]
+ login_attempts = module.params["login_attempts"]
+ login_block = module.params["login_block"]
+ validate_uri_schemes = module.params["validate_uri_schemes"]
+ uri_valid_schemes = module.params["uri_valid_schemes"]
+ x_frame_options = module.params["x_frame_options"]
+ iframe_sandboxing_enabled = module.params["iframe_sandboxing_enabled"]
+ iframe_sandboxing_exceptions = module.params["iframe_sandboxing_exceptions"]
+ connect_timeout = module.params["connect_timeout"]
+ socket_timeout = module.params["socket_timeout"]
+ media_type_test_timeout = module.params["media_type_test_timeout"]
+ item_test_timeout = module.params["item_test_timeout"]
+ script_timeout = module.params["script_timeout"]
+ report_test_timeout = module.params["report_test_timeout"]
+ auditlog_enabled = module.params["auditlog_enabled"]
+ geomaps_tile_provider = module.params["geomaps_tile_provider"]
+ geomaps_tile_url = module.params["geomaps_tile_url"]
+ geomaps_max_zoom = module.params["geomaps_max_zoom"]
+ geomaps_attribution = module.params["geomaps_attribution"]
+ vault_provider = module.params["vault_provider"]
+
+ settings = Settings(module)
+
+ current_settings = settings.get_settings()
+ settings.update_settings(
+ current_settings,
+ default_lang,
+ default_timezone,
+ default_theme,
+ search_limit,
+ max_overview_table_size,
+ max_in_table,
+ server_check_interval,
+ work_period,
+ show_technical_errors,
+ history_period,
+ period_default,
+ max_period,
+ severity_color_0,
+ severity_color_1,
+ severity_color_2,
+ severity_color_3,
+ severity_color_4,
+ severity_color_5,
+ severity_name_0,
+ severity_name_1,
+ severity_name_2,
+ severity_name_3,
+ severity_name_4,
+ severity_name_5,
+ custom_color,
+ ok_period,
+ blink_period,
+ problem_unack_color,
+ problem_ack_color,
+ ok_unack_color,
+ ok_ack_color,
+ problem_unack_style,
+ problem_ack_style,
+ ok_unack_style,
+ ok_ack_style,
+ frontend_url,
+ discovery_group,
+ default_inventory_mode,
+ alert_usrgrp,
+ snmptrap_logging,
+ login_attempts,
+ login_block,
+ validate_uri_schemes,
+ uri_valid_schemes,
+ x_frame_options,
+ iframe_sandboxing_enabled,
+ iframe_sandboxing_exceptions,
+ connect_timeout,
+ socket_timeout,
+ media_type_test_timeout,
+ item_test_timeout,
+ script_timeout,
+ report_test_timeout,
+ auditlog_enabled,
+ geomaps_tile_provider,
+ geomaps_tile_url,
+ geomaps_max_zoom,
+ geomaps_attribution,
+ vault_provider,
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_template.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_template.py
index 7c4c098af..a773790aa 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_template.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_template.py
@@ -8,19 +8,19 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
---
module: zabbix_template
-short_description: Create/update/delete/dump Zabbix template
+short_description: Create/update/delete Zabbix template
description:
- - This module allows you to create, modify, delete and dump Zabbix templates.
+ - This module allows you to create, modify and delete 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"
+ - "python >= 3.9"
options:
template_name:
description:
@@ -93,7 +93,6 @@ options:
tags:
description:
- List of tags to assign to the template.
- - Works only with >= Zabbix 4.2.
- Providing I(tags=[]) with I(force=yes) will clean all of the tags from the template.
required: false
type: list
@@ -108,54 +107,34 @@ options:
description:
- Value of the template tag.
type: str
- default: ''
- 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
+ default: ""
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 be removed in 2.14. The M(community.zabbix.zabbix_template_info) module should be used instead.
required: false
- choices: [present, absent, dump]
+ choices: [present, absent]
default: "present"
type: str
extends_documentation_fragment:
- community.zabbix.zabbix
+"""
-notes:
-- there where breaking changes in the Zabbix API with version 5.4 onwards (especially UUIDs) which may
- require you to export the templates again (see version tag >= 5.4 in the resulting file/data).
-'''
-EXAMPLES = r'''
+EXAMPLES = r"""
---
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: Create a new Zabbix template linked to groups, macros and templates
@@ -166,7 +145,7 @@ EXAMPLES = r'''
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_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_template:
template_name: ExampleHost
@@ -177,12 +156,12 @@ EXAMPLES = r'''
- Example template1
- Example template2
macros:
- - macro: '{$EXAMPLE_MACRO1}'
+ - macro: "{$EXAMPLE_MACRO1}"
value: 30000
- - macro: '{$EXAMPLE_MACRO2}'
+ - macro: "{$EXAMPLE_MACRO2}"
value: 3
- - macro: '{$EXAMPLE_MACRO3}'
- value: 'Example'
+ - macro: "{$EXAMPLE_MACRO3}"
+ value: "Example"
state: present
- name: Unlink and clear templates from the existing Zabbix template
@@ -193,7 +172,7 @@ EXAMPLES = r'''
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_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_template:
template_name: ExampleHost
@@ -210,7 +189,7 @@ EXAMPLES = r'''
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_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_template:
template_json: "{{ lookup('file', 'zabbix_apache2.json') }}"
@@ -224,7 +203,7 @@ EXAMPLES = r'''
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_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_template:
template_xml: "{{ lookup('file', 'zabbix_apache2.xml') }}"
@@ -238,20 +217,18 @@ EXAMPLES = r'''
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_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_template:
template_json:
zabbix_export:
- version: '3.2'
+ version: "3.2"
templates:
- name: Template for Testing
- description: 'Testing template import'
+ description: "Testing template import"
template: Test Template
groups:
- name: Templates
- applications:
- - name: Test Application
state: present
- name: Configure macros on the existing Zabbix template
@@ -262,13 +239,13 @@ EXAMPLES = r'''
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_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_template:
template_name: Template
macros:
- - macro: '{$TEST_MACRO}'
- value: 'Example'
+ - macro: "{$TEST_MACRO}"
+ value: "Example"
state: present
- name: Add tags to the existing Zabbix template
@@ -279,7 +256,7 @@ EXAMPLES = r'''
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_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_template:
template_name: Template
@@ -296,110 +273,16 @@ EXAMPLES = r'''
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_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_template:
template_name: Template
state: absent
+"""
-- name: Dump Zabbix template as JSON
- # 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_template:
- template_name: Template
- omit_date: yes
- state: dump
- register: template_dump
-
-- name: Dump Zabbix template as XML
- # 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_template:
- template_name: Template
- dump_format: xml
- omit_date: false
- state: dump
- register: template_dump
-'''
-
-RETURN = r'''
+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 json
@@ -422,12 +305,12 @@ class Template(ZabbixBase):
def get_group_ids_by_group_names(self, group_names):
group_ids = []
for group_name in group_names:
- if LooseVersion(self._zbx_api_version) >= LooseVersion('6.2'):
- group = self._zapi.templategroup.get({'output': ['groupid'], 'filter': {'name': group_name}})
+ if LooseVersion(self._zbx_api_version) >= LooseVersion("6.2"):
+ group = self._zapi.templategroup.get({"output": ["groupid"], "filter": {"name": group_name}})
else:
- group = self._zapi.hostgroup.get({'output': ['groupid'], 'filter': {'name': group_name}})
+ group = self._zapi.hostgroup.get({"output": ["groupid"], "filter": {"name": group_name}})
if group:
- group_ids.append({'groupid': group[0]['groupid']})
+ group_ids.append({"groupid": group[0]["groupid"]})
else:
self._module.fail_json(msg="Template group not found: %s" % group_name)
return group_ids
@@ -437,25 +320,25 @@ class Template(ZabbixBase):
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}})
+ 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({'templateid': template_id})
+ template_id = template_list[0]["templateid"]
+ template_ids.append({"templateid": template_id})
return template_ids
def add_template(self, template_name, group_ids, link_template_ids, macros, tags):
if self._module.check_mode:
self._module.exit_json(changed=True)
- new_template = {'host': template_name, 'groups': group_ids, 'templates': link_template_ids, 'macros': macros, 'tags': tags}
+ new_template = {"host": template_name, "groups": group_ids, "templates": link_template_ids, "macros": macros, "tags": tags}
if macros is None:
- new_template.update({'macros': []})
+ new_template.update({"macros": []})
if tags is None:
- new_template.update({'tags': []})
+ new_template.update({"tags": []})
if link_template_ids is None:
- new_template.update({'templates': []})
+ new_template.update({"templates": []})
self._zapi.template.create(new_template)
@@ -470,17 +353,17 @@ class Template(ZabbixBase):
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 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')
+ 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':
+ 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
@@ -489,19 +372,19 @@ class Template(ZabbixBase):
# If neither template_json or template_xml were used, user provided all parameters via module options
if template_groups is not None:
- if LooseVersion(self._zbx_api_version) >= LooseVersion('6.2'):
- existing_groups = [g['name'] for g in existing_template['zabbix_export']['template_groups']]
+ if LooseVersion(self._zbx_api_version) >= LooseVersion("6.2"):
+ existing_groups = [g["name"] for g in existing_template["zabbix_export"]["template_groups"]]
else:
- existing_groups = [g['name'] for g in existing_template['zabbix_export']['groups']]
+ 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'] = []
+ 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']]
+ 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
@@ -516,46 +399,45 @@ class Template(ZabbixBase):
changed = True
break
- if 'macros' not in existing_template['zabbix_export']['templates'][0]:
- existing_template['zabbix_export']['templates'][0]['macros'] = []
+ 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']
+ existing_macros = existing_template["zabbix_export"]["templates"][0]["macros"]
if template_macros != existing_macros:
changed = True
- if LooseVersion(self._zbx_api_version) >= LooseVersion('4.2'):
- if 'tags' not in existing_template['zabbix_export']['templates'][0]:
- existing_template['zabbix_export']['templates'][0]['tags'] = []
- if template_tags is not None:
- existing_tags = existing_template['zabbix_export']['templates'][0]['tags']
- if template_tags != existing_tags:
- changed = True
+ if "tags" not in existing_template["zabbix_export"]["templates"][0]:
+ existing_template["zabbix_export"]["templates"][0]["tags"] = []
+ if template_tags is not None:
+ existing_tags = existing_template["zabbix_export"]["templates"][0]["tags"]
+ if template_tags != existing_tags:
+ changed = True
return changed
def update_template(self, template_ids, group_ids, link_template_ids, clear_template_ids, template_macros, template_tags):
template_changes = {}
if group_ids is not None:
- template_changes.update({'groups': group_ids})
+ template_changes.update({"groups": group_ids})
if link_template_ids is not None:
- template_changes.update({'templates': link_template_ids})
+ template_changes.update({"templates": link_template_ids})
else:
- template_changes.update({'templates': []})
+ template_changes.update({"templates": []})
if clear_template_ids is not None:
- template_changes.update({'templates_clear': clear_template_ids})
+ template_changes.update({"templates_clear": clear_template_ids})
if template_macros is not None:
- template_changes.update({'macros': template_macros})
+ template_changes.update({"macros": template_macros})
else:
- template_changes.update({'macros': []})
+ template_changes.update({"macros": []})
if template_tags is not None:
- template_changes.update({'tags': template_tags})
+ template_changes.update({"tags": template_tags})
else:
- template_changes.update({'tags': []})
+ template_changes.update({"tags": []})
if template_changes:
# If we got here we know that only one template was provided via template_name
@@ -566,7 +448,7 @@ class Template(ZabbixBase):
if self._module.check_mode:
self._module.exit_json(changed=True)
- templateids_list = [t.get('templateid') for t in templateids]
+ templateids_list = [t.get("templateid") for t in templateids]
self._zapi.template.delete(templateids_list)
def ordered_json(self, obj):
@@ -578,26 +460,21 @@ class Template(ZabbixBase):
else:
return obj
- def dump_template(self, template_ids, template_type='json', omit_date=False):
- template_ids_list = [t.get('templateid') for t in template_ids]
+ def dump_template(self, template_ids, template_type="json"):
+ template_ids_list = [t.get("templateid") for t in template_ids]
try:
- dump = self._zapi.configuration.export({'format': template_type, 'options': {'templates': template_ids_list}})
- 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)
+ dump = self._zapi.configuration.export({"format": template_type, "options": {"templates": template_ids_list}})
+ if template_type == "xml":
+ xmlroot = ET.fromstring(dump.encode("utf-8"))
if PY2:
- return str(ET.tostring(xmlroot, encoding='utf-8'))
+ return str(ET.tostring(xmlroot, encoding="utf-8"))
else:
- return str(ET.tostring(xmlroot, encoding='utf-8').decode('utf-8'))
+ return str(ET.tostring(xmlroot, encoding="utf-8").decode("utf-8"))
else:
- return self.load_json_template(dump, omit_date=omit_date)
+ return self.load_json_template(dump)
except Exception as e:
- self._module.fail_json(msg='Unable to export template: %s' % 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.
@@ -609,20 +486,18 @@ class Template(ZabbixBase):
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
+ 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]
+ 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._zbx_api_version) < LooseVersion('2.4'):
- desc_not_supported = True
# Filter empty attributes from template object to allow accurate comparison
- for template in template_json['zabbix_export']['templates']:
+ 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):
+ if not template[key] or (key == "description" and desc_not_supported):
template.pop(key)
return template_json
@@ -634,7 +509,7 @@ class Template(ZabbixBase):
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']
+ keep_keys = ["graphs", "templates", "triggers", "value_maps"]
# Remove unwanted XML nodes
for node in list(parsed_xml_root):
@@ -642,209 +517,174 @@ class Template(ZabbixBase):
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 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)
+ 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):
+ def load_json_template(self, template_json):
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())
+ 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())
+ 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'):
+ def import_template(self, template_content, template_type="json"):
if self._module.check_mode:
self._module.exit_json(changed=True)
# rules schema latest version
update_rules = {
- 'applications': {
- 'createMissing': True,
- 'deleteMissing': True
+ "discoveryRules": {
+ "createMissing": True,
+ "updateExisting": True,
+ "deleteMissing": True
},
- 'discoveryRules': {
- 'createMissing': True,
- 'updateExisting': True,
- 'deleteMissing': True
+ "graphs": {
+ "createMissing": True,
+ "updateExisting": True,
+ "deleteMissing": True
},
- 'graphs': {
- 'createMissing': True,
- 'updateExisting': True,
- 'deleteMissing': True
+ "host_groups": {
+ "createMissing": True
},
- 'host_groups': {
- 'createMissing': True
+ "httptests": {
+ "createMissing": True,
+ "updateExisting": True,
+ "deleteMissing": True
},
- 'httptests': {
- 'createMissing': True,
- 'updateExisting': True,
- 'deleteMissing': True
+ "items": {
+ "createMissing": True,
+ "updateExisting": True,
+ "deleteMissing": True
},
- 'items': {
- 'createMissing': True,
- 'updateExisting': True,
- 'deleteMissing': True
+ "templates": {
+ "createMissing": True,
+ "updateExisting": True
},
- 'templates': {
- 'createMissing': True,
- 'updateExisting': True
+ "template_groups": {
+ "createMissing": True
},
- 'template_groups': {
- 'createMissing': True
+ "templateLinkage": {
+ "createMissing": True
},
- 'templateLinkage': {
- 'createMissing': True
+ "templateScreens": {
+ "createMissing": True,
+ "updateExisting": True,
+ "deleteMissing": True
},
- 'templateScreens': {
- 'createMissing': True,
- 'updateExisting': True,
- 'deleteMissing': True
+ "triggers": {
+ "createMissing": True,
+ "updateExisting": True,
+ "deleteMissing": True
},
- 'triggers': {
- 'createMissing': True,
- 'updateExisting': True,
- 'deleteMissing': True
- },
- 'valueMaps': {
- 'createMissing': True,
- 'updateExisting': True
+ "valueMaps": {
+ "createMissing": True,
+ "updateExisting": True
}
}
try:
- # updateExisting for application removed from zabbix api after 3.2
- if LooseVersion(self._zbx_api_version) <= LooseVersion('3.2'):
- 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(self._zbx_api_version).version[:2] == LooseVersion('4.0').version and \
- LooseVersion(self._zbx_api_version).version[:3] >= LooseVersion('4.0.16').version:
- update_rules['templateLinkage']['deleteMissing'] = True
- if LooseVersion(self._zbx_api_version) >= LooseVersion('4.4.4'):
- update_rules['templateLinkage']['deleteMissing'] = True
-
- # templateScreens is named templateDashboards in zabbix >= 5.2
- # https://support.zabbix.com/browse/ZBX-18677
- if LooseVersion(self._zbx_api_version) >= LooseVersion('5.2'):
- update_rules["templateDashboards"] = update_rules.pop("templateScreens")
-
- # Zabbix 5.4 no longer supports applications
- if LooseVersion(self._zbx_api_version) >= LooseVersion('5.4'):
- update_rules.pop('applications', None)
+ update_rules["templateLinkage"]["deleteMissing"] = True
+ update_rules["templateDashboards"] = update_rules.pop("templateScreens")
# before Zabbix 6.2 host_groups and template_group are joined into groups parameter
- if LooseVersion(self._zbx_api_version) < LooseVersion('6.2'):
- update_rules['groups'] = {'createMissing': True}
- update_rules.pop('host_groups', None)
- update_rules.pop('template_groups', None)
+ if LooseVersion(self._zbx_api_version) < LooseVersion("6.2"):
+ update_rules["groups"] = {"createMissing": True}
+ update_rules.pop("host_groups", None)
+ update_rules.pop("template_groups", None)
# The loaded unicode slash of multibyte as a string is escaped when parsing JSON by json.loads in Python2.
# So, it is imported in the unicode string into Zabbix.
# The following processing is removing the unnecessary slash in escaped for decoding correctly to the multibyte string.
# https://github.com/ansible-collections/community.zabbix/issues/314
if PY2:
- template_content = re.sub(r'\\\\u([0-9a-z]{,4})', r'\\u\1', template_content)
+ template_content = re.sub(r"\\\\u([0-9a-z]{,4})", r"\\u\1", template_content)
- import_data = {'format': template_type, 'source': template_content, 'rules': update_rules}
+ import_data = {"format": template_type, "source": template_content, "rules": update_rules}
self._zapi.configuration.import_(import_data)
except Exception as e:
- self._module.fail_json(msg='Unable to import template', details=to_native(e),
+ self._module.fail_json(msg="Unable to import template", details=to_native(e),
exception=traceback.format_exc())
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- 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),
+ 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, elements="str"),
+ link_templates=dict(type="list", required=False, elements="str"),
+ clear_templates=dict(type="list", required=False, elements="str"),
macros=dict(
- type='list',
- elements='dict',
+ type="list",
+ elements="dict",
options=dict(
- macro=dict(type='str', required=True),
- value=dict(type='str', required=True)
+ macro=dict(type="str", required=True),
+ value=dict(type="str", required=True)
)
),
tags=dict(
- type='list',
- elements='dict',
+ type="list",
+ elements="dict",
options=dict(
- tag=dict(type='str', required=True),
- value=dict(type='str', default='')
+ tag=dict(type="str", required=True),
+ value=dict(type="str", default="")
)
),
- 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']),
+ state=dict(type="str", default="present", choices=["present", "absent"]),
))
module = AnsibleModule(
argument_spec=argument_spec,
required_one_of=[
- ['template_name', 'template_json', 'template_xml']
+ ["template_name", "template_json", "template_xml"]
],
mutually_exclusive=[
- ['template_name', 'template_json', 'template_xml']
+ ["template_name", "template_json", "template_xml"]
],
required_if=[
- ['state', 'absent', ['template_name']],
- ['state', 'dump', ['template_name']]
+ ["state", "absent", ["template_name"]]
],
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- 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']
- template_tags = module.params['tags']
- omit_date = module.params['omit_date']
- dump_format = module.params['dump_format']
- state = module.params['state']
+ 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"]
+ template_tags = module.params["tags"]
+ state = module.params["state"]
template = Template(module)
# Identify template names for IDs retrieval
- # Template names are expected to reside in ['zabbix_export']['templates'][*]['template'] for both data types
+ # 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_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'])
+ template_names = list(t["template"] for t in json_parsed["zabbix_export"]["templates"])
elif template_xml is not None:
- template_type = 'xml'
+ 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')))
+ template_names = list(t.find("template").text for t in list(xml_parsed.find("templates")))
else:
template_names = [template_name]
@@ -858,17 +698,6 @@ def main():
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.",
- collection_name="community.zabbix", version='3.0.0') # was 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
@@ -895,14 +724,14 @@ def main():
tagitem[key] = str(tagitem[key])
if not template_ids:
- # Assume new templates are being added when no ID's were found
+ # 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')
+ 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, template_tags)
module.exit_json(changed=True, result="Successfully added template: %s" % template_name)
@@ -924,5 +753,5 @@ def main():
module.exit_json(changed=changed, result="Template successfully updated")
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_template_info.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_template_info.py
index acd5b5055..140233e1a 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_template_info.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_template_info.py
@@ -8,7 +8,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
-DOCUMENTATION = '''
+DOCUMENTATION = """
module: zabbix_template_info
short_description: Gather information about Zabbix template
author:
@@ -16,7 +16,7 @@ author:
description:
- This module allows you to search for Zabbix template.
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
options:
template_name:
description:
@@ -26,8 +26,7 @@ options:
format:
description:
- Format to use when dumping template.
- - C(yaml) works only with Zabbix >= 5.2.
- choices: ['json', 'xml', 'yaml', 'none']
+ choices: ["json", "xml", "yaml", "none"]
default: json
type: str
omit_date:
@@ -38,23 +37,19 @@ options:
default: false
extends_documentation_fragment:
- community.zabbix.zabbix
+"""
-notes:
-- there where breaking changes in the Zabbix API with version 5.4 onwards (especially UUIDs) which may
- require you to export the templates again (see version tag >= 5.4 in the resulting file/data).
-'''
-
-EXAMPLES = '''
+EXAMPLES = """
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: Get Zabbix template as JSON
@@ -65,7 +60,7 @@ EXAMPLES = '''
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_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_template_info:
template_name: Template
@@ -81,7 +76,7 @@ EXAMPLES = '''
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_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_template_info:
template_name: Template
@@ -97,7 +92,7 @@ EXAMPLES = '''
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_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_template_info:
template_name: Template
@@ -113,15 +108,15 @@ EXAMPLES = '''
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_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_template_info:
template_name: Template
format: none
register: template
-'''
+"""
-RETURN = '''
+RETURN = """
---
template_id:
description: The ID of the template
@@ -133,38 +128,33 @@ template_json:
returned: when format is json and omit_date is true
type: str
sample: {
+ "changed": false,
+ "failed": false,
+ "template_id": "10529",
+ "template_json": {
"zabbix_export": {
- "version": "4.0",
- "groups": [
- {
- "name": "Templates"
- }
- ],
- "templates": [
- {
- "template": "Test Template",
- "name": "Template for Testing",
- "description": "Testing template import",
- "groups": [
+ "groups": [
{
- "name": "Templates"
+ "name": "Templates",
+ "uuid": "7df96b18c230490a9a0a9e2307226338"
}
- ],
- "applications": [
+ ],
+ "templates": [
{
- "name": "Test Application"
+ "groups": [
+ {
+ "name": "Templates"
+ }
+ ],
+ "name": "ExampleTemplateForTempleteInfoModule",
+ "template": "ExampleTemplateForTempleteInfoModule",
+ "uuid": "615e9b0662bb4399a2503a9aaa743517"
}
- ],
- "items": [],
- "discovery_rules": [],
- "httptests": [],
- "macros": [],
- "templates": [],
- "screens": []
- }
- ]
+ ],
+ "version": "6.0"
}
- }
+ }
+ }
template_xml:
description: The XML of the template
@@ -172,34 +162,23 @@ template_xml:
type: str
sample: >-
<zabbix_export>
- <version>4.0</version>
- <date>2019-10-27T14:49:57Z</date>
+ <version>6.0</version>
<groups>
<group>
+ <uuid>7df96b18c230490a9a0a9e2307226338</uuid>
<name>Templates</name>
</group>
</groups>
<templates>
<template>
- <template>Test Template</template>
- <name>Template for Testing</name>
- <description>Testing template import</description>
+ <uuid>9a83162273f74032a1005fdb13943038</uuid>
+ <template>ExampleTemplateForTempleteInfoModule</template>
+ <name>ExampleTemplateForTempleteInfoModule</name>
<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>
@@ -210,22 +189,20 @@ template_yaml:
type: str
sample: >-
zabbix_export:
- version: '6.0'
- date: '2022-07-09T13:25:18Z'
+ version: "6.0"
groups:
-
uuid: 7df96b18c230490a9a0a9e2307226338
name: Templates
- templates:
- -
- uuid: 88a9ad240f924f669eb7d4eed736320c
- template: 'Test Template'
- name: 'Template for Testing'
- description: 'Testing template import'
- groups:
+ templates:
-
- name: Templates
-'''
+ uuid: 67b075276bf047d3aeb8f7d5c2121c6a
+ template: ExampleTemplateForTempleteInfoModule
+ name: ExampleTemplateForTempleteInfoModule
+ groups:
+ -
+ name: Templatesn
+"""
import traceback
@@ -244,13 +221,13 @@ class TemplateInfo(ZabbixBase):
def get_template_id(self, template_name):
template_id = []
try:
- template_list = self._zapi.template.get({'output': ['templateid'],
- 'filter': {'host': template_name}})
+ template_list = self._zapi.template.get({"output": ["templateid"],
+ "filter": {"host": template_name}})
except Exception as e:
- self._module.fail_json(msg='Failed to get template: %s' % e)
+ self._module.fail_json(msg="Failed to get template: %s" % e)
if template_list:
- template_id.append(template_list[0]['templateid'])
+ template_id.append(template_list[0]["templateid"])
return template_id
@@ -258,92 +235,86 @@ class TemplateInfo(ZabbixBase):
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']
+ 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())
+ self._module.fail_json(msg="Invalid JSON provided", details=to_native(e), exception=traceback.format_exc())
def load_yaml_template(self, template_yaml, omit_date=False):
if omit_date:
yaml_lines = template_yaml.splitlines(True)
for index, line in enumerate(yaml_lines):
- if 'date:' in line:
+ if "date:" in line:
del yaml_lines[index]
- return ''.join(yaml_lines)
+ return "".join(yaml_lines)
else:
return template_yaml
- def dump_template(self, template_id, template_type='json', omit_date=False):
+ 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'))
+ 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)
if PY2:
- return str(ET.tostring(xmlroot, encoding='utf-8'))
+ return str(ET.tostring(xmlroot, encoding="utf-8"))
else:
- return str(ET.tostring(xmlroot, encoding='utf-8').decode('utf-8'))
- elif template_type == 'yaml':
+ return str(ET.tostring(xmlroot, encoding="utf-8").decode("utf-8"))
+ elif template_type == "yaml":
return self.load_yaml_template(dump, omit_date)
else:
return self.load_json_template(dump, omit_date)
except Exception as e:
- self._module.fail_json(msg='Unable to export template: %s' % e)
+ self._module.fail_json(msg="Unable to export template: %s" % e)
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- template_name=dict(type='str', required=True),
- omit_date=dict(type='bool', required=False, default=False),
- format=dict(type='str', choices=['json', 'xml', 'yaml', 'none'], default='json')
+ template_name=dict(type="str", required=True),
+ omit_date=dict(type="bool", required=False, default=False),
+ format=dict(type="str", choices=["json", "xml", "yaml", "none"], default="json")
))
module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- template_name = module.params['template_name']
- omit_date = module.params['omit_date']
- format = module.params['format']
+ template_name = module.params["template_name"]
+ omit_date = module.params["omit_date"]
+ format = module.params["format"]
template_info = TemplateInfo(module)
template_id = template_info.get_template_id(template_name)
if not template_id:
- module.fail_json(msg='Template not found: %s' % template_name)
+ module.fail_json(msg="Template not found: %s" % template_name)
- if format == 'json':
+ if format == "json":
module.exit_json(
changed=False,
template_id=template_id[0],
- template_json=template_info.dump_template(template_id, template_type='json', omit_date=omit_date)
+ template_json=template_info.dump_template(template_id, template_type="json", omit_date=omit_date)
)
- elif format == 'xml':
+ elif format == "xml":
module.exit_json(
changed=False,
template_id=template_id[0],
- template_xml=template_info.dump_template(template_id, template_type='xml', omit_date=omit_date)
+ template_xml=template_info.dump_template(template_id, template_type="xml", omit_date=omit_date)
)
- elif format == 'yaml':
+ elif format == "yaml":
module.exit_json(
changed=False,
template_id=template_id[0],
- template_yaml=template_info.dump_template(template_id, template_type='yaml', omit_date=omit_date)
+ template_yaml=template_info.dump_template(template_id, template_type="yaml", omit_date=omit_date)
)
- elif format == 'none':
+ elif format == "none":
module.exit_json(changed=False, template_id=template_id[0])
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_templategroup.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_templategroup.py
new file mode 100644
index 000000000..7ab39d8fc
--- /dev/null
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_templategroup.py
@@ -0,0 +1,180 @@
+#!/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
+
+
+DOCUMENTATION = r'''
+---
+module: zabbix_templategroup
+short_description: Create/delete Zabbix template groups
+description:
+ - Create template groups if they do not exist.
+ - Delete existing template groups if they exist.
+author:
+ - "Cove (@cove)"
+ - "Tony Minfei Ding (!UNKNOWN)"
+ - "Harrison Gu (@harrisongu)"
+requirements:
+ - "python >= 2.6"
+options:
+ state:
+ description:
+ - Create or delete template group.
+ required: false
+ type: str
+ default: "present"
+ choices: [ "present", "absent" ]
+ template_groups:
+ description:
+ - List of template groups to create or delete.
+ required: true
+ type: list
+ elements: str
+ aliases: [ "template_group" ]
+
+extends_documentation_fragment:
+- community.zabbix.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'''
+# 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
+
+# Base create template groups example
+- name: Create template groups
+ # 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_group:
+ state: present
+ template_groups:
+ - Example group1
+ - Example group2
+
+# Limit the Zabbix group creations to one template since Zabbix can return an error when doing concurrent updates
+- name: Create template groups
+ # 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_group:
+ state: present
+ template_groups:
+ - Example group1
+ - Example group2
+ when: inventory_hostname==groups['group_name'][0]
+'''
+
+
+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 TemplateGroup(ZabbixBase):
+ # create template group(s) if not exists
+ def create_template_group(self, group_names):
+ try:
+ group_add_list = []
+ for group_name in group_names:
+ result = self._zapi.templategroup.get({'filter': {'name': group_name}})
+ if not result:
+ if self._module.check_mode:
+ self._module.exit_json(changed=True)
+ self._zapi.templategroup.create({'name': group_name})
+ group_add_list.append(group_name)
+ return group_add_list
+ except Exception as e:
+ self._module.fail_json(msg="Failed to create template group(s): %s" % e)
+
+ # delete template group(s)
+ def delete_template_group(self, group_ids):
+ try:
+ if self._module.check_mode:
+ self._module.exit_json(changed=True)
+ self._zapi.templategroup.delete(group_ids)
+ except Exception as e:
+ self._module.fail_json(msg="Failed to delete template group(s), Exception: %s" % e)
+
+ # get group ids by name
+ def get_group_ids(self, template_groups):
+ group_ids = []
+
+ group_list = self._zapi.templategroup.get({'output': 'extend', 'filter': {'name': template_groups}})
+ for group in group_list:
+ group_id = group['groupid']
+ group_ids.append(group_id)
+ return group_ids, group_list
+
+
+def main():
+ argument_spec = zabbix_utils.zabbix_common_argument_spec()
+ argument_spec.update(dict(
+ template_groups=dict(type='list', required=True, aliases=['template_group'], elements='str'),
+ state=dict(type='str', default="present", choices=['present', 'absent']),
+ ))
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True
+ )
+
+ template_groups = module.params['template_groups']
+ state = module.params['state']
+
+ templateGroup = TemplateGroup(module)
+
+ group_ids = []
+ group_list = []
+ if template_groups:
+ group_ids, group_list = templateGroup.get_group_ids(template_groups)
+
+ if state == "absent":
+ # delete template groups
+ if group_ids:
+ delete_group_names = []
+ templateGroup.delete_template_group(group_ids)
+ for group in group_list:
+ delete_group_names.append(group['name'])
+ module.exit_json(changed=True,
+ result="Successfully deleted template group(s): %s." % ",".join(delete_group_names))
+ else:
+ module.exit_json(changed=False, result="No template group(s) to delete.")
+ else:
+ # create template groups
+ group_add_list = templateGroup.create_template_group(template_groups)
+ if len(group_add_list) > 0:
+ module.exit_json(changed=True, result="Successfully created template group(s): %s" % group_add_list)
+ else:
+ module.exit_json(changed=False)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_token.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_token.py
new file mode 100644
index 000000000..fc4d4c791
--- /dev/null
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_token.py
@@ -0,0 +1,288 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright: (c) 2023, ONODERA Masaru <masaru-onodera@ieee.org>
+# 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 = """
+---
+module: zabbix_token
+
+short_description: Create/Update/Generate/Delete Zabbix token.
+
+description:
+ - This module allows you to create, update, generate and delete Zabbix token.
+
+author:
+ - ONODERA Masaru(@masa-orca)
+
+requirements:
+ - "python >= 3.9"
+
+version_added: 2.1.0
+
+options:
+ name:
+ description:
+ - Name of the token.
+ required: true
+ type: str
+ description:
+ description:
+ - Description of the token.
+ required: false
+ type: str
+ username:
+ description:
+ - Name of user who is the token assinged to.
+ required: true
+ type: str
+ status:
+ description:
+ - Status of the token.
+ required: false
+ type: bool
+ expires_at:
+ description:
+ - A timestamp of the token will be expired.
+ - The token will never expire if C(0)
+ required: false
+ type: int
+ generate_token:
+ description:
+ - New token string will be generated if C(true).
+ required: false
+ type: bool
+ default: false
+ state:
+ description:
+ - Create or delete token.
+ type: str
+ default: present
+ choices:
+ - present
+ - absent
+
+extends_documentation_fragment:
+ - community.zabbix.zabbix
+"""
+
+EXAMPLES = """
+# 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 Zabbix token and generate token string
+ # 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_token:
+ name: test token
+ description: Admin test token
+ username: Admin
+ status: true
+ expires_at: 1700000000
+ generate_token: true
+ state: present
+"""
+
+RETURN = """
+msg:
+ description: The result of the operation
+ returned: success
+ type: str
+ sample: "Successfully created token"
+token:
+ description: Generated token string
+ returned: I(generate_token=true)
+ type: str
+ sample: "8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895"
+"""
+
+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 Token(ZabbixBase):
+ def get_userid_from_name(self, username):
+ try:
+ userids = self._zapi.user.get(
+ {"output": "userid", "filter": {"username": username}}
+ )
+ if not userids or len(userids) > 1:
+ self._module.fail_json("User '%s' cannot be found" % username)
+ return userids[0]["userid"]
+ except Exception as e:
+ self._module.fail_json(msg="Failed to get userid: %s" % e)
+
+ # get token
+ def get_token(self, name, userid):
+ try:
+ return self._zapi.token.get(
+ {"output": "extend", "userids": [userid], "filter": {"name": name}}
+ )
+ except Exception as e:
+ self._module.fail_json(msg="Failed to get token: %s" % e)
+
+ def create_token(
+ self, name, description, userid, status, expires_at, generate_token
+ ):
+ try:
+ params = {}
+ params["name"] = name
+ if isinstance(description, str):
+ params["description"] = description
+
+ params["userid"] = userid
+
+ if isinstance(status, bool):
+ if status:
+ params["status"] = "1"
+ else:
+ params["status"] = "0"
+
+ if isinstance(expires_at, str):
+ params["expires_at"] = str(expires_at)
+
+ if self._module.check_mode:
+ self._module.exit_json(changed=True)
+ result = self._zapi.token.create(params)
+
+ if generate_token:
+ generated_tokens = self._zapi.token.generate(result["tokenids"])
+ self._module.exit_json(
+ changed=True,
+ msg="Successfully created token.",
+ token=generated_tokens[0]["token"],
+ )
+ else:
+ self._module.exit_json(changed=True, msg="Successfully created token.")
+
+ except Exception as e:
+ self._module.fail_json(msg="Failed to create token: %s" % e)
+
+ def update_token(
+ self, token, name, description, status, expires_at, generate_token
+ ):
+ try:
+ params = {}
+ params["tokenid"] = token["tokenid"]
+ params["name"] = name
+ if isinstance(description, str) and description != token["description"]:
+ params["description"] = description
+
+ if isinstance(status, bool):
+ if status:
+ if token["status"] != "0":
+ params["status"] = "0"
+ else:
+ if token["status"] != "1":
+ params["status"] = "1"
+
+ if isinstance(expires_at, int) and str(expires_at) != token["expires_at"]:
+ params["expires_at"] = str(expires_at)
+
+ # If params does not have any parameter except tokenid and name, no need to update.
+ if len(params.keys()) == 2:
+ if not generate_token:
+ self._module.exit_json(changed=False)
+ elif self._module.check_mode:
+ self._module.exit_json(changed=True)
+ else:
+ if self._module.check_mode:
+ self._module.exit_json(changed=True)
+ self._zapi.token.update(params)
+
+ if generate_token:
+ generated_tokens = self._zapi.token.generate([token["tokenid"]])
+ self._module.exit_json(
+ changed=True,
+ msg="Successfully updated token.",
+ token=generated_tokens[0]["token"],
+ )
+ else:
+ self._module.exit_json(changed=True, msg="Successfully updated token.")
+
+ except Exception as e:
+ self._module.fail_json(msg="Failed to update token: %s" % e)
+
+ # delete token
+ def delete_token(self, token):
+ try:
+ tokenid = token["tokenid"]
+ if self._module.check_mode:
+ self._module.exit_json(changed=True)
+ self._zapi.token.delete([tokenid])
+ self._module.exit_json(changed=True, msg="Successfully deleted token.")
+ except Exception as e:
+ self._module.fail_json(msg="Failed to delete token: %s" % e)
+
+
+def main():
+ argument_spec = zabbix_utils.zabbix_common_argument_spec()
+ argument_spec.update(
+ dict(
+ name=dict(type="str", required=True),
+ description=dict(type="str"),
+ username=dict(type="str", required=True),
+ status=dict(type="bool"),
+ expires_at=dict(type="int"),
+ generate_token=dict(type="bool", default=False),
+ state=dict(type="str", choices=["present", "absent"], default="present"),
+ )
+ )
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ )
+
+ name = module.params["name"]
+ description = module.params["description"]
+ username = module.params["username"]
+ status = module.params["status"]
+ expires_at = module.params["expires_at"]
+ generate_token = module.params["generate_token"]
+ state = module.params["state"]
+
+ token_class_obj = Token(module)
+ userid = token_class_obj.get_userid_from_name(username)
+ tokens = token_class_obj.get_token(name, userid)
+ if state == "absent":
+ if len(tokens) == 1:
+ token_class_obj.delete_token(tokens[0])
+ else:
+ module.exit_json(changed=False)
+ else:
+ if len(tokens) == 1:
+ token_class_obj.update_token(
+ tokens[0], name, description, status, expires_at, generate_token
+ )
+ else:
+ token_class_obj.create_token(
+ name, description, userid, status, expires_at, generate_token
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_user.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_user.py
index 3c655ffe8..92f04b989 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_user.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_user.py
@@ -6,9 +6,10 @@
from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
module: zabbix_user
short_description: Create/update/delete Zabbix users
author:
@@ -16,14 +17,12 @@ author:
description:
- This module allows you to create, modify and delete Zabbix users.
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
options:
username:
description:
- - Name of the user alias in Zabbix.
+ - Username.
- username is the unique identifier used and cannot be updated using this module.
- - alias must be replaced with username since Zabbix 6.4.
- aliases: [ alias ]
required: true
type: str
name:
@@ -45,7 +44,6 @@ options:
description:
- User's password.
- Required unless all of the I(usrgrps) are set to use LDAP as frontend access.
- - Always required for Zabbix versions lower than 4.0.
required: false
type: str
override_passwd:
@@ -54,37 +52,43 @@ options:
- Password will not be updated on subsequent runs without setting this value to yes.
default: no
type: bool
+ current_passwd:
+ description:
+ - Current password for the user when overriding its password.
+ - Required when overriding the logged in user's password.
+ - https://www.zabbix.com/documentation/6.4/en/manual/api/reference/user/update
+ required: false
+ type: str
lang:
description:
- Language code of the user's language.
- - C(default) can be used with Zabbix version 5.2 or higher.
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'
- - 'default'
+ - "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"
+ - "default"
type: str
theme:
description:
- User's theme.
choices:
- - 'default'
- - 'blue-theme'
- - 'dark-theme'
+ - "default"
+ - "blue-theme"
+ - "dark-theme"
type: str
autologin:
description:
@@ -116,7 +120,7 @@ options:
mediatype:
description:
- Media type name to set.
- default: 'Email'
+ default: "Email"
type: str
sendto:
description:
@@ -128,8 +132,8 @@ options:
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'
+ - https://www.zabbix.com/documentation/current/en/manual/appendix/time_period
+ default: "1-7,00:00-24:00"
type: str
severity:
description:
@@ -180,26 +184,15 @@ options:
type: bool
type: list
elements: dict
- type:
- description:
- - Type of the user.
- - I(type) can be used when Zabbix version is 5.0 or lower.
- choices:
- - 'Zabbix user'
- - 'Zabbix admin'
- - 'Zabbix super admin'
- type: str
timezone:
description:
- User's time zone.
- - I(timezone) can be used with Zabbix version 5.2 or higher.
- For the full list of supported time zones please refer to U(https://www.php.net/manual/en/timezones.php)
type: str
version_added: 1.2.0
role_name:
description:
- User's role.
- - I(role_name) can be used when Zabbix version is 5.2 or higher.
- Default is C(User role) when creating a new user.
- The default value will be removed at the version 2.0.0.
type: str
@@ -209,25 +202,25 @@ options:
- 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']
+ default: "present"
+ choices: ["present", "absent"]
type: str
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: create a new zabbix user.
@@ -238,7 +231,7 @@ EXAMPLES = r'''
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_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_user:
username: example
@@ -251,10 +244,10 @@ EXAMPLES = r'''
lang: en_GB
theme: blue-theme
autologin: no
- autologout: '0'
- refresh: '30'
- rows_per_page: '200'
- after_login_url: ''
+ autologout: "0"
+ refresh: "30"
+ rows_per_page: "200"
+ after_login_url: ""
user_medias:
- mediatype: Email
sendto:
@@ -269,7 +262,6 @@ EXAMPLES = r'''
high: yes
disaster: yes
active: no
- type: Zabbix super admin
state: present
- name: delete existing zabbix user.
@@ -280,20 +272,20 @@ EXAMPLES = r'''
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_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_user:
username: example
state: absent
-'''
+"""
-RETURN = r'''
+RETURN = r"""
user_ids:
description: User id created or changed
returned: success
type: dict
sample: { "userids": [ "5" ] }
-'''
+"""
import copy
@@ -301,44 +293,40 @@ import copy
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.zabbix.plugins.module_utils.base import ZabbixBase
-from ansible_collections.community.zabbix.plugins.module_utils.helpers import helper_normalize_data
+from ansible_collections.community.zabbix.plugins.module_utils.helpers import (
+ helper_normalize_data,
+)
from ansible.module_utils.compat.version import LooseVersion
import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabbix_utils
class User(ZabbixBase):
-
- def username_key(self):
- """ Returns the key name for 'username', which was 'alias'
- before Zabbix 5.4.
- """
- if LooseVersion(self._zbx_api_version) < LooseVersion('5.4'):
- return 'alias'
- return 'username'
-
def get_default_authentication(self):
- auth = self._zapi.authentication.get({'output': 'extend'})
+ auth = self._zapi.authentication.get({"output": "extend"})
try:
if auth["authentication_type"] == "0":
return "internal"
elif auth["authentication_type"] == "1":
return "LDAP"
else:
- self._module.fail_json(msg="Failed to query authentication type. Unknown authentication type %s" % auth)
+ self._module.fail_json(
+ msg="Failed to query authentication type. Unknown authentication type %s"
+ % auth
+ )
except Exception as e:
- self._module.fail_json(msg="Unhandled error while querying authentication type. %s" % (e))
+ self._module.fail_json(
+ msg="Unhandled error while querying authentication type. %s" % (e)
+ )
def get_usergroups_by_name(self, usrgrps):
params = {
- 'output': ['usrgrpid', 'name', 'gui_access'],
- 'filter': {
- 'name': usrgrps
- }
+ "output": ["usrgrpid", "name", "gui_access"],
+ "filter": {"name": usrgrps},
}
res = self._zapi.usergroup.get(params)
if res:
- ids = [{'usrgrpid': g['usrgrpid']} for g in res]
+ ids = [{"usrgrpid": g["usrgrpid"]} for g in res]
# User can be created password-less only when all groups are of non-internal
# authentication types
# 0 = use system default authentication method
@@ -346,199 +334,248 @@ class User(ZabbixBase):
# 2 = use LDAP authentication
# 3 = disable access to the frontend
- if bool([g for g in res if g['gui_access'] == '1']):
+ if bool([g for g in res if g["gui_access"] == "1"]):
require_password = True
- elif bool([g for g in res if g['gui_access'] == '2' or g['gui_access'] == '3']):
+ elif bool(
+ [g for g in res if g["gui_access"] == "2" or g["gui_access"] == "3"]
+ ):
require_password = False
- elif bool([g for g in res if g['gui_access'] == '0']):
+ elif bool([g for g in res if g["gui_access"] == "0"]):
# Zabbix API for versions < 5.2 does not have a way to query the default auth type
# so we must assume its set to internal
- if LooseVersion(self._zbx_api_version) >= LooseVersion('5.2'):
- default_authentication = self.get_default_authentication()
- require_password = True if default_authentication == 'internal' else False
- else:
- default_authentication = "internal"
- require_password = True
+ default_authentication = self.get_default_authentication()
+ require_password = (
+ True if default_authentication == "internal" else False
+ )
- not_found_groups = set(usrgrps) - set([g['name'] for g in res])
+ not_found_groups = set(usrgrps) - set([g["name"] for g in res])
if not_found_groups:
- self._module.fail_json(msg='User groups not found: %s' % not_found_groups)
+ self._module.fail_json(
+ msg="User groups not found: %s" % not_found_groups
+ )
return ids, require_password
else:
- self._module.fail_json(msg='No user groups found')
+ self._module.fail_json(msg="No user groups found")
def check_user_exist(self, username):
- zbx_user = self._zapi.user.get({'output': 'extend', 'filter': {self.username_key(): username},
- 'getAccess': True, 'selectMedias': 'extend',
- 'selectUsrgrps': 'extend'})
+ zbx_user = self._zapi.user.get(
+ {
+ "output": "extend",
+ "filter": {"username": username},
+ "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'})
+ 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']
- user_media['mediatype'] = media_type['type']
- break
- else:
- if media_type['name'] == user_media['mediatype']:
- user_media['mediatypeid'] = media_type['mediatypeid']
- user_media['mediatype'] = media_type['type']
- break
- if 'mediatypeid' not in user_media:
- self._module.fail_json(msg="Media type not found: %s" % user_media['mediatype'])
+ if media_type["name"] == user_media["mediatype"]:
+ user_media["mediatypeid"] = media_type["mediatypeid"]
+ user_media["mediatype"] = media_type["type"]
+ break
+ if "mediatypeid" not in user_media:
+ self._module.fail_json(
+ msg="Media type not found: %s" % user_media["mediatype"]
+ )
else:
- if user_media['mediatype'] == '0': # E-Mail
+ if user_media["mediatype"] == "0": # E-Mail
# Because user media sendto parameter is raw in parameters specs perform explicit check on type
- if not (isinstance(user_media['sendto'], list) or isinstance(user_media['sendto'], str)):
- self._module.fail_json('For Email media type sendto parameter must be of type list or str.')
- if isinstance(user_media['sendto'], str):
+ if not (
+ isinstance(user_media["sendto"], list)
+ or isinstance(user_media["sendto"], str)
+ ):
+ self._module.fail_json(
+ "For Email media type sendto parameter must be of type list or str."
+ )
+ if isinstance(user_media["sendto"], str):
# sendto should be a list for Email media type
- user_media['sendto'] = [user_media['sendto']]
+ user_media["sendto"] = [user_media["sendto"]]
else:
- if not isinstance(user_media['sendto'], str):
- self._module.fail_json(user_media)
- self._module.fail_json('For any other than Email media type sendto parameter must be of type str.')
- 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'
+ if not isinstance(user_media["sendto"], str):
+ self._module.fail_json(
+ "For any other than Email media type sendto parameter must be of type str."
+ )
+ 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))
+ severity_binary_number = severity_binary_number + "0"
+ user_media["severity"] = str(int(severity_binary_number, 2))
- if user_media['active']:
- user_media['active'] = '0'
+ if user_media["active"]:
+ user_media["active"] = "0"
else:
- user_media['active'] = '1'
+ user_media["active"] = "1"
return copy_user_medias
def get_roleid_by_name(self, role_name):
- roles = self._zapi.role.get({'output': 'extend'})
+ roles = self._zapi.role.get({"output": "extend"})
for role in roles:
- if role['name'] == role_name:
- return role['roleid']
+ if role["name"] == role_name:
+ return role["roleid"]
self._module.fail_json(msg="Role not found: %s" % role_name)
- def user_parameter_difference_check(self, zbx_user, username, name, surname, user_group_ids, passwd, lang, theme,
- autologin, autologout, refresh, rows_per_page, url, user_medias, user_type,
- timezone, role_name, override_passwd):
+ def user_parameter_difference_check(
+ self,
+ zbx_user,
+ username,
+ name,
+ surname,
+ user_group_ids,
+ passwd,
+ lang,
+ theme,
+ autologin,
+ autologout,
+ refresh,
+ rows_per_page,
+ url,
+ user_medias,
+ timezone,
+ role_name,
+ override_passwd,
+ ):
# 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'])
- existing_data['user_medias'] = existing_data['medias']
- for del_key in ['medias', 'attempt_clock', 'attempt_failed', 'attempt_ip', 'debug_mode', 'users_status',
- 'gui_access']:
+ for usrgrp in existing_data["usrgrps"]:
+ usrgrpids.append({"usrgrpid": usrgrp["usrgrpid"]})
+ existing_data["usrgrps"] = sorted(usrgrpids, key=lambda x: x["usrgrpid"])
+ existing_data["user_medias"] = existing_data["medias"]
+ for del_key in [
+ "medias",
+ "attempt_clock",
+ "attempt_failed",
+ "attempt_ip",
+ "debug_mode",
+ "users_status",
+ "gui_access",
+ ]:
del existing_data[del_key]
- if 'user_medias' in existing_data and existing_data['user_medias']:
- for user_media in existing_data['user_medias']:
- for del_key in ['mediaid', 'userid']:
+ if "user_medias" in existing_data and existing_data["user_medias"]:
+ 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'],
- self.username_key(): username,
- '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,
+ "userid": zbx_user[0]["userid"],
+ "username": username,
+ "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,
}
if user_medias:
- request_data['user_medias'] = user_medias
+ request_data["user_medias"] = user_medias
else:
- if 'user_medias' in existing_data and existing_data['user_medias']:
- del existing_data['user_medias']
+ if "user_medias" in existing_data and existing_data["user_medias"]:
+ del existing_data["user_medias"]
if override_passwd:
- request_data['passwd'] = passwd
+ request_data["passwd"] = passwd
- # The type key has changed to roleid key since Zabbix 5.2
- if LooseVersion(self._zbx_api_version) < LooseVersion('5.2'):
- request_data['type'] = user_type
- else:
- request_data['roleid'] = self.get_roleid_by_name(role_name) if role_name else None
- request_data['timezone'] = timezone
+ request_data["roleid"] = (
+ self.get_roleid_by_name(role_name) if role_name else None
+ )
+ request_data["timezone"] = timezone
request_data, del_keys = helper_normalize_data(request_data)
existing_data, _del_keys = helper_normalize_data(existing_data, del_keys)
user_parameter_difference_check_result = True
diff_dict = {}
- if not zabbix_utils.helper_compare_dictionaries(request_data, existing_data, diff_dict):
+ if not zabbix_utils.helper_compare_dictionaries(
+ request_data, existing_data, diff_dict
+ ):
user_parameter_difference_check_result = False
- if LooseVersion(self._zbx_api_version) >= LooseVersion('6.4'):
+ if LooseVersion(self._zbx_api_version) >= LooseVersion("6.4"):
if user_medias:
- request_data['medias'] = user_medias
- del request_data['user_medias']
+ request_data["medias"] = user_medias
+ del request_data["user_medias"]
- diff_params = {
- "before": existing_data,
- "after": request_data
- }
+ diff_params = {"before": existing_data, "after": request_data}
return user_parameter_difference_check_result, diff_params
- def add_user(self, username, name, surname, user_group_ids, passwd, lang, theme, autologin, autologout, refresh,
- rows_per_page, url, user_medias, user_type, require_password, timezone, role_name):
-
- if role_name is None and LooseVersion(self._zbx_api_version) >= LooseVersion('5.2'):
- # This variable is to set the default value because the module must have a backward-compatible.
- # The default value will be removed at the version 2.0.0.
- # https://github.com/ansible-collections/community.zabbix/pull/382
+ def add_user(
+ self,
+ username,
+ name,
+ surname,
+ user_group_ids,
+ passwd,
+ lang,
+ theme,
+ autologin,
+ autologout,
+ refresh,
+ rows_per_page,
+ url,
+ user_medias,
+ require_password,
+ timezone,
+ role_name,
+ ):
+
+ if role_name is None:
role_name = "User role"
user_ids = {}
request_data = {
- self.username_key(): username,
- '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,
+ "username": username,
+ "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,
}
if user_medias:
- if LooseVersion(self._zbx_api_version) <= LooseVersion('6.2'):
- request_data['user_medias'] = user_medias
+ if LooseVersion(self._zbx_api_version) <= LooseVersion("6.2"):
+ request_data["user_medias"] = user_medias
else:
- request_data['medias'] = user_medias
+ request_data["medias"] = user_medias
- if LooseVersion(self._zbx_api_version) < LooseVersion('4.0') or require_password:
- request_data['passwd'] = passwd
+ if (require_password):
+ request_data["passwd"] = passwd
# The type key has changed to roleid key since Zabbix 5.2
- if LooseVersion(self._zbx_api_version) < LooseVersion('5.2'):
- request_data['type'] = user_type
- else:
- request_data['roleid'] = self.get_roleid_by_name(role_name)
- request_data['timezone'] = timezone
+ request_data["roleid"] = self.get_roleid_by_name(role_name)
+ request_data["timezone"] = timezone
request_data, _del_keys = helper_normalize_data(request_data)
@@ -547,79 +584,84 @@ class User(ZabbixBase):
try:
user_ids = self._zapi.user.create(request_data)
except Exception as e:
- self._module.fail_json(msg="Failed to create user %s: %s" % (username, e))
+ self._module.fail_json(
+ msg="Failed to create user %s: %s" % (username, e)
+ )
else:
- diff_params = {
- "before": "",
- "after": request_data
- }
+ diff_params = {"before": "", "after": request_data}
return user_ids, diff_params
- def update_user(self, zbx_user, username, name, surname, user_group_ids, passwd, lang, theme, autologin, autologout,
- refresh, rows_per_page, url, user_medias, user_type, timezone, role_name, override_passwd):
+ def update_user(
+ self,
+ zbx_user,
+ username,
+ name,
+ surname,
+ user_group_ids,
+ passwd,
+ lang,
+ theme,
+ autologin,
+ autologout,
+ refresh,
+ rows_per_page,
+ url,
+ user_medias,
+ timezone,
+ role_name,
+ override_passwd,
+ current_passwd,
+ ):
user_ids = {}
request_data = {
- 'userid': zbx_user[0]['userid'],
- self.username_key(): username,
- '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,
+ "userid": zbx_user[0]["userid"],
+ "username": username,
+ "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,
}
if override_passwd:
- request_data['passwd'] = passwd
+ request_data["passwd"] = passwd
+ if current_passwd:
+ request_data["current_passwd"] = current_passwd
- # The type key has changed to roleid key since Zabbix 5.2
- if LooseVersion(self._zbx_api_version) < LooseVersion('5.2'):
- request_data['type'] = user_type
- else:
- request_data['roleid'] = self.get_roleid_by_name(role_name) if role_name else None
- request_data['timezone'] = timezone
+ request_data["roleid"] = (
+ self.get_roleid_by_name(role_name) if role_name else None
+ )
+ request_data["timezone"] = timezone
request_data, _del_keys = helper_normalize_data(request_data)
- # 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" % (username, e))
-
+ if LooseVersion(self._zbx_api_version) < LooseVersion("6.4"):
try:
if user_medias:
- 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" % (username, e))
-
- if (LooseVersion(self._zbx_api_version) >= LooseVersion('3.4')
- and LooseVersion(self._zbx_api_version) < LooseVersion('6.4')):
- try:
- if user_medias:
- request_data['user_medias'] = user_medias
+ 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" % (username, e))
+ self._module.fail_json(
+ msg="Failed to update user %s: %s" % (username, e)
+ )
- if LooseVersion(self._zbx_api_version) >= LooseVersion('6.4'):
+ if LooseVersion(self._zbx_api_version) >= LooseVersion("6.4"):
try:
if user_medias:
- request_data['medias'] = user_medias
+ request_data["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" % (username, e))
+ self._module.fail_json(
+ msg="Failed to update user %s: %s" % (username, e)
+ )
return user_ids
@@ -629,107 +671,123 @@ class User(ZabbixBase):
if not self._module.check_mode:
try:
- user_ids = self._zapi.user.delete([zbx_user[0]['userid']])
+ 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" % (username, e))
+ self._module.fail_json(
+ msg="Failed to delete user %s: %s" % (username, e)
+ )
else:
- diff_params = {
- "before": zbx_user[0],
- "after": ""
- }
+ diff_params = {"before": zbx_user[0], "after": ""}
return user_ids, diff_params
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
- argument_spec.update(dict(
- username=dict(type='str', required=True, aliases=['alias']),
- name=dict(type='str'),
- surname=dict(type='str'),
- usrgrps=dict(type='list'),
- passwd=dict(type='str', required=False, no_log=True),
- override_passwd=dict(type='bool', required=False, default=False, no_log=False),
- lang=dict(type='str', 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', 'default']),
- theme=dict(type='str', choices=['default', 'blue-theme', 'dark-theme']),
- autologin=dict(type='bool'),
- autologout=dict(type='str'),
- refresh=dict(type='str'),
- rows_per_page=dict(type='str'),
- after_login_url=dict(type='str'),
- user_medias=dict(type='list', elements='dict',
- options=dict(mediatype=dict(type='str', default='Email'),
- sendto=dict(type='raw', 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))),
- timezone=dict(type='str'),
- role_name=dict(type='str'),
- type=dict(type='str', choices=['Zabbix user', 'Zabbix admin', 'Zabbix super admin']),
- state=dict(type='str', default="present", choices=['present', 'absent'])
- ))
+ argument_spec.update(
+ dict(
+ username=dict(type="str", required=True),
+ name=dict(type="str"),
+ surname=dict(type="str"),
+ usrgrps=dict(type="list", elements="str"),
+ passwd=dict(type="str", required=False, no_log=True),
+ override_passwd=dict(
+ type="bool", required=False, default=False, no_log=False
+ ),
+ current_passwd=dict(type="str", required=False, no_log=True),
+ lang=dict(
+ type="str",
+ 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",
+ "default",
+ ],
+ ),
+ theme=dict(type="str", choices=["default", "blue-theme", "dark-theme"]),
+ autologin=dict(type="bool"),
+ autologout=dict(type="str"),
+ refresh=dict(type="str"),
+ rows_per_page=dict(type="str"),
+ after_login_url=dict(type="str"),
+ user_medias=dict(
+ type="list",
+ elements="dict",
+ options=dict(
+ mediatype=dict(type="str", default="Email"),
+ sendto=dict(type="raw", 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),
+ ),
+ ),
+ timezone=dict(type="str"),
+ role_name=dict(type="str"),
+ state=dict(type="str", default="present", choices=["present", "absent"]),
+ )
+ )
module = AnsibleModule(
argument_spec=argument_spec,
- required_if=[
- ['state', 'present', ['usrgrps']]
- ],
- supports_check_mode=True
+ required_if=[["state", "present", ["usrgrps"]]],
+ supports_check_mode=True,
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- username = module.params['username']
- 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']
- timezone = module.params['timezone']
- role_name = module.params['role_name']
- state = module.params['state']
+ username = module.params["username"]
+ name = module.params["name"]
+ surname = module.params["surname"]
+ usrgrps = module.params["usrgrps"]
+ passwd = module.params["passwd"]
+ override_passwd = module.params["override_passwd"]
+ current_passwd = module.params["current_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"]
+ timezone = module.params["timezone"]
+ role_name = module.params["role_name"]
+ state = module.params["state"]
if autologin is not None:
if autologin:
- autologin = '1'
+ 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] if user_type else None
+ autologin = "0"
user = User(module)
@@ -738,31 +796,78 @@ def main():
user_ids = {}
zbx_user = user.check_user_exist(username)
- if state == 'present':
+ if state == "present":
user_group_ids, require_password = user.get_usergroups_by_name(usrgrps)
- if LooseVersion(user._zbx_api_version) < LooseVersion('4.0') or require_password:
+ if (require_password):
if passwd is None:
- module.fail_json(msg='User password is required. One or more groups are not LDAP based.')
+ module.fail_json(
+ msg="User password is required. One or more groups are not LDAP based."
+ )
if zbx_user:
- diff_check_result, diff_params = user.user_parameter_difference_check(zbx_user, username, name, surname,
- user_group_ids, passwd, lang, theme,
- autologin, autologout, refresh,
- rows_per_page, after_login_url,
- user_medias, user_type, timezone,
- role_name, override_passwd)
+ diff_check_result, diff_params = user.user_parameter_difference_check(
+ zbx_user,
+ username,
+ name,
+ surname,
+ user_group_ids,
+ passwd,
+ lang,
+ theme,
+ autologin,
+ autologout,
+ refresh,
+ rows_per_page,
+ after_login_url,
+ user_medias,
+ timezone,
+ role_name,
+ override_passwd,
+ )
if not module.check_mode and diff_check_result:
- user_ids = user.update_user(zbx_user, username, name, surname, user_group_ids, passwd, lang,
- theme, autologin, autologout, refresh, rows_per_page, after_login_url,
- user_medias, user_type, timezone, role_name, override_passwd)
+ user_ids = user.update_user(
+ zbx_user,
+ username,
+ name,
+ surname,
+ user_group_ids,
+ passwd,
+ lang,
+ theme,
+ autologin,
+ autologout,
+ refresh,
+ rows_per_page,
+ after_login_url,
+ user_medias,
+ timezone,
+ role_name,
+ override_passwd,
+ current_passwd,
+ )
else:
diff_check_result = True
- user_ids, diff_params = user.add_user(username, name, surname, user_group_ids, passwd, lang, theme, autologin,
- autologout, refresh, rows_per_page, after_login_url, user_medias,
- user_type, require_password, timezone, role_name)
-
- if state == 'absent':
+ user_ids, diff_params = user.add_user(
+ username,
+ name,
+ surname,
+ user_group_ids,
+ passwd,
+ lang,
+ theme,
+ autologin,
+ autologout,
+ refresh,
+ rows_per_page,
+ after_login_url,
+ user_medias,
+ require_password,
+ timezone,
+ role_name,
+ )
+
+ if state == "absent":
if zbx_user:
diff_check_result = True
user_ids, diff_params = user.delete_user(zbx_user, username)
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_user_directory.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_user_directory.py
index 818fe98c0..b383fcdcf 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_user_directory.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_user_directory.py
@@ -4,10 +4,11 @@
# 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'''
+DOCUMENTATION = r"""
---
module: zabbix_user_directory
short_description: Create/update/delete Zabbix user directories
@@ -29,7 +30,7 @@ options:
- This parameter is available since Zabbix 6.4.
required: false
type: str
- choices: ['ldap', 'saml']
+ choices: ["ldap", "saml"]
provision_status:
description:
- User directory provisioning status.
@@ -63,7 +64,7 @@ options:
- User directory description.
required: false
type: str
- default: ''
+ default: ""
group_membership:
description:
- LDAP property containing groups of user. E.g. I(memberOf)
@@ -150,7 +151,7 @@ options:
- LDAP bind distinguished name string. Can be empty for anonymous binding.
required: false
type: str
- default: ''
+ default: ""
idp_entityid:
description:
- SAML URI that identifies the IdP in SAML messages.
@@ -167,7 +168,7 @@ options:
type: str
sso_url:
description:
- - SAML URL of the IdP's SAML SSO service, to which Zabbix will send SAML authentication requests.
+ - SAML URL of the IdP"s SAML SSO service, to which Zabbix will send SAML authentication requests.
- required if C(idp_type) is set to I(saml).
- This parameter is available since Zabbix 6.4.
required: false
@@ -302,27 +303,27 @@ options:
- State of the user directory.
- On C(present), it will create if user directory does not exist or update it if the associated data is different.
- On C(absent) will remove the user directory if it exists.
- choices: ['present', 'absent']
- default: 'present'
+ choices: ["present", "absent"]
+ default: "present"
type: str
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
---
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: Create new user directory or update existing info (Zabbix <= 6.2)
@@ -333,18 +334,18 @@ EXAMPLES = r'''
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_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_user_directory:
state: present
name: TestUserDirectory
- host: 'test.com'
+ host: "test.com"
port: 389
- base_dn: 'ou=Users,dc=example,dc=org'
- search_attribute: 'uid'
- bind_dn: 'cn=ldap_search,dc=example,dc=org'
- description: 'Test user directory'
- search_filter: '(%{attr}=test_user)'
+ base_dn: "ou=Users,dc=example,dc=org"
+ search_attribute: "uid"
+ bind_dn: "cn=ldap_search,dc=example,dc=org"
+ description: "Test user directory"
+ search_filter: "(%{attr}=test_user)"
start_tls: 0
- name: Create new user directory with LDAP IDP or update existing info (Zabbix >= 6.4)
@@ -355,22 +356,22 @@ EXAMPLES = r'''
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_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_user_directory:
state: present
name: TestUserDirectory
idp_type: ldap
- host: 'test.ca'
+ host: "test.ca"
port: 389
- base_dn: 'ou=Users,dc=example,dc=org'
- search_attribute: 'uid'
+ base_dn: "ou=Users,dc=example,dc=org"
+ search_attribute: "uid"
provision_status: true
group_name: cn
group_basedn: ou=Group,dc=example,dc=org
group_member: member
user_ref_attr: uid
- group_filter: '(member=uid=%{ref},ou=Users,dc=example,dc=com)'
+ group_filter: "(member=uid=%{ref},ou=Users,dc=example,dc=com)"
user_username: first_name
user_lastname: last_name
provision_media:
@@ -391,7 +392,7 @@ EXAMPLES = r'''
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_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_user_directory:
state: present
@@ -414,7 +415,7 @@ EXAMPLES = r'''
role: Guest role
user_groups:
- Guests
-'''
+"""
from ansible.module_utils.basic import AnsibleModule
@@ -426,220 +427,305 @@ import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabb
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
- argument_spec.update(dict(
- name=dict(type='str', required=True),
- idp_type=dict(type='str', required=False, choices=['ldap', 'saml']),
- host=dict(type='str', required=False),
- port=dict(type='int', required=False),
- base_dn=dict(type='str', required=False),
- search_attribute=dict(type='str', required=False),
- bind_dn=dict(type='str', required=False, default=''),
- bind_password=dict(type='str', required=False, no_log=True),
- description=dict(type='str', required=False, default=''),
- search_filter=dict(type='str', default='(%{attr}=%{user})', required=False),
- start_tls=dict(type='int', required=False, choices=[0, 1], default=0),
- idp_entityid=dict(type='str', required=False),
- sp_entityid=dict(type='str', required=False),
- sso_url=dict(type='str', required=False),
- slo_url=dict(type='str', required=False),
- username_attribute=dict(type='str', required=False),
- nameid_format=dict(type='str', required=False),
- scim_status=dict(type='bool', required=False, default=False),
- encrypt_nameid=dict(type='bool', required=False, default=False),
- encrypt_assertions=dict(type='bool', required=False, default=False),
- sign_messages=dict(type='bool', required=False, default=False),
- sign_assertions=dict(type='bool', required=False, default=False),
- sign_authn_requests=dict(type='bool', required=False, default=False),
- sign_logout_requests=dict(type='bool', required=False, default=False),
- sign_logout_responses=dict(type='bool', required=False, default=False),
- provision_status=dict(type='bool', required=False, default=False),
- group_basedn=dict(type='str', required=False),
- group_filter=dict(type='str', required=False),
- group_member=dict(type='str', required=False),
- group_membership=dict(type='str', required=False),
- group_name=dict(type='str', required=False),
- user_lastname=dict(type='str', required=False),
- user_ref_attr=dict(type='str', required=False),
- user_username=dict(type='str', required=False),
- provision_media=dict(
- type='list',
- required=False,
- elements='dict',
- options=dict(
- name=dict(type='str', required=True),
- mediatype=dict(type='str', required=True),
- attribute=dict(type='str', required=True)
- )
- ),
- provision_groups=dict(
- type='list',
- required=False,
- elements='dict',
- options=dict(
- name=dict(type='str', required=True),
- role=dict(type='str', required=True),
- user_groups=dict(type='list', elements='str', required=True)
- )
- ),
- state=dict(type='str', default='present', choices=['present', 'absent'])
- ))
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True
+ argument_spec.update(
+ dict(
+ name=dict(type="str", required=True),
+ idp_type=dict(type="str", required=False, choices=["ldap", "saml"]),
+ host=dict(type="str", required=False),
+ port=dict(type="int", required=False),
+ base_dn=dict(type="str", required=False),
+ search_attribute=dict(type="str", required=False),
+ bind_dn=dict(type="str", required=False, default=""),
+ bind_password=dict(type="str", required=False, no_log=True),
+ description=dict(type="str", required=False, default=""),
+ search_filter=dict(type="str", default="(%{attr}=%{user})", required=False),
+ start_tls=dict(type="int", required=False, choices=[0, 1], default=0),
+ idp_entityid=dict(type="str", required=False),
+ sp_entityid=dict(type="str", required=False),
+ sso_url=dict(type="str", required=False),
+ slo_url=dict(type="str", required=False),
+ username_attribute=dict(type="str", required=False),
+ nameid_format=dict(type="str", required=False),
+ scim_status=dict(type="bool", required=False, default=False),
+ encrypt_nameid=dict(type="bool", required=False, default=False),
+ encrypt_assertions=dict(type="bool", required=False, default=False),
+ sign_messages=dict(type="bool", required=False, default=False),
+ sign_assertions=dict(type="bool", required=False, default=False),
+ sign_authn_requests=dict(type="bool", required=False, default=False),
+ sign_logout_requests=dict(type="bool", required=False, default=False),
+ sign_logout_responses=dict(type="bool", required=False, default=False),
+ provision_status=dict(type="bool", required=False, default=False),
+ group_basedn=dict(type="str", required=False),
+ group_filter=dict(type="str", required=False),
+ group_member=dict(type="str", required=False),
+ group_membership=dict(type="str", required=False),
+ group_name=dict(type="str", required=False),
+ user_lastname=dict(type="str", required=False),
+ user_ref_attr=dict(type="str", required=False),
+ user_username=dict(type="str", required=False),
+ provision_media=dict(
+ type="list",
+ required=False,
+ elements="dict",
+ options=dict(
+ name=dict(type="str", required=True),
+ mediatype=dict(type="str", required=True),
+ attribute=dict(type="str", required=True),
+ ),
+ ),
+ provision_groups=dict(
+ type="list",
+ required=False,
+ elements="dict",
+ options=dict(
+ name=dict(type="str", required=True),
+ role=dict(type="str", required=True),
+ user_groups=dict(type="list", elements="str", required=True),
+ ),
+ ),
+ state=dict(type="str", default="present", choices=["present", "absent"]),
+ )
)
- ''' For future when < 6.4 disappears we should use this, now we cannot do this as at this point Zabbix version is unknown
+
+ module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
+ """ For future when < 6.4 disappears we should use this, now we cannot do this as at this point Zabbix version is unknown
module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=True,
required_if=[
- ('state', 'present', ('idp_type',)),
- ('idp_type', 'ldap', ('host', 'port', 'base_dn', 'search_attribute'), False),
- ('idp_type', 'saml', ('idp_entityid', 'sp_entityid', 'sso_url', 'username_attribute'), False),
- ('provision_status', 'true', ('provision_groups'))
+ ("state", "present", ("idp_type",)),
+ ("idp_type", "ldap", ("host", "port", "base_dn", "search_attribute"), False),
+ ("idp_type", "saml", ("idp_entityid", "sp_entityid", "sso_url", "username_attribute"), False),
+ ("provision_status", "true", ("provision_groups"))
]
)
- '''
-
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- parameters = {
- 'name': module.params['name']
- }
- for p in ['host', 'port', 'base_dn', 'search_attribute', 'bind_dn', 'bind_password', 'description', 'start_tls']:
+ """
+
+ parameters = {"name": module.params["name"]}
+ for p in [
+ "host",
+ "port",
+ "base_dn",
+ "search_attribute",
+ "bind_dn",
+ "bind_password",
+ "description",
+ "start_tls",
+ ]:
if module.params[p]:
- if p in ['port', 'start_tls']:
+ if p in ["port", "start_tls"]:
parameters[p] = str(module.params[p])
else:
parameters[p] = module.params[p]
- state = module.params['state']
+ state = module.params["state"]
user_directory = ZabbixBase(module)
- if LooseVersion(user_directory._zbx_api_version) < LooseVersion('6.2'):
- module.fail_json(msg='Zabbix < 6.2 does not support user directories.')
+ if LooseVersion(user_directory._zbx_api_version) < LooseVersion("6.2"):
+ module.fail_json(msg="Zabbix < 6.2 does not support user directories.")
- if LooseVersion(user_directory._zbx_api_version) < LooseVersion('6.4'):
- parameters['search_filter'] = module.params['search_filter']
- directory = user_directory._zapi.userdirectory.get({'filter': {'name': parameters['name']}})
+ if LooseVersion(user_directory._zbx_api_version) < LooseVersion("6.4"):
+ parameters["search_filter"] = module.params["search_filter"]
+ directory = user_directory._zapi.userdirectory.get(
+ {"filter": {"name": parameters["name"]}}
+ )
else:
# Zabbix >= 6.4
# Mandatory parameters check
- if state == 'present' and not module.params['idp_type']:
- module.fail_json('"idp_type" parameter must be provided when state is "present"')
- if module.params['idp_type']:
- if (module.params['idp_type'] == 'ldap'
- and (not module.params['host'] or not module.params['port'] or not module.params['base_dn'] or not module.params['search_attribute'])):
- module.fail_json('"host", "port", "base_dn", "search_attribute" must be provided when idp_type is "ldap"')
- if (module.params['idp_type'] == 'saml'
- and (not module.params['idp_entityid'] or not module.params['sp_entityid']
- or not module.params['sso_url'] or not module.params['username_attribute'])):
- module.fail_json('"idp_entityid", "sp_entityid", "sso_url", "username_attribute" must be provided when idp_type is "ldap"')
+ if state == "present" and not module.params["idp_type"]:
+ module.fail_json(
+ "'idp_type' parameter must be provided when state is 'present'"
+ )
+ if module.params["idp_type"]:
+ if module.params["idp_type"] == "ldap" and (
+ not module.params["host"]
+ or not module.params["port"]
+ or not module.params["base_dn"]
+ or not module.params["search_attribute"]
+ ):
+ module.fail_json(
+ "'host', 'port', 'base_dn', 'search_attribute' must be provided when idp_type is 'ldap'"
+ )
+ if module.params["idp_type"] == "saml" and (
+ not module.params["idp_entityid"]
+ or not module.params["sp_entityid"]
+ or not module.params["sso_url"]
+ or not module.params["username_attribute"]
+ ):
+ module.fail_json(
+ "'idp_entityid', 'sp_entityid', 'sso_url', 'username_attribute' must be provided when idp_type is 'ldap'"
+ )
directory = user_directory._zapi.userdirectory.get(
{
- 'search': {'name': parameters['name']},
- 'selectProvisionMedia': 'extend',
- 'selectProvisionGroups': 'extend'
- })
- parameters['idp_type'] = str(zabbix_utils.helper_to_numeric_value(['', 'ldap', 'saml'], module.params['idp_type']))
- if parameters['idp_type'] == '1':
+ "search": {"name": parameters["name"]},
+ "selectProvisionMedia": "extend",
+ "selectProvisionGroups": "extend",
+ }
+ )
+ parameters["idp_type"] = str(
+ zabbix_utils.helper_to_numeric_value(
+ ["", "ldap", "saml"], module.params["idp_type"]
+ )
+ )
+ if parameters["idp_type"] == "1":
# idp_type is ldap
- parameters['search_filter'] = module.params['search_filter']
- elif parameters['idp_type'] == '2':
+ parameters["search_filter"] = module.params["search_filter"]
+ elif parameters["idp_type"] == "2":
# idp_type is saml
- for p in ['idp_entityid', 'sso_url', 'username_attribute', 'sp_entityid', 'slo_url', 'nameid_format']:
+ for p in [
+ "idp_entityid",
+ "sso_url",
+ "username_attribute",
+ "sp_entityid",
+ "slo_url",
+ "nameid_format",
+ ]:
# str parameters
if module.params[p]:
parameters[p] = module.params[p]
- for p in ['scim_status', 'encrypt_nameid', 'encrypt_assertions', 'sign_messages', 'sign_assertions',
- 'sign_authn_requests', 'sign_logout_requests', 'sign_logout_responses']:
+ for p in [
+ "scim_status",
+ "encrypt_nameid",
+ "encrypt_assertions",
+ "sign_messages",
+ "sign_assertions",
+ "sign_authn_requests",
+ "sign_logout_requests",
+ "sign_logout_responses",
+ ]:
# boolean parameters
if module.params[p]:
parameters[p] = str(int(module.params[p]))
- if module.params['provision_status']:
- parameters['provision_status'] = int(module.params['provision_status'])
+ if module.params["provision_status"]:
+ parameters["provision_status"] = int(module.params["provision_status"])
- if module.params['provision_media']:
- if 'provision_status' not in parameters or not parameters['provision_status']:
- module.fail_json('"provision_status" must be True to define "provision_media"')
- parameters['provision_media'] = []
- for media in module.params['provision_media']:
- media_type_name = media['mediatype']
- media_type_ids = user_directory._zapi.mediatype.get({'filter': {'name': media_type_name}})
+ if module.params["provision_media"]:
+ if (
+ "provision_status" not in parameters
+ or not parameters["provision_status"]
+ ):
+ module.fail_json(
+ "'provision_status' must be True to define 'provision_media'"
+ )
+ parameters["provision_media"] = []
+ for media in module.params["provision_media"]:
+ media_type_name = media["mediatype"]
+ media_type_ids = user_directory._zapi.mediatype.get(
+ {"filter": {"name": media_type_name}}
+ )
if not media_type_ids:
- module.fail_json('Mediatype "%s" cannot be found' % media_type_name)
- parameters['provision_media'].append(
+ module.fail_json("Mediatype '%s' cannot be found" % media_type_name)
+ parameters["provision_media"].append(
{
- 'name': media['name'],
- 'mediatypeid': media_type_ids[0]['mediatypeid'],
- 'attribute': media['attribute']
+ "name": media["name"],
+ "mediatypeid": media_type_ids[0]["mediatypeid"],
+ "attribute": media["attribute"],
}
)
- if module.params['provision_groups']:
- if 'provision_status' not in parameters or not parameters['provision_status']:
- module.fail_json('"provision_status" must be True to define "provision_groups"')
- parameters['provision_groups'] = []
- for group in module.params['provision_groups']:
- role_name = group['role']
- role_ids = user_directory._zapi.role.get({'filter': {'name': role_name}})
+ if module.params["provision_groups"]:
+ if (
+ "provision_status" not in parameters
+ or not parameters["provision_status"]
+ ):
+ module.fail_json(
+ "'provision_status' must be True to define 'provision_groups'"
+ )
+ parameters["provision_groups"] = []
+ for group in module.params["provision_groups"]:
+ role_name = group["role"]
+ role_ids = user_directory._zapi.role.get(
+ {"filter": {"name": role_name}}
+ )
if not role_ids:
- module.fail_json('Role "%s" cannot be found' % role_name)
+ module.fail_json("Role '%s' cannot be found" % role_name)
user_groups = []
- for user_group in group['user_groups']:
- ug_ids = user_directory._zapi.usergroup.get({'filter': {'name': user_group}})
+ for user_group in group["user_groups"]:
+ ug_ids = user_directory._zapi.usergroup.get(
+ {"filter": {"name": user_group}}
+ )
if not ug_ids:
- module.fail_json('User group "%s" cannot be found' % user_group)
- user_groups.append({'usrgrpid': ug_ids[0]['usrgrpid']})
- parameters['provision_groups'].append(
+ module.fail_json("User group '%s' cannot be found" % user_group)
+ user_groups.append({"usrgrpid": ug_ids[0]["usrgrpid"]})
+ parameters["provision_groups"].append(
{
- 'name': group['name'],
- 'roleid': role_ids[0]['roleid'],
- 'user_groups': user_groups
+ "name": group["name"],
+ "roleid": role_ids[0]["roleid"],
+ "user_groups": user_groups,
}
)
- for p in ['group_basedn', 'group_filter', 'group_member', 'group_membership', 'group_name', 'group_name',
- 'user_lastname', 'user_ref_attr', 'user_username']:
+ for p in [
+ "group_basedn",
+ "group_filter",
+ "group_member",
+ "group_membership",
+ "group_name",
+ "group_name",
+ "user_lastname",
+ "user_ref_attr",
+ "user_username",
+ ]:
if module.params[p]:
parameters[p] = module.params[p]
if not directory:
# No User Directory found with given name
- if state == 'absent':
- module.exit_json(changed=False, msg='User directory not found. Not changed: %s' % parameters['name'])
+ if state == "absent":
+ module.exit_json(
+ changed=False,
+ msg="User directory not found. Not changed: %s" % parameters["name"],
+ )
- elif state == 'present':
+ elif state == "present":
if module.check_mode:
module.exit_json(changed=True)
else:
user_directory._zapi.userdirectory.create(parameters)
- module.exit_json(changed=True, result='Successfully added user directory %s' % parameters['name'])
+ module.exit_json(
+ changed=True,
+ result="Successfully added user directory %s" % parameters["name"],
+ )
else:
# User Directory with given name exists
- if state == 'absent':
- user_directory._zapi.userdirectory.delete([directory[0]['userdirectoryid']])
- module.exit_json(changed=True, result='Successfully deleted user directory %s' % parameters['name'])
- elif state == 'present':
+ if state == "absent":
+ if module.check_mode:
+ module.exit_json(changed=True)
+ user_directory._zapi.userdirectory.delete([directory[0]["userdirectoryid"]])
+ module.exit_json(
+ changed=True,
+ result="Successfully deleted user directory %s" % parameters["name"],
+ )
+ elif state == "present":
diff_dict = {}
- if 'provision_status' in directory[0]:
+ if "provision_status" in directory[0]:
# Zabbix API returns provision_status as str we need it as int to correctly compare
- directory[0]['provision_status'] = int(directory[0]['provision_status'])
- if zabbix_utils.helper_compare_dictionaries(parameters, directory[0], diff_dict):
- parameters['userdirectoryid'] = directory[0]['userdirectoryid']
+ directory[0]["provision_status"] = int(directory[0]["provision_status"])
+ if zabbix_utils.helper_compare_dictionaries(
+ parameters, directory[0], diff_dict
+ ):
+ parameters["userdirectoryid"] = directory[0]["userdirectoryid"]
+ if module.check_mode:
+ module.exit_json(changed=True)
user_directory._zapi.userdirectory.update(parameters)
- module.exit_json(changed=True, result='Successfully updated user directory %s' % parameters['name'])
+ module.exit_json(
+ changed=True,
+ result="Successfully updated user directory %s"
+ % parameters["name"],
+ )
else:
- module.exit_json(changed=False, result='User directory %s is up-to date' % parameters['name'])
+ module.exit_json(
+ changed=False,
+ result="User directory %s is up-to date" % parameters["name"],
+ )
- module.exit_json(changed=False, result='User directory %s is up-to date' % parameters['name'])
+ module.exit_json(
+ changed=False,
+ result="User directory %s is up-to date" % parameters["name"],
+ )
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_user_info.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_user_info.py
index 8fd0323c4..c71479532 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_user_info.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_user_info.py
@@ -8,7 +8,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
-DOCUMENTATION = '''
+DOCUMENTATION = """
module: zabbix_user_info
short_description: Gather information about Zabbix user
author:
@@ -16,32 +16,30 @@ author:
description:
- This module allows you to search for Zabbix user entries.
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
options:
username:
description:
- - Name of the user alias in Zabbix.
- - username is the unique identifier used and cannot be updated using this module.
- - alias should be replaced with username
- aliases: [ alias ]
+ - User name.
+ - sername is the unique identifier used and cannot be updated using this module.
required: true
type: str
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = '''
+EXAMPLES = """
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: Get zabbix user info
@@ -52,13 +50,13 @@ EXAMPLES = '''
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_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_user_info:
username: example
-'''
+"""
-RETURN = '''
+RETURN = """
zabbix_user:
description: example
returned: always
@@ -103,11 +101,10 @@ zabbix_user:
}
]
}
-'''
+"""
from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.compat.version import LooseVersion
from ansible_collections.community.zabbix.plugins.module_utils.base import ZabbixBase
import ansible_collections.community.zabbix.plugins.module_utils.helpers as zabbix_utils
@@ -117,13 +114,10 @@ class User(ZabbixBase):
def get_user_by_user_username(self, username):
zabbix_user = ""
try:
- data = {'output': 'extend', 'filter': {},
- 'getAccess': True, 'selectMedias': 'extend',
- 'selectUsrgrps': 'extend'}
- if LooseVersion(self._zbx_api_version) >= LooseVersion('5.4'):
- data['filter']['username'] = username
- else:
- data['filter']['alias'] = username
+ data = {"output": "extend", "filter": {},
+ "getAccess": True, "selectMedias": "extend",
+ "selectUsrgrps": "extend"}
+ data["filter"]["username"] = username
zabbix_user = self._zapi.user.get(data)
except Exception as e:
@@ -141,20 +135,14 @@ class User(ZabbixBase):
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- username=dict(type='str', required=True, aliases=['alias']),
+ username=dict(type="str", required=True),
))
module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=True
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- username = module.params['username']
+ username = module.params["username"]
user = User(module)
zabbix_user = user.get_user_by_user_username(username)
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_user_role.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_user_role.py
index 596ef5570..3495f39e1 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_user_role.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_user_role.py
@@ -8,7 +8,7 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
module: zabbix_user_role
short_description: Adds or removes zabbix roles
author:
@@ -16,15 +16,15 @@ author:
description:
- This module adds or removes zabbix roles
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
options:
state:
description:
- State of the user_role.
- On C(present), it will create if user_role does not exist or update the user_role if the associated data is different.
- On C(absent) will remove a user_role if it exists.
- default: 'present'
- choices: ['present', 'absent']
+ default: "present"
+ choices: ["present", "absent"]
type: str
required: false
name:
@@ -47,19 +47,19 @@ options:
required: false
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
# Create user role Operators with ui elements monitoring.hosts
@@ -73,7 +73,7 @@ EXAMPLES = r'''
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_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_user_role:
state: present
@@ -86,21 +86,21 @@ EXAMPLES = r'''
status: 0
- name: "monitoring.maps"
status: 1
-'''
+"""
-RETURN = r'''
+RETURN = r"""
# Return values
msg:
description: The result of the action
type: str
returned: always
- sample: 'No action'
+ sample: "No action"
changed:
description: The consequence of the action
type: bool
returned: always
sample: false
-'''
+"""
from ansible.module_utils.basic import AnsibleModule
@@ -135,7 +135,7 @@ class UserRole(ZabbixBase):
verdict = True
for rule, value in inp.items():
if not isinstance(value, list):
- verdict = verdict and self.__find_val(out.get(rule, ''), value)
+ verdict = verdict and self.__find_val(out.get(rule, ""), value)
else:
if len(value):
if not isinstance(value[0], dict):
@@ -162,10 +162,10 @@ def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- state=dict(type='str', required=False, default='present', choices=['present', 'absent']),
- name=dict(type='str', required=True),
- type=dict(type='str', required=False, choices=["User", "Admin", "Super Admin"], default='User'),
- rules=dict(type='dict', required=False, default={}),
+ state=dict(type="str", required=False, default="present", choices=["present", "absent"]),
+ name=dict(type="str", required=True),
+ type=dict(type="str", required=False, choices=["User", "Admin", "Super Admin"], default="User"),
+ rules=dict(type="dict", required=False, default={}),
))
# the AnsibleModule object
@@ -174,19 +174,12 @@ def main():
supports_check_mode=False
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection '
- 'and will be removed in the next release' % p)
-
- state = module.params['state']
- name = module.params['name']
+ state = module.params["state"]
+ name = module.params["name"]
type = zabbix_utils.helper_to_numeric_value(
- ['', 'user', 'admin', 'super admin'], module.params['type'].lower()
+ ["", "user", "admin", "super admin"], module.params["type"].lower()
)
- rules = module.params['rules']
+ rules = module.params["rules"]
user_role = UserRole(module)
@@ -194,19 +187,19 @@ def main():
if result:
if len(result) == 1:
role = result[0]
- if role['readonly'] != 1:
- roleid = role['roleid']
- if state == 'absent':
+ if role["readonly"] != 1:
+ roleid = role["roleid"]
+ if state == "absent":
result = user_role._zapi.role.delete([f"{roleid}"])
changed = True
msg = "Role deleted"
else:
- if not user_role.is_part_of(rules, role['rules']):
+ if not user_role.is_part_of(rules, role["rules"]):
result = user_role._zapi.role.update({"roleid": roleid, "rules": rules})
changed = True
msg = "Role updated"
else:
- module.fail_json(msg='Too many role matches')
+ module.fail_json(msg="Too many role matches")
else:
user_role._zapi.role.create({
"name": name,
@@ -219,5 +212,5 @@ def main():
module.exit_json(msg=msg, changed=changed)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_usergroup.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_usergroup.py
index b2a341472..14539d932 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_usergroup.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_usergroup.py
@@ -5,9 +5,10 @@
# 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'''
+DOCUMENTATION = r"""
---
module: zabbix_usergroup
short_description: Create/delete/update Zabbix user groups
@@ -18,7 +19,7 @@ description:
author:
- "Tobias Birkefeld (@tcraxs)"
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
options:
name:
description:
@@ -126,13 +127,13 @@ options:
- Tag name.
required: false
type: str
- default: ''
+ default: ""
value:
description:
- Tag value.
required: false
type: str
- default: ''
+ default: ""
userdirectory:
description:
- Authentication user directory when gui_access set to LDAP or System default.
@@ -148,23 +149,22 @@ options:
type: str
default: "present"
choices: [ "present", "absent" ]
-notes:
- - Only Zabbix >= 4.0 is supported.
+
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
# Base create user group example
@@ -176,10 +176,11 @@ EXAMPLES = r'''
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_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_usergroup:
name: ACME
+ userdirectory: LDAP infra 1
state: present
# Base create user group with selected user directory for LDAP authentication
@@ -191,7 +192,7 @@ EXAMPLES = r'''
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_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_usergroup:
name: ACME
@@ -207,7 +208,7 @@ EXAMPLES = r'''
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_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_usergroup:
name: ACME
@@ -222,7 +223,7 @@ EXAMPLES = r'''
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_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_usergroup:
name: ACME
@@ -242,7 +243,7 @@ EXAMPLES = r'''
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_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_usergroup:
name: ACME
@@ -267,7 +268,7 @@ EXAMPLES = r'''
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_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_usergroup:
name: ACME
@@ -289,35 +290,35 @@ EXAMPLES = r'''
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_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_usergroup:
name: ACME
state: absent
-'''
+"""
-RETURN = r'''
+RETURN = r"""
state:
description: User group state at the end of execution.
returned: on success
type: str
- sample: 'present'
+ sample: "present"
usergroup:
description: User group name.
returned: on success
type: str
- sample: 'ACME'
+ sample: "ACME"
usrgrpid:
description: User group id, if created, changed or deleted.
returned: on success
type: str
- sample: '42'
+ sample: "42"
msg:
description: The result of the operation
returned: always
type: str
- sample: 'User group created: ACME, ID: 42'
-'''
+ sample: "User group created: ACME, ID: 42"
+"""
from ansible.module_utils.basic import AnsibleModule
@@ -341,16 +342,15 @@ class Rights(ZabbixBase):
host group matching host group name.
"""
try:
- _hostgroup = self._zapi.hostgroup.get({
- 'output': 'extend',
- 'filter': {'name': [name]}
- })
+ _hostgroup = self._zapi.hostgroup.get(
+ {"output": "extend", "filter": {"name": [name]}}
+ )
if len(_hostgroup) < 1:
- self._module.fail_json(msg='Host group not found: %s' % name)
+ self._module.fail_json(msg="Host group not found: %s" % name)
else:
return _hostgroup[0]
except Exception as e:
- self._module.fail_json(msg='Failed to get host group "%s": %s' % (name, e))
+ self._module.fail_json(msg="Failed to get host group '%s': %s" % (name, e))
def construct_the_data(self, _rights):
"""Construct the user defined rights to fit the Zabbix API requirements
@@ -366,13 +366,12 @@ class Rights(ZabbixBase):
constructed_data = []
for right in _rights:
constructed_right = {
- 'id': self.get_hostgroup_by_hostgroup_name(right.get('host_group'))['groupid'],
- 'permission': zabbix_utils.helper_to_numeric_value([
- 'denied',
- None,
- 'read-only',
- 'read-write'], right.get('permission')
- )
+ "id": self.get_hostgroup_by_hostgroup_name(right.get("host_group"))[
+ "groupid"
+ ],
+ "permission": zabbix_utils.helper_to_numeric_value(
+ ["denied", None, "read-only", "read-write"], right.get("permission")
+ ),
}
constructed_data.append(constructed_right)
return zabbix_utils.helper_cleanup_data(constructed_data)
@@ -394,15 +393,15 @@ class HostgroupRights(ZabbixBase):
"""
try:
_hostgroup = self._zapi.hostgroup.get({
- 'output': 'extend',
- 'filter': {'name': [name]}
+ "output": "extend",
+ "filter": {"name": [name]}
})
if len(_hostgroup) < 1:
- self._module.fail_json(msg='Host group not found: %s' % name)
+ self._module.fail_json(msg="Host group not found: %s" % name)
else:
return _hostgroup[0]
except Exception as e:
- self._module.fail_json(msg='Failed to get host group "%s": %s' % (name, e))
+ self._module.fail_json(msg="Failed to get host group '%s': %s" % (name, e))
def construct_the_data(self, _rights):
"""Construct the user defined host group rights to fit the Zabbix API requirements
@@ -418,12 +417,12 @@ class HostgroupRights(ZabbixBase):
constructed_data = []
for right in _rights:
constructed_right = {
- 'id': self.get_hostgroup_by_hostgroup_name(right.get('host_group'))['groupid'],
- 'permission': zabbix_utils.helper_to_numeric_value([
- 'denied',
+ "id": self.get_hostgroup_by_hostgroup_name(right.get("host_group"))["groupid"],
+ "permission": zabbix_utils.helper_to_numeric_value([
+ "denied",
None,
- 'read-only',
- 'read-write'], right.get('permission')
+ "read-only",
+ "read-write"], right.get("permission")
)
}
constructed_data.append(constructed_right)
@@ -446,15 +445,15 @@ class TemplategroupRights(ZabbixBase):
"""
try:
_templategroup = self._zapi.templategroup.get({
- 'output': 'extend',
- 'filter': {'name': [name]}
+ "output": "extend",
+ "filter": {"name": [name]}
})
if len(_templategroup) < 1:
- self._module.fail_json(msg='Template group not found: %s' % name)
+ self._module.fail_json(msg="Template group not found: %s" % name)
else:
return _templategroup[0]
except Exception as e:
- self._module.fail_json(msg='Failed to get template group "%s": %s' % (name, e))
+ self._module.fail_json(msg="Failed to get template group '%s': %s" % (name, e))
def construct_the_data(self, _rights):
"""Construct the user defined template rights to fit the Zabbix API requirements
@@ -470,12 +469,12 @@ class TemplategroupRights(ZabbixBase):
constructed_data = []
for right in _rights:
constructed_right = {
- 'id': self.get_templategroup_by_templategroup_name(right.get('template_group'))['groupid'],
- 'permission': zabbix_utils.helper_to_numeric_value([
- 'denied',
+ "id": self.get_templategroup_by_templategroup_name(right.get("template_group"))["groupid"],
+ "permission": zabbix_utils.helper_to_numeric_value([
+ "denied",
None,
- 'read-only',
- 'read-write'], right.get('permission')
+ "read-only",
+ "read-write"], right.get("permission")
)
}
constructed_data.append(constructed_right)
@@ -501,9 +500,11 @@ class TagFilters(Rights):
constructed_data = []
for tag_filter in _tag_filters:
constructed_tag_filter = {
- 'groupid': self.get_hostgroup_by_hostgroup_name(tag_filter.get('host_group'))['groupid'],
- 'tag': tag_filter.get('tag'),
- 'value': tag_filter.get('value')
+ "groupid": self.get_hostgroup_by_hostgroup_name(
+ tag_filter.get("host_group")
+ )["groupid"],
+ "tag": tag_filter.get("tag"),
+ "value": tag_filter.get("value"),
}
constructed_data.append(constructed_tag_filter)
return zabbix_utils.helper_cleanup_data(constructed_data)
@@ -520,46 +521,50 @@ class UserGroup(ZabbixBase):
dict: dictionary of specified parameters
"""
_params = {
- 'name': kwargs['name'],
- 'gui_access': zabbix_utils.helper_to_numeric_value([
- 'default',
- 'internal',
- 'LDAP',
- 'disable'], kwargs['gui_access']
+ "name": kwargs["name"],
+ "gui_access": zabbix_utils.helper_to_numeric_value(
+ ["default", "internal", "LDAP", "disable"], kwargs["gui_access"]
),
- 'debug_mode': zabbix_utils.helper_to_numeric_value([
- 'disabled',
- 'enabled'], kwargs['debug_mode']
+ "debug_mode": zabbix_utils.helper_to_numeric_value(
+ ["disabled", "enabled"], kwargs["debug_mode"]
),
- 'users_status': zabbix_utils.helper_to_numeric_value([
- 'enabled',
- 'disabled'], kwargs['status']
+ "users_status": zabbix_utils.helper_to_numeric_value(
+ ["enabled", "disabled"], kwargs["status"]
),
- 'tag_filters': kwargs['tag_filters']
+ "tag_filters": kwargs["tag_filters"],
}
- if LooseVersion(self._zbx_api_version) < LooseVersion('6.2'):
- _params['rights'] = kwargs['rights']
+ if LooseVersion(self._zbx_api_version) < LooseVersion("6.2"):
+ _params["rights"] = kwargs["rights"]
else:
- _params['hostgroup_rights'] = kwargs['hostgroup_rights']
- _params['templategroup_rights'] = kwargs['templategroup_rights']
+ _params["hostgroup_rights"] = kwargs["hostgroup_rights"]
+ _params["templategroup_rights"] = kwargs["templategroup_rights"]
- if kwargs['userdirectory']:
+ if kwargs["userdirectory"]:
try:
- if LooseVersion(self._zbx_api_version) <= LooseVersion('6.2'):
- _userdir = self._zapi.userdirectory.get({
- 'output': 'extend',
- 'filter': {'name': [kwargs['userdirectory']]}
- })
+ if LooseVersion(self._zbx_api_version) <= LooseVersion("6.2"):
+ _userdir = self._zapi.userdirectory.get(
+ {
+ "output": "extend",
+ "filter": {"name": [kwargs["userdirectory"]]},
+ }
+ )
else:
- _userdir = self._zapi.userdirectory.get({
- 'output': 'extend',
- 'search': {'name': [kwargs['userdirectory']]}
- })
+ _userdir = self._zapi.userdirectory.get(
+ {
+ "output": "extend",
+ "search": {"name": [kwargs["userdirectory"]]},
+ }
+ )
except Exception as e:
- self._module.fail_json(msg='Failed to get user directory "%s": %s' % (kwargs['userdirectory'], e))
+ self._module.fail_json(
+ msg="Failed to get user directory '%s': %s"
+ % (kwargs["userdirectory"], e)
+ )
if len(_userdir) == 0:
- self._module.fail_json(msg='User directory "%s" not found' % kwargs['userdirectory'])
- _params['userdirectoryid'] = _userdir[0]['userdirectoryid']
+ self._module.fail_json(
+ msg="User directory '%s' not found" % kwargs["userdirectory"]
+ )
+ _params["userdirectoryid"] = _userdir[0]["userdirectoryid"]
return _params
@@ -573,14 +578,15 @@ class UserGroup(ZabbixBase):
The return value. True for success, False otherwise.
"""
try:
- _usergroup = self._zapi.usergroup.get({
- 'output': 'extend',
- 'filter': {'name': [name]}
- })
+ _usergroup = self._zapi.usergroup.get(
+ {"output": "extend", "filter": {"name": [name]}}
+ )
if len(_usergroup) > 0:
return _usergroup
except Exception as e:
- self._module.fail_json(msg='Failed to check if user group "%s" exists: %s' % (name, e))
+ self._module.fail_json(
+ msg="Failed to check if user group '%s' exists: %s" % (name, e)
+ )
def get_usergroup_by_usergroup_name(self, name):
"""Get user group by user group name.
@@ -592,28 +598,32 @@ class UserGroup(ZabbixBase):
User group matching user group name.
"""
try:
- if LooseVersion(self._zbx_api_version) < LooseVersion('6.2'):
- _usergroup = self._zapi.usergroup.get({
- 'output': 'extend',
- 'selectTagFilters': 'extend',
- 'selectRights': 'extend',
- 'filter': {'name': [name]}
- })
+ if LooseVersion(self._zbx_api_version) < LooseVersion("6.2"):
+ _usergroup = self._zapi.usergroup.get(
+ {
+ "output": "extend",
+ "selectTagFilters": "extend",
+ "selectRights": "extend",
+ "filter": {"name": [name]},
+ }
+ )
else:
- _usergroup = self._zapi.usergroup.get({
- 'output': 'extend',
- 'selectTagFilters': 'extend',
- 'selectHostGroupRights': 'extend',
- 'selectTemplateGroupRights': 'extend',
- 'filter': {'name': [name]}
- })
+ _usergroup = self._zapi.usergroup.get(
+ {
+ "output": "extend",
+ "selectTagFilters": "extend",
+ "selectHostGroupRights": "extend",
+ "selectTemplateGroupRights": "extend",
+ "filter": {"name": [name]},
+ }
+ )
if len(_usergroup) < 1:
- self._module.fail_json(msg='User group not found: %s' % name)
+ self._module.fail_json(msg="User group not found: %s" % name)
else:
return _usergroup[0]
except Exception as e:
- self._module.fail_json(msg='Failed to get user group "%s": %s' % (name, e))
+ self._module.fail_json(msg="Failed to get user group '%s': %s" % (name, e))
def check_difference(self, **kwargs):
"""Check difference between user group and user specified parameters.
@@ -624,10 +634,16 @@ class UserGroup(ZabbixBase):
Returns:
dict: dictionary of differences
"""
- existing_usergroup = zabbix_utils.helper_convert_unicode_to_str(self.get_usergroup_by_usergroup_name(kwargs['name']))
- parameters = zabbix_utils.helper_convert_unicode_to_str(self._construct_parameters(**kwargs))
+ existing_usergroup = zabbix_utils.helper_convert_unicode_to_str(
+ self.get_usergroup_by_usergroup_name(kwargs["name"])
+ )
+ parameters = zabbix_utils.helper_convert_unicode_to_str(
+ self._construct_parameters(**kwargs)
+ )
change_parameters = {}
- _diff = zabbix_utils.helper_compare_dictionaries(parameters, existing_usergroup, change_parameters)
+ _diff = zabbix_utils.helper_compare_dictionaries(
+ parameters, existing_usergroup, change_parameters
+ )
return _diff
def update(self, **kwargs):
@@ -644,7 +660,9 @@ class UserGroup(ZabbixBase):
self._module.exit_json(changed=True)
return self._zapi.usergroup.update(kwargs)
except Exception as e:
- self._module.fail_json(msg='Failed to update user group "%s": %s' % (kwargs['usrgrpid'], e))
+ self._module.fail_json(
+ msg="Failed to update user group '%s': %s" % (kwargs["usrgrpid"], e)
+ )
def add(self, **kwargs):
"""Add user group.
@@ -660,9 +678,11 @@ class UserGroup(ZabbixBase):
self._module.exit_json(changed=True)
parameters = self._construct_parameters(**kwargs)
usergroup = self._zapi.usergroup.create(parameters)
- return usergroup['usrgrpids'][0]
+ return usergroup["usrgrpids"][0]
except Exception as e:
- self._module.fail_json(msg='Failed to create user group "%s": %s' % (kwargs['name'], e))
+ self._module.fail_json(
+ msg="Failed to create user group '%s': %s" % (kwargs["name"], e)
+ )
def delete(self, usrgrpid):
"""Delete user group.
@@ -679,62 +699,102 @@ class UserGroup(ZabbixBase):
else:
return self._zapi.usergroup.delete([usrgrpid])
except Exception as e:
- self._module.fail_json(msg='Failed to delete user group "%s": %s' % (usrgrpid, e))
+ self._module.fail_json(
+ msg="Failed to delete user group '%s': %s" % (usrgrpid, e)
+ )
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(
- name=dict(type='str', required=True, aliases=['user_group']),
- gui_access=dict(type='str', required=False, default='default', choices=['default', 'internal', 'LDAP', 'disable']),
- debug_mode=dict(type='str', required=False, default='disabled', choices=['disabled', 'enabled']),
- status=dict(type='str', required=False, default='enabled', choices=['enabled', 'disabled']),
- rights=dict(type='list', elements='dict', required=False, options=dict(
- host_group=dict(type='str', required=True),
- permission=dict(type='str', required=True, choices=['denied', 'read-only', 'read-write'])
- )),
- hostgroup_rights=dict(type='list', elements='dict', required=False, options=dict(
- host_group=dict(type='str', required=True),
- permission=dict(type='str', required=True, choices=['denied', 'read-only', 'read-write'])
- )),
- templategroup_rights=dict(type='list', elements='dict', required=False, options=dict(
- template_group=dict(type='str', required=True),
- permission=dict(type='str', required=True, choices=['denied', 'read-only', 'read-write'])
- )),
- tag_filters=dict(type='list', elements='dict', required=False, options=dict(
- host_group=dict(type='str', required=True),
- tag=dict(type='str', default=''),
- value=dict(type='str', default='')
- )),
- userdirectory=dict(type='str', required=False),
- state=dict(type='str', default='present', choices=['present', 'absent'])
- )
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True
+ name=dict(type="str", required=True, aliases=["user_group"]),
+ gui_access=dict(
+ type="str",
+ required=False,
+ default="default",
+ choices=["default", "internal", "LDAP", "disable"],
+ ),
+ debug_mode=dict(
+ type="str",
+ required=False,
+ default="disabled",
+ choices=["disabled", "enabled"],
+ ),
+ status=dict(
+ type="str",
+ required=False,
+ default="enabled",
+ choices=["enabled", "disabled"],
+ ),
+ rights=dict(
+ type="list",
+ elements="dict",
+ required=False,
+ options=dict(
+ host_group=dict(type="str", required=True),
+ permission=dict(
+ type="str",
+ required=True,
+ choices=["denied", "read-only", "read-write"],
+ ),
+ ),
+ ),
+ hostgroup_rights=dict(
+ type="list",
+ elements="dict",
+ required=False,
+ options=dict(
+ host_group=dict(type="str", required=True),
+ permission=dict(
+ type="str",
+ required=True,
+ choices=["denied", "read-only", "read-write"],
+ ),
+ ),
+ ),
+ templategroup_rights=dict(
+ type="list",
+ elements="dict",
+ required=False,
+ options=dict(
+ template_group=dict(type="str", required=True),
+ permission=dict(
+ type="str",
+ required=True,
+ choices=["denied", "read-only", "read-write"],
+ ),
+ ),
+ ),
+ tag_filters=dict(
+ type="list",
+ elements="dict",
+ required=False,
+ options=dict(
+ host_group=dict(type="str", required=True),
+ tag=dict(type="str", default=""),
+ value=dict(type="str", default=""),
+ ),
+ ),
+ userdirectory=dict(type="str", required=False),
+ state=dict(type="str", default="present", choices=["present", "absent"]),
)
- zabbix_utils.require_creds_params(module)
+ module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
-
- name = module.params['name']
- gui_access = module.params['gui_access']
- debug_mode = module.params['debug_mode']
- status = module.params['status']
- rights = module.params['rights']
- hostgroup_rights = module.params['hostgroup_rights']
- templategroup_rights = module.params['templategroup_rights']
- tag_filters = module.params['tag_filters']
- userdirectory = module.params['userdirectory']
- state = module.params['state']
+ name = module.params["name"]
+ gui_access = module.params["gui_access"]
+ debug_mode = module.params["debug_mode"]
+ status = module.params["status"]
+ rights = module.params["rights"]
+ hostgroup_rights = module.params["hostgroup_rights"]
+ templategroup_rights = module.params["templategroup_rights"]
+ tag_filters = module.params["tag_filters"]
+ userdirectory = module.params["userdirectory"]
+ state = module.params["state"]
userGroup = UserGroup(module)
zbx = userGroup._zapi
- if LooseVersion(userGroup._zbx_api_version) < LooseVersion('6.2'):
+ if LooseVersion(userGroup._zbx_api_version) < LooseVersion("6.2"):
rgts = Rights(module, zbx)
else:
hostgroup_rgts = HostgroupRights(module, zbx)
@@ -744,12 +804,18 @@ def main():
usergroup_exists = userGroup.check_if_usergroup_exists(name)
if usergroup_exists:
- usrgrpid = userGroup.get_usergroup_by_usergroup_name(name)['usrgrpid']
- if state == 'absent':
+ usrgrpid = userGroup.get_usergroup_by_usergroup_name(name)["usrgrpid"]
+ if state == "absent":
userGroup.delete(usrgrpid)
- module.exit_json(changed=True, state=state, usergroup=name, usrgrpid=usrgrpid, msg='User group deleted: %s, ID: %s' % (name, usrgrpid))
+ module.exit_json(
+ changed=True,
+ state=state,
+ usergroup=name,
+ usrgrpid=usrgrpid,
+ msg="User group deleted: %s, ID: %s" % (name, usrgrpid),
+ )
else:
- if LooseVersion(userGroup._zbx_api_version) < LooseVersion('6.2'):
+ if LooseVersion(userGroup._zbx_api_version) < LooseVersion("6.2"):
difference = userGroup.check_difference(
usrgrpid=usrgrpid,
name=name,
@@ -757,7 +823,7 @@ def main():
debug_mode=debug_mode,
status=status,
rights=rgts.construct_the_data(rights),
- tag_filters=tgflts.construct_the_data(tag_filters)
+ tag_filters=tgflts.construct_the_data(tag_filters),
)
else:
difference = userGroup.check_difference(
@@ -766,31 +832,49 @@ def main():
gui_access=gui_access,
debug_mode=debug_mode,
status=status,
- hostgroup_rights=hostgroup_rgts.construct_the_data(hostgroup_rights),
- templategroup_rights=templategroup_rgts.construct_the_data(templategroup_rights),
+ hostgroup_rights=hostgroup_rgts.construct_the_data(
+ hostgroup_rights
+ ),
+ templategroup_rights=templategroup_rgts.construct_the_data(
+ templategroup_rights
+ ),
tag_filters=tgflts.construct_the_data(tag_filters),
- userdirectory=userdirectory
+ userdirectory=userdirectory,
)
if difference == {}:
- module.exit_json(changed=False, state=state, usergroup=name, usrgrpid=usrgrpid, msg='User group is up to date: %s' % name)
+ module.exit_json(
+ changed=False,
+ state=state,
+ usergroup=name,
+ usrgrpid=usrgrpid,
+ msg="User group is up to date: %s" % name,
+ )
else:
- userGroup.update(
+ userGroup.update(usrgrpid=usrgrpid, **difference)
+ module.exit_json(
+ changed=True,
+ state=state,
+ usergroup=name,
usrgrpid=usrgrpid,
- **difference
+ msg="User group updated: %s, ID: %s" % (name, usrgrpid),
)
- module.exit_json(changed=True, state=state, usergroup=name, usrgrpid=usrgrpid, msg='User group updated: %s, ID: %s' % (name, usrgrpid))
else:
- if state == 'absent':
- module.exit_json(changed=False, state=state, usergroup=name, msg='User group %s does not exists, nothing to delete' % name)
+ if state == "absent":
+ module.exit_json(
+ changed=False,
+ state=state,
+ usergroup=name,
+ msg="User group %s does not exists, nothing to delete" % name,
+ )
else:
- if LooseVersion(userGroup._zbx_api_version) < LooseVersion('6.2'):
+ if LooseVersion(userGroup._zbx_api_version) < LooseVersion("6.2"):
usrgrpid = userGroup.add(
name=name,
gui_access=gui_access,
debug_mode=debug_mode,
status=status,
rights=rgts.construct_the_data(rights),
- tag_filters=tgflts.construct_the_data(tag_filters)
+ tag_filters=tgflts.construct_the_data(tag_filters),
)
else:
usrgrpid = userGroup.add(
@@ -798,13 +882,23 @@ def main():
gui_access=gui_access,
debug_mode=debug_mode,
status=status,
- hostgroup_rights=hostgroup_rgts.construct_the_data(hostgroup_rights),
- templategroup_rights=templategroup_rgts.construct_the_data(templategroup_rights),
+ hostgroup_rights=hostgroup_rgts.construct_the_data(
+ hostgroup_rights
+ ),
+ templategroup_rights=templategroup_rgts.construct_the_data(
+ templategroup_rights
+ ),
tag_filters=tgflts.construct_the_data(tag_filters),
- userdirectory=userdirectory
+ userdirectory=userdirectory,
)
- module.exit_json(changed=True, state=state, usergroup=name, usrgrpid=usrgrpid, msg='User group created: %s, ID: %s' % (name, usrgrpid))
+ module.exit_json(
+ changed=True,
+ state=state,
+ usergroup=name,
+ usrgrpid=usrgrpid,
+ msg="User group created: %s, ID: %s" % (name, usrgrpid),
+ )
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/community/zabbix/plugins/modules/zabbix_valuemap.py b/ansible_collections/community/zabbix/plugins/modules/zabbix_valuemap.py
index 196f8ff7e..3d9a64954 100644
--- a/ansible_collections/community/zabbix/plugins/modules/zabbix_valuemap.py
+++ b/ansible_collections/community/zabbix/plugins/modules/zabbix_valuemap.py
@@ -8,7 +8,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
---
module: zabbix_valuemap
short_description: Create/update/delete Zabbix value maps
@@ -17,56 +17,56 @@ description:
author:
- "Ruben Tsirunyan (@rubentsirunyan)"
requirements:
- - "python >= 2.6"
+ - "python >= 3.9"
options:
name:
- type: 'str'
+ type: "str"
description:
- Name of the value map.
required: true
state:
- type: 'str'
+ 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'
+ choices: ["present", "absent"]
+ default: "present"
mappings:
- type: 'list'
+ type: "list"
elements: dict
description:
- List of value mappings for the value map.
- Required when I(state=present).
suboptions:
value:
- type: 'str'
+ type: "str"
description: Original value.
required: true
map_to:
- type: 'str'
+ type: "str"
description: Value to which the original value is mapped to.
required: true
extends_documentation_fragment:
- community.zabbix.zabbix
-'''
+"""
-RETURN = r'''
-'''
+RETURN = r"""
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
# If you want to use Username and Password to be authenticated by Zabbix Server
- name: Set credentials to access Zabbix Server API
- set_fact:
+ 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
- set_fact:
+ ansible.builtin.set_fact:
ansible_zabbix_auth_key: 8ec0d52432c15c91fcafe9888500cf9a607f44091ab554dbee860f6b44fac895
- name: Create a value map
@@ -77,7 +77,7 @@ EXAMPLES = r'''
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_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_valuemap:
name: Numbers
@@ -87,7 +87,7 @@ EXAMPLES = r'''
- value: 2
map_to: two
state: present
-'''
+"""
from ansible.module_utils.basic import AnsibleModule
@@ -104,31 +104,31 @@ def construct_parameters(**kwargs):
Returns:
A dictionary of arguments in a format that is understandable by Zabbix API.
"""
- if kwargs['mappings'] is None:
+ if kwargs["mappings"] is None:
return dict(
- name=kwargs['name']
+ name=kwargs["name"]
)
return dict(
- name=kwargs['name'],
+ name=kwargs["name"],
mappings=[
dict(
- value=mapping['value'],
- newvalue=mapping['map_to']
- ) for mapping in kwargs['mappings']
+ value=mapping["value"],
+ newvalue=mapping["map_to"]
+ ) for mapping in kwargs["mappings"]
]
)
def diff(existing, new):
- """Constructs the diff for Ansible's --diff option.
+ """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}
+ A dictionary like {"before": existing, "after": new}
with filtered empty values.
"""
before = {}
@@ -136,11 +136,11 @@ def diff(existing, new):
for key in new:
before[key] = existing[key]
if new[key] is None:
- after[key] = ''
+ after[key] = ""
else:
after[key] = new[key]
- return {'before': before, 'after': after}
+ return {"before": before, "after": after}
def get_update_params(existing_valuemap, **kwargs):
@@ -158,8 +158,8 @@ def get_update_params(existing_valuemap, **kwargs):
"""
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']
+ 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)
@@ -176,9 +176,9 @@ class ValuemapModule(ZabbixBase):
"""
try:
valuemap_list = self._zapi.valuemap.get({
- 'output': 'extend',
- 'selectMappings': 'extend',
- 'filter': {'name': [name]}
+ "output": "extend",
+ "selectMappings": "extend",
+ "filter": {"name": [name]}
})
if len(valuemap_list) < 1:
return False, None
@@ -197,26 +197,26 @@ class ValuemapModule(ZabbixBase):
try:
self._zapi.valuemap.update(kwargs)
except Exception as e:
- self._module.fail_json(msg="Failed to update valuemap '{_id}': {e}".format(_id=kwargs['valuemapid'], e=e))
+ self._module.fail_json(msg="Failed to update valuemap '{_id}': {e}".format(_id=kwargs["valuemapid"], e=e))
def create(self, **kwargs):
try:
self._zapi.valuemap.create(kwargs)
except Exception as e:
- self._module.fail_json(msg="Failed to create valuemap '{name}': {e}".format(name=kwargs['description'], e=e))
+ self._module.fail_json(msg="Failed to create valuemap '{name}': {e}".format(name=kwargs["description"], e=e))
def main():
argument_spec = zabbix_utils.zabbix_common_argument_spec()
argument_spec.update(dict(
- name=dict(type='str', required=True),
- state=dict(type='str', default='present', choices=['present', 'absent']),
+ name=dict(type="str", required=True),
+ state=dict(type="str", default="present", choices=["present", "absent"]),
mappings=dict(
- type='list',
- elements='dict',
+ type="list",
+ elements="dict",
options=dict(
- value=dict(type='str', required=True),
- map_to=dict(type='str', required=True)
+ value=dict(type="str", required=True),
+ map_to=dict(type="str", required=True)
)
)
))
@@ -224,20 +224,15 @@ def main():
argument_spec=argument_spec,
supports_check_mode=True,
required_if=[
- ['state', 'present', ['mappings']],
+ ["state", "present", ["mappings"]],
]
)
- zabbix_utils.require_creds_params(module)
-
- for p in ['server_url', 'login_user', 'login_password', 'timeout', 'validate_certs']:
- if p in module.params and not module.params[p] is None:
- module.warn('Option "%s" is deprecated with the move to httpapi connection and will be removed in the next release' % p)
vm = ValuemapModule(module)
- name = module.params['name']
- state = module.params['state']
- mappings = module.params['mappings']
+ name = module.params["name"]
+ state = module.params["state"]
+ mappings = module.params["mappings"]
valuemap_exists, valuemap_object = vm.check_if_valuemap_exists(name)
@@ -247,8 +242,8 @@ def main():
)
if valuemap_exists:
- valuemap_id = valuemap_object['valuemapid']
- if state == 'absent':
+ valuemap_id = valuemap_object["valuemapid"]
+ if state == "absent":
if module.check_mode:
module.exit_json(
changed=True,
@@ -313,5 +308,5 @@ def main():
)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()