diff --git a/aws-rds-dbinstance/aws-rds-dbinstance.json b/aws-rds-dbinstance/aws-rds-dbinstance.json index 5e836b997..379a3f28c 100644 --- a/aws-rds-dbinstance/aws-rds-dbinstance.json +++ b/aws-rds-dbinstance/aws-rds-dbinstance.json @@ -480,6 +480,7 @@ "/properties/DBParameterGroupName": "$lowercase(DBParameterGroupName)", "/properties/DBSnapshotIdentifier": "$lowercase(DBSnapshotIdentifier)", "/properties/DBSubnetGroupName": "$lowercase(DBSubnetGroupName)", + "/properties/DBSystemId": "$uppercase(DBSystemId)", "/properties/Engine": "$lowercase(Engine)", "/properties/EngineVersion": "$join([$string(EngineVersion), \".*\"])", "/properties/KmsKeyId": "$join([\"arn:.+?:kms:.+?:.+?:key\\/\", KmsKeyId])", @@ -499,6 +500,7 @@ "/properties/DBInstanceIdentifier", "/properties/DBName", "/properties/DBSubnetGroupName", + "/properties/DBSystemId", "/properties/KmsKeyId", "/properties/MasterUsername", "/properties/NcharCharacterSetName", @@ -551,7 +553,6 @@ "/properties/Endpoint/HostedZoneId", "/properties/DbiResourceId", "/properties/DBInstanceArn", - "/properties/DBSystemId", "/properties/MasterUserSecret/SecretArn", "/properties/CertificateDetails/CAIdentifier", "/properties/CertificateDetails/ValidTill" diff --git a/aws-rds-dbinstance/docs/README.md b/aws-rds-dbinstance/docs/README.md index 9503a4b30..d55265717 100644 --- a/aws-rds-dbinstance/docs/README.md +++ b/aws-rds-dbinstance/docs/README.md @@ -35,6 +35,7 @@ To declare this entity in your AWS CloudFormation template, use the following sy "DBSecurityGroups" : [ String, ... ], "DBSnapshotIdentifier" : String, "DBSubnetGroupName" : String, + "DBSystemId" : String, "DedicatedLogVolume" : Boolean, "DeleteAutomatedBackups" : Boolean, "DeletionProtection" : Boolean, @@ -124,6 +125,7 @@ Properties: - String DBSnapshotIdentifier: String DBSubnetGroupName: String + DBSystemId: String DedicatedLogVolume: Boolean DeleteAutomatedBackups: Boolean DeletionProtection: Boolean @@ -441,6 +443,16 @@ _Type_: String _Update requires_: [Replacement](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-replacement) +#### DBSystemId + +The Oracle system ID (Oracle SID) for a container database (CDB). The Oracle SID is also the name of the CDB. This setting is valid for RDS Custom only. + +_Required_: No + +_Type_: String + +_Update requires_: [Replacement](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-replacement) + #### DedicatedLogVolume Indicates whether the DB instance has a dedicated log volume (DLV) enabled. @@ -587,7 +599,7 @@ _Required_: No _Type_: String -_Update requires_: [Some interruptions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-some-interrupt) +_Update requires_: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt) #### EngineVersion @@ -1027,10 +1039,6 @@ The AWS Region-unique, immutable identifier for the DB instance. This identifier The Amazon Resource Name (ARN) for the DB instance. -#### DBSystemId - -The Oracle system ID (Oracle SID) for a container database (CDB). The Oracle SID is also the name of the CDB. This setting is valid for RDS Custom only. - #### SecretArn Returns the SecretArn value. diff --git a/aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/CreateHandler.java b/aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/CreateHandler.java index 499be340c..c2357e96b 100644 --- a/aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/CreateHandler.java +++ b/aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/CreateHandler.java @@ -32,6 +32,7 @@ import software.amazon.rds.dbinstance.client.RdsClientProvider; import software.amazon.rds.dbinstance.client.VersionedProxyClient; import software.amazon.rds.dbinstance.util.ResourceModelHelper; +import software.amazon.rds.dbinstance.validators.OracleCustomSystemId; public class CreateHandler extends BaseHandlerStd { @@ -56,6 +57,8 @@ protected void validateRequest(final ResourceHandlerRequest reque super.validateRequest(request); validateDeletionPolicyForClusterInstance(request); Validations.validateTimestamp(request.getDesiredResourceState().getRestoreTime()); + + OracleCustomSystemId.validateRequest(request.getDesiredResourceState()); } private void validateDeletionPolicyForClusterInstance(final ResourceHandlerRequest request) throws RequestValidationException { diff --git a/aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/Translator.java b/aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/Translator.java index 76f7c5853..a3c889c62 100644 --- a/aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/Translator.java +++ b/aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/Translator.java @@ -290,6 +290,7 @@ public static CreateDbInstanceRequest createDbInstanceRequest( .dbName(model.getDBName()) .dbParameterGroupName(model.getDBParameterGroupName()) .dbSubnetGroupName(model.getDBSubnetGroupName()) + .dbSystemId(model.getDBSystemId()) .dedicatedLogVolume(model.getDedicatedLogVolume()) .deletionProtection(model.getDeletionProtection()) .domain(model.getDomain()) diff --git a/aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/client/RdsClientProvider.java b/aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/client/RdsClientProvider.java index 83031b3f8..1c1743f78 100644 --- a/aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/client/RdsClientProvider.java +++ b/aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/client/RdsClientProvider.java @@ -17,6 +17,7 @@ import software.amazon.rds.common.client.BaseSdkClientProvider; import software.amazon.rds.common.client.RdsUserAgentProvider; + public class RdsClientProvider extends BaseSdkClientProvider { public static final String VERSION_QUERY_PARAM = "Version"; diff --git a/aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/validators/OracleCustomSystemId.java b/aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/validators/OracleCustomSystemId.java new file mode 100644 index 000000000..eded785cd --- /dev/null +++ b/aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/validators/OracleCustomSystemId.java @@ -0,0 +1,21 @@ +package software.amazon.rds.dbinstance.validators; + +import software.amazon.rds.common.request.RequestValidationException; +import software.amazon.rds.dbinstance.ResourceModel; +import software.amazon.rds.dbinstance.util.ResourceModelHelper; + +public class OracleCustomSystemId { + public static void validateRequest(final ResourceModel model) throws RequestValidationException { + if (ResourceModelHelper.isRestoreToPointInTime(model) && model.getDBSystemId() != null) { + throw new RequestValidationException("The DBSystemId parameter cannot be specified when you create a DB instance from a point-in-time restore."); + } + + if (ResourceModelHelper.isDBInstanceReadReplica(model) && model.getDBSystemId() != null) { + throw new RequestValidationException("The DBSystemId parameter cannot be specified when you create a read replica."); + } + + if (ResourceModelHelper.isRestoreFromSnapshot(model) && model.getDBSystemId() != null) { + throw new RequestValidationException("The DBSystemId parameter cannot be specified when you create a DB instance from a snapshot restore."); + } + } +} diff --git a/aws-rds-dbinstance/src/test/java/software/amazon/rds/dbinstance/AbstractHandlerTest.java b/aws-rds-dbinstance/src/test/java/software/amazon/rds/dbinstance/AbstractHandlerTest.java index cbb49e560..7c931ebd4 100644 --- a/aws-rds-dbinstance/src/test/java/software/amazon/rds/dbinstance/AbstractHandlerTest.java +++ b/aws-rds-dbinstance/src/test/java/software/amazon/rds/dbinstance/AbstractHandlerTest.java @@ -95,6 +95,7 @@ public abstract class AbstractHandlerTest extends AbstractTestBase DB_INSTANCE_ACTIVE_SYSTEM_ID, + () -> RESOURCE_MODEL_BLDR().dBSystemId("UNITTEST").build(), + expectSuccess() + ); + + verify(rdsProxy.client(), times(3)).describeDBInstances(any(DescribeDbInstancesRequest.class)); + verify(rdsProxy.client(), times(1)).addTagsToResource(any(AddTagsToResourceRequest.class)); + } + + @Test + public void handleRequest_CreateReadReplicaWithoutSid_IsSuccessful() { + when(rdsProxy.client().addTagsToResource(any(AddTagsToResourceRequest.class))) + .thenReturn(AddTagsToResourceResponse.builder().build()); + + final CallbackContext context = new CallbackContext(); + context.setCreated(true); + context.setUpdated(true); + context.setRebooted(true); + context.setUpdatedRoles(true); + + test_handleRequest_base( + context, + () -> DB_INSTANCE_ACTIVE, + () -> RESOURCE_MODEL_READ_REPLICA, + expectSuccess() + ); + + verify(rdsProxy.client(), times(3)).describeDBInstances(any(DescribeDbInstancesRequest.class)); + verify(rdsProxy.client(), times(1)).addTagsToResource(any(AddTagsToResourceRequest.class)); + } + + @Test + public void handleRequest_CreateDBInstanceFromSnapshotWithoutSid_IsSuccessful() { + when(rdsProxy.client().addTagsToResource(any(AddTagsToResourceRequest.class))) + .thenReturn(AddTagsToResourceResponse.builder().build()); + + final CallbackContext context = new CallbackContext(); + context.setCreated(true); + context.setUpdated(true); + context.setRebooted(true); + context.setUpdatedRoles(true); + + test_handleRequest_base( + context, + () -> DB_INSTANCE_ACTIVE, + () -> RESOURCE_MODEL_RESTORING_FROM_SNAPSHOT, + expectSuccess() + ); + + verify(rdsProxy.client(), times(3)).describeDBInstances(any(DescribeDbInstancesRequest.class)); + verify(rdsProxy.client(), times(1)).addTagsToResource(any(AddTagsToResourceRequest.class)); + } + + @Test + public void handleRequest_CreateReadReplicaWithSid_ThrowsRequestValidationException() { + expectServiceInvocation = false; + final CallbackContext context = new CallbackContext(); + context.setCreated(false); + context.setUpdated(true); + context.setRebooted(true); + context.setUpdatedRoles(true); + context.setAddTagsComplete(true); + + test_handleRequest_base( + context, + null, + () -> RESOURCE_MODEL_READ_REPLICA.toBuilder().dBSystemId("UNITTEST").build(), + expectFailed(HandlerErrorCode.InvalidRequest) + ); + } + + @Test + public void handleRequest_CreateDBInstanceFromSnapshotWithSid_ThrowsRequestValidationException() { + expectServiceInvocation = false; + final CallbackContext context = new CallbackContext(); + context.setCreated(false); + context.setUpdated(true); + context.setRebooted(true); + context.setUpdatedRoles(true); + context.setAddTagsComplete(true); + + test_handleRequest_base( + context, + null, + () -> RESOURCE_MODEL_RESTORING_FROM_SNAPSHOT.toBuilder().dBSystemId("UNITTEST").build(), + expectFailed(HandlerErrorCode.InvalidRequest) + ); + } + + @Test + public void handleRequest_CreateDBInstanceFromPitrWithSid_ThrowsRequestValidationException() { + expectServiceInvocation = false; + final CallbackContext context = new CallbackContext(); + context.setCreated(false); + context.setUpdated(true); + context.setRebooted(true); + context.setUpdatedRoles(true); + context.setAddTagsComplete(true); + + test_handleRequest_base( + context, + null, + () -> RESOURCE_MODEL_RESTORING_TO_POINT_IN_TIME.toBuilder().dBSystemId("UNITTEST").build(), + expectFailed(HandlerErrorCode.InvalidRequest) + ); + } + @Test public void fetchEngineForUnknownScenario() { expectServiceInvocation = false;