MQ - Initial implementation (#4789)
This commit is contained in:
parent
35d3c72039
commit
cf50da6938
@ -3587,6 +3587,34 @@
|
||||
- [X] put_object
|
||||
</details>
|
||||
|
||||
## mq
|
||||
<details>
|
||||
<summary>86% implemented</summary>
|
||||
|
||||
- [X] create_broker
|
||||
- [X] create_configuration
|
||||
- [X] create_tags
|
||||
- [X] create_user
|
||||
- [X] delete_broker
|
||||
- [X] delete_tags
|
||||
- [X] delete_user
|
||||
- [X] describe_broker
|
||||
- [ ] describe_broker_engine_types
|
||||
- [ ] describe_broker_instance_options
|
||||
- [X] describe_configuration
|
||||
- [X] describe_configuration_revision
|
||||
- [X] describe_user
|
||||
- [X] list_brokers
|
||||
- [ ] list_configuration_revisions
|
||||
- [X] list_configurations
|
||||
- [X] list_tags
|
||||
- [X] list_users
|
||||
- [X] reboot_broker
|
||||
- [X] update_broker
|
||||
- [X] update_configuration
|
||||
- [X] update_user
|
||||
</details>
|
||||
|
||||
## opsworks
|
||||
<details>
|
||||
<summary>12% implemented</summary>
|
||||
@ -5372,7 +5400,6 @@
|
||||
- migrationhub-config
|
||||
- migrationhubstrategy
|
||||
- mobile
|
||||
- mq
|
||||
- mturk
|
||||
- mwaa
|
||||
- neptune
|
||||
|
64
docs/docs/services/mq.rst
Normal file
64
docs/docs/services/mq.rst
Normal file
@ -0,0 +1,64 @@
|
||||
.. _implementedservice_mq:
|
||||
|
||||
.. |start-h3| raw:: html
|
||||
|
||||
<h3>
|
||||
|
||||
.. |end-h3| raw:: html
|
||||
|
||||
</h3>
|
||||
|
||||
==
|
||||
mq
|
||||
==
|
||||
|
||||
.. autoclass:: moto.mq.models.MQBackend
|
||||
|
||||
|start-h3| Example usage |end-h3|
|
||||
|
||||
.. sourcecode:: python
|
||||
|
||||
@mock_mq
|
||||
def test_mq_behaviour:
|
||||
boto3.client("mq")
|
||||
...
|
||||
|
||||
|
||||
|
||||
|start-h3| Implemented features for this service |end-h3|
|
||||
|
||||
- [X] create_broker
|
||||
- [X] create_configuration
|
||||
- [X] create_tags
|
||||
- [X] create_user
|
||||
- [X] delete_broker
|
||||
- [X] delete_tags
|
||||
- [X] delete_user
|
||||
- [X] describe_broker
|
||||
- [ ] describe_broker_engine_types
|
||||
- [ ] describe_broker_instance_options
|
||||
- [X] describe_configuration
|
||||
- [X] describe_configuration_revision
|
||||
- [X] describe_user
|
||||
- [X] list_brokers
|
||||
|
||||
Pagination is not yet implemented
|
||||
|
||||
|
||||
- [ ] list_configuration_revisions
|
||||
- [X] list_configurations
|
||||
|
||||
Pagination has not yet been implemented.
|
||||
|
||||
|
||||
- [X] list_tags
|
||||
- [X] list_users
|
||||
- [X] reboot_broker
|
||||
- [X] update_broker
|
||||
- [X] update_configuration
|
||||
|
||||
No validation occurs on the provided XML. The authenticationStrategy may be changed depending on the provided configuration.
|
||||
|
||||
|
||||
- [X] update_user
|
||||
|
@ -84,6 +84,7 @@ mock_kinesis = lazy_load(".kinesis", "mock_kinesis")
|
||||
mock_kms = lazy_load(".kms", "mock_kms")
|
||||
mock_logs = lazy_load(".logs", "mock_logs")
|
||||
mock_managedblockchain = lazy_load(".managedblockchain", "mock_managedblockchain")
|
||||
mock_mq = lazy_load(".mq", "mock_mq", boto3_name="mq")
|
||||
mock_opsworks = lazy_load(".opsworks", "mock_opsworks")
|
||||
mock_organizations = lazy_load(".organizations", "mock_organizations")
|
||||
mock_polly = lazy_load(".polly", "mock_polly")
|
||||
|
@ -91,6 +91,7 @@ backend_url_patterns = [
|
||||
("mediapackage", re.compile("https?://mediapackage\\.(.+)\\.amazonaws.com")),
|
||||
("mediastore", re.compile("https?://mediastore\\.(.+)\\.amazonaws\\.com")),
|
||||
("mediastore-data", re.compile("https?://data.mediastore\\.(.+)\\.amazonaws.com")),
|
||||
("mq", re.compile("https?://mq\\.(.+)\\.amazonaws\\.com")),
|
||||
("opsworks", re.compile("https?://opsworks\\.us-east-1\\.amazonaws.com")),
|
||||
("organizations", re.compile("https?://organizations\\.(.+)\\.amazonaws\\.com")),
|
||||
("polly", re.compile("https?://polly\\.(.+)\\.amazonaws.com")),
|
||||
|
5
moto/mq/__init__.py
Normal file
5
moto/mq/__init__.py
Normal file
@ -0,0 +1,5 @@
|
||||
"""mq module initialization; sets value for base decorator."""
|
||||
from .models import mq_backends
|
||||
from ..core.models import base_decorator
|
||||
|
||||
mock_mq = base_decorator(mq_backends)
|
183
moto/mq/configuration.py
Normal file
183
moto/mq/configuration.py
Normal file
@ -0,0 +1,183 @@
|
||||
DEFAULT_CONFIGURATION_DATA = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<broker xmlns="http://activemq.apache.org/schema/core" schedulePeriodForDestinationPurge="10000">
|
||||
<!--
|
||||
A configuration contains all of the settings for your ActiveMQ broker, in XML format (similar to ActiveMQ's activemq.xml file).
|
||||
You can create a configuration before creating any brokers. You can then apply the configuration to one or more brokers.
|
||||
|
||||
You can use additional attributes for the broker element above. These attributes allow you to configure broker-wide settings.
|
||||
|
||||
For more information, see Configuration and Amazon MQ Broker Configuration Parameters in the Amazon MQ Developer Guide:
|
||||
https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/amazon-mq-broker-configuration-parameters.html
|
||||
-->
|
||||
<!--
|
||||
Mirrored queues let you send a copy of each message to a topic with a similar name automatically.
|
||||
For more information, see http://activemq.apache.org/mirrored-queues.html
|
||||
|
||||
Virtual destinations let you configure advanced routing of messages between destinations.
|
||||
For more information, see http://activemq.apache.org/virtual-destinations.html
|
||||
-->
|
||||
<!--
|
||||
<destinationInterceptors>
|
||||
<mirroredQueue copyMessage="true" postfix=".qmirror" prefix=""/>
|
||||
<virtualDestinationInterceptor>
|
||||
<virtualDestinations>
|
||||
<virtualTopic name=">" prefix="VirtualTopicConsumers.*." selectorAware="false"/>
|
||||
<compositeQueue name="MY.QUEUE">
|
||||
<forwardTo>
|
||||
<queue physicalName="FOO"/>
|
||||
<topic physicalName="BAR"/>
|
||||
</forwardTo>
|
||||
</compositeQueue>
|
||||
</virtualDestinations>
|
||||
</virtualDestinationInterceptor>
|
||||
</destinationInterceptors>
|
||||
-->
|
||||
<!--
|
||||
By default, Amazon MQ optimizes for queues with fast consumers:
|
||||
Consumers are considered fast if they are able to keep up with the rate of messages generated by producers.
|
||||
Consumers are considered slow if a queue builds up a backlog of unacknowledged messages, potentially causing a decrease in producer throughput.
|
||||
To instruct Amazon MQ to optimize for queues with slow consumers, set the concurrentStoreAndDispatchQueues attribute to false.
|
||||
For more information, see https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/ensuring-effective-amazon-mq-performance.html
|
||||
-->
|
||||
<!--
|
||||
<persistenceAdapter>
|
||||
<kahaDB concurrentStoreAndDispatchQueues="false"/>
|
||||
</persistenceAdapter>
|
||||
-->
|
||||
<destinationPolicy>
|
||||
<policyMap>
|
||||
<policyEntries>
|
||||
<!--
|
||||
gcInactiveDestinations is used to automatically purge inactive destinations
|
||||
preventing them from unnecessarily using broker resources.
|
||||
|
||||
An 'inactive' destination is one that has no messages pending and no consumers connected.
|
||||
|
||||
For more information, see: http://activemq.apache.org/delete-inactive-destinations.html
|
||||
-->
|
||||
<policyEntry topic=">" gcInactiveDestinations="true" inactiveTimoutBeforeGC="600000">
|
||||
<!--
|
||||
The constantPendingMessageLimitStrategy is used to prevent
|
||||
slow topic consumers to block producers and affect other consumers
|
||||
by limiting the number of messages that are retained
|
||||
|
||||
For more information, see: http://activemq.apache.org/slow-consumer-handling.html
|
||||
-->
|
||||
<pendingMessageLimitStrategy>
|
||||
<constantPendingMessageLimitStrategy limit="1000"/>
|
||||
</pendingMessageLimitStrategy>
|
||||
</policyEntry>
|
||||
<policyEntry queue=">" gcInactiveDestinations="true" inactiveTimoutBeforeGC="600000" />
|
||||
<!--
|
||||
Destination policies let you configure a rich set of behaviors for your queues and topics.
|
||||
For more information, see http://activemq.apache.org/per-destination-policies.html
|
||||
-->
|
||||
<!--
|
||||
<policyEntry topic="FOO.>">
|
||||
<dispatchPolicy>
|
||||
<roundRobinDispatchPolicy/>
|
||||
</dispatchPolicy>
|
||||
<subscriptionRecoveryPolicy>
|
||||
<lastImageSubscriptionRecoveryPolicy/>
|
||||
</subscriptionRecoveryPolicy>
|
||||
</policyEntry>
|
||||
<policyEntry advisoryForConsumed="true" tempTopic="true"/>
|
||||
<policyEntry advisoryForConsumed="true" tempQueue="true"/>
|
||||
-->
|
||||
</policyEntries>
|
||||
</policyMap>
|
||||
</destinationPolicy>
|
||||
<!--
|
||||
Typically, destinations are created automatically when they are used. Amazon MQ lets you create destinations when the broker is started.
|
||||
For more information, see http://activemq.apache.org/configure-startup-destinations.html
|
||||
-->
|
||||
<!--
|
||||
<destinations>
|
||||
<queue physicalName="FOO.BAR"/>
|
||||
<topic physicalName="SOME.TOPIC"/>
|
||||
</destinations>
|
||||
-->
|
||||
<!--
|
||||
You can control advanced ActiveMQ features using plugins.
|
||||
-->
|
||||
<plugins>
|
||||
<!--
|
||||
The Authorization plugin allows you to control the groups of users that are allowed to perform certain operations on your destinations.
|
||||
For more information, see http://activemq.apache.org/security.html
|
||||
-->
|
||||
<!--
|
||||
<authorizationPlugin>
|
||||
<map>
|
||||
<authorizationMap>
|
||||
<authorizationEntries>
|
||||
<authorizationEntry admin="guests,users" queue="GUEST.>" read="guests" write="guests,users"/>
|
||||
<authorizationEntry admin="guests,users" read="guests,users" topic="ActiveMQ.Advisory.>" write="guests,users"/>
|
||||
</authorizationEntries>
|
||||
<tempDestinationAuthorizationEntry>
|
||||
<tempDestinationAuthorizationEntry admin="tempDestinationAdmins" read="tempDestinationAdmins" write="tempDestinationAdmins"/>
|
||||
</tempDestinationAuthorizationEntry>
|
||||
</authorizationMap>
|
||||
</map>
|
||||
</authorizationPlugin>
|
||||
-->
|
||||
<!--
|
||||
The Discarding DLQ plugin simplifies the configuration of your global dead-letter queue strategy.
|
||||
You can take advantage of a more granular per-destination control by using destination policies.
|
||||
For more information, see http://activemq.apache.org/message-redelivery-and-dlq-handling.html
|
||||
-->
|
||||
<!--
|
||||
<discardingDLQBrokerPlugin dropAll="true" dropTemporaryQueues="true" dropTemporaryTopics="true"/>
|
||||
-->
|
||||
<!--
|
||||
The Force Persistency Mode plugin can override the persistency mode set on messages.
|
||||
-->
|
||||
<!--
|
||||
<forcePersistencyModeBrokerPlugin persistenceFlag="true"/>
|
||||
-->
|
||||
<!--
|
||||
The Redelivery plugin extends the capabilities of destination policies with respect to message redelivery.
|
||||
For more information, see http://activemq.apache.org/message-redelivery-and-dlq-handling.html
|
||||
-->
|
||||
<!--
|
||||
<redeliveryPlugin fallbackToDeadLetter="true" sendToDlqIfMaxRetriesExceeded="true">
|
||||
<redeliveryPolicyMap>
|
||||
<redeliveryPolicyMap>
|
||||
<redeliveryPolicyEntries>
|
||||
<redeliveryPolicy maximumRedeliveries="4" queue="SpecialQueue" redeliveryDelay="10000"/>
|
||||
</redeliveryPolicyEntries>
|
||||
<defaultEntry>
|
||||
<redeliveryPolicy initialRedeliveryDelay="5000" maximumRedeliveries="4" redeliveryDelay="10000"/>
|
||||
</defaultEntry>
|
||||
</redeliveryPolicyMap>
|
||||
</redeliveryPolicyMap>
|
||||
</redeliveryPlugin>
|
||||
-->
|
||||
<!--
|
||||
The Statistics plugin lets you query broker or destination statistics by sending messages to the broker.
|
||||
For more information, see http://activemq.apache.org/statisticsplugin.html
|
||||
-->
|
||||
<!--
|
||||
<statisticsBrokerPlugin/>
|
||||
-->
|
||||
<!--
|
||||
The Timestamping plugin lets the broker use server-side time instead of client-provided time for messages.
|
||||
For more information, see http://activemq.apache.org/timestampplugin.html
|
||||
-->
|
||||
<!--
|
||||
<timeStampingBrokerPlugin ttlCeiling="86400000" zeroExpirationOverride="86400000"/>
|
||||
-->
|
||||
</plugins>
|
||||
<!--
|
||||
Network connectors let you connect brokers into networks of brokers.
|
||||
For more information, see Creating and Configuring an Amazon MQ Network of Brokers
|
||||
(https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/amazon-mq-creating-configuring-network-of-brokers.html)
|
||||
in the Amazon MQ Developer Guide and also Networks of Brokers
|
||||
(http://activemq.apache.org/networks-of-brokers.html) in the ActiveMQ documentation.
|
||||
-->
|
||||
<!--
|
||||
<networkConnectors>
|
||||
<networkConnector name="myNetworkConnector" userName="commonUser" uri="masterslave:(ssl://b-1a2b3c4d-1.mq.region.amazonaws.com:61617,ssl://b-1a2b3c4d-2.mq.region.amazonaws.com:61617)"/>
|
||||
</networkConnectors>
|
||||
-->
|
||||
</broker>
|
||||
"""
|
71
moto/mq/exceptions.py
Normal file
71
moto/mq/exceptions.py
Normal file
@ -0,0 +1,71 @@
|
||||
import json
|
||||
from moto.core.exceptions import JsonRESTError
|
||||
|
||||
|
||||
class MQError(JsonRESTError):
|
||||
pass
|
||||
|
||||
|
||||
class UnknownBroker(MQError):
|
||||
def __init__(self, broker_id):
|
||||
super().__init__("NotFoundException", "Can't find requested broker")
|
||||
self.broker_id = broker_id
|
||||
|
||||
def get_body(self):
|
||||
body = {
|
||||
"errorAttribute": "broker-id",
|
||||
"message": f"Can't find requested broker [{self.broker_id}]. Make sure your broker exists.",
|
||||
}
|
||||
return json.dumps(body)
|
||||
|
||||
|
||||
class UnknownConfiguration(MQError):
|
||||
def __init__(self, config_id):
|
||||
super().__init__("NotFoundException", "Can't find requested configuration")
|
||||
self.config_id = config_id
|
||||
|
||||
def get_body(self):
|
||||
body = {
|
||||
"errorAttribute": "configuration_id",
|
||||
"message": f"Can't find requested configuration [{self.config_id}]. Make sure your configuration exists.",
|
||||
}
|
||||
return json.dumps(body)
|
||||
|
||||
|
||||
class UnknownUser(MQError):
|
||||
def __init__(self, username):
|
||||
super().__init__("NotFoundException", "Can't find requested user")
|
||||
self.username = username
|
||||
|
||||
def get_body(self):
|
||||
body = {
|
||||
"errorAttribute": "username",
|
||||
"message": f"Can't find requested user [{self.username}]. Make sure your user exists.",
|
||||
}
|
||||
return json.dumps(body)
|
||||
|
||||
|
||||
class UnsupportedEngineType(MQError):
|
||||
def __init__(self, engine_type):
|
||||
super().__init__("BadRequestException", "")
|
||||
self.engine_type = engine_type
|
||||
|
||||
def get_body(self):
|
||||
body = {
|
||||
"errorAttribute": "engineType",
|
||||
"message": f"Broker engine type [{self.engine_type}] does not support configuration.",
|
||||
}
|
||||
return json.dumps(body)
|
||||
|
||||
|
||||
class UnknownEngineType(MQError):
|
||||
def __init__(self, engine_type):
|
||||
super().__init__("BadRequestException", "")
|
||||
self.engine_type = engine_type
|
||||
|
||||
def get_body(self):
|
||||
body = {
|
||||
"errorAttribute": "engineType",
|
||||
"message": f"Broker engine type [{self.engine_type}] is invalid. Valid values are: [ACTIVEMQ]",
|
||||
}
|
||||
return json.dumps(body)
|
528
moto/mq/models.py
Normal file
528
moto/mq/models.py
Normal file
@ -0,0 +1,528 @@
|
||||
import base64
|
||||
import xmltodict
|
||||
|
||||
from moto.core import ACCOUNT_ID, BaseBackend, BaseModel
|
||||
from moto.core.utils import BackendDict, get_random_hex, unix_time
|
||||
from moto.utilities.tagging_service import TaggingService
|
||||
|
||||
from .configuration import DEFAULT_CONFIGURATION_DATA
|
||||
from .exceptions import (
|
||||
UnknownBroker,
|
||||
UnknownConfiguration,
|
||||
UnknownUser,
|
||||
UnsupportedEngineType,
|
||||
UnknownEngineType,
|
||||
)
|
||||
|
||||
|
||||
class ConfigurationRevision(BaseModel):
|
||||
def __init__(self, configuration_id, revision_id, description, data=None):
|
||||
self.configuration_id = configuration_id
|
||||
self.created = unix_time()
|
||||
self.description = description
|
||||
self.is_invalid = False
|
||||
self.revision_id = revision_id
|
||||
|
||||
if data is None:
|
||||
self.data = base64.b64encode(
|
||||
DEFAULT_CONFIGURATION_DATA.encode("UTF-8")
|
||||
).decode("utf-8")
|
||||
else:
|
||||
self.data = data
|
||||
|
||||
def has_ldap_auth(self):
|
||||
try:
|
||||
xml = base64.b64decode(self.data)
|
||||
dct = xmltodict.parse(xml, dict_constructor=dict)
|
||||
return (
|
||||
"cachedLDAPAuthorizationMap"
|
||||
in dct["broker"]["plugins"]["authorizationPlugin"]["map"]
|
||||
)
|
||||
except Exception:
|
||||
# There are many configurations to enable LDAP
|
||||
# We're only checking for one here
|
||||
# If anything fails, lets assume it's not LDAP
|
||||
return False
|
||||
|
||||
def to_json(self, full=True):
|
||||
resp = {
|
||||
"created": self.created,
|
||||
"description": self.description,
|
||||
"revision": int(self.revision_id),
|
||||
}
|
||||
if full:
|
||||
resp["configurationId"] = self.configuration_id
|
||||
resp["data"] = self.data
|
||||
return resp
|
||||
|
||||
|
||||
class Configuration(BaseModel):
|
||||
def __init__(self, region, name, engine_type, engine_version):
|
||||
self.id = f"c-{get_random_hex(6)}"
|
||||
self.arn = f"arn:aws:mq:{region}:{ACCOUNT_ID}:configuration:{self.id}"
|
||||
self.created = unix_time()
|
||||
|
||||
self.name = name
|
||||
self.engine_type = engine_type
|
||||
self.engine_version = engine_version
|
||||
|
||||
self.revisions = dict()
|
||||
default_desc = (
|
||||
f"Auto-generated default for {self.name} on {engine_type} {engine_version}"
|
||||
)
|
||||
latest_revision = ConfigurationRevision(
|
||||
configuration_id=self.id, revision_id="1", description=default_desc
|
||||
)
|
||||
self.revisions[latest_revision.revision_id] = latest_revision
|
||||
|
||||
self.authentication_strategy = (
|
||||
"ldap" if latest_revision.has_ldap_auth() else "simple"
|
||||
)
|
||||
|
||||
def update(self, data, description):
|
||||
max_revision_id, _ = sorted(self.revisions.items())[-1]
|
||||
next_revision_id = str(int(max_revision_id) + 1)
|
||||
latest_revision = ConfigurationRevision(
|
||||
configuration_id=self.id,
|
||||
revision_id=next_revision_id,
|
||||
description=description,
|
||||
data=data,
|
||||
)
|
||||
self.revisions[next_revision_id] = latest_revision
|
||||
|
||||
self.authentication_strategy = (
|
||||
"ldap" if latest_revision.has_ldap_auth() else "simple"
|
||||
)
|
||||
|
||||
def get_revision(self, revision_id):
|
||||
return self.revisions[revision_id]
|
||||
|
||||
def to_json(self):
|
||||
_, latest_revision = sorted(self.revisions.items())[-1]
|
||||
return {
|
||||
"arn": self.arn,
|
||||
"authenticationStrategy": self.authentication_strategy,
|
||||
"created": self.created,
|
||||
"engineType": self.engine_type,
|
||||
"engineVersion": self.engine_version,
|
||||
"id": self.id,
|
||||
"name": self.name,
|
||||
"latestRevision": latest_revision.to_json(full=False),
|
||||
}
|
||||
|
||||
|
||||
class User(BaseModel):
|
||||
def __init__(self, broker_id, username, console_access=None, groups=None):
|
||||
self.broker_id = broker_id
|
||||
self.username = username
|
||||
self.console_access = console_access or False
|
||||
self.groups = groups or []
|
||||
|
||||
def update(self, console_access, groups):
|
||||
if console_access is not None:
|
||||
self.console_access = console_access
|
||||
if groups:
|
||||
self.groups = groups
|
||||
|
||||
def summary(self):
|
||||
return {"username": self.username}
|
||||
|
||||
def to_json(self):
|
||||
return {
|
||||
"brokerId": self.broker_id,
|
||||
"username": self.username,
|
||||
"consoleAccess": self.console_access,
|
||||
"groups": self.groups,
|
||||
}
|
||||
|
||||
|
||||
class Broker(BaseModel):
|
||||
def __init__(
|
||||
self,
|
||||
name,
|
||||
region,
|
||||
authentication_strategy,
|
||||
auto_minor_version_upgrade,
|
||||
configuration,
|
||||
deployment_mode,
|
||||
encryption_options,
|
||||
engine_type,
|
||||
engine_version,
|
||||
host_instance_type,
|
||||
ldap_server_metadata,
|
||||
logs,
|
||||
maintenance_window_start_time,
|
||||
publicly_accessible,
|
||||
security_groups,
|
||||
storage_type,
|
||||
subnet_ids,
|
||||
users,
|
||||
):
|
||||
self.name = name
|
||||
self.id = get_random_hex(6)
|
||||
self.arn = f"arn:aws:mq:{region}:{ACCOUNT_ID}:broker:{self.id}"
|
||||
self.state = "RUNNING"
|
||||
self.created = unix_time()
|
||||
|
||||
self.authentication_strategy = authentication_strategy
|
||||
self.auto_minor_version_upgrade = auto_minor_version_upgrade
|
||||
self.deployment_mode = deployment_mode
|
||||
self.encryption_options = encryption_options
|
||||
if not self.encryption_options:
|
||||
self.encryption_options = {"useAwsOwnedKey": True}
|
||||
self.engine_type = engine_type
|
||||
self.engine_version = engine_version
|
||||
self.host_instance_type = host_instance_type
|
||||
self.ldap_server_metadata = ldap_server_metadata
|
||||
self.logs = logs
|
||||
if "general" not in self.logs:
|
||||
self.logs["general"] = False
|
||||
if "audit" not in self.logs:
|
||||
if self.engine_type.upper() == "ACTIVEMQ":
|
||||
self.logs["audit"] = False
|
||||
self.maintenance_window_start_time = maintenance_window_start_time
|
||||
if not self.maintenance_window_start_time:
|
||||
self.maintenance_window_start_time = {
|
||||
"dayOfWeek": "Sunday",
|
||||
"timeOfDay": "00:00",
|
||||
"timeZone": "UTC",
|
||||
}
|
||||
self.publicly_accessible = publicly_accessible
|
||||
self.security_groups = security_groups
|
||||
self.storage_type = storage_type
|
||||
self.subnet_ids = subnet_ids
|
||||
if not self.subnet_ids:
|
||||
if self.deployment_mode == "CLUSTER_MULTI_AZ":
|
||||
self.subnet_ids = [
|
||||
"default-az1",
|
||||
"default-az2",
|
||||
"default-az3",
|
||||
"default-az4",
|
||||
]
|
||||
elif self.deployment_mode == "ACTIVE_STANDBY_MULTI_AZ":
|
||||
self.subnet_ids = ["active-subnet", "standby-subnet"]
|
||||
else:
|
||||
self.subnet_ids = ["default-subnet"]
|
||||
|
||||
self.users = dict()
|
||||
for user in users:
|
||||
self.create_user(
|
||||
username=user["username"],
|
||||
groups=user.get("groups", []),
|
||||
console_access=user.get("consoleAccess", False),
|
||||
)
|
||||
|
||||
if self.engine_type.upper() == "RABBITMQ":
|
||||
self.configurations = None
|
||||
else:
|
||||
current_config = configuration or {
|
||||
"id": f"c-{get_random_hex(6)}",
|
||||
"revision": 1,
|
||||
}
|
||||
self.configurations = {
|
||||
"current": current_config,
|
||||
"history": [],
|
||||
}
|
||||
if self.engine_type.upper() == "RABBITMQ":
|
||||
console_url = f"https://0000.mq.{region}.amazonaws.com"
|
||||
endpoints = ["amqps://mockmq:5671"]
|
||||
else:
|
||||
console_url = f"https://0000.mq.{region}.amazonaws.com:8162"
|
||||
endpoints = [
|
||||
"ssl://mockmq:61617",
|
||||
"amqp+ssl://mockmq:5671",
|
||||
"stomp+ssl://mockmq:61614",
|
||||
"mqtt+ssl://mockmq:8883",
|
||||
"wss://mockmq:61619",
|
||||
]
|
||||
self.instances = [
|
||||
{
|
||||
"consoleURL": console_url,
|
||||
"endpoints": endpoints,
|
||||
"ipAddress": "192.168.0.1",
|
||||
}
|
||||
]
|
||||
|
||||
if deployment_mode == "ACTIVE_STANDBY_MULTI_AZ":
|
||||
self.instances.append(
|
||||
{
|
||||
"consoleURL": console_url,
|
||||
"endpoints": endpoints,
|
||||
"ipAddress": "192.168.0.2",
|
||||
}
|
||||
)
|
||||
|
||||
def update(
|
||||
self,
|
||||
authentication_strategy,
|
||||
auto_minor_version_upgrade,
|
||||
configuration,
|
||||
engine_version,
|
||||
host_instance_type,
|
||||
ldap_server_metadata,
|
||||
logs,
|
||||
maintenance_window_start_time,
|
||||
security_groups,
|
||||
):
|
||||
if authentication_strategy:
|
||||
self.authentication_strategy = authentication_strategy
|
||||
if auto_minor_version_upgrade is not None:
|
||||
self.auto_minor_version_upgrade = auto_minor_version_upgrade
|
||||
if configuration:
|
||||
self.configurations["history"].append(self.configurations["current"])
|
||||
self.configurations["current"] = configuration
|
||||
if engine_version:
|
||||
self.engine_version = engine_version
|
||||
if host_instance_type:
|
||||
self.host_instance_type = host_instance_type
|
||||
if ldap_server_metadata:
|
||||
self.ldap_server_metadata = ldap_server_metadata
|
||||
if logs:
|
||||
self.logs = logs
|
||||
if maintenance_window_start_time:
|
||||
self.maintenance_window_start_time = maintenance_window_start_time
|
||||
if security_groups:
|
||||
self.security_groups = security_groups
|
||||
|
||||
def reboot(self):
|
||||
pass
|
||||
|
||||
def create_user(self, username, console_access, groups):
|
||||
user = User(self.id, username, console_access, groups)
|
||||
self.users[username] = user
|
||||
|
||||
def update_user(self, username, console_access, groups):
|
||||
user = self.get_user(username)
|
||||
user.update(console_access, groups)
|
||||
|
||||
def get_user(self, username):
|
||||
if username not in self.users:
|
||||
raise UnknownUser(username)
|
||||
return self.users[username]
|
||||
|
||||
def delete_user(self, username):
|
||||
self.users.pop(username, None)
|
||||
|
||||
def list_users(self):
|
||||
return self.users.values()
|
||||
|
||||
def summary(self):
|
||||
return {
|
||||
"brokerArn": self.arn,
|
||||
"brokerId": self.id,
|
||||
"brokerName": self.name,
|
||||
"brokerState": self.state,
|
||||
"created": self.created,
|
||||
"deploymentMode": self.deployment_mode,
|
||||
"engineType": self.engine_type,
|
||||
"hostInstanceType": self.host_instance_type,
|
||||
}
|
||||
|
||||
def to_json(self):
|
||||
return {
|
||||
"brokerId": self.id,
|
||||
"brokerArn": self.arn,
|
||||
"brokerName": self.name,
|
||||
"brokerState": self.state,
|
||||
"brokerInstances": self.instances,
|
||||
"created": self.created,
|
||||
"configurations": self.configurations,
|
||||
"authenticationStrategy": self.authentication_strategy,
|
||||
"autoMinorVersionUpgrade": self.auto_minor_version_upgrade,
|
||||
"deploymentMode": self.deployment_mode,
|
||||
"encryptionOptions": self.encryption_options,
|
||||
"engineType": self.engine_type,
|
||||
"engineVersion": self.engine_version,
|
||||
"hostInstanceType": self.host_instance_type,
|
||||
"ldapServerMetadata": self.ldap_server_metadata,
|
||||
"logs": self.logs,
|
||||
"maintenanceWindowStartTime": self.maintenance_window_start_time,
|
||||
"publiclyAccessible": self.publicly_accessible,
|
||||
"securityGroups": self.security_groups,
|
||||
"storageType": self.storage_type,
|
||||
"subnetIds": self.subnet_ids,
|
||||
"users": [u.summary() for u in self.users.values()],
|
||||
}
|
||||
|
||||
|
||||
class MQBackend(BaseBackend):
|
||||
"""
|
||||
No EC2 integration exists yet - subnet ID's and security group values are not validated. Default values may not exist.
|
||||
"""
|
||||
|
||||
def __init__(self, region_name=None):
|
||||
self.region_name = region_name
|
||||
self.brokers = dict()
|
||||
self.configs = dict()
|
||||
self.tagger = TaggingService()
|
||||
|
||||
def reset(self):
|
||||
"""Re-initialize all attributes for this instance."""
|
||||
region_name = self.region_name
|
||||
self.__dict__ = {}
|
||||
self.__init__(region_name)
|
||||
|
||||
def create_broker(
|
||||
self,
|
||||
authentication_strategy,
|
||||
auto_minor_version_upgrade,
|
||||
broker_name,
|
||||
configuration,
|
||||
creator_request_id,
|
||||
deployment_mode,
|
||||
encryption_options,
|
||||
engine_type,
|
||||
engine_version,
|
||||
host_instance_type,
|
||||
ldap_server_metadata,
|
||||
logs,
|
||||
maintenance_window_start_time,
|
||||
publicly_accessible,
|
||||
security_groups,
|
||||
storage_type,
|
||||
subnet_ids,
|
||||
tags,
|
||||
users,
|
||||
):
|
||||
broker = Broker(
|
||||
name=broker_name,
|
||||
region=self.region_name,
|
||||
authentication_strategy=authentication_strategy,
|
||||
auto_minor_version_upgrade=auto_minor_version_upgrade,
|
||||
configuration=configuration,
|
||||
deployment_mode=deployment_mode,
|
||||
encryption_options=encryption_options,
|
||||
engine_type=engine_type,
|
||||
engine_version=engine_version,
|
||||
host_instance_type=host_instance_type,
|
||||
ldap_server_metadata=ldap_server_metadata,
|
||||
logs=logs,
|
||||
maintenance_window_start_time=maintenance_window_start_time,
|
||||
publicly_accessible=publicly_accessible,
|
||||
security_groups=security_groups,
|
||||
storage_type=storage_type,
|
||||
subnet_ids=subnet_ids,
|
||||
users=users,
|
||||
)
|
||||
self.brokers[broker.id] = broker
|
||||
self.create_tags(broker.arn, tags)
|
||||
return broker.arn, broker.id
|
||||
|
||||
def delete_broker(self, broker_id):
|
||||
del self.brokers[broker_id]
|
||||
|
||||
def describe_broker(self, broker_id):
|
||||
if broker_id not in self.brokers:
|
||||
raise UnknownBroker(broker_id)
|
||||
return self.brokers[broker_id]
|
||||
|
||||
def reboot_broker(self, broker_id):
|
||||
self.brokers[broker_id].reboot()
|
||||
|
||||
def list_brokers(self):
|
||||
"""
|
||||
Pagination is not yet implemented
|
||||
"""
|
||||
return self.brokers.values()
|
||||
|
||||
def create_user(self, broker_id, username, console_access, groups):
|
||||
broker = self.describe_broker(broker_id)
|
||||
broker.create_user(username, console_access, groups)
|
||||
|
||||
def update_user(self, broker_id, console_access, groups, username):
|
||||
broker = self.describe_broker(broker_id)
|
||||
broker.update_user(username, console_access, groups)
|
||||
|
||||
def describe_user(self, broker_id, username):
|
||||
broker = self.describe_broker(broker_id)
|
||||
return broker.get_user(username)
|
||||
|
||||
def delete_user(self, broker_id, username):
|
||||
broker = self.describe_broker(broker_id)
|
||||
broker.delete_user(username)
|
||||
|
||||
def list_users(self, broker_id):
|
||||
broker = self.describe_broker(broker_id)
|
||||
return broker.list_users()
|
||||
|
||||
def create_configuration(self, name, engine_type, engine_version, tags):
|
||||
if engine_type.upper() == "RABBITMQ":
|
||||
raise UnsupportedEngineType(engine_type)
|
||||
if engine_type.upper() != "ACTIVEMQ":
|
||||
raise UnknownEngineType(engine_type)
|
||||
config = Configuration(
|
||||
region=self.region_name,
|
||||
name=name,
|
||||
engine_type=engine_type,
|
||||
engine_version=engine_version,
|
||||
)
|
||||
self.configs[config.id] = config
|
||||
self.tagger.tag_resource(
|
||||
config.arn, self.tagger.convert_dict_to_tags_input(tags)
|
||||
)
|
||||
return config
|
||||
|
||||
def update_configuration(self, config_id, data, description):
|
||||
"""
|
||||
No validation occurs on the provided XML. The authenticationStrategy may be changed depending on the provided configuration.
|
||||
"""
|
||||
config = self.configs[config_id]
|
||||
config.update(data, description)
|
||||
return config
|
||||
|
||||
def describe_configuration(self, config_id):
|
||||
if config_id not in self.configs:
|
||||
raise UnknownConfiguration(config_id)
|
||||
return self.configs[config_id]
|
||||
|
||||
def describe_configuration_revision(self, config_id, revision_id):
|
||||
config = self.configs[config_id]
|
||||
return config.get_revision(revision_id)
|
||||
|
||||
def list_configurations(self):
|
||||
"""
|
||||
Pagination has not yet been implemented.
|
||||
"""
|
||||
return self.configs.values()
|
||||
|
||||
def create_tags(self, resource_arn, tags):
|
||||
self.tagger.tag_resource(
|
||||
resource_arn, self.tagger.convert_dict_to_tags_input(tags)
|
||||
)
|
||||
|
||||
def list_tags(self, arn):
|
||||
return self.tagger.get_tag_dict_for_resource(arn)
|
||||
|
||||
def delete_tags(self, resource_arn, tag_keys):
|
||||
if not isinstance(tag_keys, list):
|
||||
tag_keys = [tag_keys]
|
||||
self.tagger.untag_resource_using_names(resource_arn, tag_keys)
|
||||
|
||||
def update_broker(
|
||||
self,
|
||||
authentication_strategy,
|
||||
auto_minor_version_upgrade,
|
||||
broker_id,
|
||||
configuration,
|
||||
engine_version,
|
||||
host_instance_type,
|
||||
ldap_server_metadata,
|
||||
logs,
|
||||
maintenance_window_start_time,
|
||||
security_groups,
|
||||
):
|
||||
broker = self.describe_broker(broker_id)
|
||||
broker.update(
|
||||
authentication_strategy=authentication_strategy,
|
||||
auto_minor_version_upgrade=auto_minor_version_upgrade,
|
||||
configuration=configuration,
|
||||
engine_version=engine_version,
|
||||
host_instance_type=host_instance_type,
|
||||
ldap_server_metadata=ldap_server_metadata,
|
||||
logs=logs,
|
||||
maintenance_window_start_time=maintenance_window_start_time,
|
||||
security_groups=security_groups,
|
||||
)
|
||||
|
||||
|
||||
mq_backends = BackendDict(MQBackend, "mq")
|
281
moto/mq/responses.py
Normal file
281
moto/mq/responses.py
Normal file
@ -0,0 +1,281 @@
|
||||
"""Handles incoming mq requests, invokes methods, returns responses."""
|
||||
import json
|
||||
from functools import wraps
|
||||
from urllib.parse import unquote
|
||||
|
||||
from moto.core.responses import BaseResponse
|
||||
from .exceptions import MQError
|
||||
from .models import mq_backends
|
||||
|
||||
|
||||
def error_handler(f):
|
||||
@wraps(f)
|
||||
def _wrapper(*args, **kwargs):
|
||||
try:
|
||||
return f(*args, **kwargs)
|
||||
except MQError as e:
|
||||
return e.code, e.get_headers(), e.get_body()
|
||||
|
||||
return _wrapper
|
||||
|
||||
|
||||
class MQResponse(BaseResponse):
|
||||
"""Handler for MQ requests and responses."""
|
||||
|
||||
@property
|
||||
def mq_backend(self):
|
||||
"""Return backend instance specific for this region."""
|
||||
return mq_backends[self.region]
|
||||
|
||||
@error_handler
|
||||
def broker(self, request, full_url, headers):
|
||||
self.setup_class(request, full_url, headers)
|
||||
if request.method == "GET":
|
||||
return self.describe_broker()
|
||||
if request.method == "DELETE":
|
||||
return self.delete_broker()
|
||||
if request.method == "PUT":
|
||||
return self.update_broker()
|
||||
|
||||
def brokers(self, request, full_url, headers):
|
||||
self.setup_class(request, full_url, headers)
|
||||
if request.method == "POST":
|
||||
return self.create_broker()
|
||||
if request.method == "GET":
|
||||
return self.list_brokers()
|
||||
|
||||
@error_handler
|
||||
def configuration(self, request, full_url, headers):
|
||||
self.setup_class(request, full_url, headers)
|
||||
if request.method == "GET":
|
||||
return self.describe_configuration()
|
||||
if request.method == "PUT":
|
||||
return self.update_configuration()
|
||||
|
||||
@error_handler
|
||||
def configurations(self, request, full_url, headers):
|
||||
self.setup_class(request, full_url, headers)
|
||||
if request.method == "POST":
|
||||
return self.create_configuration()
|
||||
if request.method == "GET":
|
||||
return self.list_configurations()
|
||||
|
||||
def configuration_revision(self, request, full_url, headers):
|
||||
self.setup_class(request, full_url, headers)
|
||||
if request.method == "GET":
|
||||
return self.get_configuration_revision()
|
||||
|
||||
def tags(self, request, full_url, headers):
|
||||
self.setup_class(request, full_url, headers)
|
||||
if request.method == "POST":
|
||||
return self.create_tags()
|
||||
if request.method == "DELETE":
|
||||
return self.delete_tags()
|
||||
|
||||
@error_handler
|
||||
def user(self, request, full_url, headers):
|
||||
self.setup_class(request, full_url, headers)
|
||||
if request.method == "POST":
|
||||
return self.create_user()
|
||||
if request.method == "GET":
|
||||
return self.describe_user()
|
||||
if request.method == "PUT":
|
||||
return self.update_user()
|
||||
if request.method == "DELETE":
|
||||
return self.delete_user()
|
||||
|
||||
def users(self, request, full_url, headers):
|
||||
self.setup_class(request, full_url, headers)
|
||||
if request.method == "GET":
|
||||
return self.list_users()
|
||||
|
||||
def create_broker(self):
|
||||
params = json.loads(self.body)
|
||||
authentication_strategy = params.get("authenticationStrategy")
|
||||
auto_minor_version_upgrade = params.get("autoMinorVersionUpgrade")
|
||||
broker_name = params.get("brokerName")
|
||||
configuration = params.get("configuration")
|
||||
creator_request_id = params.get("creatorRequestId")
|
||||
deployment_mode = params.get("deploymentMode")
|
||||
encryption_options = params.get("encryptionOptions")
|
||||
engine_type = params.get("engineType")
|
||||
engine_version = params.get("engineVersion")
|
||||
host_instance_type = params.get("hostInstanceType")
|
||||
ldap_server_metadata = params.get("ldapServerMetadata")
|
||||
logs = params.get("logs", {})
|
||||
maintenance_window_start_time = params.get("maintenanceWindowStartTime")
|
||||
publicly_accessible = params.get("publiclyAccessible")
|
||||
security_groups = params.get("securityGroups")
|
||||
storage_type = params.get("storageType")
|
||||
subnet_ids = params.get("subnetIds", [])
|
||||
tags = params.get("tags")
|
||||
users = params.get("users", [])
|
||||
broker_arn, broker_id = self.mq_backend.create_broker(
|
||||
authentication_strategy=authentication_strategy,
|
||||
auto_minor_version_upgrade=auto_minor_version_upgrade,
|
||||
broker_name=broker_name,
|
||||
configuration=configuration,
|
||||
creator_request_id=creator_request_id,
|
||||
deployment_mode=deployment_mode,
|
||||
encryption_options=encryption_options,
|
||||
engine_type=engine_type,
|
||||
engine_version=engine_version,
|
||||
host_instance_type=host_instance_type,
|
||||
ldap_server_metadata=ldap_server_metadata,
|
||||
logs=logs,
|
||||
maintenance_window_start_time=maintenance_window_start_time,
|
||||
publicly_accessible=publicly_accessible,
|
||||
security_groups=security_groups,
|
||||
storage_type=storage_type,
|
||||
subnet_ids=subnet_ids,
|
||||
tags=tags,
|
||||
users=users,
|
||||
)
|
||||
# Lowercase members - boto3 will convert it into UpperCase
|
||||
resp = {"brokerArn": broker_arn, "brokerId": broker_id}
|
||||
return 200, {}, json.dumps(resp)
|
||||
|
||||
def update_broker(self):
|
||||
params = json.loads(self.body)
|
||||
broker_id = self.path.split("/")[-1]
|
||||
authentication_strategy = params.get("authenticationStrategy")
|
||||
auto_minor_version_upgrade = params.get("autoMinorVersionUpgrade")
|
||||
configuration = params.get("configuration")
|
||||
engine_version = params.get("engineVersion")
|
||||
host_instance_type = params.get("hostInstanceType")
|
||||
ldap_server_metadata = params.get("ldapServerMetadata")
|
||||
logs = params.get("logs")
|
||||
maintenance_window_start_time = params.get("maintenanceWindowStartTime")
|
||||
security_groups = params.get("securityGroups")
|
||||
self.mq_backend.update_broker(
|
||||
authentication_strategy=authentication_strategy,
|
||||
auto_minor_version_upgrade=auto_minor_version_upgrade,
|
||||
broker_id=broker_id,
|
||||
configuration=configuration,
|
||||
engine_version=engine_version,
|
||||
host_instance_type=host_instance_type,
|
||||
ldap_server_metadata=ldap_server_metadata,
|
||||
logs=logs,
|
||||
maintenance_window_start_time=maintenance_window_start_time,
|
||||
security_groups=security_groups,
|
||||
)
|
||||
return self.describe_broker()
|
||||
|
||||
def delete_broker(self):
|
||||
broker_id = self.path.split("/")[-1]
|
||||
self.mq_backend.delete_broker(broker_id=broker_id)
|
||||
return 200, {}, json.dumps(dict(brokerId=broker_id))
|
||||
|
||||
def describe_broker(self):
|
||||
broker_id = self.path.split("/")[-1]
|
||||
broker = self.mq_backend.describe_broker(broker_id=broker_id)
|
||||
resp = broker.to_json()
|
||||
resp["tags"] = self.mq_backend.list_tags(broker.arn)
|
||||
return 200, {}, json.dumps(resp)
|
||||
|
||||
def list_brokers(self):
|
||||
brokers = self.mq_backend.list_brokers()
|
||||
return 200, {}, json.dumps(dict(brokerSummaries=[b.summary() for b in brokers]))
|
||||
|
||||
def create_user(self):
|
||||
params = json.loads(self.body)
|
||||
broker_id = self.path.split("/")[-3]
|
||||
username = self.path.split("/")[-1]
|
||||
console_access = params.get("consoleAccess", False)
|
||||
groups = params.get("groups", [])
|
||||
self.mq_backend.create_user(broker_id, username, console_access, groups)
|
||||
return 200, {}, "{}"
|
||||
|
||||
def update_user(self):
|
||||
params = json.loads(self.body)
|
||||
broker_id = self.path.split("/")[-3]
|
||||
username = self.path.split("/")[-1]
|
||||
console_access = params.get("consoleAccess", False)
|
||||
groups = params.get("groups", [])
|
||||
self.mq_backend.update_user(
|
||||
broker_id=broker_id,
|
||||
console_access=console_access,
|
||||
groups=groups,
|
||||
username=username,
|
||||
)
|
||||
return 200, {}, "{}"
|
||||
|
||||
def describe_user(self):
|
||||
broker_id = self.path.split("/")[-3]
|
||||
username = self.path.split("/")[-1]
|
||||
user = self.mq_backend.describe_user(broker_id, username)
|
||||
return 200, {}, json.dumps(user.to_json())
|
||||
|
||||
def delete_user(self):
|
||||
broker_id = self.path.split("/")[-3]
|
||||
username = self.path.split("/")[-1]
|
||||
self.mq_backend.delete_user(broker_id, username)
|
||||
return 200, {}, "{}"
|
||||
|
||||
def list_users(self):
|
||||
broker_id = self.path.split("/")[-2]
|
||||
users = self.mq_backend.list_users(broker_id=broker_id)
|
||||
resp = {
|
||||
"brokerId": broker_id,
|
||||
"users": [{"username": u.username} for u in users],
|
||||
}
|
||||
return 200, {}, json.dumps(resp)
|
||||
|
||||
def create_configuration(self):
|
||||
params = json.loads(self.body)
|
||||
name = params.get("name")
|
||||
engine_type = params.get("engineType")
|
||||
engine_version = params.get("engineVersion")
|
||||
tags = params.get("tags", {})
|
||||
|
||||
config = self.mq_backend.create_configuration(
|
||||
name, engine_type, engine_version, tags
|
||||
)
|
||||
return 200, {}, json.dumps(config.to_json())
|
||||
|
||||
def describe_configuration(self):
|
||||
config_id = self.path.split("/")[-1]
|
||||
config = self.mq_backend.describe_configuration(config_id)
|
||||
resp = config.to_json()
|
||||
resp["tags"] = self.mq_backend.list_tags(config.arn)
|
||||
return 200, {}, json.dumps(resp)
|
||||
|
||||
def list_configurations(self):
|
||||
configs = self.mq_backend.list_configurations()
|
||||
resp = {"configurations": [c.to_json() for c in configs]}
|
||||
return 200, {}, json.dumps(resp)
|
||||
|
||||
def update_configuration(self):
|
||||
config_id = self.path.split("/")[-1]
|
||||
params = json.loads(self.body)
|
||||
data = params.get("data")
|
||||
description = params.get("description")
|
||||
config = self.mq_backend.update_configuration(config_id, data, description)
|
||||
return 200, {}, json.dumps(config.to_json())
|
||||
|
||||
def get_configuration_revision(self):
|
||||
revision_id = self.path.split("/")[-1]
|
||||
config_id = self.path.split("/")[-3]
|
||||
revision = self.mq_backend.describe_configuration_revision(
|
||||
config_id, revision_id
|
||||
)
|
||||
return 200, {}, json.dumps(revision.to_json())
|
||||
|
||||
def create_tags(self):
|
||||
resource_arn = unquote(self.path.split("/")[-1])
|
||||
tags = json.loads(self.body).get("tags", {})
|
||||
self.mq_backend.create_tags(resource_arn, tags)
|
||||
return 200, {}, "{}"
|
||||
|
||||
def delete_tags(self):
|
||||
resource_arn = unquote(self.path.split("/")[-1])
|
||||
tag_keys = self._get_param("tagKeys")
|
||||
self.mq_backend.delete_tags(resource_arn, tag_keys)
|
||||
return 200, {}, "{}"
|
||||
|
||||
def reboot(self, request, full_url, headers):
|
||||
self.setup_class(request, full_url, headers)
|
||||
if request.method == "POST":
|
||||
broker_id = self.path.split("/")[-2]
|
||||
self.mq_backend.reboot_broker(broker_id=broker_id)
|
||||
return 200, {}, "{}"
|
22
moto/mq/urls.py
Normal file
22
moto/mq/urls.py
Normal file
@ -0,0 +1,22 @@
|
||||
"""mq base URL and path."""
|
||||
from .responses import MQResponse
|
||||
|
||||
url_bases = [
|
||||
r"https?://mq\.(.+)\.amazonaws\.com",
|
||||
]
|
||||
|
||||
|
||||
response = MQResponse()
|
||||
|
||||
|
||||
url_paths = {
|
||||
"{0}/v1/brokers/(?P<broker_id>[^/]+)$": response.broker,
|
||||
"{0}/v1/brokers/(?P<broker_id>[^/]+)/reboot$": response.reboot,
|
||||
"{0}/v1/brokers/(?P<broker_id>[^/]+)/users$": response.users,
|
||||
"{0}/v1/brokers/(?P<broker_id>[^/]+)/users/(?P<user_name>[^/]+)$": response.user,
|
||||
"{0}/v1/brokers$": response.brokers,
|
||||
"{0}/v1/configurations$": response.configurations,
|
||||
"{0}/v1/configurations/(?P<config_id>[^/]+)$": response.configuration,
|
||||
"{0}/v1/configurations/(?P<config_id>[^/]+)/revisions/(?P<revision_id>[^/]+)$": response.configuration_revision,
|
||||
"{0}/v1/tags/(?P<resource_arn>[^/]+)$": response.tags,
|
||||
}
|
@ -68,6 +68,7 @@ TestAccAWSIAMUserPolicy
|
||||
TestAccAWSIPRanges
|
||||
TestAccAWSKmsAlias
|
||||
TestAccAWSKmsSecretDataSource
|
||||
TestAccAWSMq
|
||||
TestAccAWSPartition
|
||||
TestAccAWSProvider
|
||||
TestAccAWSRedshiftServiceAccount
|
||||
|
0
tests/test_mq/__init__.py
Normal file
0
tests/test_mq/__init__.py
Normal file
427
tests/test_mq/test_mq.py
Normal file
427
tests/test_mq/test_mq.py
Normal file
@ -0,0 +1,427 @@
|
||||
import boto3
|
||||
import pytest
|
||||
import sure # noqa # pylint: disable=unused-import
|
||||
|
||||
from botocore.exceptions import ClientError
|
||||
from moto import mock_mq
|
||||
|
||||
# See our Development Tips on writing tests for hints on how to write good tests:
|
||||
# http://docs.getmoto.org/en/latest/docs/contributing/development_tips/tests.html
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_create_broker_minimal():
|
||||
client = boto3.client("mq", region_name="ap-southeast-1")
|
||||
resp = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="dm",
|
||||
EngineType="ACTIVEMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Users=[{"Username": "admin", "Password": "adm1n"}],
|
||||
)
|
||||
|
||||
resp.should.have.key("BrokerId")
|
||||
resp.should.have.key("BrokerArn").match("arn:aws")
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_create_with_tags():
|
||||
client = boto3.client("mq", region_name="us-east-2")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="CLUSTER_MULTI_AZ",
|
||||
EngineType="RabbitMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Tags={"key1": "val2", "key2": "val2"},
|
||||
Users=[],
|
||||
)["BrokerId"]
|
||||
|
||||
resp = client.describe_broker(BrokerId=broker_id)
|
||||
|
||||
resp.should.have.key("Tags").equals({"key1": "val2", "key2": "val2"})
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_create_with_multiple_users():
|
||||
client = boto3.client("mq", region_name="us-east-2")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="CLUSTER_MULTI_AZ",
|
||||
EngineType="RabbitMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Users=[
|
||||
{
|
||||
"ConsoleAccess": True,
|
||||
"Groups": ["second", "first", "third"],
|
||||
"Password": "SecondTestTest1234",
|
||||
"Username": "SecondTest",
|
||||
},
|
||||
{
|
||||
"ConsoleAccess": False,
|
||||
"Groups": [],
|
||||
"Password": "TestTest1234",
|
||||
"Username": "Test",
|
||||
},
|
||||
],
|
||||
)["BrokerId"]
|
||||
|
||||
user1 = client.describe_user(BrokerId=broker_id, Username="SecondTest")
|
||||
user1.should.have.key("Username").equals("SecondTest")
|
||||
user1.should.have.key("Groups").equals(["second", "first", "third"])
|
||||
user1.should.have.key("ConsoleAccess").equals(True)
|
||||
|
||||
user2 = client.describe_user(BrokerId=broker_id, Username="Test")
|
||||
user2.should.have.key("Username").equals("Test")
|
||||
user2.should.have.key("Groups").equals([])
|
||||
user2.should.have.key("ConsoleAccess").equals(False)
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_create_with_configuration():
|
||||
client = boto3.client("mq", region_name="us-east-2")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
Configuration={"Id": "config_id_x", "Revision": 3},
|
||||
DeploymentMode="CLUSTER_SINGLE",
|
||||
EngineType="ActiveMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Tags={"key1": "val2", "key2": "val2"},
|
||||
Users=[],
|
||||
)["BrokerId"]
|
||||
|
||||
resp = client.describe_broker(BrokerId=broker_id)
|
||||
|
||||
resp.should.have.key("Configurations")
|
||||
resp["Configurations"].should.have.key("Current").equals(
|
||||
{"Id": "config_id_x", "Revision": 3}
|
||||
)
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_update_with_configuration():
|
||||
client = boto3.client("mq", region_name="us-east-2")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
Configuration={"Id": "config_id_x", "Revision": 1},
|
||||
DeploymentMode="CLUSTER_SINGLE",
|
||||
EngineType="ActiveMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Tags={"key1": "val2", "key2": "val2"},
|
||||
Users=[],
|
||||
)["BrokerId"]
|
||||
|
||||
client.update_broker(
|
||||
BrokerId=broker_id, Configuration={"Id": "config_id_x", "Revision": 2}
|
||||
)
|
||||
|
||||
resp = client.describe_broker(BrokerId=broker_id)
|
||||
|
||||
resp.should.have.key("Configurations")
|
||||
resp["Configurations"].should.have.key("Current").equals(
|
||||
{"Id": "config_id_x", "Revision": 2}
|
||||
)
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_delete_broker():
|
||||
client = boto3.client("mq", region_name="ap-southeast-1")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="dm",
|
||||
EngineType="ACTIVEMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Users=[{"Username": "admin", "Password": "adm1n"}],
|
||||
)["BrokerId"]
|
||||
|
||||
resp = client.delete_broker(BrokerId=broker_id)
|
||||
resp.should.have.key("BrokerId").equals(broker_id)
|
||||
|
||||
client.list_brokers().should.have.key("BrokerSummaries").length_of(0)
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_describe_broker():
|
||||
client = boto3.client("mq", region_name="us-east-2")
|
||||
broker_id = client.create_broker(
|
||||
AuthenticationStrategy="SIMPLE",
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="dm",
|
||||
EncryptionOptions={"KmsKeyId": "kms-key", "UseAwsOwnedKey": False},
|
||||
EngineType="ACTIVEMQ",
|
||||
EngineVersion="version",
|
||||
LdapServerMetadata={
|
||||
"Hosts": ["host1"],
|
||||
"RoleBase": "role_base_thingy",
|
||||
"RoleSearchMatching": "rsm",
|
||||
"ServiceAccountUsername": "sau",
|
||||
"ServiceAccountPassword": "sap",
|
||||
"UserBase": "ub",
|
||||
"UserSearchMatching": "usm",
|
||||
},
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
SecurityGroups=["secgroup1"],
|
||||
StorageType="efs",
|
||||
SubnetIds=["s-id"],
|
||||
Users=[{"Username": "admin", "Password": "adm1n"}],
|
||||
)["BrokerId"]
|
||||
|
||||
resp = client.describe_broker(BrokerId=broker_id)
|
||||
|
||||
resp.should.have.key("BrokerId").equals(broker_id)
|
||||
resp.should.have.key("BrokerArn").match("arn:aws")
|
||||
resp.should.have.key("BrokerState").equals("RUNNING")
|
||||
|
||||
resp.should.have.key("Created")
|
||||
|
||||
resp.should.have.key("AuthenticationStrategy").equals("SIMPLE")
|
||||
resp.should.have.key("AutoMinorVersionUpgrade").equals(False)
|
||||
resp.should.have.key("BrokerName").equals("testbroker")
|
||||
resp.should.have.key("DeploymentMode").equals("dm")
|
||||
resp.should.have.key("EncryptionOptions").equals(
|
||||
{"KmsKeyId": "kms-key", "UseAwsOwnedKey": False}
|
||||
)
|
||||
resp.should.have.key("EngineType").equals("ACTIVEMQ")
|
||||
resp.should.have.key("EngineVersion").equals("version")
|
||||
resp.should.have.key("HostInstanceType").equals("hit")
|
||||
resp.should.have.key("LdapServerMetadata").equals(
|
||||
{
|
||||
"Hosts": ["host1"],
|
||||
"RoleBase": "role_base_thingy",
|
||||
"RoleSearchMatching": "rsm",
|
||||
"ServiceAccountUsername": "sau",
|
||||
"UserBase": "ub",
|
||||
"UserSearchMatching": "usm",
|
||||
}
|
||||
)
|
||||
resp.should.have.key("PubliclyAccessible").equals(True)
|
||||
resp.should.have.key("SecurityGroups").equals(["secgroup1"])
|
||||
resp.should.have.key("StorageType").equals("efs")
|
||||
resp.should.have.key("SubnetIds").equals(["s-id"])
|
||||
resp.should.have.key("Users").equals([{"Username": "admin"}])
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_describe_broker_with_defaults():
|
||||
client = boto3.client("mq", region_name="us-east-2")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="dm",
|
||||
EngineType="ACTIVEMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Users=[],
|
||||
)["BrokerId"]
|
||||
|
||||
resp = client.describe_broker(BrokerId=broker_id)
|
||||
|
||||
resp.should.have.key("BrokerInstances").length_of(1)
|
||||
|
||||
resp.should.have.key("Configurations")
|
||||
resp["Configurations"].should.have.key("Current")
|
||||
resp["Configurations"].should.have.key("History").length_of(0)
|
||||
resp["Configurations"].shouldnt.have.key("Pending")
|
||||
|
||||
resp.should.have.key("EncryptionOptions").equals({"UseAwsOwnedKey": True})
|
||||
|
||||
resp.should.have.key("MaintenanceWindowStartTime").equals(
|
||||
{"DayOfWeek": "Sunday", "TimeOfDay": "00:00", "TimeZone": "UTC"}
|
||||
)
|
||||
|
||||
resp.should.have.key("Logs").equals({"Audit": False, "General": False})
|
||||
|
||||
resp.should.have.key("SubnetIds").length_of(1)
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_describe_multiple_rabbits():
|
||||
client = boto3.client("mq", region_name="us-east-2")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="CLUSTER_MULTI_AZ",
|
||||
EngineType="RabbitMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Users=[],
|
||||
)["BrokerId"]
|
||||
|
||||
resp = client.describe_broker(BrokerId=broker_id)
|
||||
|
||||
resp.should.have.key("BrokerInstances")
|
||||
resp["BrokerInstances"][0]["ConsoleURL"].should.equal(
|
||||
"https://0000.mq.us-east-2.amazonaws.com"
|
||||
)
|
||||
resp["BrokerInstances"][0]["Endpoints"].should.have.length_of(1)
|
||||
resp.shouldnt.have.key("Configurations")
|
||||
resp.should.have.key("Logs").equals({"General": False})
|
||||
resp.should.have.key("SubnetIds").length_of(4)
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_describe_active_mq_with_standby():
|
||||
client = boto3.client("mq", region_name="us-east-2")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="ACTIVE_STANDBY_MULTI_AZ",
|
||||
EngineType="ActiveMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Users=[],
|
||||
)["BrokerId"]
|
||||
|
||||
resp = client.describe_broker(BrokerId=broker_id)
|
||||
|
||||
# Instances and subnets in two regions - one active, one standby
|
||||
resp.should.have.key("BrokerInstances").length_of(2)
|
||||
resp.should.have.key("SubnetIds").length_of(2)
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_describe_broker_unknown():
|
||||
client = boto3.client("mq", region_name="us-east-2")
|
||||
|
||||
with pytest.raises(ClientError) as exc:
|
||||
client.describe_broker(BrokerId="unknown")
|
||||
err = exc.value.response["Error"]
|
||||
err["Code"].should.equal("NotFoundException")
|
||||
err["Message"].should.equal(
|
||||
"Can't find requested broker [unknown]. Make sure your broker exists."
|
||||
)
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_list_brokers_empty():
|
||||
client = boto3.client("mq", region_name="eu-west-1")
|
||||
resp = client.list_brokers()
|
||||
|
||||
resp.should.have.key("BrokerSummaries").equals([])
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_list_brokers():
|
||||
client = boto3.client("mq", region_name="eu-west-1")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="dm",
|
||||
EngineType="ACTIVEMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Users=[{"Username": "admin", "Password": "adm1n"}],
|
||||
)["BrokerId"]
|
||||
|
||||
resp = client.list_brokers()
|
||||
|
||||
resp.should.have.key("BrokerSummaries").length_of(1)
|
||||
|
||||
summary = resp["BrokerSummaries"][0]
|
||||
summary.should.have.key("BrokerArn")
|
||||
summary.should.have.key("BrokerId").equals(broker_id)
|
||||
summary.should.have.key("BrokerName").equals("testbroker")
|
||||
summary.should.have.key("BrokerState").equals("RUNNING")
|
||||
summary.should.have.key("Created")
|
||||
summary.should.have.key("DeploymentMode").equals("dm")
|
||||
summary.should.have.key("EngineType").equals("ACTIVEMQ")
|
||||
summary.should.have.key("HostInstanceType").equals("hit")
|
||||
|
||||
summary.shouldnt.have.key("Users")
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_update_broker_single_attribute():
|
||||
client = boto3.client("mq", region_name="ap-southeast-1")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="dm",
|
||||
EngineType="ACTIVEMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Users=[{"Username": "admin", "Password": "adm1n"}],
|
||||
)["BrokerId"]
|
||||
resp = client.update_broker(AutoMinorVersionUpgrade=True, BrokerId=broker_id)
|
||||
|
||||
# Changed
|
||||
resp.should.have.key("AutoMinorVersionUpgrade").equals(True)
|
||||
|
||||
# Unchanged
|
||||
resp.should.have.key("BrokerId").equals(broker_id)
|
||||
resp.should.have.key("EngineVersion").equals("version")
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_update_broker_multiple_attributes():
|
||||
client = boto3.client("mq", region_name="ap-southeast-1")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="dm",
|
||||
EngineType="ACTIVEMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
SecurityGroups=["sg-1"],
|
||||
Users=[{"Username": "admin", "Password": "adm1n"}],
|
||||
)["BrokerId"]
|
||||
resp = client.update_broker(
|
||||
AutoMinorVersionUpgrade=True,
|
||||
BrokerId=broker_id,
|
||||
Logs={"Audit": True, "General": True},
|
||||
EngineVersion="version2",
|
||||
SecurityGroups=["sg-1", "sg-2"],
|
||||
)
|
||||
|
||||
# Changed
|
||||
resp.should.have.key("AutoMinorVersionUpgrade").equals(True)
|
||||
resp.should.have.key("Logs").equals({"Audit": True, "General": True})
|
||||
resp.should.have.key("EngineVersion").equals("version2")
|
||||
resp.should.have.key("SecurityGroups").equals(["sg-1", "sg-2"])
|
||||
|
||||
# Unchanged
|
||||
resp.should.have.key("BrokerId").equals(broker_id)
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_reboot_broker():
|
||||
client = boto3.client("mq", region_name="ap-southeast-1")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="dm",
|
||||
EngineType="ACTIVEMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Users=[{"Username": "admin", "Password": "adm1n"}],
|
||||
)["BrokerId"]
|
||||
client.reboot_broker(BrokerId=broker_id)
|
||||
|
||||
# Noop - nothing to assert or verify
|
||||
pass
|
210
tests/test_mq/test_mq_configuration.py
Normal file
210
tests/test_mq/test_mq_configuration.py
Normal file
@ -0,0 +1,210 @@
|
||||
"""Unit tests for mq-supported APIs."""
|
||||
import base64
|
||||
|
||||
import boto3
|
||||
import pytest
|
||||
import sure # noqa # pylint: disable=unused-import
|
||||
|
||||
from botocore.exceptions import ClientError
|
||||
from moto import mock_mq
|
||||
from moto.core import ACCOUNT_ID
|
||||
|
||||
# See our Development Tips on writing tests for hints on how to write good tests:
|
||||
# http://docs.getmoto.org/en/latest/docs/contributing/development_tips/tests.html
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_create_configuration_minimal():
|
||||
client = boto3.client("mq", region_name="ap-southeast-1")
|
||||
resp = client.create_configuration(
|
||||
EngineType="ACTIVEMQ", EngineVersion="rabbit1", Name="myconfig"
|
||||
)
|
||||
|
||||
resp.should.have.key("Id").match("^c-")
|
||||
resp.should.have.key("Arn").equals(
|
||||
f"arn:aws:mq:ap-southeast-1:{ACCOUNT_ID}:configuration:{resp['Id']}"
|
||||
)
|
||||
resp.should.have.key("AuthenticationStrategy").equals("simple")
|
||||
resp.should.have.key("Created")
|
||||
resp.should.have.key("Name").equals("myconfig")
|
||||
resp.should.have.key("LatestRevision")
|
||||
|
||||
revision = resp["LatestRevision"]
|
||||
revision.should.have.key("Created")
|
||||
revision.should.have.key("Description")
|
||||
revision.should.have.key("Revision").equals(1)
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_create_configuration_for_rabbitmq():
|
||||
client = boto3.client("mq", region_name="us-east-1")
|
||||
|
||||
with pytest.raises(ClientError) as exc:
|
||||
client.create_configuration(
|
||||
EngineType="RABBITMQ", EngineVersion="rabbit1", Name="myconfig"
|
||||
)
|
||||
err = exc.value.response["Error"]
|
||||
err["Code"].should.equal("BadRequestException")
|
||||
err["Message"].should.equal(
|
||||
"Broker engine type [RABBITMQ] does not support configuration."
|
||||
)
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_create_configuration_for_unknown_engine():
|
||||
client = boto3.client("mq", region_name="us-east-1")
|
||||
|
||||
with pytest.raises(ClientError) as exc:
|
||||
client.create_configuration(
|
||||
EngineType="unknown", EngineVersion="rabbit1", Name="myconfig"
|
||||
)
|
||||
err = exc.value.response["Error"]
|
||||
err["Code"].should.equal("BadRequestException")
|
||||
err["Message"].should.equal(
|
||||
"Broker engine type [unknown] is invalid. Valid values are: [ACTIVEMQ]"
|
||||
)
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_describe_configuration():
|
||||
client = boto3.client("mq", region_name="eu-north-1")
|
||||
config_id = client.create_configuration(
|
||||
EngineType="ACTIVEMQ", EngineVersion="active2", Name="myconfig"
|
||||
)["Id"]
|
||||
|
||||
resp = client.describe_configuration(ConfigurationId=config_id)
|
||||
|
||||
resp.should.have.key("Id").match("^c-")
|
||||
resp.should.have.key("Arn").equals(
|
||||
f"arn:aws:mq:eu-north-1:{ACCOUNT_ID}:configuration:{resp['Id']}"
|
||||
)
|
||||
resp.should.have.key("AuthenticationStrategy").equals("simple")
|
||||
resp.should.have.key("Created")
|
||||
resp.should.have.key("Name").equals("myconfig")
|
||||
resp.should.have.key("LatestRevision")
|
||||
|
||||
revision = resp["LatestRevision"]
|
||||
revision.should.have.key("Created")
|
||||
revision.should.have.key("Description")
|
||||
revision.should.have.key("Revision").equals(1)
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_describe_configuration_revision():
|
||||
client = boto3.client("mq", region_name="eu-north-1")
|
||||
config_id = client.create_configuration(
|
||||
EngineType="ActiveMQ", EngineVersion="5.16.3", Name="myconfig"
|
||||
)["Id"]
|
||||
|
||||
resp = client.describe_configuration_revision(
|
||||
ConfigurationId=config_id, ConfigurationRevision="1"
|
||||
)
|
||||
|
||||
resp.should.have.key("ConfigurationId").equals(config_id)
|
||||
resp.should.have.key("Created")
|
||||
resp.should.have.key("Description").equals(
|
||||
"Auto-generated default for myconfig on ActiveMQ 5.16.3"
|
||||
)
|
||||
|
||||
resp.should.have.key("Data")
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_describe_configuration_unknown():
|
||||
client = boto3.client("mq", region_name="us-east-2")
|
||||
|
||||
with pytest.raises(ClientError) as exc:
|
||||
client.describe_configuration(ConfigurationId="c-unknown")
|
||||
err = exc.value.response["Error"]
|
||||
|
||||
err["Code"].should.equal("NotFoundException")
|
||||
err["Message"].should.equal(
|
||||
"Can't find requested configuration [c-unknown]. Make sure your configuration exists."
|
||||
)
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_list_configurations_empty():
|
||||
client = boto3.client("mq", region_name="us-east-2")
|
||||
|
||||
resp = client.list_configurations()
|
||||
|
||||
resp.should.have.key("Configurations").equals([])
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_list_configurations():
|
||||
client = boto3.client("mq", region_name="ap-southeast-1")
|
||||
config_id = client.create_configuration(
|
||||
EngineType="ACTIVEMQ", EngineVersion="active1", Name="myconfig"
|
||||
)["Id"]
|
||||
|
||||
resp = client.list_configurations()
|
||||
|
||||
resp.should.have.key("Configurations").length_of(1)
|
||||
|
||||
config = resp["Configurations"][0]
|
||||
config.should.have.key("Arn").match("arn:aws")
|
||||
config.should.have.key("Created")
|
||||
config.should.have.key("Id").equals(config_id)
|
||||
config.should.have.key("Name").equals("myconfig")
|
||||
config.should.have.key("EngineType").equals("ACTIVEMQ")
|
||||
config.should.have.key("EngineVersion").equals("active1")
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_update_configuration():
|
||||
client = boto3.client("mq", region_name="ap-southeast-1")
|
||||
config_id = client.create_configuration(
|
||||
EngineType="ACTIVEMQ", EngineVersion="rabbit1", Name="myconfig"
|
||||
)["Id"]
|
||||
|
||||
resp = client.update_configuration(
|
||||
ConfigurationId=config_id,
|
||||
Data="base64encodedxmlconfig",
|
||||
Description="updated config",
|
||||
)
|
||||
|
||||
resp.should.have.key("Arn").match("arn:aws:mq")
|
||||
resp.should.have.key("Created")
|
||||
resp.should.have.key("Id")
|
||||
resp.should.have.key("Name").equals("myconfig")
|
||||
resp.should.have.key("LatestRevision")
|
||||
|
||||
revision = resp["LatestRevision"]
|
||||
revision.should.have.key("Created")
|
||||
revision.should.have.key("Description").equals("updated config")
|
||||
revision.should.have.key("Revision").equals(2)
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_update_configuration_to_ldap():
|
||||
client = boto3.client("mq", region_name="ap-southeast-1")
|
||||
config_id = client.create_configuration(
|
||||
EngineType="ACTIVEMQ", EngineVersion="rabbit1", Name="myconfig"
|
||||
)["Id"]
|
||||
|
||||
ldap_config = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<broker xmlns="http://activemq.apache.org/schema/core">
|
||||
<plugins>
|
||||
<authorizationPlugin>
|
||||
<map>
|
||||
<cachedLDAPAuthorizationMap legacyGroupMapping="false" queueSearchBase="ou=Queue,ou=Destination,ou=ActiveMQ,dc=example,dc=org" refreshInterval="0" tempSearchBase="ou=Temp,ou=Destination,ou=ActiveMQ,dc=example,dc=org" topicSearchBase="ou=Topic,ou=Destination,ou=ActiveMQ,dc=example,dc=org"/>
|
||||
</map>
|
||||
</authorizationPlugin>
|
||||
<forcePersistencyModeBrokerPlugin persistenceFlag="true"/>
|
||||
<statisticsBrokerPlugin/>
|
||||
<timeStampingBrokerPlugin ttlCeiling="86400000" zeroExpirationOverride="86400000"/>
|
||||
</plugins>
|
||||
</broker>
|
||||
"""
|
||||
|
||||
client.update_configuration(
|
||||
ConfigurationId=config_id,
|
||||
Data=base64.b64encode(ldap_config.encode("utf-8")).decode("utf-8"),
|
||||
Description="update config to use LDAP authorization",
|
||||
)
|
||||
|
||||
resp = client.describe_configuration(ConfigurationId=config_id)
|
||||
|
||||
resp.should.have.key("AuthenticationStrategy").equals("ldap")
|
109
tests/test_mq/test_mq_tags.py
Normal file
109
tests/test_mq/test_mq_tags.py
Normal file
@ -0,0 +1,109 @@
|
||||
import boto3
|
||||
import sure # noqa # pylint: disable=unused-import
|
||||
|
||||
from moto import mock_mq
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_create_broker_with_tags():
|
||||
client = boto3.client("mq", region_name="us-east-2")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="CLUSTER_MULTI_AZ",
|
||||
EngineType="RabbitMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Tags={"key1": "val2", "key2": "val2"},
|
||||
Users=[],
|
||||
)["BrokerId"]
|
||||
|
||||
resp = client.describe_broker(BrokerId=broker_id)
|
||||
|
||||
resp.should.have.key("Tags").equals({"key1": "val2", "key2": "val2"})
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_create_tags():
|
||||
client = boto3.client("mq", region_name="us-east-2")
|
||||
resp = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="CLUSTER_MULTI_AZ",
|
||||
EngineType="RabbitMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Users=[],
|
||||
)
|
||||
|
||||
broker_arn = resp["BrokerArn"]
|
||||
broker_id = resp["BrokerId"]
|
||||
|
||||
client.create_tags(ResourceArn=broker_arn, Tags={"key1": "val2", "key2": "val2"})
|
||||
|
||||
resp = client.describe_broker(BrokerId=broker_id)
|
||||
|
||||
resp.should.have.key("Tags").equals({"key1": "val2", "key2": "val2"})
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_delete_tags():
|
||||
client = boto3.client("mq", region_name="us-east-2")
|
||||
resp = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="CLUSTER_MULTI_AZ",
|
||||
EngineType="RabbitMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Users=[],
|
||||
)
|
||||
|
||||
broker_arn = resp["BrokerArn"]
|
||||
broker_id = resp["BrokerId"]
|
||||
|
||||
client.create_tags(ResourceArn=broker_arn, Tags={"key1": "val2", "key2": "val2"})
|
||||
|
||||
client.delete_tags(ResourceArn=broker_arn, TagKeys=["key1"])
|
||||
|
||||
resp = client.describe_broker(BrokerId=broker_id)
|
||||
|
||||
resp.should.have.key("Tags").equals({"key2": "val2"})
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_create_configuration_with_tags():
|
||||
client = boto3.client("mq", region_name="ap-southeast-1")
|
||||
resp = client.create_configuration(
|
||||
EngineType="ACTIVEMQ",
|
||||
EngineVersion="rabbit1",
|
||||
Name="myconfig",
|
||||
Tags={"key1": "val1", "key2": "val2"},
|
||||
)
|
||||
|
||||
# The CreateConfiguration call does not return tags
|
||||
resp.shouldnt.have.key("Tags")
|
||||
|
||||
# Only when describing will they be returned
|
||||
resp = client.describe_configuration(ConfigurationId=resp["Id"])
|
||||
resp.should.have.key("Tags").equals({"key1": "val1", "key2": "val2"})
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_add_tags_to_configuration():
|
||||
client = boto3.client("mq", region_name="ap-southeast-1")
|
||||
resp = client.create_configuration(
|
||||
EngineType="ACTIVEMQ",
|
||||
EngineVersion="rabbit1",
|
||||
Name="myconfig",
|
||||
Tags={"key1": "val1", "key2": "val2"},
|
||||
)
|
||||
|
||||
client.create_tags(ResourceArn=resp["Arn"], Tags={"key1": "val1", "key2": "val2"})
|
||||
|
||||
# Only when describing will they be returned
|
||||
resp = client.describe_configuration(ConfigurationId=resp["Id"])
|
||||
resp.should.have.key("Tags").equals({"key1": "val1", "key2": "val2"})
|
172
tests/test_mq/test_mq_users.py
Normal file
172
tests/test_mq/test_mq_users.py
Normal file
@ -0,0 +1,172 @@
|
||||
import boto3
|
||||
import pytest
|
||||
import sure # noqa # pylint: disable=unused-import
|
||||
|
||||
from botocore.exceptions import ClientError
|
||||
from moto import mock_mq
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_create_user():
|
||||
client = boto3.client("mq", region_name="us-east-1")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="dm",
|
||||
EngineType="ACTIVEMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Users=[],
|
||||
)["BrokerId"]
|
||||
|
||||
client.create_user(BrokerId=broker_id, Username="admin", Password="adm1n")
|
||||
|
||||
resp = client.describe_broker(BrokerId=broker_id)
|
||||
|
||||
resp.should.have.key("Users").equals([{"Username": "admin"}])
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_describe_user():
|
||||
client = boto3.client("mq", region_name="us-east-1")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="dm",
|
||||
EngineType="ACTIVEMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Users=[],
|
||||
)["BrokerId"]
|
||||
|
||||
client.create_user(
|
||||
BrokerId=broker_id,
|
||||
Username="admin",
|
||||
Password="adm1n",
|
||||
ConsoleAccess=True,
|
||||
Groups=["group1", "group2"],
|
||||
)
|
||||
|
||||
resp = client.describe_user(BrokerId=broker_id, Username="admin")
|
||||
|
||||
resp.should.have.key("BrokerId").equals(broker_id)
|
||||
resp.should.have.key("ConsoleAccess").equals(True)
|
||||
resp.should.have.key("Groups").equals(["group1", "group2"])
|
||||
resp.should.have.key("Username").equals("admin")
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_describe_user_unknown():
|
||||
client = boto3.client("mq", region_name="us-east-2")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="dm",
|
||||
EngineType="ACTIVEMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Users=[],
|
||||
)["BrokerId"]
|
||||
|
||||
with pytest.raises(ClientError) as exc:
|
||||
client.describe_user(BrokerId=broker_id, Username="unknown")
|
||||
err = exc.value.response["Error"]
|
||||
err["Code"].should.equal("NotFoundException")
|
||||
err["Message"].should.equal(
|
||||
"Can't find requested user [unknown]. Make sure your user exists."
|
||||
)
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_list_users_empty():
|
||||
client = boto3.client("mq", region_name="us-east-1")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="dm",
|
||||
EngineType="ACTIVEMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Users=[],
|
||||
)["BrokerId"]
|
||||
|
||||
resp = client.list_users(BrokerId=broker_id)
|
||||
|
||||
resp.should.have.key("BrokerId").equals(broker_id)
|
||||
resp.should.have.key("Users").equals([])
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_list_users():
|
||||
client = boto3.client("mq", region_name="us-east-1")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="dm",
|
||||
EngineType="ACTIVEMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Users=[{"Username": "admin", "Password": "adm1n"}],
|
||||
)["BrokerId"]
|
||||
|
||||
client.create_user(BrokerId=broker_id, Username="user1", Password="us3r1")
|
||||
|
||||
resp = client.list_users(BrokerId=broker_id)
|
||||
|
||||
resp.should.have.key("BrokerId").equals(broker_id)
|
||||
resp.should.have.key("Users").length_of(2)
|
||||
resp["Users"].should.contain({"Username": "admin"})
|
||||
resp["Users"].should.contain({"Username": "user1"})
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_update_user():
|
||||
client = boto3.client("mq", region_name="us-east-2")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="dm",
|
||||
EngineType="ACTIVEMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Users=[{"Username": "admin", "Password": "adm1n"}],
|
||||
)["BrokerId"]
|
||||
|
||||
client.update_user(BrokerId=broker_id, Username="admin", Groups=["administrators"])
|
||||
|
||||
resp = client.describe_user(BrokerId=broker_id, Username="admin")
|
||||
|
||||
resp.should.have.key("BrokerId").equals(broker_id)
|
||||
resp.should.have.key("Groups").equals(["administrators"])
|
||||
resp.should.have.key("Username").equals("admin")
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_delete_user():
|
||||
client = boto3.client("mq", region_name="us-east-1")
|
||||
broker_id = client.create_broker(
|
||||
AutoMinorVersionUpgrade=False,
|
||||
BrokerName="testbroker",
|
||||
DeploymentMode="dm",
|
||||
EngineType="ACTIVEMQ",
|
||||
EngineVersion="version",
|
||||
HostInstanceType="hit",
|
||||
PubliclyAccessible=True,
|
||||
Users=[{"Username": "admin", "Password": "adm1n"}],
|
||||
)["BrokerId"]
|
||||
|
||||
client.create_user(BrokerId=broker_id, Username="user1", Password="us3r1")
|
||||
|
||||
client.delete_user(BrokerId=broker_id, Username="admin")
|
||||
|
||||
resp = client.list_users(BrokerId=broker_id)
|
||||
|
||||
resp.should.have.key("BrokerId").equals(broker_id)
|
||||
resp.should.have.key("Users").length_of(1)
|
||||
resp["Users"].should.contain({"Username": "user1"})
|
15
tests/test_mq/test_server.py
Normal file
15
tests/test_mq/test_server.py
Normal file
@ -0,0 +1,15 @@
|
||||
import json
|
||||
import sure # noqa # pylint: disable=unused-import
|
||||
|
||||
from moto import mock_mq
|
||||
import moto.server as server
|
||||
|
||||
|
||||
@mock_mq
|
||||
def test_mq_list():
|
||||
backend = server.create_backend_app("mq")
|
||||
test_client = backend.test_client()
|
||||
|
||||
resp = test_client.get("/v1/brokers")
|
||||
resp.status_code.should.equal(200)
|
||||
json.loads(resp.data).should.equal({"brokerSummaries": []})
|
Loading…
Reference in New Issue
Block a user