Skip to content

Commit

Permalink
[CFN-27] The 'safeAddTags' method is still c/p but the core change in…
Browse files Browse the repository at this point in the history
… pattern has finished resulting in a trim create step in the create handler (line 103).
  • Loading branch information
Keynan Pratt committed Nov 25, 2024
1 parent 224e54d commit 0aee70d
Show file tree
Hide file tree
Showing 19 changed files with 824 additions and 138 deletions.
3 changes: 3 additions & 0 deletions aws-rds-dbcluster/docs/serverlessv2scalingconfiguration.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ _Type_: Double

_Update requires_: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)

<<<<<<< HEAD
#### SecondsUntilAutoPause

_Required_: No
Expand All @@ -54,3 +55,5 @@ _Type_: Integer

_Update requires_: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)

=======
>>>>>>> 77e00a3 ([CFN-27] The 'safeAddTags' method is still c/p but the core change in pattern has finished resulting in a trim create step in the create handler (line 103).)
8 changes: 4 additions & 4 deletions aws-rds-dbinstance/pom.xml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>software.amazon.rds.dbinstance</groupId>
Expand Down Expand Up @@ -267,7 +267,7 @@
<limit>
<counter>BRANCH</counter>
<value>COVEREDRATIO</value>
<minimum>0.8</minimum>
<minimum>0.82</minimum>
</limit>
<limit>
<counter>INSTRUCTION</counter>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,18 @@
package software.amazon.rds.dbinstance;

import java.time.Instant;
import java.util.Collection;
import java.util.Collections;

import org.apache.commons.lang3.BooleanUtils;

import com.amazonaws.util.StringUtils;
import org.apache.commons.lang3.BooleanUtils;
import software.amazon.awssdk.services.ec2.Ec2Client;
import software.amazon.awssdk.services.rds.RdsClient;
import software.amazon.awssdk.services.rds.model.DBInstance;
import software.amazon.awssdk.services.rds.model.DBSnapshot;
import software.amazon.awssdk.services.rds.model.SourceType;
import software.amazon.awssdk.utils.ImmutableMap;
import software.amazon.cloudformation.exceptions.CfnInvalidRequestException;
import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy;
import software.amazon.cloudformation.proxy.ProgressEvent;
import software.amazon.cloudformation.proxy.ProxyClient;
import software.amazon.cloudformation.proxy.ResourceHandlerRequest;
import software.amazon.rds.common.handler.Commons;
import software.amazon.rds.common.handler.Events;
import software.amazon.rds.common.handler.HandlerConfig;
import software.amazon.rds.common.handler.HandlerMethod;
import software.amazon.rds.common.handler.Tagging;
import software.amazon.rds.common.handler.*;
import software.amazon.rds.common.logging.LoggingProxyClient;
import software.amazon.rds.common.request.RequestValidationException;
import software.amazon.rds.common.request.ValidatedRequest;
Expand All @@ -36,6 +26,10 @@
import software.amazon.rds.dbinstance.util.ResourceModelHelper;
import software.amazon.rds.dbinstance.validators.OracleCustomSystemId;

import java.time.Instant;
import java.util.Collection;
import java.util.Collections;

