-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[CFN-27] Working towards a more extensible DBInstance create flow. St…
…atic methods and error rules have been pulled out of the base handler class; The instance create factory is now constructed by factory according to the model. [CFN-27] Continuing to seperate db-instance create flows. This pulls out the create from snapshot logic at the cost of some more copy pasta to be addressed in the next commit. [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). ...
- Loading branch information
Keynan Pratt
committed
Nov 25, 2024
1 parent
fc6dbea
commit 9727a77
Showing
13 changed files
with
733 additions
and
366 deletions.
There are no files selected for viewing
4 changes: 4 additions & 0 deletions
4
aws-rds-cfn-common/src/main/java/software/amazon/rds/ProgressStep.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package software.amazon.rds; | ||
|
||
public class ProgressStep { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
513 changes: 156 additions & 357 deletions
513
aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/CreateHandler.java
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/common/Fetch.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package software.amazon.rds.dbinstance.common; | ||
|
||
import lombok.AllArgsConstructor; | ||
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.DescribeDbInstancesResponse; | ||
import software.amazon.awssdk.services.rds.model.DescribeDbSnapshotsResponse; | ||
import software.amazon.cloudformation.proxy.ProxyClient; | ||
import software.amazon.rds.dbinstance.ResourceModel; | ||
import software.amazon.rds.dbinstance.Translator; | ||
|
||
@AllArgsConstructor | ||
public class Fetch { | ||
private final ProxyClient<RdsClient> rdsProxyClient; | ||
|
||
public DBInstance dbInstance(final ResourceModel model) { | ||
final DescribeDbInstancesResponse response = rdsProxyClient.injectCredentialsAndInvokeV2( | ||
Translator.describeDbInstancesRequest(model), | ||
rdsProxyClient.client()::describeDBInstances | ||
); | ||
return response.dbInstances().get(0); | ||
} | ||
|
||
public DBSnapshot dbSnapshot(final ResourceModel model) { | ||
final DescribeDbSnapshotsResponse response = rdsProxyClient.injectCredentialsAndInvokeV2( | ||
Translator.describeDbSnapshotsRequest(model), | ||
rdsProxyClient.client()::describeDBSnapshots | ||
); | ||
return response.dbSnapshots().get(0); | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
...nstance/src/main/java/software/amazon/rds/dbinstance/common/create/DBInstanceFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package software.amazon.rds.dbinstance.common.create; | ||
|
||
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 | ||
); | ||
|
||
boolean modelSatisfiesConstructor(ResourceModel model); | ||
} |
81 changes: 81 additions & 0 deletions
81
.../src/main/java/software/amazon/rds/dbinstance/common/create/DBInstanceFactoryFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package software.amazon.rds.dbinstance.common.create; | ||
|
||
import lombok.AllArgsConstructor; | ||
import software.amazon.awssdk.services.rds.RdsClient; | ||
import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy; | ||
import software.amazon.rds.common.handler.HandlerConfig; | ||
import software.amazon.rds.common.handler.Tagging; | ||
import software.amazon.rds.common.logging.RequestLogger; | ||
import software.amazon.rds.dbinstance.CallbackContext; | ||
import software.amazon.rds.dbinstance.ResourceModel; | ||
import software.amazon.rds.dbinstance.client.ApiVersionDispatcher; | ||
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 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 | ||
)); | ||
|
||
defaultFactory = new FreshInstance( | ||
proxy, | ||
rdsProxyClient, | ||
allTags, | ||
requestLogger, | ||
config, | ||
apiVersionDispatcher | ||
); | ||
} | ||
|
||
public DBInstanceFactory createFactory(ResourceModel model) { | ||
return discernFactoryType(model).orElse(defaultFactory); | ||
} | ||
|
||
private Optional<DBInstanceFactory> discernFactoryType(ResourceModel model) { | ||
for (DBInstanceFactory fac : factories) { | ||
if (fac.modelSatisfiesConstructor(model)) { | ||
return Optional.of(fac); | ||
} | ||
} | ||
return Optional.empty(); | ||
} | ||
} |
125 changes: 125 additions & 0 deletions
125
...-dbinstance/src/main/java/software/amazon/rds/dbinstance/common/create/FreshInstance.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
package software.amazon.rds.dbinstance.common.create; | ||
|
||
import lombok.AllArgsConstructor; | ||
import software.amazon.awssdk.services.rds.RdsClient; | ||
import software.amazon.awssdk.services.rds.model.DBInstance; | ||
import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy; | ||
import software.amazon.cloudformation.proxy.ProgressEvent; | ||
import software.amazon.cloudformation.proxy.ProxyClient; | ||
import software.amazon.rds.common.handler.Commons; | ||
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.logging.RequestLogger; | ||
import software.amazon.rds.dbinstance.CallbackContext; | ||
import software.amazon.rds.dbinstance.DBInstancePredicates; | ||
import software.amazon.rds.dbinstance.ResourceModel; | ||
import software.amazon.rds.dbinstance.Translator; | ||
import software.amazon.rds.dbinstance.client.ApiVersion; | ||
import software.amazon.rds.dbinstance.client.ApiVersionDispatcher; | ||
import software.amazon.rds.dbinstance.client.VersionedProxyClient; | ||
import software.amazon.rds.dbinstance.common.ErrorRuleSets; | ||
import software.amazon.rds.dbinstance.common.Fetch; | ||
|
||
@AllArgsConstructor | ||
public class FreshInstance implements DBInstanceFactory { | ||
|
||
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; | ||
|
||
@Override | ||
public ProgressEvent<ResourceModel, CallbackContext> create(ProgressEvent<ResourceModel, CallbackContext> progress) { | ||
final ResourceModel model = progress.getResourceModel(); | ||
final CallbackContext callbackContext = progress.getCallbackContext(); | ||
final ApiVersion apiVersion = selectVersion(model, callbackContext); | ||
|
||
if (apiVersion == ApiVersion.V12) { | ||
return createDbInstanceV12(proxy, rdsProxyClient.forVersion(apiVersion), progress, allTags); | ||
} | ||
|
||
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, | ||
final ProgressEvent<ResourceModel, CallbackContext> progress, | ||
final Tagging.TagSet tagSet | ||
) { | ||
final Fetch fetch = new Fetch(rdsProxyClient); | ||
return proxy.initiate( | ||
"rds::create-db-instance", | ||
rdsProxyClient, | ||
progress.getResourceModel(), | ||
progress.getCallbackContext() | ||
).translateToServiceRequest(model -> Translator.createDbInstanceRequest(model, tagSet)) | ||
.backoffDelay(config.getBackoff()) | ||
.makeServiceCall((createRequest, proxyInvocation) -> proxyInvocation.injectCredentialsAndInvokeV2( | ||
createRequest, | ||
proxyInvocation.client()::createDBInstance | ||
)) | ||
.stabilize((request, response, proxyInvocation, model, context) -> { | ||
final DBInstance dbInstance = fetch.dbInstance(model); | ||
return DBInstancePredicates.isDBInstanceStabilizedAfterMutate(dbInstance, model, context, requestLogger); | ||
}) | ||
.handleError((request, exception, client, model, context) -> Commons.handleException( | ||
ProgressEvent.progress(model, context), | ||
exception, | ||
software.amazon.rds.dbinstance.common.ErrorRuleSets.CREATE_DB_INSTANCE, | ||
requestLogger | ||
)) | ||
.progress(); | ||
} | ||
|
||
private ProgressEvent<ResourceModel, CallbackContext> createDbInstanceV12( | ||
final AmazonWebServicesClientProxy proxy, | ||
final ProxyClient<RdsClient> rdsProxyClient, | ||
final ProgressEvent<ResourceModel, CallbackContext> progress, | ||
final Tagging.TagSet tagSet | ||
) { | ||
requestLogger.log("CreateDbInstanceAPIv12Invoked"); | ||
requestLogger.log("API version 12 create detected", | ||
"This indicates that the customer is using DBSecurityGroup, which may result in certain features not" + | ||
" functioning properly. Please refer to the API model for supported parameters"); | ||
final Fetch fetch = new Fetch(rdsProxyClient); | ||
return proxy.initiate( | ||
"rds::create-db-instance-v12", | ||
rdsProxyClient, | ||
progress.getResourceModel(), | ||
progress.getCallbackContext() | ||
).translateToServiceRequest(Translator::createDbInstanceRequestV12) | ||
.backoffDelay(config.getBackoff()) | ||
.makeServiceCall((createRequest, proxyInvocation) -> proxyInvocation.injectCredentialsAndInvokeV2( | ||
createRequest, | ||
proxyInvocation.client()::createDBInstance | ||
)) | ||
.stabilize((request, response, proxyInvocation, model, context) -> { | ||
final DBInstance dbInstance = fetch.dbInstance(model); | ||
return DBInstancePredicates.isDBInstanceStabilizedAfterMutate(dbInstance, model, context, requestLogger); | ||
}) | ||
.handleError((request, exception, client, model, context) -> Commons.handleException( | ||
ProgressEvent.progress(model, context), | ||
exception, | ||
ErrorRuleSets.CREATE_DB_INSTANCE, | ||
requestLogger | ||
)) | ||
.progress(); | ||
} | ||
|
||
private ApiVersion selectVersion(ResourceModel model, CallbackContext callbackContext) { | ||
return apiVersionDispatcher.dispatch(model, callbackContext); | ||
} | ||
|
||
private HandlerMethod<ResourceModel, CallbackContext> safeAddTags(final HandlerMethod<ResourceModel, CallbackContext> handlerMethod) { | ||
return (proxy, rdsProxyClient, progress, tagSet) -> progress.then(p -> Tagging.createWithTaggingFallback(proxy, rdsProxyClient, handlerMethod, progress, tagSet)); | ||
} | ||
} |
Oops, something went wrong.