1import copy 2import datetime 3import os 4import random 5import string 6 7from collections import defaultdict 8from boto3 import Session 9from jinja2 import Template 10from re import compile as re_compile 11from collections import OrderedDict 12from moto.core import BaseBackend, BaseModel, CloudFormationModel, ACCOUNT_ID 13 14from moto.core.utils import iso_8601_datetime_with_milliseconds 15from moto.ec2.models import ec2_backends 16from .exceptions import ( 17 RDSClientError, 18 DBClusterNotFoundError, 19 DBInstanceNotFoundError, 20 DBSnapshotNotFoundError, 21 DBSecurityGroupNotFoundError, 22 DBSubnetGroupNotFoundError, 23 DBParameterGroupNotFoundError, 24 OptionGroupNotFoundFaultError, 25 InvalidDBClusterStateFaultError, 26 InvalidDBInstanceStateError, 27 SnapshotQuotaExceededError, 28 DBSnapshotAlreadyExistsError, 29 InvalidParameterValue, 30 InvalidParameterCombination, 31 InvalidDBClusterStateFault, 32) 33from .utils import FilterDef, apply_filter, merge_filters, validate_filters 34 35 36class Cluster: 37 def __init__(self, **kwargs): 38 self.db_name = kwargs.get("db_name") 39 self.db_cluster_identifier = kwargs.get("db_cluster_identifier") 40 self.engine = kwargs.get("engine") 41 self.engine_version = kwargs.get("engine_version") 42 if not self.engine_version: 43 # Set default 44 self.engine_version = "5.6.mysql_aurora.1.22.5" # TODO: depends on engine 45 self.engine_mode = kwargs.get("engine_mode") or "provisioned" 46 self.status = "active" 47 self.region = kwargs.get("region") 48 self.cluster_create_time = iso_8601_datetime_with_milliseconds( 49 datetime.datetime.now() 50 ) 51 self.master_username = kwargs.get("master_username") 52 if not self.master_username: 53 raise InvalidParameterValue( 54 "The parameter MasterUsername must be provided and must not be blank." 55 ) 56 self.master_user_password = kwargs.get("master_user_password") 57 if not self.master_user_password: 58 raise InvalidParameterValue( 59 "The parameter MasterUserPassword must be provided and must not be blank." 60 ) 61 if len(self.master_user_password) < 8: 62 raise InvalidParameterValue( 63 "The parameter MasterUserPassword is not a valid password because it is shorter than 8 characters." 64 ) 65 self.availability_zones = kwargs.get("availability_zones") 66 if not self.availability_zones: 67 self.availability_zones = [ 68 f"{self.region}a", 69 f"{self.region}b", 70 f"{self.region}c", 71 ] 72 self.parameter_group = kwargs.get("parameter_group") or "default.aurora5.6" 73 self.subnet_group = "default" 74 self.status = "creating" 75 self.url_identifier = "".join( 76 random.choice(string.ascii_lowercase + string.digits) for _ in range(12) 77 ) 78 self.endpoint = f"{self.db_cluster_identifier}.cluster-{self.url_identifier}.{self.region}.rds.amazonaws.com" 79 self.reader_endpoint = f"{self.db_cluster_identifier}.cluster-ro-{self.url_identifier}.{self.region}.rds.amazonaws.com" 80 self.port = kwargs.get("port") or 3306 81 self.preferred_backup_window = "01:37-02:07" 82 self.preferred_maintenance_window = "wed:02:40-wed:03:10" 83 # This should default to the default security group 84 self.vpc_security_groups = [] 85 self.hosted_zone_id = "".join( 86 random.choice(string.ascii_uppercase + string.digits) for _ in range(14) 87 ) 88 self.resource_id = "cluster-" + "".join( 89 random.choice(string.ascii_uppercase + string.digits) for _ in range(26) 90 ) 91 self.arn = f"arn:aws:rds:{self.region}:{ACCOUNT_ID}:cluster:{self.db_cluster_identifier}" 92 93 def to_xml(self): 94 template = Template( 95 """<DBCluster> 96 <AllocatedStorage>1</AllocatedStorage> 97 <AvailabilityZones> 98 {% for zone in cluster.availability_zones %} 99 <AvailabilityZone>{{ zone }}</AvailabilityZone> 100 {% endfor %} 101 </AvailabilityZones> 102 <BackupRetentionPeriod>1</BackupRetentionPeriod> 103 <DBInstanceStatus>{{ cluster.status }}</DBInstanceStatus> 104 {% if cluster.db_name %}<DatabaseName>{{ cluster.db_name }}</DatabaseName>{% endif %} 105 <DBClusterIdentifier>{{ cluster.db_cluster_identifier }}</DBClusterIdentifier> 106 <DBClusterParameterGroup>{{ cluster.parameter_group }}</DBClusterParameterGroup> 107 <DBSubnetGroup>{{ cluster.subnet_group }}</DBSubnetGroup> 108 <ClusterCreateTime>{{ cluster.cluster_create_time }}</ClusterCreateTime> 109 <Engine>{{ cluster.engine }}</Engine> 110 <Status>{{ cluster.status }}</Status> 111 <Endpoint>{{ cluster.endpoint }}</Endpoint> 112 <ReaderEndpoint>{{ cluster.reader_endpoint }}</ReaderEndpoint> 113 <MultiAZ>false</MultiAZ> 114 <EngineVersion>{{ cluster.engine_version }}</EngineVersion> 115 <Port>{{ cluster.port }}</Port> 116 <MasterUsername>{{ cluster.master_username }}</MasterUsername> 117 <PreferredBackupWindow>{{ cluster.preferred_backup_window }}</PreferredBackupWindow> 118 <PreferredMaintenanceWindow>{{ cluster.preferred_maintenance_window }}</PreferredMaintenanceWindow> 119 <ReadReplicaIdentifiers></ReadReplicaIdentifiers> 120 <DBClusterMembers></DBClusterMembers> 121 <VpcSecurityGroups> 122 {% for id in cluster.vpc_security_groups %} 123 <VpcSecurityGroup> 124 <VpcSecurityGroupId>{{ id }}</VpcSecurityGroupId> 125 <Status>active</Status> 126 </VpcSecurityGroup> 127 {% endfor %} 128 </VpcSecurityGroups> 129 <HostedZoneId>{{ cluster.hosted_zone_id }}</HostedZoneId> 130 <StorageEncrypted>false</StorageEncrypted> 131 <DbClusterResourceId>{{ cluster.resource_id }}</DbClusterResourceId> 132 <DBClusterArn>{{ cluster.arn }}</DBClusterArn> 133 <AssociatedRoles></AssociatedRoles> 134 <IAMDatabaseAuthenticationEnabled>false</IAMDatabaseAuthenticationEnabled> 135 <EngineMode>{{ cluster.engine_mode }}</EngineMode> 136 <DeletionProtection>false</DeletionProtection> 137 <HttpEndpointEnabled>false</HttpEndpointEnabled> 138 <CopyTagsToSnapshot>false</CopyTagsToSnapshot> 139 <CrossAccountClone>false</CrossAccountClone> 140 <DomainMemberships></DomainMemberships> 141 <TagList></TagList> 142 </DBCluster>""" 143 ) 144 return template.render(cluster=self) 145 146 147class Database(CloudFormationModel): 148 149 SUPPORTED_FILTERS = { 150 "db-cluster-id": FilterDef(None, "DB Cluster Identifiers"), 151 "db-instance-id": FilterDef( 152 ["db_instance_arn", "db_instance_identifier"], "DB Instance Identifiers" 153 ), 154 "dbi-resource-id": FilterDef(["dbi_resource_id"], "Dbi Resource Ids"), 155 "domain": FilterDef(None, ""), 156 "engine": FilterDef(["engine"], "Engine Names"), 157 } 158 159 default_engine_versions = { 160 "MySQL": "5.6.21", 161 "mysql": "5.6.21", 162 "oracle-se1": "11.2.0.4.v3", 163 "oracle-se": "11.2.0.4.v3", 164 "oracle-ee": "11.2.0.4.v3", 165 "sqlserver-ee": "11.00.2100.60.v1", 166 "sqlserver-se": "11.00.2100.60.v1", 167 "sqlserver-ex": "11.00.2100.60.v1", 168 "sqlserver-web": "11.00.2100.60.v1", 169 "postgres": "9.3.3", 170 } 171 172 def __init__(self, **kwargs): 173 self.status = "available" 174 self.is_replica = False 175 self.replicas = [] 176 self.region = kwargs.get("region") 177 self.engine = kwargs.get("engine") 178 self.engine_version = kwargs.get("engine_version", None) 179 if not self.engine_version and self.engine in self.default_engine_versions: 180 self.engine_version = self.default_engine_versions[self.engine] 181 self.iops = kwargs.get("iops") 182 self.storage_encrypted = kwargs.get("storage_encrypted", False) 183 if self.storage_encrypted: 184 self.kms_key_id = kwargs.get("kms_key_id", "default_kms_key_id") 185 else: 186 self.kms_key_id = kwargs.get("kms_key_id") 187 self.storage_type = kwargs.get("storage_type") 188 if self.storage_type is None: 189 self.storage_type = Database.default_storage_type(iops=self.iops) 190 self.master_username = kwargs.get("master_username") 191 self.master_user_password = kwargs.get("master_user_password") 192 self.auto_minor_version_upgrade = kwargs.get("auto_minor_version_upgrade") 193 if self.auto_minor_version_upgrade is None: 194 self.auto_minor_version_upgrade = True 195 self.allocated_storage = kwargs.get("allocated_storage") 196 if self.allocated_storage is None: 197 self.allocated_storage = Database.default_allocated_storage( 198 engine=self.engine, storage_type=self.storage_type 199 ) 200 self.db_instance_identifier = kwargs.get("db_instance_identifier") 201 self.source_db_identifier = kwargs.get("source_db_identifier") 202 self.db_instance_class = kwargs.get("db_instance_class") 203 self.port = kwargs.get("port") 204 if self.port is None: 205 self.port = Database.default_port(self.engine) 206 self.db_instance_identifier = kwargs.get("db_instance_identifier") 207 self.db_name = kwargs.get("db_name") 208 self.instance_create_time = iso_8601_datetime_with_milliseconds( 209 datetime.datetime.now() 210 ) 211 self.publicly_accessible = kwargs.get("publicly_accessible") 212 if self.publicly_accessible is None: 213 self.publicly_accessible = True 214 self.copy_tags_to_snapshot = kwargs.get("copy_tags_to_snapshot") 215 if self.copy_tags_to_snapshot is None: 216 self.copy_tags_to_snapshot = False 217 self.backup_retention_period = kwargs.get("backup_retention_period") 218 if self.backup_retention_period is None: 219 self.backup_retention_period = 1 220 self.availability_zone = kwargs.get("availability_zone") 221 self.multi_az = kwargs.get("multi_az") 222 self.db_subnet_group_name = kwargs.get("db_subnet_group_name") 223 if self.db_subnet_group_name: 224 self.db_subnet_group = rds2_backends[self.region].describe_subnet_groups( 225 self.db_subnet_group_name 226 )[0] 227 else: 228 self.db_subnet_group = None 229 self.security_groups = kwargs.get("security_groups", []) 230 self.vpc_security_group_ids = kwargs.get("vpc_security_group_ids", []) 231 self.preferred_maintenance_window = kwargs.get( 232 "preferred_maintenance_window", "wed:06:38-wed:07:08" 233 ) 234 self.db_parameter_group_name = kwargs.get("db_parameter_group_name") 235 if ( 236 self.db_parameter_group_name 237 and not self.is_default_parameter_group(self.db_parameter_group_name) 238 and self.db_parameter_group_name 239 not in rds2_backends[self.region].db_parameter_groups 240 ): 241 raise DBParameterGroupNotFoundError(self.db_parameter_group_name) 242 243 self.preferred_backup_window = kwargs.get( 244 "preferred_backup_window", "13:14-13:44" 245 ) 246 self.license_model = kwargs.get("license_model", "general-public-license") 247 self.option_group_name = kwargs.get("option_group_name", None) 248 self.option_group_supplied = self.option_group_name is not None 249 if ( 250 self.option_group_name 251 and self.option_group_name not in rds2_backends[self.region].option_groups 252 ): 253 raise OptionGroupNotFoundFaultError(self.option_group_name) 254 self.default_option_groups = { 255 "MySQL": "default.mysql5.6", 256 "mysql": "default.mysql5.6", 257 "postgres": "default.postgres9.3", 258 } 259 if not self.option_group_name and self.engine in self.default_option_groups: 260 self.option_group_name = self.default_option_groups[self.engine] 261 self.character_set_name = kwargs.get("character_set_name", None) 262 self.enable_iam_database_authentication = kwargs.get( 263 "enable_iam_database_authentication", False 264 ) 265 self.dbi_resource_id = "db-M5ENSHXFPU6XHZ4G4ZEI5QIO2U" 266 self.tags = kwargs.get("tags", []) 267 268 @property 269 def db_instance_arn(self): 270 return "arn:aws:rds:{0}:{1}:db:{2}".format( 271 self.region, ACCOUNT_ID, self.db_instance_identifier 272 ) 273 274 @property 275 def physical_resource_id(self): 276 return self.db_instance_identifier 277 278 def db_parameter_groups(self): 279 if not self.db_parameter_group_name or self.is_default_parameter_group( 280 self.db_parameter_group_name 281 ): 282 ( 283 db_family, 284 db_parameter_group_name, 285 ) = self.default_db_parameter_group_details() 286 description = "Default parameter group for {0}".format(db_family) 287 return [ 288 DBParameterGroup( 289 name=db_parameter_group_name, 290 family=db_family, 291 description=description, 292 tags={}, 293 region=self.region, 294 ) 295 ] 296 else: 297 return [ 298 rds2_backends[self.region].db_parameter_groups[ 299 self.db_parameter_group_name 300 ] 301 ] 302 303 def is_default_parameter_group(self, param_group_name): 304 return param_group_name.startswith("default.%s" % self.engine.lower()) 305 306 def default_db_parameter_group_details(self): 307 if not self.engine_version: 308 return (None, None) 309 310 minor_engine_version = ".".join(str(self.engine_version).rsplit(".")[:-1]) 311 db_family = "{0}{1}".format(self.engine.lower(), minor_engine_version) 312 313 return db_family, "default.{0}".format(db_family) 314 315 def to_xml(self): 316 template = Template( 317 """<DBInstance> 318 <BackupRetentionPeriod>{{ database.backup_retention_period }}</BackupRetentionPeriod> 319 <DBInstanceStatus>{{ database.status }}</DBInstanceStatus> 320 {% if database.db_name %}<DBName>{{ database.db_name }}</DBName>{% endif %} 321 <MultiAZ>{{ database.multi_az }}</MultiAZ> 322 <VpcSecurityGroups> 323 {% for vpc_security_group_id in database.vpc_security_group_ids %} 324 <VpcSecurityGroupMembership> 325 <Status>active</Status> 326 <VpcSecurityGroupId>{{ vpc_security_group_id }}</VpcSecurityGroupId> 327 </VpcSecurityGroupMembership> 328 {% endfor %} 329 </VpcSecurityGroups> 330 <DBInstanceIdentifier>{{ database.db_instance_identifier }}</DBInstanceIdentifier> 331 <DbiResourceId>{{ database.dbi_resource_id }}</DbiResourceId> 332 <InstanceCreateTime>{{ database.instance_create_time }}</InstanceCreateTime> 333 <PreferredBackupWindow>03:50-04:20</PreferredBackupWindow> 334 <PreferredMaintenanceWindow>wed:06:38-wed:07:08</PreferredMaintenanceWindow> 335 <ReadReplicaDBInstanceIdentifiers> 336 {% for replica_id in database.replicas %} 337 <ReadReplicaDBInstanceIdentifier>{{ replica_id }}</ReadReplicaDBInstanceIdentifier> 338 {% endfor %} 339 </ReadReplicaDBInstanceIdentifiers> 340 <StatusInfos> 341 {% if database.is_replica %} 342 <DBInstanceStatusInfo> 343 <StatusType>read replication</StatusType> 344 <Status>replicating</Status> 345 <Normal>true</Normal> 346 <Message></Message> 347 </DBInstanceStatusInfo> 348 {% endif %} 349 </StatusInfos> 350 {% if database.is_replica %} 351 <ReadReplicaSourceDBInstanceIdentifier>{{ database.source_db_identifier }}</ReadReplicaSourceDBInstanceIdentifier> 352 {% endif %} 353 <Engine>{{ database.engine }}</Engine> 354 <IAMDatabaseAuthenticationEnabled>{{database.enable_iam_database_authentication|lower }}</IAMDatabaseAuthenticationEnabled> 355 <LicenseModel>{{ database.license_model }}</LicenseModel> 356 <EngineVersion>{{ database.engine_version }}</EngineVersion> 357 <OptionGroupMemberships> 358 <OptionGroupMembership> 359 <OptionGroupName>{{ database.option_group_name }}</OptionGroupName> 360 <Status>in-sync</Status> 361 </OptionGroupMembership> 362 </OptionGroupMemberships> 363 <DBParameterGroups> 364 {% for db_parameter_group in database.db_parameter_groups() %} 365 <DBParameterGroup> 366 <ParameterApplyStatus>in-sync</ParameterApplyStatus> 367 <DBParameterGroupName>{{ db_parameter_group.name }}</DBParameterGroupName> 368 </DBParameterGroup> 369 {% endfor %} 370 </DBParameterGroups> 371 <DBSecurityGroups> 372 {% for security_group in database.security_groups %} 373 <DBSecurityGroup> 374 <Status>active</Status> 375 <DBSecurityGroupName>{{ security_group }}</DBSecurityGroupName> 376 </DBSecurityGroup> 377 {% endfor %} 378 </DBSecurityGroups> 379 {% if database.db_subnet_group %} 380 <DBSubnetGroup> 381 <DBSubnetGroupName>{{ database.db_subnet_group.subnet_name }}</DBSubnetGroupName> 382 <DBSubnetGroupDescription>{{ database.db_subnet_group.description }}</DBSubnetGroupDescription> 383 <SubnetGroupStatus>{{ database.db_subnet_group.status }}</SubnetGroupStatus> 384 <Subnets> 385 {% for subnet in database.db_subnet_group.subnets %} 386 <Subnet> 387 <SubnetStatus>Active</SubnetStatus> 388 <SubnetIdentifier>{{ subnet.id }}</SubnetIdentifier> 389 <SubnetAvailabilityZone> 390 <Name>{{ subnet.availability_zone }}</Name> 391 <ProvisionedIopsCapable>false</ProvisionedIopsCapable> 392 </SubnetAvailabilityZone> 393 </Subnet> 394 {% endfor %} 395 </Subnets> 396 <VpcId>{{ database.db_subnet_group.vpc_id }}</VpcId> 397 </DBSubnetGroup> 398 {% endif %} 399 <PubliclyAccessible>{{ database.publicly_accessible }}</PubliclyAccessible> 400 <CopyTagsToSnapshot>{{ database.copy_tags_to_snapshot }}</CopyTagsToSnapshot> 401 <AutoMinorVersionUpgrade>{{ database.auto_minor_version_upgrade }}</AutoMinorVersionUpgrade> 402 <AllocatedStorage>{{ database.allocated_storage }}</AllocatedStorage> 403 <StorageEncrypted>{{ database.storage_encrypted }}</StorageEncrypted> 404 {% if database.kms_key_id %} 405 <KmsKeyId>{{ database.kms_key_id }}</KmsKeyId> 406 {% endif %} 407 {% if database.iops %} 408 <Iops>{{ database.iops }}</Iops> 409 <StorageType>io1</StorageType> 410 {% else %} 411 <StorageType>{{ database.storage_type }}</StorageType> 412 {% endif %} 413 <DBInstanceClass>{{ database.db_instance_class }}</DBInstanceClass> 414 <MasterUsername>{{ database.master_username }}</MasterUsername> 415 <Endpoint> 416 <Address>{{ database.address }}</Address> 417 <Port>{{ database.port }}</Port> 418 </Endpoint> 419 <DBInstanceArn>{{ database.db_instance_arn }}</DBInstanceArn> 420 <TagList> 421 {%- for tag in database.tags -%} 422 <Tag> 423 <Key>{{ tag['Key'] }}</Key> 424 <Value>{{ tag['Value'] }}</Value> 425 </Tag> 426 {%- endfor -%} 427 </TagList> 428 </DBInstance>""" 429 ) 430 return template.render(database=self) 431 432 @property 433 def address(self): 434 return "{0}.aaaaaaaaaa.{1}.rds.amazonaws.com".format( 435 self.db_instance_identifier, self.region 436 ) 437 438 def add_replica(self, replica): 439 self.replicas.append(replica.db_instance_identifier) 440 441 def remove_replica(self, replica): 442 self.replicas.remove(replica.db_instance_identifier) 443 444 def set_as_replica(self): 445 self.is_replica = True 446 self.replicas = [] 447 448 def update(self, db_kwargs): 449 for key, value in db_kwargs.items(): 450 if value is not None: 451 setattr(self, key, value) 452 453 @classmethod 454 def has_cfn_attr(cls, attribute): 455 return attribute in ["Endpoint.Address", "Endpoint.Port"] 456 457 def get_cfn_attribute(self, attribute_name): 458 # Local import to avoid circular dependency with cloudformation.parsing 459 from moto.cloudformation.exceptions import UnformattedGetAttTemplateException 460 461 if attribute_name == "Endpoint.Address": 462 return self.address 463 elif attribute_name == "Endpoint.Port": 464 return self.port 465 raise UnformattedGetAttTemplateException() 466 467 @staticmethod 468 def default_port(engine): 469 return { 470 "mysql": 3306, 471 "mariadb": 3306, 472 "postgres": 5432, 473 "oracle-ee": 1521, 474 "oracle-se2": 1521, 475 "oracle-se1": 1521, 476 "oracle-se": 1521, 477 "sqlserver-ee": 1433, 478 "sqlserver-ex": 1433, 479 "sqlserver-se": 1433, 480 "sqlserver-web": 1433, 481 }[engine] 482 483 @staticmethod 484 def default_storage_type(iops): 485 if iops is None: 486 return "gp2" 487 else: 488 return "io1" 489 490 @staticmethod 491 def default_allocated_storage(engine, storage_type): 492 return { 493 "aurora": {"gp2": 0, "io1": 0, "standard": 0}, 494 "mysql": {"gp2": 20, "io1": 100, "standard": 5}, 495 "mariadb": {"gp2": 20, "io1": 100, "standard": 5}, 496 "postgres": {"gp2": 20, "io1": 100, "standard": 5}, 497 "oracle-ee": {"gp2": 20, "io1": 100, "standard": 10}, 498 "oracle-se2": {"gp2": 20, "io1": 100, "standard": 10}, 499 "oracle-se1": {"gp2": 20, "io1": 100, "standard": 10}, 500 "oracle-se": {"gp2": 20, "io1": 100, "standard": 10}, 501 "sqlserver-ee": {"gp2": 200, "io1": 200, "standard": 200}, 502 "sqlserver-ex": {"gp2": 20, "io1": 100, "standard": 20}, 503 "sqlserver-se": {"gp2": 200, "io1": 200, "standard": 200}, 504 "sqlserver-web": {"gp2": 20, "io1": 100, "standard": 20}, 505 }[engine][storage_type] 506 507 @staticmethod 508 def cloudformation_name_type(): 509 return "DBInstanceIdentifier" 510 511 @staticmethod 512 def cloudformation_type(): 513 # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbinstance.html 514 return "AWS::RDS::DBInstance" 515 516 @classmethod 517 def create_from_cloudformation_json( 518 cls, resource_name, cloudformation_json, region_name, **kwargs 519 ): 520 properties = cloudformation_json["Properties"] 521 522 db_security_groups = properties.get("DBSecurityGroups") 523 if not db_security_groups: 524 db_security_groups = [] 525 security_groups = [group.group_name for group in db_security_groups] 526 db_subnet_group = properties.get("DBSubnetGroupName") 527 db_subnet_group_name = db_subnet_group.subnet_name if db_subnet_group else None 528 db_kwargs = { 529 "auto_minor_version_upgrade": properties.get("AutoMinorVersionUpgrade"), 530 "allocated_storage": properties.get("AllocatedStorage"), 531 "availability_zone": properties.get("AvailabilityZone"), 532 "backup_retention_period": properties.get("BackupRetentionPeriod"), 533 "db_instance_class": properties.get("DBInstanceClass"), 534 "db_instance_identifier": resource_name, 535 "db_name": properties.get("DBName"), 536 "db_subnet_group_name": db_subnet_group_name, 537 "engine": properties.get("Engine"), 538 "engine_version": properties.get("EngineVersion"), 539 "iops": properties.get("Iops"), 540 "kms_key_id": properties.get("KmsKeyId"), 541 "master_user_password": properties.get("MasterUserPassword"), 542 "master_username": properties.get("MasterUsername"), 543 "multi_az": properties.get("MultiAZ"), 544 "db_parameter_group_name": properties.get("DBParameterGroupName"), 545 "port": properties.get("Port", 3306), 546 "publicly_accessible": properties.get("PubliclyAccessible"), 547 "copy_tags_to_snapshot": properties.get("CopyTagsToSnapshot"), 548 "region": region_name, 549 "security_groups": security_groups, 550 "storage_encrypted": properties.get("StorageEncrypted"), 551 "storage_type": properties.get("StorageType"), 552 "tags": properties.get("Tags"), 553 "vpc_security_group_ids": properties.get("VpcSecurityGroupIds", []), 554 } 555 556 rds2_backend = rds2_backends[region_name] 557 source_db_identifier = properties.get("SourceDBInstanceIdentifier") 558 if source_db_identifier: 559 # Replica 560 db_kwargs["source_db_identifier"] = source_db_identifier 561 database = rds2_backend.create_database_replica(db_kwargs) 562 else: 563 database = rds2_backend.create_database(db_kwargs) 564 return database 565 566 def to_json(self): 567 template = Template( 568 """{ 569 "AllocatedStorage": 10, 570 "AutoMinorVersionUpgrade": "{{ database.auto_minor_version_upgrade }}", 571 "AvailabilityZone": "{{ database.availability_zone }}", 572 "BackupRetentionPeriod": "{{ database.backup_retention_period }}", 573 "CharacterSetName": {%- if database.character_set_name -%}{{ database.character_set_name }}{%- else %} null{%- endif -%}, 574 "DBInstanceClass": "{{ database.db_instance_class }}", 575 "DBInstanceIdentifier": "{{ database.db_instance_identifier }}", 576 "DBInstanceStatus": "{{ database.status }}", 577 "DBName": {%- if database.db_name -%}"{{ database.db_name }}"{%- else %} null{%- endif -%}, 578 {% if database.db_parameter_group_name -%}"DBParameterGroups": { 579 "DBParameterGroup": { 580 "ParameterApplyStatus": "in-sync", 581 "DBParameterGroupName": "{{ database.db_parameter_group_name }}" 582 } 583 },{%- endif %} 584 "DBSecurityGroups": [ 585 {% for security_group in database.security_groups -%}{%- if loop.index != 1 -%},{%- endif -%} 586 {"DBSecurityGroup": { 587 "Status": "active", 588 "DBSecurityGroupName": "{{ security_group }}" 589 }}{% endfor %} 590 ], 591 {%- if database.db_subnet_group -%}{{ database.db_subnet_group.to_json() }},{%- endif %} 592 "Engine": "{{ database.engine }}", 593 "EngineVersion": "{{ database.engine_version }}", 594 "LatestRestorableTime": null, 595 "LicenseModel": "{{ database.license_model }}", 596 "MasterUsername": "{{ database.master_username }}", 597 "MultiAZ": "{{ database.multi_az }}",{% if database.option_group_name %} 598 "OptionGroupMemberships": [{ 599 "OptionGroupMembership": { 600 "OptionGroupName": "{{ database.option_group_name }}", 601 "Status": "in-sync" 602 } 603 }],{%- endif %} 604 "PendingModifiedValues": { "MasterUserPassword": "****" }, 605 "PreferredBackupWindow": "{{ database.preferred_backup_window }}", 606 "PreferredMaintenanceWindow": "{{ database.preferred_maintenance_window }}", 607 "PubliclyAccessible": "{{ database.publicly_accessible }}", 608 "CopyTagsToSnapshot": "{{ database.copy_tags_to_snapshot }}", 609 "AllocatedStorage": "{{ database.allocated_storage }}", 610 "Endpoint": { 611 "Address": "{{ database.address }}", 612 "Port": "{{ database.port }}" 613 }, 614 "InstanceCreateTime": "{{ database.instance_create_time }}", 615 "Iops": null, 616 "ReadReplicaDBInstanceIdentifiers": [{%- for replica in database.replicas -%} 617 {%- if not loop.first -%},{%- endif -%} 618 "{{ replica }}" 619 {%- endfor -%} 620 ], 621 {%- if database.source_db_identifier -%} 622 "ReadReplicaSourceDBInstanceIdentifier": "{{ database.source_db_identifier }}", 623 {%- else -%} 624 "ReadReplicaSourceDBInstanceIdentifier": null, 625 {%- endif -%} 626 "SecondaryAvailabilityZone": null, 627 "StatusInfos": null, 628 "VpcSecurityGroups": [ 629 {% for vpc_security_group_id in database.vpc_security_group_ids %} 630 { 631 "Status": "active", 632 "VpcSecurityGroupId": "{{ vpc_security_group_id }}" 633 } 634 {% endfor %} 635 ], 636 "DBInstanceArn": "{{ database.db_instance_arn }}" 637 }""" 638 ) 639 return template.render(database=self) 640 641 def get_tags(self): 642 return self.tags 643 644 def add_tags(self, tags): 645 new_keys = [tag_set["Key"] for tag_set in tags] 646 self.tags = [tag_set for tag_set in self.tags if tag_set["Key"] not in new_keys] 647 self.tags.extend(tags) 648 return self.tags 649 650 def remove_tags(self, tag_keys): 651 self.tags = [tag_set for tag_set in self.tags if tag_set["Key"] not in tag_keys] 652 653 def delete(self, region_name): 654 backend = rds2_backends[region_name] 655 backend.delete_database(self.db_instance_identifier) 656 657 658class Snapshot(BaseModel): 659 660 SUPPORTED_FILTERS = { 661 "db-instance-id": FilterDef( 662 ["database.db_instance_arn", "database.db_instance_identifier"], 663 "DB Instance Identifiers", 664 ), 665 "db-snapshot-id": FilterDef(["snapshot_id"], "DB Snapshot Identifiers"), 666 "dbi-resource-id": FilterDef(["database.dbi_resource_id"], "Dbi Resource Ids"), 667 "snapshot-type": FilterDef(None, "Snapshot Types"), 668 "engine": FilterDef(["database.engine"], "Engine Names"), 669 } 670 671 def __init__(self, database, snapshot_id, tags): 672 self.database = database 673 self.snapshot_id = snapshot_id 674 self.tags = tags 675 self.created_at = iso_8601_datetime_with_milliseconds(datetime.datetime.now()) 676 677 @property 678 def snapshot_arn(self): 679 return "arn:aws:rds:{0}:{1}:snapshot:{2}".format( 680 self.database.region, ACCOUNT_ID, self.snapshot_id 681 ) 682 683 def to_xml(self): 684 template = Template( 685 """<DBSnapshot> 686 <DBSnapshotIdentifier>{{ snapshot.snapshot_id }}</DBSnapshotIdentifier> 687 <DBInstanceIdentifier>{{ database.db_instance_identifier }}</DBInstanceIdentifier> 688 <DbiResourceId>{{ database.dbi_resource_id }}</DbiResourceId> 689 <SnapshotCreateTime>{{ snapshot.created_at }}</SnapshotCreateTime> 690 <Engine>{{ database.engine }}</Engine> 691 <AllocatedStorage>{{ database.allocated_storage }}</AllocatedStorage> 692 <Status>available</Status> 693 <Port>{{ database.port }}</Port> 694 <AvailabilityZone>{{ database.availability_zone }}</AvailabilityZone> 695 <VpcId>{{ database.db_subnet_group.vpc_id }}</VpcId> 696 <InstanceCreateTime>{{ snapshot.created_at }}</InstanceCreateTime> 697 <MasterUsername>{{ database.master_username }}</MasterUsername> 698 <EngineVersion>{{ database.engine_version }}</EngineVersion> 699 <LicenseModel>{{ database.license_model }}</LicenseModel> 700 <SnapshotType>manual</SnapshotType> 701 {% if database.iops %} 702 <Iops>{{ database.iops }}</Iops> 703 <StorageType>io1</StorageType> 704 {% else %} 705 <StorageType>{{ database.storage_type }}</StorageType> 706 {% endif %} 707 <OptionGroupName>{{ database.option_group_name }}</OptionGroupName> 708 <PercentProgress>{{ 100 }}</PercentProgress> 709 <SourceRegion>{{ database.region }}</SourceRegion> 710 <SourceDBSnapshotIdentifier></SourceDBSnapshotIdentifier> 711 <TdeCredentialArn></TdeCredentialArn> 712 <Encrypted>{{ database.storage_encrypted }}</Encrypted> 713 <KmsKeyId>{{ database.kms_key_id }}</KmsKeyId> 714 <DBSnapshotArn>{{ snapshot.snapshot_arn }}</DBSnapshotArn> 715 <Timezone></Timezone> 716 <IAMDatabaseAuthenticationEnabled>{{ database.enable_iam_database_authentication|lower }}</IAMDatabaseAuthenticationEnabled> 717 </DBSnapshot>""" 718 ) 719 return template.render(snapshot=self, database=self.database) 720 721 def get_tags(self): 722 return self.tags 723 724 def add_tags(self, tags): 725 new_keys = [tag_set["Key"] for tag_set in tags] 726 self.tags = [tag_set for tag_set in self.tags if tag_set["Key"] not in new_keys] 727 self.tags.extend(tags) 728 return self.tags 729 730 def remove_tags(self, tag_keys): 731 self.tags = [tag_set for tag_set in self.tags if tag_set["Key"] not in tag_keys] 732 733 734class SecurityGroup(CloudFormationModel): 735 def __init__(self, group_name, description, tags): 736 self.group_name = group_name 737 self.description = description 738 self.status = "authorized" 739 self.ip_ranges = [] 740 self.ec2_security_groups = [] 741 self.tags = tags 742 self.owner_id = ACCOUNT_ID 743 self.vpc_id = None 744 745 def to_xml(self): 746 template = Template( 747 """<DBSecurityGroup> 748 <EC2SecurityGroups> 749 {% for security_group in security_group.ec2_security_groups %} 750 <EC2SecurityGroup> 751 <EC2SecurityGroupId>{{ security_group.id }}</EC2SecurityGroupId> 752 <EC2SecurityGroupName>{{ security_group.name }}</EC2SecurityGroupName> 753 <EC2SecurityGroupOwnerId>{{ security_group.owner_id }}</EC2SecurityGroupOwnerId> 754 <Status>authorized</Status> 755 </EC2SecurityGroup> 756 {% endfor %} 757 </EC2SecurityGroups> 758 759 <DBSecurityGroupDescription>{{ security_group.description }}</DBSecurityGroupDescription> 760 <IPRanges> 761 {% for ip_range in security_group.ip_ranges %} 762 <IPRange> 763 <CIDRIP>{{ ip_range }}</CIDRIP> 764 <Status>authorized</Status> 765 </IPRange> 766 {% endfor %} 767 </IPRanges> 768 <OwnerId>{{ security_group.ownder_id }}</OwnerId> 769 <DBSecurityGroupName>{{ security_group.group_name }}</DBSecurityGroupName> 770 </DBSecurityGroup>""" 771 ) 772 return template.render(security_group=self) 773 774 def to_json(self): 775 template = Template( 776 """{ 777 "DBSecurityGroupDescription": "{{ security_group.description }}", 778 "DBSecurityGroupName": "{{ security_group.group_name }}", 779 "EC2SecurityGroups": {{ security_group.ec2_security_groups }}, 780 "IPRanges": [{%- for ip in security_group.ip_ranges -%} 781 {%- if loop.index != 1 -%},{%- endif -%} 782 "{{ ip }}" 783 {%- endfor -%} 784 ], 785 "OwnerId": "{{ security_group.owner_id }}", 786 "VpcId": "{{ security_group.vpc_id }}" 787 }""" 788 ) 789 return template.render(security_group=self) 790 791 def authorize_cidr(self, cidr_ip): 792 self.ip_ranges.append(cidr_ip) 793 794 def authorize_security_group(self, security_group): 795 self.ec2_security_groups.append(security_group) 796 797 @staticmethod 798 def cloudformation_name_type(): 799 return None 800 801 @staticmethod 802 def cloudformation_type(): 803 # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbsecuritygroup.html 804 return "AWS::RDS::DBSecurityGroup" 805 806 @classmethod 807 def create_from_cloudformation_json( 808 cls, resource_name, cloudformation_json, region_name, **kwargs 809 ): 810 properties = cloudformation_json["Properties"] 811 group_name = resource_name.lower() 812 description = properties["GroupDescription"] 813 security_group_ingress_rules = properties.get("DBSecurityGroupIngress", []) 814 tags = properties.get("Tags") 815 816 ec2_backend = ec2_backends[region_name] 817 rds2_backend = rds2_backends[region_name] 818 security_group = rds2_backend.create_security_group( 819 group_name, description, tags 820 ) 821 for security_group_ingress in security_group_ingress_rules: 822 for ingress_type, ingress_value in security_group_ingress.items(): 823 if ingress_type == "CIDRIP": 824 security_group.authorize_cidr(ingress_value) 825 elif ingress_type == "EC2SecurityGroupName": 826 subnet = ec2_backend.get_security_group_from_name(ingress_value) 827 security_group.authorize_security_group(subnet) 828 elif ingress_type == "EC2SecurityGroupId": 829 subnet = ec2_backend.get_security_group_from_id(ingress_value) 830 security_group.authorize_security_group(subnet) 831 return security_group 832 833 def get_tags(self): 834 return self.tags 835 836 def add_tags(self, tags): 837 new_keys = [tag_set["Key"] for tag_set in tags] 838 self.tags = [tag_set for tag_set in self.tags if tag_set["Key"] not in new_keys] 839 self.tags.extend(tags) 840 return self.tags 841 842 def remove_tags(self, tag_keys): 843 self.tags = [tag_set for tag_set in self.tags if tag_set["Key"] not in tag_keys] 844 845 def delete(self, region_name): 846 backend = rds2_backends[region_name] 847 backend.delete_security_group(self.group_name) 848 849 850class SubnetGroup(CloudFormationModel): 851 def __init__(self, subnet_name, description, subnets, tags): 852 self.subnet_name = subnet_name 853 self.description = description 854 self.subnets = subnets 855 self.status = "Complete" 856 self.tags = tags 857 self.vpc_id = self.subnets[0].vpc_id 858 859 def to_xml(self): 860 template = Template( 861 """<DBSubnetGroup> 862 <VpcId>{{ subnet_group.vpc_id }}</VpcId> 863 <SubnetGroupStatus>{{ subnet_group.status }}</SubnetGroupStatus> 864 <DBSubnetGroupDescription>{{ subnet_group.description }}</DBSubnetGroupDescription> 865 <DBSubnetGroupName>{{ subnet_group.subnet_name }}</DBSubnetGroupName> 866 <Subnets> 867 {% for subnet in subnet_group.subnets %} 868 <Subnet> 869 <SubnetStatus>Active</SubnetStatus> 870 <SubnetIdentifier>{{ subnet.id }}</SubnetIdentifier> 871 <SubnetAvailabilityZone> 872 <Name>{{ subnet.availability_zone }}</Name> 873 <ProvisionedIopsCapable>false</ProvisionedIopsCapable> 874 </SubnetAvailabilityZone> 875 </Subnet> 876 {% endfor %} 877 </Subnets> 878 </DBSubnetGroup>""" 879 ) 880 return template.render(subnet_group=self) 881 882 def to_json(self): 883 template = Template( 884 """"DBSubnetGroup": { 885 "VpcId": "{{ subnet_group.vpc_id }}", 886 "SubnetGroupStatus": "{{ subnet_group.status }}", 887 "DBSubnetGroupDescription": "{{ subnet_group.description }}", 888 "DBSubnetGroupName": "{{ subnet_group.subnet_name }}", 889 "Subnets": { 890 "Subnet": [ 891 {% for subnet in subnet_group.subnets %}{ 892 "SubnetStatus": "Active", 893 "SubnetIdentifier": "{{ subnet.id }}", 894 "SubnetAvailabilityZone": { 895 "Name": "{{ subnet.availability_zone }}", 896 "ProvisionedIopsCapable": "false" 897 } 898 }{%- if not loop.last -%},{%- endif -%}{% endfor %} 899 ] 900 } 901 }""" 902 ) 903 return template.render(subnet_group=self) 904 905 @staticmethod 906 def cloudformation_name_type(): 907 return "DBSubnetGroupName" 908 909 @staticmethod 910 def cloudformation_type(): 911 # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbsubnetgroup.html 912 return "AWS::RDS::DBSubnetGroup" 913 914 @classmethod 915 def create_from_cloudformation_json( 916 cls, resource_name, cloudformation_json, region_name, **kwargs 917 ): 918 properties = cloudformation_json["Properties"] 919 920 description = properties["DBSubnetGroupDescription"] 921 subnet_ids = properties["SubnetIds"] 922 tags = properties.get("Tags") 923 924 ec2_backend = ec2_backends[region_name] 925 subnets = [ec2_backend.get_subnet(subnet_id) for subnet_id in subnet_ids] 926 rds2_backend = rds2_backends[region_name] 927 subnet_group = rds2_backend.create_subnet_group( 928 resource_name, description, subnets, tags 929 ) 930 return subnet_group 931 932 def get_tags(self): 933 return self.tags 934 935 def add_tags(self, tags): 936 new_keys = [tag_set["Key"] for tag_set in tags] 937 self.tags = [tag_set for tag_set in self.tags if tag_set["Key"] not in new_keys] 938 self.tags.extend(tags) 939 return self.tags 940 941 def remove_tags(self, tag_keys): 942 self.tags = [tag_set for tag_set in self.tags if tag_set["Key"] not in tag_keys] 943 944 def delete(self, region_name): 945 backend = rds2_backends[region_name] 946 backend.delete_subnet_group(self.subnet_name) 947 948 949class RDS2Backend(BaseBackend): 950 def __init__(self, region): 951 self.region = region 952 self.arn_regex = re_compile( 953 r"^arn:aws:rds:.*:[0-9]*:(db|es|og|pg|ri|secgrp|snapshot|subgrp):.*$" 954 ) 955 self.clusters = OrderedDict() 956 self.databases = OrderedDict() 957 self.snapshots = OrderedDict() 958 self.db_parameter_groups = {} 959 self.option_groups = {} 960 self.security_groups = {} 961 self.subnet_groups = {} 962 963 def reset(self): 964 # preserve region 965 region = self.region 966 self.__dict__ = {} 967 self.__init__(region) 968 969 @staticmethod 970 def default_vpc_endpoint_service(service_region, zones): 971 """Default VPC endpoint service.""" 972 return BaseBackend.default_vpc_endpoint_service_factory( 973 service_region, zones, "rds" 974 ) + BaseBackend.default_vpc_endpoint_service_factory( 975 service_region, zones, "rds-data" 976 ) 977 978 def create_database(self, db_kwargs): 979 database_id = db_kwargs["db_instance_identifier"] 980 database = Database(**db_kwargs) 981 self.databases[database_id] = database 982 return database 983 984 def create_snapshot( 985 self, db_instance_identifier, db_snapshot_identifier, tags=None 986 ): 987 database = self.databases.get(db_instance_identifier) 988 if not database: 989 raise DBInstanceNotFoundError(db_instance_identifier) 990 if db_snapshot_identifier in self.snapshots: 991 raise DBSnapshotAlreadyExistsError(db_snapshot_identifier) 992 if len(self.snapshots) >= int(os.environ.get("MOTO_RDS_SNAPSHOT_LIMIT", "100")): 993 raise SnapshotQuotaExceededError() 994 if tags is None: 995 tags = list() 996 if database.copy_tags_to_snapshot and not tags: 997 tags = database.get_tags() 998 snapshot = Snapshot(database, db_snapshot_identifier, tags) 999 self.snapshots[db_snapshot_identifier] = snapshot 1000 return snapshot 1001 1002 def delete_snapshot(self, db_snapshot_identifier): 1003 if db_snapshot_identifier not in self.snapshots: 1004 raise DBSnapshotNotFoundError(db_snapshot_identifier) 1005 1006 return self.snapshots.pop(db_snapshot_identifier) 1007 1008 def create_database_replica(self, db_kwargs): 1009 database_id = db_kwargs["db_instance_identifier"] 1010 source_database_id = db_kwargs["source_db_identifier"] 1011 primary = self.find_db_from_id(source_database_id) 1012 if self.arn_regex.match(source_database_id): 1013 db_kwargs["region"] = self.region 1014 1015 # Shouldn't really copy here as the instance is duplicated. RDS replicas have different instances. 1016 replica = copy.copy(primary) 1017 replica.update(db_kwargs) 1018 replica.set_as_replica() 1019 self.databases[database_id] = replica 1020 primary.add_replica(replica) 1021 return replica 1022 1023 def describe_databases(self, db_instance_identifier=None, filters=None): 1024 databases = self.databases 1025 if db_instance_identifier: 1026 filters = merge_filters( 1027 filters, {"db-instance-id": [db_instance_identifier]} 1028 ) 1029 if filters: 1030 databases = self._filter_resources(databases, filters, Database) 1031 if db_instance_identifier and not databases: 1032 raise DBInstanceNotFoundError(db_instance_identifier) 1033 return list(databases.values()) 1034 1035 def describe_snapshots( 1036 self, db_instance_identifier, db_snapshot_identifier, filters=None 1037 ): 1038 snapshots = self.snapshots 1039 if db_instance_identifier: 1040 filters = merge_filters( 1041 filters, {"db-instance-id": [db_instance_identifier]} 1042 ) 1043 if db_snapshot_identifier: 1044 filters = merge_filters( 1045 filters, {"db-snapshot-id": [db_snapshot_identifier]} 1046 ) 1047 if filters: 1048 snapshots = self._filter_resources(snapshots, filters, Snapshot) 1049 if db_snapshot_identifier and not snapshots and not db_instance_identifier: 1050 raise DBSnapshotNotFoundError(db_snapshot_identifier) 1051 return list(snapshots.values()) 1052 1053 def modify_database(self, db_instance_identifier, db_kwargs): 1054 database = self.describe_databases(db_instance_identifier)[0] 1055 if "new_db_instance_identifier" in db_kwargs: 1056 del self.databases[db_instance_identifier] 1057 db_instance_identifier = db_kwargs[ 1058 "db_instance_identifier" 1059 ] = db_kwargs.pop("new_db_instance_identifier") 1060 self.databases[db_instance_identifier] = database 1061 database.update(db_kwargs) 1062 return database 1063 1064 def reboot_db_instance(self, db_instance_identifier): 1065 database = self.describe_databases(db_instance_identifier)[0] 1066 return database 1067 1068 def restore_db_instance_from_db_snapshot(self, from_snapshot_id, overrides): 1069 snapshot = self.describe_snapshots( 1070 db_instance_identifier=None, db_snapshot_identifier=from_snapshot_id 1071 )[0] 1072 original_database = snapshot.database 1073 new_instance_props = copy.deepcopy(original_database.__dict__) 1074 if not original_database.option_group_supplied: 1075 # If the option group is not supplied originally, the 'option_group_name' will receive a default value 1076 # Force this reconstruction, and prevent any validation on the default value 1077 del new_instance_props["option_group_name"] 1078 1079 for key, value in overrides.items(): 1080 if value: 1081 new_instance_props[key] = value 1082 1083 return self.create_database(new_instance_props) 1084 1085 def stop_database(self, db_instance_identifier, db_snapshot_identifier=None): 1086 database = self.describe_databases(db_instance_identifier)[0] 1087 # todo: certain rds types not allowed to be stopped at this time. 1088 # https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_StopInstance.html#USER_StopInstance.Limitations 1089 if database.is_replica or ( 1090 database.multi_az and database.engine.lower().startswith("sqlserver") 1091 ): 1092 # todo: more db types not supported by stop/start instance api 1093 raise InvalidDBClusterStateFaultError(db_instance_identifier) 1094 if database.status != "available": 1095 raise InvalidDBInstanceStateError(db_instance_identifier, "stop") 1096 if db_snapshot_identifier: 1097 self.create_snapshot(db_instance_identifier, db_snapshot_identifier) 1098 database.status = "stopped" 1099 return database 1100 1101 def start_database(self, db_instance_identifier): 1102 database = self.describe_databases(db_instance_identifier)[0] 1103 # todo: bunch of different error messages to be generated from this api call 1104 if database.status != "stopped": 1105 raise InvalidDBInstanceStateError(db_instance_identifier, "start") 1106 database.status = "available" 1107 return database 1108 1109 def find_db_from_id(self, db_id): 1110 if self.arn_regex.match(db_id): 1111 arn_breakdown = db_id.split(":") 1112 region = arn_breakdown[3] 1113 backend = rds2_backends[region] 1114 db_name = arn_breakdown[-1] 1115 else: 1116 backend = self 1117 db_name = db_id 1118 1119 return backend.describe_databases(db_name)[0] 1120 1121 def delete_database(self, db_instance_identifier, db_snapshot_name=None): 1122 if db_instance_identifier in self.databases: 1123 if db_snapshot_name: 1124 self.create_snapshot(db_instance_identifier, db_snapshot_name) 1125 database = self.databases.pop(db_instance_identifier) 1126 if database.is_replica: 1127 primary = self.find_db_from_id(database.source_db_identifier) 1128 primary.remove_replica(database) 1129 database.status = "deleting" 1130 return database 1131 else: 1132 raise DBInstanceNotFoundError(db_instance_identifier) 1133 1134 def create_security_group(self, group_name, description, tags): 1135 security_group = SecurityGroup(group_name, description, tags) 1136 self.security_groups[group_name] = security_group 1137 return security_group 1138 1139 def describe_security_groups(self, security_group_name): 1140 if security_group_name: 1141 if security_group_name in self.security_groups: 1142 return [self.security_groups[security_group_name]] 1143 else: 1144 raise DBSecurityGroupNotFoundError(security_group_name) 1145 return self.security_groups.values() 1146 1147 def delete_security_group(self, security_group_name): 1148 if security_group_name in self.security_groups: 1149 return self.security_groups.pop(security_group_name) 1150 else: 1151 raise DBSecurityGroupNotFoundError(security_group_name) 1152 1153 def delete_db_parameter_group(self, db_parameter_group_name): 1154 if db_parameter_group_name in self.db_parameter_groups: 1155 return self.db_parameter_groups.pop(db_parameter_group_name) 1156 else: 1157 raise DBParameterGroupNotFoundError(db_parameter_group_name) 1158 1159 def authorize_security_group(self, security_group_name, cidr_ip): 1160 security_group = self.describe_security_groups(security_group_name)[0] 1161 security_group.authorize_cidr(cidr_ip) 1162 return security_group 1163 1164 def create_subnet_group(self, subnet_name, description, subnets, tags): 1165 subnet_group = SubnetGroup(subnet_name, description, subnets, tags) 1166 self.subnet_groups[subnet_name] = subnet_group 1167 return subnet_group 1168 1169 def describe_subnet_groups(self, subnet_group_name): 1170 if subnet_group_name: 1171 if subnet_group_name in self.subnet_groups: 1172 return [self.subnet_groups[subnet_group_name]] 1173 else: 1174 raise DBSubnetGroupNotFoundError(subnet_group_name) 1175 return self.subnet_groups.values() 1176 1177 def modify_db_subnet_group(self, subnet_name, description, subnets): 1178 subnet_group = self.subnet_groups.pop(subnet_name) 1179 if not subnet_group: 1180 raise DBSubnetGroupNotFoundError(subnet_name) 1181 subnet_group.subnet_name = subnet_name 1182 subnet_group.subnets = subnets 1183 if description is not None: 1184 subnet_group.description = description 1185 return subnet_group 1186 1187 def delete_subnet_group(self, subnet_name): 1188 if subnet_name in self.subnet_groups: 1189 return self.subnet_groups.pop(subnet_name) 1190 else: 1191 raise DBSubnetGroupNotFoundError(subnet_name) 1192 1193 def create_option_group(self, option_group_kwargs): 1194 option_group_id = option_group_kwargs["name"] 1195 valid_option_group_engines = { 1196 "mariadb": ["10.0", "10.1", "10.2", "10.3"], 1197 "mysql": ["5.5", "5.6", "5.7", "8.0"], 1198 "oracle-se2": ["11.2", "12.1", "12.2"], 1199 "oracle-se1": ["11.2", "12.1", "12.2"], 1200 "oracle-se": ["11.2", "12.1", "12.2"], 1201 "oracle-ee": ["11.2", "12.1", "12.2"], 1202 "sqlserver-se": ["10.50", "11.00"], 1203 "sqlserver-ee": ["10.50", "11.00"], 1204 "sqlserver-ex": ["10.50", "11.00"], 1205 "sqlserver-web": ["10.50", "11.00"], 1206 } 1207 if option_group_kwargs["name"] in self.option_groups: 1208 raise RDSClientError( 1209 "OptionGroupAlreadyExistsFault", 1210 "An option group named {0} already exists.".format( 1211 option_group_kwargs["name"] 1212 ), 1213 ) 1214 if ( 1215 "description" not in option_group_kwargs 1216 or not option_group_kwargs["description"] 1217 ): 1218 raise RDSClientError( 1219 "InvalidParameterValue", 1220 "The parameter OptionGroupDescription must be provided and must not be blank.", 1221 ) 1222 if option_group_kwargs["engine_name"] not in valid_option_group_engines.keys(): 1223 raise RDSClientError( 1224 "InvalidParameterValue", "Invalid DB engine: non-existent" 1225 ) 1226 if ( 1227 option_group_kwargs["major_engine_version"] 1228 not in valid_option_group_engines[option_group_kwargs["engine_name"]] 1229 ): 1230 raise RDSClientError( 1231 "InvalidParameterCombination", 1232 "Cannot find major version {0} for {1}".format( 1233 option_group_kwargs["major_engine_version"], 1234 option_group_kwargs["engine_name"], 1235 ), 1236 ) 1237 option_group = OptionGroup(**option_group_kwargs) 1238 self.option_groups[option_group_id] = option_group 1239 return option_group 1240 1241 def delete_option_group(self, option_group_name): 1242 if option_group_name in self.option_groups: 1243 return self.option_groups.pop(option_group_name) 1244 else: 1245 raise OptionGroupNotFoundFaultError(option_group_name) 1246 1247 def describe_option_groups(self, option_group_kwargs): 1248 option_group_list = [] 1249 1250 if option_group_kwargs["marker"]: 1251 marker = option_group_kwargs["marker"] 1252 else: 1253 marker = 0 1254 if option_group_kwargs["max_records"]: 1255 if ( 1256 option_group_kwargs["max_records"] < 20 1257 or option_group_kwargs["max_records"] > 100 1258 ): 1259 raise RDSClientError( 1260 "InvalidParameterValue", 1261 "Invalid value for max records. Must be between 20 and 100", 1262 ) 1263 max_records = option_group_kwargs["max_records"] 1264 else: 1265 max_records = 100 1266 1267 for option_group_name, option_group in self.option_groups.items(): 1268 if ( 1269 option_group_kwargs["name"] 1270 and option_group.name != option_group_kwargs["name"] 1271 ): 1272 continue 1273 elif ( 1274 option_group_kwargs["engine_name"] 1275 and option_group.engine_name != option_group_kwargs["engine_name"] 1276 ): 1277 continue 1278 elif ( 1279 option_group_kwargs["major_engine_version"] 1280 and option_group.major_engine_version 1281 != option_group_kwargs["major_engine_version"] 1282 ): 1283 continue 1284 else: 1285 option_group_list.append(option_group) 1286 if not len(option_group_list): 1287 raise OptionGroupNotFoundFaultError(option_group_kwargs["name"]) 1288 return option_group_list[marker : max_records + marker] 1289 1290 @staticmethod 1291 def describe_option_group_options(engine_name, major_engine_version=None): 1292 default_option_group_options = { 1293 "mysql": { 1294 "5.6": '<DescribeOptionGroupOptionsResponse xmlns="http://rds.amazonaws.com/doc/2014-09-01/">\n <DescribeOptionGroupOptionsResult>\n <OptionGroupOptions>\n \n <OptionGroupOption><MajorEngineVersion>5.6</MajorEngineVersion><DefaultPort>11211</DefaultPort><PortRequired>True</PortRequired><OptionsDependedOn></OptionsDependedOn><Description>Innodb Memcached for MySQL</Description><Name>MEMCACHED</Name><OptionGroupOptionSettings><OptionGroupOptionSetting><AllowedValues>1-4294967295</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>1</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies how many memcached read operations (get) to perform before doing a COMMIT to start a new transaction</SettingDescription><SettingName>DAEMON_MEMCACHED_R_BATCH_SIZE</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>1-4294967295</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>1</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies how many memcached write operations, such as add, set, or incr, to perform before doing a COMMIT to start a new transaction</SettingDescription><SettingName>DAEMON_MEMCACHED_W_BATCH_SIZE</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>1-1073741824</AllowedValues><ApplyType>DYNAMIC</ApplyType><DefaultValue>5</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies how often to auto-commit idle connections that use the InnoDB memcached interface.</SettingDescription><SettingName>INNODB_API_BK_COMMIT_INTERVAL</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>0,1</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>0</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Disables the use of row locks when using the InnoDB memcached interface.</SettingDescription><SettingName>INNODB_API_DISABLE_ROWLOCK</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>0,1</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>0</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Locks the table used by the InnoDB memcached plugin, so that it cannot be dropped or altered by DDL through the SQL interface.</SettingDescription><SettingName>INNODB_API_ENABLE_MDL</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>0-3</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>0</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Lets you control the transaction isolation level on queries processed by the memcached interface.</SettingDescription><SettingName>INNODB_API_TRX_LEVEL</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>auto,ascii,binary</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>auto</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>The binding protocol to use which can be either auto, ascii, or binary. The default is auto which means the server automatically negotiates the protocol with the client.</SettingDescription><SettingName>BINDING_PROTOCOL</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>1-2048</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>1024</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>The backlog queue configures how many network connections can be waiting to be processed by memcached</SettingDescription><SettingName>BACKLOG_QUEUE_LIMIT</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>0,1</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>0</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Disable the use of compare and swap (CAS) which reduces the per-item size by 8 bytes.</SettingDescription><SettingName>CAS_DISABLED</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>1-48</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>48</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Minimum chunk size in bytes to allocate for the smallest item\'s key, value, and flags. The default is 48 and you can get a significant memory efficiency gain with a lower value.</SettingDescription><SettingName>CHUNK_SIZE</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>1-2</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>1.25</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Chunk size growth factor that controls the size of each successive chunk with each chunk growing times this amount larger than the previous chunk.</SettingDescription><SettingName>CHUNK_SIZE_GROWTH_FACTOR</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>0,1</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>0</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>If enabled when there is no more memory to store items, memcached will return an error rather than evicting items.</SettingDescription><SettingName>ERROR_ON_MEMORY_EXHAUSTED</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>10-1024</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>1024</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Maximum number of concurrent connections. Setting this value to anything less than 10 prevents MySQL from starting.</SettingDescription><SettingName>MAX_SIMULTANEOUS_CONNECTIONS</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>v,vv,vvv</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>v</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Verbose level for memcached.</SettingDescription><SettingName>VERBOSITY</SettingName></OptionGroupOptionSetting></OptionGroupOptionSettings><EngineName>mysql</EngineName></OptionGroupOption>\n \n </OptionGroupOptions>\n </DescribeOptionGroupOptionsResult>\n <ResponseMetadata>\n <RequestId>457f7bb8-9fbf-11e4-9084-5754f80d5144</RequestId>\n </ResponseMetadata>\n</DescribeOptionGroupOptionsResponse>', 1295 "all": '<DescribeOptionGroupOptionsResponse xmlns="http://rds.amazonaws.com/doc/2014-09-01/">\n <DescribeOptionGroupOptionsResult>\n <OptionGroupOptions>\n \n <OptionGroupOption><MajorEngineVersion>5.6</MajorEngineVersion><DefaultPort>11211</DefaultPort><PortRequired>True</PortRequired><OptionsDependedOn></OptionsDependedOn><Description>Innodb Memcached for MySQL</Description><Name>MEMCACHED</Name><OptionGroupOptionSettings><OptionGroupOptionSetting><AllowedValues>1-4294967295</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>1</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies how many memcached read operations (get) to perform before doing a COMMIT to start a new transaction</SettingDescription><SettingName>DAEMON_MEMCACHED_R_BATCH_SIZE</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>1-4294967295</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>1</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies how many memcached write operations, such as add, set, or incr, to perform before doing a COMMIT to start a new transaction</SettingDescription><SettingName>DAEMON_MEMCACHED_W_BATCH_SIZE</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>1-1073741824</AllowedValues><ApplyType>DYNAMIC</ApplyType><DefaultValue>5</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies how often to auto-commit idle connections that use the InnoDB memcached interface.</SettingDescription><SettingName>INNODB_API_BK_COMMIT_INTERVAL</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>0,1</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>0</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Disables the use of row locks when using the InnoDB memcached interface.</SettingDescription><SettingName>INNODB_API_DISABLE_ROWLOCK</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>0,1</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>0</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Locks the table used by the InnoDB memcached plugin, so that it cannot be dropped or altered by DDL through the SQL interface.</SettingDescription><SettingName>INNODB_API_ENABLE_MDL</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>0-3</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>0</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Lets you control the transaction isolation level on queries processed by the memcached interface.</SettingDescription><SettingName>INNODB_API_TRX_LEVEL</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>auto,ascii,binary</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>auto</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>The binding protocol to use which can be either auto, ascii, or binary. The default is auto which means the server automatically negotiates the protocol with the client.</SettingDescription><SettingName>BINDING_PROTOCOL</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>1-2048</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>1024</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>The backlog queue configures how many network connections can be waiting to be processed by memcached</SettingDescription><SettingName>BACKLOG_QUEUE_LIMIT</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>0,1</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>0</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Disable the use of compare and swap (CAS) which reduces the per-item size by 8 bytes.</SettingDescription><SettingName>CAS_DISABLED</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>1-48</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>48</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Minimum chunk size in bytes to allocate for the smallest item\'s key, value, and flags. The default is 48 and you can get a significant memory efficiency gain with a lower value.</SettingDescription><SettingName>CHUNK_SIZE</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>1-2</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>1.25</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Chunk size growth factor that controls the size of each successive chunk with each chunk growing times this amount larger than the previous chunk.</SettingDescription><SettingName>CHUNK_SIZE_GROWTH_FACTOR</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>0,1</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>0</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>If enabled when there is no more memory to store items, memcached will return an error rather than evicting items.</SettingDescription><SettingName>ERROR_ON_MEMORY_EXHAUSTED</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>10-1024</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>1024</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Maximum number of concurrent connections. Setting this value to anything less than 10 prevents MySQL from starting.</SettingDescription><SettingName>MAX_SIMULTANEOUS_CONNECTIONS</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>v,vv,vvv</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>v</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Verbose level for memcached.</SettingDescription><SettingName>VERBOSITY</SettingName></OptionGroupOptionSetting></OptionGroupOptionSettings><EngineName>mysql</EngineName></OptionGroupOption>\n \n </OptionGroupOptions>\n </DescribeOptionGroupOptionsResult>\n <ResponseMetadata>\n <RequestId>457f7bb8-9fbf-11e4-9084-5754f80d5144</RequestId>\n </ResponseMetadata>\n</DescribeOptionGroupOptionsResponse>', 1296 }, 1297 "oracle-ee": { 1298 "11.2": '<DescribeOptionGroupOptionsResponse xmlns="http://rds.amazonaws.com/doc/2014-09-01/">\n <DescribeOptionGroupOptionsResult>\n <OptionGroupOptions>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn><OptionName>XMLDB</OptionName></OptionsDependedOn><Description>Oracle Application Express Runtime Environment</Description><Name>APEX</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn><OptionName>APEX</OptionName></OptionsDependedOn><Description>Oracle Application Express Development Environment</Description><Name>APEX-DEV</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>Oracle Advanced Security - Native Network Encryption</Description><Name>NATIVE_NETWORK_ENCRYPTION</Name><OptionGroupOptionSettings><OptionGroupOptionSetting><AllowedValues>ACCEPTED,REJECTED,REQUESTED,REQUIRED</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>REQUESTED</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies the desired encryption behavior</SettingDescription><SettingName>SQLNET.ENCRYPTION_SERVER</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>ACCEPTED,REJECTED,REQUESTED,REQUIRED</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>REQUESTED</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies the desired data integrity behavior</SettingDescription><SettingName>SQLNET.CRYPTO_CHECKSUM_SERVER</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>RC4_256,AES256,AES192,3DES168,RC4_128,AES128,3DES112,RC4_56,DES,RC4_40,DES40</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>RC4_256,AES256,AES192,3DES168,RC4_128,AES128,3DES112,RC4_56,DES,RC4_40,DES40</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies list of encryption algorithms in order of intended use</SettingDescription><SettingName>SQLNET.ENCRYPTION_TYPES_SERVER</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>SHA1,MD5</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>SHA1,MD5</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies list of checksumming algorithms in order of intended use</SettingDescription><SettingName>SQLNET.CRYPTO_CHECKSUM_TYPES_SERVER</SettingName></OptionGroupOptionSetting></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><DefaultPort>1158</DefaultPort><PortRequired>True</PortRequired><OptionsDependedOn></OptionsDependedOn><Description>Oracle Enterprise Manager (Database Control only)</Description><Name>OEM</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>Oracle Statspack</Description><Name>STATSPACK</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Permanent>True</Permanent><Description>Oracle Advanced Security - Transparent Data Encryption</Description><Name>TDE</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Permanent>True</Permanent><Description>Oracle Advanced Security - TDE with HSM</Description><Name>TDE_HSM</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Permanent>True</Permanent><Description>Change time zone</Description><Name>Timezone</Name><OptionGroupOptionSettings><OptionGroupOptionSetting><AllowedValues>Africa/Cairo,Africa/Casablanca,Africa/Harare,Africa/Monrovia,Africa/Nairobi,Africa/Tripoli,Africa/Windhoek,America/Araguaina,America/Asuncion,America/Bogota,America/Caracas,America/Chihuahua,America/Cuiaba,America/Denver,America/Fortaleza,America/Guatemala,America/Halifax,America/Manaus,America/Matamoros,America/Monterrey,America/Montevideo,America/Phoenix,America/Santiago,America/Tijuana,Asia/Amman,Asia/Ashgabat,Asia/Baghdad,Asia/Baku,Asia/Bangkok,Asia/Beirut,Asia/Calcutta,Asia/Damascus,Asia/Dhaka,Asia/Irkutsk,Asia/Jerusalem,Asia/Kabul,Asia/Karachi,Asia/Kathmandu,Asia/Krasnoyarsk,Asia/Magadan,Asia/Muscat,Asia/Novosibirsk,Asia/Riyadh,Asia/Seoul,Asia/Shanghai,Asia/Singapore,Asia/Taipei,Asia/Tehran,Asia/Tokyo,Asia/Ulaanbaatar,Asia/Vladivostok,Asia/Yakutsk,Asia/Yerevan,Atlantic/Azores,Australia/Adelaide,Australia/Brisbane,Australia/Darwin,Australia/Hobart,Australia/Perth,Australia/Sydney,Brazil/East,Canada/Newfoundland,Canada/Saskatchewan,Europe/Amsterdam,Europe/Athens,Europe/Dublin,Europe/Helsinki,Europe/Istanbul,Europe/Kaliningrad,Europe/Moscow,Europe/Paris,Europe/Prague,Europe/Sarajevo,Pacific/Auckland,Pacific/Fiji,Pacific/Guam,Pacific/Honolulu,Pacific/Samoa,US/Alaska,US/Central,US/Eastern,US/East-Indiana,US/Pacific,UTC</AllowedValues><ApplyType>DYNAMIC</ApplyType><DefaultValue>UTC</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies the timezone the user wants to change the system time to</SettingDescription><SettingName>TIME_ZONE</SettingName></OptionGroupOptionSetting></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>Oracle XMLDB Repository</Description><Name>XMLDB</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n </OptionGroupOptions>\n </DescribeOptionGroupOptionsResult>\n <ResponseMetadata>\n <RequestId>457f7bb8-9fbf-11e4-9084-5754f80d5144</RequestId>\n </ResponseMetadata>\n</DescribeOptionGroupOptionsResponse>', 1299 "all": '<DescribeOptionGroupOptionsResponse xmlns="http://rds.amazonaws.com/doc/2014-09-01/">\n <DescribeOptionGroupOptionsResult>\n <OptionGroupOptions>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn><OptionName>XMLDB</OptionName></OptionsDependedOn><Description>Oracle Application Express Runtime Environment</Description><Name>APEX</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn><OptionName>APEX</OptionName></OptionsDependedOn><Description>Oracle Application Express Development Environment</Description><Name>APEX-DEV</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>Oracle Advanced Security - Native Network Encryption</Description><Name>NATIVE_NETWORK_ENCRYPTION</Name><OptionGroupOptionSettings><OptionGroupOptionSetting><AllowedValues>ACCEPTED,REJECTED,REQUESTED,REQUIRED</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>REQUESTED</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies the desired encryption behavior</SettingDescription><SettingName>SQLNET.ENCRYPTION_SERVER</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>ACCEPTED,REJECTED,REQUESTED,REQUIRED</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>REQUESTED</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies the desired data integrity behavior</SettingDescription><SettingName>SQLNET.CRYPTO_CHECKSUM_SERVER</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>RC4_256,AES256,AES192,3DES168,RC4_128,AES128,3DES112,RC4_56,DES,RC4_40,DES40</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>RC4_256,AES256,AES192,3DES168,RC4_128,AES128,3DES112,RC4_56,DES,RC4_40,DES40</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies list of encryption algorithms in order of intended use</SettingDescription><SettingName>SQLNET.ENCRYPTION_TYPES_SERVER</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>SHA1,MD5</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>SHA1,MD5</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies list of checksumming algorithms in order of intended use</SettingDescription><SettingName>SQLNET.CRYPTO_CHECKSUM_TYPES_SERVER</SettingName></OptionGroupOptionSetting></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><DefaultPort>1158</DefaultPort><PortRequired>True</PortRequired><OptionsDependedOn></OptionsDependedOn><Description>Oracle Enterprise Manager (Database Control only)</Description><Name>OEM</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>Oracle Statspack</Description><Name>STATSPACK</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Permanent>True</Permanent><Description>Oracle Advanced Security - Transparent Data Encryption</Description><Name>TDE</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Permanent>True</Permanent><Description>Oracle Advanced Security - TDE with HSM</Description><Name>TDE_HSM</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Permanent>True</Permanent><Description>Change time zone</Description><Name>Timezone</Name><OptionGroupOptionSettings><OptionGroupOptionSetting><AllowedValues>Africa/Cairo,Africa/Casablanca,Africa/Harare,Africa/Monrovia,Africa/Nairobi,Africa/Tripoli,Africa/Windhoek,America/Araguaina,America/Asuncion,America/Bogota,America/Caracas,America/Chihuahua,America/Cuiaba,America/Denver,America/Fortaleza,America/Guatemala,America/Halifax,America/Manaus,America/Matamoros,America/Monterrey,America/Montevideo,America/Phoenix,America/Santiago,America/Tijuana,Asia/Amman,Asia/Ashgabat,Asia/Baghdad,Asia/Baku,Asia/Bangkok,Asia/Beirut,Asia/Calcutta,Asia/Damascus,Asia/Dhaka,Asia/Irkutsk,Asia/Jerusalem,Asia/Kabul,Asia/Karachi,Asia/Kathmandu,Asia/Krasnoyarsk,Asia/Magadan,Asia/Muscat,Asia/Novosibirsk,Asia/Riyadh,Asia/Seoul,Asia/Shanghai,Asia/Singapore,Asia/Taipei,Asia/Tehran,Asia/Tokyo,Asia/Ulaanbaatar,Asia/Vladivostok,Asia/Yakutsk,Asia/Yerevan,Atlantic/Azores,Australia/Adelaide,Australia/Brisbane,Australia/Darwin,Australia/Hobart,Australia/Perth,Australia/Sydney,Brazil/East,Canada/Newfoundland,Canada/Saskatchewan,Europe/Amsterdam,Europe/Athens,Europe/Dublin,Europe/Helsinki,Europe/Istanbul,Europe/Kaliningrad,Europe/Moscow,Europe/Paris,Europe/Prague,Europe/Sarajevo,Pacific/Auckland,Pacific/Fiji,Pacific/Guam,Pacific/Honolulu,Pacific/Samoa,US/Alaska,US/Central,US/Eastern,US/East-Indiana,US/Pacific,UTC</AllowedValues><ApplyType>DYNAMIC</ApplyType><DefaultValue>UTC</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies the timezone the user wants to change the system time to</SettingDescription><SettingName>TIME_ZONE</SettingName></OptionGroupOptionSetting></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>Oracle XMLDB Repository</Description><Name>XMLDB</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n </OptionGroupOptions>\n </DescribeOptionGroupOptionsResult>\n <ResponseMetadata>\n <RequestId>457f7bb8-9fbf-11e4-9084-5754f80d5144</RequestId>\n </ResponseMetadata>\n</DescribeOptionGroupOptionsResponse>', 1300 }, 1301 "oracle-sa": { 1302 "11.2": '<DescribeOptionGroupOptionsResponse xmlns="http://rds.amazonaws.com/doc/2014-09-01/">\n <DescribeOptionGroupOptionsResult>\n <OptionGroupOptions>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn><OptionName>XMLDB</OptionName></OptionsDependedOn><Description>Oracle Application Express Runtime Environment</Description><Name>APEX</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn><OptionName>APEX</OptionName></OptionsDependedOn><Description>Oracle Application Express Development Environment</Description><Name>APEX-DEV</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>Oracle Advanced Security - Native Network Encryption</Description><Name>NATIVE_NETWORK_ENCRYPTION</Name><OptionGroupOptionSettings><OptionGroupOptionSetting><AllowedValues>ACCEPTED,REJECTED,REQUESTED,REQUIRED</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>REQUESTED</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies the desired encryption behavior</SettingDescription><SettingName>SQLNET.ENCRYPTION_SERVER</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>ACCEPTED,REJECTED,REQUESTED,REQUIRED</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>REQUESTED</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies the desired data integrity behavior</SettingDescription><SettingName>SQLNET.CRYPTO_CHECKSUM_SERVER</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>RC4_256,AES256,AES192,3DES168,RC4_128,AES128,3DES112,RC4_56,DES,RC4_40,DES40</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>RC4_256,AES256,AES192,3DES168,RC4_128,AES128,3DES112,RC4_56,DES,RC4_40,DES40</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies list of encryption algorithms in order of intended use</SettingDescription><SettingName>SQLNET.ENCRYPTION_TYPES_SERVER</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>SHA1,MD5</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>SHA1,MD5</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies list of checksumming algorithms in order of intended use</SettingDescription><SettingName>SQLNET.CRYPTO_CHECKSUM_TYPES_SERVER</SettingName></OptionGroupOptionSetting></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><DefaultPort>1158</DefaultPort><PortRequired>True</PortRequired><OptionsDependedOn></OptionsDependedOn><Description>Oracle Enterprise Manager (Database Control only)</Description><Name>OEM</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>Oracle Statspack</Description><Name>STATSPACK</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Permanent>True</Permanent><Description>Oracle Advanced Security - Transparent Data Encryption</Description><Name>TDE</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Permanent>True</Permanent><Description>Oracle Advanced Security - TDE with HSM</Description><Name>TDE_HSM</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Permanent>True</Permanent><Description>Change time zone</Description><Name>Timezone</Name><OptionGroupOptionSettings><OptionGroupOptionSetting><AllowedValues>Africa/Cairo,Africa/Casablanca,Africa/Harare,Africa/Monrovia,Africa/Nairobi,Africa/Tripoli,Africa/Windhoek,America/Araguaina,America/Asuncion,America/Bogota,America/Caracas,America/Chihuahua,America/Cuiaba,America/Denver,America/Fortaleza,America/Guatemala,America/Halifax,America/Manaus,America/Matamoros,America/Monterrey,America/Montevideo,America/Phoenix,America/Santiago,America/Tijuana,Asia/Amman,Asia/Ashgabat,Asia/Baghdad,Asia/Baku,Asia/Bangkok,Asia/Beirut,Asia/Calcutta,Asia/Damascus,Asia/Dhaka,Asia/Irkutsk,Asia/Jerusalem,Asia/Kabul,Asia/Karachi,Asia/Kathmandu,Asia/Krasnoyarsk,Asia/Magadan,Asia/Muscat,Asia/Novosibirsk,Asia/Riyadh,Asia/Seoul,Asia/Shanghai,Asia/Singapore,Asia/Taipei,Asia/Tehran,Asia/Tokyo,Asia/Ulaanbaatar,Asia/Vladivostok,Asia/Yakutsk,Asia/Yerevan,Atlantic/Azores,Australia/Adelaide,Australia/Brisbane,Australia/Darwin,Australia/Hobart,Australia/Perth,Australia/Sydney,Brazil/East,Canada/Newfoundland,Canada/Saskatchewan,Europe/Amsterdam,Europe/Athens,Europe/Dublin,Europe/Helsinki,Europe/Istanbul,Europe/Kaliningrad,Europe/Moscow,Europe/Paris,Europe/Prague,Europe/Sarajevo,Pacific/Auckland,Pacific/Fiji,Pacific/Guam,Pacific/Honolulu,Pacific/Samoa,US/Alaska,US/Central,US/Eastern,US/East-Indiana,US/Pacific,UTC</AllowedValues><ApplyType>DYNAMIC</ApplyType><DefaultValue>UTC</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies the timezone the user wants to change the system time to</SettingDescription><SettingName>TIME_ZONE</SettingName></OptionGroupOptionSetting></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>Oracle XMLDB Repository</Description><Name>XMLDB</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n </OptionGroupOptions>\n </DescribeOptionGroupOptionsResult>\n <ResponseMetadata>\n <RequestId>457f7bb8-9fbf-11e4-9084-5754f80d5144</RequestId>\n </ResponseMetadata>\n</DescribeOptionGroupOptionsResponse>', 1303 "all": '<DescribeOptionGroupOptionsResponse xmlns="http://rds.amazonaws.com/doc/2014-09-01/">\n <DescribeOptionGroupOptionsResult>\n <OptionGroupOptions>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn><OptionName>XMLDB</OptionName></OptionsDependedOn><Description>Oracle Application Express Runtime Environment</Description><Name>APEX</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn><OptionName>APEX</OptionName></OptionsDependedOn><Description>Oracle Application Express Development Environment</Description><Name>APEX-DEV</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>Oracle Advanced Security - Native Network Encryption</Description><Name>NATIVE_NETWORK_ENCRYPTION</Name><OptionGroupOptionSettings><OptionGroupOptionSetting><AllowedValues>ACCEPTED,REJECTED,REQUESTED,REQUIRED</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>REQUESTED</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies the desired encryption behavior</SettingDescription><SettingName>SQLNET.ENCRYPTION_SERVER</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>ACCEPTED,REJECTED,REQUESTED,REQUIRED</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>REQUESTED</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies the desired data integrity behavior</SettingDescription><SettingName>SQLNET.CRYPTO_CHECKSUM_SERVER</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>RC4_256,AES256,AES192,3DES168,RC4_128,AES128,3DES112,RC4_56,DES,RC4_40,DES40</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>RC4_256,AES256,AES192,3DES168,RC4_128,AES128,3DES112,RC4_56,DES,RC4_40,DES40</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies list of encryption algorithms in order of intended use</SettingDescription><SettingName>SQLNET.ENCRYPTION_TYPES_SERVER</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>SHA1,MD5</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>SHA1,MD5</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies list of checksumming algorithms in order of intended use</SettingDescription><SettingName>SQLNET.CRYPTO_CHECKSUM_TYPES_SERVER</SettingName></OptionGroupOptionSetting></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><DefaultPort>1158</DefaultPort><PortRequired>True</PortRequired><OptionsDependedOn></OptionsDependedOn><Description>Oracle Enterprise Manager (Database Control only)</Description><Name>OEM</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>Oracle Statspack</Description><Name>STATSPACK</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Permanent>True</Permanent><Description>Oracle Advanced Security - Transparent Data Encryption</Description><Name>TDE</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Permanent>True</Permanent><Description>Oracle Advanced Security - TDE with HSM</Description><Name>TDE_HSM</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Permanent>True</Permanent><Description>Change time zone</Description><Name>Timezone</Name><OptionGroupOptionSettings><OptionGroupOptionSetting><AllowedValues>Africa/Cairo,Africa/Casablanca,Africa/Harare,Africa/Monrovia,Africa/Nairobi,Africa/Tripoli,Africa/Windhoek,America/Araguaina,America/Asuncion,America/Bogota,America/Caracas,America/Chihuahua,America/Cuiaba,America/Denver,America/Fortaleza,America/Guatemala,America/Halifax,America/Manaus,America/Matamoros,America/Monterrey,America/Montevideo,America/Phoenix,America/Santiago,America/Tijuana,Asia/Amman,Asia/Ashgabat,Asia/Baghdad,Asia/Baku,Asia/Bangkok,Asia/Beirut,Asia/Calcutta,Asia/Damascus,Asia/Dhaka,Asia/Irkutsk,Asia/Jerusalem,Asia/Kabul,Asia/Karachi,Asia/Kathmandu,Asia/Krasnoyarsk,Asia/Magadan,Asia/Muscat,Asia/Novosibirsk,Asia/Riyadh,Asia/Seoul,Asia/Shanghai,Asia/Singapore,Asia/Taipei,Asia/Tehran,Asia/Tokyo,Asia/Ulaanbaatar,Asia/Vladivostok,Asia/Yakutsk,Asia/Yerevan,Atlantic/Azores,Australia/Adelaide,Australia/Brisbane,Australia/Darwin,Australia/Hobart,Australia/Perth,Australia/Sydney,Brazil/East,Canada/Newfoundland,Canada/Saskatchewan,Europe/Amsterdam,Europe/Athens,Europe/Dublin,Europe/Helsinki,Europe/Istanbul,Europe/Kaliningrad,Europe/Moscow,Europe/Paris,Europe/Prague,Europe/Sarajevo,Pacific/Auckland,Pacific/Fiji,Pacific/Guam,Pacific/Honolulu,Pacific/Samoa,US/Alaska,US/Central,US/Eastern,US/East-Indiana,US/Pacific,UTC</AllowedValues><ApplyType>DYNAMIC</ApplyType><DefaultValue>UTC</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies the timezone the user wants to change the system time to</SettingDescription><SettingName>TIME_ZONE</SettingName></OptionGroupOptionSetting></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>Oracle XMLDB Repository</Description><Name>XMLDB</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n </OptionGroupOptions>\n </DescribeOptionGroupOptionsResult>\n <ResponseMetadata>\n <RequestId>457f7bb8-9fbf-11e4-9084-5754f80d5144</RequestId>\n </ResponseMetadata>\n</DescribeOptionGroupOptionsResponse>', 1304 }, 1305 "oracle-sa1": { 1306 "11.2": '<DescribeOptionGroupOptionsResponse xmlns="http://rds.amazonaws.com/doc/2014-09-01/">\n <DescribeOptionGroupOptionsResult>\n <OptionGroupOptions>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn><OptionName>XMLDB</OptionName></OptionsDependedOn><Description>Oracle Application Express Runtime Environment</Description><Name>APEX</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn><OptionName>APEX</OptionName></OptionsDependedOn><Description>Oracle Application Express Development Environment</Description><Name>APEX-DEV</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>Oracle Advanced Security - Native Network Encryption</Description><Name>NATIVE_NETWORK_ENCRYPTION</Name><OptionGroupOptionSettings><OptionGroupOptionSetting><AllowedValues>ACCEPTED,REJECTED,REQUESTED,REQUIRED</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>REQUESTED</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies the desired encryption behavior</SettingDescription><SettingName>SQLNET.ENCRYPTION_SERVER</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>ACCEPTED,REJECTED,REQUESTED,REQUIRED</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>REQUESTED</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies the desired data integrity behavior</SettingDescription><SettingName>SQLNET.CRYPTO_CHECKSUM_SERVER</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>RC4_256,AES256,AES192,3DES168,RC4_128,AES128,3DES112,RC4_56,DES,RC4_40,DES40</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>RC4_256,AES256,AES192,3DES168,RC4_128,AES128,3DES112,RC4_56,DES,RC4_40,DES40</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies list of encryption algorithms in order of intended use</SettingDescription><SettingName>SQLNET.ENCRYPTION_TYPES_SERVER</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>SHA1,MD5</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>SHA1,MD5</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies list of checksumming algorithms in order of intended use</SettingDescription><SettingName>SQLNET.CRYPTO_CHECKSUM_TYPES_SERVER</SettingName></OptionGroupOptionSetting></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><DefaultPort>1158</DefaultPort><PortRequired>True</PortRequired><OptionsDependedOn></OptionsDependedOn><Description>Oracle Enterprise Manager (Database Control only)</Description><Name>OEM</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>Oracle Statspack</Description><Name>STATSPACK</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Permanent>True</Permanent><Description>Oracle Advanced Security - Transparent Data Encryption</Description><Name>TDE</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Permanent>True</Permanent><Description>Oracle Advanced Security - TDE with HSM</Description><Name>TDE_HSM</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Permanent>True</Permanent><Description>Change time zone</Description><Name>Timezone</Name><OptionGroupOptionSettings><OptionGroupOptionSetting><AllowedValues>Africa/Cairo,Africa/Casablanca,Africa/Harare,Africa/Monrovia,Africa/Nairobi,Africa/Tripoli,Africa/Windhoek,America/Araguaina,America/Asuncion,America/Bogota,America/Caracas,America/Chihuahua,America/Cuiaba,America/Denver,America/Fortaleza,America/Guatemala,America/Halifax,America/Manaus,America/Matamoros,America/Monterrey,America/Montevideo,America/Phoenix,America/Santiago,America/Tijuana,Asia/Amman,Asia/Ashgabat,Asia/Baghdad,Asia/Baku,Asia/Bangkok,Asia/Beirut,Asia/Calcutta,Asia/Damascus,Asia/Dhaka,Asia/Irkutsk,Asia/Jerusalem,Asia/Kabul,Asia/Karachi,Asia/Kathmandu,Asia/Krasnoyarsk,Asia/Magadan,Asia/Muscat,Asia/Novosibirsk,Asia/Riyadh,Asia/Seoul,Asia/Shanghai,Asia/Singapore,Asia/Taipei,Asia/Tehran,Asia/Tokyo,Asia/Ulaanbaatar,Asia/Vladivostok,Asia/Yakutsk,Asia/Yerevan,Atlantic/Azores,Australia/Adelaide,Australia/Brisbane,Australia/Darwin,Australia/Hobart,Australia/Perth,Australia/Sydney,Brazil/East,Canada/Newfoundland,Canada/Saskatchewan,Europe/Amsterdam,Europe/Athens,Europe/Dublin,Europe/Helsinki,Europe/Istanbul,Europe/Kaliningrad,Europe/Moscow,Europe/Paris,Europe/Prague,Europe/Sarajevo,Pacific/Auckland,Pacific/Fiji,Pacific/Guam,Pacific/Honolulu,Pacific/Samoa,US/Alaska,US/Central,US/Eastern,US/East-Indiana,US/Pacific,UTC</AllowedValues><ApplyType>DYNAMIC</ApplyType><DefaultValue>UTC</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies the timezone the user wants to change the system time to</SettingDescription><SettingName>TIME_ZONE</SettingName></OptionGroupOptionSetting></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>Oracle XMLDB Repository</Description><Name>XMLDB</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n </OptionGroupOptions>\n </DescribeOptionGroupOptionsResult>\n <ResponseMetadata>\n <RequestId>457f7bb8-9fbf-11e4-9084-5754f80d5144</RequestId>\n </ResponseMetadata>\n</DescribeOptionGroupOptionsResponse>', 1307 "all": '<DescribeOptionGroupOptionsResponse xmlns="http://rds.amazonaws.com/doc/2014-09-01/">\n <DescribeOptionGroupOptionsResult>\n <OptionGroupOptions>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn><OptionName>XMLDB</OptionName></OptionsDependedOn><Description>Oracle Application Express Runtime Environment</Description><Name>APEX</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn><OptionName>APEX</OptionName></OptionsDependedOn><Description>Oracle Application Express Development Environment</Description><Name>APEX-DEV</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>Oracle Advanced Security - Native Network Encryption</Description><Name>NATIVE_NETWORK_ENCRYPTION</Name><OptionGroupOptionSettings><OptionGroupOptionSetting><AllowedValues>ACCEPTED,REJECTED,REQUESTED,REQUIRED</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>REQUESTED</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies the desired encryption behavior</SettingDescription><SettingName>SQLNET.ENCRYPTION_SERVER</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>ACCEPTED,REJECTED,REQUESTED,REQUIRED</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>REQUESTED</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies the desired data integrity behavior</SettingDescription><SettingName>SQLNET.CRYPTO_CHECKSUM_SERVER</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>RC4_256,AES256,AES192,3DES168,RC4_128,AES128,3DES112,RC4_56,DES,RC4_40,DES40</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>RC4_256,AES256,AES192,3DES168,RC4_128,AES128,3DES112,RC4_56,DES,RC4_40,DES40</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies list of encryption algorithms in order of intended use</SettingDescription><SettingName>SQLNET.ENCRYPTION_TYPES_SERVER</SettingName></OptionGroupOptionSetting><OptionGroupOptionSetting><AllowedValues>SHA1,MD5</AllowedValues><ApplyType>STATIC</ApplyType><DefaultValue>SHA1,MD5</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies list of checksumming algorithms in order of intended use</SettingDescription><SettingName>SQLNET.CRYPTO_CHECKSUM_TYPES_SERVER</SettingName></OptionGroupOptionSetting></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><DefaultPort>1158</DefaultPort><PortRequired>True</PortRequired><OptionsDependedOn></OptionsDependedOn><Description>Oracle Enterprise Manager (Database Control only)</Description><Name>OEM</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>Oracle Statspack</Description><Name>STATSPACK</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Permanent>True</Permanent><Description>Oracle Advanced Security - Transparent Data Encryption</Description><Name>TDE</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Permanent>True</Permanent><Description>Oracle Advanced Security - TDE with HSM</Description><Name>TDE_HSM</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Permanent>True</Permanent><Description>Change time zone</Description><Name>Timezone</Name><OptionGroupOptionSettings><OptionGroupOptionSetting><AllowedValues>Africa/Cairo,Africa/Casablanca,Africa/Harare,Africa/Monrovia,Africa/Nairobi,Africa/Tripoli,Africa/Windhoek,America/Araguaina,America/Asuncion,America/Bogota,America/Caracas,America/Chihuahua,America/Cuiaba,America/Denver,America/Fortaleza,America/Guatemala,America/Halifax,America/Manaus,America/Matamoros,America/Monterrey,America/Montevideo,America/Phoenix,America/Santiago,America/Tijuana,Asia/Amman,Asia/Ashgabat,Asia/Baghdad,Asia/Baku,Asia/Bangkok,Asia/Beirut,Asia/Calcutta,Asia/Damascus,Asia/Dhaka,Asia/Irkutsk,Asia/Jerusalem,Asia/Kabul,Asia/Karachi,Asia/Kathmandu,Asia/Krasnoyarsk,Asia/Magadan,Asia/Muscat,Asia/Novosibirsk,Asia/Riyadh,Asia/Seoul,Asia/Shanghai,Asia/Singapore,Asia/Taipei,Asia/Tehran,Asia/Tokyo,Asia/Ulaanbaatar,Asia/Vladivostok,Asia/Yakutsk,Asia/Yerevan,Atlantic/Azores,Australia/Adelaide,Australia/Brisbane,Australia/Darwin,Australia/Hobart,Australia/Perth,Australia/Sydney,Brazil/East,Canada/Newfoundland,Canada/Saskatchewan,Europe/Amsterdam,Europe/Athens,Europe/Dublin,Europe/Helsinki,Europe/Istanbul,Europe/Kaliningrad,Europe/Moscow,Europe/Paris,Europe/Prague,Europe/Sarajevo,Pacific/Auckland,Pacific/Fiji,Pacific/Guam,Pacific/Honolulu,Pacific/Samoa,US/Alaska,US/Central,US/Eastern,US/East-Indiana,US/Pacific,UTC</AllowedValues><ApplyType>DYNAMIC</ApplyType><DefaultValue>UTC</DefaultValue><IsModifiable>True</IsModifiable><SettingDescription>Specifies the timezone the user wants to change the system time to</SettingDescription><SettingName>TIME_ZONE</SettingName></OptionGroupOptionSetting></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.2</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>Oracle XMLDB Repository</Description><Name>XMLDB</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>oracle-ee</EngineName></OptionGroupOption>\n \n </OptionGroupOptions>\n </DescribeOptionGroupOptionsResult>\n <ResponseMetadata>\n <RequestId>457f7bb8-9fbf-11e4-9084-5754f80d5144</RequestId>\n </ResponseMetadata>\n</DescribeOptionGroupOptionsResponse>', 1308 }, 1309 "sqlserver-ee": { 1310 "10.50": '<DescribeOptionGroupOptionsResponse xmlns="http://rds.amazonaws.com/doc/2014-09-01/">\n <DescribeOptionGroupOptionsResult>\n <OptionGroupOptions>\n \n <OptionGroupOption><MajorEngineVersion>10.50</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>SQLServer Database Mirroring</Description><Name>Mirroring</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>sqlserver-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>10.50</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Description>SQL Server - Transparent Data Encryption</Description><Name>TDE</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>sqlserver-ee</EngineName></OptionGroupOption>\n \n </OptionGroupOptions>\n </DescribeOptionGroupOptionsResult>\n <ResponseMetadata>\n <RequestId>457f7bb8-9fbf-11e4-9084-5754f80d5144</RequestId>\n </ResponseMetadata>\n</DescribeOptionGroupOptionsResponse>', 1311 "11.00": '<DescribeOptionGroupOptionsResponse xmlns="http://rds.amazonaws.com/doc/2014-09-01/">\n <DescribeOptionGroupOptionsResult>\n <OptionGroupOptions>\n \n <OptionGroupOption><MajorEngineVersion>11.00</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>SQLServer Database Mirroring</Description><Name>Mirroring</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>sqlserver-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.00</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Description>SQL Server - Transparent Data Encryption</Description><Name>TDE</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>sqlserver-ee</EngineName></OptionGroupOption>\n \n </OptionGroupOptions>\n </DescribeOptionGroupOptionsResult>\n <ResponseMetadata>\n <RequestId>457f7bb8-9fbf-11e4-9084-5754f80d5144</RequestId>\n </ResponseMetadata>\n</DescribeOptionGroupOptionsResponse>', 1312 "all": '<DescribeOptionGroupOptionsResponse xmlns="http://rds.amazonaws.com/doc/2014-09-01/">\n <DescribeOptionGroupOptionsResult>\n <OptionGroupOptions>\n \n <OptionGroupOption><MajorEngineVersion>10.50</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>SQLServer Database Mirroring</Description><Name>Mirroring</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>sqlserver-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>10.50</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Description>SQL Server - Transparent Data Encryption</Description><Name>TDE</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>sqlserver-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.00</MajorEngineVersion><OptionsDependedOn></OptionsDependedOn><Description>SQLServer Database Mirroring</Description><Name>Mirroring</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>sqlserver-ee</EngineName></OptionGroupOption>\n \n <OptionGroupOption><MajorEngineVersion>11.00</MajorEngineVersion><Persistent>True</Persistent><OptionsDependedOn></OptionsDependedOn><Description>SQL Server - Transparent Data Encryption</Description><Name>TDE</Name><OptionGroupOptionSettings></OptionGroupOptionSettings><EngineName>sqlserver-ee</EngineName></OptionGroupOption>\n \n </OptionGroupOptions>\n </DescribeOptionGroupOptionsResult>\n <ResponseMetadata>\n <RequestId>457f7bb8-9fbf-11e4-9084-5754f80d5144</RequestId>\n </ResponseMetadata>\n</DescribeOptionGroupOptionsResponse>', 1313 }, 1314 } 1315 1316 if engine_name not in default_option_group_options: 1317 raise RDSClientError( 1318 "InvalidParameterValue", "Invalid DB engine: {0}".format(engine_name) 1319 ) 1320 if ( 1321 major_engine_version 1322 and major_engine_version not in default_option_group_options[engine_name] 1323 ): 1324 raise RDSClientError( 1325 "InvalidParameterCombination", 1326 "Cannot find major version {0} for {1}".format( 1327 major_engine_version, engine_name 1328 ), 1329 ) 1330 if major_engine_version: 1331 return default_option_group_options[engine_name][major_engine_version] 1332 return default_option_group_options[engine_name]["all"] 1333 1334 def modify_option_group( 1335 self, 1336 option_group_name, 1337 options_to_include=None, 1338 options_to_remove=None, 1339 apply_immediately=None, 1340 ): 1341 if option_group_name not in self.option_groups: 1342 raise OptionGroupNotFoundFaultError(option_group_name) 1343 if not options_to_include and not options_to_remove: 1344 raise RDSClientError( 1345 "InvalidParameterValue", 1346 "At least one option must be added, modified, or removed.", 1347 ) 1348 if options_to_remove: 1349 self.option_groups[option_group_name].remove_options(options_to_remove) 1350 if options_to_include: 1351 self.option_groups[option_group_name].add_options(options_to_include) 1352 return self.option_groups[option_group_name] 1353 1354 def create_db_parameter_group(self, db_parameter_group_kwargs): 1355 db_parameter_group_id = db_parameter_group_kwargs["name"] 1356 if db_parameter_group_kwargs["name"] in self.db_parameter_groups: 1357 raise RDSClientError( 1358 "DBParameterGroupAlreadyExistsFault", 1359 "A DB parameter group named {0} already exists.".format( 1360 db_parameter_group_kwargs["name"] 1361 ), 1362 ) 1363 if not db_parameter_group_kwargs.get("description"): 1364 raise RDSClientError( 1365 "InvalidParameterValue", 1366 "The parameter Description must be provided and must not be blank.", 1367 ) 1368 if not db_parameter_group_kwargs.get("family"): 1369 raise RDSClientError( 1370 "InvalidParameterValue", 1371 "The parameter DBParameterGroupName must be provided and must not be blank.", 1372 ) 1373 db_parameter_group_kwargs["region"] = self.region 1374 db_parameter_group = DBParameterGroup(**db_parameter_group_kwargs) 1375 self.db_parameter_groups[db_parameter_group_id] = db_parameter_group 1376 return db_parameter_group 1377 1378 def describe_db_parameter_groups(self, db_parameter_group_kwargs): 1379 db_parameter_group_list = [] 1380 1381 if db_parameter_group_kwargs.get("marker"): 1382 marker = db_parameter_group_kwargs["marker"] 1383 else: 1384 marker = 0 1385 if db_parameter_group_kwargs.get("max_records"): 1386 if ( 1387 db_parameter_group_kwargs["max_records"] < 20 1388 or db_parameter_group_kwargs["max_records"] > 100 1389 ): 1390 raise RDSClientError( 1391 "InvalidParameterValue", 1392 "Invalid value for max records. Must be between 20 and 100", 1393 ) 1394 max_records = db_parameter_group_kwargs["max_records"] 1395 else: 1396 max_records = 100 1397 1398 for ( 1399 db_parameter_group_name, 1400 db_parameter_group, 1401 ) in self.db_parameter_groups.items(): 1402 if not db_parameter_group_kwargs.get( 1403 "name" 1404 ) or db_parameter_group.name == db_parameter_group_kwargs.get("name"): 1405 db_parameter_group_list.append(db_parameter_group) 1406 else: 1407 continue 1408 1409 return db_parameter_group_list[marker : max_records + marker] 1410 1411 def modify_db_parameter_group( 1412 self, db_parameter_group_name, db_parameter_group_parameters 1413 ): 1414 if db_parameter_group_name not in self.db_parameter_groups: 1415 raise DBParameterGroupNotFoundError(db_parameter_group_name) 1416 1417 db_parameter_group = self.db_parameter_groups[db_parameter_group_name] 1418 db_parameter_group.update_parameters(db_parameter_group_parameters) 1419 1420 return db_parameter_group 1421 1422 def create_db_cluster(self, kwargs): 1423 cluster_id = kwargs["db_cluster_identifier"] 1424 cluster = Cluster(**kwargs) 1425 self.clusters[cluster_id] = cluster 1426 initial_state = copy.deepcopy(cluster) # Return status=creating 1427 cluster.status = "available" # Already set the final status in the background 1428 return initial_state 1429 1430 def describe_db_clusters(self, cluster_identifier): 1431 if cluster_identifier: 1432 return [self.clusters[cluster_identifier]] 1433 return self.clusters.values() 1434 1435 def delete_db_cluster(self, cluster_identifier): 1436 return self.clusters.pop(cluster_identifier) 1437 1438 def start_db_cluster(self, cluster_identifier): 1439 if cluster_identifier not in self.clusters: 1440 raise DBClusterNotFoundError(cluster_identifier) 1441 cluster = self.clusters[cluster_identifier] 1442 if cluster.status != "stopped": 1443 raise InvalidDBClusterStateFault( 1444 "DbCluster cluster-id is not in stopped state." 1445 ) 1446 temp_state = copy.deepcopy(cluster) 1447 temp_state.status = "started" 1448 cluster.status = "available" # This is the final status - already setting it in the background 1449 return temp_state 1450 1451 def stop_db_cluster(self, cluster_identifier): 1452 if cluster_identifier not in self.clusters: 1453 raise DBClusterNotFoundError(cluster_identifier) 1454 cluster = self.clusters[cluster_identifier] 1455 if cluster.status not in ["available"]: 1456 raise InvalidDBClusterStateFault( 1457 "DbCluster cluster-id is not in available state." 1458 ) 1459 previous_state = copy.deepcopy(cluster) 1460 cluster.status = "stopped" 1461 return previous_state 1462 1463 def list_tags_for_resource(self, arn): 1464 if self.arn_regex.match(arn): 1465 arn_breakdown = arn.split(":") 1466 resource_type = arn_breakdown[len(arn_breakdown) - 2] 1467 resource_name = arn_breakdown[len(arn_breakdown) - 1] 1468 if resource_type == "db": # Database 1469 if resource_name in self.databases: 1470 return self.databases[resource_name].get_tags() 1471 elif resource_type == "es": # Event Subscription 1472 # TODO: Complete call to tags on resource type Event 1473 # Subscription 1474 return [] 1475 elif resource_type == "og": # Option Group 1476 if resource_name in self.option_groups: 1477 return self.option_groups[resource_name].get_tags() 1478 elif resource_type == "pg": # Parameter Group 1479 if resource_name in self.db_parameter_groups: 1480 return self.db_parameter_groups[resource_name].get_tags() 1481 elif resource_type == "ri": # Reserved DB instance 1482 # TODO: Complete call to tags on resource type Reserved DB 1483 # instance 1484 return [] 1485 elif resource_type == "secgrp": # DB security group 1486 if resource_name in self.security_groups: 1487 return self.security_groups[resource_name].get_tags() 1488 elif resource_type == "snapshot": # DB Snapshot 1489 if resource_name in self.snapshots: 1490 return self.snapshots[resource_name].get_tags() 1491 elif resource_type == "subgrp": # DB subnet group 1492 if resource_name in self.subnet_groups: 1493 return self.subnet_groups[resource_name].get_tags() 1494 else: 1495 raise RDSClientError( 1496 "InvalidParameterValue", "Invalid resource name: {0}".format(arn) 1497 ) 1498 return [] 1499 1500 def remove_tags_from_resource(self, arn, tag_keys): 1501 if self.arn_regex.match(arn): 1502 arn_breakdown = arn.split(":") 1503 resource_type = arn_breakdown[len(arn_breakdown) - 2] 1504 resource_name = arn_breakdown[len(arn_breakdown) - 1] 1505 if resource_type == "db": # Database 1506 if resource_name in self.databases: 1507 self.databases[resource_name].remove_tags(tag_keys) 1508 elif resource_type == "es": # Event Subscription 1509 return None 1510 elif resource_type == "og": # Option Group 1511 if resource_name in self.option_groups: 1512 return self.option_groups[resource_name].remove_tags(tag_keys) 1513 elif resource_type == "pg": # Parameter Group 1514 return None 1515 elif resource_type == "ri": # Reserved DB instance 1516 return None 1517 elif resource_type == "secgrp": # DB security group 1518 if resource_name in self.security_groups: 1519 return self.security_groups[resource_name].remove_tags(tag_keys) 1520 elif resource_type == "snapshot": # DB Snapshot 1521 if resource_name in self.snapshots: 1522 return self.snapshots[resource_name].remove_tags(tag_keys) 1523 elif resource_type == "subgrp": # DB subnet group 1524 if resource_name in self.subnet_groups: 1525 return self.subnet_groups[resource_name].remove_tags(tag_keys) 1526 else: 1527 raise RDSClientError( 1528 "InvalidParameterValue", "Invalid resource name: {0}".format(arn) 1529 ) 1530 1531 def add_tags_to_resource(self, arn, tags): 1532 if self.arn_regex.match(arn): 1533 arn_breakdown = arn.split(":") 1534 resource_type = arn_breakdown[len(arn_breakdown) - 2] 1535 resource_name = arn_breakdown[len(arn_breakdown) - 1] 1536 if resource_type == "db": # Database 1537 if resource_name in self.databases: 1538 return self.databases[resource_name].add_tags(tags) 1539 elif resource_type == "es": # Event Subscription 1540 return [] 1541 elif resource_type == "og": # Option Group 1542 if resource_name in self.option_groups: 1543 return self.option_groups[resource_name].add_tags(tags) 1544 elif resource_type == "pg": # Parameter Group 1545 return [] 1546 elif resource_type == "ri": # Reserved DB instance 1547 return [] 1548 elif resource_type == "secgrp": # DB security group 1549 if resource_name in self.security_groups: 1550 return self.security_groups[resource_name].add_tags(tags) 1551 elif resource_type == "snapshot": # DB Snapshot 1552 if resource_name in self.snapshots: 1553 return self.snapshots[resource_name].add_tags(tags) 1554 elif resource_type == "subgrp": # DB subnet group 1555 if resource_name in self.subnet_groups: 1556 return self.subnet_groups[resource_name].add_tags(tags) 1557 else: 1558 raise RDSClientError( 1559 "InvalidParameterValue", "Invalid resource name: {0}".format(arn) 1560 ) 1561 1562 @staticmethod 1563 def _filter_resources(resources, filters, resource_class): 1564 try: 1565 filter_defs = resource_class.SUPPORTED_FILTERS 1566 validate_filters(filters, filter_defs) 1567 return apply_filter(resources, filters, filter_defs) 1568 except KeyError as e: 1569 # https://stackoverflow.com/questions/24998968/why-does-strkeyerror-add-extra-quotes 1570 raise InvalidParameterValue(e.args[0]) 1571 except ValueError as e: 1572 raise InvalidParameterCombination(str(e)) 1573 1574 1575class OptionGroup(object): 1576 def __init__(self, name, engine_name, major_engine_version, description=None): 1577 self.engine_name = engine_name 1578 self.major_engine_version = major_engine_version 1579 self.description = description 1580 self.name = name 1581 self.vpc_and_non_vpc_instance_memberships = False 1582 self.options = {} 1583 self.vpcId = "null" 1584 self.tags = [] 1585 1586 def to_json(self): 1587 template = Template( 1588 """{ 1589 "VpcId": null, 1590 "MajorEngineVersion": "{{ option_group.major_engine_version }}", 1591 "OptionGroupDescription": "{{ option_group.description }}", 1592 "AllowsVpcAndNonVpcInstanceMemberships": "{{ option_group.vpc_and_non_vpc_instance_memberships }}", 1593 "EngineName": "{{ option_group.engine_name }}", 1594 "Options": [], 1595 "OptionGroupName": "{{ option_group.name }}" 1596}""" 1597 ) 1598 return template.render(option_group=self) 1599 1600 def to_xml(self): 1601 template = Template( 1602 """<OptionGroup> 1603 <OptionGroupName>{{ option_group.name }}</OptionGroupName> 1604 <AllowsVpcAndNonVpcInstanceMemberships>{{ option_group.vpc_and_non_vpc_instance_memberships }}</AllowsVpcAndNonVpcInstanceMemberships> 1605 <MajorEngineVersion>{{ option_group.major_engine_version }}</MajorEngineVersion> 1606 <EngineName>{{ option_group.engine_name }}</EngineName> 1607 <OptionGroupDescription>{{ option_group.description }}</OptionGroupDescription> 1608 <Options/> 1609 </OptionGroup>""" 1610 ) 1611 return template.render(option_group=self) 1612 1613 def remove_options(self, options_to_remove): 1614 # TODO: Check for option in self.options and remove if exists. Raise 1615 # error otherwise 1616 return 1617 1618 def add_options(self, options_to_add): 1619 # TODO: Validate option and add it to self.options. If invalid raise 1620 # error 1621 return 1622 1623 def get_tags(self): 1624 return self.tags 1625 1626 def add_tags(self, tags): 1627 new_keys = [tag_set["Key"] for tag_set in tags] 1628 self.tags = [tag_set for tag_set in self.tags if tag_set["Key"] not in new_keys] 1629 self.tags.extend(tags) 1630 return self.tags 1631 1632 def remove_tags(self, tag_keys): 1633 self.tags = [tag_set for tag_set in self.tags if tag_set["Key"] not in tag_keys] 1634 1635 1636class OptionGroupOption(object): 1637 def __init__(self, **kwargs): 1638 self.default_port = kwargs.get("default_port") 1639 self.description = kwargs.get("description") 1640 self.engine_name = kwargs.get("engine_name") 1641 self.major_engine_version = kwargs.get("major_engine_version") 1642 self.name = kwargs.get("name") 1643 self.option_group_option_settings = self._make_option_group_option_settings( 1644 kwargs.get("option_group_option_settings", []) 1645 ) 1646 self.options_depended_on = kwargs.get("options_depended_on", []) 1647 self.permanent = kwargs.get("permanent") 1648 self.persistent = kwargs.get("persistent") 1649 self.port_required = kwargs.get("port_required") 1650 1651 def _make_option_group_option_settings(self, option_group_option_settings_kwargs): 1652 return [ 1653 OptionGroupOptionSetting(**setting_kwargs) 1654 for setting_kwargs in option_group_option_settings_kwargs 1655 ] 1656 1657 def to_json(self): 1658 template = Template( 1659 """{ "MinimumRequiredMinorEngineVersion": 1660 "2789.0.v1", 1661 "OptionsDependedOn": [], 1662 "MajorEngineVersion": "10.50", 1663 "Persistent": false, 1664 "DefaultPort": null, 1665 "Permanent": false, 1666 "OptionGroupOptionSettings": [], 1667 "EngineName": "sqlserver-se", 1668 "Name": "Mirroring", 1669 "PortRequired": false, 1670 "Description": "SQLServer Database Mirroring" 1671 }""" 1672 ) 1673 return template.render(option_group=self) 1674 1675 def to_xml(self): 1676 template = Template( 1677 """<OptionGroupOption> 1678 <MajorEngineVersion>{{ option_group.major_engine_version }}</MajorEngineVersion> 1679 <DefaultPort>{{ option_group.default_port }}</DefaultPort> 1680 <PortRequired>{{ option_group.port_required }}</PortRequired> 1681 <Persistent>{{ option_group.persistent }}</Persistent> 1682 <OptionsDependedOn> 1683 {%- for option_name in option_group.options_depended_on -%} 1684 <OptionName>{{ option_name }}</OptionName> 1685 {%- endfor -%} 1686 </OptionsDependedOn> 1687 <Permanent>{{ option_group.permanent }}</Permanent> 1688 <Description>{{ option_group.description }}</Description> 1689 <Name>{{ option_group.name }}</Name> 1690 <OptionGroupOptionSettings> 1691 {%- for setting in option_group.option_group_option_settings -%} 1692 {{ setting.to_xml() }} 1693 {%- endfor -%} 1694 </OptionGroupOptionSettings> 1695 <EngineName>{{ option_group.engine_name }}</EngineName> 1696 <MinimumRequiredMinorEngineVersion>{{ option_group.minimum_required_minor_engine_version }}</MinimumRequiredMinorEngineVersion> 1697</OptionGroupOption>""" 1698 ) 1699 return template.render(option_group=self) 1700 1701 1702class OptionGroupOptionSetting(object): 1703 def __init__(self, *kwargs): 1704 self.allowed_values = kwargs.get("allowed_values") 1705 self.apply_type = kwargs.get("apply_type") 1706 self.default_value = kwargs.get("default_value") 1707 self.is_modifiable = kwargs.get("is_modifiable") 1708 self.setting_description = kwargs.get("setting_description") 1709 self.setting_name = kwargs.get("setting_name") 1710 1711 def to_xml(self): 1712 template = Template( 1713 """<OptionGroupOptionSetting> 1714 <AllowedValues>{{ option_group_option_setting.allowed_values }}</AllowedValues> 1715 <ApplyType>{{ option_group_option_setting.apply_type }}</ApplyType> 1716 <DefaultValue>{{ option_group_option_setting.default_value }}</DefaultValue> 1717 <IsModifiable>{{ option_group_option_setting.is_modifiable }}</IsModifiable> 1718 <SettingDescription>{{ option_group_option_setting.setting_description }}</SettingDescription> 1719 <SettingName>{{ option_group_option_setting.setting_name }}</SettingName> 1720</OptionGroupOptionSetting>""" 1721 ) 1722 return template.render(option_group_option_setting=self) 1723 1724 1725def make_rds_arn(region, name): 1726 return "arn:aws:rds:{0}:{1}:pg:{2}".format(region, ACCOUNT_ID, name) 1727 1728 1729class DBParameterGroup(CloudFormationModel): 1730 def __init__(self, name, description, family, tags, region): 1731 self.name = name 1732 self.description = description 1733 self.family = family 1734 self.tags = tags 1735 self.parameters = defaultdict(dict) 1736 self.arn = make_rds_arn(region, name) 1737 1738 def to_xml(self): 1739 template = Template( 1740 """<DBParameterGroup> 1741 <DBParameterGroupName>{{ param_group.name }}</DBParameterGroupName> 1742 <DBParameterGroupFamily>{{ param_group.family }}</DBParameterGroupFamily> 1743 <Description>{{ param_group.description }}</Description> 1744 <DBParameterGroupArn>{{ param_group.arn }}</DBParameterGroupArn> 1745 </DBParameterGroup>""" 1746 ) 1747 return template.render(param_group=self) 1748 1749 def get_tags(self): 1750 return self.tags 1751 1752 def add_tags(self, tags): 1753 new_keys = [tag_set["Key"] for tag_set in tags] 1754 self.tags = [tag_set for tag_set in self.tags if tag_set["Key"] not in new_keys] 1755 self.tags.extend(tags) 1756 return self.tags 1757 1758 def remove_tags(self, tag_keys): 1759 self.tags = [tag_set for tag_set in self.tags if tag_set["Key"] not in tag_keys] 1760 1761 def update_parameters(self, new_parameters): 1762 for new_parameter in new_parameters: 1763 parameter = self.parameters[new_parameter["ParameterName"]] 1764 parameter.update(new_parameter) 1765 1766 def delete(self, region_name): 1767 backend = rds2_backends[region_name] 1768 backend.delete_db_parameter_group(self.name) 1769 1770 @staticmethod 1771 def cloudformation_name_type(): 1772 return None 1773 1774 @staticmethod 1775 def cloudformation_type(): 1776 # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbparametergroup.html 1777 return "AWS::RDS::DBParameterGroup" 1778 1779 @classmethod 1780 def create_from_cloudformation_json( 1781 cls, resource_name, cloudformation_json, region_name, **kwargs 1782 ): 1783 properties = cloudformation_json["Properties"] 1784 1785 db_parameter_group_kwargs = { 1786 "description": properties["Description"], 1787 "family": properties["Family"], 1788 "name": resource_name.lower(), 1789 "tags": properties.get("Tags"), 1790 } 1791 db_parameter_group_parameters = [] 1792 for db_parameter, db_parameter_value in properties.get( 1793 "Parameters", {} 1794 ).items(): 1795 db_parameter_group_parameters.append( 1796 {"ParameterName": db_parameter, "ParameterValue": db_parameter_value} 1797 ) 1798 1799 rds2_backend = rds2_backends[region_name] 1800 db_parameter_group = rds2_backend.create_db_parameter_group( 1801 db_parameter_group_kwargs 1802 ) 1803 db_parameter_group.update_parameters(db_parameter_group_parameters) 1804 return db_parameter_group 1805 1806 1807rds2_backends = {} 1808for region in Session().get_available_regions("rds"): 1809 rds2_backends[region] = RDS2Backend(region) 1810for region in Session().get_available_regions("rds", partition_name="aws-us-gov"): 1811 rds2_backends[region] = RDS2Backend(region) 1812for region in Session().get_available_regions("rds", partition_name="aws-cn"): 1813 rds2_backends[region] = RDS2Backend(region) 1814