diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/SyntheticsCanaryRetryDefaultTestDeployAssert341E434F.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/SyntheticsCanaryRetryDefaultTestDeployAssert341E434F.assets.json new file mode 100644 index 0000000000000..ac6f36f43697e --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/SyntheticsCanaryRetryDefaultTestDeployAssert341E434F.assets.json @@ -0,0 +1,20 @@ +{ + "version": "45.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "displayName": "SyntheticsCanaryRetryDefaultTestDeployAssert341E434F Template", + "source": { + "path": "SyntheticsCanaryRetryDefaultTestDeployAssert341E434F.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/SyntheticsCanaryRetryDefaultTestDeployAssert341E434F.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/SyntheticsCanaryRetryDefaultTestDeployAssert341E434F.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/SyntheticsCanaryRetryDefaultTestDeployAssert341E434F.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/SyntheticsCanaryRetryStack.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/SyntheticsCanaryRetryStack.assets.json new file mode 100644 index 0000000000000..4402216f4e91d --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/SyntheticsCanaryRetryStack.assets.json @@ -0,0 +1,34 @@ +{ + "version": "45.0.0", + "files": { + "5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f": { + "displayName": "RetryCanary/Code", + "source": { + "path": "asset.5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "bb7088ad2a940f3f3e4e2bddcb75f539d2fd3fb5128081ffa02f6054249b0098": { + "displayName": "SyntheticsCanaryRetryStack Template", + "source": { + "path": "SyntheticsCanaryRetryStack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "bb7088ad2a940f3f3e4e2bddcb75f539d2fd3fb5128081ffa02f6054249b0098.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/SyntheticsCanaryRetryStack.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/SyntheticsCanaryRetryStack.template.json new file mode 100644 index 0000000000000..77acd96d50678 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/SyntheticsCanaryRetryStack.template.json @@ -0,0 +1,242 @@ +{ + "Resources": { + "RetryCanaryArtifactsBucket96F3BE6A": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketEncryption": { + "ServerSideEncryptionConfiguration": [ + { + "ServerSideEncryptionByDefault": { + "SSEAlgorithm": "aws:kms" + } + } + ] + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "RetryCanaryArtifactsBucketPolicy381668A7": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "RetryCanaryArtifactsBucket96F3BE6A" + }, + "PolicyDocument": { + "Statement": [ + { + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "RetryCanaryArtifactsBucket96F3BE6A", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "RetryCanaryArtifactsBucket96F3BE6A", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + } + }, + "RetryCanaryServiceRole6EAC7F33": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": "s3:ListAllMyBuckets", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "s3:GetBucketLocation", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "RetryCanaryArtifactsBucket96F3BE6A", + "Arn" + ] + } + }, + { + "Action": "s3:PutObject", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "RetryCanaryArtifactsBucket96F3BE6A", + "Arn" + ] + }, + "/*" + ] + ] + } + }, + { + "Action": "cloudwatch:PutMetricData", + "Condition": { + "StringEquals": { + "cloudwatch:namespace": "CloudWatchSynthetics" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":log-group:/aws/lambda/cwsyn-*" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "canaryPolicy" + } + ] + } + }, + "RetryCanary3B0C27B7": { + "Type": "AWS::Synthetics::Canary", + "Properties": { + "ArtifactS3Location": { + "Fn::Join": [ + "", + [ + "s3://", + { + "Ref": "RetryCanaryArtifactsBucket96F3BE6A" + } + ] + ] + }, + "Code": { + "Handler": "canary.handler", + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f.zip" + }, + "ExecutionRoleArn": { + "Fn::GetAtt": [ + "RetryCanaryServiceRole6EAC7F33", + "Arn" + ] + }, + "Name": "retry", + "RunConfig": { + "MemoryInMB": 2048, + "TimeoutInSeconds": 240 + }, + "RuntimeVersion": "syn-python-selenium-5.1", + "Schedule": { + "DurationInSeconds": "0", + "Expression": "rate(5 minutes)", + "RetryConfig": { + "MaxRetries": 2 + } + }, + "StartCanaryAfterCreation": true + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/asset.5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f/canary.mjs b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/asset.5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f/canary.mjs new file mode 100644 index 0000000000000..eb6bd4e9b823d --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/asset.5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f/canary.mjs @@ -0,0 +1,87 @@ +import { URL } from 'url'; +import { synthetics } from '@amzn/synthetics-playwright'; + +const loadBlueprints = async function () { + const urls = [process.env.URL]; + + const browser = await synthetics.launch(); + const browserContext = await browser.newContext(); + let page = await synthetics.newPage(browserContext); + + for (const url of urls) { + await loadUrl(page, url); + } + + // Ensure browser is closed + await synthetics.close(); +}; + +// Reset the page in-between +const resetPage = async function(page) { + try { + // Set page.goto timeout to 30 seconds, adjust as needed + // See https://playwright.dev/docs/api/class-page for page.goto options + await page.goto('about:blank', { waitUntil: 'load', timeout: 30000 }); + } catch (e) { + console.error('Unable to open a blank page. ', e); + } +}; + +const loadUrl = async function (page, url) { + let stepName = null; + let domcontentloaded = false; + + try { + stepName = new URL(url).hostname; + } catch (e) { + const errorString = `Error parsing url: ${url}. ${e}`; + log.error(errorString); + /* If we fail to parse the URL, don't emit a metric with a stepName based on it. + It may not be a legal CloudWatch metric dimension name and we may not have an alarms + setup on the malformed URL stepName. Instead, fail this step which will + show up in the logs and will fail the overall canary and alarm on the overall canary + success rate. + */ + throw e; + }; + + await synthetics.executeStep(stepName, async function () { + try { + /* You can customize the wait condition here. + 'domcontentloaded' - consider operation to be finished when the DOMContentLoaded event is fired. + 'load' - consider operation to be finished when the load event is fired. + 'networkidle' - DISCOURAGED consider operation to be finished when there are no network connections for at least 500 ms. Don't use this method for testing, rely on web assertions to assess readiness instead. + 'commit' - consider operation to be finished when network response is received and the document started loading. + + Set page.goto timeout to 30 seconds, adjust as needed + See https://playwright.dev/docs/api/class-page for page.goto options + */ + const response = await page.goto(url, { waitUntil: 'load', timeout: 30000 }); + if (response) { + domcontentloaded = true; + const status = response.status(); + console.log(`Response status: ${status}`); + + // If the response status code is not a 2xx success code + if (status < 200 || status > 299) { + console.error(`Failed to load url: ${url}, status code: ${status}`); + throw new Error('Failed'); + } + } else { + console.error(`No response returned for url: ${url}`); + throw new Error(logNoResponseString); + } + } catch (e) { + const errorString = `Error navigating to url: ${url}. ${e}`; + console.error(errorString); + throw e; + } + }); + + // Reset page + await resetPage(page); +}; + +export const handler = async (event, context) => { + return await loadBlueprints(); +}; \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/asset.5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f/nodejs/node_modules/canary.js b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/asset.5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f/nodejs/node_modules/canary.js new file mode 100644 index 0000000000000..d7936811fd8c1 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/asset.5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f/nodejs/node_modules/canary.js @@ -0,0 +1,52 @@ +var synthetics = require('Synthetics'); +const log = require('SyntheticsLogger'); +const https = require('https'); +const http = require('http'); + +const apiCanaryBlueprint = async function () { + const postData = ""; + + const verifyRequest = async function (requestOption) { + return new Promise((resolve, reject) => { + log.info("Making request with options: " + JSON.stringify(requestOption)); + let req + if (requestOption.protocol === 'https:') { + req = https.request(requestOption); + } else { + req = http.request(requestOption); + } + req.on('response', (res) => { + log.info(`Status Code: ${res.statusCode}`) + log.info(`Response Headers: ${JSON.stringify(res.headers)}`) + if (res.statusCode !== 200) { + reject("Failed: " + requestOption.pathname); + } + res.on('data', (d) => { + log.info("Response: " + d); + }); + res.on('end', () => { + resolve(); + }) + }); + + req.on('error', (error) => { + reject(error); + }); + + if (postData) { + req.write(postData); + } + req.end(); + }); + } + + const headers = {} + headers['User-Agent'] = [synthetics.getCanaryUserAgentString(), headers['User-Agent']].join(' '); + const requestOptions = new URL(process.env.URL); + requestOptions['headers'] = headers; + await verifyRequest(requestOptions); +}; + +exports.handler = async () => { + return await apiCanaryBlueprint(); +}; \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/asset.5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f/nodejs/node_modules/folder/canary.js b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/asset.5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f/nodejs/node_modules/folder/canary.js new file mode 100644 index 0000000000000..2ee399fbc633f --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/asset.5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f/nodejs/node_modules/folder/canary.js @@ -0,0 +1,52 @@ +var synthetics = require('Synthetics'); +const log = require('SyntheticsLogger'); +const https = require('https'); +const http = require('http'); + +const apiCanaryBlueprint = async function () { + const postData = ""; + + const verifyRequest = async function (requestOption) { + return new Promise((resolve, reject) => { + log.info("Making request with options: " + JSON.stringify(requestOption)); + let req + if (requestOption.protocol === 'https:') { + req = https.request(requestOption); + } else { + req = http.request(requestOption); + } + req.on('response', (res) => { + log.info(`Status Code: ${res.statusCode}`) + log.info(`Response Headers: ${JSON.stringify(res.headers)}`) + if (res.statusCode !== 200) { + reject("Failed: " + requestOption.pathname); + } + res.on('data', (d) => { + log.info("Response: " + d); + }); + res.on('end', () => { + resolve(); + }) + }); + + req.on('error', (error) => { + reject(error); + }); + + if (postData) { + req.write(postData); + } + req.end(); + }); + } + + const headers = {} + headers['User-Agent'] = [synthetics.getCanaryUserAgentString(), headers['User-Agent']].join(' '); + const requestOptions = new URL(process.env.URL); + requestOptions['headers'] = headers; + await verifyRequest(requestOptions); +}; + +exports.functionName = async () => { + return await apiCanaryBlueprint(); +}; \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/asset.5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f/playwright/canary.mjs b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/asset.5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f/playwright/canary.mjs new file mode 100644 index 0000000000000..eb6bd4e9b823d --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/asset.5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f/playwright/canary.mjs @@ -0,0 +1,87 @@ +import { URL } from 'url'; +import { synthetics } from '@amzn/synthetics-playwright'; + +const loadBlueprints = async function () { + const urls = [process.env.URL]; + + const browser = await synthetics.launch(); + const browserContext = await browser.newContext(); + let page = await synthetics.newPage(browserContext); + + for (const url of urls) { + await loadUrl(page, url); + } + + // Ensure browser is closed + await synthetics.close(); +}; + +// Reset the page in-between +const resetPage = async function(page) { + try { + // Set page.goto timeout to 30 seconds, adjust as needed + // See https://playwright.dev/docs/api/class-page for page.goto options + await page.goto('about:blank', { waitUntil: 'load', timeout: 30000 }); + } catch (e) { + console.error('Unable to open a blank page. ', e); + } +}; + +const loadUrl = async function (page, url) { + let stepName = null; + let domcontentloaded = false; + + try { + stepName = new URL(url).hostname; + } catch (e) { + const errorString = `Error parsing url: ${url}. ${e}`; + log.error(errorString); + /* If we fail to parse the URL, don't emit a metric with a stepName based on it. + It may not be a legal CloudWatch metric dimension name and we may not have an alarms + setup on the malformed URL stepName. Instead, fail this step which will + show up in the logs and will fail the overall canary and alarm on the overall canary + success rate. + */ + throw e; + }; + + await synthetics.executeStep(stepName, async function () { + try { + /* You can customize the wait condition here. + 'domcontentloaded' - consider operation to be finished when the DOMContentLoaded event is fired. + 'load' - consider operation to be finished when the load event is fired. + 'networkidle' - DISCOURAGED consider operation to be finished when there are no network connections for at least 500 ms. Don't use this method for testing, rely on web assertions to assess readiness instead. + 'commit' - consider operation to be finished when network response is received and the document started loading. + + Set page.goto timeout to 30 seconds, adjust as needed + See https://playwright.dev/docs/api/class-page for page.goto options + */ + const response = await page.goto(url, { waitUntil: 'load', timeout: 30000 }); + if (response) { + domcontentloaded = true; + const status = response.status(); + console.log(`Response status: ${status}`); + + // If the response status code is not a 2xx success code + if (status < 200 || status > 299) { + console.error(`Failed to load url: ${url}, status code: ${status}`); + throw new Error('Failed'); + } + } else { + console.error(`No response returned for url: ${url}`); + throw new Error(logNoResponseString); + } + } catch (e) { + const errorString = `Error navigating to url: ${url}. ${e}`; + console.error(errorString); + throw e; + } + }); + + // Reset page + await resetPage(page); +}; + +export const handler = async (event, context) => { + return await loadBlueprints(); +}; \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/asset.5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f/python/canary.py b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/asset.5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f/python/canary.py new file mode 100644 index 0000000000000..fac8b8004a7a7 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/asset.5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f/python/canary.py @@ -0,0 +1,62 @@ +# This example comes from the AWS Synthetics service console "API canary" blueprint + +import os +import json +import http.client +import urllib.parse +from aws_synthetics.selenium import synthetics_webdriver as syn_webdriver +from aws_synthetics.common import synthetics_logger as logger + + +def verify_request(method, url, post_data=None, headers={}): + parsed_url = urllib.parse.urlparse(url) + user_agent = str(syn_webdriver.get_canary_user_agent_string()) + if "User-Agent" in headers: + headers["User-Agent"] = " ".join([user_agent, headers["User-Agent"]]) + else: + headers["User-Agent"] = "{}".format(user_agent) + + logger.info("Making request with Method: '%s' URL: %s: Data: %s Headers: %s" % ( + method, url, json.dumps(post_data), json.dumps(headers))) + + if parsed_url.scheme == "https": + conn = http.client.HTTPSConnection(parsed_url.hostname, parsed_url.port) + else: + conn = http.client.HTTPConnection(parsed_url.hostname, parsed_url.port) + + conn.request(method, url, post_data, headers) + response = conn.getresponse() + logger.info("Status Code: %s " % response.status) + logger.info("Response Headers: %s" % json.dumps(response.headers.as_string())) + + if not response.status or response.status < 200 or response.status > 299: + try: + logger.error("Response: %s" % response.read().decode()) + finally: + if response.reason: + conn.close() + raise Exception("Failed: %s" % response.reason) + else: + conn.close() + raise Exception("Failed with status code: %s" % response.status) + + logger.info("Response: %s" % response.read().decode()) + logger.info("HTTP request successfully executed") + conn.close() + + +def main(): + + url = os.environ['URL'] + method = 'GET' + postData = "" + headers = {} + + verify_request(method, url, None, headers) + + logger.info("Canary successfully executed") + + +def handler(event, context): + logger.info("Selenium Python API canary") + main() \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/cdk.out new file mode 100644 index 0000000000000..3704a1b682acf --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"45.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/integ.json new file mode 100644 index 0000000000000..d0df0fad099e4 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/integ.json @@ -0,0 +1,13 @@ +{ + "version": "45.0.0", + "testCases": { + "SyntheticsCanaryRetry/DefaultTest": { + "stacks": [ + "SyntheticsCanaryRetryStack" + ], + "assertionStack": "SyntheticsCanaryRetry/DefaultTest/DeployAssert", + "assertionStackName": "SyntheticsCanaryRetryDefaultTestDeployAssert341E434F" + } + }, + "minimumCliVersion": "2.1020.1" +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/manifest.json new file mode 100644 index 0000000000000..c2d820caecf75 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/manifest.json @@ -0,0 +1,181 @@ +{ + "version": "45.0.0", + "artifacts": { + "SyntheticsCanaryRetryStack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "SyntheticsCanaryRetryStack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "SyntheticsCanaryRetryStack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "SyntheticsCanaryRetryStack.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/bb7088ad2a940f3f3e4e2bddcb75f539d2fd3fb5128081ffa02f6054249b0098.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "SyntheticsCanaryRetryStack.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "SyntheticsCanaryRetryStack.assets" + ], + "metadata": { + "/SyntheticsCanaryRetryStack/RetryCanary": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "canaryName": "*", + "runtime": "*", + "test": "*", + "memory": "*", + "timeout": "*" + } + } + ], + "/SyntheticsCanaryRetryStack/RetryCanary/ArtifactsBucket": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "encryption": "KMS_MANAGED", + "enforceSSL": true, + "lifecycleRules": "*" + } + } + ], + "/SyntheticsCanaryRetryStack/RetryCanary/ArtifactsBucket/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "RetryCanaryArtifactsBucket96F3BE6A" + } + ], + "/SyntheticsCanaryRetryStack/RetryCanary/ArtifactsBucket/Policy": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "bucket": "*" + } + } + ], + "/SyntheticsCanaryRetryStack/RetryCanary/ArtifactsBucket/Policy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "RetryCanaryArtifactsBucketPolicy381668A7" + } + ], + "/SyntheticsCanaryRetryStack/RetryCanary/ServiceRole": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "assumedBy": { + "principalAccount": "*", + "assumeRoleAction": "*" + }, + "inlinePolicies": "*", + "managedPolicies": [] + } + } + ], + "/SyntheticsCanaryRetryStack/RetryCanary/ServiceRole/ImportServiceRole": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + } + ], + "/SyntheticsCanaryRetryStack/RetryCanary/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "RetryCanaryServiceRole6EAC7F33" + } + ], + "/SyntheticsCanaryRetryStack/RetryCanary/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "RetryCanary3B0C27B7" + } + ], + "/SyntheticsCanaryRetryStack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/SyntheticsCanaryRetryStack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "SyntheticsCanaryRetryStack" + }, + "SyntheticsCanaryRetryDefaultTestDeployAssert341E434F.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "SyntheticsCanaryRetryDefaultTestDeployAssert341E434F.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "SyntheticsCanaryRetryDefaultTestDeployAssert341E434F": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "SyntheticsCanaryRetryDefaultTestDeployAssert341E434F.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "SyntheticsCanaryRetryDefaultTestDeployAssert341E434F.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "SyntheticsCanaryRetryDefaultTestDeployAssert341E434F.assets" + ], + "metadata": { + "/SyntheticsCanaryRetry/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/SyntheticsCanaryRetry/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "SyntheticsCanaryRetry/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + }, + "minimumCliVersion": "2.1020.2" +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/tree.json new file mode 100644 index 0000000000000..2ea572bde90ab --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.js.snapshot/tree.json @@ -0,0 +1 @@ +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"SyntheticsCanaryRetryStack":{"id":"SyntheticsCanaryRetryStack","path":"SyntheticsCanaryRetryStack","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"RetryCanary":{"id":"RetryCanary","path":"SyntheticsCanaryRetryStack/RetryCanary","constructInfo":{"fqn":"aws-cdk-lib.aws_synthetics.Canary","version":"0.0.0","metadata":[{"canaryName":"*","runtime":"*","test":"*","memory":"*","timeout":"*"}]},"children":{"ArtifactsBucket":{"id":"ArtifactsBucket","path":"SyntheticsCanaryRetryStack/RetryCanary/ArtifactsBucket","constructInfo":{"fqn":"aws-cdk-lib.aws_s3.Bucket","version":"0.0.0","metadata":[{"encryption":"KMS_MANAGED","enforceSSL":true,"lifecycleRules":"*"}]},"children":{"Resource":{"id":"Resource","path":"SyntheticsCanaryRetryStack/RetryCanary/ArtifactsBucket/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_s3.CfnBucket","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::S3::Bucket","aws:cdk:cloudformation:props":{"bucketEncryption":{"serverSideEncryptionConfiguration":[{"serverSideEncryptionByDefault":{"sseAlgorithm":"aws:kms"}}]}}}},"Policy":{"id":"Policy","path":"SyntheticsCanaryRetryStack/RetryCanary/ArtifactsBucket/Policy","constructInfo":{"fqn":"aws-cdk-lib.aws_s3.BucketPolicy","version":"0.0.0","metadata":[{"bucket":"*"}]},"children":{"Resource":{"id":"Resource","path":"SyntheticsCanaryRetryStack/RetryCanary/ArtifactsBucket/Policy/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_s3.CfnBucketPolicy","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::S3::BucketPolicy","aws:cdk:cloudformation:props":{"bucket":{"Ref":"RetryCanaryArtifactsBucket96F3BE6A"},"policyDocument":{"Statement":[{"Action":"s3:*","Condition":{"Bool":{"aws:SecureTransport":"false"}},"Effect":"Deny","Principal":{"AWS":"*"},"Resource":[{"Fn::GetAtt":["RetryCanaryArtifactsBucket96F3BE6A","Arn"]},{"Fn::Join":["",[{"Fn::GetAtt":["RetryCanaryArtifactsBucket96F3BE6A","Arn"]},"/*"]]}]}],"Version":"2012-10-17"}}}}}}}},"ServiceRole":{"id":"ServiceRole","path":"SyntheticsCanaryRetryStack/RetryCanary/ServiceRole","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Role","version":"0.0.0","metadata":[{"assumedBy":{"principalAccount":"*","assumeRoleAction":"*"},"inlinePolicies":"*","managedPolicies":[]}]},"children":{"ImportServiceRole":{"id":"ImportServiceRole","path":"SyntheticsCanaryRetryStack/RetryCanary/ServiceRole/ImportServiceRole","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":["*"]}},"Resource":{"id":"Resource","path":"SyntheticsCanaryRetryStack/RetryCanary/ServiceRole/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnRole","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Role","aws:cdk:cloudformation:props":{"assumeRolePolicyDocument":{"Statement":[{"Action":"sts:AssumeRole","Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"}}],"Version":"2012-10-17"},"policies":[{"policyName":"canaryPolicy","policyDocument":{"Statement":[{"Action":"s3:ListAllMyBuckets","Effect":"Allow","Resource":"*"},{"Action":"s3:GetBucketLocation","Effect":"Allow","Resource":{"Fn::GetAtt":["RetryCanaryArtifactsBucket96F3BE6A","Arn"]}},{"Action":"s3:PutObject","Effect":"Allow","Resource":{"Fn::Join":["",[{"Fn::GetAtt":["RetryCanaryArtifactsBucket96F3BE6A","Arn"]},"/*"]]}},{"Action":"cloudwatch:PutMetricData","Condition":{"StringEquals":{"cloudwatch:namespace":"CloudWatchSynthetics"}},"Effect":"Allow","Resource":"*"},{"Action":["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],"Effect":"Allow","Resource":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":logs:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":log-group:/aws/lambda/cwsyn-*"]]}}],"Version":"2012-10-17"}}]}}}}},"Code":{"id":"Code","path":"SyntheticsCanaryRetryStack/RetryCanary/Code","constructInfo":{"fqn":"aws-cdk-lib.aws_s3_assets.Asset","version":"0.0.0"},"children":{"Stage":{"id":"Stage","path":"SyntheticsCanaryRetryStack/RetryCanary/Code/Stage","constructInfo":{"fqn":"aws-cdk-lib.AssetStaging","version":"0.0.0"}},"AssetBucket":{"id":"AssetBucket","path":"SyntheticsCanaryRetryStack/RetryCanary/Code/AssetBucket","constructInfo":{"fqn":"aws-cdk-lib.aws_s3.BucketBase","version":"0.0.0","metadata":[]}}}},"Resource":{"id":"Resource","path":"SyntheticsCanaryRetryStack/RetryCanary/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_synthetics.CfnCanary","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::Synthetics::Canary","aws:cdk:cloudformation:props":{"artifactS3Location":{"Fn::Join":["",["s3://",{"Ref":"RetryCanaryArtifactsBucket96F3BE6A"}]]},"code":{"handler":"canary.handler","s3Bucket":{"Fn::Sub":"cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}"},"s3Key":"5178413cfe8db00b2d5dcfa9be417e934c64601d0da3031d88c145c8293bc27f.zip"},"executionRoleArn":{"Fn::GetAtt":["RetryCanaryServiceRole6EAC7F33","Arn"]},"name":"retry","runConfig":{"memoryInMb":2048,"timeoutInSeconds":240},"runtimeVersion":"syn-python-selenium-5.1","schedule":{"durationInSeconds":"0","expression":"rate(5 minutes)","retryConfig":{"maxRetries":2}},"startCanaryAfterCreation":true}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"SyntheticsCanaryRetryStack/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"SyntheticsCanaryRetryStack/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"SyntheticsCanaryRetry":{"id":"SyntheticsCanaryRetry","path":"SyntheticsCanaryRetry","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"SyntheticsCanaryRetry/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"SyntheticsCanaryRetry/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"DeployAssert":{"id":"DeployAssert","path":"SyntheticsCanaryRetry/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"SyntheticsCanaryRetry/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"SyntheticsCanaryRetry/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.ts new file mode 100644 index 0000000000000..a781f9f73ab61 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-synthetics/test/integ.canary-retry.ts @@ -0,0 +1,32 @@ +import * as path from 'node:path'; +import { App, Duration, Size, Stack, StackProps } from 'aws-cdk-lib/core'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import { Construct } from 'constructs'; +import * as synthetics from 'aws-cdk-lib/aws-synthetics'; + +class TestStack extends Stack { + public canary: synthetics.Canary; + + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + + this.canary = new synthetics.Canary(this, 'RetryCanary', { + canaryName: 'retry', + runtime: synthetics.Runtime.SYNTHETICS_PYTHON_SELENIUM_5_1, + test: synthetics.Test.custom({ + handler: 'canary.handler', + code: synthetics.Code.fromAsset(path.join(__dirname, 'canaries')), + }), + memory: Size.mebibytes(2048), + timeout: Duration.minutes(4), + maxRetries: 2, + }); + } +} + +const app = new App(); +const testStack = new TestStack(app, 'SyntheticsCanaryRetryStack'); + +new IntegTest(app, 'SyntheticsCanaryRetry', { + testCases: [testStack], +}); diff --git a/packages/aws-cdk-lib/aws-synthetics/README.md b/packages/aws-cdk-lib/aws-synthetics/README.md index d8c7b847d8b92..09ffe2642a96f 100644 --- a/packages/aws-cdk-lib/aws-synthetics/README.md +++ b/packages/aws-cdk-lib/aws-synthetics/README.md @@ -87,6 +87,28 @@ const schedule = synthetics.Schedule.cron({ If you want the canary to run just once upon deployment, you can use `Schedule.once()`. +### Automatic Retries + +You can configure the canary to automatically retry failed runs by using the `maxRetries` property. + +This is only supported on the following runtimes or newer: `Runtime.SYNTHETICS_NODEJS_PUPPETEER_10_0`, `Runtime.SYNTHETICS_NODEJS_PLAYWRIGHT_2_0`, `Runtime.SYNTHETICS_PYTHON_SELENIUM_5_1`. + +Max retries can be set between 0 and 2. Canaries which time out after 10 minutes are automatically limited to one retry. + +For more information, see [Configuring your canary to retry automatically](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries_autoretry.html). + +```ts +const canary = new synthetics.Canary(this, 'MyCanary', { + schedule: synthetics.Schedule.rate(Duration.minutes(5)), + test: synthetics.Test.custom({ + handler: 'canary.handler', + code: synthetics.Code.fromAsset(path.join(__dirname, 'canaries')), + }), + runtime: synthetics.Runtime.SYNTHETICS_PYTHON_SELENIUM_5_1, + maxRetries: 2, // The canary run will retry up to 2 times on a failure +}); +``` + ### Active Tracing You can choose to enable active AWS X-Ray tracing on canaries that use the `syn-nodejs-2.0` or later runtime by setting `activeTracing` to `true`. diff --git a/packages/aws-cdk-lib/aws-synthetics/lib/canary.ts b/packages/aws-cdk-lib/aws-synthetics/lib/canary.ts index 5c2fc521b7429..a3817844c6b91 100644 --- a/packages/aws-cdk-lib/aws-synthetics/lib/canary.ts +++ b/packages/aws-cdk-lib/aws-synthetics/lib/canary.ts @@ -138,6 +138,16 @@ export interface CanaryProps { */ readonly schedule?: Schedule; + /** + * The amount of times the canary will automatically retry a failed run. + * This is only supported on the following runtimes or newer: `Runtime.SYNTHETICS_NODEJS_PUPPETEER_10_0`, `Runtime.SYNTHETICS_NODEJS_PLAYWRIGHT_2_0`, `Runtime.SYNTHETICS_PYTHON_SELENIUM_5_1`. + * Max retries can be set between 0 and 2. Canaries which time out after 10 minutes are automatically limited to one retry. + * + * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries_autoretry.html + * @default 0 + */ + readonly maxRetries?: number; + /** * Whether or not the canary should start after creation. * @@ -708,6 +718,9 @@ export class Canary extends cdk.Resource implements ec2.IConnectable { return { durationInSeconds: String(`${props.timeToLive?.toSeconds() ?? 0}`), expression: props.schedule?.expressionString ?? 'rate(5 minutes)', + retryConfig: props.maxRetries ? { + maxRetries: props.maxRetries, + } : undefined, }; } diff --git a/packages/aws-cdk-lib/aws-synthetics/test/canary.test.ts b/packages/aws-cdk-lib/aws-synthetics/test/canary.test.ts index 0563317244cab..ab956ae36d327 100644 --- a/packages/aws-cdk-lib/aws-synthetics/test/canary.test.ts +++ b/packages/aws-cdk-lib/aws-synthetics/test/canary.test.ts @@ -22,6 +22,7 @@ test('Basic canary properties work', () => { failureRetentionPeriod: Duration.days(10), startAfterCreation: false, timeToLive: Duration.minutes(30), + maxRetries: 2, runtime: synthetics.Runtime.SYNTHETICS_NODEJS_PUPPETEER_8_0, }); @@ -31,7 +32,7 @@ test('Basic canary properties work', () => { SuccessRetentionPeriod: 10, FailureRetentionPeriod: 10, StartCanaryAfterCreation: false, - Schedule: Match.objectLike({ DurationInSeconds: '1800' }), + Schedule: Match.objectLike({ DurationInSeconds: '1800', RetryConfig: { MaxRetries: 2 } }), RuntimeVersion: 'syn-nodejs-puppeteer-8.0', }); });