From 7b1cf9eecd7e6da7939e13839d7f6a594fe82235 Mon Sep 17 00:00:00 2001 From: Stephen Huff Date: Tue, 15 Oct 2019 16:18:37 -0400 Subject: [PATCH 1/2] fix(rds2): handle create_db_instance when AllocatedStorage is not specified In all of the tests of `create_db_instance()`, the `AllocatedStorage` parameter is provided. The [RDS API reference](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBInstance.html) says this parameter is optional; however, when none is provided, moto returns an obscure error message: ``` self = , shape = , text = 'None' @_text_content def _handle_integer(self, shape, text): > return int(text) E ValueError: invalid literal for int() with base 10: 'None' /usr/local/Cellar/pyenv/1.2.13_1/versions/3.7.4/envs/rds_encrypt/lib/python3.7/site-packages/botocore/parsers.py:466: ValueError ``` This PR adds default values that correspond to the current default API behaviors. --- moto/rds2/models.py | 77 ++++++++++++++++++++++++++++++++++++ moto/rds2/responses.py | 2 +- tests/test_rds2/test_rds2.py | 14 +++++++ 3 files changed, 92 insertions(+), 1 deletion(-) diff --git a/moto/rds2/models.py b/moto/rds2/models.py index 4c0daa230..18f605511 100644 --- a/moto/rds2/models.py +++ b/moto/rds2/models.py @@ -56,6 +56,8 @@ class Database(BaseModel): else: self.kms_key_id = kwargs.get("kms_key_id") self.storage_type = kwargs.get("storage_type") + if self.storage_type is None: + self.storage_type = Database.default_storage_type(iops=self.iops) self.master_username = kwargs.get('master_username') self.master_user_password = kwargs.get('master_user_password') self.auto_minor_version_upgrade = kwargs.get( @@ -63,6 +65,8 @@ class Database(BaseModel): if self.auto_minor_version_upgrade is None: self.auto_minor_version_upgrade = True self.allocated_storage = kwargs.get('allocated_storage') + if self.allocated_storage is None: + self.allocated_storage = Database.default_allocated_storage(engine=self.engine,storage_type=self.storage_type) self.db_instance_identifier = kwargs.get('db_instance_identifier') self.source_db_identifier = kwargs.get("source_db_identifier") self.db_instance_class = kwargs.get('db_instance_class') @@ -292,6 +296,79 @@ class Database(BaseModel): 'sqlserver-web': 1433, }[engine] + @staticmethod + def default_storage_type(iops): + if iops is None: + return 'gp2' + else: + return 'io1' + + + @staticmethod + def default_allocated_storage(engine,storage_type): + return { + 'aurora': { + 'gp2': 0, + 'io1': 0, + 'standard': 0, + }, + 'mysql': { + 'gp2': 20, + 'io1': 100, + 'standard': 5, + }, + 'mariadb': { + 'gp2': 20, + 'io1': 100, + 'standard': 5, + }, + 'postgres': { + 'gp2': 20, + 'io1': 100, + 'standard': 5, + }, + 'oracle-ee': { + 'gp2': 20, + 'io1': 100, + 'standard': 10, + }, + 'oracle-se2': { + 'gp2': 20, + 'io1': 100, + 'standard': 10, + }, + 'oracle-se1': { + 'gp2': 20, + 'io1': 100, + 'standard': 10, + }, + 'oracle-se': { + 'gp2': 20, + 'io1': 100, + 'standard': 10, + }, + 'sqlserver-ee': { + 'gp2': 200, + 'io1': 200, + 'standard': 200, + }, + 'sqlserver-ex': { + 'gp2': 20, + 'io1': 100, + 'standard': 20, + }, + 'sqlserver-se': { + 'gp2': 200, + 'io1': 200, + 'standard': 200, + }, + 'sqlserver-web': { + 'gp2': 20, + 'io1': 100, + 'standard': 20, + }, + }[engine][storage_type] + @classmethod def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name): properties = cloudformation_json['Properties'] diff --git a/moto/rds2/responses.py b/moto/rds2/responses.py index 7b8d0b63a..fdba73248 100644 --- a/moto/rds2/responses.py +++ b/moto/rds2/responses.py @@ -42,7 +42,7 @@ class RDS2Response(BaseResponse): "region": self.region, "security_groups": self._get_multi_param('DBSecurityGroups.DBSecurityGroupName'), "storage_encrypted": self._get_param("StorageEncrypted"), - "storage_type": self._get_param("StorageType", 'standard'), + "storage_type": self._get_param("StorageType", None), "vpc_security_group_ids": self._get_multi_param("VpcSecurityGroupIds.VpcSecurityGroupId"), "tags": list(), } diff --git a/tests/test_rds2/test_rds2.py b/tests/test_rds2/test_rds2.py index aacaf04f1..911f682a8 100644 --- a/tests/test_rds2/test_rds2.py +++ b/tests/test_rds2/test_rds2.py @@ -39,6 +39,20 @@ def test_create_database(): db_instance['VpcSecurityGroups'][0]['VpcSecurityGroupId'].should.equal('sg-123456') +@mock_rds2 +def test_create_database_no_allocated_storage(): + conn = boto3.client('rds', region_name='us-west-2') + database = conn.create_db_instance( + DBInstanceIdentifier='db-master-1', + Engine='postgres', + DBName='staging-postgres', + DBInstanceClass='db.m1.small') + db_instance = database['DBInstance'] + db_instance['Engine'].should.equal('postgres') + db_instance['StorageType'].should.equal('gp2') + db_instance['AllocatedStorage'].should.equal(20) + + @mock_rds2 def test_create_database_non_existing_option_group(): conn = boto3.client('rds', region_name='us-west-2') From d1a13ed7827f521dd67af8f6f8a0e623afda628d Mon Sep 17 00:00:00 2001 From: Stephen Huff Date: Wed, 16 Oct 2019 09:10:56 -0400 Subject: [PATCH 2/2] chore(rds2): make flake8 happy --- moto/rds2/models.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/moto/rds2/models.py b/moto/rds2/models.py index 18f605511..cd56599e6 100644 --- a/moto/rds2/models.py +++ b/moto/rds2/models.py @@ -66,7 +66,7 @@ class Database(BaseModel): self.auto_minor_version_upgrade = True self.allocated_storage = kwargs.get('allocated_storage') if self.allocated_storage is None: - self.allocated_storage = Database.default_allocated_storage(engine=self.engine,storage_type=self.storage_type) + self.allocated_storage = Database.default_allocated_storage(engine=self.engine, storage_type=self.storage_type) self.db_instance_identifier = kwargs.get('db_instance_identifier') self.source_db_identifier = kwargs.get("source_db_identifier") self.db_instance_class = kwargs.get('db_instance_class') @@ -303,9 +303,8 @@ class Database(BaseModel): else: return 'io1' - @staticmethod - def default_allocated_storage(engine,storage_type): + def default_allocated_storage(engine, storage_type): return { 'aurora': { 'gp2': 0,