diff --git a/IMPLEMENTATION_COVERAGE.md b/IMPLEMENTATION_COVERAGE.md
index 699c85d59..0d95af4cb 100644
--- a/IMPLEMENTATION_COVERAGE.md
+++ b/IMPLEMENTATION_COVERAGE.md
@@ -4294,7 +4294,7 @@
- [X] describe_db_clusters
- [ ] describe_db_engine_versions
- [ ] describe_db_instance_automated_backups
-- [ ] describe_db_instances
+- [X] describe_db_instances
- [ ] describe_db_log_files
- [X] describe_db_parameter_groups
- [ ] describe_db_parameters
diff --git a/docs/docs/services/rds.rst b/docs/docs/services/rds.rst
index dfe0c6166..06d1a4994 100644
--- a/docs/docs/services/rds.rst
+++ b/docs/docs/services/rds.rst
@@ -82,7 +82,7 @@ rds
- [X] describe_db_clusters
- [ ] describe_db_engine_versions
- [ ] describe_db_instance_automated_backups
-- [ ] describe_db_instances
+- [X] describe_db_instances
- [ ] describe_db_log_files
- [X] describe_db_parameter_groups
- [ ] describe_db_parameters
diff --git a/moto/rds/exceptions.py b/moto/rds/exceptions.py
index 20306bb6d..4512df86e 100644
--- a/moto/rds/exceptions.py
+++ b/moto/rds/exceptions.py
@@ -7,14 +7,14 @@ class RDSClientError(BadRequest):
super().__init__()
template = Template(
"""
-
+
{{ code }}
{{ message }}
Sender
6876f774-7273-11e4-85dc-39e55ca848d1
- """
+ """
)
self.description = template.render(code=code, message=message)
diff --git a/moto/rds/models.py b/moto/rds/models.py
index db7409e66..956499834 100644
--- a/moto/rds/models.py
+++ b/moto/rds/models.py
@@ -110,6 +110,9 @@ class Cluster:
random.choice(string.ascii_uppercase + string.digits) for _ in range(26)
)
self.tags = kwargs.get("tags", [])
+ self.enabled_cloudwatch_logs_exports = (
+ kwargs.get("enable_cloudwatch_logs_exports") or []
+ )
@property
def db_cluster_arn(self):
@@ -172,6 +175,11 @@ class Cluster:
{{ cluster.copy_tags_to_snapshot }}
false
+
+ {% for export in cluster.enabled_cloudwatch_logs_exports %}
+ {{ export }}
+ {% endfor %}
+
{%- for tag in cluster.tags -%}
@@ -426,6 +434,9 @@ class Database(CloudFormationModel):
self.dbi_resource_id = "db-M5ENSHXFPU6XHZ4G4ZEI5QIO2U"
self.tags = kwargs.get("tags", [])
self.deletion_protection = kwargs.get("deletion_protection", False)
+ self.enabled_cloudwatch_logs_exports = (
+ kwargs.get("enable_cloudwatch_logs_exports") or []
+ )
@property
def db_instance_arn(self):
@@ -516,6 +527,11 @@ class Database(CloudFormationModel):
{% endif %}
+
+ {% for export in database.enabled_cloudwatch_logs_exports %}
+ {{ export }}
+ {% endfor %}
+
{% if database.is_replica %}
{{ database.source_db_identifier }}
{% endif %}
@@ -1331,7 +1347,7 @@ class RDSBackend(BaseBackend):
primary.add_replica(replica)
return replica
- def describe_databases(self, db_instance_identifier=None, filters=None):
+ def describe_db_instances(self, db_instance_identifier=None, filters=None):
databases = self.databases
if db_instance_identifier:
filters = merge_filters(
@@ -1362,7 +1378,7 @@ class RDSBackend(BaseBackend):
return list(snapshots.values())
def modify_db_instance(self, db_instance_identifier, db_kwargs):
- database = self.describe_databases(db_instance_identifier)[0]
+ database = self.describe_db_instances(db_instance_identifier)[0]
if "new_db_instance_identifier" in db_kwargs:
del self.databases[db_instance_identifier]
db_instance_identifier = db_kwargs[
@@ -1373,7 +1389,7 @@ class RDSBackend(BaseBackend):
return database
def reboot_db_instance(self, db_instance_identifier):
- database = self.describe_databases(db_instance_identifier)[0]
+ database = self.describe_db_instances(db_instance_identifier)[0]
return database
def restore_db_instance_from_db_snapshot(self, from_snapshot_id, overrides):
@@ -1394,7 +1410,7 @@ class RDSBackend(BaseBackend):
return self.create_db_instance(new_instance_props)
def stop_db_instance(self, db_instance_identifier, db_snapshot_identifier=None):
- database = self.describe_databases(db_instance_identifier)[0]
+ database = self.describe_db_instances(db_instance_identifier)[0]
# todo: certain rds types not allowed to be stopped at this time.
# https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_StopInstance.html#USER_StopInstance.Limitations
if database.is_replica or (
@@ -1410,7 +1426,7 @@ class RDSBackend(BaseBackend):
return database
def start_db_instance(self, db_instance_identifier):
- database = self.describe_databases(db_instance_identifier)[0]
+ database = self.describe_db_instances(db_instance_identifier)[0]
# todo: bunch of different error messages to be generated from this api call
if database.status != "stopped":
raise InvalidDBInstanceStateError(db_instance_identifier, "start")
@@ -1427,7 +1443,7 @@ class RDSBackend(BaseBackend):
backend = self
db_name = db_id
- return backend.describe_databases(db_name)[0]
+ return backend.describe_db_instances(db_name)[0]
def delete_db_instance(self, db_instance_identifier, db_snapshot_name=None):
if db_instance_identifier in self.databases:
diff --git a/moto/rds/responses.py b/moto/rds/responses.py
index c2b7b9bac..77f01bb51 100644
--- a/moto/rds/responses.py
+++ b/moto/rds/responses.py
@@ -27,6 +27,9 @@ class RDSResponse(BaseResponse):
"db_subnet_group_name": self._get_param("DBSubnetGroupName"),
"engine": self._get_param("Engine"),
"engine_version": self._get_param("EngineVersion"),
+ "enable_cloudwatch_logs_exports": self._get_params().get(
+ "EnableCloudwatchLogsExports"
+ ),
"enable_iam_database_authentication": self._get_bool_param(
"EnableIAMDatabaseAuthentication"
),
@@ -92,6 +95,9 @@ class RDSResponse(BaseResponse):
"availability_zones": self._get_multi_param(
"AvailabilityZones.AvailabilityZone"
),
+ "enable_cloudwatch_logs_exports": self._get_params().get(
+ "EnableCloudwatchLogsExports"
+ ),
"db_name": self._get_param("DatabaseName"),
"db_cluster_identifier": self._get_param("DBClusterIdentifier"),
"deletion_protection": self._get_bool_param("DeletionProtection"),
@@ -174,7 +180,7 @@ class RDSResponse(BaseResponse):
filters = self._get_multi_param("Filters.Filter.")
filters = {f["Name"]: f["Values"] for f in filters}
all_instances = list(
- self.backend.describe_databases(db_instance_identifier, filters=filters)
+ self.backend.describe_db_instances(db_instance_identifier, filters=filters)
)
marker = self._get_param("Marker")
all_ids = [instance.db_instance_identifier for instance in all_instances]
diff --git a/tests/test_rds/test_rds.py b/tests/test_rds/test_rds.py
index 13df7ff38..522af30dd 100644
--- a/tests/test_rds/test_rds.py
+++ b/tests/test_rds/test_rds.py
@@ -21,6 +21,7 @@ def test_create_database():
Port=1234,
DBSecurityGroups=["my_sg"],
VpcSecurityGroupIds=["sg-123456"],
+ EnableCloudwatchLogsExports=["audit", "error"],
)
db_instance = database["DBInstance"]
db_instance["AllocatedStorage"].should.equal(10)
@@ -40,6 +41,7 @@ def test_create_database():
db_instance["InstanceCreateTime"].should.be.a("datetime.datetime")
db_instance["VpcSecurityGroups"][0]["VpcSecurityGroupId"].should.equal("sg-123456")
db_instance["DeletionProtection"].should.equal(False)
+ db_instance["EnabledCloudwatchLogsExports"].should.equal(["audit", "error"])
@mock_rds
diff --git a/tests/test_rds/test_rds_clusters.py b/tests/test_rds/test_rds_clusters.py
index 9e6fd2c11..e9614c745 100644
--- a/tests/test_rds/test_rds_clusters.py
+++ b/tests/test_rds/test_rds_clusters.py
@@ -157,6 +157,7 @@ def test_create_db_cluster_additional_parameters():
MasterUserPassword="hunter2_",
Port=1234,
DeletionProtection=True,
+ EnableCloudwatchLogsExports=["audit"],
)
cluster = resp["DBCluster"]
@@ -167,6 +168,7 @@ def test_create_db_cluster_additional_parameters():
cluster.should.have.key("EngineMode").equal("serverless")
cluster.should.have.key("Port").equal(1234)
cluster.should.have.key("DeletionProtection").equal(True)
+ cluster.should.have.key("EnabledCloudwatchLogsExports").equals(["audit"])
@mock_rds