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

303 lines
11 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_alert_profiles
short_description: Configuration of alert profiles for ManageIQ
extends_documentation_fragment: manageiq
version_added: '2.5'
author: Elad Alfassa (@elad661) <ealfassa@redhat.com>
description:
- The manageiq_alert_profiles module supports adding, updating and deleting alert profiles in ManageIQ.
options:
state:
description:
- absent - alert profile should not exist,
- present - alert profile should exist,
choices: ['absent', 'present']
default: 'present'
name:
description:
- The unique alert profile name in ManageIQ.
- Required when state is "absent" or "present".
resource_type:
description:
- The resource type for the alert profile in ManageIQ. Required when state is "present".
choices: ['Vm', 'ContainerNode', 'MiqServer', 'Host', 'Storage', 'EmsCluster',
'ExtManagementSystem', 'MiddlewareServer']
alerts:
description:
- List of alert descriptions to assign to this profile.
- Required if state is "present"
notes:
description:
- Optional notes for this profile
'''
EXAMPLES = '''
- name: Add an alert profile to ManageIQ
manageiq_alert_profiles:
state: present
name: Test profile
resource_type: ContainerNode
alerts:
- Test Alert 01
- Test Alert 02
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 profile from ManageIQ
manageiq_alert_profiles:
state: absent
name: Test profile
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 ManageIQAlertProfiles(object):
""" Object to execute alert profile 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.url = '{api_url}/alert_definition_profiles'.format(api_url=self.api_url)
def get_profiles(self):
""" Get all alert profiles from ManageIQ
"""
try:
response = self.client.get(self.url + '?expand=alert_definitions,resources')
except Exception as e:
self.module.fail_json(msg="Failed to query alert profiles: {error}".format(error=e))
return response.get('resources') or []
def get_alerts(self, alert_descriptions):
""" Get a list of alert hrefs from a list of alert descriptions
"""
alerts = []
for alert_description in alert_descriptions:
alert = self.manageiq.find_collection_resource_or_fail("alert_definitions",
description=alert_description)
alerts.append(alert['href'])
return alerts
def add_profile(self, profile):
""" Add a new alert profile to ManageIQ
"""
# find all alerts to add to the profile
# we do this first to fail early if one is missing.
alerts = self.get_alerts(profile['alerts'])
# build the profile dict to send to the server
profile_dict = dict(name=profile['name'],
description=profile['name'],
mode=profile['resource_type'])
if profile['notes']:
profile_dict['set_data'] = dict(notes=profile['notes'])
# send it to the server
try:
result = self.client.post(self.url, resource=profile_dict, action="create")
except Exception as e:
self.module.fail_json(msg="Creating profile failed {error}".format(error=e))
# now that it has been created, we can assign the alerts
self.assign_or_unassign(result['results'][0], alerts, "assign")
msg = "Profile {name} created successfully"
msg = msg.format(name=profile['name'])
return dict(changed=True, msg=msg)
def delete_profile(self, profile):
""" Delete an alert profile from ManageIQ
"""
try:
self.client.post(profile['href'], action="delete")
except Exception as e:
self.module.fail_json(msg="Deleting profile failed: {error}".format(error=e))
msg = "Successfuly deleted profile {name}".format(name=profile['name'])
return dict(changed=True, msg=msg)
def get_alert_href(self, alert):
""" Get an absolute href for an alert
"""
return "{url}/alert_definitions/{id}".format(url=self.api_url, id=alert['id'])
def assign_or_unassign(self, profile, resources, action):
""" Assign or unassign alerts to profile, and validate the result.
"""
alerts = [dict(href=href) for href in resources]
subcollection_url = profile['href'] + '/alert_definitions'
try:
result = self.client.post(subcollection_url, resources=alerts, action=action)
if len(result['results']) != len(alerts):
msg = "Failed to {action} alerts to profile '{name}'," +\
"expected {expected} alerts to be {action}ed," +\
"but only {changed} were {action}ed"
msg = msg.format(action=action,
name=profile['name'],
expected=len(alerts),
changed=result['results'])
self.module.fail_json(msg=msg)
except Exception as e:
msg = "Failed to {action} alerts to profile '{name}': {error}"
msg = msg.format(action=action, name=profile['name'], error=e)
self.module.fail_json(msg=msg)
return result['results']
def update_profile(self, old_profile, desired_profile):
""" Update alert profile in ManageIQ
"""
changed = False
# we need to use client.get to query the alert definitions
old_profile = self.client.get(old_profile['href'] + '?expand=alert_definitions')
# figure out which alerts we need to assign / unassign
# alerts listed by the user:
desired_alerts = set(self.get_alerts(desired_profile['alerts']))
# alert which currently exist in the profile
if 'alert_definitions' in old_profile:
# we use get_alert_href to have a direct href to the alert
existing_alerts = set([self.get_alert_href(alert) for alert in old_profile['alert_definitions']])
else:
# no alerts in this profile
existing_alerts = set()
to_add = list(desired_alerts - existing_alerts)
to_remove = list(existing_alerts - desired_alerts)
# assign / unassign the alerts, if needed
if to_remove:
self.assign_or_unassign(old_profile, to_remove, "unassign")
changed = True
if to_add:
self.assign_or_unassign(old_profile, to_add, "assign")
changed = True
# update other properties
profile_dict = dict()
if old_profile['mode'] != desired_profile['resource_type']:
# mode needs to be updated
profile_dict['mode'] = desired_profile['resource_type']
# check if notes need to be updated
old_notes = old_profile.get('set_data', {}).get('notes')
if desired_profile['notes'] != old_notes:
profile_dict['set_data'] = dict(notes=desired_profile['notes'])
if profile_dict:
# if we have any updated values
changed = True
try:
result = self.client.post(old_profile['href'],
resource=profile_dict,
action="edit")
except Exception as e:
msg = "Updating profile '{name}' failed: {error}"
msg = msg.format(name=old_profile['name'], error=e)
self.module.fail_json(msg=msg, result=result)
if changed:
msg = "Profile {name} updated successfully".format(name=desired_profile['name'])
else:
msg = "No update needed for profile {name}".format(name=desired_profile['name'])
return dict(changed=changed, msg=msg)
def main():
argument_spec = dict(
name=dict(type='str'),
resource_type=dict(type='str', choices=['Vm',
'ContainerNode',
'MiqServer',
'Host',
'Storage',
'EmsCluster',
'ExtManagementSystem',
'MiddlewareServer']),
alerts=dict(type='list'),
notes=dict(type='str'),
state=dict(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', ['name', 'resource_type']),
('state', 'absent', ['name'])])
state = module.params['state']
name = module.params['name']
manageiq = ManageIQ(module)
manageiq_alert_profiles = ManageIQAlertProfiles(manageiq)
existing_profile = manageiq.find_collection_resource_by("alert_definition_profiles",
name=name)
# we need to add or update the alert profile
if state == "present":
if not existing_profile:
# a profile with this name doesn't exist yet, let's create it
res_args = manageiq_alert_profiles.add_profile(module.params)
else:
# a profile with this name exists, we might need to update it
res_args = manageiq_alert_profiles.update_profile(existing_profile, module.params)
# this alert profile should not exist
if state == "absent":
# if we have an alert profile with this name, delete it
if existing_profile:
res_args = manageiq_alert_profiles.delete_profile(existing_profile)
else:
# This alert profile does not exist in ManageIQ, and that's okay
msg = "Alert profile '{name}' does not exist in ManageIQ"
msg = msg.format(name=name)
res_args = dict(changed=False, msg=msg)
module.exit_json(**res_args)
if __name__ == "__main__":
main()