public class CreateHandler extends BaseHandlerStd {

private static final IdentifierFactory instanceIdentifierFactory = new IdentifierFactory(
Expand Down Expand Up @@ -98,6 +92,7 @@ protected ProgressEvent<ResourceModel, CallbackContext> handleRequest(
proxy, rdsProxyClient, allTags, requestLogger, config, getApiVersionDispatcher()
);

final DBInstanceFactory dbInstanceFactory = factoryFactory.createFactory(model);
return ProgressEvent.progress(model, callbackContext)
.then(progress -> {
if (StringUtils.isNullOrEmpty(progress.getResourceModel().getEngine())) {
Expand All @@ -109,21 +104,12 @@ proxy, rdsProxyClient, allTags, requestLogger, config, getApiVersionDispatcher()
}
return progress;
})
.then(progress -> Commons.execOnce(progress, () -> {
final DBInstanceFactory dbInstanceFactory = factoryFactory.createFactory(progress);

if (ResourceModelHelper.isRestoreToPointInTime(progress.getResourceModel())) {
// restoreDBInstanceToPointInTime is not a versioned call.
return safeAddTags(this::restoreDbInstanceToPointInTimeRequest)
.invoke(proxy, rdsProxyClient.defaultClient(), progress, allTags);
} else if (ResourceModelHelper.isReadReplica(progress.getResourceModel())) {
// createDBInstanceReadReplica is not a versioned call.
return safeAddTags(this::createDbInstanceReadReplica)
.invoke(proxy, rdsProxyClient.defaultClient(), progress, allTags);
}
// FIXME Currently only handling the fresh instance & snapshot. TODO Handle above cases in factory.
return dbInstanceFactory.create(progress);
}, CallbackContext::isCreated, CallbackContext::setCreated))
.then(progress -> Commons.execOnce(
progress,
() -> dbInstanceFactory.create(progress),
CallbackContext::isCreated,
CallbackContext::setCreated
))
.then(progress -> Commons.execOnce(progress, () -> {
final Tagging.TagSet extraTags = Tagging.TagSet.builder()
.stackTags(allTags.getStackTags())
Expand Down Expand Up @@ -260,63 +246,6 @@ private String fetchEngine(final ProxyClient<RdsClient> client,
throw new CfnInvalidRequestException("Cannot fetch the engine based on current template. Please add the Engine parameter to the template and try again.");
}

private ProgressEvent<ResourceModel, CallbackContext> restoreDbInstanceToPointInTimeRequest(
final AmazonWebServicesClientProxy proxy,
final ProxyClient<RdsClient> rdsProxyClient,
final ProgressEvent<ResourceModel, CallbackContext> progress,
final Tagging.TagSet tagSet
) {
return proxy.initiate(
"rds::restore-db-instance-to-point-in-time",
rdsProxyClient,
progress.getResourceModel(),
progress.getCallbackContext()
).translateToServiceRequest(model -> Translator.restoreDbInstanceToPointInTimeRequest(model, tagSet))
.backoffDelay(config.getBackoff())
.makeServiceCall((restoreRequest, proxyInvocation) -> proxyInvocation.injectCredentialsAndInvokeV2(
restoreRequest,
proxyInvocation.client()::restoreDBInstanceToPointInTime
))
.stabilize((request, response, proxyInvocation, model, context) ->
isDBInstanceStabilizedAfterMutate(proxyInvocation, model, context))
.handleError((request, exception, client, model, context) -> Commons.handleException(
ProgressEvent.progress(model, context),
exception,
ErrorRuleSets.RESTORE_DB_INSTANCE,
requestLogger
))
.progress();
}

private ProgressEvent<ResourceModel, CallbackContext> createDbInstanceReadReplica(
final AmazonWebServicesClientProxy proxy,
final ProxyClient<RdsClient> rdsProxyClient,
final ProgressEvent<ResourceModel, CallbackContext> progress,
final Tagging.TagSet tagSet
) {
final String currentRegion = progress.getCallbackContext().getCurrentRegion();
return proxy.initiate(
"rds::create-db-instance-read-replica",
rdsProxyClient,
progress.getResourceModel(),
progress.getCallbackContext()
).translateToServiceRequest(model -> Translator.createDbInstanceReadReplicaRequest(model, tagSet, currentRegion))
.backoffDelay(config.getBackoff())
.makeServiceCall((createRequest, proxyInvocation) -> proxyInvocation.injectCredentialsAndInvokeV2(
createRequest,
proxyInvocation.client()::createDBInstanceReadReplica
))
.stabilize((request, response, proxyInvocation, model, context) ->
isDBInstanceStabilizedAfterMutate(proxyInvocation, model, context))
.handleError((request, exception, client, model, context) -> Commons.handleException(
ProgressEvent.progress(model, context),
exception,
ErrorRuleSets.CREATE_DB_INSTANCE_READ_REPLICA,
requestLogger
))
.progress();
}

protected ProgressEvent<ResourceModel, CallbackContext> updateDbInstanceAfterCreateV12(
final AmazonWebServicesClientProxy proxy,
final ResourceHandlerRequest<ResourceModel> request,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ public static CreateDbInstanceRequest createDbInstanceRequest(
return builder.build();
}

static RestoreDbInstanceToPointInTimeRequest restoreDbInstanceToPointInTimeRequest(
public static RestoreDbInstanceToPointInTimeRequest restoreDbInstanceToPointInTimeRequest(
final ResourceModel model,
final Tagging.TagSet tagSet
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
import software.amazon.cloudformation.proxy.ProgressEvent;
import software.amazon.rds.dbinstance.CallbackContext;
import software.amazon.rds.dbinstance.ResourceModel;
import software.amazon.rds.dbinstance.util.ResourceModelHelper;

public interface DBInstanceFactory {

ProgressEvent<ResourceModel, CallbackContext> create(
ProgressEvent<ResourceModel, CallbackContext> input
ProgressEvent<ResourceModel, CallbackContext> input
);

boolean modelSatisfiesConstructor(ResourceModel model);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import lombok.AllArgsConstructor;
import software.amazon.awssdk.services.rds.RdsClient;
import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy;
import software.amazon.cloudformation.proxy.ProgressEvent;
import software.amazon.rds.common.handler.HandlerConfig;
import software.amazon.rds.common.handler.Tagging;
import software.amazon.rds.common.logging.RequestLogger;
Expand All @@ -13,54 +12,70 @@
import software.amazon.rds.dbinstance.client.VersionedProxyClient;
import software.amazon.rds.dbinstance.util.ResourceModelHelper;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Optional;

@AllArgsConstructor
public class DBInstanceFactoryFactory {

private final AmazonWebServicesClientProxy proxy;
private final VersionedProxyClient<RdsClient> rdsProxyClient;
private final Tagging.TagSet allTags;
private final RequestLogger requestLogger;
private final HandlerConfig config;
private final ApiVersionDispatcher<ResourceModel, CallbackContext> apiVersionDispatcher;
private final Collection<DBInstanceFactory> factories;
private final DBInstanceFactory defaultFactory;

public DBInstanceFactoryFactory(
final AmazonWebServicesClientProxy proxy,
final VersionedProxyClient<RdsClient> rdsProxyClient,
final Tagging.TagSet allTags,
final RequestLogger requestLogger,
final HandlerConfig config,
final ApiVersionDispatcher<ResourceModel, CallbackContext> apiVersionDispatcher
) {

factories = new ArrayList<>();
// The order of this list matters. Do NOT re-order.
factories.add(new FromPointInTime(
proxy,
rdsProxyClient,
allTags,
requestLogger,
config
));
factories.add(new ReadReplica(
proxy,
rdsProxyClient,
allTags,
requestLogger,
config
));
factories.add(new FromSnapshot(
proxy,
rdsProxyClient,
allTags,
requestLogger,
config,
apiVersionDispatcher
));

private enum FactoryType {
IS_READ_REPLICA,
IS_FROM_SNAPSHOT,
IS_FROM_POINT_IN_TIME,
IS_FRESH_INSTANCE;
defaultFactory = new FreshInstance(
proxy,
rdsProxyClient,
allTags,
requestLogger,
config,
apiVersionDispatcher
);
}

public DBInstanceFactory createFactory(
ProgressEvent<ResourceModel, CallbackContext> progress
) {
switch (discernFactoryType(progress.getResourceModel())) {
case IS_FROM_SNAPSHOT:
return new FromSnapshot(
proxy,
rdsProxyClient,
allTags,
requestLogger,
config,
apiVersionDispatcher
);
case IS_FRESH_INSTANCE:
default:
return new FreshInstance(
proxy,
rdsProxyClient,
allTags,
requestLogger,
config,
apiVersionDispatcher
);
}
public DBInstanceFactory createFactory(ResourceModel model) {
return discernFactoryType(model).orElse(defaultFactory);
}

private FactoryType discernFactoryType(ResourceModel model) {
if(ResourceModelHelper.isRestoreFromSnapshot(model) || ResourceModelHelper.isRestoreFromClusterSnapshot(model)) {
return FactoryType.IS_FROM_SNAPSHOT;
private Optional<DBInstanceFactory> discernFactoryType(ResourceModel model) {
for (DBInstanceFactory fac : factories) {
if (fac.modelSatisfiesConstructor(model)) {
return Optional.of(fac);
}
}

return FactoryType.IS_FRESH_INSTANCE;
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class FreshInstance implements DBInstanceFactory {
private final HandlerConfig config;
private final ApiVersionDispatcher<ResourceModel, CallbackContext> apiVersionDispatcher;

@Override
public ProgressEvent<ResourceModel, CallbackContext> create(ProgressEvent<ResourceModel, CallbackContext> progress) {
final ResourceModel model = progress.getResourceModel();
final CallbackContext callbackContext = progress.getCallbackContext();
Expand All @@ -43,6 +44,11 @@ public ProgressEvent<ResourceModel, CallbackContext> create(ProgressEvent<Resour
return safeAddTags(this::createDbInstance).invoke(proxy, rdsProxyClient.forVersion(apiVersion), progress, allTags);
}

@Override
public boolean modelSatisfiesConstructor(ResourceModel model) {
return true;
}

private ProgressEvent<ResourceModel, CallbackContext> createDbInstance(
final AmazonWebServicesClientProxy proxy,
final ProxyClient<RdsClient> rdsProxyClient,
Expand All @@ -61,8 +67,7 @@ private ProgressEvent<ResourceModel, CallbackContext> createDbInstance(
createRequest,
proxyInvocation.client()::createDBInstance
))
.stabilize((request, response, proxyInvocation, model, context) ->
{
.stabilize((request, response, proxyInvocation, model, context) -> {
final DBInstance dbInstance = fetch.dbInstance(model);
return DBInstancePredicates.isDBInstanceStabilizedAfterMutate(dbInstance, model, context, requestLogger);
})
Expand Down
Loading

0 comments on commit 0aee70d

Please sign in to comment.