Skip to content

Commit

Permalink
[DBInstance] Support for Oracle Multitenant SID
Browse files Browse the repository at this point in the history
  • Loading branch information
angusy29 committed Nov 5, 2024
1 parent c316d58 commit a6a8c28
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 6 deletions.
3 changes: 2 additions & 1 deletion aws-rds-dbinstance/aws-rds-dbinstance.json
Original file line number Diff line number Diff line change
Expand Up @@ -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])",
Expand All @@ -499,6 +500,7 @@
"/properties/DBInstanceIdentifier",
"/properties/DBName",
"/properties/DBSubnetGroupName",
"/properties/DBSystemId",
"/properties/KmsKeyId",
"/properties/MasterUsername",
"/properties/NcharCharacterSetName",
Expand Down Expand Up @@ -551,7 +553,6 @@
"/properties/Endpoint/HostedZoneId",
"/properties/DbiResourceId",
"/properties/DBInstanceArn",
"/properties/DBSystemId",
"/properties/MasterUserSecret/SecretArn",
"/properties/CertificateDetails/CAIdentifier",
"/properties/CertificateDetails/ValidTill"
Expand Down
18 changes: 13 additions & 5 deletions aws-rds-dbinstance/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ To declare this entity in your AWS CloudFormation template, use the following sy
"<a href="#dbsecuritygroups" title="DBSecurityGroups">DBSecurityGroups</a>" : <i>[ String, ... ]</i>,
"<a href="#dbsnapshotidentifier" title="DBSnapshotIdentifier">DBSnapshotIdentifier</a>" : <i>String</i>,
"<a href="#dbsubnetgroupname" title="DBSubnetGroupName">DBSubnetGroupName</a>" : <i>String</i>,
"<a href="#dbsystemid" title="DBSystemId">DBSystemId</a>" : <i>String</i>,
"<a href="#dedicatedlogvolume" title="DedicatedLogVolume">DedicatedLogVolume</a>" : <i>Boolean</i>,
"<a href="#deleteautomatedbackups" title="DeleteAutomatedBackups">DeleteAutomatedBackups</a>" : <i>Boolean</i>,
"<a href="#deletionprotection" title="DeletionProtection">DeletionProtection</a>" : <i>Boolean</i>,
Expand Down Expand Up @@ -124,6 +125,7 @@ Properties:
- String</i>
<a href="#dbsnapshotidentifier" title="DBSnapshotIdentifier">DBSnapshotIdentifier</a>: <i>String</i>
<a href="#dbsubnetgroupname" title="DBSubnetGroupName">DBSubnetGroupName</a>: <i>String</i>
<a href="#dbsystemid" title="DBSystemId">DBSystemId</a>: <i>String</i>
<a href="#dedicatedlogvolume" title="DedicatedLogVolume">DedicatedLogVolume</a>: <i>Boolean</i>
<a href="#deleteautomatedbackups" title="DeleteAutomatedBackups">DeleteAutomatedBackups</a>: <i>Boolean</i>
<a href="#deletionprotection" title="DeletionProtection">DeletionProtection</a>: <i>Boolean</i>
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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 <code>SecretArn</code> value.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand All @@ -56,6 +57,8 @@ protected void validateRequest(final ResourceHandlerRequest<ResourceModel> reque
super.validateRequest(request);
validateDeletionPolicyForClusterInstance(request);
Validations.validateTimestamp(request.getDesiredResourceState().getRestoreTime());

OracleCustomSystemId.validateRequest(request.getDesiredResourceState());
}

private void validateDeletionPolicyForClusterInstance(final ResourceHandlerRequest<ResourceModel> request) throws RequestValidationException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import software.amazon.rds.common.client.BaseSdkClientProvider;
import software.amazon.rds.common.client.RdsUserAgentProvider;


public class RdsClientProvider extends BaseSdkClientProvider<RdsClientBuilder, RdsClient> {

public static final String VERSION_QUERY_PARAM = "Version";
Expand Down
Original file line number Diff line number Diff line change
@@ -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.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ public abstract class AbstractHandlerTest extends AbstractTestBase<DBInstance, R
protected static final String DB_INSTANCE_STATUS_MODIFYING = "modifying";
protected static final String DB_INSTANCE_STATUS_FAILED = "failed";
protected static final String DB_INSTANCE_STATUS_STORAGE_FULL = "storage-full";
protected static final String DB_INSTANCE_SYSTEM_ID = "UNITTEST";
protected static final String DB_NAME = "db-instance-db-name";
protected static final String DB_PARAMETER_GROUP_NAME_DEFAULT = "default";
protected static final String DB_PARAMETER_GROUP_NAME_ALTER = "alternative-parameter-group";
Expand Down Expand Up @@ -207,6 +208,7 @@ public abstract class AbstractHandlerTest extends AbstractTestBase<DBInstance, R

static final DBInstance DB_INSTANCE_BASE;
static final DBInstance DB_INSTANCE_ACTIVE;
static final DBInstance DB_INSTANCE_ACTIVE_SYSTEM_ID;
static final DBInstance DB_INSTANCE_AURORA_ACTIVE;
static final DBInstance DB_INSTANCE_SQLSERVER_ACTIVE;
static final DBInstance DB_INSTANCE_READ_REPLICA_ACTIVE;
Expand Down Expand Up @@ -576,6 +578,8 @@ public abstract class AbstractHandlerTest extends AbstractTestBase<DBInstance, R
.promotionTier(PROMOTION_TIER_DEFAULT)
.build();

DB_INSTANCE_ACTIVE_SYSTEM_ID = DB_INSTANCE_ACTIVE.toBuilder().dbSystemId(DB_INSTANCE_SYSTEM_ID).build();

DB_INSTANCE_AURORA_ACTIVE = DB_INSTANCE_ACTIVE.toBuilder()
.dbClusterIdentifier(DB_CLUSTER_IDENTIFIER_NON_EMPTY)
.engine(ENGINE_AURORA_MYSQL)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2241,6 +2241,126 @@ public void fetchEngineForPointInTimeRestoreFromAutomatedBackup() {
Assertions.assertThat(captor.getValue().dbInstanceAutomatedBackupsArn()).isEqualTo("backup-arn");
}

@Test
public void handleRequest_CreateDBInstanceWithSid_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_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;
Expand Down

0 comments on commit a6a8c28

Please sign in to comment.