Mini Shell
"""
Manage RabbitMQ Upstreams
=========================
Example:
.. code-block:: yaml
rabbit_upstream:
rabbitmq_upstream.present:
- name: upstream_1
- uri: amqp://my_user:my_password@rabbitmq_host
- trust_user_id: True
- ack_mode: on-confirm
- max_hops: 1
.. versionadded:: 3000
"""
import json
import logging
import salt.utils.data
import salt.utils.dictdiffer
from salt.exceptions import CommandExecutionError
log = logging.getLogger(__name__)
def __virtual__():
"""
Only load if the appropriate rabbitmq module functions are loaded.
"""
requirements = [
"rabbitmq.list_upstreams",
"rabbitmq.upstream_exists",
"rabbitmq.set_upstream",
"rabbitmq.delete_upstream",
]
if all(req in __salt__ for req in requirements):
return True
return (False, "rabbitmq module could not be loaded")
def present(
name,
uri,
prefetch_count=None,
reconnect_delay=None,
ack_mode=None,
trust_user_id=None,
exchange=None,
max_hops=None,
expires=None,
message_ttl=None,
ha_policy=None,
queue=None,
runas=None,
):
"""
Ensure the RabbitMQ upstream exists.
:param str name: The name of the upstream connection
:param str uri: The URI to connect to. If upstream is a cluster and can have
several URIs, you can enter them here separated by spaces.
Examples:
- amqp://user:password@server_name
- amqp://user:password@server_name/vhost
When connecting with SSL, several URI-parameters need also be specified:
- cacertfile = /path/to/cacert.pem
- certfile = /path/to/cert.pem
- keyfile = /part/to/key.pem
- verity = verify_peer
- fail_if_no_peer_cert = true | false
- auth_mechanism = external
Example:
- amqp://user:password@server_name?cacertfile=/path/to/cacert.pem&\
certfile=/path/to/cert.pem&keyfile=/path/to/key.pem&verify=verify_peer
- amqp://server-name?cacertfile=/path/to/cacert.pem&certfile=/path/to/cert.pem&\
keyfile=/path/to/key.pem&verify=verify_peer&fail_if_no_peer_cert=true&auth_mechanism=external
:param int prefetch_count: Maximum number of unacknowledged messages that may
be in flight over a federation link at one time. Default: 1000
:param int reconnect_delay: Time in seconds to wait after a network link
goes down before attempting reconnection. Default: 5
:param str ack_mode: The following values are allowed:
on-confirm: Messages are acknowledged to the upstream broker after they
have been confirmed downstream. Handles network errors and broker failures
without losing messages. The slowest option, and the default.
on-publish: Messages are acknowledged to the upstream broker after they
have been published downstream. Handles network errors without losing
messages, but may lose messages in the event of broker failures.
no-ack: Message acknowledgements are not used. The fastest option, but
you may lose messages in the event of network or broker failures.
:param bool trust_user_id: Set ``True`` to preserve the "user-id" field across
a federation link, even if the user-id does not match that used to republish
the message. Set to ``False`` to clear the "user-id" field when messages
are federated. Only set this to ``True`` if you trust the upstream broker
not to forge user-ids.
:param str exchange: The name of the upstream exchange. Default is to use the
same name as the federated exchange.
:param int max_hops: Maximum number of federation links that messages can
traverse before being dropped. Defaults to 1 if not set.
:param int expires: Time in milliseconds that the upstream should remember
about this node for. After this time all upstream state will be removed.
Set to ``None`` (Default) to mean "forever".
:param int message_ttl: Time in milliseconds that undelivered messages should
be held upstream when there is a network outage or backlog.
Set to ``None`` (default) to mean "forever".
:param str ha_policy: Determines the "x-ha-policy"-argument for the upstream
queue for a federated exchange. Default is "none" meaning the queue is
not HA.
:param str queue: The name of the upstream queue. Default is to use the same
name as the federated queue.
.. versionadded:: 3000
"""
ret = {"name": name, "result": False, "comment": "", "changes": {}}
action = None
try:
current_upstreams = __salt__["rabbitmq.list_upstreams"](runas=runas)
except CommandExecutionError as err:
ret["comment"] = f"Error: {err}"
return ret
new_config = salt.utils.data.filter_falsey(
{
"uri": uri,
"prefetch-count": prefetch_count,
"reconnect-delay": reconnect_delay,
"ack-mode": ack_mode,
"trust-user-id": trust_user_id,
"exchange": exchange,
"max-hops": max_hops,
"expires": expires,
"message-ttl": message_ttl,
"ha-policy": ha_policy,
"queue": queue,
}
)
if name in current_upstreams:
current_config = json.loads(current_upstreams.get(name, ""))
diff_config = salt.utils.dictdiffer.deep_diff(current_config, new_config)
if diff_config:
action = "update"
else:
ret["result"] = True
ret["comment"] = f'Upstream "{name}" already present as specified.'
else:
action = "create"
diff_config = {"old": None, "new": new_config}
if action:
if __opts__["test"]:
ret["result"] = None
ret["comment"] = f'Upstream "{name}" would have been {action}d.'
else:
try:
res = __salt__["rabbitmq.set_upstream"](
name,
uri,
prefetch_count=prefetch_count,
reconnect_delay=reconnect_delay,
ack_mode=ack_mode,
trust_user_id=trust_user_id,
exchange=exchange,
max_hops=max_hops,
expires=expires,
message_ttl=message_ttl,
ha_policy=ha_policy,
queue=queue,
runas=runas,
)
ret["result"] = res
ret["comment"] = f'Upstream "{name}" {action}d.'
ret["changes"] = diff_config
except CommandExecutionError as exp:
ret["comment"] = f"Error trying to {action} upstream: {exp}"
return ret
def absent(name, runas=None):
"""
Ensure the named upstream is absent.
:param str name: The name of the upstream to remove
:param str runas: User to run the command
.. versionadded:: 3000
"""
ret = {"name": name, "result": False, "comment": "", "changes": {}}
try:
upstream_exists = __salt__["rabbitmq.upstream_exists"](name, runas=runas)
except CommandExecutionError as err:
ret["comment"] = f"Error: {err}"
return ret
if upstream_exists:
if __opts__["test"]:
ret["result"] = None
ret["comment"] = f'Upstream "{name}" would have been deleted.'
else:
try:
res = __salt__["rabbitmq.delete_upstream"](name, runas=runas)
if res:
ret["result"] = True
ret["comment"] = f'Upstream "{name}" has been deleted.'
ret["changes"] = {"old": name, "new": None}
except CommandExecutionError as err:
ret["comment"] = f"Error: {err}"
else:
ret["result"] = True
ret["comment"] = f'The upstream "{name}" is already absent.'
return ret
Zerion Mini Shell 1.0