community.general/lib/ansible/modules/remote_management/manageiq/manageiq_alerts.py

347 lines
13 KiB
Python
Raw Normal View History

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright (c) 2017 Red Hat Inc.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
module: manageiq_alerts
short_description: Configuration of alerts in ManageIQ
extends_documentation_fragment: manageiq
version_added: '2.5'
author: Elad Alfassa (@elad661) <ealfassa@redhat.com
description:
- The manageiq_alerts module supports adding, updating and deleting alerts in ManageIQ.
options:
state:
description:
- absent - alert should not exist,
- present - alert should exist,
required: False
choices: ['absent', 'present']
default: 'present'
description:
description:
- The unique alert description in ManageIQ.
- Required when state is "absent" or "present".
resource_type:
description:
- The entity type for the alert in ManageIQ. Required when state is "present".
choices: ['Vm', 'ContainerNode', 'MiqServer', 'Host', 'Storage', 'EmsCluster',
'ExtManagementSystem', 'MiddlewareServer']
expression_type:
description:
- Expression type.
default: hash
choices: ["hash", "miq"]
expression:
description:
- The alert expression for ManageIQ.
- Can either be in the "Miq Expression" format or the "Hash Expression format".
- Required if state is "present".
enabled:
description:
- Enable or disable the alert. Required if state is "present".
type: bool
options:
description:
- Additional alert options, such as notification type and frequency
'''
EXAMPLES = '''
- name: Add an alert with a "hash expression" to ManageIQ
manageiq_alerts:
state: present
description: Test Alert 01
options:
notifications:
email:
to: ["example@example.com"]
from: "example@example.com"
resource_type: ContainerNode
expression:
eval_method: hostd_log_threshold
mode: internal
options: {}
enabled: true
manageiq_connection:
url: 'http://127.0.0.1:3000'
username: 'admin'
password: 'smartvm'
standardize TLS connection properties (#54315) * openstack: standardize tls params * tower: tower_verify_ssl->validate_certs * docker: use standard tls config params - cacert_path -> ca_cert - cert_path -> client_cert - key_path -> client_key - tls_verify -> validate_certs * k8s: standardize tls connection params - verify_ssl -> validate_certs - ssl_ca_cert -> ca_cert - cert_file -> client_cert - key_file -> client_key * ingate: verify_ssl -> validate_certs * manageiq: standardize tls params - verify_ssl -> validate_certs - ca_bundle_path -> ca_cert * mysql: standardize tls params - ssl_ca -> ca_cert - ssl_cert -> client_cert - ssl_key -> client_key * nios: ssl_verify -> validate_certs * postgresql: ssl_rootcert -> ca_cert * rabbitmq: standardize tls params - cacert -> ca_cert - cert -> client_cert - key -> client_key * rackspace: verify_ssl -> validate_certs * vca: verify_certs -> validate_certs * kubevirt_cdi_upload: upload_host_verify_ssl -> upload_host_validate_certs * lxd: standardize tls params - key_file -> client_key - cert_file -> client_cert * get_certificate: ca_certs -> ca_cert * get_certificate.py: clarify one or more certs in a file Co-Authored-By: jamescassell <code@james.cassell.me> * zabbix: tls_issuer -> ca_cert * bigip_device_auth_ldap: standardize tls params - ssl_check_peer -> validate_certs - ssl_client_cert -> client_cert - ssl_client_key -> client_key - ssl_ca_cert -> ca_cert * vdirect: vdirect_validate_certs -> validate_certs * mqtt: standardize tls params - ca_certs -> ca_cert - certfile -> client_cert - keyfile -> client_key * pulp_repo: standardize tls params remove `importer_ssl` prefix * rhn_register: sslcacert -> ca_cert * yum_repository: standardize tls params The fix for yum_repository is not straightforward since this module is only a thin wrapper for the underlying commands and config. In this case, we add the new values as aliases, keeping the old as primary, only due to the internal structure of the module. Aliases added: - sslcacert -> ca_cert - sslclientcert -> client_cert - sslclientkey -> client_key - sslverify -> validate_certs * gitlab_hook: enable_ssl_verification -> hook_validate_certs * Adjust arguments for docker_swarm inventory plugin. * foreman callback: standardize tls params - ssl_cert -> client_cert - ssl_key -> client_key * grafana_annotations: validate_grafana_certs -> validate_certs * nrdp callback: validate_nrdp_certs -> validate_certs * kubectl connection: standardize tls params - kubectl_cert_file -> client_cert - kubectl_key_file -> client_key - kubectl_ssl_ca_cert -> ca_cert - kubectl_verify_ssl -> validate_certs * oc connection: standardize tls params - oc_cert_file -> client_cert - oc_key_file -> client_key - oc_ssl_ca_cert -> ca_cert - oc_verify_ssl -> validate_certs * psrp connection: cert_trust_path -> ca_cert TODO: cert_validation -> validate_certs (multi-valued vs bool) * k8s inventory: standardize tls params - cert_file -> client_cert - key_file -> client_key - ca_cert -> ca_cert - verify_ssl -> validate_certs * openshift inventory: standardize tls params - cert_file -> client_cert - key_file -> client_key - ca_cert -> ca_cert - verify_ssl -> validate_certs * tower inventory: verify_ssl -> validate_certs * hashi_vault lookup: cacert -> ca_cert * k8s lookup: standardize tls params - cert_file -> client_cert - key_file -> client_key - ca_cert -> ca_cert - verify_ssl -> validate_certs * laps_passord lookup: cacert_file -> ca_cert * changelog for TLS parameter standardization
2019-03-28 05:19:28 +00:00
validate_certs: False
- name: Add an alert with a "miq expression" to ManageIQ
manageiq_alerts:
state: present
description: Test Alert 02
options:
notifications:
email:
to: ["example@example.com"]
from: "example@example.com"
resource_type: Vm
expression_type: miq
expression:
and:
- CONTAINS:
tag: Vm.managed-environment
value: prod
- not:
CONTAINS:
tag: Vm.host.managed-environment
value: prod
enabled: true
manageiq_connection:
url: 'http://127.0.0.1:3000'
username: 'admin'
password: 'smartvm'
standardize TLS connection properties (#54315) * openstack: standardize tls params * tower: tower_verify_ssl->validate_certs * docker: use standard tls config params - cacert_path -> ca_cert - cert_path -> client_cert - key_path -> client_key - tls_verify -> validate_certs * k8s: standardize tls connection params - verify_ssl -> validate_certs - ssl_ca_cert -> ca_cert - cert_file -> client_cert - key_file -> client_key * ingate: verify_ssl -> validate_certs * manageiq: standardize tls params - verify_ssl -> validate_certs - ca_bundle_path -> ca_cert * mysql: standardize tls params - ssl_ca -> ca_cert - ssl_cert -> client_cert - ssl_key -> client_key * nios: ssl_verify -> validate_certs * postgresql: ssl_rootcert -> ca_cert * rabbitmq: standardize tls params - cacert -> ca_cert - cert -> client_cert - key -> client_key * rackspace: verify_ssl -> validate_certs * vca: verify_certs -> validate_certs * kubevirt_cdi_upload: upload_host_verify_ssl -> upload_host_validate_certs * lxd: standardize tls params - key_file -> client_key - cert_file -> client_cert * get_certificate: ca_certs -> ca_cert * get_certificate.py: clarify one or more certs in a file Co-Authored-By: jamescassell <code@james.cassell.me> * zabbix: tls_issuer -> ca_cert * bigip_device_auth_ldap: standardize tls params - ssl_check_peer -> validate_certs - ssl_client_cert -> client_cert - ssl_client_key -> client_key - ssl_ca_cert -> ca_cert * vdirect: vdirect_validate_certs -> validate_certs * mqtt: standardize tls params - ca_certs -> ca_cert - certfile -> client_cert - keyfile -> client_key * pulp_repo: standardize tls params remove `importer_ssl` prefix * rhn_register: sslcacert -> ca_cert * yum_repository: standardize tls params The fix for yum_repository is not straightforward since this module is only a thin wrapper for the underlying commands and config. In this case, we add the new values as aliases, keeping the old as primary, only due to the internal structure of the module. Aliases added: - sslcacert -> ca_cert - sslclientcert -> client_cert - sslclientkey -> client_key - sslverify -> validate_certs * gitlab_hook: enable_ssl_verification -> hook_validate_certs * Adjust arguments for docker_swarm inventory plugin. * foreman callback: standardize tls params - ssl_cert -> client_cert - ssl_key -> client_key * grafana_annotations: validate_grafana_certs -> validate_certs * nrdp callback: validate_nrdp_certs -> validate_certs * kubectl connection: standardize tls params - kubectl_cert_file -> client_cert - kubectl_key_file -> client_key - kubectl_ssl_ca_cert -> ca_cert - kubectl_verify_ssl -> validate_certs * oc connection: standardize tls params - oc_cert_file -> client_cert - oc_key_file -> client_key - oc_ssl_ca_cert -> ca_cert - oc_verify_ssl -> validate_certs * psrp connection: cert_trust_path -> ca_cert TODO: cert_validation -> validate_certs (multi-valued vs bool) * k8s inventory: standardize tls params - cert_file -> client_cert - key_file -> client_key - ca_cert -> ca_cert - verify_ssl -> validate_certs * openshift inventory: standardize tls params - cert_file -> client_cert - key_file -> client_key - ca_cert -> ca_cert - verify_ssl -> validate_certs * tower inventory: verify_ssl -> validate_certs * hashi_vault lookup: cacert -> ca_cert * k8s lookup: standardize tls params - cert_file -> client_cert - key_file -> client_key - ca_cert -> ca_cert - verify_ssl -> validate_certs * laps_passord lookup: cacert_file -> ca_cert * changelog for TLS parameter standardization
2019-03-28 05:19:28 +00:00
validate_certs: False
- name: Delete an alert from ManageIQ
manageiq_alerts:
state: absent
description: Test Alert 01
manageiq_connection:
url: 'http://127.0.0.1:3000'
username: 'admin'
password: 'smartvm'
standardize TLS connection properties (#54315) * openstack: standardize tls params * tower: tower_verify_ssl->validate_certs * docker: use standard tls config params - cacert_path -> ca_cert - cert_path -> client_cert - key_path -> client_key - tls_verify -> validate_certs * k8s: standardize tls connection params - verify_ssl -> validate_certs - ssl_ca_cert -> ca_cert - cert_file -> client_cert - key_file -> client_key * ingate: verify_ssl -> validate_certs * manageiq: standardize tls params - verify_ssl -> validate_certs - ca_bundle_path -> ca_cert * mysql: standardize tls params - ssl_ca -> ca_cert - ssl_cert -> client_cert - ssl_key -> client_key * nios: ssl_verify -> validate_certs * postgresql: ssl_rootcert -> ca_cert * rabbitmq: standardize tls params - cacert -> ca_cert - cert -> client_cert - key -> client_key * rackspace: verify_ssl -> validate_certs * vca: verify_certs -> validate_certs * kubevirt_cdi_upload: upload_host_verify_ssl -> upload_host_validate_certs * lxd: standardize tls params - key_file -> client_key - cert_file -> client_cert * get_certificate: ca_certs -> ca_cert * get_certificate.py: clarify one or more certs in a file Co-Authored-By: jamescassell <code@james.cassell.me> * zabbix: tls_issuer -> ca_cert * bigip_device_auth_ldap: standardize tls params - ssl_check_peer -> validate_certs - ssl_client_cert -> client_cert - ssl_client_key -> client_key - ssl_ca_cert -> ca_cert * vdirect: vdirect_validate_certs -> validate_certs * mqtt: standardize tls params - ca_certs -> ca_cert - certfile -> client_cert - keyfile -> client_key * pulp_repo: standardize tls params remove `importer_ssl` prefix * rhn_register: sslcacert -> ca_cert * yum_repository: standardize tls params The fix for yum_repository is not straightforward since this module is only a thin wrapper for the underlying commands and config. In this case, we add the new values as aliases, keeping the old as primary, only due to the internal structure of the module. Aliases added: - sslcacert -> ca_cert - sslclientcert -> client_cert - sslclientkey -> client_key - sslverify -> validate_certs * gitlab_hook: enable_ssl_verification -> hook_validate_certs * Adjust arguments for docker_swarm inventory plugin. * foreman callback: standardize tls params - ssl_cert -> client_cert - ssl_key -> client_key * grafana_annotations: validate_grafana_certs -> validate_certs * nrdp callback: validate_nrdp_certs -> validate_certs * kubectl connection: standardize tls params - kubectl_cert_file -> client_cert - kubectl_key_file -> client_key - kubectl_ssl_ca_cert -> ca_cert - kubectl_verify_ssl -> validate_certs * oc connection: standardize tls params - oc_cert_file -> client_cert - oc_key_file -> client_key - oc_ssl_ca_cert -> ca_cert - oc_verify_ssl -> validate_certs * psrp connection: cert_trust_path -> ca_cert TODO: cert_validation -> validate_certs (multi-valued vs bool) * k8s inventory: standardize tls params - cert_file -> client_cert - key_file -> client_key - ca_cert -> ca_cert - verify_ssl -> validate_certs * openshift inventory: standardize tls params - cert_file -> client_cert - key_file -> client_key - ca_cert -> ca_cert - verify_ssl -> validate_certs * tower inventory: verify_ssl -> validate_certs * hashi_vault lookup: cacert -> ca_cert * k8s lookup: standardize tls params - cert_file -> client_cert - key_file -> client_key - ca_cert -> ca_cert - verify_ssl -> validate_certs * laps_passord lookup: cacert_file -> ca_cert * changelog for TLS parameter standardization
2019-03-28 05:19:28 +00:00
validate_certs: False
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.manageiq import ManageIQ, manageiq_argument_spec
class ManageIQAlert(object):
""" Represent a ManageIQ alert. Can be initialized with both the format
we recieve from the server and the format we get from the user.
"""
def __init__(self, alert):
self.description = alert['description']
self.db = alert['db']
self.enabled = alert['enabled']
self.options = alert['options']
self.hash_expression = None
self.miq_expressipn = None
if 'hash_expression' in alert:
self.hash_expression = alert['hash_expression']
if 'miq_expression' in alert:
self.miq_expression = alert['miq_expression']
if 'exp' in self.miq_expression:
# miq_expression is a field that needs a special case, because
# it's returned surrounded by a dict named exp even though we don't
# send it with that dict.
self.miq_expression = self.miq_expression['exp']
def __eq__(self, other):
""" Compare two ManageIQAlert objects
"""
return self.__dict__ == other.__dict__
class ManageIQAlerts(object):
""" Object to execute alert management operations in manageiq.
"""
def __init__(self, manageiq):
self.manageiq = manageiq
self.module = self.manageiq.module
self.api_url = self.manageiq.api_url
self.client = self.manageiq.client
self.alerts_url = '{api_url}/alert_definitions'.format(api_url=self.api_url)
def get_alerts(self):
""" Get all alerts from ManageIQ
"""
try:
response = self.client.get(self.alerts_url + '?expand=resources')
except Exception as e:
self.module.fail_json(msg="Failed to query alerts: {error}".format(error=e))
return response.get('resources', [])
def validate_hash_expression(self, expression):
""" Validate a 'hash expression' alert definition
"""
# hash expressions must have the following fields
for key in ['options', 'eval_method', 'mode']:
if key not in expression:
msg = "Hash expression is missing required field {key}".format(key=key)
self.module.fail_json(msg)
def create_alert_dict(self, params):
""" Create a dict representing an alert
"""
if params['expression_type'] == 'hash':
# hash expression supports depends on https://github.com/ManageIQ/manageiq-api/pull/76
self.validate_hash_expression(params['expression'])
expression_type = 'hash_expression'
else:
# actually miq_expression, but we call it "expression" for backwards-compatibility
expression_type = 'expression'
# build the alret
alert = dict(description=params['description'],
db=params['resource_type'],
options=params['options'],
enabled=params['enabled'])
# add the actual expression.
alert.update({expression_type: params['expression']})
return alert
def add_alert(self, alert):
""" Add a new alert to ManageIQ
"""
try:
result = self.client.post(self.alerts_url, action='create', resource=alert)
msg = "Alert {description} created successfully: {details}"
msg = msg.format(description=alert['description'], details=result)
return dict(changed=True, msg=msg)
except Exception as e:
msg = "Creating alert {description} failed: {error}"
if "Resource expression needs be specified" in str(e):
# Running on an older version of ManageIQ and trying to create a hash expression
msg = msg.format(description=alert['description'],
error="Your version of ManageIQ does not support hash_expression")
else:
msg = msg.format(description=alert['description'], error=e)
self.module.fail_json(msg=msg)
def delete_alert(self, alert):
""" Delete an alert
"""
try:
result = self.client.post('{url}/{id}'.format(url=self.alerts_url,
id=alert['id']),
action="delete")
msg = "Alert {description} deleted: {details}"
msg = msg.format(description=alert['description'], details=result)
return dict(changed=True, msg=msg)
except Exception as e:
msg = "Deleting alert {description} failed: {error}"
msg = msg.format(description=alert['description'], error=e)
self.module.fail_json(msg=msg)
def update_alert(self, existing_alert, new_alert):
""" Update an existing alert with the values from `new_alert`
"""
new_alert_obj = ManageIQAlert(new_alert)
if new_alert_obj == ManageIQAlert(existing_alert):
# no change needed - alerts are identical
return dict(changed=False, msg="No update needed")
else:
try:
url = '{url}/{id}'.format(url=self.alerts_url, id=existing_alert['id'])
result = self.client.post(url, action="edit", resource=new_alert)
# make sure that the update was indeed successful by comparing
# the result to the expected result.
if new_alert_obj == ManageIQAlert(result):
# success!
msg = "Alert {description} upated successfully: {details}"
msg = msg.format(description=existing_alert['description'], details=result)
return dict(changed=True, msg=msg)
else:
# unexpected result
msg = "Updating alert {description} failed, unexpected result {details}"
msg = msg.format(description=existing_alert['description'], details=result)
self.module.fail_json(msg=msg)
except Exception as e:
msg = "Updating alert {description} failed: {error}"
if "Resource expression needs be specified" in str(e):
# Running on an older version of ManageIQ and trying to update a hash expression
msg = msg.format(description=existing_alert['description'],
error="Your version of ManageIQ does not support hash_expression")
else:
msg = msg.format(description=existing_alert['description'], error=e)
self.module.fail_json(msg=msg)
def main():
argument_spec = dict(
description=dict(type='str'),
resource_type=dict(type='str', choices=['Vm',
'ContainerNode',
'MiqServer',
'Host',
'Storage',
'EmsCluster',
'ExtManagementSystem',
'MiddlewareServer']),
expression_type=dict(type='str', default='hash', choices=['miq', 'hash']),
expression=dict(type='dict'),
options=dict(type='dict'),
enabled=dict(type='bool'),
state=dict(require=False, default='present',
choices=['present', 'absent']),
)
# add the manageiq connection arguments to the arguments
argument_spec.update(manageiq_argument_spec())
module = AnsibleModule(argument_spec=argument_spec,
required_if=[('state', 'present', ['description',
'resource_type',
'expression',
'enabled',
'options']),
('state', 'absent', ['description'])])
state = module.params['state']
description = module.params['description']
manageiq = ManageIQ(module)
manageiq_alerts = ManageIQAlerts(manageiq)
existing_alert = manageiq.find_collection_resource_by("alert_definitions",
description=description)
# we need to add or update the alert
if state == "present":
alert = manageiq_alerts.create_alert_dict(module.params)
if not existing_alert:
# an alert with this description doesn't exist yet, let's create it
res_args = manageiq_alerts.add_alert(alert)
else:
# an alert with this description exists, we might need to update it
res_args = manageiq_alerts.update_alert(existing_alert, alert)
# this alert should not exist
elif state == "absent":
# if we have an alert with this description, delete it
if existing_alert:
res_args = manageiq_alerts.delete_alert(existing_alert)
else:
# it doesn't exist, and that's okay
msg = "Alert '{description}' does not exist in ManageIQ"
msg = msg.format(description=description)
res_args = dict(changed=False, msg=msg)
module.exit_json(**res_args)
if __name__ == "__main__":
main()