summaryrefslogtreecommitdiffstats
path: root/collections-debian-merged/ansible_collections/community/rabbitmq/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'collections-debian-merged/ansible_collections/community/rabbitmq/plugins')
-rw-r--r--collections-debian-merged/ansible_collections/community/rabbitmq/plugins/doc_fragments/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/community/rabbitmq/plugins/doc_fragments/rabbitmq.py60
-rw-r--r--collections-debian-merged/ansible_collections/community/rabbitmq/plugins/lookup/rabbitmq.py189
-rw-r--r--collections-debian-merged/ansible_collections/community/rabbitmq/plugins/module_utils/rabbitmq.py220
-rw-r--r--collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_binding.py298
-rw-r--r--collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_exchange.py209
-rw-r--r--collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_global_parameter.py155
-rw-r--r--collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_parameter.py155
-rw-r--r--collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_plugin.py187
-rw-r--r--collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_policy.py248
-rw-r--r--collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_publish.py220
-rw-r--r--collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_queue.py257
-rw-r--r--collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_user.py463
-rw-r--r--collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_vhost.py142
-rw-r--r--collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_vhost_limits.py173
15 files changed, 2976 insertions, 0 deletions
diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/doc_fragments/__init__.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/doc_fragments/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/doc_fragments/__init__.py
diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/doc_fragments/rabbitmq.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/doc_fragments/rabbitmq.py
new file mode 100644
index 00000000..acae82e8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/doc_fragments/rabbitmq.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2016, Jorge Rodriguez <jorge.rodriguez@tiriel.eu>
+# 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
+
+
+class ModuleDocFragment(object):
+ # Parameters for RabbitMQ modules
+ DOCUMENTATION = r'''
+options:
+ login_user:
+ description:
+ - RabbitMQ user for connection.
+ type: str
+ default: guest
+ login_password:
+ description:
+ - RabbitMQ password for connection.
+ type: str
+ default: guest
+ login_host:
+ description:
+ - RabbitMQ host for connection.
+ type: str
+ default: localhost
+ login_port:
+ description:
+ - RabbitMQ management API port.
+ type: str
+ default: '15672'
+ login_protocol:
+ description:
+ - RabbitMQ management API protocol.
+ type: str
+ choices: [ http , https ]
+ default: http
+ ca_cert:
+ description:
+ - CA certificate to verify SSL connection to management API.
+ type: path
+ aliases: [ cacert ]
+ client_cert:
+ description:
+ - Client certificate to send on SSL connections to management API.
+ type: path
+ aliases: [ cert ]
+ client_key:
+ description:
+ - Private key matching the client certificate.
+ type: path
+ aliases: [ key ]
+ vhost:
+ description:
+ - RabbitMQ virtual host.
+ type: str
+ default: "/"
+'''
diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/lookup/rabbitmq.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/lookup/rabbitmq.py
new file mode 100644
index 00000000..406936de
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/lookup/rabbitmq.py
@@ -0,0 +1,189 @@
+# (c) 2018, John Imison <john+github@imison.net>
+# 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 = '''
+ lookup: rabbitmq
+ author: John Imison <@Im0>
+ short_description: Retrieve messages from an AMQP/AMQPS RabbitMQ queue.
+ description:
+ - This lookup uses a basic get to retrieve all, or a limited number C(count), messages from a RabbitMQ queue.
+ options:
+ url:
+ description:
+ - An URI connection string to connect to the AMQP/AMQPS RabbitMQ server.
+ - For more information refer to the URI spec U(https://www.rabbitmq.com/uri-spec.html).
+ required: True
+ queue:
+ description:
+ - The queue to get messages from.
+ required: True
+ count:
+ description:
+ - How many messages to collect from the queue.
+ - If not set, defaults to retrieving all the messages from the queue.
+ requirements:
+ - The python pika package U(https://pypi.org/project/pika/).
+ notes:
+ - This lookup implements BlockingChannel.basic_get to get messages from a RabbitMQ server.
+ - After retrieving a message from the server, receipt of the message is acknowledged and the message on the server is deleted.
+ - Pika is a pure-Python implementation of the AMQP 0-9-1 protocol that tries to stay fairly independent of the underlying network support library.
+ - More information about pika can be found at U(https://pika.readthedocs.io/en/stable/).
+ - This plugin is tested against RabbitMQ. Other AMQP 0.9.1 protocol based servers may work but not tested/guaranteed.
+ - Assigning the return messages to a variable under C(vars) may result in unexpected results as the lookup is evaluated every time the
+ variable is referenced.
+ - Currently this plugin only handles text based messages from a queue. Unexpected results may occur when retrieving binary data.
+'''
+
+
+EXAMPLES = """
+- name: Get all messages off a queue
+ debug:
+ msg: "{{ lookup('community.rabbitmq.rabbitmq', url='amqp://guest:guest@192.168.0.10:5672/%2F', queue='hello') }}"
+
+
+# If you are intending on using the returned messages as a variable in more than
+# one task (eg. debug, template), it is recommended to set_fact.
+
+- name: Get 2 messages off a queue and set a fact for re-use
+ set_fact:
+ messages: "{{ lookup('community.rabbitmq.rabbiotmq', url='amqp://guest:guest@192.168.0.10:5672/%2F', queue='hello', count=2) }}"
+
+- name: Dump out contents of the messages
+ debug:
+ var: messages
+
+"""
+
+RETURN = """
+ _list:
+ description:
+ - A list of dictionaries with keys and value from the queue.
+ type: list
+ contains:
+ content_type:
+ description: The content_type on the message in the queue.
+ type: str
+ delivery_mode:
+ description: The delivery_mode on the message in the queue.
+ type: str
+ delivery_tag:
+ description: The delivery_tag on the message in the queue.
+ type: str
+ exchange:
+ description: The exchange the message came from.
+ type: str
+ message_count:
+ description: The message_count for the message on the queue.
+ type: str
+ msg:
+ description: The content of the message.
+ type: str
+ redelivered:
+ description: The redelivered flag. True if the message has been delivered before.
+ type: bool
+ routing_key:
+ description: The routing_key on the message in the queue.
+ type: str
+ headers:
+ description: The headers for the message returned from the queue.
+ type: dict
+ json:
+ description: If application/json is specified in content_type, json will be loaded into variables.
+ type: dict
+
+"""
+
+import json
+
+from ansible.errors import AnsibleError, AnsibleParserError
+from ansible.plugins.lookup import LookupBase
+from ansible.module_utils._text import to_native, to_text
+from ansible.utils.display import Display
+
+try:
+ import pika
+ from pika import spec
+ HAS_PIKA = True
+except ImportError:
+ HAS_PIKA = False
+
+display = Display()
+
+
+class LookupModule(LookupBase):
+
+ def run(self, terms, variables=None, url=None, queue=None, count=None):
+ if not HAS_PIKA:
+ raise AnsibleError('pika python package is required for rabbitmq lookup.')
+ if not url:
+ raise AnsibleError('URL is required for rabbitmq lookup.')
+ if not queue:
+ raise AnsibleError('Queue is required for rabbitmq lookup.')
+
+ display.vvv(u"terms:%s : variables:%s url:%s queue:%s count:%s" % (terms, variables, url, queue, count))
+
+ try:
+ parameters = pika.URLParameters(url)
+ except Exception as e:
+ raise AnsibleError("URL malformed: %s" % to_native(e))
+
+ try:
+ connection = pika.BlockingConnection(parameters)
+ except Exception as e:
+ raise AnsibleError("Connection issue: %s" % to_native(e))
+
+ try:
+ conn_channel = connection.channel()
+ except pika.exceptions.AMQPChannelError as e:
+ try:
+ connection.close()
+ except pika.exceptions.AMQPConnectionError as ie:
+ raise AnsibleError("Channel and connection closing issues: %s / %s" % to_native(e), to_native(ie))
+ raise AnsibleError("Channel issue: %s" % to_native(e))
+
+ ret = []
+ idx = 0
+
+ while True:
+ method_frame, properties, body = conn_channel.basic_get(queue=queue)
+ if method_frame:
+ display.vvv(u"%s, %s, %s " % (method_frame, properties, to_text(body)))
+
+ # TODO: In the future consider checking content_type and handle text/binary data differently.
+ msg_details = dict({
+ 'msg': to_text(body),
+ 'message_count': method_frame.message_count,
+ 'routing_key': method_frame.routing_key,
+ 'delivery_tag': method_frame.delivery_tag,
+ 'redelivered': method_frame.redelivered,
+ 'exchange': method_frame.exchange,
+ 'delivery_mode': properties.delivery_mode,
+ 'content_type': properties.content_type,
+ 'headers': properties.headers
+ })
+ if properties.content_type == 'application/json':
+ try:
+ msg_details['json'] = json.loads(msg_details['msg'])
+ except ValueError as e:
+ raise AnsibleError("Unable to decode JSON for message %s: %s" % (method_frame.delivery_tag, to_native(e)))
+
+ ret.append(msg_details)
+ conn_channel.basic_ack(method_frame.delivery_tag)
+ idx += 1
+ if method_frame.message_count == 0 or idx == count:
+ break
+ # If we didn't get a method_frame, exit.
+ else:
+ break
+
+ if connection.is_closed:
+ return [ret]
+ else:
+ try:
+ connection.close()
+ except pika.exceptions.AMQPConnectionError:
+ pass
+ return [ret]
diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/module_utils/rabbitmq.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/module_utils/rabbitmq.py
new file mode 100644
index 00000000..cf764006
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/module_utils/rabbitmq.py
@@ -0,0 +1,220 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright: (c) 2016, Jorge Rodriguez <jorge.rodriguez@tiriel.eu>
+# Copyright: (c) 2018, John Imison <john+github@imison.net>
+#
+# 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
+
+from ansible.module_utils._text import to_native
+from ansible.module_utils.basic import missing_required_lib
+from ansible.module_utils.six.moves.urllib import parse as urllib_parse
+from mimetypes import MimeTypes
+
+import os
+import json
+import traceback
+
+PIKA_IMP_ERR = None
+try:
+ import pika
+ import pika.exceptions
+ from pika import spec
+ HAS_PIKA = True
+except ImportError:
+ PIKA_IMP_ERR = traceback.format_exc()
+ HAS_PIKA = False
+
+
+def rabbitmq_argument_spec():
+ return dict(
+ login_user=dict(type='str', default='guest'),
+ login_password=dict(type='str', default='guest', no_log=True),
+ login_host=dict(type='str', default='localhost'),
+ login_port=dict(type='str', default='15672'),
+ login_protocol=dict(type='str', default='http', choices=['http', 'https']),
+ ca_cert=dict(type='path', aliases=['cacert']),
+ client_cert=dict(type='path', aliases=['cert']),
+ client_key=dict(type='path', aliases=['key']),
+ vhost=dict(type='str', default='/'),
+ )
+
+
+# notification/rabbitmq_basic_publish.py
+class RabbitClient():
+ def __init__(self, module):
+ self.module = module
+ self.params = module.params
+ self.check_required_library()
+ self.check_host_params()
+ self.url = self.params['url']
+ self.proto = self.params['proto']
+ self.username = self.params['username']
+ self.password = self.params['password']
+ self.host = self.params['host']
+ self.port = self.params['port']
+ self.vhost = self.params['vhost']
+ self.queue = self.params['queue']
+ self.headers = self.params['headers']
+ self.cafile = self.params['cafile']
+ self.certfile = self.params['certfile']
+ self.keyfile = self.params['keyfile']
+
+ if self.host is not None:
+ self.build_url()
+
+ if self.cafile is not None:
+ self.append_ssl_certs()
+
+ self.connect_to_rabbitmq()
+
+ def check_required_library(self):
+ if not HAS_PIKA:
+ self.module.fail_json(msg=missing_required_lib("pika"), exception=PIKA_IMP_ERR)
+
+ def check_host_params(self):
+ # Fail if url is specified and other conflicting parameters have been specified
+ if self.params['url'] is not None and any(self.params[k] is not None for k in ['proto', 'host', 'port', 'password', 'username', 'vhost']):
+ self.module.fail_json(msg="url and proto, host, port, vhost, username or password cannot be specified at the same time.")
+
+ # Fail if url not specified and there is a missing parameter to build the url
+ if self.params['url'] is None and any(self.params[k] is None for k in ['proto', 'host', 'port', 'password', 'username', 'vhost']):
+ self.module.fail_json(msg="Connection parameters must be passed via url, or, proto, host, port, vhost, username or password.")
+
+ def append_ssl_certs(self):
+ ssl_options = {}
+ if self.cafile:
+ ssl_options['cafile'] = self.cafile
+ if self.certfile:
+ ssl_options['certfile'] = self.certfile
+ if self.keyfile:
+ ssl_options['keyfile'] = self.keyfile
+
+ self.url = self.url + '?ssl_options=' + urllib_parse.quote(json.dumps(ssl_options))
+
+ @staticmethod
+ def rabbitmq_argument_spec():
+ return dict(
+ url=dict(type='str'),
+ proto=dict(type='str', choices=['amqp', 'amqps']),
+ host=dict(type='str'),
+ port=dict(type='int'),
+ username=dict(type='str'),
+ password=dict(type='str', no_log=True),
+ vhost=dict(type='str'),
+ queue=dict(type='str')
+ )
+
+ ''' Consider some file size limits here '''
+ def _read_file(self, path):
+ try:
+ with open(path, "rb") as file_handle:
+ return file_handle.read()
+ except IOError as e:
+ self.module.fail_json(msg="Unable to open file %s: %s" % (path, to_native(e)))
+
+ @staticmethod
+ def _check_file_mime_type(path):
+ mime = MimeTypes()
+ return mime.guess_type(path)
+
+ def build_url(self):
+ self.url = '{0}://{1}:{2}@{3}:{4}/{5}'.format(self.proto,
+ self.username,
+ self.password,
+ self.host,
+ self.port,
+ self.vhost)
+
+ def connect_to_rabbitmq(self):
+ """
+ Function to connect to rabbitmq using username and password
+ """
+ try:
+ parameters = pika.URLParameters(self.url)
+ except Exception as e:
+ self.module.fail_json(msg="URL malformed: %s" % to_native(e))
+
+ try:
+ self.connection = pika.BlockingConnection(parameters)
+ except Exception as e:
+ self.module.fail_json(msg="Connection issue: %s" % to_native(e))
+
+ try:
+ self.conn_channel = self.connection.channel()
+ except pika.exceptions.AMQPChannelError as e:
+ self.close_connection()
+ self.module.fail_json(msg="Channel issue: %s" % to_native(e))
+
+ def close_connection(self):
+ try:
+ self.connection.close()
+ except pika.exceptions.AMQPConnectionError:
+ pass
+
+ def basic_publish(self):
+ self.content_type = self.params.get("content_type")
+
+ if self.params.get("body") is not None:
+ args = dict(
+ body=self.params.get("body"),
+ exchange=self.params.get("exchange"),
+ routing_key=self.params.get("routing_key"),
+ properties=pika.BasicProperties(content_type=self.content_type, delivery_mode=1, headers=self.headers))
+
+ # If src (file) is defined and content_type is left as default, do a mime lookup on the file
+ if self.params.get("src") is not None and self.content_type == 'text/plain':
+ self.content_type = RabbitClient._check_file_mime_type(self.params.get("src"))[0]
+ self.headers.update(
+ filename=os.path.basename(self.params.get("src"))
+ )
+
+ args = dict(
+ body=self._read_file(self.params.get("src")),
+ exchange=self.params.get("exchange"),
+ routing_key=self.params.get("routing_key"),
+ properties=pika.BasicProperties(content_type=self.content_type,
+ delivery_mode=1,
+ headers=self.headers
+ ))
+ elif self.params.get("src") is not None:
+ args = dict(
+ body=self._read_file(self.params.get("src")),
+ exchange=self.params.get("exchange"),
+ routing_key=self.params.get("routing_key"),
+ properties=pika.BasicProperties(content_type=self.content_type,
+ delivery_mode=1,
+ headers=self.headers
+ ))
+
+ try:
+ # If queue is not defined, RabbitMQ will return the queue name of the automatically generated queue.
+ if self.queue is None:
+ result = self.conn_channel.queue_declare(durable=self.params.get("durable"),
+ exclusive=self.params.get("exclusive"),
+ auto_delete=self.params.get("auto_delete"))
+ self.conn_channel.confirm_delivery()
+ self.queue = result.method.queue
+ else:
+ self.conn_channel.queue_declare(queue=self.queue,
+ durable=self.params.get("durable"),
+ exclusive=self.params.get("exclusive"),
+ auto_delete=self.params.get("auto_delete"))
+ self.conn_channel.confirm_delivery()
+ except Exception as e:
+ self.module.fail_json(msg="Queue declare issue: %s" % to_native(e))
+
+ # https://github.com/ansible/ansible/blob/devel/lib/ansible/module_utils/cloudstack.py#L150
+ if args['routing_key'] is None:
+ args['routing_key'] = self.queue
+
+ if args['exchange'] is None:
+ args['exchange'] = ''
+
+ try:
+ self.conn_channel.basic_publish(**args)
+ return True
+ except pika.exceptions.UnroutableError:
+ return False
diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_binding.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_binding.py
new file mode 100644
index 00000000..80194e20
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_binding.py
@@ -0,0 +1,298 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2015, Manuel Sousa <manuel.sousa@gmail.com>
+# 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: rabbitmq_binding
+author: Manuel Sousa (@manuel-sousa)
+
+short_description: Manage rabbitMQ bindings
+description:
+ - This module uses rabbitMQ REST APIs to create / delete bindings.
+requirements: [ "requests >= 1.0.0" ]
+options:
+ state:
+ description:
+ - Whether the bindings should be present or absent.
+ type: str
+ choices: [ "present", "absent" ]
+ default: present
+ name:
+ description:
+ - source exchange to create binding on.
+ type: str
+ required: true
+ aliases: [ "src", "source" ]
+ destination:
+ description:
+ - destination exchange or queue for the binding.
+ type: str
+ required: true
+ aliases: [ "dst", "dest" ]
+ destination_type:
+ description:
+ - Either queue or exchange.
+ type: str
+ required: true
+ choices: [ "queue", "exchange" ]
+ aliases: [ "type", "dest_type" ]
+ routing_key:
+ description:
+ - routing key for the binding.
+ type: str
+ default: "#"
+ arguments:
+ description:
+ - extra arguments for exchange. If defined this argument is a key/value dictionary
+ type: dict
+ required: false
+ default: {}
+extends_documentation_fragment:
+ - community.rabbitmq.rabbitmq
+
+'''
+
+EXAMPLES = '''
+# Bind myQueue to directExchange with routing key info
+- community.rabbitmq.rabbitmq_binding:
+ name: directExchange
+ destination: myQueue
+ type: queue
+ routing_key: info
+
+# Bind directExchange to topicExchange with routing key *.info
+- community.rabbitmq.rabbitmq_binding:
+ name: topicExchange
+ destination: topicExchange
+ type: exchange
+ routing_key: '*.info'
+'''
+
+import json
+import traceback
+
+REQUESTS_IMP_ERR = None
+try:
+ import requests
+ HAS_REQUESTS = True
+except ImportError:
+ REQUESTS_IMP_ERR = traceback.format_exc()
+ HAS_REQUESTS = False
+
+from ansible.module_utils.six.moves.urllib import parse as urllib_parse
+from ansible.module_utils.basic import AnsibleModule, missing_required_lib
+from ansible_collections.community.rabbitmq.plugins.module_utils.rabbitmq import rabbitmq_argument_spec
+
+
+class RabbitMqBinding(object):
+ def __init__(self, module):
+ """
+ :param module:
+ """
+ self.module = module
+ self.name = self.module.params['name']
+ self.login_user = self.module.params['login_user']
+ self.login_password = self.module.params['login_password']
+ self.login_host = self.module.params['login_host']
+ self.login_port = self.module.params['login_port']
+ self.login_protocol = self.module.params['login_protocol']
+ self.vhost = self.module.params['vhost']
+ self.destination = self.module.params['destination']
+ self.destination_type = 'q' if self.module.params['destination_type'] == 'queue' else 'e'
+ self.routing_key = self.module.params['routing_key']
+ self.arguments = self.module.params['arguments']
+ self.verify = self.module.params['ca_cert']
+ self.cert = self.module.params['client_cert']
+ self.key = self.module.params['client_key']
+ self.props = urllib_parse.quote(self.routing_key) if self.routing_key != '' else '~'
+ self.base_url = '{0}://{1}:{2}/api/bindings'.format(self.login_protocol,
+ self.login_host,
+ self.login_port)
+ self.url = '{0}/{1}/e/{2}/{3}/{4}/{5}'.format(self.base_url,
+ urllib_parse.quote(self.vhost, safe=''),
+ urllib_parse.quote(self.name, safe=''),
+ self.destination_type,
+ urllib_parse.quote(self.destination, safe=''),
+ self.props)
+ self.result = {
+ 'changed': False,
+ 'name': self.module.params['name'],
+ }
+ self.authentication = (
+ self.login_user,
+ self.login_password
+ )
+ self.request = requests
+ self.http_check_states = {
+ 200: True,
+ 404: False,
+ }
+ self.http_actionable_states = {
+ 201: True,
+ 204: True,
+ }
+ self.api_result = self.request.get(self.url, auth=self.authentication, verify=self.verify, cert=(self.cert, self.key))
+
+ def run(self):
+ """
+ :return:
+ """
+ self.check_presence()
+ self.check_mode()
+ self.action_mode()
+
+ def check_presence(self):
+ """
+ :return:
+ """
+ if self.check_should_throw_fail():
+ self.fail()
+
+ def change_required(self):
+ """
+ :return:
+ """
+ if self.module.params['state'] == 'present':
+ if not self.is_present():
+ return True
+ elif self.module.params['state'] == 'absent':
+ if self.is_present():
+ return True
+ return False
+
+ def is_present(self):
+ """
+ :return:
+ """
+ return self.http_check_states.get(self.api_result.status_code, False)
+
+ def check_mode(self):
+ """
+ :return:
+ """
+ if self.module.check_mode:
+ result = self.result
+ result['changed'] = self.change_required()
+ result['details'] = self.api_result.json() if self.is_present() else self.api_result.text
+ result['arguments'] = self.module.params['arguments']
+ self.module.exit_json(**result)
+
+ def check_reply_is_correct(self):
+ """
+ :return:
+ """
+ if self.api_result.status_code in self.http_check_states:
+ return True
+ return False
+
+ def check_should_throw_fail(self):
+ """
+ :return:
+ """
+ if not self.is_present():
+ if not self.check_reply_is_correct():
+ return True
+ return False
+
+ def action_mode(self):
+ """
+ :return:
+ """
+ result = self.result
+ if self.change_required():
+ if self.module.params['state'] == 'present':
+ self.create()
+ if self.module.params['state'] == 'absent':
+ self.remove()
+ if self.action_should_throw_fail():
+ self.fail()
+ result['changed'] = True
+ result['destination'] = self.module.params['destination']
+ self.module.exit_json(**result)
+ else:
+ result['changed'] = False
+ self.module.exit_json(**result)
+
+ def action_reply_is_correct(self):
+ """
+ :return:
+ """
+ if self.api_result.status_code in self.http_actionable_states:
+ return True
+ return False
+
+ def action_should_throw_fail(self):
+ """
+ :return:
+ """
+ if not self.action_reply_is_correct():
+ return True
+ return False
+
+ def create(self):
+ """
+ :return:
+ """
+ self.url = '{0}/{1}/e/{2}/{3}/{4}'.format(self.base_url,
+ urllib_parse.quote(self.vhost, safe=''),
+ urllib_parse.quote(self.name, safe=''),
+ self.destination_type,
+ urllib_parse.quote(self.destination, safe=''))
+ self.api_result = self.request.post(self.url,
+ auth=self.authentication,
+ verify=self.verify,
+ cert=(self.cert, self.key),
+ headers={"content-type": "application/json"},
+ data=json.dumps({
+ 'routing_key': self.routing_key,
+ 'arguments': self.arguments
+ }))
+
+ def remove(self):
+ """
+ :return:
+ """
+ self.api_result = self.request.delete(self.url, auth=self.authentication, verify=self.verify, cert=(self.cert, self.key))
+
+ def fail(self):
+ """
+ :return:
+ """
+ self.module.fail_json(
+ msg="Unexpected reply from API",
+ status=self.api_result.status_code,
+ details=self.api_result.text
+ )
+
+
+def main():
+
+ argument_spec = rabbitmq_argument_spec()
+ argument_spec.update(
+ dict(
+ state=dict(default='present', choices=['present', 'absent'], type='str'),
+ name=dict(required=True, aliases=["src", "source"], type='str'),
+ destination=dict(required=True, aliases=["dst", "dest"], type='str'),
+ destination_type=dict(required=True, aliases=["type", "dest_type"], choices=["queue", "exchange"],
+ type='str'),
+ routing_key=dict(default='#', type='str'),
+ arguments=dict(default=dict(), type='dict')
+ )
+ )
+ module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
+
+ if not HAS_REQUESTS:
+ module.fail_json(msg=missing_required_lib("requests"), exception=REQUESTS_IMP_ERR)
+
+ RabbitMqBinding(module).run()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_exchange.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_exchange.py
new file mode 100644
index 00000000..0feb07ed
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_exchange.py
@@ -0,0 +1,209 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2015, Manuel Sousa <manuel.sousa@gmail.com>
+# 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: rabbitmq_exchange
+author: Manuel Sousa (@manuel-sousa)
+
+short_description: Manage rabbitMQ exchanges
+description:
+ - This module uses rabbitMQ Rest API to create/delete exchanges
+requirements: [ "requests >= 1.0.0" ]
+options:
+ name:
+ description:
+ - Name of the exchange to create
+ type: str
+ required: true
+ state:
+ description:
+ - Whether the exchange should be present or absent
+ type: str
+ choices: [ "present", "absent" ]
+ required: false
+ default: present
+ durable:
+ description:
+ - whether exchange is durable or not
+ type: bool
+ required: false
+ default: yes
+ exchange_type:
+ description:
+ - type for the exchange
+ type: str
+ required: false
+ choices: [ "fanout", "direct", "headers", "topic" ]
+ aliases: [ "type" ]
+ default: direct
+ auto_delete:
+ description:
+ - if the exchange should delete itself after all queues/exchanges unbound from it
+ type: bool
+ required: false
+ default: no
+ internal:
+ description:
+ - exchange is available only for other exchanges
+ type: bool
+ required: false
+ default: no
+ arguments:
+ description:
+ - extra arguments for exchange. If defined this argument is a key/value dictionary
+ type: dict
+ required: false
+ default: {}
+extends_documentation_fragment:
+ - community.rabbitmq.rabbitmq
+
+'''
+
+EXAMPLES = '''
+# Create direct exchange
+- community.rabbitmq.rabbitmq_exchange:
+ name: directExchange
+
+# Create topic exchange on vhost
+- community.rabbitmq.rabbitmq_exchange:
+ name: topicExchange
+ type: topic
+ vhost: myVhost
+'''
+
+import json
+import traceback
+
+REQUESTS_IMP_ERR = None
+try:
+ import requests
+ HAS_REQUESTS = True
+except ImportError:
+ REQUESTS_IMP_ERR = traceback.format_exc()
+ HAS_REQUESTS = False
+
+from ansible.module_utils.basic import AnsibleModule, missing_required_lib
+from ansible.module_utils.six.moves.urllib import parse as urllib_parse
+from ansible_collections.community.rabbitmq.plugins.module_utils.rabbitmq import rabbitmq_argument_spec
+
+
+def main():
+
+ argument_spec = rabbitmq_argument_spec()
+ argument_spec.update(
+ dict(
+ state=dict(default='present', choices=['present', 'absent'], type='str'),
+ name=dict(required=True, type='str'),
+ durable=dict(default=True, type='bool'),
+ auto_delete=dict(default=False, type='bool'),
+ internal=dict(default=False, type='bool'),
+ exchange_type=dict(default='direct', aliases=['type'],
+ choices=['fanout', 'direct', 'headers', 'topic'],
+ type='str'),
+ arguments=dict(default=dict(), type='dict')
+ )
+ )
+ module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
+
+ url = "%s://%s:%s/api/exchanges/%s/%s" % (
+ module.params['login_protocol'],
+ module.params['login_host'],
+ module.params['login_port'],
+ urllib_parse.quote(module.params['vhost'], ''),
+ urllib_parse.quote(module.params['name'], '')
+ )
+
+ if not HAS_REQUESTS:
+ module.fail_json(msg=missing_required_lib("requests"), exception=REQUESTS_IMP_ERR)
+
+ result = dict(changed=False, name=module.params['name'])
+
+ # Check if exchange already exists
+ r = requests.get(url, auth=(module.params['login_user'], module.params['login_password']),
+ verify=module.params['ca_cert'], cert=(module.params['client_cert'], module.params['client_key']))
+
+ if r.status_code == 200:
+ exchange_exists = True
+ response = r.json()
+ elif r.status_code == 404:
+ exchange_exists = False
+ response = r.text
+ else:
+ module.fail_json(
+ msg="Invalid response from RESTAPI when trying to check if exchange exists",
+ details=r.text
+ )
+
+ if module.params['state'] == 'present':
+ change_required = not exchange_exists
+ else:
+ change_required = exchange_exists
+
+ # Check if attributes change on existing exchange
+ if not change_required and r.status_code == 200 and module.params['state'] == 'present':
+ if not (
+ response['durable'] == module.params['durable'] and
+ response['auto_delete'] == module.params['auto_delete'] and
+ response['internal'] == module.params['internal'] and
+ response['type'] == module.params['exchange_type']
+ ):
+ module.fail_json(
+ msg="RabbitMQ RESTAPI doesn't support attribute changes for existing exchanges"
+ )
+
+ # Exit if check_mode
+ if module.check_mode:
+ result['changed'] = change_required
+ result['details'] = response
+ result['arguments'] = module.params['arguments']
+ module.exit_json(**result)
+
+ # Do changes
+ if change_required:
+ if module.params['state'] == 'present':
+ r = requests.put(
+ url,
+ auth=(module.params['login_user'], module.params['login_password']),
+ headers={"content-type": "application/json"},
+ data=json.dumps({
+ "durable": module.params['durable'],
+ "auto_delete": module.params['auto_delete'],
+ "internal": module.params['internal'],
+ "type": module.params['exchange_type'],
+ "arguments": module.params['arguments']
+ }),
+ verify=module.params['ca_cert'],
+ cert=(module.params['client_cert'], module.params['client_key'])
+ )
+ elif module.params['state'] == 'absent':
+ r = requests.delete(url, auth=(module.params['login_user'], module.params['login_password']),
+ verify=module.params['ca_cert'], cert=(module.params['client_cert'], module.params['client_key']))
+
+ # RabbitMQ 3.6.7 changed this response code from 204 to 201
+ if r.status_code == 204 or r.status_code == 201:
+ result['changed'] = True
+ module.exit_json(**result)
+ else:
+ module.fail_json(
+ msg="Error creating exchange",
+ status=r.status_code,
+ details=r.text
+ )
+
+ else:
+ module.exit_json(
+ changed=False,
+ name=module.params['name']
+ )
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_global_parameter.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_global_parameter.py
new file mode 100644
index 00000000..97fc90cb
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_global_parameter.py
@@ -0,0 +1,155 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2013, Chatham Financial <oss@chathamfinancial.com>
+# Copyright: (c) 2017, Juergen Kirschbaum <jk@jk-itc.de>
+# 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: rabbitmq_global_parameter
+short_description: Manage RabbitMQ global parameters
+description:
+ - Manage dynamic, cluster-wide global parameters for RabbitMQ
+author: "Juergen Kirschbaum (@jgkirschbaum)"
+options:
+ name:
+ description:
+ - Name of the global parameter being set
+ type: str
+ required: true
+ default: null
+ value:
+ description:
+ - Value of the global parameter, as a JSON term
+ type: str
+ required: false
+ default: null
+ node:
+ description:
+ - erlang node name of the rabbit we wish to configure
+ type: str
+ required: false
+ default: rabbit
+ state:
+ description:
+ - Specify if user is to be added or removed
+ type: str
+ required: false
+ default: present
+ choices: [ 'present', 'absent']
+'''
+
+EXAMPLES = '''
+# Set the global parameter 'cluster_name' to a value of 'mq-cluster' (in quotes)
+- community.rabbitmq.rabbitmq_global_parameter:
+ name: cluster_name
+ value: "{{ 'mq-cluster' | to_json }}"
+ state: present
+'''
+
+RETURN = '''
+name:
+ description: name of the global parameter being set
+ returned: success
+ type: str
+ sample: "cluster_name"
+value:
+ description: value of the global parameter, as a JSON term
+ returned: changed
+ type: str
+ sample: "the-cluster-name"
+'''
+
+import json
+from ansible.module_utils.basic import AnsibleModule
+
+
+class RabbitMqGlobalParameter(object):
+ def __init__(self, module, name, value, node):
+ self.module = module
+ self.name = name
+ self.value = value
+ self.node = node
+
+ self._value = None
+
+ self._rabbitmqctl = module.get_bin_path('rabbitmqctl', True)
+
+ def _exec(self, args, run_in_check_mode=False):
+ if not self.module.check_mode or (self.module.check_mode and run_in_check_mode):
+ cmd = [self._rabbitmqctl, '-q', '-n', self.node]
+ rc, out, err = self.module.run_command(cmd + args, check_rc=True)
+ return out.splitlines()
+ return list()
+
+ def get(self):
+ global_parameters = self._exec(['list_global_parameters'], True)
+
+ for param_item in global_parameters:
+ name, value = param_item.split('\t')
+
+ if name == self.name:
+ self._value = json.loads(value)
+ return True
+ return False
+
+ def set(self):
+ self._exec(['set_global_parameter',
+ self.name,
+ json.dumps(self.value)])
+
+ def delete(self):
+ self._exec(['clear_global_parameter', self.name])
+
+ def has_modifications(self):
+ return self.value != self._value
+
+
+def main():
+ arg_spec = dict(
+ name=dict(type='str', required=True),
+ value=dict(type='str', default=None),
+ state=dict(default='present', choices=['present', 'absent']),
+ node=dict(type='str', default='rabbit')
+ )
+ module = AnsibleModule(
+ argument_spec=arg_spec,
+ supports_check_mode=True
+ )
+
+ name = module.params['name']
+ value = module.params['value']
+ if isinstance(value, str):
+ value = json.loads(value)
+ state = module.params['state']
+ node = module.params['node']
+
+ result = dict(changed=False)
+ rabbitmq_global_parameter = RabbitMqGlobalParameter(module, name, value, node)
+
+ if rabbitmq_global_parameter.get():
+ if state == 'absent':
+ rabbitmq_global_parameter.delete()
+ result['changed'] = True
+ else:
+ if rabbitmq_global_parameter.has_modifications():
+ rabbitmq_global_parameter.set()
+ result['changed'] = True
+ elif state == 'present':
+ rabbitmq_global_parameter.set()
+ result['changed'] = True
+
+ result['name'] = name
+ result['value'] = value
+ result['state'] = state
+
+ module.exit_json(**result)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_parameter.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_parameter.py
new file mode 100644
index 00000000..d88bdcd6
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_parameter.py
@@ -0,0 +1,155 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2013, Chatham Financial <oss@chathamfinancial.com>
+# 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: rabbitmq_parameter
+short_description: Manage RabbitMQ parameters
+description:
+ - Manage dynamic, cluster-wide parameters for RabbitMQ
+author: Chris Hoffman (@chrishoffman)
+options:
+ component:
+ description:
+ - Name of the component of which the parameter is being set
+ type: str
+ required: true
+ name:
+ description:
+ - Name of the parameter being set
+ type: str
+ required: true
+ value:
+ description:
+ - Value of the parameter, as a JSON term
+ type: str
+ vhost:
+ description:
+ - vhost to apply access privileges.
+ type: str
+ default: /
+ node:
+ description:
+ - erlang node name of the rabbit we wish to configure
+ type: str
+ default: rabbit
+ state:
+ description:
+ - Specify if user is to be added or removed
+ type: str
+ default: present
+ choices: [ 'present', 'absent']
+'''
+
+EXAMPLES = """
+# Set the federation parameter 'local_username' to a value of 'guest' (in quotes)
+- community.rabbitmq.rabbitmq_parameter:
+ component: federation
+ name: local-username
+ value: '"guest"'
+ state: present
+"""
+import json
+from ansible.module_utils.basic import AnsibleModule
+
+
+class RabbitMqParameter(object):
+ def __init__(self, module, component, name, value, vhost, node):
+ self.module = module
+ self.component = component
+ self.name = name
+ self.value = value
+ self.vhost = vhost
+ self.node = node
+
+ self._value = None
+
+ self._rabbitmqctl = module.get_bin_path('rabbitmqctl', True)
+
+ def _exec(self, args, run_in_check_mode=False):
+ if not self.module.check_mode or (self.module.check_mode and run_in_check_mode):
+ cmd = [self._rabbitmqctl, '-q', '-n', self.node]
+ rc, out, err = self.module.run_command(cmd + args, check_rc=True)
+ return out.strip().splitlines()
+ return list()
+
+ def get(self):
+ parameters = [param for param in self._exec(['list_parameters', '-p', self.vhost], True) if param.strip()]
+
+ for param_item in parameters:
+ component, name, value = param_item.split('\t')
+
+ if component == self.component and name == self.name:
+ self._value = json.loads(value)
+ return True
+ return False
+
+ def set(self):
+ self._exec(['set_parameter',
+ '-p',
+ self.vhost,
+ self.component,
+ self.name,
+ json.dumps(self.value)])
+
+ def delete(self):
+ self._exec(['clear_parameter', '-p', self.vhost, self.component, self.name])
+
+ def has_modifications(self):
+ return self.value != self._value
+
+
+def main():
+ arg_spec = dict(
+ component=dict(required=True),
+ name=dict(required=True),
+ value=dict(default=None),
+ vhost=dict(default='/'),
+ state=dict(default='present', choices=['present', 'absent']),
+ node=dict(default='rabbit')
+ )
+ module = AnsibleModule(
+ argument_spec=arg_spec,
+ supports_check_mode=True
+ )
+
+ component = module.params['component']
+ name = module.params['name']
+ value = module.params['value']
+ if isinstance(value, str):
+ value = json.loads(value)
+ vhost = module.params['vhost']
+ state = module.params['state']
+ node = module.params['node']
+
+ result = dict(changed=False)
+ rabbitmq_parameter = RabbitMqParameter(module, component, name, value, vhost, node)
+
+ if rabbitmq_parameter.get():
+ if state == 'absent':
+ rabbitmq_parameter.delete()
+ result['changed'] = True
+ else:
+ if rabbitmq_parameter.has_modifications():
+ rabbitmq_parameter.set()
+ result['changed'] = True
+ elif state == 'present':
+ rabbitmq_parameter.set()
+ result['changed'] = True
+
+ result['component'] = component
+ result['name'] = name
+ result['vhost'] = vhost
+ result['state'] = state
+ module.exit_json(**result)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_plugin.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_plugin.py
new file mode 100644
index 00000000..87a08b9f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_plugin.py
@@ -0,0 +1,187 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2013, Chatham Financial <oss@chathamfinancial.com>
+# 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: rabbitmq_plugin
+short_description: Manage RabbitMQ plugins
+description:
+ - This module can be used to enable or disable RabbitMQ plugins.
+author:
+ - Chris Hoffman (@chrishoffman)
+options:
+ names:
+ description:
+ - Comma-separated list of plugin names. Also, accepts plugin name.
+ type: str
+ required: true
+ aliases: [name]
+ new_only:
+ description:
+ - Only enable missing plugins.
+ - Does not disable plugins that are not in the names list.
+ type: bool
+ default: "no"
+ state:
+ description:
+ - Specify if plugins are to be enabled or disabled.
+ type: str
+ default: enabled
+ choices: [enabled, disabled]
+ broker_state:
+ description:
+ - Specify whether the broker should be online or offline for the plugin change.
+ type: str
+ default: online
+ choices: [online, offline]
+ prefix:
+ description:
+ - Specify a custom install prefix to a Rabbit.
+ type: str
+'''
+
+EXAMPLES = '''
+- name: Enables the rabbitmq_management plugin
+ community.rabbitmq.rabbitmq_plugin:
+ names: rabbitmq_management
+ state: enabled
+
+- name: Enable multiple rabbitmq plugins
+ community.rabbitmq.rabbitmq_plugin:
+ names: rabbitmq_management,rabbitmq_management_visualiser
+ state: enabled
+
+- name: Disable plugin
+ community.rabbitmq.rabbitmq_plugin:
+ names: rabbitmq_management
+ state: disabled
+
+- name: Enable every plugin in list with existing plugins
+ community.rabbitmq.rabbitmq_plugin:
+ names: rabbitmq_management,rabbitmq_management_visualiser,rabbitmq_shovel,rabbitmq_shovel_management
+ state: enabled
+ new_only: 'yes'
+
+- name: Enables the rabbitmq_peer_discovery_aws plugin without requiring a broker connection.
+ community.rabbitmq.rabbitmq_plugin:
+ names: rabbitmq_peer_discovery_aws_plugin
+ state: enabled
+ broker_state: offline
+'''
+
+RETURN = '''
+enabled:
+ description: list of plugins enabled during task run
+ returned: always
+ type: list
+ sample: ["rabbitmq_management"]
+disabled:
+ description: list of plugins disabled during task run
+ returned: always
+ type: list
+ sample: ["rabbitmq_management"]
+'''
+
+import os
+from ansible.module_utils.basic import AnsibleModule
+
+
+class RabbitMqPlugins(object):
+
+ def __init__(self, module):
+ self.module = module
+ bin_path = ''
+ if module.params['prefix']:
+ if os.path.isdir(os.path.join(module.params['prefix'], 'bin')):
+ bin_path = os.path.join(module.params['prefix'], 'bin')
+ elif os.path.isdir(os.path.join(module.params['prefix'], 'sbin')):
+ bin_path = os.path.join(module.params['prefix'], 'sbin')
+ else:
+ # No such path exists.
+ module.fail_json(msg="No binary folder in prefix %s" % module.params['prefix'])
+
+ self._rabbitmq_plugins = os.path.join(bin_path, "rabbitmq-plugins")
+ else:
+ self._rabbitmq_plugins = module.get_bin_path('rabbitmq-plugins', True)
+
+ def _exec(self, args, run_in_check_mode=False):
+ if not self.module.check_mode or (self.module.check_mode and run_in_check_mode):
+ cmd = [self._rabbitmq_plugins]
+ rc, out, err = self.module.run_command(cmd + args, check_rc=True)
+ return out.splitlines()
+ return list()
+
+ def get_all(self):
+ list_output = self._exec(['list', '-E', '-m'], True)
+ plugins = []
+ for plugin in list_output:
+ if not plugin:
+ break
+ plugins.append(plugin)
+
+ return plugins
+
+ def enable(self, name):
+ self._exec(['enable', "--%s" % self.module.params['broker_state'], name])
+
+ def disable(self, name):
+ self._exec(['disable', "--%s" % self.module.params['broker_state'], name])
+
+
+def main():
+ arg_spec = dict(
+ names=dict(required=True, aliases=['name']),
+ new_only=dict(default='no', type='bool'),
+ state=dict(default='enabled', choices=['enabled', 'disabled']),
+ broker_state=dict(default='online', choices=['online', 'offline']),
+ prefix=dict(required=False, default=None)
+ )
+ module = AnsibleModule(
+ argument_spec=arg_spec,
+ supports_check_mode=True
+ )
+
+ result = dict()
+ names = module.params['names'].split(',')
+ new_only = module.params['new_only']
+ state = module.params['state']
+
+ rabbitmq_plugins = RabbitMqPlugins(module)
+ enabled_plugins = rabbitmq_plugins.get_all()
+
+ enabled = []
+ disabled = []
+ if state == 'enabled':
+ if not new_only:
+ for plugin in enabled_plugins:
+ if " " in plugin:
+ continue
+ if plugin not in names:
+ rabbitmq_plugins.disable(plugin)
+ disabled.append(plugin)
+
+ for name in names:
+ if name not in enabled_plugins:
+ rabbitmq_plugins.enable(name)
+ enabled.append(name)
+ else:
+ for plugin in enabled_plugins:
+ if plugin in names:
+ rabbitmq_plugins.disable(plugin)
+ disabled.append(plugin)
+
+ result['changed'] = len(enabled) > 0 or len(disabled) > 0
+ result['enabled'] = enabled
+ result['disabled'] = disabled
+ module.exit_json(**result)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_policy.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_policy.py
new file mode 100644
index 00000000..41faebaa
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_policy.py
@@ -0,0 +1,248 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2013, John Dewey <john@dewey.ws>
+# 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: rabbitmq_policy
+short_description: Manage the state of policies in RabbitMQ
+description:
+ - Manage the state of a policy in RabbitMQ.
+author: John Dewey (@retr0h)
+options:
+ name:
+ description:
+ - The name of the policy to manage.
+ type: str
+ required: true
+ vhost:
+ description:
+ - The name of the vhost to apply to.
+ type: str
+ default: /
+ apply_to:
+ description:
+ - What the policy applies to. Requires RabbitMQ 3.2.0 or later.
+ type: str
+ default: all
+ choices: [all, exchanges, queues]
+ pattern:
+ description:
+ - A regex of queues to apply the policy to. Required when
+ C(state=present). This option is no longer required as of Ansible 2.9.
+ type: str
+ required: false
+ default: null
+ tags:
+ description:
+ - A dict or string describing the policy. Required when
+ C(state=present). This option is no longer required as of Ansible 2.9.
+ type: dict
+ required: false
+ default: null
+ priority:
+ description:
+ - The priority of the policy.
+ type: str
+ default: '0'
+ node:
+ description:
+ - Erlang node name of the rabbit we wish to configure.
+ type: str
+ default: rabbit
+ state:
+ description:
+ - The state of the policy.
+ type: str
+ default: present
+ choices: [present, absent]
+'''
+
+EXAMPLES = '''
+- name: ensure the default vhost contains the HA policy via a dict
+ community.rabbitmq.rabbitmq_policy:
+ name: HA
+ pattern: .*
+ args:
+ tags:
+ ha-mode: all
+
+- name: ensure the default vhost contains the HA policy
+ community.rabbitmq.rabbitmq_policy:
+ name: HA
+ pattern: .*
+ tags:
+ ha-mode: all
+'''
+
+import json
+import re
+from distutils.version import LooseVersion as Version
+
+from ansible.module_utils.basic import AnsibleModule
+
+
+class RabbitMqPolicy(object):
+
+ def __init__(self, module, name):
+ self._module = module
+ self._name = name
+ self._vhost = module.params['vhost']
+ self._pattern = module.params['pattern']
+ self._apply_to = module.params['apply_to']
+ self._tags = module.params['tags']
+ self._priority = module.params['priority']
+ self._node = module.params['node']
+ self._rabbitmqctl = module.get_bin_path('rabbitmqctl', True)
+
+ self._version = self._rabbit_version()
+
+ def _exec(self,
+ args,
+ run_in_check_mode=False,
+ split_lines=True,
+ add_vhost=True):
+ if (not self._module.check_mode
+ or (self._module.check_mode and run_in_check_mode)):
+ cmd = [self._rabbitmqctl, '-q', '-n', self._node]
+
+ if add_vhost:
+ args.insert(1, '-p')
+ args.insert(2, self._vhost)
+
+ rc, out, err = self._module.run_command(cmd + args, check_rc=True)
+ if split_lines:
+ return out.splitlines()
+
+ return out
+ return list()
+
+ def _rabbit_version(self):
+ status = self._exec(['status'], True, False, False)
+
+ # 3.7.x erlang style output
+ version_match = re.search('{rabbit,".*","(?P<version>.*)"}', status)
+ if version_match:
+ return Version(version_match.group('version'))
+
+ # 3.8.x style ouput
+ version_match = re.search('RabbitMQ version: (?P<version>.*)', status)
+ if version_match:
+ return Version(version_match.group('version'))
+
+ return None
+
+ def _list_policies(self):
+ if self._version and self._version >= Version('3.7.9'):
+ # Remove first header line from policies list for version > 3.7.9
+ return self._exec(['list_policies'], True)[1:]
+
+ return self._exec(['list_policies'], True)
+
+ def has_modifications(self):
+ if self._pattern is None or self._tags is None:
+ self._module.fail_json(
+ msg=('pattern and tags are required for '
+ 'state=present'))
+
+ if self._version and self._version >= Version('3.7.0'):
+ # Change fields order in rabbitmqctl output in version 3.7
+ return not any(
+ self._policy_check(policy, apply_to_fno=3, pattern_fno=2)
+ for policy in self._list_policies())
+ else:
+ return not any(
+ self._policy_check(policy) for policy in self._list_policies())
+
+ def should_be_deleted(self):
+ return any(
+ self._policy_check_by_name(policy)
+ for policy in self._list_policies())
+
+ def set(self):
+ args = ['set_policy']
+ args.append(self._name)
+ args.append(self._pattern)
+ args.append(json.dumps(self._tags))
+ args.append('--priority')
+ args.append(self._priority)
+ if self._apply_to != 'all':
+ args.append('--apply-to')
+ args.append(self._apply_to)
+ return self._exec(args)
+
+ def clear(self):
+ return self._exec(['clear_policy', self._name])
+
+ def _policy_check(self,
+ policy,
+ name_fno=1,
+ apply_to_fno=2,
+ pattern_fno=3,
+ tags_fno=4,
+ priority_fno=5):
+ if not policy:
+ return False
+
+ policy_data = policy.split('\t')
+
+ policy_name = policy_data[name_fno]
+ apply_to = policy_data[apply_to_fno]
+ pattern = policy_data[pattern_fno].replace('\\\\', '\\')
+ tags = json.loads(policy_data[tags_fno])
+ priority = policy_data[priority_fno]
+
+ return (policy_name == self._name and apply_to == self._apply_to
+ and tags == self._tags and priority == self._priority
+ and pattern == self._pattern)
+
+ def _policy_check_by_name(self, policy):
+ if not policy:
+ return False
+
+ policy_name = policy.split('\t')[1]
+
+ return policy_name == self._name
+
+
+def main():
+ arg_spec = dict(
+ name=dict(required=True),
+ vhost=dict(default='/'),
+ pattern=dict(required=False, default=None),
+ apply_to=dict(default='all', choices=['all', 'exchanges', 'queues']),
+ tags=dict(type='dict', required=False, default=None),
+ priority=dict(default='0'),
+ node=dict(default='rabbit'),
+ state=dict(default='present', choices=['present', 'absent']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=arg_spec,
+ supports_check_mode=True
+ )
+
+ name = module.params['name']
+ state = module.params['state']
+ rabbitmq_policy = RabbitMqPolicy(module, name)
+
+ result = dict(changed=False, name=name, state=state)
+
+ if state == 'present' and rabbitmq_policy.has_modifications():
+ rabbitmq_policy.set()
+ result['changed'] = True
+ elif state == 'absent' and rabbitmq_policy.should_be_deleted():
+ rabbitmq_policy.clear()
+ result['changed'] = True
+
+ module.exit_json(**result)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_publish.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_publish.py
new file mode 100644
index 00000000..12f7af31
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_publish.py
@@ -0,0 +1,220 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# (c) 2018, John Imison <john+github@imison.net>
+# 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: rabbitmq_publish
+short_description: Publish a message to a RabbitMQ queue.
+description:
+ - Publish a message on a RabbitMQ queue using a blocking connection.
+options:
+ url:
+ description:
+ - An URL connection string to connect to the RabbitMQ server.
+ - I(url) and I(host)/I(port)/I(user)/I(pass)/I(vhost) are mutually exclusive, use either or but not both.
+ type: str
+ proto:
+ description:
+ - The protocol to use.
+ type: str
+ choices: [amqps, amqp]
+ host:
+ description:
+ - The RabbitMQ server hostname or IP.
+ type: str
+ port:
+ description:
+ - The RabbitMQ server port.
+ type: int
+ username:
+ description:
+ - The RabbitMQ username.
+ type: str
+ password:
+ description:
+ - The RabbitMQ password.
+ type: str
+ vhost:
+ description:
+ - The virtual host to target.
+ - If default vhost is required, use C('%2F').
+ type: str
+ queue:
+ description:
+ - The queue to publish a message to. If no queue is specified, RabbitMQ will return a random queue name.
+ type: str
+ exchange:
+ description:
+ - The exchange to publish a message to.
+ type: str
+ routing_key:
+ description:
+ - The routing key.
+ type: str
+ body:
+ description:
+ - The body of the message.
+ - A C(body) cannot be provided if a C(src) is specified.
+ type: str
+ src:
+ description:
+ - A file to upload to the queue. Automatic mime type detection is attempted if content_type is not defined (left as default).
+ - A C(src) cannot be provided if a C(body) is specified.
+ - The filename is added to the headers of the posted message to RabbitMQ. Key being the C(filename), value is the filename.
+ type: path
+ aliases: ['file']
+ content_type:
+ description:
+ - The content type of the body.
+ type: str
+ default: text/plain
+ durable:
+ description:
+ - Set the queue to be durable.
+ type: bool
+ default: False
+ exclusive:
+ description:
+ - Set the queue to be exclusive.
+ type: bool
+ default: False
+ auto_delete:
+ description:
+ - Set the queue to auto delete.
+ type: bool
+ default: False
+ headers:
+ description:
+ - A dictionary of headers to post with the message.
+ type: dict
+ default: {}
+ cafile:
+ description:
+ - CA file used during connection to the RabbitMQ server over SSL.
+ - If this option is specified, also I(certfile) and I(keyfile) must be specified.
+ type: str
+ certfile:
+ description:
+ - Client certificate to establish SSL connection.
+ - If this option is specified, also I(cafile) and I(keyfile) must be specified.
+ type: str
+ keyfile:
+ description:
+ - Client key to establish SSL connection.
+ - If this option is specified, also I(cafile) and I(certfile) must be specified.
+ type: str
+
+
+
+requirements: [ pika ]
+notes:
+ - This module requires the pika python library U(https://pika.readthedocs.io/).
+ - Pika is a pure-Python implementation of the AMQP 0-9-1 protocol that tries to stay fairly independent of the underlying network support library.
+ - This module is tested against RabbitMQ. Other AMQP 0.9.1 protocol based servers may work but not tested/guaranteed.
+ - The certificate authentication was tested with certificates created
+ via U(https://www.rabbitmq.com/ssl.html#automated-certificate-generation) and RabbitMQ
+ configuration variables C(ssl_options.verify = verify_peer) & C(ssl_options.fail_if_no_peer_cert = true).
+author: "John Imison (@Im0)"
+'''
+
+EXAMPLES = '''
+- name: Publish a message to a queue with headers
+ community.rabbitmq.rabbitmq_publish:
+ url: "amqp://guest:guest@192.168.0.32:5672/%2F"
+ queue: 'test'
+ body: "Hello world from ansible module rabbitmq_publish"
+ content_type: "text/plain"
+ headers:
+ myHeader: myHeaderValue
+
+
+- name: Publish a file to a queue
+ community.rabbitmq.rabbitmq_publish:
+ url: "amqp://guest:guest@192.168.0.32:5672/%2F"
+ queue: 'images'
+ file: 'path/to/logo.gif'
+
+- name: RabbitMQ auto generated queue
+ community.rabbitmq.rabbitmq_publish:
+ url: "amqp://guest:guest@192.168.0.32:5672/%2F"
+ body: "Hello world random queue from ansible module rabbitmq_publish"
+ content_type: "text/plain"
+
+- name: Publish with certs
+ community.rabbitmq.rabbitmq_publish:
+ url: "amqps://guest:guest@192.168.0.32:5671/%2F"
+ body: "Hello test queue from ansible module rabbitmq_publish via SSL certs"
+ queue: 'test'
+ content_type: "text/plain"
+ cafile: 'ca_certificate.pem'
+ certfile: 'client_certificate.pem'
+ keyfile: 'client_key.pem'
+
+'''
+
+RETURN = '''
+result:
+ description:
+ - Contains the status I(msg), content type I(content_type) and the queue name I(queue).
+ returned: success
+ type: dict
+ sample: |
+ 'result': { 'content_type': 'text/plain', 'msg': 'Successfully published to queue test', 'queue': 'test' }
+'''
+
+try:
+ import pika
+ HAS_PIKA = True
+except ImportError:
+ HAS_PIKA = False
+
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils._text import to_native, to_text
+from ansible_collections.community.rabbitmq.plugins.module_utils.rabbitmq import RabbitClient
+
+
+def main():
+ argument_spec = RabbitClient.rabbitmq_argument_spec()
+ argument_spec.update(
+ exchange=dict(type='str', default=''),
+ routing_key=dict(type='str', required=False),
+ body=dict(type='str', required=False),
+ src=dict(aliases=['file'], type='path', required=False),
+ content_type=dict(default="text/plain", type='str'),
+ durable=dict(default=False, type='bool'),
+ exclusive=dict(default=False, type='bool'),
+ auto_delete=dict(default=False, type='bool'),
+ headers=dict(default={}, type='dict'),
+ cafile=dict(type='str', required=False),
+ certfile=dict(type='str', required=False),
+ keyfile=dict(type='str', required=False),
+ )
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ mutually_exclusive=[['body', 'src']],
+ required_together=[['cafile', 'certfile', 'keyfile']],
+ supports_check_mode=False
+ )
+
+ rabbitmq = RabbitClient(module)
+
+ if rabbitmq.basic_publish():
+ rabbitmq.close_connection()
+ module.exit_json(changed=True, result={"msg": "Successfully published to queue %s" % rabbitmq.queue,
+ "queue": rabbitmq.queue,
+ "content_type": rabbitmq.content_type})
+ else:
+ rabbitmq.close_connection()
+ module.fail_json(changed=False, msg="Unsuccessful publishing to queue %s" % rabbitmq.queue)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_queue.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_queue.py
new file mode 100644
index 00000000..85878773
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_queue.py
@@ -0,0 +1,257 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2015, Manuel Sousa <manuel.sousa@gmail.com>
+# 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: rabbitmq_queue
+author: Manuel Sousa (@manuel-sousa)
+
+short_description: Manage rabbitMQ queues
+description:
+ - This module uses rabbitMQ Rest API to create/delete queues
+requirements: [ "requests >= 1.0.0" ]
+options:
+ name:
+ description:
+ - Name of the queue
+ type: str
+ required: true
+ state:
+ description:
+ - Whether the queue should be present or absent
+ type: str
+ choices: [ "present", "absent" ]
+ default: present
+ durable:
+ description:
+ - whether queue is durable or not
+ type: bool
+ default: 'yes'
+ auto_delete:
+ description:
+ - if the queue should delete itself after all queues/queues unbound from it
+ type: bool
+ default: 'no'
+ message_ttl:
+ description:
+ - How long a message can live in queue before it is discarded (milliseconds)
+ type: int
+ auto_expires:
+ description:
+ - How long a queue can be unused before it is automatically deleted (milliseconds)
+ type: int
+ max_length:
+ description:
+ - How many messages can the queue contain before it starts rejecting
+ type: int
+ dead_letter_exchange:
+ description:
+ - Optional name of an exchange to which messages will be republished if they
+ - are rejected or expire
+ type: str
+ dead_letter_routing_key:
+ description:
+ - Optional replacement routing key to use when a message is dead-lettered.
+ - Original routing key will be used if unset
+ type: str
+ max_priority:
+ description:
+ - Maximum number of priority levels for the queue to support.
+ - If not set, the queue will not support message priorities.
+ - Larger numbers indicate higher priority.
+ type: int
+ arguments:
+ description:
+ - extra arguments for queue. If defined this argument is a key/value dictionary
+ type: dict
+ default: {}
+extends_documentation_fragment:
+- community.rabbitmq.rabbitmq
+
+'''
+
+EXAMPLES = '''
+# Create a queue
+- community.rabbitmq.rabbitmq_queue:
+ name: myQueue
+
+# Create a queue on remote host
+- community.rabbitmq.rabbitmq_queue:
+ name: myRemoteQueue
+ login_user: user
+ login_password: secret
+ login_host: remote.example.org
+'''
+
+import json
+import traceback
+
+REQUESTS_IMP_ERR = None
+try:
+ import requests
+ HAS_REQUESTS = True
+except ImportError:
+ REQUESTS_IMP_ERR = traceback.format_exc()
+ HAS_REQUESTS = False
+
+from ansible.module_utils.basic import AnsibleModule, missing_required_lib
+from ansible.module_utils.six.moves.urllib import parse as urllib_parse
+from ansible_collections.community.rabbitmq.plugins.module_utils.rabbitmq import rabbitmq_argument_spec
+
+
+def main():
+
+ argument_spec = rabbitmq_argument_spec()
+ argument_spec.update(
+ dict(
+ state=dict(default='present', choices=['present', 'absent'], type='str'),
+ name=dict(required=True, type='str'),
+ durable=dict(default=True, type='bool'),
+ auto_delete=dict(default=False, type='bool'),
+ message_ttl=dict(default=None, type='int'),
+ auto_expires=dict(default=None, type='int'),
+ max_length=dict(default=None, type='int'),
+ dead_letter_exchange=dict(default=None, type='str'),
+ dead_letter_routing_key=dict(default=None, type='str'),
+ arguments=dict(default=dict(), type='dict'),
+ max_priority=dict(default=None, type='int')
+ )
+ )
+ module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
+
+ url = "%s://%s:%s/api/queues/%s/%s" % (
+ module.params['login_protocol'],
+ module.params['login_host'],
+ module.params['login_port'],
+ urllib_parse.quote(module.params['vhost'], ''),
+ module.params['name']
+ )
+
+ if not HAS_REQUESTS:
+ module.fail_json(msg=missing_required_lib("requests"), exception=REQUESTS_IMP_ERR)
+
+ result = dict(changed=False, name=module.params['name'])
+
+ # Check if queue already exists
+ r = requests.get(url, auth=(module.params['login_user'], module.params['login_password']),
+ verify=module.params['ca_cert'], cert=(module.params['client_cert'], module.params['client_key']))
+
+ if r.status_code == 200:
+ queue_exists = True
+ response = r.json()
+ elif r.status_code == 404:
+ queue_exists = False
+ response = r.text
+ else:
+ module.fail_json(
+ msg="Invalid response from RESTAPI when trying to check if queue exists",
+ details=r.text
+ )
+
+ if module.params['state'] == 'present':
+ change_required = not queue_exists
+ else:
+ change_required = queue_exists
+
+ # Check if attributes change on existing queue
+ if not change_required and r.status_code == 200 and module.params['state'] == 'present':
+ if not (
+ response['durable'] == module.params['durable'] and
+ response['auto_delete'] == module.params['auto_delete'] and
+ (
+ ('x-message-ttl' in response['arguments'] and response['arguments']['x-message-ttl'] == module.params['message_ttl']) or
+ ('x-message-ttl' not in response['arguments'] and module.params['message_ttl'] is None)
+ ) and
+ (
+ ('x-expires' in response['arguments'] and response['arguments']['x-expires'] == module.params['auto_expires']) or
+ ('x-expires' not in response['arguments'] and module.params['auto_expires'] is None)
+ ) and
+ (
+ ('x-max-length' in response['arguments'] and response['arguments']['x-max-length'] == module.params['max_length']) or
+ ('x-max-length' not in response['arguments'] and module.params['max_length'] is None)
+ ) and
+ (
+ ('x-dead-letter-exchange' in response['arguments'] and
+ response['arguments']['x-dead-letter-exchange'] == module.params['dead_letter_exchange']) or
+ ('x-dead-letter-exchange' not in response['arguments'] and module.params['dead_letter_exchange'] is None)
+ ) and
+ (
+ ('x-dead-letter-routing-key' in response['arguments'] and
+ response['arguments']['x-dead-letter-routing-key'] == module.params['dead_letter_routing_key']) or
+ ('x-dead-letter-routing-key' not in response['arguments'] and module.params['dead_letter_routing_key'] is None)
+ ) and
+ (
+ ('x-max-priority' in response['arguments'] and
+ response['arguments']['x-max-priority'] == module.params['max_priority']) or
+ ('x-max-priority' not in response['arguments'] and module.params['max_priority'] is None)
+ )
+ ):
+ module.fail_json(
+ msg="RabbitMQ RESTAPI doesn't support attribute changes for existing queues",
+ )
+
+ # Copy parameters to arguments as used by RabbitMQ
+ for k, v in {
+ 'message_ttl': 'x-message-ttl',
+ 'auto_expires': 'x-expires',
+ 'max_length': 'x-max-length',
+ 'dead_letter_exchange': 'x-dead-letter-exchange',
+ 'dead_letter_routing_key': 'x-dead-letter-routing-key',
+ 'max_priority': 'x-max-priority'
+ }.items():
+ if module.params[k] is not None:
+ module.params['arguments'][v] = module.params[k]
+
+ # Exit if check_mode
+ if module.check_mode:
+ result['changed'] = change_required
+ result['details'] = response
+ result['arguments'] = module.params['arguments']
+ module.exit_json(**result)
+
+ # Do changes
+ if change_required:
+ if module.params['state'] == 'present':
+ r = requests.put(
+ url,
+ auth=(module.params['login_user'], module.params['login_password']),
+ headers={"content-type": "application/json"},
+ data=json.dumps({
+ "durable": module.params['durable'],
+ "auto_delete": module.params['auto_delete'],
+ "arguments": module.params['arguments']
+ }),
+ verify=module.params['ca_cert'],
+ cert=(module.params['client_cert'], module.params['client_key'])
+ )
+ elif module.params['state'] == 'absent':
+ r = requests.delete(url, auth=(module.params['login_user'], module.params['login_password']),
+ verify=module.params['ca_cert'], cert=(module.params['client_cert'], module.params['client_key']))
+
+ # RabbitMQ 3.6.7 changed this response code from 204 to 201
+ if r.status_code == 204 or r.status_code == 201:
+ result['changed'] = True
+ module.exit_json(**result)
+ else:
+ module.fail_json(
+ msg="Error creating queue",
+ status=r.status_code,
+ details=r.text
+ )
+
+ else:
+ module.exit_json(
+ changed=False,
+ name=module.params['name']
+ )
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_user.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_user.py
new file mode 100644
index 00000000..1902e88c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_user.py
@@ -0,0 +1,463 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2013, Chatham Financial <oss@chathamfinancial.com>
+# 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: rabbitmq_user
+short_description: Manage RabbitMQ users
+description:
+ - Add or remove users to RabbitMQ and assign permissions
+author: Chris Hoffman (@chrishoffman)
+options:
+ user:
+ description:
+ - Name of user to add
+ type: str
+ required: true
+ aliases: [username, name]
+ password:
+ description:
+ - Password of user to add.
+ - To change the password of an existing user, you must also specify
+ C(update_password=always).
+ type: str
+ tags:
+ description:
+ - User tags specified as comma delimited
+ type: str
+ permissions:
+ description:
+ - a list of dicts, each dict contains vhost, configure_priv, write_priv, and read_priv,
+ and represents a permission rule for that vhost.
+ - This option should be preferable when you care about all permissions of the user.
+ - You should use vhost, configure_priv, write_priv, and read_priv options instead
+ if you care about permissions for just some vhosts.
+ type: list
+ elements: dict
+ default: []
+ vhost:
+ description:
+ - vhost to apply access privileges.
+ - This option will be ignored when permissions option is used.
+ type: str
+ default: /
+ node:
+ description:
+ - erlang node name of the rabbit we wish to configure
+ type: str
+ default: rabbit
+ configure_priv:
+ description:
+ - Regular expression to restrict configure actions on a resource
+ for the specified vhost.
+ - By default all actions are restricted.
+ - This option will be ignored when permissions option is used.
+ type: str
+ default: '^$'
+ write_priv:
+ description:
+ - Regular expression to restrict configure actions on a resource
+ for the specified vhost.
+ - By default all actions are restricted.
+ - This option will be ignored when permissions option is used.
+ type: str
+ default: '^$'
+ read_priv:
+ description:
+ - Regular expression to restrict configure actions on a resource
+ for the specified vhost.
+ - By default all actions are restricted.
+ - This option will be ignored when permissions option is used.
+ type: str
+ default: '^$'
+ force:
+ description:
+ - Deletes and recreates the user.
+ type: bool
+ default: 'no'
+ state:
+ description:
+ - Specify if user is to be added or removed
+ type: str
+ default: present
+ choices: ['present', 'absent']
+ update_password:
+ description:
+ - C(on_create) will only set the password for newly created users. C(always) will update passwords if they differ.
+ type: str
+ required: false
+ default: on_create
+ choices: ['on_create', 'always']
+'''
+
+EXAMPLES = '''
+# Add user to server and assign full access control on / vhost.
+# The user might have permission rules for other vhost but you don't care.
+- community.rabbitmq.rabbitmq_user:
+ user: joe
+ password: changeme
+ vhost: /
+ configure_priv: .*
+ read_priv: .*
+ write_priv: .*
+ state: present
+
+# Add user to server and assign full access control on / vhost.
+# The user doesn't have permission rules for other vhosts
+- community.rabbitmq.rabbitmq_user:
+ user: joe
+ password: changeme
+ permissions:
+ - vhost: /
+ configure_priv: .*
+ read_priv: .*
+ write_priv: .*
+ state: present
+'''
+
+import distutils.version
+import json
+import re
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.common.collections import count
+
+
+def normalized_permissions(vhost_permission_list):
+ """Older versions of RabbitMQ output permissions with slightly different names.
+
+ In older versions of RabbitMQ, the names of the permissions had the `_priv` suffix, which was removed in versions
+ >= 3.7.6. For simplicity we only check the `configure` permission. If it's in the old format then all the other
+ ones will be wrong too.
+ """
+ for vhost_permission in vhost_permission_list:
+ if 'configure_priv' in vhost_permission:
+ yield {
+ 'configure': vhost_permission['configure_priv'],
+ 'read': vhost_permission['read_priv'],
+ 'write': vhost_permission['write_priv'],
+ 'vhost': vhost_permission['vhost']
+ }
+ else:
+ yield vhost_permission
+
+
+def as_permission_dict(vhost_permission_list):
+ return dict([(vhost_permission['vhost'], vhost_permission) for vhost_permission
+ in normalized_permissions(vhost_permission_list)])
+
+
+def only(vhost, vhost_permissions):
+ return {vhost: vhost_permissions.get(vhost, {})}
+
+
+def first(iterable):
+ return next(iter(iterable))
+
+
+class RabbitMqUser(object):
+ def __init__(self, module, username, password, tags, permissions,
+ node, bulk_permissions=False):
+ self.module = module
+ self.username = username
+ self.password = password or ''
+ self.node = node
+ self.tags = list() if not tags else tags.replace(' ', '').split(',')
+ self.permissions = as_permission_dict(permissions)
+ self.bulk_permissions = bulk_permissions
+
+ self.existing_tags = None
+ self.existing_permissions = dict()
+ self._rabbitmqctl = module.get_bin_path('rabbitmqctl', True)
+ self._version = self._check_version()
+
+ def _check_version(self):
+ """Get the version of the RabbitMQ server."""
+ version = self._rabbitmq_version_post_3_7(fail_on_error=False)
+ if not version:
+ version = self._rabbitmq_version_pre_3_7(fail_on_error=False)
+ if not version:
+ self.module.fail_json(msg="Could not determine the version of the RabbitMQ server.")
+ return version
+
+ def _fail(self, msg, stop_execution=False):
+ if stop_execution:
+ self.module.fail_json(msg=msg)
+ # This is a dummy return to prevent linters from throwing errors.
+ return None
+
+ def _rabbitmq_version_post_3_7(self, fail_on_error=False):
+ """Use the JSON formatter to get a machine readable output of the version.
+
+ At this point we do not know which RabbitMQ server version we are dealing with and which
+ version of `rabbitmqctl` we are using, so we will try to use the JSON formatter and see
+ what happens. In some versions of
+ """
+ def int_list_to_str(ints):
+ return ''.join([chr(i) for i in ints])
+
+ rc, output, err = self._exec(['status', '--formatter', 'json'], check_rc=False)
+ if rc != 0:
+ return self._fail(msg="Could not parse the version of the RabbitMQ server, "
+ "because `rabbitmqctl status` returned no output.",
+ stop_execution=fail_on_error)
+ try:
+ status_json = json.loads(output)
+ if 'rabbitmq_version' in status_json:
+ return distutils.version.StrictVersion(status_json['rabbitmq_version'])
+ for application in status_json.get('running_applications', list()):
+ if application[0] == 'rabbit':
+ if isinstance(application[1][0], int):
+ return distutils.version.StrictVersion(int_list_to_str(application[2]))
+ else:
+ return distutils.version.StrictVersion(application[1])
+ return self._fail(msg="Could not find RabbitMQ version of `rabbitmqctl status` command.",
+ stop_execution=fail_on_error)
+ except ValueError as e:
+ return self._fail(msg="Could not parse output of `rabbitmqctl status` as JSON: {exc}.".format(exc=repr(e)),
+ stop_execution=fail_on_error)
+
+ def _rabbitmq_version_pre_3_7(self, fail_on_error=False):
+ """Get the version of the RabbitMQ Server.
+
+ Before version 3.7.6 the `rabbitmqctl` utility did not support the
+ `--formatter` flag, so the output has to be parsed using regular expressions.
+ """
+ version_reg_ex = r"{rabbit,\"RabbitMQ\",\"([0-9]+\.[0-9]+\.[0-9]+)\"}"
+ rc, output, err = self._exec(['status'], check_rc=False)
+ if rc != 0:
+ if fail_on_error:
+ self.module.fail_json(msg="Could not parse the version of the RabbitMQ server, because"
+ " `rabbitmqctl status` returned no output.")
+ else:
+ return None
+ reg_ex_res = re.search(version_reg_ex, output, re.IGNORECASE)
+ if not reg_ex_res:
+ return self._fail(msg="Could not parse the version of the RabbitMQ server from the output of "
+ "`rabbitmqctl status` command: {output}.".format(output=output),
+ stop_execution=fail_on_error)
+ try:
+ return distutils.version.StrictVersion(reg_ex_res.group(1))
+ except ValueError as e:
+ return self._fail(msg="Could not parse the version of the RabbitMQ server: {exc}.".format(exc=repr(e)),
+ stop_execution=fail_on_error)
+
+ def _exec(self, args, check_rc=True):
+ """Execute a command using the `rabbitmqctl` utility.
+
+ By default the _exec call will cause the module to fail, if the error code is non-zero. If the `check_rc`
+ flag is set to False, then the exit_code, stdout and stderr will be returned to the calling function to
+ perform whatever error handling it needs.
+
+ :param args: the arguments to pass to the `rabbitmqctl` utility
+ :param check_rc: when set to True, fail if the utility's exit code is non-zero
+ :return: the output of the command or all the outputs plus the error code in case of error
+ """
+ cmd = [self._rabbitmqctl, '-q']
+ if self.node:
+ cmd.extend(['-n', self.node])
+ rc, out, err = self.module.run_command(cmd + args)
+ if check_rc and rc != 0:
+ # check_rc is not passed to the `run_command` method directly to allow for more fine grained checking of
+ # error messages returned by `rabbitmqctl`.
+ user_error_msg_regex = r"(Only root or .* .* run rabbitmqctl)"
+ user_error_msg = re.search(user_error_msg_regex, out)
+ if user_error_msg:
+ self.module.fail_json(msg="Wrong user used to run the `rabbitmqctl` utility: {err}"
+ .format(err=user_error_msg.group(1)))
+ else:
+ self.module.fail_json(msg="rabbitmqctl exited with non-zero code: {err}".format(err=err),
+ rc=rc, stdout=out)
+ return out if check_rc else (rc, out, err)
+
+ def get(self):
+ """Retrieves the list of registered users from the node.
+
+ If the user is already present, the node will also be queried for the user's permissions.
+ If the version of the node is >= 3.7.6 the JSON formatter will be used, otherwise the plaintext will be
+ parsed.
+ """
+ if self._version >= distutils.version.StrictVersion('3.7.6'):
+ users = dict([(user_entry['user'], user_entry['tags'])
+ for user_entry in json.loads(self._exec(['list_users', '--formatter', 'json']))])
+ else:
+ users = self._exec(['list_users'])
+
+ def process_tags(tags):
+ if not tags:
+ return list()
+ return tags.replace('[', '').replace(']', '').replace(' ', '').strip('\t').split(',')
+
+ users_and_tags = [user_entry.split('\t') for user_entry in users.strip().split('\n')]
+ users = dict([(user, process_tags(tags)) for user, tags in users_and_tags])
+
+ self.existing_tags = users.get(self.username, list())
+ self.existing_permissions = self._get_permissions() if self.username in users else dict()
+ return self.username in users
+
+ def _get_permissions(self):
+ """Get permissions of the user from RabbitMQ."""
+ if self._version >= distutils.version.StrictVersion('3.7.6'):
+ permissions = json.loads(self._exec(['list_user_permissions', self.username, '--formatter', 'json']))
+ else:
+ output = self._exec(['list_user_permissions', self.username]).strip().split('\n')
+ perms_out = [perm.split('\t') for perm in output if perm.strip()]
+ # Filter out headers from the output of the command in case they are still present
+ perms_out = [perm for perm in perms_out if perm != ["vhost", "configure", "write", "read"]]
+
+ permissions = list()
+ for vhost, configure, write, read in perms_out:
+ permissions.append(dict(vhost=vhost, configure=configure, write=write, read=read))
+
+ if self.bulk_permissions:
+ return as_permission_dict(permissions)
+ else:
+ return only(first(self.permissions.keys()), as_permission_dict(permissions))
+
+ def check_password(self):
+ """Return `True` if the user can authenticate successfully."""
+ rc, out, err = self._exec(['authenticate_user', self.username, self.password], check_rc=False)
+ return rc == 0
+
+ def add(self):
+ self._exec(['add_user', self.username, self.password or ''])
+ if not self.password:
+ self._exec(['clear_password', self.username])
+
+ def delete(self):
+ self._exec(['delete_user', self.username])
+
+ def change_password(self):
+ if self.password:
+ self._exec(['change_password', self.username, self.password])
+ else:
+ self._exec(['clear_password', self.username])
+
+ def set_tags(self):
+ self._exec(['set_user_tags', self.username] + self.tags)
+
+ def set_permissions(self):
+ permissions_to_add = list()
+ for vhost, permission_dict in self.permissions.items():
+ if permission_dict != self.existing_permissions.get(vhost, {}):
+ permissions_to_add.append(permission_dict)
+
+ permissions_to_clear = list()
+ for vhost in self.existing_permissions.keys():
+ if vhost not in self.permissions:
+ permissions_to_clear.append(vhost)
+
+ for vhost in permissions_to_clear:
+ cmd = 'clear_permissions -p {vhost} {username}'.format(username=self.username, vhost=vhost)
+ self._exec(cmd.split(' '))
+ for permissions in permissions_to_add:
+ cmd = ('set_permissions -p {vhost} {username} {configure} {write} {read}'
+ .format(username=self.username, **permissions))
+ self._exec(cmd.split(' '))
+ self.existing_permissions = self._get_permissions()
+
+ def has_tags_modifications(self):
+ return set(self.tags) != set(self.existing_tags)
+
+ def has_permissions_modifications(self):
+ return self.existing_permissions != self.permissions
+
+
+def main():
+ arg_spec = dict(
+ user=dict(required=True, aliases=['username', 'name']),
+ password=dict(default=None, no_log=True),
+ tags=dict(default=None),
+ permissions=dict(default=list(), type='list', elements='dict'),
+ vhost=dict(default='/'),
+ configure_priv=dict(default='^$'),
+ write_priv=dict(default='^$'),
+ read_priv=dict(default='^$'),
+ force=dict(default='no', type='bool'),
+ state=dict(default='present', choices=['present', 'absent']),
+ node=dict(default='rabbit'),
+ update_password=dict(default='on_create', choices=['on_create', 'always'], no_log=False)
+ )
+ module = AnsibleModule(
+ argument_spec=arg_spec,
+ supports_check_mode=True
+ )
+
+ username = module.params['user']
+ password = module.params['password']
+ tags = module.params['tags']
+ permissions = module.params['permissions']
+ vhost = module.params['vhost']
+ configure_priv = module.params['configure_priv']
+ write_priv = module.params['write_priv']
+ read_priv = module.params['read_priv']
+ force = module.params['force']
+ state = module.params['state']
+ node = module.params['node']
+ update_password = module.params['update_password']
+
+ if permissions:
+ vhosts = [permission.get('vhost', '/') for permission in permissions]
+ if any([vhost_count > 1 for vhost_count in count(vhosts).values()]):
+ module.fail_json(msg="Error parsing vhost permissions: You can't "
+ "have two permission dicts for the same vhost")
+ bulk_permissions = True
+ else:
+ perm = {
+ 'vhost': vhost,
+ 'configure_priv': configure_priv,
+ 'write_priv': write_priv,
+ 'read_priv': read_priv
+ }
+ permissions.append(perm)
+ bulk_permissions = False
+
+ for permission in permissions:
+ if not permission['vhost']:
+ module.fail_json(msg="Error parsing vhost permissions: You can't"
+ "have an empty vhost when setting permissions")
+
+ rabbitmq_user = RabbitMqUser(module, username, password, tags, permissions,
+ node, bulk_permissions=bulk_permissions)
+
+ result = dict(changed=False, user=username, state=state)
+ if rabbitmq_user.get():
+ if state == 'absent':
+ rabbitmq_user.delete()
+ result['changed'] = True
+ else:
+ if force:
+ rabbitmq_user.delete()
+ rabbitmq_user.add()
+ rabbitmq_user.get()
+ result['changed'] = True
+ elif update_password == 'always':
+ if not rabbitmq_user.check_password():
+ rabbitmq_user.change_password()
+ result['changed'] = True
+
+ if rabbitmq_user.has_tags_modifications():
+ rabbitmq_user.set_tags()
+ result['changed'] = True
+
+ if rabbitmq_user.has_permissions_modifications():
+ rabbitmq_user.set_permissions()
+ result['changed'] = True
+ elif state == 'present':
+ rabbitmq_user.add()
+ rabbitmq_user.set_tags()
+ rabbitmq_user.set_permissions()
+ result['changed'] = True
+
+ module.exit_json(**result)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_vhost.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_vhost.py
new file mode 100644
index 00000000..3c1eee52
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_vhost.py
@@ -0,0 +1,142 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2013, Chatham Financial <oss@chathamfinancial.com>
+# 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: rabbitmq_vhost
+short_description: Manage the state of a virtual host in RabbitMQ
+description:
+ - Manage the state of a virtual host in RabbitMQ
+author: Chris Hoffman (@chrishoffman)
+options:
+ name:
+ description:
+ - The name of the vhost to manage
+ type: str
+ required: true
+ aliases: [vhost]
+ node:
+ description:
+ - erlang node name of the rabbit we wish to configure
+ type: str
+ default: rabbit
+ tracing:
+ description:
+ - Enable/disable tracing for a vhost
+ type: bool
+ default: 'no'
+ aliases: [trace]
+ state:
+ description:
+ - The state of vhost
+ type: str
+ default: present
+ choices: [present, absent]
+'''
+
+EXAMPLES = '''
+# Ensure that the vhost /test exists.
+- community.rabbitmq.rabbitmq_vhost:
+ name: /test
+ state: present
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+
+
+class RabbitMqVhost(object):
+ def __init__(self, module, name, tracing, node):
+ self.module = module
+ self.name = name
+ self.tracing = tracing
+ self.node = node
+
+ self._tracing = False
+ self._rabbitmqctl = module.get_bin_path('rabbitmqctl', True)
+
+ def _exec(self, args, run_in_check_mode=False):
+ if not self.module.check_mode or (self.module.check_mode and run_in_check_mode):
+ cmd = [self._rabbitmqctl, '-q', '-n', self.node]
+ rc, out, err = self.module.run_command(cmd + args, check_rc=True)
+ return out.splitlines()
+ return list()
+
+ def get(self):
+ vhosts = self._exec(['list_vhosts', 'name', 'tracing'], True)
+
+ for vhost in vhosts:
+ if '\t' not in vhost:
+ continue
+
+ name, tracing = vhost.split('\t')
+ if name == self.name:
+ self._tracing = self.module.boolean(tracing)
+ return True
+ return False
+
+ def add(self):
+ return self._exec(['add_vhost', self.name])
+
+ def delete(self):
+ return self._exec(['delete_vhost', self.name])
+
+ def set_tracing(self):
+ if self.tracing != self._tracing:
+ if self.tracing:
+ self._enable_tracing()
+ else:
+ self._disable_tracing()
+ return True
+ return False
+
+ def _enable_tracing(self):
+ return self._exec(['trace_on', '-p', self.name])
+
+ def _disable_tracing(self):
+ return self._exec(['trace_off', '-p', self.name])
+
+
+def main():
+ arg_spec = dict(
+ name=dict(required=True, aliases=['vhost']),
+ tracing=dict(default='off', aliases=['trace'], type='bool'),
+ state=dict(default='present', choices=['present', 'absent']),
+ node=dict(default='rabbit'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=arg_spec,
+ supports_check_mode=True
+ )
+
+ name = module.params['name']
+ tracing = module.params['tracing']
+ state = module.params['state']
+ node = module.params['node']
+ result = dict(changed=False, name=name, state=state)
+ rabbitmq_vhost = RabbitMqVhost(module, name, tracing, node)
+
+ if rabbitmq_vhost.get():
+ if state == 'absent':
+ rabbitmq_vhost.delete()
+ result['changed'] = True
+ else:
+ if rabbitmq_vhost.set_tracing():
+ result['changed'] = True
+ elif state == 'present':
+ rabbitmq_vhost.add()
+ rabbitmq_vhost.set_tracing()
+ result['changed'] = True
+
+ module.exit_json(**result)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_vhost_limits.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_vhost_limits.py
new file mode 100644
index 00000000..4d54df10
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_vhost_limits.py
@@ -0,0 +1,173 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2018, Hiroyuki Matsuo <h.matsuo.engineer@gmail.com>
+# 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: rabbitmq_vhost_limits
+author: Hiroyuki Matsuo (@h-matsuo)
+
+short_description: Manage the state of virtual host limits in RabbitMQ
+description:
+ - This module sets/clears certain limits on a virtual host.
+ - The configurable limits are I(max_connections) and I(max-queues).
+
+options:
+ max_connections:
+ description:
+ - Max number of concurrent client connections.
+ - Negative value means "no limit".
+ - Ignored when the I(state) is C(absent).
+ type: int
+ default: -1
+ max_queues:
+ description:
+ - Max number of queues.
+ - Negative value means "no limit".
+ - Ignored when the I(state) is C(absent).
+ type: int
+ default: -1
+ node:
+ description:
+ - Name of the RabbitMQ Erlang node to manage.
+ type: str
+ state:
+ description:
+ - Specify whether the limits are to be set or cleared.
+ - If set to C(absent), the limits of both I(max_connections) and I(max-queues) will be cleared.
+ type: str
+ default: present
+ choices: [present, absent]
+ vhost:
+ description:
+ - Name of the virtual host to manage.
+ type: str
+ default: /
+'''
+
+EXAMPLES = '''
+# Limit both of the max number of connections and queues on the vhost '/'.
+- community.rabbitmq.rabbitmq_vhost_limits:
+ vhost: /
+ max_connections: 64
+ max_queues: 256
+ state: present
+
+# Limit the max number of connections on the vhost '/'.
+# This task implicitly clears the max number of queues limit using default value: -1.
+- community.rabbitmq.rabbitmq_vhost_limits:
+ vhost: /
+ max_connections: 64
+ state: present
+
+# Clear the limits on the vhost '/'.
+- community.rabbitmq.rabbitmq_vhost_limits:
+ vhost: /
+ state: absent
+'''
+
+RETURN = ''' # '''
+
+
+import json
+from ansible.module_utils.basic import AnsibleModule
+
+
+class RabbitMqVhostLimits(object):
+ def __init__(self, module):
+ self._module = module
+ self._max_connections = module.params['max_connections']
+ self._max_queues = module.params['max_queues']
+ self._node = module.params['node']
+ self._state = module.params['state']
+ self._vhost = module.params['vhost']
+ self._rabbitmqctl = module.get_bin_path('rabbitmqctl', True)
+
+ def _exec(self, args):
+ cmd = [self._rabbitmqctl, '-q', '-p', self._vhost]
+ if self._node is not None:
+ cmd.extend(['-n', self._node])
+ rc, out, err = self._module.run_command(cmd + args, check_rc=True)
+ return dict(rc=rc, out=out.splitlines(), err=err.splitlines())
+
+ def list(self):
+ exec_result = self._exec(['list_vhost_limits'])
+ vhost_limits = exec_result['out'][0]
+ max_connections = None
+ max_queues = None
+ if vhost_limits:
+ vhost_limits = json.loads(vhost_limits)
+ if 'max-connections' in vhost_limits:
+ max_connections = vhost_limits['max-connections']
+ if 'max-queues' in vhost_limits:
+ max_queues = vhost_limits['max-queues']
+ return dict(
+ max_connections=max_connections,
+ max_queues=max_queues
+ )
+
+ def set(self):
+ if self._module.check_mode:
+ return
+ json_str = '{{"max-connections": {0}, "max-queues": {1}}}'.format(self._max_connections, self._max_queues)
+ self._exec(['set_vhost_limits', json_str])
+
+ def clear(self):
+ if self._module.check_mode:
+ return
+ self._exec(['clear_vhost_limits'])
+
+
+def main():
+ arg_spec = dict(
+ max_connections=dict(default=-1, type='int'),
+ max_queues=dict(default=-1, type='int'),
+ node=dict(default=None, type='str'),
+ state=dict(default='present', choices=['present', 'absent'], type='str'),
+ vhost=dict(default='/', type='str')
+ )
+
+ module = AnsibleModule(
+ argument_spec=arg_spec,
+ supports_check_mode=True
+ )
+
+ max_connections = module.params['max_connections']
+ max_queues = module.params['max_queues']
+ node = module.params['node']
+ state = module.params['state']
+ vhost = module.params['vhost']
+
+ module_result = dict(changed=False)
+ rabbitmq_vhost_limits = RabbitMqVhostLimits(module)
+ current_status = rabbitmq_vhost_limits.list()
+
+ if state == 'present':
+ wanted_status = dict(
+ max_connections=max_connections,
+ max_queues=max_queues
+ )
+ else: # state == 'absent'
+ wanted_status = dict(
+ max_connections=None,
+ max_queues=None
+ )
+
+ if current_status != wanted_status:
+ module_result['changed'] = True
+ if state == 'present':
+ rabbitmq_vhost_limits.set()
+ else: # state == 'absent'
+ rabbitmq_vhost_limits.clear()
+
+ module.exit_json(**module_result)
+
+
+if __name__ == '__main__':
+ main()