Skip to content

Commit

Permalink
Updated Canary handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
aolsh99 committed May 5, 2023
1 parent e491ba8 commit 3d1871a
Show file tree
Hide file tree
Showing 12 changed files with 543 additions and 494 deletions.
15 changes: 12 additions & 3 deletions aws-synthetics-canary/aws-synthetics-canary.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@
},
"Handler": {
"type": "string"
},
"SourceLocationArn": {
"type": "string"
}
},
"required": [
Expand Down Expand Up @@ -275,8 +278,7 @@
"ArtifactS3Location",
"ExecutionRoleArn",
"Schedule",
"RuntimeVersion",
"StartCanaryAfterCreation"
"RuntimeVersion"
],
"handlers": {
"create": {
Expand Down Expand Up @@ -349,6 +351,13 @@
"/properties/Code/S3Bucket",
"/properties/Code/S3Key",
"/properties/Code/S3ObjectVersion",
"/properties/Code/Script"
"/properties/Code/Script",
"/properties/DeleteLambdaResourcesOnCanaryDeletion",
"/properties/StartCanaryAfterCreation",
"/properties/RunConfig/EnvironmentVariables",
"/properties/VisualReference"
],
"deprecatedProperties": [
"/properties/DeleteLambdaResourcesOnCanaryDeletion"
]
}
7 changes: 7 additions & 0 deletions aws-synthetics-canary/resource-role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ Resources:
Principal:
Service: resources.cloudformation.amazonaws.com
Action: sts:AssumeRole
Condition:
StringEquals:
aws:SourceAccount:
Ref: AWS::AccountId
StringLike:
aws:SourceArn:
Fn::Sub: arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:type/resource/AWS-Synthetics-Canary/*
Path: "/"
Policies:
- PolicyName: ResourceTypePolicy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.google.common.base.Strings;
import software.amazon.awssdk.services.synthetics.SyntheticsClient;
import software.amazon.awssdk.services.synthetics.model.ArtifactConfigOutput;
import software.amazon.awssdk.services.synthetics.model.Canary;
import software.amazon.awssdk.services.synthetics.model.CanaryRunConfigOutput;
import software.amazon.awssdk.services.synthetics.model.GetCanaryRequest;
Expand Down Expand Up @@ -39,6 +40,14 @@ public static boolean isNullOrEmpty(CanaryRunConfigOutput runConfigOutput) {
&& runConfigOutput.memoryInMB() == null;
}

public static boolean isNullOrEmpty(ArtifactConfigOutput artifactConfigOutput) {
if (artifactConfigOutput == null || artifactConfigOutput.s3Encryption() == null) {
return true;
}

return artifactConfigOutput.s3Encryption().encryptionMode() == null;
}

public static Canary getCanaryOrNull(AmazonWebServicesClientProxy proxy,
SyntheticsClient syntheticsClient,
String canaryName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ protected ProgressEvent<ResourceModel, CallbackContext> handleRequest() {

private ProgressEvent<ResourceModel, CallbackContext> handleCanaryInStateReady(Canary canary) {
log("Canary is in state READY.");
if (model.getStartCanaryAfterCreation()) {
if (model.getStartCanaryAfterCreation() != null && model.getStartCanaryAfterCreation()) {
// There is a race condition here. We will get an exception if someone calls
// DeleteCanary, StartCanary, or UpdateCanary before we call StartCanary.

Expand All @@ -80,7 +80,7 @@ private ProgressEvent<ResourceModel, CallbackContext> handleCanaryInStateStartin
// If the customer calls StartCanary before we handle the canary in READY state,
// then we can end up here even when StartCanaryAfterCreation is false.

if (model.getStartCanaryAfterCreation()) {
if (model.getStartCanaryAfterCreation() != null && model.getStartCanaryAfterCreation()) {
return waitingForCanaryStateTransition(
"Starting canary",
"Canary is in state STARTING.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,11 @@ public class ModelHelper {
// Python Runtime
private static final String PYTHON_DIR = "/python/";
private static final String PY_SUFFIX = ".py";
private static final String PYTHON_PATTERN = "^syn-python-*";
private static final String PYTHON_PATTERN = "^syn-python-.*";
private static final Pattern python_pattern = Pattern.compile(PYTHON_PATTERN);

public static ResourceModel constructModel(Canary canary, ResourceModel model) {
Map<String, String> tags = canary.tags();

model.setId(canary.id());
model.setName(canary.name());
model.setArtifactS3Location("s3://" + canary.artifactS3Location());
Expand All @@ -48,7 +47,6 @@ public static ResourceModel constructModel(Canary canary, ResourceModel model) {
model.setSuccessRetentionPeriod(canary.successRetentionPeriodInDays());
model.setRuntimeVersion(canary.runtimeVersion());
model.setState(canary.status().stateAsString());

model.setCode(buildCodeObject(canary.code()));
model.setSchedule(buildCanaryScheduleObject(canary.schedule()));
// Tags are optional. Check for null
Expand All @@ -67,12 +65,23 @@ public static ResourceModel constructModel(Canary canary, ResourceModel model) {
.build());
}

if (!CanaryHelper.isNullOrEmpty(canary.artifactConfig())) {
model.setArtifactConfig(ArtifactConfig.builder()
.s3Encryption(
S3Encryption.builder()
.encryptionMode(canary.artifactConfig().s3Encryption().encryptionModeAsString())
.kmsKeyArn(canary.artifactConfig().s3Encryption().kmsKeyArn())
.build())
.build());
}

return model;
}

private static Code buildCodeObject(CanaryCodeOutput canaryCodeOutput) {
return Code.builder()
.handler(canaryCodeOutput.handler())
.sourceLocationArn(canaryCodeOutput.sourceLocationArn())
.build();
}

Expand Down Expand Up @@ -172,6 +181,7 @@ public static String buildCanaryArn(ResourceHandlerRequest<ResourceModel> reques
public static Map<String, String> buildTagInputMap(ResourceModel model) {
Map<String, String> tagMap = new HashMap<>();
List<Tag> tagList = model.getTags();

// return null if no Tag specified.
if (tagList == null) return null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,28 @@

import com.google.common.base.Strings;
import java.util.Objects;
import software.amazon.awssdk.services.synthetics.model.*;

import software.amazon.awssdk.services.synthetics.model.ArtifactConfigInput;
import software.amazon.awssdk.services.synthetics.model.Canary;
import software.amazon.awssdk.services.synthetics.model.CanaryCodeInput;
import software.amazon.awssdk.services.synthetics.model.CanaryRunConfigInput;
import software.amazon.awssdk.services.synthetics.model.CanaryScheduleInput;
import software.amazon.awssdk.services.synthetics.model.CanaryState;
import software.amazon.awssdk.services.synthetics.model.StartCanaryRequest;
import software.amazon.awssdk.services.synthetics.model.StopCanaryRequest;
import software.amazon.awssdk.services.synthetics.model.TagResourceRequest;
import software.amazon.awssdk.services.synthetics.model.UntagResourceRequest;
import software.amazon.awssdk.services.synthetics.model.UpdateCanaryRequest;
import software.amazon.awssdk.services.synthetics.model.ValidationException;
import software.amazon.awssdk.services.synthetics.model.VisualReferenceInput;
import software.amazon.awssdk.services.synthetics.model.VpcConfigInput;
import software.amazon.cloudformation.Action;
import software.amazon.cloudformation.exceptions.*;
import software.amazon.cloudformation.proxy.*;
import software.amazon.cloudformation.exceptions.CfnGeneralServiceException;
import software.amazon.cloudformation.exceptions.CfnInvalidRequestException;
import software.amazon.cloudformation.proxy.HandlerErrorCode;
import software.amazon.cloudformation.proxy.OperationStatus;
import software.amazon.cloudformation.proxy.ProgressEvent;


import java.util.Collections;
import java.util.Map;
Expand Down Expand Up @@ -97,7 +115,7 @@ private ProgressEvent<ResourceModel, CallbackContext> handleCanaryInStateReadyOr
canary.status().stateReason());
}

if (model.getStartCanaryAfterCreation()) {
if (model.getStartCanaryAfterCreation() != null && model.getStartCanaryAfterCreation()) {
// There is a race condition here. We will get an exception if someone calls
// DeleteCanary, StartCanary, or UpdateCanary before we call StartCanary.

Expand All @@ -117,7 +135,7 @@ private ProgressEvent<ResourceModel, CallbackContext> handleCanaryInStateStartin
// If the customer calls StartCanary before we handle the canary in READY or
// STOPPED state, then we can end up here even when StartCanaryAfterCreation is false.

if (model.getStartCanaryAfterCreation()) {
if (model.getStartCanaryAfterCreation() != null && model.getStartCanaryAfterCreation()) {
return waitingForCanaryStateTransition(
"Starting canary",
"Canary is in state STARTING.",
Expand Down Expand Up @@ -147,7 +165,7 @@ private ProgressEvent<ResourceModel, CallbackContext> handleCanaryInStateRunning

// If the canary was initially in state RUNNING and StartCanaryAfterCreation is
// false, we should stop the canary.
if (!model.getStartCanaryAfterCreation()) {
if (model.getStartCanaryAfterCreation() == null || !model.getStartCanaryAfterCreation()) {
// There is a race condition here. We will get an exception if someone calls
// DeleteCanary, StopCanary, or UpdateCanary before we call StopCanary.
proxy.injectCredentialsAndInvokeV2(
Expand Down
Loading

0 comments on commit 3d1871a

Please sign in to comment.