mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-07-22 12:50:22 -07:00
Initial commit
This commit is contained in:
commit
aebc1b03fd
4861 changed files with 812621 additions and 0 deletions
297
plugins/modules/messaging/rabbitmq/rabbitmq_binding.py
Normal file
297
plugins/modules/messaging/rabbitmq/rabbitmq_binding.py
Normal file
|
@ -0,0 +1,297 @@
|
|||
#!/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
|
||||
|
||||
ANSIBLE_METADATA = {
|
||||
'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'
|
||||
}
|
||||
|
||||
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.
|
||||
choices: [ "present", "absent" ]
|
||||
default: present
|
||||
name:
|
||||
description:
|
||||
- source exchange to create binding on.
|
||||
required: true
|
||||
aliases: [ "src", "source" ]
|
||||
destination:
|
||||
description:
|
||||
- destination exchange or queue for the binding.
|
||||
required: true
|
||||
aliases: [ "dst", "dest" ]
|
||||
destination_type:
|
||||
description:
|
||||
- Either queue or exchange.
|
||||
required: true
|
||||
choices: [ "queue", "exchange" ]
|
||||
aliases: [ "type", "dest_type" ]
|
||||
routing_key:
|
||||
description:
|
||||
- routing key for the binding.
|
||||
default: "#"
|
||||
arguments:
|
||||
description:
|
||||
- extra arguments for exchange. If defined this argument is a key/value dictionary
|
||||
required: false
|
||||
default: {}
|
||||
extends_documentation_fragment:
|
||||
- community.general.rabbitmq
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Bind myQueue to directExchange with routing key info
|
||||
- rabbitmq_binding:
|
||||
name: directExchange
|
||||
destination: myQueue
|
||||
type: queue
|
||||
routing_key: info
|
||||
|
||||
# Bind directExchange to topicExchange with routing key *.info
|
||||
- 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.general.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()
|
208
plugins/modules/messaging/rabbitmq/rabbitmq_exchange.py
Normal file
208
plugins/modules/messaging/rabbitmq/rabbitmq_exchange.py
Normal file
|
@ -0,0 +1,208 @@
|
|||
#!/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
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
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
|
||||
required: true
|
||||
state:
|
||||
description:
|
||||
- Whether the exchange should be present or absent
|
||||
choices: [ "present", "absent" ]
|
||||
required: false
|
||||
default: present
|
||||
durable:
|
||||
description:
|
||||
- whether exchange is durable or not
|
||||
required: false
|
||||
type: bool
|
||||
default: yes
|
||||
exchange_type:
|
||||
description:
|
||||
- type for the exchange
|
||||
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
|
||||
required: false
|
||||
type: bool
|
||||
default: no
|
||||
internal:
|
||||
description:
|
||||
- exchange is available only for other exchanges
|
||||
required: false
|
||||
type: bool
|
||||
default: no
|
||||
arguments:
|
||||
description:
|
||||
- extra arguments for exchange. If defined this argument is a key/value dictionary
|
||||
required: false
|
||||
default: {}
|
||||
extends_documentation_fragment:
|
||||
- community.general.rabbitmq
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Create direct exchange
|
||||
- rabbitmq_exchange:
|
||||
name: directExchange
|
||||
|
||||
# Create topic exchange on vhost
|
||||
- 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.general.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'], 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()
|
156
plugins/modules/messaging/rabbitmq/rabbitmq_global_parameter.py
Normal file
156
plugins/modules/messaging/rabbitmq/rabbitmq_global_parameter.py
Normal file
|
@ -0,0 +1,156 @@
|
|||
#!/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
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
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
|
||||
required: true
|
||||
default: null
|
||||
value:
|
||||
description:
|
||||
- Value of the global parameter, as a JSON term
|
||||
required: false
|
||||
default: null
|
||||
node:
|
||||
description:
|
||||
- erlang node name of the rabbit we wish to configure
|
||||
required: false
|
||||
default: rabbit
|
||||
state:
|
||||
description:
|
||||
- Specify if user is to be added or removed
|
||||
required: false
|
||||
default: present
|
||||
choices: [ 'present', 'absent']
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Set the global parameter 'cluster_name' to a value of 'mq-cluster' (in quotes)
|
||||
- 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()
|
154
plugins/modules/messaging/rabbitmq/rabbitmq_parameter.py
Normal file
154
plugins/modules/messaging/rabbitmq/rabbitmq_parameter.py
Normal file
|
@ -0,0 +1,154 @@
|
|||
#!/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
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
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
|
||||
required: true
|
||||
name:
|
||||
description:
|
||||
- Name of the parameter being set
|
||||
required: true
|
||||
value:
|
||||
description:
|
||||
- Value of the parameter, as a JSON term
|
||||
vhost:
|
||||
description:
|
||||
- vhost to apply access privileges.
|
||||
default: /
|
||||
node:
|
||||
description:
|
||||
- erlang node name of the rabbit we wish to configure
|
||||
default: rabbit
|
||||
state:
|
||||
description:
|
||||
- Specify if user is to be added or removed
|
||||
default: present
|
||||
choices: [ 'present', 'absent']
|
||||
'''
|
||||
|
||||
EXAMPLES = """
|
||||
# Set the federation parameter 'local_username' to a value of 'guest' (in quotes)
|
||||
- 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()
|
178
plugins/modules/messaging/rabbitmq/rabbitmq_plugin.py
Normal file
178
plugins/modules/messaging/rabbitmq/rabbitmq_plugin.py
Normal file
|
@ -0,0 +1,178 @@
|
|||
#!/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
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {
|
||||
'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'
|
||||
}
|
||||
|
||||
|
||||
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.
|
||||
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.
|
||||
default: enabled
|
||||
choices: [enabled, disabled]
|
||||
prefix:
|
||||
description:
|
||||
- Specify a custom install prefix to a Rabbit.
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Enables the rabbitmq_management plugin
|
||||
rabbitmq_plugin:
|
||||
names: rabbitmq_management
|
||||
state: enabled
|
||||
|
||||
- name: Enable multiple rabbitmq plugins
|
||||
rabbitmq_plugin:
|
||||
names: rabbitmq_management,rabbitmq_management_visualiser
|
||||
state: enabled
|
||||
|
||||
- name: Disable plugin
|
||||
rabbitmq_plugin:
|
||||
names: rabbitmq_management
|
||||
state: disabled
|
||||
|
||||
- name: Enable every plugin in list with existing plugins
|
||||
rabbitmq_plugin:
|
||||
names: rabbitmq_management,rabbitmq_management_visualiser,rabbitmq_shovel,rabbitmq_shovel_management
|
||||
state: enabled
|
||||
new_only: 'yes'
|
||||
'''
|
||||
|
||||
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', name])
|
||||
|
||||
def disable(self, name):
|
||||
self._exec(['disable', 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']),
|
||||
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()
|
245
plugins/modules/messaging/rabbitmq/rabbitmq_policy.py
Normal file
245
plugins/modules/messaging/rabbitmq/rabbitmq_policy.py
Normal file
|
@ -0,0 +1,245 @@
|
|||
#!/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
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
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.
|
||||
required: true
|
||||
vhost:
|
||||
description:
|
||||
- The name of the vhost to apply to.
|
||||
default: /
|
||||
apply_to:
|
||||
description:
|
||||
- What the policy applies to. Requires RabbitMQ 3.2.0 or later.
|
||||
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.
|
||||
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.
|
||||
required: false
|
||||
default: null
|
||||
priority:
|
||||
description:
|
||||
- The priority of the policy.
|
||||
default: 0
|
||||
node:
|
||||
description:
|
||||
- Erlang node name of the rabbit we wish to configure.
|
||||
default: rabbit
|
||||
state:
|
||||
description:
|
||||
- The state of the policy.
|
||||
default: present
|
||||
choices: [present, absent]
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: ensure the default vhost contains the HA policy via a dict
|
||||
rabbitmq_policy:
|
||||
name: HA
|
||||
pattern: .*
|
||||
args:
|
||||
tags:
|
||||
ha-mode: all
|
||||
|
||||
- name: ensure the default vhost contains the HA policy
|
||||
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()
|
256
plugins/modules/messaging/rabbitmq/rabbitmq_queue.py
Normal file
256
plugins/modules/messaging/rabbitmq/rabbitmq_queue.py
Normal file
|
@ -0,0 +1,256 @@
|
|||
#!/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
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
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
|
||||
required: true
|
||||
state:
|
||||
description:
|
||||
- Whether the queue should be present or absent
|
||||
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)
|
||||
default: forever
|
||||
auto_expires:
|
||||
description:
|
||||
- How long a queue can be unused before it is automatically deleted (milliseconds)
|
||||
default: forever
|
||||
max_length:
|
||||
description:
|
||||
- How many messages can the queue contain before it starts rejecting
|
||||
default: no limit
|
||||
dead_letter_exchange:
|
||||
description:
|
||||
- Optional name of an exchange to which messages will be republished if they
|
||||
- are rejected or expire
|
||||
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
|
||||
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.
|
||||
arguments:
|
||||
description:
|
||||
- extra arguments for queue. If defined this argument is a key/value dictionary
|
||||
default: {}
|
||||
extends_documentation_fragment:
|
||||
- community.general.rabbitmq
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Create a queue
|
||||
- rabbitmq_queue:
|
||||
name: myQueue
|
||||
|
||||
# Create a queue on remote host
|
||||
- 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.general.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()
|
321
plugins/modules/messaging/rabbitmq/rabbitmq_user.py
Normal file
321
plugins/modules/messaging/rabbitmq/rabbitmq_user.py
Normal file
|
@ -0,0 +1,321 @@
|
|||
#!/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
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
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
|
||||
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).
|
||||
tags:
|
||||
description:
|
||||
- User tags specified as comma delimited
|
||||
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.
|
||||
default: []
|
||||
vhost:
|
||||
description:
|
||||
- vhost to apply access privileges.
|
||||
- This option will be ignored when permissions option is used.
|
||||
default: /
|
||||
node:
|
||||
description:
|
||||
- erlang node name of the rabbit we wish to configure
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
default: ^$
|
||||
force:
|
||||
description:
|
||||
- Deletes and recreates the user.
|
||||
type: bool
|
||||
default: 'no'
|
||||
state:
|
||||
description:
|
||||
- Specify if user is to be added or removed
|
||||
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.
|
||||
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.
|
||||
- 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
|
||||
- rabbitmq_user:
|
||||
user: joe
|
||||
password: changeme
|
||||
permissions:
|
||||
- vhost: /
|
||||
configure_priv: .*
|
||||
read_priv: .*
|
||||
write_priv: .*
|
||||
state: present
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.common.collections import count
|
||||
|
||||
|
||||
class RabbitMqUser(object):
|
||||
def __init__(self, module, username, password, tags, permissions,
|
||||
node, bulk_permissions=False):
|
||||
self.module = module
|
||||
self.username = username
|
||||
self.password = password
|
||||
self.node = node
|
||||
if not tags:
|
||||
self.tags = list()
|
||||
else:
|
||||
self.tags = tags.split(',')
|
||||
|
||||
self.permissions = permissions
|
||||
self.bulk_permissions = bulk_permissions
|
||||
|
||||
self._tags = None
|
||||
self._permissions = []
|
||||
self._rabbitmqctl = module.get_bin_path('rabbitmqctl', True)
|
||||
|
||||
def _exec(self, args, run_in_check_mode=False, check_rc=True):
|
||||
if not self.module.check_mode or run_in_check_mode:
|
||||
cmd = [self._rabbitmqctl, '-q']
|
||||
if self.node:
|
||||
cmd.extend(['-n', self.node])
|
||||
rc, out, err = self.module.run_command(cmd + args, check_rc=check_rc)
|
||||
return out.splitlines()
|
||||
return list()
|
||||
|
||||
def get(self):
|
||||
users = self._exec(['list_users'], True)
|
||||
|
||||
for user_tag in users:
|
||||
if '\t' not in user_tag:
|
||||
continue
|
||||
|
||||
user, tags = user_tag.split('\t')
|
||||
|
||||
if user == self.username:
|
||||
for c in ['[', ']', ' ']:
|
||||
tags = tags.replace(c, '')
|
||||
|
||||
if tags != '':
|
||||
self._tags = tags.split(',')
|
||||
else:
|
||||
self._tags = list()
|
||||
|
||||
self._permissions = self._get_permissions()
|
||||
return True
|
||||
return False
|
||||
|
||||
def _get_permissions(self):
|
||||
"""Get permissions of the user from RabbitMQ."""
|
||||
perms_out = [perm for perm in self._exec(['list_user_permissions', self.username], True) if perm.strip()]
|
||||
|
||||
perms_list = list()
|
||||
for perm in perms_out:
|
||||
vhost, configure_priv, write_priv, read_priv = perm.split('\t')
|
||||
if not self.bulk_permissions:
|
||||
if vhost == self.permissions[0]['vhost']:
|
||||
perms_list.append(dict(vhost=vhost, configure_priv=configure_priv,
|
||||
write_priv=write_priv, read_priv=read_priv))
|
||||
break
|
||||
else:
|
||||
perms_list.append(dict(vhost=vhost, configure_priv=configure_priv,
|
||||
write_priv=write_priv, read_priv=read_priv))
|
||||
return perms_list
|
||||
|
||||
def check_password(self):
|
||||
return self._exec(['authenticate_user', self.username, self.password],
|
||||
run_in_check_mode=True, check_rc=False)
|
||||
|
||||
def add(self):
|
||||
if self.password is not None:
|
||||
self._exec(['add_user', self.username, self.password])
|
||||
else:
|
||||
self._exec(['add_user', self.username, ''])
|
||||
self._exec(['clear_password', self.username])
|
||||
|
||||
def delete(self):
|
||||
self._exec(['delete_user', self.username])
|
||||
|
||||
def change_password(self):
|
||||
if self.password is not None:
|
||||
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_clear = [permission for permission in self._permissions if permission not in self.permissions]
|
||||
permissions_to_add = [permission for permission in self.permissions if permission not in self._permissions]
|
||||
for permission in permissions_to_clear:
|
||||
cmd = 'clear_permissions -p {vhost} {username}'.format(username=self.username,
|
||||
vhost=permission['vhost'])
|
||||
self._exec(cmd.split(' '))
|
||||
for permission in permissions_to_add:
|
||||
cmd = ('set_permissions -p {vhost} {username} {configure_priv} {write_priv} {read_priv}'
|
||||
.format(username=self.username, **permission))
|
||||
self._exec(cmd.split(' '))
|
||||
|
||||
def has_tags_modifications(self):
|
||||
return set(self.tags) != set(self._tags)
|
||||
|
||||
def has_permissions_modifications(self):
|
||||
def to_permission_tuple(vhost_permission_dict):
|
||||
return vhost_permission_dict['vhost'], vhost_permission_dict
|
||||
|
||||
def permission_dict(vhost_permission_list):
|
||||
return dict(map(to_permission_tuple, vhost_permission_list))
|
||||
|
||||
return permission_dict(self._permissions) != permission_dict(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'),
|
||||
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'])
|
||||
)
|
||||
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 = map(lambda permission: permission.get('vhost', '/'), permissions)
|
||||
if any(map(lambda count: count > 1, count(vhosts).values())):
|
||||
module.fail_json(msg="Error parsing 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
|
||||
|
||||
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()
|
144
plugins/modules/messaging/rabbitmq/rabbitmq_vhost.py
Normal file
144
plugins/modules/messaging/rabbitmq/rabbitmq_vhost.py
Normal file
|
@ -0,0 +1,144 @@
|
|||
#!/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
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
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
|
||||
required: true
|
||||
aliases: [vhost]
|
||||
node:
|
||||
description:
|
||||
- erlang node name of the rabbit we wish to configure
|
||||
default: rabbit
|
||||
tracing:
|
||||
description:
|
||||
- Enable/disable tracing for a vhost
|
||||
type: bool
|
||||
default: 'no'
|
||||
aliases: [trace]
|
||||
state:
|
||||
description:
|
||||
- The state of vhost
|
||||
default: present
|
||||
choices: [present, absent]
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Ensure that the vhost /test exists.
|
||||
- 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()
|
172
plugins/modules/messaging/rabbitmq/rabbitmq_vhost_limits.py
Normal file
172
plugins/modules/messaging/rabbitmq/rabbitmq_vhost_limits.py
Normal file
|
@ -0,0 +1,172 @@
|
|||
#!/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
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
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).
|
||||
default: -1
|
||||
max_queues:
|
||||
description:
|
||||
- Max number of queues.
|
||||
- Negative value means "no limit".
|
||||
- Ignored when the I(state) is C(absent).
|
||||
default: -1
|
||||
node:
|
||||
description:
|
||||
- Name of the RabbitMQ Erlang node to manage.
|
||||
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.
|
||||
default: present
|
||||
choices: [present, absent]
|
||||
vhost:
|
||||
description:
|
||||
- Name of the virtual host to manage.
|
||||
default: /
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Limit both of the max number of connections and queues on the vhost '/'.
|
||||
- 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.
|
||||
- rabbitmq_vhost_limits:
|
||||
vhost: /
|
||||
max_connections: 64
|
||||
state: present
|
||||
|
||||
# Clear the limits on the vhost '/'.
|
||||
- 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()
|
Loading…
Add table
Add a link
Reference in a new issue