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