From 7c06857f6315dcd59ccb3ac0c12f7094ef6be706 Mon Sep 17 00:00:00 2001 From: Daniel Neilson <53624638+ddneilson@users.noreply.github.com> Date: Thu, 28 Jul 2022 12:41:52 -0500 Subject: [PATCH] feat(all): migrate to CDKv2 (#738) * Migrates the RFDK library, examples, and integration tests to CDKv2. BREAKING CHANGE: This change migrates the RFDK to be based on CDK v2. All apps that use the RFDK will have to be migrated to CDKv2 as well. To update your app, follow the CDK's migration guide at: https://docs.aws.amazon.com/cdk/v2/guide/migrating-v2.html --- .gitignore | 3 + .../python/cdk.json | 13 - .../python/package/app.py | 2 +- .../python/package/config.py | 1 + .../python/package/lib/compute_tier.py | 6 +- .../python/package/lib/network_tier.py | 8 +- .../python/package/lib/security_tier.py | 6 +- .../python/package/lib/service_tier.py | 10 +- .../python/package/lib/storage_tier.py | 11 +- .../python/setup.py | 2 +- .../ts/bin/app.ts | 4 +- .../ts/bin/config.ts | 1 + .../ts/cdk.json | 13 - .../ts/lib/compute-tier.ts | 11 +- .../ts/lib/network-tier.ts | 9 +- .../ts/lib/security-tier.ts | 5 +- .../ts/lib/service-tier.ts | 13 +- .../ts/lib/storage-tier.ts | 34 +- .../ts/lib/subnets.ts | 2 +- .../ts/package.json | 4 +- .../python/cdk.json | 13 - .../python/package/app.py | 2 +- .../python/package/config.py | 2 - .../python/package/lib/sep_stack.py | 9 +- .../python/setup.py | 2 +- .../ts/bin/app.ts | 4 +- .../All-In-AWS-Infrastructure-SEP/ts/cdk.json | 13 - .../ts/lib/sep-stack.ts | 12 +- .../ts/package.json | 5 +- .../EC2-Image-Builder/python/cdk.json | 13 - .../EC2-Image-Builder/python/package/app.py | 2 +- .../python/package/lib/base_farm_stack.py | 6 +- .../python/package/lib/compute_stack.py | 6 +- .../package/lib/deadline_machine_image.py | 8 +- .../EC2-Image-Builder/python/setup.py | 6 +- .../deadline/EC2-Image-Builder/ts/bin/app.ts | 2 +- .../deadline/EC2-Image-Builder/ts/cdk.json | 13 - .../ts/lib/base-farm-stack.ts | 6 +- .../EC2-Image-Builder/ts/lib/compute-stack.ts | 6 +- .../ts/lib/deadline-machine-image.ts | 10 +- .../EC2-Image-Builder/ts/package.json | 12 +- examples/deadline/Local-Zone/python/cdk.json | 13 - .../deadline/Local-Zone/python/package/app.py | 2 +- .../python/package/lib/compute_tier.py | 8 +- .../python/package/lib/network_tier.py | 8 +- .../python/package/lib/security_tier.py | 7 +- .../python/package/lib/service_tier.py | 18 +- examples/deadline/Local-Zone/python/setup.py | 8 +- examples/deadline/Local-Zone/ts/bin/app.ts | 4 +- examples/deadline/Local-Zone/ts/cdk.json | 13 - .../Local-Zone/ts/lib/compute-tier.ts | 7 +- .../Local-Zone/ts/lib/network-tier.ts | 9 +- .../Local-Zone/ts/lib/security-tier.ts | 5 +- .../Local-Zone/ts/lib/service-tier.ts | 10 +- examples/deadline/Local-Zone/ts/package.json | 8 +- .../_infrastructure/bin/_infrastructure.ts | 2 +- integ/components/_infrastructure/cdk.json | 13 - .../_infrastructure/lib/network-tier.ts | 12 +- .../common/functions/awaitSsmCommand.ts | 5 + .../bin/deadline_01_repository.ts | 2 +- .../deadline/deadline_01_repository/cdk.json | 13 - .../lib/repository-testing-tier.ts | 5 +- .../bin/deadline_02_renderQueue.ts | 2 +- .../deadline/deadline_02_renderQueue/cdk.json | 13 - .../lib/renderQueue-testing-tier.ts | 2 +- .../bin/deadline_03_workerFleetHttp.ts | 2 +- .../deadline_03_workerFleetHttp/cdk.json | 13 - .../lib/workerFleetHttp-testing-tier.ts | 4 +- .../bin/deadline_04_workerFleetHttps.ts | 2 +- .../deadline_04_workerFleetHttps/cdk.json | 13 - .../lib/workerFleetHttps-testing-tier.ts | 4 +- .../bin/deadline_05_secretsManagement.ts | 2 +- .../deadline_05_secretsManagement/cdk.json | 13 - .../lib/secretsManagement-testing-tier.ts | 5 +- .../deadline_05_secretsManagement.test.ts | 6 +- integ/lib/render-struct.ts | 19 +- integ/lib/sep-worker-struct.ts | 15 +- integ/lib/ssm-policy-aspect.ts | 11 +- integ/lib/storage-struct.ts | 34 +- integ/lib/testing-tier.ts | 7 +- integ/lib/thinkbox-docker-image-overrides.ts | 6 +- integ/lib/worker-struct.ts | 17 +- integ/package.json | 43 +- package.json | 77 +- packages/aws-rfdk/docs/diagrams/README.md | 2 +- .../aws-rfdk/docs/upgrade/upgrading-0.27.md | 4 +- .../aws-rfdk/docs/upgrade/upgrading-0.38.md | 2 +- .../aws-rfdk/lib/core/lib/cloudwatch-agent.ts | 9 +- .../lib/core/lib/cloudwatch-config-builder.ts | 2 +- .../lib/core/lib/deployment-instance.ts | 20 +- packages/aws-rfdk/lib/core/lib/endpoint.ts | 6 +- .../lib/core/lib/exporting-log-group.ts | 15 +- .../aws-rfdk/lib/core/lib/health-monitor.ts | 32 +- .../lib/core/lib/imported-acm-certificate.ts | 36 +- .../lib/core/lib/load-balancer-manager.ts | 6 +- .../lib/core/lib/log-group-factory.ts | 4 +- .../lib/core/lib/mongodb-installer.ts | 12 +- .../aws-rfdk/lib/core/lib/mongodb-instance.ts | 29 +- .../lib/core/lib/mongodb-post-install.ts | 22 +- .../aws-rfdk/lib/core/lib/mountable-ebs.ts | 15 +- .../aws-rfdk/lib/core/lib/mountable-efs.ts | 21 +- .../lib/core/lib/mountable-filesystem.ts | 6 +- .../lib/core/lib/mountable-fsx-lustre.ts | 15 +- .../aws-rfdk/lib/core/lib/pad-efs-storage.ts | 30 +- .../aws-rfdk/lib/core/lib/runtime-info.ts | 4 +- .../aws-rfdk/lib/core/lib/script-assets.ts | 8 +- .../lib/core/lib/session-manager-helper.ts | 2 +- .../aws-rfdk/lib/core/lib/staticip-server.ts | 36 +- .../aws-rfdk/lib/core/lib/x509-certificate.ts | 35 +- .../aws-rfdk/lib/core/test/asset-constants.ts | 31 +- .../lib/core/test/cloudwatch-agent.test.ts | 298 +- .../core/test/cloudwatch-config-builder.ts | 2 +- .../lib/core/test/deployment-instance.test.ts | 321 ++- .../aws-rfdk/lib/core/test/endpoint.test.ts | 18 +- .../lib/core/test/exporting-log-group.test.ts | 36 +- .../lib/core/test/health-monitor.test.ts | 217 +- .../test/imported-acm-certificate.test.ts | 103 +- .../lib/core/test/log-group-factory.test.ts | 63 +- .../lib/core/test/mongodb-installer.test.ts | 74 +- .../lib/core/test/mongodb-instance.test.ts | 413 +-- .../core/test/mongodb-post-install.test.ts | 52 +- .../lib/core/test/mountable-ebs.test.ts | 36 +- .../lib/core/test/mountable-efs.test.ts | 65 +- .../core/test/mountable-fsx-lustre.test.ts | 30 +- .../lib/core/test/pad-efs-storage.test.ts | 72 +- .../lib/core/test/script-assets.test.ts | 268 +- .../core/test/sessions-manager-helper.test.ts | 19 +- .../lib/core/test/staticip-server.test.ts | 141 +- .../aws-rfdk/lib/core/test/tag-helpers.ts | 22 +- .../aws-rfdk/lib/core/test/test-helper.ts | 20 + .../lib/core/test/x509-certificate.test.ts | 347 ++- .../lib/configure-spot-event-plugin.ts | 46 +- .../lib/deadline/lib/database-connection.ts | 20 +- .../aws-rfdk/lib/deadline/lib/host-ref.ts | 4 +- .../lib/deadline/lib/render-queue-ref.ts | 18 +- .../aws-rfdk/lib/deadline/lib/render-queue.ts | 67 +- .../aws-rfdk/lib/deadline/lib/repository.ts | 72 +- .../lib/deadline/lib/rq-connection.ts | 8 +- .../deadline/lib/secrets-management-ref.ts | 4 +- .../lib/deadline/lib/secrets-management.ts | 10 +- .../deadline/lib/spot-event-plugin-fleet.ts | 24 +- packages/aws-rfdk/lib/deadline/lib/stage.ts | 4 +- .../deadline/lib/thinkbox-docker-images.ts | 61 +- .../deadline/lib/thinkbox-docker-recipes.ts | 8 +- .../lib/deadline/lib/usage-based-licensing.ts | 18 +- .../lib/deadline/lib/version-query.ts | 18 +- .../aws-rfdk/lib/deadline/lib/version-ref.ts | 2 +- .../deadline/lib/wait-for-stable-service.ts | 18 +- .../lib/deadline/lib/worker-configuration.ts | 12 +- .../aws-rfdk/lib/deadline/lib/worker-fleet.ts | 21 +- .../lib/deadline/test/asset-constants.ts | 1186 +------- .../test/configure-spot-event-plugin.test.ts | 151 +- .../deadline/test/database-connection.test.ts | 121 +- .../lib/deadline/test/render-queue.test.ts | 2412 ++++++++--------- .../lib/deadline/test/repository.test.ts | 283 +- .../deadline/test/secrets-management.test.ts | 87 +- .../test/spot-event-plugin-fleet.test.ts | 292 +- .../aws-rfdk/lib/deadline/test/stage.test.ts | 19 +- .../aws-rfdk/lib/deadline/test/test-helper.ts | 20 + .../test/thinkbox-docker-images.test.ts | 50 +- .../test/thinkbox-docker-recipes.test.ts | 24 +- .../test/usage-based-licensing.test.ts | 191 +- .../lib/deadline/test/version-query.test.ts | 42 +- .../test/wait-for-stable-service.test.ts | 46 +- .../test/worker-configuration.test.ts | 358 ++- .../lib/deadline/test/worker-fleet.test.ts | 1353 +++------ .../test/handler.test.ts | 8 +- packages/aws-rfdk/package.json | 216 +- tools/cdk-build-tools/package.json | 2 +- tools/pkglint/lib/rules.ts | 2 +- yarn.lock | 1914 ++++--------- 171 files changed, 4715 insertions(+), 8310 deletions(-) create mode 100644 packages/aws-rfdk/lib/core/test/test-helper.ts create mode 100644 packages/aws-rfdk/lib/deadline/test/test-helper.ts diff --git a/.gitignore b/.gitignore index 0cfc0594e..3770cb71b 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ yarn-error.log #Defines license that must be present !license-header.js + +# Visual Studio Code working space +.vscode/ diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/cdk.json b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/cdk.json index fa91d40d2..954054a6e 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/cdk.json +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/cdk.json @@ -1,18 +1,5 @@ { "app": "python -m package.app", "context": { - "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, - "@aws-cdk/core:enableStackNameDuplicates": true, - "aws-cdk:enableDiffNoFail": true, - "@aws-cdk/core:stackRelativeExports": true, - "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true, - "@aws-cdk/aws-secretsmanager:parseOwnedSecretName": true, - "@aws-cdk/aws-kms:defaultKeyPolicies": true, - "@aws-cdk/aws-s3:grantWriteWithoutAcl": true, - "@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount": true, - "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, - "@aws-cdk/aws-efs:defaultEncryptionAtRest": true, - "@aws-cdk/aws-lambda:recognizeVersionProps": true, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true } } diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/app.py b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/app.py index bdba29ef6..f7a340b0c 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/app.py +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/app.py @@ -5,7 +5,7 @@ import os -from aws_cdk.core import ( +from aws_cdk import ( App, Environment ) diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/config.py b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/config.py index 01f270c1b..2103706ba 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/config.py +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/config.py @@ -46,6 +46,7 @@ def __init__(self): self.deadline_client_linux_ami_map: Mapping[str, str] = {'us-west-2': 'ami-04ae356533dc07fb5'} # A secret (in binary form) in SecretsManager that stores the UBL certificates in a .zip file. + # This must be in the format `arn::secretsmanager:::secret:-<6RandomCharacters` self.ubl_certificate_secret_arn: str =\ '' diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/compute_tier.py b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/compute_tier.py index ebf94a3f3..41fbd3577 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/compute_tier.py +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/compute_tier.py @@ -8,8 +8,7 @@ Optional ) -from aws_cdk.core import ( - Construct, +from aws_cdk import ( Stack, StackProps ) @@ -35,6 +34,9 @@ UsageBasedLicensing, WorkerInstanceFleet, ) +from constructs import ( + Construct +) from . import subnets diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/network_tier.py b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/network_tier.py index 51182b948..e895d094d 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/network_tier.py +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/network_tier.py @@ -1,11 +1,9 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -from aws_cdk.core import ( +from aws_cdk import ( Stack, - Construct ) - from aws_cdk.aws_ec2 import ( FlowLogDestination, FlowLogTrafficType, @@ -15,10 +13,12 @@ SubnetSelection, SubnetType ) - from aws_cdk.aws_route53 import ( PrivateHostedZone ) +from constructs import ( + Construct +) from . import subnets diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/security_tier.py b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/security_tier.py index c14169f0f..de7f4fd7e 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/security_tier.py +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/security_tier.py @@ -1,14 +1,16 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -from aws_cdk.core import ( - Construct, +from aws_cdk import ( Stack, ) from aws_rfdk import ( DistinguishedName, X509CertificatePem ) +from constructs import ( + Construct +) class SecurityTier(Stack): diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/service_tier.py b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/service_tier.py index 381f3620c..7ac5a7fb2 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/service_tier.py +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/service_tier.py @@ -4,8 +4,7 @@ import typing from dataclasses import dataclass -from aws_cdk.core import ( - Construct, +from aws_cdk import ( Duration, Stack, StackProps @@ -26,7 +25,6 @@ from aws_cdk.aws_route53 import ( IPrivateHostedZone ) - from aws_rfdk import ( DistinguishedName, MountableEfs, @@ -47,6 +45,10 @@ UsageBasedLicensing, VersionQuery, ) +from constructs import ( + Construct +) + from . import subnets @@ -222,7 +224,7 @@ def __init__(self, scope: Construct, stack_id: str, *, props: ServiceTierProps, if props.ubl_licenses: if not props.ubl_certs_secret_arn: raise ValueError('UBL certificates secret ARN is required when using UBL but was not specified.') - ubl_cert_secret = Secret.from_secret_arn(self, 'ublcertssecret', props.ubl_certs_secret_arn) + ubl_cert_secret = Secret.from_secret_complete_arn(self, 'ublcertssecret', props.ubl_certs_secret_arn) self.ubl_licensing = UsageBasedLicensing( self, 'UsageBasedLicensing', diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/storage_tier.py b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/storage_tier.py index d3b52c645..22600a7c2 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/storage_tier.py +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/storage_tier.py @@ -5,8 +5,7 @@ from dataclasses import dataclass from typing import Optional -from aws_cdk.core import ( - Construct, +from aws_cdk import ( Duration, RemovalPolicy, Size, @@ -52,7 +51,6 @@ from aws_cdk.aws_sns_subscriptions import ( EmailSubscription ) - from aws_rfdk import ( MongoDbUsers, MongoDbX509User, @@ -67,10 +65,12 @@ X509CertificatePem, X509CertificatePkcs12 ) - from aws_rfdk.deadline import ( DatabaseConnection ) +from constructs import ( + Construct +) from . import subnets @@ -231,8 +231,7 @@ def add_low_efs_burst_credit_alarms(self, filesystem: FileSystem, email_address: 'SNSEncryptionKey', description='Used to encrypt the SNS Topic for sending EFS Burst Credit alerts', enable_key_rotation=True, - removal_policy=RemovalPolicy.DESTROY, - trust_account_identities=True + removal_policy=RemovalPolicy.DESTROY ) key.grant(ServicePrincipal('cloudwatch.amazonaws.com'), 'kms:Decrypt', 'kms:GenerateDataKey') diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/setup.py b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/setup.py index 439e5607a..81eafcf21 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/setup.py +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/setup.py @@ -17,7 +17,7 @@ packages=setuptools.find_packages(where="package"), install_requires=[ - "aws-cdk.core==1.160.0", + "aws-cdk-lib==2.33.0", "aws-rfdk==0.42.0" ], diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/bin/app.ts b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/bin/app.ts index 0fb24bd20..8c85df261 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/bin/app.ts +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/bin/app.ts @@ -6,7 +6,7 @@ import 'source-map-support/register'; import { config } from './config'; -import * as cdk from '@aws-cdk/core'; +import * as cdk from 'aws-cdk-lib'; import { NetworkTier } from '../lib/network-tier'; import { ServiceTier, @@ -22,7 +22,7 @@ import { InstanceSize, InstanceType, MachineImage, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { ComputeTier } from '../lib/compute-tier'; // ------------------------------ // diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/bin/config.ts b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/bin/config.ts index b04d67e0e..a3eb6105f 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/bin/config.ts +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/bin/config.ts @@ -49,6 +49,7 @@ class AppConfig { /** * (Optional) A secret (in binary form) in SecretsManager that stores the UBL certificates in a .zip file. + * This must be in the format `arn::secretsmanager:::secret:-<6RandomCharacters` */ public readonly ublCertificatesSecretArn?: string; diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/cdk.json b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/cdk.json index c39a981a2..15a1c8fa2 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/cdk.json +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/cdk.json @@ -1,18 +1,5 @@ { "app": "npx ts-node bin/app.ts", "context": { - "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, - "@aws-cdk/core:enableStackNameDuplicates": true, - "aws-cdk:enableDiffNoFail": true, - "@aws-cdk/core:stackRelativeExports": true, - "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true, - "@aws-cdk/aws-secretsmanager:parseOwnedSecretName": true, - "@aws-cdk/aws-kms:defaultKeyPolicies": true, - "@aws-cdk/aws-s3:grantWriteWithoutAcl": true, - "@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount": true, - "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, - "@aws-cdk/aws-efs:defaultEncryptionAtRest": true, - "@aws-cdk/aws-lambda:recognizeVersionProps": true, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true } } diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/compute-tier.ts b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/compute-tier.ts index 9479d0dab..d9ff2d3ea 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/compute-tier.ts +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/compute-tier.ts @@ -8,8 +8,8 @@ import { IMachineImage, IVpc, Port, -} from '@aws-cdk/aws-ec2'; -import * as cdk from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; +import * as cdk from 'aws-cdk-lib'; import { IHost, InstanceUserDataProvider, @@ -24,7 +24,8 @@ import { IHealthMonitor, SessionManagerHelper, } from 'aws-rfdk'; -import { Asset } from '@aws-cdk/aws-s3-assets'; +import { Asset } from 'aws-cdk-lib/aws-s3-assets'; +import { Construct } from 'constructs'; import * as path from 'path' import { Subnets } from './subnets'; @@ -83,7 +84,7 @@ class UserDataProvider extends InstanceUserDataProvider { host.userData.addCommands('echo postWorkerLaunch'); if (host.node.scope != undefined) { const testScript = new Asset( - host.node.scope as cdk.Construct, + host.node.scope as Construct, 'SampleAsset', {path: path.join(__dirname, '..', '..', 'scripts', 'configure_worker.sh')}, ); @@ -120,7 +121,7 @@ export class ComputeTier extends cdk.Stack { * @param id The ID of this construct. * @param props The properties of this construct. */ - constructor(scope: cdk.Construct, id: string, props: ComputeTierProps) { + constructor(scope: Construct, id: string, props: ComputeTierProps) { super(scope, id, props); this.healthMonitor = new HealthMonitor(this, 'HealthMonitor', { diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/network-tier.ts b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/network-tier.ts index 0c314f59e..15916bbd8 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/network-tier.ts +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/network-tier.ts @@ -14,11 +14,12 @@ import { SubnetSelection, SubnetType, Vpc, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { PrivateHostedZone, -} from '@aws-cdk/aws-route53'; -import * as cdk from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-route53'; +import * as cdk from 'aws-cdk-lib'; +import { Construct } from 'constructs'; import { Subnets } from './subnets'; @@ -67,7 +68,7 @@ export class NetworkTier extends cdk.Stack { * @param id The ID of this construct. * @param props The stack properties. */ - constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { + constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); this.vpc = new Vpc(this, 'Vpc', { diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/security-tier.ts b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/security-tier.ts index f4e4376af..85ffe6e97 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/security-tier.ts +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/security-tier.ts @@ -3,10 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -import * as cdk from '@aws-cdk/core'; +import * as cdk from 'aws-cdk-lib'; import { X509CertificatePem, } from 'aws-rfdk'; +import { Construct } from 'constructs'; /** * The security tier of the render farm. This stack contains resources used to @@ -24,7 +25,7 @@ export class SecurityTier extends cdk.Stack { * @param id The ID of this construct. * @param props The properties for the security tier. */ - constructor(scope: cdk.Construct, id: string, props: cdk.StackProps) { + constructor(scope: Construct, id: string, props: cdk.StackProps) { super(scope, id, props); this.rootCa = new X509CertificatePem(this, 'RootCA', { diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/service-tier.ts b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/service-tier.ts index 0b184a750..d8272f8e6 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/service-tier.ts +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/service-tier.ts @@ -7,14 +7,14 @@ import { BastionHostLinux, BlockDeviceVolume, IVpc, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { ApplicationProtocol, -} from '@aws-cdk/aws-elasticloadbalancingv2'; +} from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import { IPrivateHostedZone, -} from '@aws-cdk/aws-route53'; -import * as cdk from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-route53'; +import * as cdk from 'aws-cdk-lib'; import { MountableEfs, X509CertificatePem, @@ -31,8 +31,9 @@ import { } from 'aws-rfdk/deadline'; import { Secret, -} from '@aws-cdk/aws-secretsmanager'; +} from 'aws-cdk-lib/aws-secretsmanager'; import { SessionManagerHelper } from 'aws-rfdk/lib/core'; +import { Construct } from 'constructs'; import { Subnets } from './subnets'; @@ -130,7 +131,7 @@ export class ServiceTier extends cdk.Stack { * @param id The ID of this construct. * @param props The properties for this construct. */ - constructor(scope: cdk.Construct, id: string, props: ServiceTierProps) { + constructor(scope: Construct, id: string, props: ServiceTierProps) { super(scope, id, props); // Bastion instance for convenience (e.g. SSH into RenderQueue and WorkerFleet instances). diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/storage-tier.ts b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/storage-tier.ts index 05cc9c19e..b9862683c 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/storage-tier.ts +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/storage-tier.ts @@ -7,35 +7,35 @@ import { InstanceType, IVpc, SubnetSelection, -} from '@aws-cdk/aws-ec2'; -import * as cdk from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; +import * as cdk from 'aws-cdk-lib'; import { ComparisonOperator, Metric, TreatMissingData, -} from '@aws-cdk/aws-cloudwatch'; +} from 'aws-cdk-lib/aws-cloudwatch'; import { SnsAction, -} from '@aws-cdk/aws-cloudwatch-actions'; -import { DatabaseCluster } from '@aws-cdk/aws-docdb'; +} from 'aws-cdk-lib/aws-cloudwatch-actions'; +import { DatabaseCluster } from 'aws-cdk-lib/aws-docdb'; import { AccessPoint, FileSystem, -} from '@aws-cdk/aws-efs'; +} from 'aws-cdk-lib/aws-efs'; import { ServicePrincipal, -} from '@aws-cdk/aws-iam'; +} from 'aws-cdk-lib/aws-iam'; import { Key, -} from '@aws-cdk/aws-kms'; -import { IPrivateHostedZone } from '@aws-cdk/aws-route53'; +} from 'aws-cdk-lib/aws-kms'; +import { IPrivateHostedZone } from 'aws-cdk-lib/aws-route53'; import { Topic, -} from '@aws-cdk/aws-sns'; +} from 'aws-cdk-lib/aws-sns'; import { EmailSubscription, -} from '@aws-cdk/aws-sns-subscriptions'; -import { RemovalPolicy, Duration } from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-sns-subscriptions'; +import { RemovalPolicy, Duration } from 'aws-cdk-lib'; import { MongoDbInstance, MongoDbPostInstallSetup, @@ -49,6 +49,7 @@ import { import { DatabaseConnection, } from 'aws-rfdk/deadline'; +import { Construct } from 'constructs'; import { Subnets } from './subnets'; @@ -91,7 +92,7 @@ export abstract class StorageTier extends cdk.Stack { * @param id The ID of this construct. * @param props The properties for the storage tier. */ - constructor(scope: cdk.Construct, id: string, props: StorageTierProps) { + constructor(scope: Construct, id: string, props: StorageTierProps) { super(scope, id, props); const fileSystem = new FileSystem(this, 'EfsFileSystem', { @@ -208,8 +209,7 @@ export abstract class StorageTier extends cdk.Stack { const key = new Key(this, 'SNSEncryptionKey', { description: 'Used to encrypt the SNS Topic for sending EFS Burst Credit alerts', enableKeyRotation: true, - removalPolicy: RemovalPolicy.DESTROY, - trustAccountIdentities: true, + removalPolicy: RemovalPolicy.DESTROY }); key.grant(new ServicePrincipal('cloudwatch.amazonaws.com'), 'kms:Decrypt', 'kms:GenerateDataKey'); @@ -310,7 +310,7 @@ export class StorageTierDocDB extends StorageTier { * @param id The ID of this construct. * @param props The properties for this construct. */ - constructor(scope: cdk.Construct, id: string, props: StorageTierDocDBProps) { + constructor(scope: Construct, id: string, props: StorageTierDocDBProps) { super(scope, id, props); const docDb = new DatabaseCluster(this, 'DocDBCluster', { @@ -391,7 +391,7 @@ export class StorageTierMongoDB extends StorageTier { * @param id The ID of this construct. * @param props The properties for this construct. */ - constructor(scope: cdk.Construct, id: string, props: StorageTierMongoDBProps) { + constructor(scope: Construct, id: string, props: StorageTierMongoDBProps) { super(scope, id, props); const serverCert = new X509CertificatePem(this, 'MongoCert', { diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/subnets.ts b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/subnets.ts index 01f9665c3..f0b97722e 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/subnets.ts +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/subnets.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { SubnetConfiguration, SubnetType } from '@aws-cdk/aws-ec2'; +import { SubnetConfiguration, SubnetType } from 'aws-cdk-lib/aws-ec2'; export class Subnets { /** diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/package.json b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/package.json index cdff21c5b..af486b873 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/package.json +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/package.json @@ -14,12 +14,12 @@ }, "devDependencies": { "@types/node": "^18.0.0", - "aws-cdk": "1.160.0", + "aws-cdk": "2.33.0", "ts-node": "^10.8.1", "typescript": "~4.7.3" }, "dependencies": { - "@aws-cdk/core": "1.160.0", + "aws-cdk-lib": "^2.33.0", "aws-rfdk": "0.42.0", "source-map-support": "^0.5.21" } diff --git a/examples/deadline/All-In-AWS-Infrastructure-SEP/python/cdk.json b/examples/deadline/All-In-AWS-Infrastructure-SEP/python/cdk.json index fa91d40d2..954054a6e 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-SEP/python/cdk.json +++ b/examples/deadline/All-In-AWS-Infrastructure-SEP/python/cdk.json @@ -1,18 +1,5 @@ { "app": "python -m package.app", "context": { - "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, - "@aws-cdk/core:enableStackNameDuplicates": true, - "aws-cdk:enableDiffNoFail": true, - "@aws-cdk/core:stackRelativeExports": true, - "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true, - "@aws-cdk/aws-secretsmanager:parseOwnedSecretName": true, - "@aws-cdk/aws-kms:defaultKeyPolicies": true, - "@aws-cdk/aws-s3:grantWriteWithoutAcl": true, - "@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount": true, - "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, - "@aws-cdk/aws-efs:defaultEncryptionAtRest": true, - "@aws-cdk/aws-lambda:recognizeVersionProps": true, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true } } diff --git a/examples/deadline/All-In-AWS-Infrastructure-SEP/python/package/app.py b/examples/deadline/All-In-AWS-Infrastructure-SEP/python/package/app.py index 194e70c45..12186f4bf 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-SEP/python/package/app.py +++ b/examples/deadline/All-In-AWS-Infrastructure-SEP/python/package/app.py @@ -5,7 +5,7 @@ import os -from aws_cdk.core import ( +from aws_cdk import ( App, Environment, ) diff --git a/examples/deadline/All-In-AWS-Infrastructure-SEP/python/package/config.py b/examples/deadline/All-In-AWS-Infrastructure-SEP/python/package/config.py index 21102770a..5922be355 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-SEP/python/package/config.py +++ b/examples/deadline/All-In-AWS-Infrastructure-SEP/python/package/config.py @@ -2,9 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import ( - List, Mapping, - Optional, ) class AppConfig: diff --git a/examples/deadline/All-In-AWS-Infrastructure-SEP/python/package/lib/sep_stack.py b/examples/deadline/All-In-AWS-Infrastructure-SEP/python/package/lib/sep_stack.py index 3732ef590..68d8a52f0 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-SEP/python/package/lib/sep_stack.py +++ b/examples/deadline/All-In-AWS-Infrastructure-SEP/python/package/lib/sep_stack.py @@ -1,12 +1,8 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -from typing import ( - Optional, -) from dataclasses import dataclass -from aws_cdk.core import ( - Construct, +from aws_cdk import ( Duration, RemovalPolicy, Stack, @@ -49,6 +45,9 @@ DistinguishedName, X509CertificatePem, ) +from constructs import ( + Construct +) @dataclass diff --git a/examples/deadline/All-In-AWS-Infrastructure-SEP/python/setup.py b/examples/deadline/All-In-AWS-Infrastructure-SEP/python/setup.py index 4f04f6bd5..4f7c2d808 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-SEP/python/setup.py +++ b/examples/deadline/All-In-AWS-Infrastructure-SEP/python/setup.py @@ -17,7 +17,7 @@ packages=setuptools.find_packages(where="package"), install_requires=[ - "aws-cdk.core==1.160.0", + "aws-cdk-lib==2.33.0", "aws-rfdk==0.42.0" ], diff --git a/examples/deadline/All-In-AWS-Infrastructure-SEP/ts/bin/app.ts b/examples/deadline/All-In-AWS-Infrastructure-SEP/ts/bin/app.ts index d66c05a2f..f1dbb9fba 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-SEP/ts/bin/app.ts +++ b/examples/deadline/All-In-AWS-Infrastructure-SEP/ts/bin/app.ts @@ -7,8 +7,8 @@ import 'source-map-support/register'; import * as path from 'path'; import * as pkg from '../package.json'; -import { MachineImage } from '@aws-cdk/aws-ec2'; -import * as cdk from '@aws-cdk/core'; +import { MachineImage } from 'aws-cdk-lib/aws-ec2'; +import * as cdk from 'aws-cdk-lib'; import { SEPStack } from '../lib/sep-stack'; import { config } from './config'; diff --git a/examples/deadline/All-In-AWS-Infrastructure-SEP/ts/cdk.json b/examples/deadline/All-In-AWS-Infrastructure-SEP/ts/cdk.json index c39a981a2..15a1c8fa2 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-SEP/ts/cdk.json +++ b/examples/deadline/All-In-AWS-Infrastructure-SEP/ts/cdk.json @@ -1,18 +1,5 @@ { "app": "npx ts-node bin/app.ts", "context": { - "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, - "@aws-cdk/core:enableStackNameDuplicates": true, - "aws-cdk:enableDiffNoFail": true, - "@aws-cdk/core:stackRelativeExports": true, - "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true, - "@aws-cdk/aws-secretsmanager:parseOwnedSecretName": true, - "@aws-cdk/aws-kms:defaultKeyPolicies": true, - "@aws-cdk/aws-s3:grantWriteWithoutAcl": true, - "@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount": true, - "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, - "@aws-cdk/aws-efs:defaultEncryptionAtRest": true, - "@aws-cdk/aws-lambda:recognizeVersionProps": true, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true } } diff --git a/examples/deadline/All-In-AWS-Infrastructure-SEP/ts/lib/sep-stack.ts b/examples/deadline/All-In-AWS-Infrastructure-SEP/ts/lib/sep-stack.ts index 9464a4998..921c02b43 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-SEP/ts/lib/sep-stack.ts +++ b/examples/deadline/All-In-AWS-Infrastructure-SEP/ts/lib/sep-stack.ts @@ -9,22 +9,21 @@ import { InstanceSize, InstanceType, Vpc, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { - Construct, Duration, RemovalPolicy, Stack, StackProps, Tags, -} from '@aws-cdk/core'; -import { ApplicationProtocol } from '@aws-cdk/aws-elasticloadbalancingv2'; +} from 'aws-cdk-lib'; +import { ApplicationProtocol } from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import { ManagedPolicy, Role, ServicePrincipal, -} from '@aws-cdk/aws-iam'; -import { PrivateHostedZone } from '@aws-cdk/aws-route53'; +} from 'aws-cdk-lib/aws-iam'; +import { PrivateHostedZone } from 'aws-cdk-lib/aws-route53'; import { ConfigureSpotEventPlugin, RenderQueue, @@ -34,6 +33,7 @@ import { ThinkboxDockerRecipes, } from 'aws-rfdk/deadline'; import { X509CertificatePem } from 'aws-rfdk'; +import { Construct } from 'constructs'; /** * Properties for {@link SEPStack}. diff --git a/examples/deadline/All-In-AWS-Infrastructure-SEP/ts/package.json b/examples/deadline/All-In-AWS-Infrastructure-SEP/ts/package.json index 0492fecde..ee2bb003a 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-SEP/ts/package.json +++ b/examples/deadline/All-In-AWS-Infrastructure-SEP/ts/package.json @@ -19,13 +19,14 @@ }, "devDependencies": { "@types/node": "^18.0.0", - "aws-cdk": "1.160.0", + "aws-cdk": "2.33.0", "ts-node": "^10.8.1", "typescript": "~4.7.3" }, "dependencies": { - "@aws-cdk/core": "1.160.0", + "aws-cdk-lib": "^2.33.0", "aws-rfdk": "0.42.0", + "constructs": "^10.0.0", "source-map-support": "^0.5.21" } } diff --git a/examples/deadline/EC2-Image-Builder/python/cdk.json b/examples/deadline/EC2-Image-Builder/python/cdk.json index fa91d40d2..954054a6e 100644 --- a/examples/deadline/EC2-Image-Builder/python/cdk.json +++ b/examples/deadline/EC2-Image-Builder/python/cdk.json @@ -1,18 +1,5 @@ { "app": "python -m package.app", "context": { - "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, - "@aws-cdk/core:enableStackNameDuplicates": true, - "aws-cdk:enableDiffNoFail": true, - "@aws-cdk/core:stackRelativeExports": true, - "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true, - "@aws-cdk/aws-secretsmanager:parseOwnedSecretName": true, - "@aws-cdk/aws-kms:defaultKeyPolicies": true, - "@aws-cdk/aws-s3:grantWriteWithoutAcl": true, - "@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount": true, - "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, - "@aws-cdk/aws-efs:defaultEncryptionAtRest": true, - "@aws-cdk/aws-lambda:recognizeVersionProps": true, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true } } diff --git a/examples/deadline/EC2-Image-Builder/python/package/app.py b/examples/deadline/EC2-Image-Builder/python/package/app.py index 5a59030b1..3b6bde29d 100644 --- a/examples/deadline/EC2-Image-Builder/python/package/app.py +++ b/examples/deadline/EC2-Image-Builder/python/package/app.py @@ -5,7 +5,7 @@ import os -from aws_cdk.core import ( +from aws_cdk import ( App, Environment ) diff --git a/examples/deadline/EC2-Image-Builder/python/package/lib/base_farm_stack.py b/examples/deadline/EC2-Image-Builder/python/package/lib/base_farm_stack.py index 3bfac26d9..c63c27686 100644 --- a/examples/deadline/EC2-Image-Builder/python/package/lib/base_farm_stack.py +++ b/examples/deadline/EC2-Image-Builder/python/package/lib/base_farm_stack.py @@ -3,8 +3,7 @@ from dataclasses import dataclass -from aws_cdk.core import ( - Construct, +from aws_cdk import ( RemovalPolicy, Stack, StackProps @@ -20,6 +19,9 @@ ThinkboxDockerImages, VersionQuery, ) +from constructs import ( + Construct +) @dataclass diff --git a/examples/deadline/EC2-Image-Builder/python/package/lib/compute_stack.py b/examples/deadline/EC2-Image-Builder/python/package/lib/compute_stack.py index 2a187ebe0..ef45012a3 100644 --- a/examples/deadline/EC2-Image-Builder/python/package/lib/compute_stack.py +++ b/examples/deadline/EC2-Image-Builder/python/package/lib/compute_stack.py @@ -8,8 +8,7 @@ Vpc, WindowsVersion ) -from aws_cdk.core import ( - Construct, +from aws_cdk import ( Stack, StackProps ) @@ -18,6 +17,9 @@ VersionQuery, WorkerInstanceFleet ) +from constructs import ( + Construct +) from .deadline_machine_image import ( DeadlineMachineImage, diff --git a/examples/deadline/EC2-Image-Builder/python/package/lib/deadline_machine_image.py b/examples/deadline/EC2-Image-Builder/python/package/lib/deadline_machine_image.py index 05d07b77a..4914f2b5b 100644 --- a/examples/deadline/EC2-Image-Builder/python/package/lib/deadline_machine_image.py +++ b/examples/deadline/EC2-Image-Builder/python/package/lib/deadline_machine_image.py @@ -6,6 +6,9 @@ import os from typing import List +from aws_cdk import ( + Token +) from aws_cdk.aws_ec2 import ( IMachineImage, OperatingSystemType @@ -24,9 +27,8 @@ CfnImageRecipe, CfnInfrastructureConfiguration ) -from aws_cdk.core import ( - Construct, - Token +from constructs import ( + Construct ) from . import template diff --git a/examples/deadline/EC2-Image-Builder/python/setup.py b/examples/deadline/EC2-Image-Builder/python/setup.py index 3317a0fe3..7a7961ea4 100644 --- a/examples/deadline/EC2-Image-Builder/python/setup.py +++ b/examples/deadline/EC2-Image-Builder/python/setup.py @@ -17,11 +17,7 @@ packages=setuptools.find_packages(where="package"), install_requires=[ - "aws-cdk.aws-iam==1.160.0", - "aws-cdk.aws-imagebuilder==1.160.0", - "aws-cdk.aws-ec2==1.160.0", - "aws-cdk.aws-s3-assets==1.160.0", - "aws-cdk.core==1.160.0", + "aws-cdk-lib==2.33.0", "aws-rfdk==0.42.0", ], diff --git a/examples/deadline/EC2-Image-Builder/ts/bin/app.ts b/examples/deadline/EC2-Image-Builder/ts/bin/app.ts index e81370803..32249d670 100644 --- a/examples/deadline/EC2-Image-Builder/ts/bin/app.ts +++ b/examples/deadline/EC2-Image-Builder/ts/bin/app.ts @@ -5,7 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import * as cdk from '@aws-cdk/core'; +import * as cdk from 'aws-cdk-lib'; import { config } from './config'; diff --git a/examples/deadline/EC2-Image-Builder/ts/cdk.json b/examples/deadline/EC2-Image-Builder/ts/cdk.json index c39a981a2..15a1c8fa2 100644 --- a/examples/deadline/EC2-Image-Builder/ts/cdk.json +++ b/examples/deadline/EC2-Image-Builder/ts/cdk.json @@ -1,18 +1,5 @@ { "app": "npx ts-node bin/app.ts", "context": { - "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, - "@aws-cdk/core:enableStackNameDuplicates": true, - "aws-cdk:enableDiffNoFail": true, - "@aws-cdk/core:stackRelativeExports": true, - "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true, - "@aws-cdk/aws-secretsmanager:parseOwnedSecretName": true, - "@aws-cdk/aws-kms:defaultKeyPolicies": true, - "@aws-cdk/aws-s3:grantWriteWithoutAcl": true, - "@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount": true, - "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, - "@aws-cdk/aws-efs:defaultEncryptionAtRest": true, - "@aws-cdk/aws-lambda:recognizeVersionProps": true, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true } } diff --git a/examples/deadline/EC2-Image-Builder/ts/lib/base-farm-stack.ts b/examples/deadline/EC2-Image-Builder/ts/lib/base-farm-stack.ts index de2addf04..9fbd80c36 100644 --- a/examples/deadline/EC2-Image-Builder/ts/lib/base-farm-stack.ts +++ b/examples/deadline/EC2-Image-Builder/ts/lib/base-farm-stack.ts @@ -5,13 +5,12 @@ import { Vpc, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { - Construct, RemovalPolicy, Stack, StackProps -} from '@aws-cdk/core'; +} from 'aws-cdk-lib'; import { AwsThinkboxEulaAcceptance, RenderQueue, @@ -19,6 +18,7 @@ import { ThinkboxDockerImages, VersionQuery } from 'aws-rfdk/deadline'; +import { Construct } from 'constructs'; export interface FarmProps extends StackProps { /** diff --git a/examples/deadline/EC2-Image-Builder/ts/lib/compute-stack.ts b/examples/deadline/EC2-Image-Builder/ts/lib/compute-stack.ts index 19842b982..7b2eaa256 100644 --- a/examples/deadline/EC2-Image-Builder/ts/lib/compute-stack.ts +++ b/examples/deadline/EC2-Image-Builder/ts/lib/compute-stack.ts @@ -7,18 +7,18 @@ import { MachineImage, Vpc, WindowsVersion, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { CfnResource, - Construct, Stack, StackProps -} from '@aws-cdk/core'; +} from 'aws-cdk-lib'; import { RenderQueue, VersionQuery, WorkerInstanceFleet, } from 'aws-rfdk/deadline'; +import { Construct } from 'constructs'; import { DeadlineMachineImage, diff --git a/examples/deadline/EC2-Image-Builder/ts/lib/deadline-machine-image.ts b/examples/deadline/EC2-Image-Builder/ts/lib/deadline-machine-image.ts index 423095df2..99d0a6ca6 100644 --- a/examples/deadline/EC2-Image-Builder/ts/lib/deadline-machine-image.ts +++ b/examples/deadline/EC2-Image-Builder/ts/lib/deadline-machine-image.ts @@ -8,26 +8,26 @@ import * as path from 'path'; import { IMachineImage, OperatingSystemType, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { CfnInstanceProfile, ManagedPolicy, PolicyStatement, Role, ServicePrincipal, -} from '@aws-cdk/aws-iam'; +} from 'aws-cdk-lib/aws-iam'; import { CfnComponent, CfnDistributionConfiguration, CfnImage, CfnImageRecipe, CfnInfrastructureConfiguration, -} from '@aws-cdk/aws-imagebuilder'; +} from 'aws-cdk-lib/aws-imagebuilder'; import { CfnResource, - Construct, Token, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib'; +import { Construct } from 'constructs'; import { templateComponent } from './template'; diff --git a/examples/deadline/EC2-Image-Builder/ts/package.json b/examples/deadline/EC2-Image-Builder/ts/package.json index 25725229b..16f44184f 100644 --- a/examples/deadline/EC2-Image-Builder/ts/package.json +++ b/examples/deadline/EC2-Image-Builder/ts/package.json @@ -15,16 +15,14 @@ }, "devDependencies": { "@types/node": "^18.0.0", - "aws-cdk": "1.160.0", + "aws-cdk": "2.33.0", "ts-node": "^10.8.1", "typescript": "~4.7.3" }, "dependencies": { - "@aws-cdk/aws-ec2": "1.160.0", - "@aws-cdk/aws-iam": "1.160.0", - "@aws-cdk/aws-imagebuilder": "1.160.0", - "@aws-cdk/aws-s3-assets": "1.160.0", - "@aws-cdk/core": "1.160.0", - "aws-rfdk": "0.42.0" + "aws-cdk-lib": "^2.33.0", + "aws-rfdk": "0.42.0", + "constructs": "^10.0.0", + "source-map-support": "^0.5.21" } } diff --git a/examples/deadline/Local-Zone/python/cdk.json b/examples/deadline/Local-Zone/python/cdk.json index fa91d40d2..954054a6e 100644 --- a/examples/deadline/Local-Zone/python/cdk.json +++ b/examples/deadline/Local-Zone/python/cdk.json @@ -1,18 +1,5 @@ { "app": "python -m package.app", "context": { - "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, - "@aws-cdk/core:enableStackNameDuplicates": true, - "aws-cdk:enableDiffNoFail": true, - "@aws-cdk/core:stackRelativeExports": true, - "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true, - "@aws-cdk/aws-secretsmanager:parseOwnedSecretName": true, - "@aws-cdk/aws-kms:defaultKeyPolicies": true, - "@aws-cdk/aws-s3:grantWriteWithoutAcl": true, - "@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount": true, - "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, - "@aws-cdk/aws-efs:defaultEncryptionAtRest": true, - "@aws-cdk/aws-lambda:recognizeVersionProps": true, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true } } diff --git a/examples/deadline/Local-Zone/python/package/app.py b/examples/deadline/Local-Zone/python/package/app.py index e89aeac53..613684a8d 100644 --- a/examples/deadline/Local-Zone/python/package/app.py +++ b/examples/deadline/Local-Zone/python/package/app.py @@ -5,7 +5,7 @@ import os -from aws_cdk.core import ( +from aws_cdk import ( App, Environment ) diff --git a/examples/deadline/Local-Zone/python/package/lib/compute_tier.py b/examples/deadline/Local-Zone/python/package/lib/compute_tier.py index 57b2d7200..e95c5b042 100644 --- a/examples/deadline/Local-Zone/python/package/lib/compute_tier.py +++ b/examples/deadline/Local-Zone/python/package/lib/compute_tier.py @@ -7,8 +7,7 @@ Optional ) -from aws_cdk.core import ( - Construct, +from aws_cdk import ( Stack, StackProps ) @@ -21,7 +20,6 @@ SubnetSelection, SubnetType ) - from aws_rfdk import ( HealthMonitor, SessionManagerHelper @@ -31,7 +29,9 @@ IRenderQueue, WorkerInstanceFleet ) - +from constructs import ( + Construct +) @dataclass class ComputeTierProps(StackProps): diff --git a/examples/deadline/Local-Zone/python/package/lib/network_tier.py b/examples/deadline/Local-Zone/python/package/lib/network_tier.py index 4fb0c0f5c..fd8915068 100644 --- a/examples/deadline/Local-Zone/python/package/lib/network_tier.py +++ b/examples/deadline/Local-Zone/python/package/lib/network_tier.py @@ -4,6 +4,9 @@ import builtins import typing +from aws_cdk import ( + Stack +) from aws_cdk.aws_ec2 import ( GatewayVpcEndpointAwsService, InterfaceVpcEndpointAwsService, @@ -15,9 +18,8 @@ from aws_cdk.aws_route53 import ( PrivateHostedZone ) -from aws_cdk.core import ( - Construct, - Stack +from constructs import ( + Construct ) import jsii diff --git a/examples/deadline/Local-Zone/python/package/lib/security_tier.py b/examples/deadline/Local-Zone/python/package/lib/security_tier.py index c14169f0f..1e2cdfa2c 100644 --- a/examples/deadline/Local-Zone/python/package/lib/security_tier.py +++ b/examples/deadline/Local-Zone/python/package/lib/security_tier.py @@ -1,15 +1,16 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -from aws_cdk.core import ( - Construct, +from aws_cdk import ( Stack, ) from aws_rfdk import ( DistinguishedName, X509CertificatePem ) - +from constructs import ( + Construct +) class SecurityTier(Stack): """ diff --git a/examples/deadline/Local-Zone/python/package/lib/service_tier.py b/examples/deadline/Local-Zone/python/package/lib/service_tier.py index d6bc3c361..cc5f2825f 100644 --- a/examples/deadline/Local-Zone/python/package/lib/service_tier.py +++ b/examples/deadline/Local-Zone/python/package/lib/service_tier.py @@ -4,6 +4,12 @@ from dataclasses import dataclass from typing import List +from aws_cdk import ( + Duration, + RemovalPolicy, + Stack, + StackProps +) from aws_cdk.aws_ec2 import ( IVpc, SubnetSelection, @@ -15,14 +21,6 @@ from aws_cdk.aws_route53 import ( IPrivateHostedZone ) -from aws_cdk.core import ( - Construct, - Duration, - RemovalPolicy, - Stack, - StackProps -) - from aws_rfdk import ( DistinguishedName, SessionManagerHelper, @@ -39,7 +37,9 @@ ThinkboxDockerImages, VersionQuery ) - +from constructs import ( + Construct +) @dataclass class ServiceTierProps(StackProps): diff --git a/examples/deadline/Local-Zone/python/setup.py b/examples/deadline/Local-Zone/python/setup.py index 0faf4a02b..00d000d21 100644 --- a/examples/deadline/Local-Zone/python/setup.py +++ b/examples/deadline/Local-Zone/python/setup.py @@ -17,12 +17,8 @@ packages=setuptools.find_packages(where="package"), install_requires=[ - "aws-cdk.aws-ec2==1.160.0", - "aws-cdk.aws-elasticloadbalancingv2==1.160.0", - "aws-cdk.aws-route53==1.160.0", - "aws-cdk.core==1.160.0", - "aws-rfdk==0.42.0", - "jsii==1.50.0", + "aws-cdk-lib==2.33.0", + "aws-rfdk==0.42.0" ], python_requires=">=3.7", diff --git a/examples/deadline/Local-Zone/ts/bin/app.ts b/examples/deadline/Local-Zone/ts/bin/app.ts index dc075f05c..ac6339a00 100644 --- a/examples/deadline/Local-Zone/ts/bin/app.ts +++ b/examples/deadline/Local-Zone/ts/bin/app.ts @@ -7,8 +7,8 @@ import 'source-map-support/register'; import { MachineImage, -} from '@aws-cdk/aws-ec2'; -import * as cdk from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; +import * as cdk from 'aws-cdk-lib'; import { config } from './config'; import { ComputeTier } from '../lib/compute-tier'; diff --git a/examples/deadline/Local-Zone/ts/cdk.json b/examples/deadline/Local-Zone/ts/cdk.json index c39a981a2..15a1c8fa2 100644 --- a/examples/deadline/Local-Zone/ts/cdk.json +++ b/examples/deadline/Local-Zone/ts/cdk.json @@ -1,18 +1,5 @@ { "app": "npx ts-node bin/app.ts", "context": { - "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, - "@aws-cdk/core:enableStackNameDuplicates": true, - "aws-cdk:enableDiffNoFail": true, - "@aws-cdk/core:stackRelativeExports": true, - "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true, - "@aws-cdk/aws-secretsmanager:parseOwnedSecretName": true, - "@aws-cdk/aws-kms:defaultKeyPolicies": true, - "@aws-cdk/aws-s3:grantWriteWithoutAcl": true, - "@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount": true, - "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, - "@aws-cdk/aws-efs:defaultEncryptionAtRest": true, - "@aws-cdk/aws-lambda:recognizeVersionProps": true, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true } } diff --git a/examples/deadline/Local-Zone/ts/lib/compute-tier.ts b/examples/deadline/Local-Zone/ts/lib/compute-tier.ts index 5eddadcab..9af87fecf 100644 --- a/examples/deadline/Local-Zone/ts/lib/compute-tier.ts +++ b/examples/deadline/Local-Zone/ts/lib/compute-tier.ts @@ -12,8 +12,8 @@ import { IVpc, SubnetSelection, SubnetType, -} from '@aws-cdk/aws-ec2'; -import * as cdk from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; +import * as cdk from 'aws-cdk-lib'; import { HealthMonitor, IHealthMonitor, @@ -26,6 +26,7 @@ import { IWorkerFleet, WorkerInstanceFleet, } from 'aws-rfdk/deadline'; +import { Construct } from 'constructs'; /** * Properties for {@link ComputeTier}. @@ -89,7 +90,7 @@ export class ComputeTier extends cdk.Stack { /** * Initializes a new instance of {@link ComputeTier}. */ - constructor(scope: cdk.Construct, id: string, props: ComputeTierProps) { + constructor(scope: Construct, id: string, props: ComputeTierProps) { super(scope, id, props); // We can put the health monitor and worker fleet in all of the local zones we're using diff --git a/examples/deadline/Local-Zone/ts/lib/network-tier.ts b/examples/deadline/Local-Zone/ts/lib/network-tier.ts index 5743b25b9..62f05527e 100644 --- a/examples/deadline/Local-Zone/ts/lib/network-tier.ts +++ b/examples/deadline/Local-Zone/ts/lib/network-tier.ts @@ -12,11 +12,12 @@ import { SubnetSelection, SubnetType, Vpc, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { PrivateHostedZone, -} from '@aws-cdk/aws-route53'; -import * as cdk from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-route53'; +import * as cdk from 'aws-cdk-lib'; +import { Construct } from 'constructs'; import { config } from '../bin/config'; @@ -72,7 +73,7 @@ export class NetworkTier extends cdk.Stack { /** * Initializes a new instance of {@link NetworkTier}. */ - constructor(scope: cdk.Construct, id: string, props: cdk.StackProps) { + constructor(scope: Construct, id: string, props: cdk.StackProps) { super(scope, id, props); // We're creating a SubnetSelection with only the standard availability zones to be diff --git a/examples/deadline/Local-Zone/ts/lib/security-tier.ts b/examples/deadline/Local-Zone/ts/lib/security-tier.ts index f4e4376af..85ffe6e97 100644 --- a/examples/deadline/Local-Zone/ts/lib/security-tier.ts +++ b/examples/deadline/Local-Zone/ts/lib/security-tier.ts @@ -3,10 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -import * as cdk from '@aws-cdk/core'; +import * as cdk from 'aws-cdk-lib'; import { X509CertificatePem, } from 'aws-rfdk'; +import { Construct } from 'constructs'; /** * The security tier of the render farm. This stack contains resources used to @@ -24,7 +25,7 @@ export class SecurityTier extends cdk.Stack { * @param id The ID of this construct. * @param props The properties for the security tier. */ - constructor(scope: cdk.Construct, id: string, props: cdk.StackProps) { + constructor(scope: Construct, id: string, props: cdk.StackProps) { super(scope, id, props); this.rootCa = new X509CertificatePem(this, 'RootCA', { diff --git a/examples/deadline/Local-Zone/ts/lib/service-tier.ts b/examples/deadline/Local-Zone/ts/lib/service-tier.ts index 3cd9f15f8..96b618ec0 100644 --- a/examples/deadline/Local-Zone/ts/lib/service-tier.ts +++ b/examples/deadline/Local-Zone/ts/lib/service-tier.ts @@ -7,20 +7,19 @@ import { IVpc, SubnetSelection, SubnetType, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { ApplicationProtocol, -} from '@aws-cdk/aws-elasticloadbalancingv2'; +} from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import { IPrivateHostedZone, -} from '@aws-cdk/aws-route53'; +} from 'aws-cdk-lib/aws-route53'; import { - Construct, Duration, RemovalPolicy, Stack, StackProps, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib'; import { SessionManagerHelper, X509CertificatePem, @@ -32,6 +31,7 @@ import { ThinkboxDockerImages, VersionQuery, } from 'aws-rfdk/deadline'; +import { Construct } from 'constructs'; /** * Properties for {@link ServiceTier}. diff --git a/examples/deadline/Local-Zone/ts/package.json b/examples/deadline/Local-Zone/ts/package.json index e46984d34..2d1843292 100644 --- a/examples/deadline/Local-Zone/ts/package.json +++ b/examples/deadline/Local-Zone/ts/package.json @@ -14,16 +14,14 @@ }, "devDependencies": { "@types/node": "^18.0.0", - "aws-cdk": "1.160.0", + "aws-cdk": "2.33.0", "ts-node": "^10.8.1", "typescript": "~4.7.3" }, "dependencies": { - "@aws-cdk/aws-ec2": "1.160.0", - "@aws-cdk/aws-elasticloadbalancingv2": "1.160.0", - "@aws-cdk/aws-route53": "1.160.0", - "@aws-cdk/core": "1.160.0", + "aws-cdk-lib": "^2.33.0", "aws-rfdk": "0.42.0", + "constructs": "^10.0.0", "source-map-support": "^0.5.21" } } diff --git a/integ/components/_infrastructure/bin/_infrastructure.ts b/integ/components/_infrastructure/bin/_infrastructure.ts index dde187338..3247abb23 100644 --- a/integ/components/_infrastructure/bin/_infrastructure.ts +++ b/integ/components/_infrastructure/bin/_infrastructure.ts @@ -5,7 +5,7 @@ /* eslint-disable no-console */ -import { App } from '@aws-cdk/core'; +import { App } from 'aws-cdk-lib'; import { NetworkTier } from '../lib/network-tier'; // Create a cdk app containing just a Vpc, that will then be used for the tests that follow diff --git a/integ/components/_infrastructure/cdk.json b/integ/components/_infrastructure/cdk.json index 3654e66bc..22fb34fa1 100644 --- a/integ/components/_infrastructure/cdk.json +++ b/integ/components/_infrastructure/cdk.json @@ -1,18 +1,5 @@ { "app": "npx ts-node bin/_infrastructure.ts", "context": { - "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, - "@aws-cdk/core:enableStackNameDuplicates": true, - "aws-cdk:enableDiffNoFail": true, - "@aws-cdk/core:stackRelativeExports": true, - "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true, - "@aws-cdk/aws-secretsmanager:parseOwnedSecretName": true, - "@aws-cdk/aws-kms:defaultKeyPolicies": true, - "@aws-cdk/aws-s3:grantWriteWithoutAcl": true, - "@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount": true, - "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, - "@aws-cdk/aws-efs:defaultEncryptionAtRest": true, - "@aws-cdk/aws-lambda:recognizeVersionProps": true, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true } } diff --git a/integ/components/_infrastructure/lib/network-tier.ts b/integ/components/_infrastructure/lib/network-tier.ts index e58fec08a..45f65aa94 100644 --- a/integ/components/_infrastructure/lib/network-tier.ts +++ b/integ/components/_infrastructure/lib/network-tier.ts @@ -3,16 +3,16 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { + Stack, + StackProps, +} from 'aws-cdk-lib'; import { SubnetConfiguration, SubnetType, Vpc, -} from '@aws-cdk/aws-ec2'; -import { - Construct, - Stack, - StackProps, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; +import { Construct } from 'constructs'; export interface NetworkTierSubnetConfiguration { readonly testRunner: SubnetConfiguration; diff --git a/integ/components/deadline/common/functions/awaitSsmCommand.ts b/integ/components/deadline/common/functions/awaitSsmCommand.ts index 1a99e8f0a..d9d0bfe60 100644 --- a/integ/components/deadline/common/functions/awaitSsmCommand.ts +++ b/integ/components/deadline/common/functions/awaitSsmCommand.ts @@ -5,6 +5,11 @@ import {SSM, SendCommandRequest } from '@aws-sdk/client-ssm'; +// Workaround for AWS SDK v3 bug: https://github.com/aws/aws-sdk-js-v3/issues/3807 +declare global { + interface ReadableStream {} +} + const ssm = new SSM({}); interface CommandResponse { diff --git a/integ/components/deadline/deadline_01_repository/bin/deadline_01_repository.ts b/integ/components/deadline/deadline_01_repository/bin/deadline_01_repository.ts index 823bf5a01..2da3cc926 100644 --- a/integ/components/deadline/deadline_01_repository/bin/deadline_01_repository.ts +++ b/integ/components/deadline/deadline_01_repository/bin/deadline_01_repository.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { App, Stack, Aspects } from '@aws-cdk/core'; +import { App, Stack, Aspects } from 'aws-cdk-lib'; import { Stage, ThinkboxDockerRecipes, diff --git a/integ/components/deadline/deadline_01_repository/cdk.json b/integ/components/deadline/deadline_01_repository/cdk.json index f1efd7cbd..6a9421292 100644 --- a/integ/components/deadline/deadline_01_repository/cdk.json +++ b/integ/components/deadline/deadline_01_repository/cdk.json @@ -1,18 +1,5 @@ { "app": "npx ts-node bin/deadline_01_repository.ts", "context": { - "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, - "@aws-cdk/core:enableStackNameDuplicates": true, - "aws-cdk:enableDiffNoFail": true, - "@aws-cdk/core:stackRelativeExports": true, - "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true, - "@aws-cdk/aws-secretsmanager:parseOwnedSecretName": true, - "@aws-cdk/aws-kms:defaultKeyPolicies": true, - "@aws-cdk/aws-s3:grantWriteWithoutAcl": true, - "@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount": true, - "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, - "@aws-cdk/aws-efs:defaultEncryptionAtRest": true, - "@aws-cdk/aws-lambda:recognizeVersionProps": true, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true } } diff --git a/integ/components/deadline/deadline_01_repository/lib/repository-testing-tier.ts b/integ/components/deadline/deadline_01_repository/lib/repository-testing-tier.ts index ff539ed7d..c2a155949 100644 --- a/integ/components/deadline/deadline_01_repository/lib/repository-testing-tier.ts +++ b/integ/components/deadline/deadline_01_repository/lib/repository-testing-tier.ts @@ -4,10 +4,11 @@ */ import * as path from 'path'; -import { ILogGroup } from '@aws-cdk/aws-logs'; -import { CfnOutput, Construct } from '@aws-cdk/core'; +import { CfnOutput } from 'aws-cdk-lib'; +import { ILogGroup } from 'aws-cdk-lib/aws-logs'; import { MongoDbInstaller, MongoDbSsplLicenseAcceptance, MongoDbVersion } from 'aws-rfdk'; import { Repository } from 'aws-rfdk/deadline'; +import { Construct } from 'constructs'; import { StorageStruct } from '../../../../lib/storage-struct'; import { TestingTier, TestingTierProps } from '../../../../lib/testing-tier'; diff --git a/integ/components/deadline/deadline_02_renderQueue/bin/deadline_02_renderQueue.ts b/integ/components/deadline/deadline_02_renderQueue/bin/deadline_02_renderQueue.ts index f355fe4ac..11cf1f63d 100644 --- a/integ/components/deadline/deadline_02_renderQueue/bin/deadline_02_renderQueue.ts +++ b/integ/components/deadline/deadline_02_renderQueue/bin/deadline_02_renderQueue.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { App, Stack, Aspects } from '@aws-cdk/core'; +import { App, Stack, Aspects } from 'aws-cdk-lib'; import { Stage, ThinkboxDockerRecipes, diff --git a/integ/components/deadline/deadline_02_renderQueue/cdk.json b/integ/components/deadline/deadline_02_renderQueue/cdk.json index 90af678a0..29b735e05 100644 --- a/integ/components/deadline/deadline_02_renderQueue/cdk.json +++ b/integ/components/deadline/deadline_02_renderQueue/cdk.json @@ -1,18 +1,5 @@ { "app": "npx ts-node bin/deadline_02_renderQueue.ts", "context": { - "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, - "@aws-cdk/core:enableStackNameDuplicates": true, - "aws-cdk:enableDiffNoFail": true, - "@aws-cdk/core:stackRelativeExports": true, - "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true, - "@aws-cdk/aws-secretsmanager:parseOwnedSecretName": true, - "@aws-cdk/aws-kms:defaultKeyPolicies": true, - "@aws-cdk/aws-s3:grantWriteWithoutAcl": true, - "@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount": true, - "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, - "@aws-cdk/aws-efs:defaultEncryptionAtRest": true, - "@aws-cdk/aws-lambda:recognizeVersionProps": true, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true } } diff --git a/integ/components/deadline/deadline_02_renderQueue/lib/renderQueue-testing-tier.ts b/integ/components/deadline/deadline_02_renderQueue/lib/renderQueue-testing-tier.ts index a7e63ef76..70b5b13c2 100644 --- a/integ/components/deadline/deadline_02_renderQueue/lib/renderQueue-testing-tier.ts +++ b/integ/components/deadline/deadline_02_renderQueue/lib/renderQueue-testing-tier.ts @@ -4,7 +4,7 @@ */ import * as path from 'path'; -import { Construct } from '@aws-cdk/core'; +import { Construct } from 'constructs'; import { RenderStruct } from '../../../../lib/render-struct'; import { TestingTier, TestingTierProps } from '../../../../lib/testing-tier'; diff --git a/integ/components/deadline/deadline_03_workerFleetHttp/bin/deadline_03_workerFleetHttp.ts b/integ/components/deadline/deadline_03_workerFleetHttp/bin/deadline_03_workerFleetHttp.ts index d48d51975..2090e355b 100644 --- a/integ/components/deadline/deadline_03_workerFleetHttp/bin/deadline_03_workerFleetHttp.ts +++ b/integ/components/deadline/deadline_03_workerFleetHttp/bin/deadline_03_workerFleetHttp.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { App, Stack, Aspects } from '@aws-cdk/core'; +import { App, Stack, Aspects } from 'aws-cdk-lib'; import { Stage, ThinkboxDockerRecipes, diff --git a/integ/components/deadline/deadline_03_workerFleetHttp/cdk.json b/integ/components/deadline/deadline_03_workerFleetHttp/cdk.json index 3d187c870..3a24211a6 100644 --- a/integ/components/deadline/deadline_03_workerFleetHttp/cdk.json +++ b/integ/components/deadline/deadline_03_workerFleetHttp/cdk.json @@ -1,18 +1,5 @@ { "app": "npx ts-node bin/deadline_03_workerFleetHttp.ts", "context": { - "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, - "@aws-cdk/core:enableStackNameDuplicates": true, - "aws-cdk:enableDiffNoFail": true, - "@aws-cdk/core:stackRelativeExports": true, - "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true, - "@aws-cdk/aws-secretsmanager:parseOwnedSecretName": true, - "@aws-cdk/aws-kms:defaultKeyPolicies": true, - "@aws-cdk/aws-s3:grantWriteWithoutAcl": true, - "@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount": true, - "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, - "@aws-cdk/aws-efs:defaultEncryptionAtRest": true, - "@aws-cdk/aws-lambda:recognizeVersionProps": true, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true } } diff --git a/integ/components/deadline/deadline_03_workerFleetHttp/lib/workerFleetHttp-testing-tier.ts b/integ/components/deadline/deadline_03_workerFleetHttp/lib/workerFleetHttp-testing-tier.ts index fb858a1d7..672e7e8ee 100644 --- a/integ/components/deadline/deadline_03_workerFleetHttp/lib/workerFleetHttp-testing-tier.ts +++ b/integ/components/deadline/deadline_03_workerFleetHttp/lib/workerFleetHttp-testing-tier.ts @@ -4,9 +4,9 @@ */ import * as path from 'path'; -import { Port } from '@aws-cdk/aws-ec2'; -import { Construct } from '@aws-cdk/core'; +import { Port } from 'aws-cdk-lib/aws-ec2'; import { IWorkerFleet } from 'aws-rfdk/deadline'; +import { Construct } from 'constructs'; import { TestingTier, TestingTierProps } from '../../../../lib/testing-tier'; import { WorkerStruct } from '../../../../lib/worker-struct'; diff --git a/integ/components/deadline/deadline_04_workerFleetHttps/bin/deadline_04_workerFleetHttps.ts b/integ/components/deadline/deadline_04_workerFleetHttps/bin/deadline_04_workerFleetHttps.ts index c2888dba3..3642b96bd 100644 --- a/integ/components/deadline/deadline_04_workerFleetHttps/bin/deadline_04_workerFleetHttps.ts +++ b/integ/components/deadline/deadline_04_workerFleetHttps/bin/deadline_04_workerFleetHttps.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { App, Stack, Aspects } from '@aws-cdk/core'; +import { App, Stack, Aspects } from 'aws-cdk-lib'; import { Stage, ThinkboxDockerRecipes, diff --git a/integ/components/deadline/deadline_04_workerFleetHttps/cdk.json b/integ/components/deadline/deadline_04_workerFleetHttps/cdk.json index a121ce687..db8ddb2bf 100644 --- a/integ/components/deadline/deadline_04_workerFleetHttps/cdk.json +++ b/integ/components/deadline/deadline_04_workerFleetHttps/cdk.json @@ -1,18 +1,5 @@ { "app": "npx ts-node bin/deadline_04_workerFleetHttps.ts", "context": { - "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, - "@aws-cdk/core:enableStackNameDuplicates": true, - "aws-cdk:enableDiffNoFail": true, - "@aws-cdk/core:stackRelativeExports": true, - "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true, - "@aws-cdk/aws-secretsmanager:parseOwnedSecretName": true, - "@aws-cdk/aws-kms:defaultKeyPolicies": true, - "@aws-cdk/aws-s3:grantWriteWithoutAcl": true, - "@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount": true, - "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, - "@aws-cdk/aws-efs:defaultEncryptionAtRest": true, - "@aws-cdk/aws-lambda:recognizeVersionProps": true, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true } } diff --git a/integ/components/deadline/deadline_04_workerFleetHttps/lib/workerFleetHttps-testing-tier.ts b/integ/components/deadline/deadline_04_workerFleetHttps/lib/workerFleetHttps-testing-tier.ts index b80d67b32..15e37aced 100644 --- a/integ/components/deadline/deadline_04_workerFleetHttps/lib/workerFleetHttps-testing-tier.ts +++ b/integ/components/deadline/deadline_04_workerFleetHttps/lib/workerFleetHttps-testing-tier.ts @@ -4,9 +4,9 @@ */ import * as path from 'path'; -import { Port } from '@aws-cdk/aws-ec2'; -import { Construct } from '@aws-cdk/core'; +import { Port } from 'aws-cdk-lib/aws-ec2'; import { IWorkerFleet } from 'aws-rfdk/deadline'; +import { Construct } from 'constructs'; import { TestingTier, TestingTierProps } from '../../../../lib/testing-tier'; import { WorkerStruct } from '../../../../lib/worker-struct'; diff --git a/integ/components/deadline/deadline_05_secretsManagement/bin/deadline_05_secretsManagement.ts b/integ/components/deadline/deadline_05_secretsManagement/bin/deadline_05_secretsManagement.ts index 08ffa8898..6b44de71b 100644 --- a/integ/components/deadline/deadline_05_secretsManagement/bin/deadline_05_secretsManagement.ts +++ b/integ/components/deadline/deadline_05_secretsManagement/bin/deadline_05_secretsManagement.ts @@ -5,8 +5,8 @@ import * as fs from 'fs'; import * as path from 'path'; -import { App, Stack, Aspects } from '@aws-cdk/core'; import { SecretsManager, ResourceNotFoundException } from '@aws-sdk/client-secrets-manager'; +import { App, Stack, Aspects } from 'aws-cdk-lib'; import { Stage, ThinkboxDockerRecipes, diff --git a/integ/components/deadline/deadline_05_secretsManagement/cdk.json b/integ/components/deadline/deadline_05_secretsManagement/cdk.json index e209b4377..2ce57444a 100644 --- a/integ/components/deadline/deadline_05_secretsManagement/cdk.json +++ b/integ/components/deadline/deadline_05_secretsManagement/cdk.json @@ -1,18 +1,5 @@ { "app": "npx ts-node bin/deadline_05_secretsManagement.ts", "context": { - "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, - "@aws-cdk/core:enableStackNameDuplicates": true, - "aws-cdk:enableDiffNoFail": true, - "@aws-cdk/core:stackRelativeExports": true, - "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true, - "@aws-cdk/aws-secretsmanager:parseOwnedSecretName": true, - "@aws-cdk/aws-kms:defaultKeyPolicies": true, - "@aws-cdk/aws-s3:grantWriteWithoutAcl": true, - "@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount": true, - "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, - "@aws-cdk/aws-efs:defaultEncryptionAtRest": true, - "@aws-cdk/aws-lambda:recognizeVersionProps": true, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true } } diff --git a/integ/components/deadline/deadline_05_secretsManagement/lib/secretsManagement-testing-tier.ts b/integ/components/deadline/deadline_05_secretsManagement/lib/secretsManagement-testing-tier.ts index 8d009d647..0ade06e70 100644 --- a/integ/components/deadline/deadline_05_secretsManagement/lib/secretsManagement-testing-tier.ts +++ b/integ/components/deadline/deadline_05_secretsManagement/lib/secretsManagement-testing-tier.ts @@ -4,11 +4,12 @@ */ import * as path from 'path'; +import { CfnOutput } from 'aws-cdk-lib'; import { IVpc, -} from '@aws-cdk/aws-ec2'; -import { CfnOutput, Construct } from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; import { Repository } from 'aws-rfdk/deadline'; +import { Construct } from 'constructs'; import { RenderStruct } from '../../../../lib/render-struct'; import { StorageStruct } from '../../../../lib/storage-struct'; import { diff --git a/integ/components/deadline/deadline_05_secretsManagement/test/deadline_05_secretsManagement.test.ts b/integ/components/deadline/deadline_05_secretsManagement/test/deadline_05_secretsManagement.test.ts index f3b18a53b..7c96b6dbf 100644 --- a/integ/components/deadline/deadline_05_secretsManagement/test/deadline_05_secretsManagement.test.ts +++ b/integ/components/deadline/deadline_05_secretsManagement/test/deadline_05_secretsManagement.test.ts @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { CloudFormation } from '@aws-sdk/client-cloudformation'; +import { SecretsManager } from '@aws-sdk/client-secrets-manager'; import { CidrBlock, NetworkUtils, -} from '@aws-cdk/aws-ec2/lib/network-util'; -import { CloudFormation } from '@aws-sdk/client-cloudformation'; -import { SecretsManager } from '@aws-sdk/client-secrets-manager'; +} from 'aws-cdk-lib/aws-ec2/lib/network-util'; import { ssmCommand } from '../../common/functions/awaitSsmCommand'; // Name of testing stack is derived from env variable to ensure uniqueness diff --git a/integ/lib/render-struct.ts b/integ/lib/render-struct.ts index 0e0859457..5f334f33d 100644 --- a/integ/lib/render-struct.ts +++ b/integ/lib/render-struct.ts @@ -3,11 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Vpc } from '@aws-cdk/aws-ec2'; -import { ApplicationProtocol } from '@aws-cdk/aws-elasticloadbalancingv2'; -import { PrivateHostedZone } from '@aws-cdk/aws-route53'; -import { Secret } from '@aws-cdk/aws-secretsmanager'; -import { Construct, Stack } from '@aws-cdk/core'; +import { Stack } from 'aws-cdk-lib'; +import { Vpc } from 'aws-cdk-lib/aws-ec2'; +import { ApplicationProtocol } from 'aws-cdk-lib/aws-elasticloadbalancingv2'; +import { RetentionDays } from 'aws-cdk-lib/aws-logs'; +import { PrivateHostedZone } from 'aws-cdk-lib/aws-route53'; +import { Secret } from 'aws-cdk-lib/aws-secretsmanager'; import { X509CertificatePem } from 'aws-rfdk'; import { IRepository, @@ -18,6 +19,7 @@ import { UsageBasedLicense, UsageBasedLicensing, } from 'aws-rfdk/deadline'; +import { Construct } from 'constructs'; import { NetworkTier } from '../components/_infrastructure/lib/network-tier'; import { ThinkboxDockerImageOverrides } from './thinkbox-docker-image-overrides'; @@ -106,7 +108,8 @@ export class RenderStruct extends Construct { repository: props.repository, images: dockerImageOverrides?.renderQueueImages ?? props.recipes.renderQueueImages, logGroupProps: { - logGroupPrefix: Stack.of(this).stackName + '-' + id, + logGroupPrefix: `/${Stack.of(this).stackName}-${id}/`, + retention: RetentionDays.TWO_MONTHS, }, hostname, version: props.recipes.version, @@ -125,6 +128,10 @@ export class RenderStruct extends Construct { images: dockerImageOverrides?.ublImages ?? props.recipes.ublImages, licenses: props.ubl.licenses, certificateSecret: ublCertificates, + logGroupProps: { + logGroupPrefix: `/${Stack.of(this).stackName}-${id}/`, + retention: RetentionDays.TWO_MONTHS, + }, }); } } diff --git a/integ/lib/sep-worker-struct.ts b/integ/lib/sep-worker-struct.ts index 96aab3502..04a84b110 100644 --- a/integ/lib/sep-worker-struct.ts +++ b/integ/lib/sep-worker-struct.ts @@ -3,19 +3,22 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { + Stack, +} from 'aws-cdk-lib'; import { InstanceType, MachineImage, Vpc, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { - Construct, - Stack, -} from '@aws-cdk/core'; + RetentionDays, +} from 'aws-cdk-lib/aws-logs'; import { ConfigureSpotEventPlugin, SpotEventPluginFleet, } from 'aws-rfdk/deadline'; +import { Construct } from 'constructs'; import { NetworkTier } from '../components/_infrastructure/lib/network-tier'; import { RenderStruct } from './render-struct'; @@ -52,6 +55,10 @@ export class SepWorkerStruct extends Construct { workerMachineImage: MachineImage.genericLinux({ [Stack.of(this).region]: linuxAmi }), deadlineGroups: ['sep_group'], instanceTypes: [new InstanceType('t2.micro')], + logGroupProps: { + logGroupPrefix: `/${Stack.of(this).stackName}-${id}/`, + retention: RetentionDays.TWO_MONTHS, + }, }), ]; diff --git a/integ/lib/ssm-policy-aspect.ts b/integ/lib/ssm-policy-aspect.ts index 1c52a00a7..5684ded6a 100644 --- a/integ/lib/ssm-policy-aspect.ts +++ b/integ/lib/ssm-policy-aspect.ts @@ -3,14 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { AutoScalingGroup } from '@aws-cdk/aws-autoscaling'; -import { Instance } from '@aws-cdk/aws-ec2'; -import { ManagedPolicy } from '@aws-cdk/aws-iam'; -import * as cdk from '@aws-cdk/core'; +import * as cdk from 'aws-cdk-lib'; +import { AutoScalingGroup } from 'aws-cdk-lib/aws-autoscaling'; +import { Instance } from 'aws-cdk-lib/aws-ec2'; +import { ManagedPolicy } from 'aws-cdk-lib/aws-iam'; +import { IConstruct } from 'constructs'; export class SSMInstancePolicyAspect implements cdk.IAspect { private static readonly SSM_POLICY = ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'); - public visit(node: cdk.IConstruct): void { + public visit(node: IConstruct): void { if (node instanceof Instance || node instanceof AutoScalingGroup) { node.role.addManagedPolicy(SSMInstancePolicyAspect.SSM_POLICY); } diff --git a/integ/lib/storage-struct.ts b/integ/lib/storage-struct.ts index da41bb3d3..f0188dd04 100644 --- a/integ/lib/storage-struct.ts +++ b/integ/lib/storage-struct.ts @@ -3,26 +3,29 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { DatabaseCluster } from '@aws-cdk/aws-docdb'; +import { + Duration, + RemovalPolicy, + Stack, +} from 'aws-cdk-lib'; +import { DatabaseCluster } from 'aws-cdk-lib/aws-docdb'; import { InstanceClass, InstanceSize, InstanceType, Vpc, SubnetType, -} from '@aws-cdk/aws-ec2'; + Volume, +} from 'aws-cdk-lib/aws-ec2'; import { AccessPoint, FileSystem, -} from '@aws-cdk/aws-efs'; -import { PrivateHostedZone } from '@aws-cdk/aws-route53'; -import { ISecret } from '@aws-cdk/aws-secretsmanager'; +} from 'aws-cdk-lib/aws-efs'; import { - Construct, - Duration, - RemovalPolicy, - Stack, -} from '@aws-cdk/core'; + RetentionDays, +} from 'aws-cdk-lib/aws-logs'; +import { PrivateHostedZone } from 'aws-cdk-lib/aws-route53'; +import { ISecret } from 'aws-cdk-lib/aws-secretsmanager'; import { MongoDbInstance, MongoDbPostInstallSetup, @@ -37,6 +40,7 @@ import { IVersion, Repository, } from 'aws-rfdk/deadline'; +import { Construct } from 'constructs'; // Interface for supplying database connection and accompanying secret for credentials @@ -172,6 +176,10 @@ export class StorageStruct extends Construct { // Create the mongoDB instance database = new MongoDbInstance(this, 'MongoDB', { + logGroupProps: { + logGroupPrefix: `/${Stack.of(this).stackName}-${id}/`, + retention: RetentionDays.TWO_MONTHS, + }, mongoDb: { userSsplAcceptance, version: MongoDbVersion.COMMUNITY_3_6, @@ -185,6 +193,9 @@ export class StorageStruct extends Construct { vpc, }); databaseSecret = database.adminUser!; + // Ensure that the EBS Volume created by the MongoDB construct is deleted. + const dbDataEBS = database.node.findChild('MongoDbData') as Volume; + dbDataEBS.applyRemovalPolicy(RemovalPolicy.DESTROY); new MongoDbPostInstallSetup(this, 'MongoDbPostInstall', { vpc, @@ -220,7 +231,8 @@ export class StorageStruct extends Construct { version: props.version, repositoryInstallationTimeout: Duration.minutes(20), logGroupProps: { - logGroupPrefix: Stack.of(this).stackName + '-' + id, + logGroupPrefix: `/${Stack.of(this).stackName}-${id}/`, + retention: RetentionDays.TWO_MONTHS, }, removalPolicy: { database: RemovalPolicy.DESTROY, diff --git a/integ/lib/testing-tier.ts b/integ/lib/testing-tier.ts index 9f2925740..ef287e41d 100644 --- a/integ/lib/testing-tier.ts +++ b/integ/lib/testing-tier.ts @@ -4,19 +4,20 @@ */ import * as path from 'path'; +import { CfnOutput, Duration, Stack, StackProps } from 'aws-cdk-lib'; import { BastionHostLinux, InstanceType, Port, Vpc, -} from '@aws-cdk/aws-ec2'; -import { Asset } from '@aws-cdk/aws-s3-assets'; -import { CfnOutput, Construct, Duration, Stack, StackProps } from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; +import { Asset } from 'aws-cdk-lib/aws-s3-assets'; import { SessionManagerHelper, X509CertificatePem, } from 'aws-rfdk'; import { RenderQueue } from 'aws-rfdk/deadline'; +import { Construct } from 'constructs'; import { NetworkTier } from '../components/_infrastructure/lib/network-tier'; import { IRenderFarmDb } from './storage-struct'; diff --git a/integ/lib/thinkbox-docker-image-overrides.ts b/integ/lib/thinkbox-docker-image-overrides.ts index 2fa68b05e..6e63637fb 100644 --- a/integ/lib/thinkbox-docker-image-overrides.ts +++ b/integ/lib/thinkbox-docker-image-overrides.ts @@ -3,14 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Repository } from '@aws-cdk/aws-ecr'; -import { ContainerImage } from '@aws-cdk/aws-ecs'; -import { Construct } from '@aws-cdk/core'; +import { Repository } from 'aws-cdk-lib/aws-ecr'; +import { ContainerImage } from 'aws-cdk-lib/aws-ecs'; import { RenderQueueImages, ThinkboxManagedDeadlineDockerRecipes as Recipes, UsageBasedLicensingImages, } from 'aws-rfdk/deadline'; +import { Construct } from 'constructs'; type DeadlineDockerImageOverrides = {[key in Recipes]?: string}; diff --git a/integ/lib/worker-struct.ts b/integ/lib/worker-struct.ts index 508f7708e..1d898a598 100644 --- a/integ/lib/worker-struct.ts +++ b/integ/lib/worker-struct.ts @@ -3,13 +3,17 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { IMachineImage, MachineImage, Port, Vpc } from '@aws-cdk/aws-ec2'; -import { Construct, Stack } from '@aws-cdk/core'; +import { Stack } from 'aws-cdk-lib'; +import { IMachineImage, MachineImage, Port, Vpc } from 'aws-cdk-lib/aws-ec2'; +import { + RetentionDays, +} from 'aws-cdk-lib/aws-logs'; import { X509CertificatePem } from 'aws-rfdk'; import { RenderQueue, WorkerInstanceFleet, } from 'aws-rfdk/deadline'; +import { Construct } from 'constructs'; import { NetworkTier } from '../components/_infrastructure/lib/network-tier'; import { RenderStruct } from './render-struct'; @@ -58,7 +62,8 @@ export class WorkerStruct extends Construct { renderQueue: this.renderQueue, workerMachineImage, logGroupProps: { - logGroupPrefix: Stack.of(this).stackName + '-' + id, + logGroupPrefix: `/${Stack.of(this).stackName}-${id}/`, + retention: RetentionDays.TWO_MONTHS, }, groups: ['testgroup'], }), @@ -68,7 +73,8 @@ export class WorkerStruct extends Construct { renderQueue: this.renderQueue, workerMachineImage, logGroupProps: { - logGroupPrefix: Stack.of(this).stackName + '-' + id, + logGroupPrefix: `/${Stack.of(this).stackName}-${id}/`, + retention: RetentionDays.TWO_MONTHS, }, pools: ['testpool'], }), @@ -78,7 +84,8 @@ export class WorkerStruct extends Construct { renderQueue: this.renderQueue, workerMachineImage, logGroupProps: { - logGroupPrefix: Stack.of(this).stackName + '-' + id, + logGroupPrefix: `/${Stack.of(this).stackName}-${id}/`, + retention: RetentionDays.TWO_MONTHS, }, region: 'testregion', }), diff --git a/integ/package.json b/integ/package.json index e56032f6a..258ec823d 100644 --- a/integ/package.json +++ b/integ/package.json @@ -52,15 +52,16 @@ "clean": "./scripts/bash/cleanup.sh", "deploy-all": "./scripts/bash/deploy-all.sh", "tear-down": "./scripts/bash/tear-down.sh", - "pkglint": "pkglint -f" + "pkglint": "pkglint -f", + "lint": "eslint . --ext=.ts", + "lintfix": "eslint . --ext=.ts --fix" }, "devDependencies": { - "@aws-cdk/assert": "1.160.0", "@types/jest": "^27.5.2", "@types/node": "^18.0.0", "@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/parser": "^4.33.0", - "aws-cdk": "1.160.0", + "aws-cdk": "2.33.0", "eslint": "^7.32.0", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^2.7.1", @@ -73,42 +74,18 @@ "typescript": "~4.7.3" }, "dependencies": { - "@aws-cdk/aws-autoscaling": "1.160.0", - "@aws-cdk/aws-docdb": "1.160.0", - "@aws-cdk/aws-ec2": "1.160.0", - "@aws-cdk/aws-ecr": "1.160.0", - "@aws-cdk/aws-ecs": "1.160.0", - "@aws-cdk/aws-efs": "1.160.0", - "@aws-cdk/aws-elasticloadbalancingv2": "1.160.0", - "@aws-cdk/aws-iam": "1.160.0", - "@aws-cdk/aws-logs": "1.160.0", - "@aws-cdk/aws-route53": "1.160.0", - "@aws-cdk/aws-s3": "1.160.0", - "@aws-cdk/aws-s3-assets": "1.160.0", - "@aws-cdk/aws-secretsmanager": "1.160.0", - "@aws-cdk/core": "1.160.0", "@aws-sdk/client-cloudformation": "^3.110.0", "@aws-sdk/client-cloudwatch-logs": "^3.110.0", "@aws-sdk/client-secrets-manager": "^3.110.0", "@aws-sdk/client-ssm": "^3.110.0", - "aws-rfdk": "0.42.0" + "aws-cdk-lib": "2.33.0", + "aws-rfdk": "0.42.0", + "constructs": "^10.0.0" }, "peerDependencies": { - "@aws-cdk/aws-autoscaling": "1.160.0", - "@aws-cdk/aws-docdb": "1.160.0", - "@aws-cdk/aws-ec2": "1.160.0", - "@aws-cdk/aws-ecr": "1.160.0", - "@aws-cdk/aws-ecs": "1.160.0", - "@aws-cdk/aws-efs": "1.160.0", - "@aws-cdk/aws-elasticloadbalancingv2": "1.160.0", - "@aws-cdk/aws-iam": "1.160.0", - "@aws-cdk/aws-logs": "1.160.0", - "@aws-cdk/aws-route53": "1.160.0", - "@aws-cdk/aws-s3": "1.160.0", - "@aws-cdk/aws-s3-assets": "1.160.0", - "@aws-cdk/aws-secretsmanager": "1.160.0", - "@aws-cdk/core": "1.160.0", - "aws-rfdk": "0.42.0" + "aws-cdk-lib": "2.33.0", + "aws-rfdk": "0.42.0", + "constructs": "^10.0.0" }, "engines": { "node": ">= 14.15.0" diff --git a/package.json b/package.json index 4fa25da48..a3628f896 100644 --- a/package.json +++ b/package.json @@ -26,82 +26,15 @@ } }, "devDependencies": { - "@aws-cdk/assets": "1.160.0", - "@aws-cdk/aws-acmpca": "1.160.0", - "@aws-cdk/aws-apigateway": "1.160.0", - "@aws-cdk/aws-apigatewayv2": "1.160.0", - "@aws-cdk/aws-apigatewayv2-integrations": "1.160.0", - "@aws-cdk/aws-applicationautoscaling": "1.160.0", - "@aws-cdk/aws-autoscaling": "1.160.0", - "@aws-cdk/aws-autoscaling-common": "1.160.0", - "@aws-cdk/aws-autoscaling-hooktargets": "1.160.0", - "@aws-cdk/aws-batch": "1.160.0", - "@aws-cdk/aws-certificatemanager": "1.160.0", - "@aws-cdk/aws-cloudformation": "1.160.0", - "@aws-cdk/aws-cloudfront": "1.160.0", - "@aws-cdk/aws-cloudwatch": "1.160.0", - "@aws-cdk/aws-cloudwatch-actions": "1.160.0", - "@aws-cdk/aws-codebuild": "1.160.0", - "@aws-cdk/aws-codecommit": "1.160.0", - "@aws-cdk/aws-codeguruprofiler": "1.160.0", - "@aws-cdk/aws-codepipeline": "1.160.0", - "@aws-cdk/aws-codestarnotifications": "1.160.0", - "@aws-cdk/aws-cognito": "1.160.0", - "@aws-cdk/aws-databrew": "1.160.0", - "@aws-cdk/aws-docdb": "1.160.0", - "@aws-cdk/aws-dynamodb": "1.160.0", - "@aws-cdk/aws-ec2": "1.160.0", - "@aws-cdk/aws-ecr": "1.160.0", - "@aws-cdk/aws-ecr-assets": "1.160.0", - "@aws-cdk/aws-ecs": "1.160.0", - "@aws-cdk/aws-ecs-patterns": "1.160.0", - "@aws-cdk/aws-efs": "1.160.0", - "@aws-cdk/aws-eks": "1.160.0", - "@aws-cdk/aws-elasticloadbalancing": "1.160.0", - "@aws-cdk/aws-elasticloadbalancingv2": "1.160.0", - "@aws-cdk/aws-events": "1.160.0", - "@aws-cdk/aws-events-targets": "1.160.0", - "@aws-cdk/aws-fsx": "1.160.0", - "@aws-cdk/aws-globalaccelerator": "1.160.0", - "@aws-cdk/aws-glue": "1.160.0", - "@aws-cdk/aws-iam": "1.160.0", - "@aws-cdk/aws-kinesis": "1.160.0", - "@aws-cdk/aws-kinesisfirehose": "1.160.0", - "@aws-cdk/aws-kms": "1.160.0", - "@aws-cdk/aws-lambda": "1.160.0", - "@aws-cdk/aws-lambda-nodejs": "1.160.0", - "@aws-cdk/aws-logs": "1.160.0", - "@aws-cdk/aws-route53": "1.160.0", - "@aws-cdk/aws-route53-targets": "1.160.0", - "@aws-cdk/aws-s3": "1.160.0", - "@aws-cdk/aws-s3-assets": "1.160.0", - "@aws-cdk/aws-sam": "1.160.0", - "@aws-cdk/aws-secretsmanager": "1.160.0", - "@aws-cdk/aws-servicediscovery": "1.160.0", - "@aws-cdk/aws-signer": "1.160.0", - "@aws-cdk/aws-sns": "1.160.0", - "@aws-cdk/aws-sns-subscriptions": "1.160.0", - "@aws-cdk/aws-sqs": "1.160.0", - "@aws-cdk/aws-ssm": "1.160.0", - "@aws-cdk/aws-stepfunctions": "1.160.0", - "@aws-cdk/aws-stepfunctions-tasks": "1.160.0", - "@aws-cdk/cloud-assembly-schema": "1.160.0", - "@aws-cdk/core": "1.160.0", - "@aws-cdk/custom-resources": "1.160.0", - "@aws-cdk/cx-api": "1.160.0", - "@aws-cdk/lambda-layer-awscli": "1.160.0", - "@aws-cdk/lambda-layer-kubectl": "1.160.0", - "@aws-cdk/lambda-layer-node-proxy-agent": "1.160.0", - "@aws-cdk/region-info": "1.160.0", - "@types/jest": "^27.5.2", - "@types/node": "^18.0.0", - "aws-cdk": "1.160.0", - "aws-sdk": "^2.1155.0", "@aws-sdk/client-ssm": "^3.110.0", "@aws-sdk/client-cloudformation": "^3.110.0", "@aws-sdk/client-cloudwatch-logs": "^3.110.0", "@aws-sdk/client-secrets-manager": "^3.110.0", - "constructs": "^3.3.69", + "@types/jest": "^27.5.2", + "@types/node": "^18.0.0", + "aws-cdk-lib": "2.33.0", + "aws-sdk": "^2.1155.0", + "constructs": "^10.0.0", "fs-extra": "^9.1.0", "jest": "^27.5.1", "jest-junit": "^13.2.0", diff --git a/packages/aws-rfdk/docs/diagrams/README.md b/packages/aws-rfdk/docs/diagrams/README.md index a79dbca52..54c33d7b8 100644 --- a/packages/aws-rfdk/docs/diagrams/README.md +++ b/packages/aws-rfdk/docs/diagrams/README.md @@ -40,7 +40,7 @@ only process image URLs that begin with `/diagrams`. Putting this together, the in the `core` package would look: ```ts -import { Construct } from '@aws-cdk/core'; +import { Construct } from 'aws-cdk-lib'; /** * Documentation for MyConstruct diff --git a/packages/aws-rfdk/docs/upgrade/upgrading-0.27.md b/packages/aws-rfdk/docs/upgrade/upgrading-0.27.md index 93accceac..ab6891864 100644 --- a/packages/aws-rfdk/docs/upgrade/upgrading-0.27.md +++ b/packages/aws-rfdk/docs/upgrade/upgrading-0.27.md @@ -114,7 +114,7 @@ the root of the EFS file-system. Sample code: **TypeScript:** ```ts -import { AccessPoint, FileSystem } from '@aws-cdk/aws-efs'; +import { AccessPoint, FileSystem } from 'aws-cdk-lib/aws-efs'; const fileSystem = new FileSystem(scope, 'FileSystem', { // ... @@ -169,7 +169,7 @@ EFS file-system, you could do the following: **TypeScript:** ```ts -import { AccessPoint, FileSystem } from '@aws-cdk/aws-efs'; +import { AccessPoint, FileSystem } from 'aws-cdk-lib/aws-efs'; import { MountableEfs } from 'aws-rfdk'; import { Repository } from 'aws-rfdk/deadline'; diff --git a/packages/aws-rfdk/docs/upgrade/upgrading-0.38.md b/packages/aws-rfdk/docs/upgrade/upgrading-0.38.md index 57c302f67..0a6f12ddc 100644 --- a/packages/aws-rfdk/docs/upgrade/upgrading-0.38.md +++ b/packages/aws-rfdk/docs/upgrade/upgrading-0.38.md @@ -38,7 +38,7 @@ The below example code snippets demonstrate what each case above may look like:
Typescript (click to expand) ```ts -import { ApplicationProtocol } from '@aws-cdk/aws-elasticloadbalancingv2'; +import { ApplicationProtocol } from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import { RenderQueue } from 'aws-rfdk/deadline'; new RenderQueue(this, 'RenderQueue', { diff --git a/packages/aws-rfdk/lib/core/lib/cloudwatch-agent.ts b/packages/aws-rfdk/lib/core/lib/cloudwatch-agent.ts index aa7c69ef9..b41d5fb2a 100644 --- a/packages/aws-rfdk/lib/core/lib/cloudwatch-agent.ts +++ b/packages/aws-rfdk/lib/core/lib/cloudwatch-agent.ts @@ -5,10 +5,11 @@ import * as path from 'path'; -import { IGrantable } from '@aws-cdk/aws-iam'; -import { Bucket } from '@aws-cdk/aws-s3'; -import { StringParameter } from '@aws-cdk/aws-ssm'; -import { Construct, Stack } from '@aws-cdk/core'; +import { Stack } from 'aws-cdk-lib'; +import { IGrantable } from 'aws-cdk-lib/aws-iam'; +import { Bucket } from 'aws-cdk-lib/aws-s3'; +import { StringParameter } from 'aws-cdk-lib/aws-ssm'; +import { Construct } from 'constructs'; import { IScriptHost, ScriptAsset } from './script-assets'; diff --git a/packages/aws-rfdk/lib/core/lib/cloudwatch-config-builder.ts b/packages/aws-rfdk/lib/core/lib/cloudwatch-config-builder.ts index 5f84c2b83..fbb18ca01 100644 --- a/packages/aws-rfdk/lib/core/lib/cloudwatch-config-builder.ts +++ b/packages/aws-rfdk/lib/core/lib/cloudwatch-config-builder.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {Duration} from '@aws-cdk/core'; +import {Duration} from 'aws-cdk-lib'; /** * Enum to describe the time zone property diff --git a/packages/aws-rfdk/lib/core/lib/deployment-instance.ts b/packages/aws-rfdk/lib/core/lib/deployment-instance.ts index 8dec37fdd..1ae8f4fac 100644 --- a/packages/aws-rfdk/lib/core/lib/deployment-instance.ts +++ b/packages/aws-rfdk/lib/core/lib/deployment-instance.ts @@ -3,11 +3,17 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { + Duration, + Names, + Stack, + Tags, +} from 'aws-cdk-lib'; import { AutoScalingGroup, Signals, UpdatePolicy, -} from '@aws-cdk/aws-autoscaling'; +} from 'aws-cdk-lib/aws-autoscaling'; import { AmazonLinuxGeneration, Connections, @@ -21,17 +27,11 @@ import { MachineImage, SubnetSelection, SubnetType, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { PolicyStatement, -} from '@aws-cdk/aws-iam'; -import { - Construct, - Duration, - Names, - Stack, - Tags, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-iam'; +import { Construct } from 'constructs'; import { CloudWatchConfigBuilder, diff --git a/packages/aws-rfdk/lib/core/lib/endpoint.ts b/packages/aws-rfdk/lib/core/lib/endpoint.ts index 708836f69..c23255c65 100644 --- a/packages/aws-rfdk/lib/core/lib/endpoint.ts +++ b/packages/aws-rfdk/lib/core/lib/endpoint.ts @@ -3,14 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { Token } from 'aws-cdk-lib'; import { Connections, IConnectable, Port, Protocol, -} from '@aws-cdk/aws-ec2'; -import { ApplicationProtocol } from '@aws-cdk/aws-elasticloadbalancingv2'; -import { Token } from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; +import { ApplicationProtocol } from 'aws-cdk-lib/aws-elasticloadbalancingv2'; /** * Properties for constructing an {@link Endpoint} diff --git a/packages/aws-rfdk/lib/core/lib/exporting-log-group.ts b/packages/aws-rfdk/lib/core/lib/exporting-log-group.ts index 009e1f6d7..e3e3e1c24 100644 --- a/packages/aws-rfdk/lib/core/lib/exporting-log-group.ts +++ b/packages/aws-rfdk/lib/core/lib/exporting-log-group.ts @@ -4,26 +4,27 @@ */ import * as path from 'path'; -import { Alarm } from '@aws-cdk/aws-cloudwatch'; +import { Duration } from 'aws-cdk-lib'; +import { Alarm } from 'aws-cdk-lib/aws-cloudwatch'; import { Rule, RuleTargetInput, Schedule, -} from '@aws-cdk/aws-events'; -import { LambdaFunction } from '@aws-cdk/aws-events-targets'; -import { Effect, PolicyStatement } from '@aws-cdk/aws-iam'; +} from 'aws-cdk-lib/aws-events'; +import { LambdaFunction } from 'aws-cdk-lib/aws-events-targets'; +import { Effect, PolicyStatement } from 'aws-cdk-lib/aws-iam'; import { Code, Runtime, SingletonFunction, -} from '@aws-cdk/aws-lambda'; +} from 'aws-cdk-lib/aws-lambda'; import { ILogGroup, LogGroup, LogRetention, RetentionDays, -} from '@aws-cdk/aws-logs'; -import { Construct, Duration } from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-logs'; +import { Construct } from 'constructs'; /** * Properties for setting up an {@link ExportingLogGroup}. diff --git a/packages/aws-rfdk/lib/core/lib/health-monitor.ts b/packages/aws-rfdk/lib/core/lib/health-monitor.ts index 28be0dddb..1a7bb8530 100644 --- a/packages/aws-rfdk/lib/core/lib/health-monitor.ts +++ b/packages/aws-rfdk/lib/core/lib/health-monitor.ts @@ -4,38 +4,37 @@ */ import * as path from 'path'; +import { + Duration, + Names, + RemovalPolicy, +} from 'aws-cdk-lib'; import { ComparisonOperator, IAlarmAction, IMetric, MathExpression, TreatMissingData, -} from '@aws-cdk/aws-cloudwatch'; -import {SnsAction} from '@aws-cdk/aws-cloudwatch-actions'; +} from 'aws-cdk-lib/aws-cloudwatch'; +import {SnsAction} from 'aws-cdk-lib/aws-cloudwatch-actions'; import { IConnectable, ISecurityGroup, IVpc, Port, SubnetSelection, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { ApplicationLoadBalancer, ApplicationTargetGroup, IApplicationLoadBalancerTarget, -} from '@aws-cdk/aws-elasticloadbalancingv2'; -import {IPolicy, IRole, Policy, ServicePrincipal} from '@aws-cdk/aws-iam'; -import {IKey, Key} from '@aws-cdk/aws-kms'; -import {Code, Runtime, SingletonFunction} from '@aws-cdk/aws-lambda'; -import {ITopic, Topic} from '@aws-cdk/aws-sns'; -import {LambdaSubscription} from '@aws-cdk/aws-sns-subscriptions'; -import { - Construct, - Duration, - IConstruct, - Names, - RemovalPolicy, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-elasticloadbalancingv2'; +import {IPolicy, IRole, Policy, ServicePrincipal} from 'aws-cdk-lib/aws-iam'; +import {IKey, Key} from 'aws-cdk-lib/aws-kms'; +import {Code, Runtime, SingletonFunction} from 'aws-cdk-lib/aws-lambda'; +import {ITopic, Topic} from 'aws-cdk-lib/aws-sns'; +import {LambdaSubscription} from 'aws-cdk-lib/aws-sns-subscriptions'; +import { Construct, IConstruct } from 'constructs'; import {LoadBalancerFactory} from './load-balancer-manager'; import {tagConstruct} from './runtime-info'; @@ -378,7 +377,6 @@ export class HealthMonitor extends HealthMonitorBase { description: `This key is used to encrypt SNS messages for ${Names.uniqueId(this)}.`, enableKeyRotation: true, removalPolicy: RemovalPolicy.DESTROY, - trustAccountIdentities: true, }); // allow cloudwatch service to send encrypted messages diff --git a/packages/aws-rfdk/lib/core/lib/imported-acm-certificate.ts b/packages/aws-rfdk/lib/core/lib/imported-acm-certificate.ts index 1ead92770..e52ef8fe3 100644 --- a/packages/aws-rfdk/lib/core/lib/imported-acm-certificate.ts +++ b/packages/aws-rfdk/lib/core/lib/imported-acm-certificate.ts @@ -6,40 +6,40 @@ import * as crypto from 'crypto'; import { join } from 'path'; +import { + CustomResource, + Duration, + Names, + RemovalPolicy, + ResourceEnvironment, + Stack, + Tag, + Token, +} from 'aws-cdk-lib'; import { Certificate, ICertificate, -} from '@aws-cdk/aws-certificatemanager'; +} from 'aws-cdk-lib/aws-certificatemanager'; import { Metric, MetricOptions, -} from '@aws-cdk/aws-cloudwatch'; +} from 'aws-cdk-lib/aws-cloudwatch'; import { AttributeType, BillingMode, Table, TableEncryption, -} from '@aws-cdk/aws-dynamodb'; -import { PolicyStatement } from '@aws-cdk/aws-iam'; -import { IKey } from '@aws-cdk/aws-kms'; +} from 'aws-cdk-lib/aws-dynamodb'; +import { PolicyStatement } from 'aws-cdk-lib/aws-iam'; +import { IKey } from 'aws-cdk-lib/aws-kms'; import { Code, LayerVersion, Runtime, SingletonFunction, -} from '@aws-cdk/aws-lambda'; -import { ISecret } from '@aws-cdk/aws-secretsmanager'; -import { - Construct, - CustomResource, - Duration, - Names, - RemovalPolicy, - ResourceEnvironment, - Stack, - Tag, - Token, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-lambda'; +import { ISecret } from 'aws-cdk-lib/aws-secretsmanager'; +import { Construct } from 'constructs'; import { ARNS } from '../../lambdas/lambdaLayerVersionArns'; import { IAcmImportCertProps } from '../../lambdas/nodejs/x509-certificate'; diff --git a/packages/aws-rfdk/lib/core/lib/load-balancer-manager.ts b/packages/aws-rfdk/lib/core/lib/load-balancer-manager.ts index 74c3f7242..ae69875ec 100644 --- a/packages/aws-rfdk/lib/core/lib/load-balancer-manager.ts +++ b/packages/aws-rfdk/lib/core/lib/load-balancer-manager.ts @@ -3,15 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {IVpc} from '@aws-cdk/aws-ec2'; +import {IVpc} from 'aws-cdk-lib/aws-ec2'; import { ApplicationListener, ApplicationLoadBalancer, ApplicationProtocol, ApplicationTargetGroup, Protocol, -} from '@aws-cdk/aws-elasticloadbalancingv2'; -import {Construct} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-elasticloadbalancingv2'; +import { Construct } from 'constructs'; import { HealthCheckConfig, HealthMonitor, diff --git a/packages/aws-rfdk/lib/core/lib/log-group-factory.ts b/packages/aws-rfdk/lib/core/lib/log-group-factory.ts index d955d9951..1d0c418ee 100644 --- a/packages/aws-rfdk/lib/core/lib/log-group-factory.ts +++ b/packages/aws-rfdk/lib/core/lib/log-group-factory.ts @@ -8,8 +8,8 @@ import { LogGroup, LogRetention, RetentionDays, -} from '@aws-cdk/aws-logs'; -import { Construct } from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-logs'; +import { Construct } from 'constructs'; import { ExportingLogGroup } from './exporting-log-group'; /** diff --git a/packages/aws-rfdk/lib/core/lib/mongodb-installer.ts b/packages/aws-rfdk/lib/core/lib/mongodb-installer.ts index 3584a7f08..c9889e906 100644 --- a/packages/aws-rfdk/lib/core/lib/mongodb-installer.ts +++ b/packages/aws-rfdk/lib/core/lib/mongodb-installer.ts @@ -5,16 +5,16 @@ import * as path from 'path'; +import { + Stack, +} from 'aws-cdk-lib'; import { OperatingSystemType, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { Asset, -} from '@aws-cdk/aws-s3-assets'; -import { - Construct, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-s3-assets'; +import { Construct } from 'constructs'; import { IScriptHost, diff --git a/packages/aws-rfdk/lib/core/lib/mongodb-instance.ts b/packages/aws-rfdk/lib/core/lib/mongodb-instance.ts index a8fe986ec..f44f95465 100644 --- a/packages/aws-rfdk/lib/core/lib/mongodb-instance.ts +++ b/packages/aws-rfdk/lib/core/lib/mongodb-instance.ts @@ -5,9 +5,14 @@ import * as path from 'path'; +import { + Duration, + Names, + Size, +} from 'aws-cdk-lib'; import { BlockDeviceVolume, -} from '@aws-cdk/aws-autoscaling'; +} from 'aws-cdk-lib/aws-autoscaling'; import { AmazonLinuxGeneration, Connections, @@ -20,34 +25,28 @@ import { SubnetSelection, UserData, Volume, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { IGrantable, IPrincipal, IRole, -} from '@aws-cdk/aws-iam'; +} from 'aws-cdk-lib/aws-iam'; import { IKey, -} from '@aws-cdk/aws-kms'; +} from 'aws-cdk-lib/aws-kms'; import { ARecord, IPrivateHostedZone, RecordTarget, -} from '@aws-cdk/aws-route53'; +} from 'aws-cdk-lib/aws-route53'; import { Asset, -} from '@aws-cdk/aws-s3-assets'; +} from 'aws-cdk-lib/aws-s3-assets'; import { ISecret, Secret, -} from '@aws-cdk/aws-secretsmanager'; -import { - Construct, - Duration, - IConstruct, - Names, - Size, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-secretsmanager'; +import { Construct, IConstruct } from 'constructs'; import { BlockVolumeFormat, @@ -607,7 +606,7 @@ export class MongoDbInstance extends Construct implements IMongoDb, IGrantable { instance.userData.addOnExitCommands( // Clean up the temporary RAM filesystem - 'test "${MONGO_SETUP_DIR} != "" && sudo umount "${MONGO_SETUP_DIR}', + 'test "${MONGO_SETUP_DIR}" != "" && sudo umount "${MONGO_SETUP_DIR}"', ); } diff --git a/packages/aws-rfdk/lib/core/lib/mongodb-post-install.ts b/packages/aws-rfdk/lib/core/lib/mongodb-post-install.ts index bb5284e54..7b09925b8 100644 --- a/packages/aws-rfdk/lib/core/lib/mongodb-post-install.ts +++ b/packages/aws-rfdk/lib/core/lib/mongodb-post-install.ts @@ -5,31 +5,31 @@ import * as path from 'path'; +import { + CustomResource, + Duration, + Names, + Stack, +} from 'aws-cdk-lib'; import { IVpc, Port, SubnetSelection, SubnetType, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { Code, Function as LambdaFunction, LayerVersion, Runtime, -} from '@aws-cdk/aws-lambda'; +} from 'aws-cdk-lib/aws-lambda'; import { RetentionDays, -} from '@aws-cdk/aws-logs'; +} from 'aws-cdk-lib/aws-logs'; import { ISecret, -} from '@aws-cdk/aws-secretsmanager'; -import { - Construct, - CustomResource, - Duration, - Names, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-secretsmanager'; +import { Construct } from 'constructs'; import { IMongoDb, diff --git a/packages/aws-rfdk/lib/core/lib/mountable-ebs.ts b/packages/aws-rfdk/lib/core/lib/mountable-ebs.ts index 52b5b0970..101fdf1a0 100644 --- a/packages/aws-rfdk/lib/core/lib/mountable-ebs.ts +++ b/packages/aws-rfdk/lib/core/lib/mountable-ebs.ts @@ -5,22 +5,21 @@ import * as path from 'path'; +import { + Stack, +} from 'aws-cdk-lib'; import { IVolume, OperatingSystemType, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { Effect, PolicyStatement, -} from '@aws-cdk/aws-iam'; +} from 'aws-cdk-lib/aws-iam'; import { Asset, -} from '@aws-cdk/aws-s3-assets'; -import { - Construct, - IConstruct, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-s3-assets'; +import { Construct, IConstruct } from 'constructs'; import { MountPermissionsHelper, diff --git a/packages/aws-rfdk/lib/core/lib/mountable-efs.ts b/packages/aws-rfdk/lib/core/lib/mountable-efs.ts index 85c6402dc..e3e573a0e 100644 --- a/packages/aws-rfdk/lib/core/lib/mountable-efs.ts +++ b/packages/aws-rfdk/lib/core/lib/mountable-efs.ts @@ -5,24 +5,23 @@ import * as path from 'path'; +import { + IResolvable, + Stack, + isResolvableObject, +} from 'aws-cdk-lib'; import { OperatingSystemType, Port, -} from '@aws-cdk/aws-ec2'; -import * as efs from '@aws-cdk/aws-efs'; +} from 'aws-cdk-lib/aws-ec2'; +import * as efs from 'aws-cdk-lib/aws-efs'; import { PolicyStatement, -} from '@aws-cdk/aws-iam'; +} from 'aws-cdk-lib/aws-iam'; import { Asset, -} from '@aws-cdk/aws-s3-assets'; -import { - Construct, - IConstruct, - IResolvable, - Stack, - isResolvableObject, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-s3-assets'; +import { Construct, IConstruct } from 'constructs'; import { MountPermissionsHelper, diff --git a/packages/aws-rfdk/lib/core/lib/mountable-filesystem.ts b/packages/aws-rfdk/lib/core/lib/mountable-filesystem.ts index b491d2ae0..062cc1c20 100644 --- a/packages/aws-rfdk/lib/core/lib/mountable-filesystem.ts +++ b/packages/aws-rfdk/lib/core/lib/mountable-filesystem.ts @@ -5,10 +5,8 @@ import { IConnectable, -} from '@aws-cdk/aws-ec2'; -import { - IConstruct, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; +import { IConstruct } from 'constructs'; import { IScriptHost } from './script-assets'; diff --git a/packages/aws-rfdk/lib/core/lib/mountable-fsx-lustre.ts b/packages/aws-rfdk/lib/core/lib/mountable-fsx-lustre.ts index 8dd3d4ef2..e750949f9 100644 --- a/packages/aws-rfdk/lib/core/lib/mountable-fsx-lustre.ts +++ b/packages/aws-rfdk/lib/core/lib/mountable-fsx-lustre.ts @@ -4,21 +4,20 @@ */ import * as path from 'path'; +import { + Stack, +} from 'aws-cdk-lib'; import { OperatingSystemType, Port, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { LustreFileSystem, -} from '@aws-cdk/aws-fsx'; +} from 'aws-cdk-lib/aws-fsx'; import { Asset, -} from '@aws-cdk/aws-s3-assets'; -import { - Construct, - IConstruct, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-s3-assets'; +import { Construct, IConstruct } from 'constructs'; import { MountPermissionsHelper, } from './mount-permissions-helper'; diff --git a/packages/aws-rfdk/lib/core/lib/pad-efs-storage.ts b/packages/aws-rfdk/lib/core/lib/pad-efs-storage.ts index c125f413f..7b9148c4d 100644 --- a/packages/aws-rfdk/lib/core/lib/pad-efs-storage.ts +++ b/packages/aws-rfdk/lib/core/lib/pad-efs-storage.ts @@ -4,25 +4,32 @@ */ import * as path from 'path'; +import { + Annotations, + Duration, + Size, + SizeRoundingBehavior, + Stack, +} from 'aws-cdk-lib'; import { ISecurityGroup, IVpc, SecurityGroup, SubnetSelection, SubnetType, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { IAccessPoint, -} from '@aws-cdk/aws-efs'; +} from 'aws-cdk-lib/aws-efs'; import { Code, FileSystem as LambdaFilesystem, Function as LambdaFunction, Runtime, -} from '@aws-cdk/aws-lambda'; +} from 'aws-cdk-lib/aws-lambda'; import { RetentionDays, -} from '@aws-cdk/aws-logs'; +} from 'aws-cdk-lib/aws-logs'; import { Choice, Condition, @@ -30,24 +37,17 @@ import { InputType, StateMachine, Succeed, -}from '@aws-cdk/aws-stepfunctions'; +}from 'aws-cdk-lib/aws-stepfunctions'; import { LambdaInvoke, -} from '@aws-cdk/aws-stepfunctions-tasks'; -import { - Annotations, - Construct, - Duration, - Size, - SizeRoundingBehavior, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-stepfunctions-tasks'; import { AwsSdkCall, AwsCustomResource, AwsCustomResourcePolicy, PhysicalResourceId, -} from '@aws-cdk/custom-resources'; +} from 'aws-cdk-lib/custom-resources'; +import { Construct } from 'constructs'; import { tagConstruct, } from './runtime-info'; diff --git a/packages/aws-rfdk/lib/core/lib/runtime-info.ts b/packages/aws-rfdk/lib/core/lib/runtime-info.ts index d1e80df79..9d8aee009 100644 --- a/packages/aws-rfdk/lib/core/lib/runtime-info.ts +++ b/packages/aws-rfdk/lib/core/lib/runtime-info.ts @@ -6,9 +6,9 @@ import * as path from 'path'; import { - Construct, Tags, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib'; +import { Construct } from 'constructs'; /** * The name of the tag used to associate the RFDK version and construct that deploys a given resources. diff --git a/packages/aws-rfdk/lib/core/lib/script-assets.ts b/packages/aws-rfdk/lib/core/lib/script-assets.ts index f6dbce28a..9c019ccf5 100644 --- a/packages/aws-rfdk/lib/core/lib/script-assets.ts +++ b/packages/aws-rfdk/lib/core/lib/script-assets.ts @@ -5,10 +5,10 @@ import * as path from 'path'; -import { OperatingSystemType, UserData } from '@aws-cdk/aws-ec2'; -import { IGrantable } from '@aws-cdk/aws-iam'; -import { Asset, AssetProps } from '@aws-cdk/aws-s3-assets'; -import { Construct } from '@aws-cdk/core'; +import { OperatingSystemType, UserData } from 'aws-cdk-lib/aws-ec2'; +import { IGrantable } from 'aws-cdk-lib/aws-iam'; +import { Asset, AssetProps } from 'aws-cdk-lib/aws-s3-assets'; +import { Construct } from 'constructs'; enum ScriptExtension { '.sh' = OperatingSystemType.LINUX, diff --git a/packages/aws-rfdk/lib/core/lib/session-manager-helper.ts b/packages/aws-rfdk/lib/core/lib/session-manager-helper.ts index 05fd2ed13..fa2e2289e 100644 --- a/packages/aws-rfdk/lib/core/lib/session-manager-helper.ts +++ b/packages/aws-rfdk/lib/core/lib/session-manager-helper.ts @@ -6,7 +6,7 @@ import { IGrantable, PolicyStatement, -} from '@aws-cdk/aws-iam'; +} from 'aws-cdk-lib/aws-iam'; /** * This is a helper class meant to make it easier to use the AWS Systems Manager Session Manager diff --git a/packages/aws-rfdk/lib/core/lib/staticip-server.ts b/packages/aws-rfdk/lib/core/lib/staticip-server.ts index e2f314fbf..0edefbd69 100644 --- a/packages/aws-rfdk/lib/core/lib/staticip-server.ts +++ b/packages/aws-rfdk/lib/core/lib/staticip-server.ts @@ -4,13 +4,22 @@ */ import * as path from 'path'; +import { + CfnResource, + Duration, + Lazy, + Names, + Stack, + Tags, +} from 'aws-cdk-lib'; import { AutoScalingGroup, BlockDevice, CfnAutoScalingGroup, DefaultResult, LifecycleTransition, -} from '@aws-cdk/aws-autoscaling'; + Signals, +} from 'aws-cdk-lib/aws-autoscaling'; import { CfnNetworkInterface, Connections, @@ -22,7 +31,7 @@ import { OperatingSystemType, SubnetSelection, UserData, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { Effect, IGrantable, @@ -31,30 +40,22 @@ import { PolicyStatement, Role, ServicePrincipal, -} from '@aws-cdk/aws-iam'; +} from 'aws-cdk-lib/aws-iam'; import { Code, Function as LambdaFunction, Runtime, -} from '@aws-cdk/aws-lambda'; +} from 'aws-cdk-lib/aws-lambda'; import { RetentionDays, -} from '@aws-cdk/aws-logs'; +} from 'aws-cdk-lib/aws-logs'; import { Topic, -} from '@aws-cdk/aws-sns'; +} from 'aws-cdk-lib/aws-sns'; import { LambdaSubscription, -} from '@aws-cdk/aws-sns-subscriptions'; -import { - CfnResource, - Construct, - Duration, - Lazy, - Names, - Stack, - Tags, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-sns-subscriptions'; +import { Construct } from 'constructs'; /** @@ -241,8 +242,7 @@ export class StaticPrivateIpServer extends Construct implements IConnectable, IG vpcSubnets: { subnets: [subnet] }, blockDevices: props.blockDevices, keyName: props.keyName, - resourceSignalCount: props.resourceSignalTimeout ? 1 : undefined, - resourceSignalTimeout: props.resourceSignalTimeout, + signals: props.resourceSignalTimeout ? Signals.waitForCount(1, { timeout: props.resourceSignalTimeout }) : undefined, role: props.role, securityGroup: props.securityGroup, userData: props.userData, diff --git a/packages/aws-rfdk/lib/core/lib/x509-certificate.ts b/packages/aws-rfdk/lib/core/lib/x509-certificate.ts index 3406a7789..42102f618 100644 --- a/packages/aws-rfdk/lib/core/lib/x509-certificate.ts +++ b/packages/aws-rfdk/lib/core/lib/x509-certificate.ts @@ -6,38 +6,37 @@ import * as crypto from 'crypto'; import { join } from 'path'; +import { + Annotations, + CustomResource, + Duration, + Names, + RemovalPolicy, + Stack, + Tag, + Token, +} from 'aws-cdk-lib'; import { AttributeType, BillingMode, Table, TableEncryption, -} from '@aws-cdk/aws-dynamodb'; +} from 'aws-cdk-lib/aws-dynamodb'; import { Grant, IGrantable, PolicyStatement, -} from '@aws-cdk/aws-iam'; -import { IKey } from '@aws-cdk/aws-kms'; +} from 'aws-cdk-lib/aws-iam'; +import { IKey } from 'aws-cdk-lib/aws-kms'; import { Code, Function as LambdaFunction, LayerVersion, Runtime, -} from '@aws-cdk/aws-lambda'; -import { RetentionDays } from '@aws-cdk/aws-logs'; -import { ISecret, Secret } from '@aws-cdk/aws-secretsmanager'; -import { - Annotations, - Construct, - CustomResource, - Duration, - IConstruct, - Names, - RemovalPolicy, - Stack, - Tag, - Token, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-lambda'; +import { RetentionDays } from 'aws-cdk-lib/aws-logs'; +import { ISecret, Secret } from 'aws-cdk-lib/aws-secretsmanager'; +import { Construct, IConstruct } from 'constructs'; import { ARNS } from '../../lambdas/lambdaLayerVersionArns'; import { IX509CertificateEncodePkcs12, IX509CertificateGenerate } from '../../lambdas/nodejs/x509-certificate'; diff --git a/packages/aws-rfdk/lib/core/test/asset-constants.ts b/packages/aws-rfdk/lib/core/test/asset-constants.ts index 5627b269a..5a5127398 100644 --- a/packages/aws-rfdk/lib/core/test/asset-constants.ts +++ b/packages/aws-rfdk/lib/core/test/asset-constants.ts @@ -3,25 +3,40 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { stringLike } from '@aws-cdk/assert'; - // ConfigureCloudWatchAgent.sh export const CWA_ASSET_LINUX = { - Bucket: 'AssetParametersf3261b0f6923b012a8fce5cd6984211bc48b9977844b3fa44229234dc6f21d43S3BucketCC60E56A', - Key: 'AssetParametersf3261b0f6923b012a8fce5cd6984211bc48b9977844b3fa44229234dc6f21d43S3VersionKey027288B6', + Bucket: 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}', + Key: 'f3261b0f6923b012a8fce5cd6984211bc48b9977844b3fa44229234dc6f21d43', }; // ConfigureCloudWatchAgent.ps1 export const CWA_ASSET_WINDOWS = { - Bucket: 'AssetParametersb3a03a74afa8a045b35e08f11a719544622172869cc031787f580407d665ee36S3BucketE3A6D532', - Key: 'AssetParametersb3a03a74afa8a045b35e08f11a719544622172869cc031787f580407d665ee36S3VersionKey0A26AF8C', + Bucket: 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}', + Key: 'b3a03a74afa8a045b35e08f11a719544622172869cc031787f580407d665ee36', }; // mountEbsBlockVolume.sh + metadataUtilities.sh + ec2-certificates.crt export const MOUNT_EBS_SCRIPT_LINUX = { - Bucket: stringLike('AssetParameters*S3BucketD97C6FDA'), + Bucket: 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}', + Key: '11325bc3262f331157129ec344f0be7fae82e28e86cab0cef04c47b428cd8ef5', +}; + +export const MOUNT_EFS_SCRIPT_LINUX = { + Bucket: 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}', + Key: 'df4591e2346578a80738105aa20aab9c8cee38098d62b4b9a595681c14b8e716', +}; + +export const MOUNT_FSX_SCRIPT_LINUX = { + Bucket: 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}', + Key: '9afc7cd192aacbc562e018fb8f9c3848df6a247d43d2486ee91c0ded179e2774', }; export const INSTALL_MONGODB_3_6_SCRIPT_LINUX = { - Bucket: stringLike('AssetParameters*S3BucketAF54A815'), + Bucket: 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}', + Key: '80faba664ebb899d63d89c8fcea1d867475d1ddd28159f418b42af81197849e1', +}; + +export const MONGODB_3_6_CONFIGURATION_SCRIPTS = { + Bucket: 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}', + Key: '433ead41839a7d4dad68bf0149f907050caa6d95bb7b5b180e5ff21a5dad3c19', }; diff --git a/packages/aws-rfdk/lib/core/test/cloudwatch-agent.test.ts b/packages/aws-rfdk/lib/core/test/cloudwatch-agent.test.ts index 746e1ece6..4c2764815 100644 --- a/packages/aws-rfdk/lib/core/test/cloudwatch-agent.test.ts +++ b/packages/aws-rfdk/lib/core/test/cloudwatch-agent.test.ts @@ -3,11 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {Stack} from 'aws-cdk-lib'; import { - expect as expectCDK, - haveResource, - haveResourceLike, -} from '@aws-cdk/assert'; + Template, +} from 'aws-cdk-lib/assertions'; import { AmazonLinuxGeneration, AmazonLinuxImage, @@ -18,8 +17,7 @@ import { Vpc, WindowsImage, WindowsVersion, -} from '@aws-cdk/aws-ec2'; -import {Stack} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; import { CloudWatchAgent, CloudWatchConfigBuilder, @@ -60,32 +58,10 @@ describe('CloudWatchAgent', () => { }); // THEN - expectCDK(stack).to(haveResource('AWS::SSM::Parameter', { + Template.fromStack(stack).hasResourceProperties('AWS::SSM::Parameter', { Type: 'String', Value: cloudWatchConfig, - })); - }); - - test('creates an asset', () => { - // GIVEN - const host = new Instance(stack, 'Instance', { - instanceType: InstanceType.of(InstanceClass.T2, InstanceSize.LARGE), - machineImage: new AmazonLinuxImage({ - generation: AmazonLinuxGeneration.AMAZON_LINUX_2, - }), - vpc, }); - - // WHEN - new CloudWatchAgent(stack, 'testResource', { - cloudWatchConfig, - host, - }); - - // THEN - // Find an asset created by the CloudWatchAgentConfigResource - const asset = stack.node.metadataEntry.find(m => m.type === 'aws:cdk:asset'); - expect(asset).toBeDefined(); }); test('creates an IAM policy to access the SSM parameter, CDK asset bucket, and CloudWatch agent bucket', () => { @@ -105,7 +81,7 @@ describe('CloudWatchAgent', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -123,7 +99,7 @@ describe('CloudWatchAgent', () => { 'arn:', { Ref: 'AWS::Partition' }, ':s3:::', - { Ref: CWA_ASSET_LINUX.Bucket }, + { 'Fn::Sub': CWA_ASSET_LINUX.Bucket }, ], ], }, @@ -134,7 +110,7 @@ describe('CloudWatchAgent', () => { 'arn:', { Ref: 'AWS::Partition' }, ':s3:::', - { Ref: CWA_ASSET_LINUX.Bucket }, + { 'Fn::Sub': CWA_ASSET_LINUX.Bucket }, '/*', ], ], @@ -228,13 +204,13 @@ describe('CloudWatchAgent', () => { }, PolicyName: 'InstanceInstanceRoleDefaultPolicy4ACE9290', Roles: [ { Ref: 'InstanceInstanceRoleE9785DE5' } ], - })); + }); }); test.each([ - ["' -i ", undefined], - ["' -i ", true], - ["' ", false], + [' -i', undefined], + [' -i', true], + ['', false], ])('adds user data commands to fetch and execute the script (linux). installFlag: %s shouldInstallAgent: %p', (installFlag: string, shouldInstallAgent?: boolean) => { // GIVEN const host = new Instance(stack, 'Instance', { @@ -258,124 +234,9 @@ describe('CloudWatchAgent', () => { 'Fn::Join': [ '', [ - "#!/bin/bash\nmkdir -p $(dirname '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - "')\naws s3 cp 's3://", - { Ref: CWA_ASSET_LINUX.Bucket }, - '/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - "' '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - "'\nset -e\nchmod +x '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - "'\n'/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - installFlag, + `#!/bin/bash\nmkdir -p $(dirname '/tmp/${CWA_ASSET_LINUX.Key}.sh')\naws s3 cp 's3://`, + { 'Fn::Sub': CWA_ASSET_LINUX.Bucket }, + `/${CWA_ASSET_LINUX.Key}.sh' '/tmp/${CWA_ASSET_LINUX.Key}.sh'\nset -e\nchmod +x '/tmp/${CWA_ASSET_LINUX.Key}.sh'\n'/tmp/${CWA_ASSET_LINUX.Key}.sh'${installFlag} `, { Ref: 'AWS::Region' }, ' ', { Ref: 'StringParameter472EED0E' }, @@ -385,9 +246,9 @@ describe('CloudWatchAgent', () => { }); test.each([ - ["' -i ", undefined], - ["' -i ", true], - ["' ", false], + [' -i', undefined], + [' -i', true], + ['', false], ])('adds user data commands to fetch and execute the script (windows). installFlag: %s shouldInstallAgent: %p', (installFlag: string, shouldInstallAgent?: boolean) => { // GIVEN const host = new Instance(stack, 'Instance', { @@ -409,128 +270,13 @@ describe('CloudWatchAgent', () => { 'Fn::Join': [ '', [ - "mkdir (Split-Path -Path 'C:/temp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - "' ) -ea 0\nRead-S3Object -BucketName '", - { Ref: CWA_ASSET_WINDOWS.Bucket }, - "' -key '", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - "' -file 'C:/temp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - "' -ErrorAction Stop\n&'C:/temp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - installFlag, + `mkdir (Split-Path -Path 'C:/temp/${CWA_ASSET_WINDOWS.Key}.ps1' ) -ea 0\nRead-S3Object -BucketName '`, + { 'Fn::Sub': CWA_ASSET_WINDOWS.Bucket }, + `' -key '${CWA_ASSET_WINDOWS.Key}.ps1' -file 'C:/temp/${CWA_ASSET_WINDOWS.Key}.ps1' -ErrorAction Stop\n&'C:/temp/${CWA_ASSET_WINDOWS.Key}.ps1'${installFlag} `, { Ref: 'AWS::Region' }, ' ', { Ref: 'StringParameter472EED0E' }, - "\nif (!$?) { Write-Error 'Failed to execute the file \"C:/temp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - "\"' -ErrorAction Stop }", + `\nif (!$?) { Write-Error 'Failed to execute the file \"C:/temp/${CWA_ASSET_WINDOWS.Key}.ps1\"' -ErrorAction Stop }`, ], ], }); diff --git a/packages/aws-rfdk/lib/core/test/cloudwatch-config-builder.ts b/packages/aws-rfdk/lib/core/test/cloudwatch-config-builder.ts index 24f25e2ab..1233dc520 100644 --- a/packages/aws-rfdk/lib/core/test/cloudwatch-config-builder.ts +++ b/packages/aws-rfdk/lib/core/test/cloudwatch-config-builder.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {Duration} from '@aws-cdk/core'; +import {Duration} from 'aws-cdk-lib'; import { CloudWatchConfigBuilder, TimeZone, diff --git a/packages/aws-rfdk/lib/core/test/deployment-instance.test.ts b/packages/aws-rfdk/lib/core/test/deployment-instance.test.ts index d9a1d5739..603281b23 100644 --- a/packages/aws-rfdk/lib/core/test/deployment-instance.test.ts +++ b/packages/aws-rfdk/lib/core/test/deployment-instance.test.ts @@ -3,15 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +import * as cdk from 'aws-cdk-lib'; import { - arrayWith, - countResources, - expect as expectCDK, - haveResourceLike, - ResourcePart, - stringLike, -} from '@aws-cdk/assert'; -import { CfnLaunchConfiguration } from '@aws-cdk/aws-autoscaling'; + Match, + Template, +} from 'aws-cdk-lib/assertions'; +import { CfnLaunchConfiguration } from 'aws-cdk-lib/aws-autoscaling'; import { AmazonLinuxGeneration, AmazonLinuxImage, @@ -21,19 +18,20 @@ import { SecurityGroup, SubnetType, Vpc, -} from '@aws-cdk/aws-ec2'; -import * as iam from '@aws-cdk/aws-iam'; -import { ILogGroup } from '@aws-cdk/aws-logs'; -import { Bucket } from '@aws-cdk/aws-s3'; -import { Asset } from '@aws-cdk/aws-s3-assets'; -import { StringParameter } from '@aws-cdk/aws-ssm'; -import * as cdk from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; +import * as iam from 'aws-cdk-lib/aws-iam'; +import { ILogGroup } from 'aws-cdk-lib/aws-logs'; +import { Bucket } from 'aws-cdk-lib/aws-s3'; +import { Asset } from 'aws-cdk-lib/aws-s3-assets'; +import { StringParameter } from 'aws-cdk-lib/aws-ssm'; +import {Construct} from 'constructs'; import { DeploymentInstance, DeploymentInstanceProps, } from '../lib/deployment-instance'; import { resourceTagMatcher, testConstructTags } from './tag-helpers'; +import { resourcePropertiesCountIs } from './test-helper'; const DEFAULT_CONSTRUCT_ID = 'DeploymentInstance'; @@ -45,7 +43,7 @@ const DEFAULT_CONSTRUCT_ID = 'DeploymentInstance'; * * `.addExecuteFileCommand` */ class AmazonLinuxWithUserDataSpy extends AmazonLinuxImage { - public getImage(scope: cdk.Construct) { + public getImage(scope: Construct) { const result = super.getImage(scope); jest.spyOn(result.userData, 'addOnExitCommands'); jest.spyOn(result.userData, 'addExecuteFileCommand'); @@ -54,23 +52,18 @@ class AmazonLinuxWithUserDataSpy extends AmazonLinuxImage { } describe('DeploymentInstance', () => { - let app: cdk.App; - let depStack: cdk.Stack; - let stack: cdk.Stack; - let vpc: Vpc; - let target: DeploymentInstance; - - beforeAll(() => { - // GIVEN - app = new cdk.App(); - depStack = new cdk.Stack(app, 'DepStack'); - vpc = new Vpc(depStack, 'VPC'); - }); - describe('defaults', () => { + let app: cdk.App; + let depStack: cdk.Stack; + let vpc: Vpc; + let stack: cdk.Stack; + let target: DeploymentInstance; beforeAll(() => { // GIVEN + app = new cdk.App(); + depStack = new cdk.Stack(app, 'DepStack'); + vpc = new Vpc(depStack, 'VPC'); stack = new cdk.Stack(app, 'DefaultsStack'); target = new DeploymentInstance(stack, DEFAULT_CONSTRUCT_ID, { vpc, @@ -83,21 +76,21 @@ describe('DeploymentInstance', () => { // ASG makes these assertions linked test('deploys a single Auto-Scaling Group', () => { // THEN - expectCDK(stack).to(countResources('AWS::AutoScaling::AutoScalingGroup', 1)); + Template.fromStack(stack).resourceCountIs('AWS::AutoScaling::AutoScalingGroup', 1); }); test('MaxSize is 1', () => { // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { MaxSize: '1', - })); + }); }); test('MinSize is 1', () => { // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { MinSize: '1', - })); + }); }); test('uses private subnets', () => { @@ -105,16 +98,16 @@ describe('DeploymentInstance', () => { const privateSubnetIDs = vpc.selectSubnets({ subnetType: SubnetType.PRIVATE_WITH_NAT }).subnetIds; // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { - VPCZoneIdentifier: arrayWith( + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { + VPCZoneIdentifier: Match.arrayWith([ ...stack.resolve(privateSubnetIDs), - ), - })); + ]), + }); }); test('waits 15 minutes for one signal', () => { // THEN - expectCDK(stack).to(haveResourceLike( + Template.fromStack(stack).hasResource( 'AWS::AutoScaling::AutoScalingGroup', { CreationPolicy: { @@ -124,13 +117,12 @@ describe('DeploymentInstance', () => { }, }, }, - ResourcePart.CompleteDefinition, - )); + ); }); test('sets replacing update policy', () => { // THEN - expectCDK(stack).to(haveResourceLike( + Template.fromStack(stack).hasResource( 'AWS::AutoScaling::AutoScalingGroup', { UpdatePolicy: { @@ -142,8 +134,7 @@ describe('DeploymentInstance', () => { }, }, }, - ResourcePart.CompleteDefinition, - )); + ); }); test('uses Launch Configuration', () => { @@ -151,9 +142,9 @@ describe('DeploymentInstance', () => { const launchConfig = target.node.findChild('ASG').node.findChild('LaunchConfig') as CfnLaunchConfiguration; // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { LaunchConfigurationName: stack.resolve(launchConfig.ref), - })); + }); }); }); @@ -163,7 +154,7 @@ describe('DeploymentInstance', () => { // ASG makes these assertions linked test('deploys a single Launch Configuration', () => { // THEN - expectCDK(stack).to(countResources('AWS::AutoScaling::LaunchConfiguration', 1)); + Template.fromStack(stack).resourceCountIs('AWS::AutoScaling::LaunchConfiguration', 1); }); test('uses latest Amazon Linux machine image', () => { @@ -172,16 +163,16 @@ describe('DeploymentInstance', () => { const imageId: { Ref: string } = stack.resolve(amazonLinux.getImage(stack)).imageId; // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { ImageId: imageId, - })); + }); }); test('uses t3.small', () => { // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { InstanceType: 't3.small', - })); + }); }); test('Uses created Security Group', () => { @@ -192,11 +183,11 @@ describe('DeploymentInstance', () => { ) as SecurityGroup; // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { SecurityGroups: [ stack.resolve(securityGroup.securityGroupId), ], - })); + }); }); test('depends on policy', () => { @@ -210,25 +201,24 @@ describe('DeploymentInstance', () => { ) as iam.CfnPolicy; // THEN - expectCDK(stack).to(haveResourceLike( + Template.fromStack(stack).hasResource( 'AWS::AutoScaling::LaunchConfiguration', { - DependsOn: arrayWith( + DependsOn: Match.arrayWith([ stack.resolve(policy.logicalId), - ), + ]), }, - ResourcePart.CompleteDefinition, - )); + ); }); }); describe('Security Group', () => { test('creates Security Group in the desired VPC', () => { // THEN - expectCDK(stack).to(countResources('AWS::EC2::SecurityGroup', 1)); - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroup', { + Template.fromStack(stack).resourceCountIs('AWS::EC2::SecurityGroup', 1); + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { VpcId: stack.resolve(vpc.vpcId), - })); + }); }); }); @@ -247,11 +237,11 @@ describe('DeploymentInstance', () => { test('creates an instance profile', () => { // THEN - expectCDK(stack).to(haveResourceLike('AWS::IAM::InstanceProfile', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::InstanceProfile', { Roles: [ { Ref: stack.getLogicalId(instanceRole) }, ], - })); + }); }); test('creates a role that can be assumed by EC2', () => { @@ -259,7 +249,7 @@ describe('DeploymentInstance', () => { const servicePrincipal = new iam.ServicePrincipal('ec2.amazonaws.com'); // THEN - expectCDK(stack).to(haveResourceLike('AWS::IAM::Role', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { AssumeRolePolicyDocument: { Statement: [ { @@ -271,25 +261,25 @@ describe('DeploymentInstance', () => { }, ], }, - })); + }); }); test('can signal to CloudFormation', () => { // THEN - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: 'cloudformation:SignalResource', Effect: 'Allow', Resource: { Ref: 'AWS::StackId' }, }, - ), + ]), }, Roles: [ stack.resolve(instanceRole.ref), ], - })); + }); }); test('can write to the log group', () => { @@ -297,9 +287,9 @@ describe('DeploymentInstance', () => { const logGroup = target.node.findChild(`${DEFAULT_CONSTRUCT_ID}LogGroup`) as ILogGroup; // THEN - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: [ 'logs:CreateLogStream', @@ -308,12 +298,12 @@ describe('DeploymentInstance', () => { Effect: 'Allow', Resource: stack.resolve(logGroup.logGroupArn), }, - ), + ]), }, Roles: [ stack.resolve(instanceRole.ref), ], - })); + }); }); test('can fetch the CloudWatch Agent install script', () => { @@ -324,9 +314,9 @@ describe('DeploymentInstance', () => { ) as Asset; // THEN - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: [ 's3:GetObject*', @@ -339,12 +329,12 @@ describe('DeploymentInstance', () => { cloudWatchAgentScriptAsset.bucket.arnForObjects('*'), ]), }, - ), + ]), }, Roles: [ stack.resolve(instanceRole.ref), ], - })); + }); }); test('can fetch the CloudWatch Agent configuration file SSM parameter', () => { @@ -355,9 +345,9 @@ describe('DeploymentInstance', () => { ) as StringParameter; // THEN - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: [ 'ssm:DescribeParameters', @@ -368,12 +358,12 @@ describe('DeploymentInstance', () => { Effect: 'Allow', Resource: stack.resolve(cloudWatchConfigSsmParam.parameterArn), }, - ), + ]), }, Roles: [ stack.resolve(instanceRole.ref), ], - })); + }); }); test('can fetch the CloudWatch Agent installer from S3', () => { @@ -381,9 +371,9 @@ describe('DeploymentInstance', () => { const cloudWatchAgentInstallerBucket = Bucket.fromBucketArn(depStack, 'CloudWatchAgentInstallerBucket', `arn:aws:s3:::amazoncloudwatch-agent-${stack.region}` ); // THEN - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: [ 's3:GetObject*', @@ -396,12 +386,12 @@ describe('DeploymentInstance', () => { cloudWatchAgentInstallerBucket.arnForObjects('*'), ]), }, - ), + ]), }, Roles: [ stack.resolve(instanceRole.ref), ], - })); + }); }); test('can fetch GPG installer from RFDK dependencies S3 bucket', () => { @@ -409,9 +399,9 @@ describe('DeploymentInstance', () => { const rfdkExternalDepsBucket = Bucket.fromBucketArn(depStack, 'RfdkExternalDependenciesBucket', `arn:aws:s3:::rfdk-external-dependencies-${stack.region}` ); // THEN - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: [ 's3:GetObject*', @@ -424,19 +414,19 @@ describe('DeploymentInstance', () => { rfdkExternalDepsBucket.arnForObjects('*'), ]), }, - ), + ]), }, Roles: [ stack.resolve(instanceRole.ref), ], - })); + }); }); test('can scale the Auto-Scaling Group', () => { // THEN - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: 'autoscaling:UpdateAutoScalingGroup', Condition: { @@ -453,12 +443,12 @@ describe('DeploymentInstance', () => { Effect: 'Allow', Resource: '*', }, - ), + ]), }, Roles: [ stack.resolve(instanceRole.ref), ], - })); + }); }); }); @@ -468,33 +458,33 @@ describe('DeploymentInstance', () => { const logGroup = target.node.findChild(`${DEFAULT_CONSTRUCT_ID}LogGroup`) as ILogGroup; // THEN - expectCDK(stack).to(haveResourceLike('AWS::SSM::Parameter', { + Template.fromStack(stack).hasResourceProperties('AWS::SSM::Parameter', { Type: 'String', Value: { 'Fn::Join': [ '', - arrayWith( + Match.arrayWith([ '{"logs":{"logs_collected":{"files":{"collect_list":[{"log_group_name":"', stack.resolve(logGroup.logGroupName), - ), + ]), ], }, - })); + }); }); test('configures cloud-init log', () => { // THEN - expectCDK(stack).to(haveResourceLike('AWS::SSM::Parameter', { + Template.fromStack(stack).hasResourceProperties('AWS::SSM::Parameter', { Type: 'String', Value: { 'Fn::Join': [ '', - arrayWith( - stringLike('*"log_stream_name":"cloud-init-output-{instance_id}","file_path":"/var/log/cloud-init-output.log",*'), - ), + Match.arrayWith([ + Match.stringLikeRegexp('.*"log_stream_name":"cloud-init-output-{instance_id}","file_path":"/var/log/cloud-init-output.log",.*'), + ]), ], }, - })); + }); }); }); @@ -520,13 +510,22 @@ describe('DeploymentInstance', () => { const matcher = resourceTagMatcher('AWS::AutoScaling::AutoScalingGroup', 'resourceLogicalId', cdk.Names.uniqueId(target)); // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', matcher)); + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', matcher); }); }); describe('User Data', () => { + let app: cdk.App; + let depStack: cdk.Stack; + let vpc: Vpc; + let stack: cdk.Stack; + let target: DeploymentInstance; + beforeAll(() => { // GIVEN + app = new cdk.App(); + depStack = new cdk.Stack(app, 'DepStack'); + vpc = new Vpc(depStack, 'VPC'); stack = new cdk.Stack(app, 'UserDataStack'); // WHEN @@ -582,6 +581,11 @@ describe('DeploymentInstance', () => { }); describe('Custom::LogRetention.LogGroupName', () => { + let app: cdk.App; + let depStack: cdk.Stack; + let vpc: Vpc; + let stack: cdk.Stack; + beforeEach(() => { // We need a clean construct tree, because the tests use the same construct ID app = new cdk.App(); @@ -634,19 +638,18 @@ describe('DeploymentInstance', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { LogGroupName: expectedLogGroupName, - })); + }); }); }); - // GIVEN test('uses specified instance type', () => { // GIVEN + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'TestStack'); + const vpc = new Vpc(stack, 'VPC'); const instanceType = new InstanceType('c5.large'); - // We want an isolated stack to ensure expectCDK is only searching resources - // synthesized by the specific DeploymentInstance stack - stack = new cdk.Stack(app, 'InstanceTypeStack'); // WHEN new DeploymentInstance(stack, DEFAULT_CONSTRUCT_ID, { @@ -655,16 +658,19 @@ describe('DeploymentInstance', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { InstanceType: instanceType.toString(), - })); + }); }); test('uses specified security group', () => { // GIVEN + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'TestStack'); + const vpc = new Vpc(stack, 'VPC'); + const securityGroupId = 'securityGroupId'; - const securityGroup = SecurityGroup.fromSecurityGroupId(depStack, 'SecurityGroup', securityGroupId); - stack = new cdk.Stack(app, 'SecurityGroupStack'); + const securityGroup = SecurityGroup.fromSecurityGroupId(stack, 'SecurityGroup', securityGroupId); // WHEN new DeploymentInstance(stack, DEFAULT_CONSTRUCT_ID, { @@ -673,17 +679,26 @@ describe('DeploymentInstance', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { - SecurityGroups: arrayWith( + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { + SecurityGroups: Match.arrayWith([ securityGroupId, - ), - })); + ]), + }); }); describe('.selfTermination = false', () => { + let app: cdk.App; + let depStack: cdk.Stack; + let vpc: Vpc; + let stack: cdk.Stack; + let target: DeploymentInstance; + beforeAll(() => { // GIVEN - stack = new cdk.Stack(app, 'SelfTerminationDisabledStack'); + app = new cdk.App(); + depStack = new cdk.Stack(app, 'DepStack'); + vpc = new Vpc(depStack, 'VPC'); + stack = new cdk.Stack(app, 'DefaultsStack'); // Spy on user data method calls const machineImage = new AmazonLinuxWithUserDataSpy(); @@ -712,33 +727,36 @@ describe('DeploymentInstance', () => { .node.findChild('InstanceRole') .node.defaultChild ) as iam.CfnRole; - - // THEN - expectCDK(stack).notTo(haveResourceLike('AWS::IAM::Policy', { - PolicyDocument: { - Statement: arrayWith( - { - Action: 'autoscaling:UpdateAutoScalingGroup', - Condition: { - // This tag is added by RFDK to scope down the permissions of the policy for least-privilege - StringEquals: { 'autoscaling:ResourceTag/resourceLogicalId': cdk.Names.uniqueId(target) }, + const matcher = Match.objectLike({ + Properties: { + PolicyDocument: { + Statement: Match.arrayWith([ + { + Action: 'autoscaling:UpdateAutoScalingGroup', + Condition: { + // This tag is added by RFDK to scope down the permissions of the policy for least-privilege + StringEquals: { 'autoscaling:ResourceTag/resourceLogicalId': cdk.Names.uniqueId(target) }, + }, + Effect: 'Allow', + Resource: '*', }, - Effect: 'Allow', - Resource: '*', - }, - // The instance determines its Auto-Scaling Group by reading the tag created on the instance by the EC2 - // Auto-Scaling service - { - Action: 'ec2:DescribeTags', - Effect: 'Allow', - Resource: '*', - }, - ), + // The instance determines its Auto-Scaling Group by reading the tag created on the instance by the EC2 + // Auto-Scaling service + { + Action: 'ec2:DescribeTags', + Effect: 'Allow', + Resource: '*', + }, + ]), + }, + Roles: [ + stack.resolve(instanceRole.ref), + ], }, - Roles: [ - stack.resolve(instanceRole.ref), - ], - })); + }); + + // THEN + resourcePropertiesCountIs(stack, 'AWS::IAM::Policy', matcher, 0); }); test('does not tag for self-termination', () => { @@ -746,18 +764,24 @@ describe('DeploymentInstance', () => { const matcher = resourceTagMatcher('AWS::AutoScaling::AutoScalingGroup', 'resourceLogicalId', cdk.Names.uniqueId(target)); // THEN - expectCDK(stack).notTo(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', matcher)); + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', Match.not(matcher)); }); }); // GIVEN describe('.executionTimeout is specified', () => { + let app: cdk.App; + let depStack: cdk.Stack; + let vpc: Vpc; + let stack: cdk.Stack; const executionTimeout = cdk.Duration.minutes(30); beforeAll(() => { // GIVEN - // Use a clean stack to not pollute other stacks with resources - stack = new cdk.Stack(app, 'ExecutionTimeout'); + app = new cdk.App(); + depStack = new cdk.Stack(app, 'DepStack'); + vpc = new Vpc(depStack, 'VPC'); + stack = new cdk.Stack(app, 'DefaultsStack'); const deploymentInstanceProps: DeploymentInstanceProps = { vpc, executionTimeout, @@ -769,7 +793,7 @@ describe('DeploymentInstance', () => { // THEN test('AWS::AutoScaling::AutoScalingGroup creation policy signal timeout is set accordingly', () => { - expectCDK(stack).to(haveResourceLike( + Template.fromStack(stack).hasResource( 'AWS::AutoScaling::AutoScalingGroup', { CreationPolicy: { @@ -779,8 +803,7 @@ describe('DeploymentInstance', () => { }, }, }, - ResourcePart.CompleteDefinition, - )); + ); }); }); }); diff --git a/packages/aws-rfdk/lib/core/test/endpoint.test.ts b/packages/aws-rfdk/lib/core/test/endpoint.test.ts index fa5af0314..d19eb2daa 100644 --- a/packages/aws-rfdk/lib/core/test/endpoint.test.ts +++ b/packages/aws-rfdk/lib/core/test/endpoint.test.ts @@ -3,7 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { expect as expectCDK, haveResource } from '@aws-cdk/assert'; +import { + Lazy, + Stack, + Token, +} from 'aws-cdk-lib'; +import { Template } from 'aws-cdk-lib/assertions'; import { Connections, IConnectable, @@ -11,13 +16,8 @@ import { Protocol, SecurityGroup, Vpc, -} from '@aws-cdk/aws-ec2'; -import { ApplicationProtocol } from '@aws-cdk/aws-elasticloadbalancingv2'; -import { - Lazy, - Stack, - Token, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; +import { ApplicationProtocol } from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import { ApplicationEndpoint, @@ -214,7 +214,7 @@ describe('ConnectableApplicationEndpoint', () => { somethingConnectable.connections.allowTo(endpoint, Port.tcp(80), 'Connecting to endpoint'); // THEN - expectCDK(stack).to(haveResource('AWS::EC2::SecurityGroupIngress')); + Template.fromStack(stack).resourceCountIs('AWS::EC2::SecurityGroupIngress', 1); }); }); diff --git a/packages/aws-rfdk/lib/core/test/exporting-log-group.test.ts b/packages/aws-rfdk/lib/core/test/exporting-log-group.test.ts index 9dc599897..58add28d8 100644 --- a/packages/aws-rfdk/lib/core/test/exporting-log-group.test.ts +++ b/packages/aws-rfdk/lib/core/test/exporting-log-group.test.ts @@ -3,10 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { expect as expectCDK, haveResource, haveResourceLike } from '@aws-cdk/assert'; -import { RetentionDays } from '@aws-cdk/aws-logs'; -import { Bucket } from '@aws-cdk/aws-s3'; -import { Stack } from '@aws-cdk/core'; +import { Stack } from 'aws-cdk-lib'; +import { Template } from 'aws-cdk-lib/assertions'; +import { RetentionDays } from 'aws-cdk-lib/aws-logs'; +import { Bucket } from 'aws-cdk-lib/aws-s3'; import { ExportingLogGroup } from '../lib/exporting-log-group'; test('default exporting log group is created correctly', () => { @@ -23,7 +23,7 @@ test('default exporting log group is created correctly', () => { }); // THEN - expectCDK(stack).to(haveResource('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { ServiceToken: { 'Fn::GetAtt': [ 'LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A', @@ -32,8 +32,8 @@ test('default exporting log group is created correctly', () => { }, LogGroupName: 'logGroup', RetentionInDays: 3, - })); - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + }); + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -74,9 +74,9 @@ test('default exporting log group is created correctly', () => { }, ], }, - })); + }); - expectCDK(stack).to(haveResourceLike('AWS::CloudWatch::Alarm', { + Template.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Alarm', { ComparisonOperator: 'GreaterThanOrEqualToThreshold', EvaluationPeriods: 1, Dimensions: [ @@ -92,9 +92,9 @@ test('default exporting log group is created correctly', () => { Period: 300, Statistic: 'Sum', Threshold: 1, - })); + }); - expectCDK(stack).to(haveResourceLike('AWS::Events::Rule', { + Template.fromStack(stack).hasResourceProperties('AWS::Events::Rule', { ScheduleExpression: 'rate(1 hour)', State: 'ENABLED', Targets: [ @@ -120,8 +120,8 @@ test('default exporting log group is created correctly', () => { }, }, ], - })); - expectCDK(stack).to(haveResource('AWS::Lambda::Function')); + }); + Template.fromStack(stack).resourceCountIs('AWS::Lambda::Function', 2); }); test('custom set retention is created correctly', () => { @@ -139,7 +139,7 @@ test('custom set retention is created correctly', () => { }); // THEN - expectCDK(stack).to(haveResource('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { ServiceToken: { 'Fn::GetAtt': [ 'LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A', @@ -148,8 +148,8 @@ test('custom set retention is created correctly', () => { }, LogGroupName: 'logGroup', RetentionInDays: 7, - })); - expectCDK(stack).to(haveResource('AWS::Lambda::Function')); - expectCDK(stack).to(haveResource('AWS::CloudWatch::Alarm')); - expectCDK(stack).to(haveResource('AWS::Events::Rule')); + }); + Template.fromStack(stack).resourceCountIs('AWS::Lambda::Function', 2); + Template.fromStack(stack).resourceCountIs('AWS::CloudWatch::Alarm', 1); + Template.fromStack(stack).resourceCountIs('AWS::Events::Rule', 1); }); diff --git a/packages/aws-rfdk/lib/core/test/health-monitor.test.ts b/packages/aws-rfdk/lib/core/test/health-monitor.test.ts index 769dc6ec3..ca71f3a70 100644 --- a/packages/aws-rfdk/lib/core/test/health-monitor.test.ts +++ b/packages/aws-rfdk/lib/core/test/health-monitor.test.ts @@ -4,26 +4,23 @@ */ import { - arrayWith, - countResources, - countResourcesLike, - deepObjectLike, - expect as expectCDK, - haveResource, - haveResourceLike, - not, - ABSENT, - notMatching, - stringLike, -} from '@aws-cdk/assert'; + App, + CfnElement, + Names, + Stack, +} from 'aws-cdk-lib'; +import { + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { AutoScalingGroup, CfnAutoScalingGroup, -} from '@aws-cdk/aws-autoscaling'; +} from 'aws-cdk-lib/aws-autoscaling'; import { IMetric, Metric, -} from '@aws-cdk/aws-cloudwatch'; +} from 'aws-cdk-lib/aws-cloudwatch'; import { AmazonLinuxGeneration, AmazonLinuxImage, @@ -35,23 +32,17 @@ import { SecurityGroup, SubnetType, Vpc, -} from '@aws-cdk/aws-ec2'; -import {IApplicationLoadBalancerTarget} from '@aws-cdk/aws-elasticloadbalancingv2'; +} from 'aws-cdk-lib/aws-ec2'; +import {IApplicationLoadBalancerTarget} from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import { IPolicy, Policy, PolicyStatement, -} from '@aws-cdk/aws-iam'; +} from 'aws-cdk-lib/aws-iam'; import { Key, -} from '@aws-cdk/aws-kms'; -import { - App, - CfnElement, - Construct, - Names, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-kms'; +import {Construct} from 'constructs'; import { HealthMonitor, @@ -60,6 +51,9 @@ import { import { testConstructTags, } from './tag-helpers'; +import { + resourcePropertiesCountIs, +} from './test-helper'; let app: App; let infraStack: Stack; @@ -130,8 +124,8 @@ describe('HealthMonitor', () => { vpc, }); // THEN - expectCDK(hmStack).notTo(haveResource('AWS::ElasticLoadBalancingV2::LoadBalancer')); - expectCDK(hmStack).to(haveResourceLike('AWS::KMS::Key', { + Template.fromStack(hmStack).resourceCountIs('AWS::ElasticLoadBalancingV2::LoadBalancer', 0); + Template.fromStack(hmStack).hasResourceProperties('AWS::KMS::Key', { KeyPolicy: { Statement: [ { @@ -172,8 +166,8 @@ describe('HealthMonitor', () => { }, Description: `This key is used to encrypt SNS messages for ${Names.uniqueId(healthMonitor)}.`, EnableKeyRotation: true, - })); - expectCDK(hmStack).to(haveResourceLike('AWS::SNS::TopicPolicy', { + }); + Template.fromStack(hmStack).hasResourceProperties('AWS::SNS::TopicPolicy', { PolicyDocument: { Statement: [ { @@ -194,17 +188,17 @@ describe('HealthMonitor', () => { Ref: hmStack.getLogicalId(healthMonitor.unhealthyFleetActionTopic.node.defaultChild as CfnElement), }, ], - })); - expectCDK(hmStack).to(haveResourceLike('AWS::SNS::Topic', { + }); + Template.fromStack(hmStack).hasResourceProperties('AWS::SNS::Topic', { KmsMasterKeyId: { 'Fn::GetAtt': [ `${hmStack.getLogicalId(healthMonitor.node.findChild('SNSEncryptionKey').node.defaultChild as CfnElement)}`, 'Arn', ], }, - })); - expectCDK(hmStack).to(haveResource('AWS::Lambda::Function')); - expectCDK(hmStack).to(haveResourceLike('AWS::SNS::Subscription', { + }); + Template.fromStack(hmStack).hasResourceProperties('AWS::Lambda::Function', {}); + Template.fromStack(hmStack).hasResourceProperties('AWS::SNS::Subscription', { Protocol: 'lambda', TopicArn: { Ref: `${infraStack.getLogicalId(healthMonitor.node.findChild('UnhealthyFleetTopic').node.defaultChild as CfnElement)}`, @@ -215,7 +209,7 @@ describe('HealthMonitor', () => { 'Arn', ], }, - })); + }); }); test('validating health monitor properties while passing a key', () => { @@ -225,13 +219,13 @@ describe('HealthMonitor', () => { encryptionKey: Key.fromKeyArn(hmStack, 'importedKey', 'arn:aws:kms:us-west-2:123456789012:key/testarn'), }); // THEN - expectCDK(hmStack).notTo(haveResource('AWS::ElasticLoadBalancingV2::LoadBalancer')); - expectCDK(hmStack).notTo(haveResource('AWS::KMS::Key')); - expectCDK(hmStack).to(haveResourceLike('AWS::SNS::Topic', { + Template.fromStack(hmStack).resourceCountIs('AWS::ElasticLoadBalancingV2::LoadBalancer', 0); + Template.fromStack(hmStack).resourceCountIs('AWS::KMS::Key', 0); + Template.fromStack(hmStack).hasResourceProperties('AWS::SNS::Topic', { KmsMasterKeyId: 'arn:aws:kms:us-west-2:123456789012:key/testarn', - })); - expectCDK(hmStack).to(haveResource('AWS::Lambda::Function')); - expectCDK(hmStack).to(haveResourceLike('AWS::SNS::Subscription', { + }); + Template.fromStack(hmStack).hasResourceProperties('AWS::Lambda::Function', {}); + Template.fromStack(hmStack).hasResourceProperties('AWS::SNS::Subscription', { Protocol: 'lambda', TopicArn: { Ref: `${infraStack.getLogicalId(healthMonitor.node.findChild('UnhealthyFleetTopic').node.defaultChild as CfnElement)}`, @@ -242,7 +236,7 @@ describe('HealthMonitor', () => { 'Arn', ], }, - })); + }); }); test('validating the target with default health config', () => { @@ -258,24 +252,24 @@ describe('HealthMonitor', () => { healthMonitor.registerFleet(fleet, {}); // THEN - expectCDK(wfStack).to(haveResource('AWS::ElasticLoadBalancingV2::Listener')); - expectCDK(hmStack).notTo((haveResourceLike('AWS::EC2::SecurityGroup', { - SecurityGroupIngress: arrayWith(deepObjectLike({ + Template.fromStack(wfStack).hasResourceProperties('AWS::ElasticLoadBalancingV2::Listener', {}); + Template.fromStack(hmStack).hasResourceProperties('AWS::EC2::SecurityGroup', Match.not({ + SecurityGroupIngress: Match.arrayWith([{ CidrIp: '0.0.0.0/0', FromPort: 8081, IpProtocol: 'tcp', ToPort: 8081, - })), - }))); - expectCDK(wfStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::TargetGroup', { + }]), + })); + Template.fromStack(wfStack).hasResourceProperties('AWS::ElasticLoadBalancingV2::TargetGroup', { HealthCheckIntervalSeconds: 300, HealthCheckPort: '8081', HealthCheckProtocol: 'HTTP', Port: 8081, Protocol: 'HTTP', TargetType: 'instance', - })); - expectCDK(wfStack).to(haveResource('AWS::CloudWatch::Alarm')); + }); + Template.fromStack(wfStack).hasResourceProperties('AWS::CloudWatch::Alarm', {}); }); test('validating the target with custom health config', () => { @@ -292,16 +286,16 @@ describe('HealthMonitor', () => { }); // THEN - expectCDK(wfStack).to(haveResource('AWS::ElasticLoadBalancingV2::Listener')); - expectCDK(wfStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::TargetGroup', { + Template.fromStack(wfStack).hasResourceProperties('AWS::ElasticLoadBalancingV2::Listener' ,{}); + Template.fromStack(wfStack).hasResourceProperties('AWS::ElasticLoadBalancingV2::TargetGroup', { HealthCheckIntervalSeconds: 300, HealthCheckPort: '7171', HealthCheckProtocol: 'HTTP', Port: 8081, Protocol: 'HTTP', TargetType: 'instance', - })); - expectCDK(wfStack).to(haveResource('AWS::CloudWatch::Alarm')); + }); + Template.fromStack(wfStack).hasResourceProperties('AWS::CloudWatch::Alarm', {}); }); test('2 ASG gets registered to same LB', () => { @@ -321,41 +315,40 @@ describe('HealthMonitor', () => { healthMonitor.registerFleet(fleet2, {port: 7171}); // THEN - expectCDK(hmStack).to(countResourcesLike('AWS::ElasticLoadBalancingV2::LoadBalancer', 1, { - LoadBalancerAttributes: [ + resourcePropertiesCountIs(hmStack, 'AWS::ElasticLoadBalancingV2::LoadBalancer', { + LoadBalancerAttributes: Match.arrayWith([ { Key: 'deletion_protection.enabled', Value: 'true', }, - ], + ]), Scheme: 'internal', - })); - expectCDK(wfStack).to(countResources('AWS::ElasticLoadBalancingV2::Listener', 2)); - expectCDK(wfStack).to(haveResource('AWS::ElasticLoadBalancingV2::Listener')); - expectCDK(wfStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::TargetGroup', { + }, 1); + Template.fromStack(wfStack).resourceCountIs('AWS::ElasticLoadBalancingV2::Listener', 2); + Template.fromStack(wfStack).hasResourceProperties('AWS::ElasticLoadBalancingV2::TargetGroup', { HealthCheckIntervalSeconds: 300, HealthCheckPort: '7171', HealthCheckProtocol: 'HTTP', Port: 8081, Protocol: 'HTTP', TargetType: 'instance', - })); - expectCDK(wfStack).to(haveResourceLike('AWS::CloudWatch::Alarm', { + }); + Template.fromStack(wfStack).hasResourceProperties('AWS::CloudWatch::Alarm', { ComparisonOperator: 'GreaterThanThreshold', EvaluationPeriods: 8, ActionsEnabled: true, DatapointsToAlarm: 8, Threshold: 0, TreatMissingData: 'notBreaching', - })); - expectCDK(wfStack).to(haveResourceLike('AWS::CloudWatch::Alarm', { + }); + Template.fromStack(wfStack).hasResourceProperties('AWS::CloudWatch::Alarm', { ComparisonOperator: 'GreaterThanThreshold', EvaluationPeriods: 1, ActionsEnabled: true, DatapointsToAlarm: 1, Threshold: 35, TreatMissingData: 'notBreaching', - })); + }); }); test('validating LB target limit', () => { @@ -381,21 +374,21 @@ describe('HealthMonitor', () => { healthMonitor.registerFleet(fleet2, {}); // THEN - expectCDK(hmStack).to(countResourcesLike('AWS::ElasticLoadBalancingV2::LoadBalancer', 2, { - LoadBalancerAttributes: [ + resourcePropertiesCountIs(hmStack, 'AWS::ElasticLoadBalancingV2::LoadBalancer', { + LoadBalancerAttributes: Match.arrayWith([ { Key: 'deletion_protection.enabled', Value: 'true', }, - ], + ]), Scheme: 'internal', Type: 'application', - })); - expectCDK(wfStack).to(countResources('AWS::ElasticLoadBalancingV2::Listener', 2)); - expectCDK(wfStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::Listener', { + }, 2); + Template.fromStack(wfStack).resourceCountIs('AWS::ElasticLoadBalancingV2::Listener', 2); + Template.fromStack(wfStack).hasResourceProperties('AWS::ElasticLoadBalancingV2::Listener', { Port: 8081, Protocol: 'HTTP', - })); + }); }); test('validating LB listener limit', () => { @@ -422,21 +415,21 @@ describe('HealthMonitor', () => { healthMonitor.registerFleet(fleet2, {}); // THEN - expectCDK(hmStack).to(countResourcesLike('AWS::ElasticLoadBalancingV2::LoadBalancer', 2, { - LoadBalancerAttributes: [ + resourcePropertiesCountIs(hmStack, 'AWS::ElasticLoadBalancingV2::LoadBalancer', { + LoadBalancerAttributes: Match.arrayWith([ { Key: 'deletion_protection.enabled', Value: 'true', }, - ], + ]), Scheme: 'internal', Type: 'application', - })); - expectCDK(wfStack).to(countResources('AWS::ElasticLoadBalancingV2::Listener', 2)); - expectCDK(wfStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::Listener', { + }, 2); + Template.fromStack(wfStack).resourceCountIs('AWS::ElasticLoadBalancingV2::Listener', 2); + Template.fromStack(wfStack).hasResourceProperties('AWS::ElasticLoadBalancingV2::Listener', { Port: 8081, Protocol: 'HTTP', - })); + }); }); test('validating target group limit per lb', () => { @@ -460,15 +453,15 @@ describe('HealthMonitor', () => { healthMonitor.registerFleet(fleet2, {}); // THEN - expectCDK(hmStack).to(countResourcesLike('AWS::ElasticLoadBalancingV2::LoadBalancer', 2, { + resourcePropertiesCountIs(hmStack, 'AWS::ElasticLoadBalancingV2::LoadBalancer', { Scheme: 'internal', Type: 'application', - })); - expectCDK(wfStack).to(countResources('AWS::ElasticLoadBalancingV2::Listener', 2)); - expectCDK(wfStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::Listener', { + }, 2); + Template.fromStack(wfStack).resourceCountIs('AWS::ElasticLoadBalancingV2::Listener', 2); + Template.fromStack(wfStack).hasResourceProperties('AWS::ElasticLoadBalancingV2::Listener', { Port: 8081, Protocol: 'HTTP', - })); + }); }); test('validating target limit exhaustion', () => { @@ -503,15 +496,17 @@ describe('HealthMonitor', () => { healthMonitor.registerFleet(fleet, {}); // THEN - expectCDK(hmStack).to(not(haveResourceLike('AWS::ElasticLoadBalancingV2::LoadBalancer', { - LoadBalancerAttributes: arrayWith( - { - Key: 'deletion_protection.enabled', - Value: 'true', - }, - ), - Scheme: ABSENT, - Type: ABSENT, + Template.fromStack(hmStack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', Match.not(Match.objectLike({ + Properties: { + LoadBalancerAttributes: Match.arrayWith([ + { + Key: 'deletion_protection.enabled', + Value: 'true', + }, + ]), + Scheme: Match.absent, + Type: Match.absent, + }, }))); }); @@ -527,14 +522,14 @@ describe('HealthMonitor', () => { healthMonitor.registerFleet(fleet, {}); // THEN - expectCDK(hmStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::LoadBalancer', { - LoadBalancerAttributes: arrayWith( + Template.fromStack(hmStack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', { + LoadBalancerAttributes: Match.arrayWith([ { Key: 'routing.http.drop_invalid_header_fields.enabled', Value: 'true', }, - ), - })); + ]), + }); }); test('specifying a subnet', () => { @@ -553,19 +548,19 @@ describe('HealthMonitor', () => { // THEN // Make sure it has the public subnets - expectCDK(hmStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::LoadBalancer', { + Template.fromStack(hmStack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', { Subnets: [ - {'Fn::ImportValue': stringLike('*PublicSubnet*')}, - {'Fn::ImportValue': stringLike('*PublicSubnet*')}, + {'Fn::ImportValue': Match.stringLikeRegexp('.*PublicSubnet.*')}, + {'Fn::ImportValue': Match.stringLikeRegexp('.*PublicSubnet.*')}, ], - })); + }); // Make sure the private subnets aren't present - expectCDK(hmStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::LoadBalancer', { + Template.fromStack(hmStack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', { Subnets: [ - {'Fn::ImportValue': notMatching(stringLike('*PrivateSubnet*'))}, - {'Fn::ImportValue': notMatching(stringLike('*PrivateSubnet*'))}, + {'Fn::ImportValue': Match.not(Match.stringLikeRegexp('.*PrivateSubnet.*'))}, + {'Fn::ImportValue': Match.not(Match.stringLikeRegexp('.*PrivateSubnet.*'))}, ], - })); + }); }); test('specifying a security group', () => { @@ -584,13 +579,13 @@ describe('HealthMonitor', () => { // THEN // Make sure it has the security group - expectCDK(hmStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::LoadBalancer', { - SecurityGroups: arrayWith( + Template.fromStack(hmStack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', { + SecurityGroups: Match.arrayWith([ hmStack.resolve(securityGroup.securityGroupId), - ), - })); + ]), + }); // HealthMonitor should not create its own security group - expectCDK(hmStack).notTo(haveResource('AWS::EC2::SecurityGroup')); + Template.fromStack(hmStack).resourceCountIs('AWS::EC2::SecurityGroup', 0); }); describe('tagging', () => { diff --git a/packages/aws-rfdk/lib/core/test/imported-acm-certificate.test.ts b/packages/aws-rfdk/lib/core/test/imported-acm-certificate.test.ts index 18fe3081f..9679d6b57 100644 --- a/packages/aws-rfdk/lib/core/test/imported-acm-certificate.test.ts +++ b/packages/aws-rfdk/lib/core/test/imported-acm-certificate.test.ts @@ -3,21 +3,17 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { RemovalPolicy, Stack } from 'aws-cdk-lib'; import { - arrayWith, - expect as expectCDK, - haveResourceLike, - objectLike, - ResourcePart, - stringLike, -} from '@aws-cdk/assert'; + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { Metric, Statistic, -} from '@aws-cdk/aws-cloudwatch'; -import { Table } from '@aws-cdk/aws-dynamodb'; -import { CfnSecret } from '@aws-cdk/aws-secretsmanager'; -import { RemovalPolicy, Stack } from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-cloudwatch'; +import { Table } from 'aws-cdk-lib/aws-dynamodb'; +import { CfnSecret } from 'aws-cdk-lib/aws-secretsmanager'; import { ImportedAcmCertificate } from '../lib/imported-acm-certificate'; import { X509CertificatePem } from '../lib/x509-certificate'; @@ -48,7 +44,7 @@ describe('ImportedAcmCertificate', () => { test('creates Custom::RFDK_AcmImportedCertificate', () => { // THEN - expectCDK(stack).to(haveResourceLike('Custom::RFDK_AcmImportedCertificate', { + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_AcmImportedCertificate', { X509CertificatePem: { Cert: { 'Fn::GetAtt': [ @@ -77,53 +73,53 @@ describe('ImportedAcmCertificate', () => { Value: 'f4e2abf974443234fdb095fafcfa9ee2', }, ], - })); + }); }); describe('creates AWS::DynamoDB::Table for database', () => { test('with PhysicalID partition key', () => { // THEN - expectCDK(stack).to(haveResourceLike('AWS::DynamoDB::Table', { - AttributeDefinitions: arrayWith( + Template.fromStack(stack).hasResourceProperties('AWS::DynamoDB::Table', { + AttributeDefinitions: Match.arrayWith([ { AttributeName: 'PhysicalId', AttributeType: 'S', }, - ), - KeySchema: arrayWith( + ]), + KeySchema: Match.arrayWith([ { AttributeName: 'PhysicalId', KeyType: 'HASH', }, - ), - })); + ]), + }); }); test('with CustomResource sort key', () => { // THEN - expectCDK(stack).to(haveResourceLike('AWS::DynamoDB::Table', { - AttributeDefinitions: arrayWith( + Template.fromStack(stack).hasResourceProperties('AWS::DynamoDB::Table', { + AttributeDefinitions: Match.arrayWith([ { AttributeName: 'CustomResource', AttributeType: 'S', }, - ), - KeySchema: arrayWith( + ]), + KeySchema: Match.arrayWith([ { AttributeName: 'CustomResource', KeyType: 'RANGE', }, - ), - })); + ]), + }); }); }); test('creates AWS::IAM::Policy', () => { // THEN - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ - { + Match.objectLike({ Action: [ 'dynamodb:BatchGetItem', 'dynamodb:GetRecords', @@ -136,12 +132,13 @@ describe('ImportedAcmCertificate', () => { 'dynamodb:PutItem', 'dynamodb:UpdateItem', 'dynamodb:DeleteItem', + 'dynamodb:DescribeTable', ], - }, - { + }), + Match.objectLike({ Action: 'dynamodb:DescribeTable', - }, - { + }), + Match.objectLike({ Action: [ 'secretsmanager:GetSecretValue', 'secretsmanager:DescribeSecret', @@ -152,8 +149,8 @@ describe('ImportedAcmCertificate', () => { 'Cert', ], }, - }, - { + }), + Match.objectLike({ Action: [ 'secretsmanager:GetSecretValue', 'secretsmanager:DescribeSecret', @@ -164,7 +161,7 @@ describe('ImportedAcmCertificate', () => { 'Key', ], }, - }, + }), { Action: [ 'secretsmanager:GetSecretValue', @@ -174,7 +171,7 @@ describe('ImportedAcmCertificate', () => { Ref: certPassphraseID, }, }, - { + Match.objectLike({ Action: [ 'acm:AddTagsToCertificate', 'acm:ImportCertificate', @@ -185,35 +182,35 @@ describe('ImportedAcmCertificate', () => { }, }, Resource: '*', - }, - { + }), + Match.objectLike({ Action: [ 'acm:DeleteCertificate', 'acm:DescribeCertificate', 'acm:GetCertificate', ], Resource: '*', - }, + }), ], }, - })); + }); }); describe('custom resource lambda function', () => { test('uses correct handler', () => { // THEN - expectCDK(stack).to(haveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'x509-certificate.importCert', - })); + }); }); test('uses RFDK lambda layer', () => { // THEN - expectCDK(stack).to(haveResourceLike('AWS::Lambda::Function', { - Layers: arrayWith( - stringLike('arn:aws:lambda:us-west-2:224375009292:layer:openssl-al2:*'), - ), - })); + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { + Layers: Match.arrayWith([ + Match.stringLikeRegexp('arn:aws:lambda:us-west-2:224375009292:layer:openssl-al2:.*'), + ]), + }); }); test('sets DATABASE environment variable', () => { @@ -221,30 +218,30 @@ describe('ImportedAcmCertificate', () => { const table = importedAcmCertificate.node.findChild('Table') as Table; // THEN - expectCDK(stack).to(haveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Environment: { - Variables: objectLike({ + Variables: Match.objectLike({ DATABASE: stack.resolve(table.tableName), }), }, - })); + }); }); }); describe('applyRemovalPolicy', () => { test('default RemovalPolicy is Delete', () => { - expectCDK(stack).to(haveResourceLike('Custom::RFDK_AcmImportedCertificate', { + Template.fromStack(stack).hasResource('Custom::RFDK_AcmImportedCertificate', { DeletionPolicy: 'Delete', UpdateReplacePolicy: 'Delete', - }, ResourcePart.CompleteDefinition)); + }); }); test('Different policy can be applied', () => { importedAcmCertificate.applyRemovalPolicy(RemovalPolicy.RETAIN); - expectCDK(stack).to(haveResourceLike('Custom::RFDK_AcmImportedCertificate', { + Template.fromStack(stack).hasResource('Custom::RFDK_AcmImportedCertificate', { DeletionPolicy: 'Retain', UpdateReplacePolicy: 'Retain', - }, ResourcePart.CompleteDefinition)); + }); }); }); diff --git a/packages/aws-rfdk/lib/core/test/log-group-factory.test.ts b/packages/aws-rfdk/lib/core/test/log-group-factory.test.ts index dc3c21e77..97e1c1570 100644 --- a/packages/aws-rfdk/lib/core/test/log-group-factory.test.ts +++ b/packages/aws-rfdk/lib/core/test/log-group-factory.test.ts @@ -3,9 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { expect as expectCDK, haveResourceLike } from '@aws-cdk/assert'; -import { RetentionDays } from '@aws-cdk/aws-logs'; -import { Stack } from '@aws-cdk/core'; +import { Stack } from 'aws-cdk-lib'; +import { + Match, + Template, +} from 'aws-cdk-lib/assertions'; +import { RetentionDays } from 'aws-cdk-lib/aws-logs'; import { LogGroupFactory } from '../lib/log-group-factory'; describe('log group', () => { @@ -16,11 +19,11 @@ describe('log group', () => { LogGroupFactory.createOrFetch(stack, 'TestId', 'testLogGroup'); // THEN - expectCDK(stack).to(haveResourceLike('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { LogGroupName: 'testLogGroup', RetentionInDays: 3, - })); - expectCDK(stack).notTo(haveResourceLike('AWS::Lambda::Function', { + }); + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', Match.not({ Role: { 'Fn::GetAtt': [ 'LogGroupExporter6382448ce4b242e9b14fa0a9ccdb198eServiceRoleB67C808B', @@ -39,11 +42,11 @@ describe('log group', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { LogGroupName: 'prefix-testLogGroup', RetentionInDays: 3, - })); - expectCDK(stack).notTo(haveResourceLike('AWS::Lambda::Function', { + }); + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', Match.not({ Role: { 'Fn::GetAtt': [ 'LogGroupExporter6382448ce4b242e9b14fa0a9ccdb198eServiceRoleB67C808B', @@ -62,11 +65,11 @@ describe('log group', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { LogGroupName: 'testLogGroup', RetentionInDays: 7, - })); - expectCDK(stack).notTo(haveResourceLike('AWS::Lambda::Function', { + }); + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', Match.not({ Role: { 'Fn::GetAtt': [ 'LogGroupExporter6382448ce4b242e9b14fa0a9ccdb198eServiceRoleB67C808B', @@ -87,26 +90,26 @@ describe('exporting log group', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { LogGroupName: 'testLogGroup', RetentionInDays: 3, - })); + }); - expectCDK(stack).to(haveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Role: { 'Fn::GetAtt': [ 'LogGroupExporter6382448ce4b242e9b14fa0a9ccdb198eServiceRoleB67C808B', 'Arn', ], }, - })); - expectCDK(stack).to(haveResourceLike('AWS::Events::Rule', { + }); + Template.fromStack(stack).hasResourceProperties('AWS::Events::Rule', { Targets: [ { Input: '{\"BucketName\":\"test-bucket\",\"ExportFrequencyInHours\":1,\"LogGroupName\":\"testLogGroup\",\"RetentionInHours\":72}', }, ], - })); + }); }); test('created correctly with prefix', () => { @@ -119,27 +122,27 @@ describe('exporting log group', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { LogGroupName: 'prefix-testLogGroup', RetentionInDays: 3, - })); + }); - expectCDK(stack).to(haveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Role: { 'Fn::GetAtt': [ 'LogGroupExporter6382448ce4b242e9b14fa0a9ccdb198eServiceRoleB67C808B', 'Arn', ], }, - })); + }); - expectCDK(stack).to(haveResourceLike('AWS::Events::Rule', { + Template.fromStack(stack).hasResourceProperties('AWS::Events::Rule', { Targets: [ { Input: '{\"BucketName\":\"test-bucket\",\"ExportFrequencyInHours\":1,\"LogGroupName\":\"prefix-testLogGroup\",\"RetentionInHours\":72}', }, ], - })); + }); }); test('created correctly with custom retention', () => { @@ -152,26 +155,26 @@ describe('exporting log group', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { LogGroupName: 'testLogGroup', RetentionInDays: 7, - })); + }); - expectCDK(stack).to(haveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Role: { 'Fn::GetAtt': [ 'LogGroupExporter6382448ce4b242e9b14fa0a9ccdb198eServiceRoleB67C808B', 'Arn', ], }, - })); + }); - expectCDK(stack).to(haveResourceLike('AWS::Events::Rule', { + Template.fromStack(stack).hasResourceProperties('AWS::Events::Rule', { Targets: [ { Input: '{\"BucketName\":\"test-bucket\",\"ExportFrequencyInHours\":1,\"LogGroupName\":\"testLogGroup\",\"RetentionInHours\":168}', }, ], - })); + }); }); }); diff --git a/packages/aws-rfdk/lib/core/test/mongodb-installer.test.ts b/packages/aws-rfdk/lib/core/test/mongodb-installer.test.ts index d0447cd92..14cf19c1b 100644 --- a/packages/aws-rfdk/lib/core/test/mongodb-installer.test.ts +++ b/packages/aws-rfdk/lib/core/test/mongodb-installer.test.ts @@ -4,9 +4,12 @@ */ import { - expect as cdkExpect, - haveResourceLike, -} from '@aws-cdk/assert'; + Stack, +} from 'aws-cdk-lib'; +import { + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { AmazonLinuxGeneration, Instance, @@ -14,10 +17,7 @@ import { MachineImage, Vpc, WindowsVersion, -} from '@aws-cdk/aws-ec2'; -import { - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; import { MongoDbInstaller, @@ -28,9 +28,6 @@ import { import { INSTALL_MONGODB_3_6_SCRIPT_LINUX, } from './asset-constants'; -import { - escapeTokenRegex, -} from './token-regex-helpers'; describe('Test MongoDbInstaller', () => { let stack: Stack; @@ -85,10 +82,9 @@ Please set the userSsplAcceptance property to USER_ACCEPTS_SSPL to signify your // WHEN installer.installOnLinuxInstance(instance); - const userData = instance.userData.render(); // THEN - cdkExpect(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -109,7 +105,7 @@ Please set the userSsplAcceptance property to USER_ACCEPTS_SSPL to signify your }, ':s3:::', { - Ref: INSTALL_MONGODB_3_6_SCRIPT_LINUX.Bucket, + 'Fn::Sub': INSTALL_MONGODB_3_6_SCRIPT_LINUX.Bucket, }, ], ], @@ -124,7 +120,7 @@ Please set the userSsplAcceptance property to USER_ACCEPTS_SSPL to signify your }, ':s3:::', { - Ref: INSTALL_MONGODB_3_6_SCRIPT_LINUX.Bucket, + 'Fn::Sub': INSTALL_MONGODB_3_6_SCRIPT_LINUX.Bucket, }, '/*', ], @@ -134,12 +130,24 @@ Please set the userSsplAcceptance property to USER_ACCEPTS_SSPL to signify your }, ], }, - })); - // Make sure we download the mountEFS script asset bundle - const s3Copy = 'aws s3 cp \'s3://${Token[TOKEN.\\d+]}/${Token[TOKEN.\\d+]}${Token[TOKEN.\\d+]}\' \'/tmp/${Token[TOKEN.\\d+]}${Token[TOKEN.\\d+]}\''; - expect(userData).toMatch(new RegExp(escapeTokenRegex(s3Copy))); - // Make sure we execute the script with the correct args - expect(userData).toMatch(new RegExp(escapeTokenRegex('bash /tmp/${Token[TOKEN.\\d+]}${Token[TOKEN.\\d+]}'))); + }); + // Make sure we download and run the mongo install script + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + [ + `#!/bin/bash\nmkdir -p $(dirname '/tmp/${INSTALL_MONGODB_3_6_SCRIPT_LINUX.Key}.sh')\naws s3 cp 's3://`, + { + 'Fn::Sub': INSTALL_MONGODB_3_6_SCRIPT_LINUX.Bucket, + }, + `/${INSTALL_MONGODB_3_6_SCRIPT_LINUX.Key}.sh' '/tmp/${INSTALL_MONGODB_3_6_SCRIPT_LINUX.Key}.sh'\nbash /tmp/${INSTALL_MONGODB_3_6_SCRIPT_LINUX.Key}.sh`, + ], + ], + }, + }, + }); }); test('assert Linux-only', () => { @@ -179,14 +187,28 @@ Please set the userSsplAcceptance property to USER_ACCEPTS_SSPL to signify your // WHEN installer1.installOnLinuxInstance(instance); installer2.installOnLinuxInstance(instance); - const userData = instance.userData.render(); - const s3Copy = 'aws s3 cp \'s3://${Token[TOKEN.\\d+]}/${Token[TOKEN.\\d+]}${Token[TOKEN.\\d+]}\''; - const regex = new RegExp(escapeTokenRegex(s3Copy), 'g'); - const matches = userData.match(regex) ?? []; // THEN // The source of the asset copy should be identical from installer1 & installer2 - expect(matches).toHaveLength(2); - expect(matches[0]).toBe(matches[1]); + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + Match.arrayWith([ + `#!/bin/bash\nmkdir -p $(dirname '/tmp/${INSTALL_MONGODB_3_6_SCRIPT_LINUX.Key}.sh')\naws s3 cp 's3://`, + { + 'Fn::Sub': INSTALL_MONGODB_3_6_SCRIPT_LINUX.Bucket, + }, + `/${INSTALL_MONGODB_3_6_SCRIPT_LINUX.Key}.sh' '/tmp/${INSTALL_MONGODB_3_6_SCRIPT_LINUX.Key}.sh'\nbash /tmp/${INSTALL_MONGODB_3_6_SCRIPT_LINUX.Key}.sh\nmkdir -p $(dirname '/tmp/${INSTALL_MONGODB_3_6_SCRIPT_LINUX.Key}.sh')\naws s3 cp 's3://`, + { + 'Fn::Sub': INSTALL_MONGODB_3_6_SCRIPT_LINUX.Bucket, + }, + `/${INSTALL_MONGODB_3_6_SCRIPT_LINUX.Key}.sh' '/tmp/${INSTALL_MONGODB_3_6_SCRIPT_LINUX.Key}.sh'\nbash /tmp/${INSTALL_MONGODB_3_6_SCRIPT_LINUX.Key}.sh`, + ]), + ], + }, + }, + }); }); }); diff --git a/packages/aws-rfdk/lib/core/test/mongodb-instance.test.ts b/packages/aws-rfdk/lib/core/test/mongodb-instance.test.ts index 816ec91f0..7bac46d59 100644 --- a/packages/aws-rfdk/lib/core/test/mongodb-instance.test.ts +++ b/packages/aws-rfdk/lib/core/test/mongodb-instance.test.ts @@ -4,42 +4,38 @@ */ import { - arrayWith, - countResources, - expect as cdkExpect, - haveResource, - haveResourceLike, - objectLike, -} from '@aws-cdk/assert'; + App, + Names, + Size, + Stack, +} from 'aws-cdk-lib'; +import { + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { InstanceType, SecurityGroup, SubnetType, Volume, Vpc, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { Role, ServicePrincipal, -} from '@aws-cdk/aws-iam'; +} from 'aws-cdk-lib/aws-iam'; import { Key, -} from '@aws-cdk/aws-kms'; +} from 'aws-cdk-lib/aws-kms'; import { RetentionDays, -} from '@aws-cdk/aws-logs'; +} from 'aws-cdk-lib/aws-logs'; import { PrivateHostedZone, -} from '@aws-cdk/aws-route53'; +} from 'aws-cdk-lib/aws-route53'; import { Secret, -} from '@aws-cdk/aws-secretsmanager'; -import { - App, - Names, - Size, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-secretsmanager'; import { MongoDbInstance, @@ -49,14 +45,11 @@ import { } from '../lib'; import { - CWA_ASSET_LINUX, + CWA_ASSET_LINUX, INSTALL_MONGODB_3_6_SCRIPT_LINUX, MONGODB_3_6_CONFIGURATION_SCRIPTS, MOUNT_EBS_SCRIPT_LINUX, } from './asset-constants'; import { testConstructTags, } from './tag-helpers'; -import { - escapeTokenRegex, -} from './token-regex-helpers'; describe('Test MongoDbInstance', () => { let app: App; @@ -106,23 +99,23 @@ describe('Test MongoDbInstance', () => { }); // THEN - cdkExpect(stack).to(haveResource('AWS::AutoScaling::AutoScalingGroup')); - cdkExpect(stack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).resourceCountIs('AWS::AutoScaling::AutoScalingGroup', 1); + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { InstanceType: 'r5.large', - BlockDeviceMappings: arrayWith( - objectLike({ - Ebs: objectLike({ + BlockDeviceMappings: Match.arrayWith([ + Match.objectLike({ + Ebs: Match.objectLike({ Encrypted: true, }), }), - ), - })); + ]), + }); - cdkExpect(stack).to(haveResourceLike('AWS::Route53::RecordSet', { + Template.fromStack(stack).hasResourceProperties('AWS::Route53::RecordSet', { Name: hostname + '.' + zoneName + '.', - })); + }); - cdkExpect(stack).to(haveResourceLike('AWS::SecretsManager::Secret', { + Template.fromStack(stack).hasResourceProperties('AWS::SecretsManager::Secret', { Description: `Admin credentials for the MongoDB database ${Names.uniqueId(instance)}`, GenerateSecretString: { ExcludeCharacters: '\"()$\'', @@ -133,21 +126,28 @@ describe('Test MongoDbInstance', () => { RequireEachIncludedType: true, SecretStringTemplate: '{\"username\":\"admin\"}', }, - })); + }); - cdkExpect(stack).to(haveResourceLike('AWS::EC2::Volume', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Volume', { Encrypted: true, - Tags: arrayWith( - objectLike({ + Tags: Match.arrayWith([ + Match.objectLike({ Key: 'VolumeGrantAttach-6238D22B12', Value: '6238d22b121db8094cb816e2a49d2b61', }), - ), - })); + ]), + }); - cdkExpect(stack).to(haveResourceLike('AWS::IAM::Policy', { - PolicyDocument: objectLike({ - Statement: arrayWith( + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: Match.objectLike({ + Statement: Match.arrayWith([ + { + Action: 'cloudformation:SignalResource', + Effect: 'Allow', + Resource: { + Ref: 'AWS::StackId', + }, + }, { Action: [ 'logs:CreateLogStream', @@ -200,7 +200,7 @@ describe('Test MongoDbInstance', () => { }, ':s3:::', { - Ref: CWA_ASSET_LINUX.Bucket, + 'Fn::Sub': CWA_ASSET_LINUX.Bucket, }, ], ], @@ -215,7 +215,7 @@ describe('Test MongoDbInstance', () => { }, ':s3:::', { - Ref: CWA_ASSET_LINUX.Bucket, + 'Fn::Sub': CWA_ASSET_LINUX.Bucket, }, '/*', ], @@ -223,6 +223,38 @@ describe('Test MongoDbInstance', () => { }, ], }, + { + Action: [ + 'ssm:DescribeParameters', + 'ssm:GetParameters', + 'ssm:GetParameter', + 'ssm:GetParameterHistory', + ], + Effect: 'Allow', + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':ssm:', + { + Ref: 'AWS::Region', + }, + ':', + { + Ref: 'AWS::AccountId', + }, + ':parameter/', + { + Ref: Match.stringLikeRegexp('^MongoDbInstanceStringParameter.*'), + }, + ], + ], + }, + }, { Action: [ 'secretsmanager:GetSecretValue', @@ -269,7 +301,7 @@ describe('Test MongoDbInstance', () => { ], Effect: 'Allow', Resource: { - Ref: 'ServerCertPassphraseE4C3CB38', + Ref: Match.stringLikeRegexp('^ServerCertPassphrase.*'), }, }, { @@ -279,114 +311,169 @@ describe('Test MongoDbInstance', () => { ], Effect: 'Allow', Resource: { - Ref: 'MongoDbInstanceAdminUser54147F2B', + Ref: Match.stringLikeRegexp('^MongoDbInstanceAdminUser.*'), }, }, - - ), + ]), }), - })); + }); - cdkExpect(stack).to(haveResourceLike('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { LogGroupName: '/renderfarm/MongoDbInstance', - })); + }); const cloudInitLogPath = '/var/log/cloud-init-output.log'; const cloudInitLogPrefix = 'cloud-init-output'; const mongoLogPath = '/var/log/mongodb/mongod.log'; const mongoLogPrefix = 'MongoDB'; - cdkExpect(stack).to(haveResourceLike('AWS::SSM::Parameter', { + Template.fromStack(stack).hasResourceProperties('AWS::SSM::Parameter', { Description: 'config file for Repository logs config', - Value: objectLike({ - 'Fn::Join': arrayWith( - arrayWith( - '\",\"log_stream_name\":\"' + cloudInitLogPrefix + '-{instance_id}\",\"file_path\":\"' + cloudInitLogPath + '\",' + + Value: { + 'Fn::Join': [ + '', + Match.arrayWith([ + `\",\"log_stream_name\":\"${cloudInitLogPrefix}-{instance_id}\",\"file_path\":\"${cloudInitLogPath}\",` + '\"timezone\":\"Local\"},{\"log_group_name\":\"', - '\",\"log_stream_name\":\"' + mongoLogPrefix + '-{instance_id}\",\"file_path\":\"' + mongoLogPath + '\"' + + `\",\"log_stream_name\":\"${mongoLogPrefix}-{instance_id}\",\"file_path\":\"${mongoLogPath}\"` + ',\"timezone\":\"Local\"}]}},\"log_stream_name\":\"DefaultLogStream-{instance_id}\",\"force_flush_interval\":15}}', - ), - ), - }), - })); - - const userData = instance.userData.render(); - const token = '${Token[TOKEN.\\d+]}'; - - // Make sure we add signal on exit - const exitTrap = '#!/bin/bash\n' + - 'function exitTrap(){\n' + - 'exitCode=$?\n' + - '/opt/aws/bin/cfn-signal --stack Stack --resource MongoDbInstanceServerAsgASG2643AD1D --region ' + token + - ' -e $exitCode || echo \'Failed to send Cloudformation Signal\'\n' + - 'test \"${MONGO_SETUP_DIR} != \"\" && sudo umount \"${MONGO_SETUP_DIR}\n' + - '}'; - expect(userData).toMatch(new RegExp(escapeTokenRegex(exitTrap))); - - const callExitTrap = 'trap exitTrap EXIT'; - expect(userData).toMatch(new RegExp(callExitTrap)); - - const settings = 'set -xefuo pipefail'; - expect(userData).toMatch(new RegExp(settings)); - - const createTempDir = 'mkdir -p $\\(dirname \'/tmp/' + token + token + '\'\\)\n'; - const s3Copy = 'aws s3 cp \'s3://' + token + '/' + token + token + '\' \'/tmp/' + token + token + '\'\n'; - - // CloudWatch Agent - const setE = 'set -e\n'; - const setChmod = 'chmod \\+x \'/tmp/' + token + token + '\'\n'; - const execute = '\'/tmp/' + token + token + '\' -i ${Token[AWS.Region.\\d+]} ' + token + '\n'; - expect(userData).toMatch(new RegExp(escapeTokenRegex(createTempDir + s3Copy + setE + setChmod + execute))); - - // Make sure we mount EBS volume - const mount = 'TMPDIR=$\\(mktemp -d\\)\n' + - 'pushd \"$TMPDIR\"\n' + - 'unzip /tmp/' + token + token + '\n' + - 'bash ./mountEbsBlockVolume.sh ' + token + ' xfs /var/lib/mongo rw \"\"\n' + - 'popd\n' + - 'rm -f /tmp/' + token + token; - expect(userData).toMatch(new RegExp(escapeTokenRegex(createTempDir + s3Copy + mount))); - - // install mongodb - const bashCmd = 'bash /tmp/' + token + token; - expect(userData).toMatch(new RegExp(escapeTokenRegex(createTempDir + s3Copy + bashCmd))); - - // configureMongoDb - const monogdbConfig = 'which mongod && test -f /etc/mongod.conf\n' + - 'sudo service mongod stop\n' + - 'MONGO_SETUP_DIR=$\\(mktemp -d\\)\n' + - 'mkdir -p \"${MONGO_SETUP_DIR}\"\n' + - 'sudo mount -t tmpfs -o size=50M tmpfs \"${MONGO_SETUP_DIR}\"\n' + - 'pushd \"${MONGO_SETUP_DIR}\"\n' + - 'unzip /tmp/' + token + token + '\n' + - 'cp /etc/mongod.conf .'; - expect(userData).toMatch(new RegExp(escapeTokenRegex(createTempDir + s3Copy + monogdbConfig))); - - // Getting the server certificate - const serverCertCmd = 'bash serverCertFromSecrets.sh \\"' + token + '\\" \\"' + token + '\\" \\"' + token + '\\" \\"' + token + '\\"'; - expect(userData).toMatch(new RegExp(escapeTokenRegex(serverCertCmd))); - - // set mongodb certificates and credentials - const monogdbCredentials = 'sudo mkdir -p /etc/mongod_certs\n' + - 'sudo mv ./ca.crt ./key.pem /etc/mongod_certs\n' + - 'sudo chown root.mongod -R /etc/mongod_certs/\n' + - 'sudo chmod 640 -R /etc/mongod_certs/\n' + - 'sudo chmod 750 /etc/mongod_certs/\n' + - 'sudo chown mongod.mongod -R /var/lib/mongo\n' + - 'bash ./setMongoLimits.sh\n' + - 'bash ./setStoragePath.sh \"/var/lib/mongo\"\n' + - 'bash ./setMongoNoAuth.sh\n' + - 'sudo service mongod start\n' + - 'bash ./setAdminCredentials.sh \"' + token + '\"'; - expect(userData).toMatch(new RegExp(escapeTokenRegex(monogdbCredentials))); - - // Setup for live deployment, and start mongod - const startMongo = 'sudo service mongod stop\n' + - 'bash ./setLiveConfiguration.sh\n' + - 'sudo systemctl enable mongod\n' + - 'sudo service mongod start\n' + - 'popd'; - expect(userData).toMatch(new RegExp(escapeTokenRegex(startMongo))); + ]), + ], + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + Match.arrayWith([ + // Make sure we add signal on exit + '#!/bin/bash\n' + + 'function exitTrap(){\n' + + 'exitCode=$?\n' + + '/opt/aws/bin/cfn-signal --stack Stack --resource MongoDbInstanceServerAsgASG2643AD1D --region ', + { + Ref: 'AWS::Region', + }, + ' -e $exitCode || echo \'Failed to send Cloudformation Signal\'\n' + + 'test "${MONGO_SETUP_DIR}" != "" && sudo umount "${MONGO_SETUP_DIR}"\n' + + '}\n' + + // Set up the exit trap + 'trap exitTrap EXIT\n' + + // Script settings + 'set -xefuo pipefail\n' + + // Setup CloudWatch agent + `mkdir -p $(dirname '/tmp/${CWA_ASSET_LINUX.Key}.sh')\n` + + 'aws s3 cp \'s3://', + { + 'Fn::Sub': CWA_ASSET_LINUX.Bucket, + }, + `/${CWA_ASSET_LINUX.Key}.sh' '/tmp/${CWA_ASSET_LINUX.Key}.sh'\n` + + 'set -e\n' + + `chmod +x '/tmp/${CWA_ASSET_LINUX.Key}.sh'\n'/tmp/${CWA_ASSET_LINUX.Key}.sh' -i `, + { + Ref: 'AWS::Region', + }, + ' ', + { + Ref: Match.stringLikeRegexp('^MongoDbInstanceStringParameter.*'), + }, + // Make sure we mount the EBS Volume + `\nmkdir -p $(dirname '/tmp/${MOUNT_EBS_SCRIPT_LINUX.Key}.zip')\n` + + 'aws s3 cp \'s3://', + { + 'Fn::Sub': MOUNT_EBS_SCRIPT_LINUX.Bucket, + }, + `/${MOUNT_EBS_SCRIPT_LINUX.Key}.zip' '/tmp/${MOUNT_EBS_SCRIPT_LINUX.Key}.zip'\n` + + 'TMPDIR=$(mktemp -d)\n' + + 'pushd "$TMPDIR"\n' + + `unzip /tmp/${MOUNT_EBS_SCRIPT_LINUX.Key}.zip\n` + + 'bash ./mountEbsBlockVolume.sh ', + { + Ref: Match.stringLikeRegexp('^MongoDbInstanceMongoDbData.*'), + }, + ' xfs /var/lib/mongo rw ""\n' + + 'popd\n' + + `rm -f /tmp/${MOUNT_EBS_SCRIPT_LINUX.Key}.zip\n` + + // Install MongoDB + `mkdir -p $(dirname '/tmp/${INSTALL_MONGODB_3_6_SCRIPT_LINUX.Key}.sh')\n` + + 'aws s3 cp \'s3://', + { + 'Fn::Sub': INSTALL_MONGODB_3_6_SCRIPT_LINUX.Bucket, + }, + `/${INSTALL_MONGODB_3_6_SCRIPT_LINUX.Key}.sh' '/tmp/${INSTALL_MONGODB_3_6_SCRIPT_LINUX.Key}.sh'\n` + + `bash /tmp/${INSTALL_MONGODB_3_6_SCRIPT_LINUX.Key}.sh\n` + + // Fetching the MongoDB configuration scripts + `mkdir -p $(dirname '/tmp/${MONGODB_3_6_CONFIGURATION_SCRIPTS.Key}.zip')\n` + + 'aws s3 cp \'s3://', + { + 'Fn::Sub': MONGODB_3_6_CONFIGURATION_SCRIPTS.Bucket, + }, + `/${MONGODB_3_6_CONFIGURATION_SCRIPTS.Key}.zip' '/tmp/${MONGODB_3_6_CONFIGURATION_SCRIPTS.Key}.zip'\n` + + // Configure MongoDB + 'which mongod && test -f /etc/mongod.conf\n' + + 'sudo service mongod stop\n' + + 'MONGO_SETUP_DIR=$(mktemp -d)\n' + + 'mkdir -p "${MONGO_SETUP_DIR}"\n' + + 'sudo mount -t tmpfs -o size=50M tmpfs "${MONGO_SETUP_DIR}"\n' + + 'pushd "${MONGO_SETUP_DIR}"\n' + + `unzip /tmp/${MONGODB_3_6_CONFIGURATION_SCRIPTS.Key}.zip\n` + + 'cp /etc/mongod.conf .\n' + + // Getting the server certificate + 'bash serverCertFromSecrets.sh \"', + { + 'Fn::GetAtt': [ + 'ServerCert', + 'Cert', + ], + }, + '" "', + { + 'Fn::GetAtt': [ + 'ServerCert', + 'CertChain', + ], + }, + '" "', + { + 'Fn::GetAtt': [ + 'ServerCert', + 'Key', + ], + }, + '" "', + { + Ref: Match.stringLikeRegexp('^ServerCertPassphrase.*'), + }, + '"\n' + + // Set mongodb certificates and credentials + 'sudo mkdir -p /etc/mongod_certs\n' + + 'sudo mv ./ca.crt ./key.pem /etc/mongod_certs\n' + + 'sudo chown root.mongod -R /etc/mongod_certs/\n' + + 'sudo chmod 640 -R /etc/mongod_certs/\n' + + 'sudo chmod 750 /etc/mongod_certs/\n' + + 'sudo chown mongod.mongod -R /var/lib/mongo\n' + + 'bash ./setMongoLimits.sh\n' + + 'bash ./setStoragePath.sh "/var/lib/mongo"\n' + + 'bash ./setMongoNoAuth.sh\n' + + 'sudo service mongod start\n' + + 'bash ./setAdminCredentials.sh \"', + { + Ref: Match.stringLikeRegexp('^MongoDbInstanceAdminUser.*'), + }, + '"\n' + + // Setup for live deployment, and start mongod + 'sudo service mongod stop\n' + + 'bash ./setLiveConfiguration.sh\n' + + 'sudo systemctl enable mongod\n' + + 'sudo service mongod start\n' + + 'popd', + ]), + ], + }, + }, + }); // Make sure all the required public members are set expect(instance.version).toBe(version); @@ -449,9 +536,9 @@ describe('Test MongoDbInstance', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { InstanceType: expectedInstanceType, - })); + }); }); test('allowing ssh connection with key name', () => { @@ -472,9 +559,9 @@ describe('Test MongoDbInstance', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { KeyName: expectedKeyName, - })); + }); }); test('using custom admin user works correctly', () => { @@ -530,7 +617,7 @@ describe('Test MongoDbInstance', () => { }); // THEN - cdkExpect(stack).to(countResources('AWS::EC2::SecurityGroup', 1)); + Template.fromStack(stack).resourceCountIs('AWS::EC2::SecurityGroup', 1); }); test('setting role works correctly', () => { @@ -581,7 +668,7 @@ describe('Test MongoDbInstance', () => { }); // THEN - cdkExpect(stack).to(countResources('AWS::EC2::Volume', 1)); + Template.fromStack(stack).resourceCountIs('AWS::EC2::Volume', 1); }); test('setting custom encryption key for data volume works correctly', () => { @@ -609,14 +696,14 @@ describe('Test MongoDbInstance', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('AWS::EC2::Volume', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Volume', { Encrypted: true, - KmsKeyId: objectLike({ - 'Fn::GetAtt': arrayWith( + KmsKeyId: Match.objectLike({ + 'Fn::GetAtt': Match.arrayWith([ 'Key961B73FD', - ), + ]), }), - })); + }); }); test('setting custom size for data volume works correctly', () => { @@ -641,9 +728,9 @@ describe('Test MongoDbInstance', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('AWS::EC2::Volume', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Volume', { Size: volumeSize, - })); + }); }); test('setting LogGroup bucket name enables export to S3', () => { @@ -665,11 +752,11 @@ describe('Test MongoDbInstance', () => { }, }); - cdkExpect(stack).to(haveResource('AWS::Events::Rule', { - Targets: arrayWith(objectLike({ + Template.fromStack(stack).hasResourceProperties('AWS::Events::Rule', { + Targets: Match.arrayWith([Match.objectLike({ Input: '{\"BucketName\":\"' + bucketName + '\",\"ExportFrequencyInHours\":1,\"LogGroupName\":\"/renderfarm/MongoDbInstance\",\"RetentionInHours\":72}', - })), - })); + })]), + }); }); test.each([ @@ -695,9 +782,9 @@ describe('Test MongoDbInstance', () => { }); // THEN - cdkExpect(stack).to(haveResource('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { LogGroupName: testPrefix + id, - })); + }); }); test('is created with correct LogGroup retention', () => { @@ -720,9 +807,9 @@ describe('Test MongoDbInstance', () => { }); // THEN - cdkExpect(stack).to(haveResource('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { RetentionInDays: retention, - })); + }); }); test('adds security group', () => { @@ -745,9 +832,9 @@ describe('Test MongoDbInstance', () => { instance.addSecurityGroup(securityGroup); // THEN - cdkExpect(stack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { - SecurityGroups: arrayWith(stack.resolve(securityGroup.securityGroupId)), - })); + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { + SecurityGroups: Match.arrayWith([stack.resolve(securityGroup.securityGroupId)]), + }); }); testConstructTags({ diff --git a/packages/aws-rfdk/lib/core/test/mongodb-post-install.test.ts b/packages/aws-rfdk/lib/core/test/mongodb-post-install.test.ts index 85e165493..83cb4d2f4 100644 --- a/packages/aws-rfdk/lib/core/test/mongodb-post-install.test.ts +++ b/packages/aws-rfdk/lib/core/test/mongodb-post-install.test.ts @@ -4,24 +4,22 @@ */ import { - expect as cdkExpect, - haveResource, - haveResourceLike, - ResourcePart, -} from '@aws-cdk/assert'; + Stack, +} from 'aws-cdk-lib'; +import { + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { Vpc, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { PrivateHostedZone, -} from '@aws-cdk/aws-route53'; +} from 'aws-cdk-lib/aws-route53'; import { ISecret, Secret, -} from '@aws-cdk/aws-secretsmanager'; -import { - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-secretsmanager'; import { MongoDbUsers, @@ -112,7 +110,7 @@ describe('MongoDbPostInstall', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'mongodb.configureMongo', Environment: { Variables: { @@ -138,12 +136,12 @@ describe('MongoDbPostInstall', () => { }, ], }, - })); + }); // Lambda role can get the required secrets. - cdkExpect(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: [ + Statement: Match.arrayWith([ { Action: [ 'secretsmanager:GetSecretValue', @@ -183,11 +181,11 @@ describe('MongoDbPostInstall', () => { Effect: 'Allow', Resource: pwUser2Arn, }, - ], + ]), }, - })); + }); - cdkExpect(stack).to(haveResourceLike('Custom::RFDK_MongoDbPostInstallSetup', { + Template.fromStack(stack).hasResource('Custom::RFDK_MongoDbPostInstallSetup', { Properties: { Connection: { Hostname: 'mongodb.testZone.internal', @@ -222,7 +220,7 @@ describe('MongoDbPostInstall', () => { 'MongoPostInstallLambdaServiceRoleDefaultPolicy8B1C1CE8', 'MongoPostInstallLambdaServiceRoleCD03B9B9', ], - }, ResourcePart.CompleteDefinition)); + }); }); test('created correctly: only password users', () => { @@ -240,7 +238,7 @@ describe('MongoDbPostInstall', () => { // THEN // Lambda role can get the required secrets. - cdkExpect(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -284,9 +282,9 @@ describe('MongoDbPostInstall', () => { }, ], }, - })); + }); - cdkExpect(stack).to(haveResource('Custom::RFDK_MongoDbPostInstallSetup', { + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_MongoDbPostInstallSetup', { Connection: { Hostname: 'mongodb.testZone.internal', Port: '27017', @@ -304,7 +302,7 @@ describe('MongoDbPostInstall', () => { pwUser1Arn, pwUser2Arn, ], - })); + }); }); test('created correctly: only x509 users', () => { @@ -321,7 +319,7 @@ describe('MongoDbPostInstall', () => { }); // THEN - cdkExpect(stack).to(haveResource('Custom::RFDK_MongoDbPostInstallSetup', { + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_MongoDbPostInstallSetup', { Connection: { Hostname: 'mongodb.testZone.internal', Port: '27017', @@ -345,7 +343,7 @@ describe('MongoDbPostInstall', () => { Roles: x509User2.roles, }, ], - })); + }); }); test('use selected subnets', () => { @@ -364,7 +362,7 @@ describe('MongoDbPostInstall', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'mongodb.configureMongo', VpcConfig: { SubnetIds: [ @@ -373,7 +371,7 @@ describe('MongoDbPostInstall', () => { }, ], }, - })); + }); }); test('assert bad x509 role', () => { diff --git a/packages/aws-rfdk/lib/core/test/mountable-ebs.test.ts b/packages/aws-rfdk/lib/core/test/mountable-ebs.test.ts index 570ffd7f7..98bf3befb 100644 --- a/packages/aws-rfdk/lib/core/test/mountable-ebs.test.ts +++ b/packages/aws-rfdk/lib/core/test/mountable-ebs.test.ts @@ -4,9 +4,13 @@ */ import { - expect as cdkExpect, - haveResourceLike, -} from '@aws-cdk/assert'; + Size, + Stack, +} from 'aws-cdk-lib'; +import { + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { AmazonLinuxGeneration, Instance, @@ -15,11 +19,7 @@ import { Volume, Vpc, WindowsVersion, -} from '@aws-cdk/aws-ec2'; -import { - Size, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; import { BlockVolumeFormat, @@ -69,9 +69,9 @@ describe('Test MountableBlockVolume', () => { // THEN // Make sure the instance role has the correct permissions to get & run the script - cdkExpect(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: [ + Statement: Match.arrayWith([ { Effect: 'Allow', Action: 'ec2:DescribeVolumes', @@ -149,7 +149,7 @@ describe('Test MountableBlockVolume', () => { }, ':s3:::', { - Ref: MOUNT_EBS_SCRIPT_LINUX.Bucket, + 'Fn::Sub': MOUNT_EBS_SCRIPT_LINUX.Bucket, }, ], ], @@ -164,7 +164,7 @@ describe('Test MountableBlockVolume', () => { }, ':s3:::', { - Ref: MOUNT_EBS_SCRIPT_LINUX.Bucket, + 'Fn::Sub': MOUNT_EBS_SCRIPT_LINUX.Bucket, }, '/*', ], @@ -172,14 +172,14 @@ describe('Test MountableBlockVolume', () => { }, ], }, - ], + ]), }, - })); + }); // Make sure we download the mountEFS script asset bundle - const s3Copy = 'aws s3 cp \'s3://${Token[TOKEN.\\d+]}/${Token[TOKEN.\\d+]}${Token[TOKEN.\\d+]}\' \'/tmp/${Token[TOKEN.\\d+]}${Token[TOKEN.\\d+]}\''; + const s3Copy = `aws s3 cp 's3://\${Token[TOKEN.\\d+]}/${MOUNT_EBS_SCRIPT_LINUX.Key}.zip' '/tmp/${MOUNT_EBS_SCRIPT_LINUX.Key}.zip'`; expect(userData).toMatch(new RegExp(escapeTokenRegex(s3Copy))); - expect(userData).toMatch(new RegExp(escapeTokenRegex('unzip /tmp/${Token[TOKEN.\\d+]}${Token[TOKEN.\\d+]}'))); - // Make sure we execute the script with the correct args + expect(userData).toMatch(new RegExp(escapeTokenRegex(`unzip /tmp/${MOUNT_EBS_SCRIPT_LINUX.Key}.zip`))); + // Make sure we run the script with the correct args expect(userData).toMatch(new RegExp(escapeTokenRegex('bash ./mountEbsBlockVolume.sh ${Token[TOKEN.\\d+]} xfs /mnt/fs rw'))); }); @@ -300,7 +300,7 @@ describe('Test MountableBlockVolume', () => { location: '/mnt/fs', }); const userData = instance.userData.render(); - const s3Copy = 'aws s3 cp \'s3://${Token[TOKEN.\\d+]}/${Token[TOKEN.\\d+]}${Token[TOKEN.\\d+]}\''; + const s3Copy = `aws s3 cp 's3://\${Token[TOKEN.\\d+]}/${MOUNT_EBS_SCRIPT_LINUX.Key}.zip'`; const regex = new RegExp(escapeTokenRegex(s3Copy), 'g'); const matches = userData.match(regex) ?? []; diff --git a/packages/aws-rfdk/lib/core/test/mountable-efs.test.ts b/packages/aws-rfdk/lib/core/test/mountable-efs.test.ts index 2be862a15..9e2babacc 100644 --- a/packages/aws-rfdk/lib/core/test/mountable-efs.test.ts +++ b/packages/aws-rfdk/lib/core/test/mountable-efs.test.ts @@ -4,11 +4,15 @@ */ import { - arrayWith, - expect as cdkExpect, - haveResourceLike, - objectLike, -} from '@aws-cdk/assert'; + Arn, + App, + CfnResource, + Stack, +} from 'aws-cdk-lib'; +import { + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { AmazonLinuxGeneration, Instance, @@ -16,14 +20,8 @@ import { MachineImage, Vpc, WindowsVersion, -} from '@aws-cdk/aws-ec2'; -import * as efs from '@aws-cdk/aws-efs'; -import { - Arn, - App, - CfnResource, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; +import * as efs from 'aws-cdk-lib/aws-efs'; import { MountableEfs, @@ -34,6 +32,9 @@ import { MountPermissionsHelper, } from '../lib/mount-permissions-helper'; +import { + MOUNT_EFS_SCRIPT_LINUX, +} from './asset-constants'; import { escapeTokenRegex, } from './token-regex-helpers'; @@ -71,7 +72,7 @@ describe('Test MountableEFS', () => { // THEN // Make sure the instance has been granted ingress to the EFS's security group - cdkExpect(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', FromPort: 2049, ToPort: 2049, @@ -87,11 +88,11 @@ describe('Test MountableEFS', () => { 'GroupId', ], }, - })); + }); // Make sure we download the mountEfs script asset bundle - const s3Copy = 'aws s3 cp \'s3://${Token[TOKEN.\\d+]}/${Token[TOKEN.\\d+]}${Token[TOKEN.\\d+]}\' \'/tmp/${Token[TOKEN.\\d+]}${Token[TOKEN.\\d+]}\''; + const s3Copy = `aws s3 cp 's3://\${Token[TOKEN.\\d+]}/${MOUNT_EFS_SCRIPT_LINUX.Key}.zip' '/tmp/${MOUNT_EFS_SCRIPT_LINUX.Key}.zip'`; expect(userData).toMatch(new RegExp(escapeTokenRegex(s3Copy))); - expect(userData).toMatch(new RegExp(escapeTokenRegex('unzip /tmp/${Token[TOKEN.\\d+]}${Token[TOKEN.\\d+]}'))); + expect(userData).toMatch(new RegExp(escapeTokenRegex(`unzip /tmp/${MOUNT_EFS_SCRIPT_LINUX.Key}.zip`))); // Make sure we execute the script with the correct args expect(userData).toMatch(new RegExp(escapeTokenRegex('bash ./mountEfs.sh ${Token[TOKEN.\\d+]} /mnt/efs/fs1 false rw'))); }); @@ -216,9 +217,9 @@ describe('Test MountableEFS', () => { }); test('grants IAM access point permissions', () => { - cdkExpect(stack).to(haveResourceLike('AWS::IAM::Policy', { - PolicyDocument: objectLike({ - Statement: arrayWith( + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: Match.objectLike({ + Statement: Match.arrayWith([ { Action: expectedActions.length === 1 ? expectedActions[0] : expectedActions, Condition: { @@ -229,14 +230,14 @@ describe('Test MountableEFS', () => { Effect: 'Allow', Resource: stack.resolve((efsFS.node.defaultChild as efs.CfnFileSystem).attrArn), }, - ), + ]), Version: '2012-10-17', }), - Roles: arrayWith( + Roles: Match.arrayWith([ // The Policy construct micro-optimizes the reference to a role in the same stack using its logical ID stack.resolve((instance.role.node.defaultChild as CfnResource).ref), - ), - })); + ]), + }); }); }); }); @@ -278,7 +279,7 @@ describe('Test MountableEFS', () => { location: '/mnt/efs/fs1', }); const userData = instance.userData.render(); - const s3Copy = 'aws s3 cp \'s3://${Token[TOKEN.\\d+]}/${Token[TOKEN.\\d+]}${Token[TOKEN.\\d+]}\''; + const s3Copy = `aws s3 cp 's3://\${Token[TOKEN.\\d+]}/${MOUNT_EFS_SCRIPT_LINUX.Key}.zip'`; const regex = new RegExp(escapeTokenRegex(s3Copy), 'g'); const matches = userData.match(regex) ?? []; @@ -326,20 +327,20 @@ describe('Test MountableEFS', () => { if (accessPoint) { expectedResources.push(stack.resolve(accessPoint?.accessPointArn)); } - cdkExpect(stack).to(haveResourceLike('AWS::IAM::Policy', { - PolicyDocument: objectLike({ - Statement: arrayWith( + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: Match.objectLike({ + Statement: Match.arrayWith([ { Action: 'elasticfilesystem:DescribeMountTargets', Effect: 'Allow', Resource: expectedResources.length == 1 ? expectedResources[0] : expectedResources, }, - ), + ]), }), - Roles: arrayWith( + Roles: Match.arrayWith([ stack.resolve((instance.role.node.defaultChild as CfnResource).ref), - ), - })); + ]), + }); }); }); }); diff --git a/packages/aws-rfdk/lib/core/test/mountable-fsx-lustre.test.ts b/packages/aws-rfdk/lib/core/test/mountable-fsx-lustre.test.ts index 53e67219e..a522c4753 100644 --- a/packages/aws-rfdk/lib/core/test/mountable-fsx-lustre.test.ts +++ b/packages/aws-rfdk/lib/core/test/mountable-fsx-lustre.test.ts @@ -4,9 +4,12 @@ */ import { - expect as cdkExpect, - haveResourceLike, -} from '@aws-cdk/assert'; + App, + Stack, +} from 'aws-cdk-lib'; +import { + Template, +} from 'aws-cdk-lib/assertions'; import { AmazonLinuxGeneration, Instance, @@ -15,18 +18,17 @@ import { SecurityGroup, Vpc, WindowsVersion, -} from '@aws-cdk/aws-ec2'; -import * as fsx from '@aws-cdk/aws-fsx'; -import { - App, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; +import * as fsx from 'aws-cdk-lib/aws-fsx'; import { MountableFsxLustre, MountPermissions, } from '../lib'; +import { + MOUNT_FSX_SCRIPT_LINUX, +} from './asset-constants'; import { escapeTokenRegex, } from './token-regex-helpers'; @@ -81,17 +83,17 @@ describe('MountableFsxLustre', () => { // THEN // Make sure the instance has been granted ingress to the FSxL's security group - cdkExpect(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', FromPort: 988, ToPort: 1023, SourceSecurityGroupId: stack.resolve(instanceSecurityGroup.securityGroupId), GroupId: stack.resolve(fsSecurityGroup.securityGroupId), - })); + }); // Make sure we download the mountFsxLustre script asset bundle - const s3Copy = 'aws s3 cp \'s3://${Token[TOKEN.\\d+]}/${Token[TOKEN.\\d+]}${Token[TOKEN.\\d+]}\' \'/tmp/${Token[TOKEN.\\d+]}${Token[TOKEN.\\d+]}\''; + const s3Copy = `aws s3 cp 's3://\${Token[TOKEN.\\d+]}/${MOUNT_FSX_SCRIPT_LINUX.Key}.zip' '/tmp/${MOUNT_FSX_SCRIPT_LINUX.Key}.zip'`; expect(userData).toMatch(new RegExp(escapeTokenRegex(s3Copy))); - expect(userData).toMatch(new RegExp(escapeTokenRegex('unzip /tmp/${Token[TOKEN.\\d+]}${Token[TOKEN.\\d+]}'))); + expect(userData).toMatch(new RegExp(escapeTokenRegex(`unzip /tmp/${MOUNT_FSX_SCRIPT_LINUX.Key}.zip`))); // Make sure we install the Lustre client expect(userData).toMatch('bash ./installLustreClient.sh'); // Make sure we execute the script with the correct args @@ -172,7 +174,7 @@ describe('MountableFsxLustre', () => { location: '/mnt/fsx/fs1', }); const userData = instance.userData.render(); - const s3Copy = 'aws s3 cp \'s3://${Token[TOKEN.\\d+]}/${Token[TOKEN.\\d+]}${Token[TOKEN.\\d+]}\''; + const s3Copy = `aws s3 cp 's3://\${Token[TOKEN.\\d+]}/${MOUNT_FSX_SCRIPT_LINUX.Key}.zip'`; const regex = new RegExp(escapeTokenRegex(s3Copy), 'g'); const matches = userData.match(regex) ?? []; diff --git a/packages/aws-rfdk/lib/core/test/pad-efs-storage.test.ts b/packages/aws-rfdk/lib/core/test/pad-efs-storage.test.ts index 32eb23ee4..90d8024f1 100644 --- a/packages/aws-rfdk/lib/core/test/pad-efs-storage.test.ts +++ b/packages/aws-rfdk/lib/core/test/pad-efs-storage.test.ts @@ -4,28 +4,27 @@ */ import { - arrayWith, - expect as cdkExpect, - haveResourceLike, - ResourcePart, -} from '@aws-cdk/assert'; + App, + CfnElement, + Size, + Stack, +} from 'aws-cdk-lib'; +import { + Annotations, + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { SecurityGroup, Vpc, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { AccessPoint, FileSystem as EfsFileSystem, -} from '@aws-cdk/aws-efs'; +} from 'aws-cdk-lib/aws-efs'; import { Function as LambdaFunction, -} from '@aws-cdk/aws-lambda'; -import { - App, - CfnElement, - Size, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-lambda'; import { PadEfsStorage, } from '../lib/pad-efs-storage'; @@ -70,7 +69,7 @@ describe('Test PadEfsStorage', () => { const padFilesystem = pad.node.findChild('PadFilesystem') as LambdaFunction; // THEN - cdkExpect(stack).to(haveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResource('AWS::Lambda::Function', { Properties: { FileSystemConfigs: [ { @@ -93,9 +92,9 @@ describe('Test PadEfsStorage', () => { ], }, }, - DependsOn: arrayWith(stack.getLogicalId(accessPoint.node.defaultChild as CfnElement)), - }, ResourcePart.CompleteDefinition)); - cdkExpect(stack).to(haveResourceLike('AWS::Lambda::Function', { + DependsOn: Match.arrayWith([stack.getLogicalId(accessPoint.node.defaultChild as CfnElement)]), + }); + Template.fromStack(stack).hasResource('AWS::Lambda::Function', { Properties: { FileSystemConfigs: [ { @@ -118,8 +117,8 @@ describe('Test PadEfsStorage', () => { ], }, }, - DependsOn: arrayWith(stack.getLogicalId(accessPoint.node.defaultChild as CfnElement)), - }, ResourcePart.CompleteDefinition)); + DependsOn: Match.arrayWith([stack.getLogicalId(accessPoint.node.defaultChild as CfnElement)]), + }); const lambdaRetryCatch = { Retry: [ @@ -141,7 +140,7 @@ describe('Test PadEfsStorage', () => { }, ], }; - cdkExpect(stack).to(haveResourceLike('AWS::StepFunctions::StateMachine', { + Template.fromStack(stack).hasResourceProperties('AWS::StepFunctions::StateMachine', { DefinitionString: stack.resolve(JSON.stringify({ StartAt: 'QueryDiskUsage', States: { @@ -217,9 +216,9 @@ describe('Test PadEfsStorage', () => { }, }, })), - })); + }); - cdkExpect(stack).to(haveResourceLike('Custom::AWS', { + Template.fromStack(stack).hasResourceProperties('Custom::AWS', { Create: { 'Fn::Join': [ '', @@ -252,7 +251,7 @@ describe('Test PadEfsStorage', () => { ], ], }, - })); + }); }); test('Set desiredPadding', () => { @@ -265,20 +264,20 @@ describe('Test PadEfsStorage', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('Custom::AWS', { + Template.fromStack(stack).hasResourceProperties('Custom::AWS', { Create: { 'Fn::Join': [ '', - arrayWith(`","input":"{\\"desiredPadding\\":${desiredPadding}}"}}`), + Match.arrayWith([`","input":"{\\"desiredPadding\\":${desiredPadding}}"}}`]), ], }, Update: { 'Fn::Join': [ '', - arrayWith(`","input":"{\\"desiredPadding\\":${desiredPadding}}"}}`), + Match.arrayWith([`","input":"{\\"desiredPadding\\":${desiredPadding}}"}}`]), ], }, - })); + }); }); test('Throws on bad desiredPadding', () => { @@ -290,14 +289,7 @@ describe('Test PadEfsStorage', () => { }); // THEN - expect(pad.node.metadataEntry).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - type: 'aws:cdk:error', - data: 'Failed to round desiredSize to an integer number of GiB. The size must be in GiB.', - }), - ]), - ); + Annotations.fromStack(stack).hasError(`/${pad.node.path}`, 'Failed to round desiredSize to an integer number of GiB. The size must be in GiB.'); }); test('Provide SecurityGroup', () => { @@ -315,18 +307,18 @@ describe('Test PadEfsStorage', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'pad-efs-storage.getDiskUsage', VpcConfig: { SecurityGroupIds: [ stack.resolve(sg.securityGroupId) ], }, - })); - cdkExpect(stack).to(haveResourceLike('AWS::Lambda::Function', { + }); + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'pad-efs-storage.padFilesystem', VpcConfig: { SecurityGroupIds: [ stack.resolve(sg.securityGroupId) ], }, - })); + }); }); }); diff --git a/packages/aws-rfdk/lib/core/test/script-assets.test.ts b/packages/aws-rfdk/lib/core/test/script-assets.test.ts index b82797f8d..f8dd9c45a 100644 --- a/packages/aws-rfdk/lib/core/test/script-assets.test.ts +++ b/packages/aws-rfdk/lib/core/test/script-assets.test.ts @@ -5,7 +5,11 @@ import * as path from 'path'; -import { expect as expectCDK, haveResource } from '@aws-cdk/assert'; +import { Stack } from 'aws-cdk-lib'; +import { + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { AmazonLinuxImage, Instance, @@ -15,8 +19,7 @@ import { Vpc, WindowsImage, WindowsVersion, -} from '@aws-cdk/aws-ec2'; -import { Stack } from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; import { ScriptAsset } from '../lib/script-assets'; @@ -54,9 +57,9 @@ describe('executeScriptAsset', () => { asset.executeOn({ host: instance }); // THEN - expectCDK(stack).to(haveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: [ + Statement: Match.arrayWith([ { Action: [ 's3:GetObject*', @@ -72,7 +75,7 @@ describe('executeScriptAsset', () => { 'arn:', { Ref: 'AWS::Partition' }, ':s3:::', - { Ref: bucketKey }, + { 'Fn::Sub': bucketKey }, ], ], }, @@ -83,19 +86,19 @@ describe('executeScriptAsset', () => { 'arn:', { Ref: 'AWS::Partition' }, ':s3:::', - { Ref: bucketKey }, + { 'Fn::Sub': bucketKey }, '/*', ], ], }, ], }, - ], + ]), Version: '2012-10-17', }, PolicyName: 'instInstanceRoleDefaultPolicyCB9E402C', Roles: [ { Ref: 'instInstanceRoleFE783FB1' } ], - })); + }); }); test('downloads and executes script for linux', () => { @@ -116,135 +119,22 @@ describe('executeScriptAsset', () => { }); // THEN - expectCDK(stack).to(haveResource('AWS::EC2::Instance', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { UserData: { 'Fn::Base64': { 'Fn::Join': [ '', [ - "#!/bin/bash\nmkdir -p $(dirname '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - "')\naws s3 cp 's3://", - { Ref: CWA_ASSET_LINUX.Bucket }, - '/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - "' '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - "'\nset -e\nchmod +x '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, + `#!/bin/bash\nmkdir -p $(dirname '/tmp/${CWA_ASSET_LINUX.Key}.sh')\naws s3 cp 's3://`, { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - "'\n'/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], + 'Fn::Sub': CWA_ASSET_LINUX.Bucket, }, - "' arg1", + `/${CWA_ASSET_LINUX.Key}.sh' '/tmp/${CWA_ASSET_LINUX.Key}.sh'\nset -e\nchmod +x '/tmp/${CWA_ASSET_LINUX.Key}.sh'\n'/tmp/${CWA_ASSET_LINUX.Key}.sh' arg1`, ], ], }, }, - })); + }); }); test('downloads and executes script for windows', () => { @@ -265,134 +155,22 @@ describe('executeScriptAsset', () => { }); // THEN - expectCDK(stack).to(haveResource('AWS::EC2::Instance', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { UserData: { 'Fn::Base64': { 'Fn::Join': [ '', [ - "mkdir (Split-Path -Path 'C:/temp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - "' ) -ea 0\nRead-S3Object -BucketName '", - { Ref: CWA_ASSET_WINDOWS.Bucket }, - "' -key '", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - "' -file 'C:/temp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - "' -ErrorAction Stop\n&'C:/temp/", + `mkdir (Split-Path -Path 'C:/temp/${CWA_ASSET_WINDOWS.Key}.ps1' ) -ea 0\nRead-S3Object -BucketName '`, { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], + 'Fn::Sub': CWA_ASSET_WINDOWS.Bucket, }, - "' arg1\nif (!$?) { Write-Error 'Failed to execute the file \"C:/temp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - "\"' -ErrorAction Stop }", + `' -key '${CWA_ASSET_WINDOWS.Key}.ps1' -file 'C:/temp/${CWA_ASSET_WINDOWS.Key}.ps1' -ErrorAction Stop\n` + + `&'C:/temp/${CWA_ASSET_WINDOWS.Key}.ps1' arg1\nif (!$?) { Write-Error 'Failed to execute the file "C:/temp/${CWA_ASSET_WINDOWS.Key}.ps1"' -ErrorAction Stop }`, ], ], }, }, - })); + }); }); }); diff --git a/packages/aws-rfdk/lib/core/test/sessions-manager-helper.test.ts b/packages/aws-rfdk/lib/core/test/sessions-manager-helper.test.ts index cb9d2eb6e..108ed67bd 100644 --- a/packages/aws-rfdk/lib/core/test/sessions-manager-helper.test.ts +++ b/packages/aws-rfdk/lib/core/test/sessions-manager-helper.test.ts @@ -3,13 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { CfnElement, Stack } from 'aws-cdk-lib'; import { - expect as expectCDK, - haveResourceLike, -} from '@aws-cdk/assert'; + Template, +} from 'aws-cdk-lib/assertions'; import { AutoScalingGroup, -} from '@aws-cdk/aws-autoscaling'; +} from 'aws-cdk-lib/aws-autoscaling'; import { AmazonLinuxImage, Instance, @@ -17,8 +17,7 @@ import { InstanceSize, InstanceType, Vpc, -} from '@aws-cdk/aws-ec2'; -import { CfnElement, Stack } from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; import { SessionManagerHelper } from '../lib'; @@ -42,7 +41,7 @@ test('Grant SSM permissions to Instance', () => { const instanceRole = stack.getLogicalId(instance.role.node.defaultChild as CfnElement); - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -59,7 +58,7 @@ test('Grant SSM permissions to Instance', () => { ], }, Roles: [{ Ref: instanceRole }], - })); + }); }); test('Grant SSM permissions to ASG', () => { @@ -72,7 +71,7 @@ test('Grant SSM permissions to ASG', () => { const asgRole = stack.getLogicalId(asg.role.node.defaultChild as CfnElement); - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -89,5 +88,5 @@ test('Grant SSM permissions to ASG', () => { ], }, Roles: [{ Ref: asgRole }], - })); + }); }); diff --git a/packages/aws-rfdk/lib/core/test/staticip-server.test.ts b/packages/aws-rfdk/lib/core/test/staticip-server.test.ts index f0a6564b3..505e06d74 100644 --- a/packages/aws-rfdk/lib/core/test/staticip-server.test.ts +++ b/packages/aws-rfdk/lib/core/test/staticip-server.test.ts @@ -4,27 +4,23 @@ */ import { - arrayWith, - countResources, - countResourcesLike, - expect as cdkExpect, - haveResourceLike, - objectLike, - ResourcePart, -} from '@aws-cdk/assert'; + App, + Duration, + Stack, +} from 'aws-cdk-lib'; +import { + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { AmazonLinuxGeneration, InstanceType, MachineImage, SubnetType, Vpc, -} from '@aws-cdk/aws-ec2'; -import { - App, - Duration, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; import {StaticPrivateIpServer} from '../lib'; +import {resourcePropertiesCountIs} from './test-helper'; describe('Test StaticIpServer', () => { let stack: Stack; @@ -45,58 +41,68 @@ describe('Test StaticIpServer', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(stack).hasResource('AWS::AutoScaling::AutoScalingGroup', { Properties: { MinSize: '1', MaxSize: '1', - LifecycleHookSpecificationList: arrayWith(objectLike({ - DefaultResult: 'ABANDON', - HeartbeatTimeout: 120, - LifecycleHookName: 'NewStaticPrivateIpServer', - LifecycleTransition: 'autoscaling:EC2_INSTANCE_LAUNCHING', - NotificationMetadata: { - 'Fn::Join': arrayWith([ - '{\"eniId\":\"', - { - Ref: 'InstanceEniA230F5FE', - }, - '\"}', - ]), - }, - })), - Tags: arrayWith({ + LifecycleHookSpecificationList: Match.arrayWith([ + Match.objectLike({ + DefaultResult: 'ABANDON', + HeartbeatTimeout: 120, + LifecycleHookName: 'NewStaticPrivateIpServer', + LifecycleTransition: 'autoscaling:EC2_INSTANCE_LAUNCHING', + NotificationMetadata: { + 'Fn::Join': [ + '', + Match.arrayWith([ + '{"eniId":"', + { + Ref: 'InstanceEniA230F5FE', + }, + '"}', + ]), + ], + }, + }), + ]), + Tags: Match.arrayWith([{ Key: 'RfdkStaticPrivateIpServerGrantConditionKey', PropagateAtLaunch: true, Value: 'StackNameAttachEniToInstance83a5dca5db544aa485d28d419cdf85ceF20CDF73', - }), + }]), }, - DependsOn: arrayWith( + DependsOn: Match.arrayWith([ 'AttachEniToInstance83a5dca5db544aa485d28d419cdf85ceAttachEniNotificationTopicc8b1e9a6783c4954b191204dd5e3b9e0695D3E7F', // The SNS Topic Subscription; this is key. 'InstanceEniA230F5FE', // The NetWorkInterface. Also key. - ), - }, ResourcePart.CompleteDefinition)); + ]), + UpdatePolicy: { + AutoScalingScheduledAction: { + IgnoreUnmodifiedGroupSizeProperties: true, + }, + }, + }); - cdkExpect(stack).to(haveResourceLike('AWS::EC2::NetworkInterface', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::NetworkInterface', { Description: 'Static ENI for StackName/Instance', - GroupSet: arrayWith({ + GroupSet: Match.arrayWith([{ 'Fn::GetAtt': [ 'InstanceAsgInstanceSecurityGroup2DB1DA8B', 'GroupId', ], - }), - })); + }]), + }); - cdkExpect(stack).to(haveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'index.handler', Runtime: 'nodejs16.x', Description: 'Created by RFDK StaticPrivateIpServer to process instance launch lifecycle events in stack \'StackName\'. This lambda attaches an ENI to newly launched instances.', - })); + }); - cdkExpect(stack).to(haveResourceLike('AWS::SNS::Topic', { + Template.fromStack(stack).hasResourceProperties('AWS::SNS::Topic', { DisplayName: 'For RFDK instance-launch notifications for stack \'StackName\'', - })); + }); - cdkExpect(stack).to(haveResourceLike('AWS::SNS::Subscription', { + Template.fromStack(stack).hasResourceProperties('AWS::SNS::Subscription', { Protocol: 'lambda', TopicArn: { Ref: 'AttachEniNotificationTopicc8b1e9a6783c4954b191204dd5e3b9e0F5D22665', @@ -107,13 +113,13 @@ describe('Test StaticIpServer', () => { 'Arn', ], }, - })); + }); // The Lambda's policy should allow ENI attachment & condition-limited CompleteLifecycle. - cdkExpect(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith( - objectLike({ + Statement: Match.arrayWith([ + Match.objectLike({ Action: 'autoscaling:CompleteLifecycleAction', Effect: 'Allow', Condition: { @@ -142,7 +148,7 @@ describe('Test StaticIpServer', () => { ], }, }), - objectLike({ + Match.objectLike({ Effect: 'Allow', Action: [ 'ec2:DescribeNetworkInterfaces', @@ -150,14 +156,15 @@ describe('Test StaticIpServer', () => { ], Resource: '*', }), - ), + ]), }, - })); + }); // Count singleton objects - cdkExpect(stack).to(countResources('AWS::Lambda::Function', 2)); // Log retention & event handler. - cdkExpect(stack).to(countResources('AWS::SNS::Topic', 1)); - cdkExpect(stack).to(countResourcesLike('AWS::IAM::Role', 1, { + Template.fromStack(stack).resourceCountIs('AWS::Lambda::Function', 2); // Log retention & event handler. + Template.fromStack(stack).resourceCountIs('AWS::SNS::Topic', 1); + + resourcePropertiesCountIs(stack, 'AWS::IAM::Role', { AssumeRolePolicyDocument: { Statement: [ { @@ -169,8 +176,8 @@ describe('Test StaticIpServer', () => { }, ], }, - })); - cdkExpect(stack).to(countResourcesLike('AWS::IAM::Policy', 1, { + }, 1); + resourcePropertiesCountIs(stack, 'AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -182,7 +189,7 @@ describe('Test StaticIpServer', () => { }, ], }, - })); + }, 1); }); test('creates singleton resources', () => { @@ -200,18 +207,18 @@ describe('Test StaticIpServer', () => { // THEN // Make sure both ASGs are tagged to allow CompleteLifeCycle by the singleton lambda. - cdkExpect(stack).to(countResourcesLike('AWS::AutoScaling::AutoScalingGroup', 2, { - Tags: arrayWith({ + resourcePropertiesCountIs(stack, 'AWS::AutoScaling::AutoScalingGroup', { + Tags: Match.arrayWith([{ Key: 'RfdkStaticPrivateIpServerGrantConditionKey', PropagateAtLaunch: true, Value: 'StackNameAttachEniToInstance83a5dca5db544aa485d28d419cdf85ceF20CDF73', - }), - })); + }]), + }, 2); // Count singleton objects - cdkExpect(stack).to(countResources('AWS::Lambda::Function', 2)); // Log retention & event handler. - cdkExpect(stack).to(countResources('AWS::SNS::Topic', 1)); - cdkExpect(stack).to(countResourcesLike('AWS::IAM::Role', 1, { + Template.fromStack(stack).resourceCountIs('AWS::Lambda::Function', 2); // Log retention & event handler. + Template.fromStack(stack).resourceCountIs('AWS::SNS::Topic', 1); + resourcePropertiesCountIs(stack, 'AWS::IAM::Role', { AssumeRolePolicyDocument: { Statement: [ { @@ -223,7 +230,7 @@ describe('Test StaticIpServer', () => { }, ], }, - })); + }, 1); }); test('throw exception when no available subnets', () => { @@ -251,14 +258,14 @@ describe('Test StaticIpServer', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(stack).hasResource('AWS::AutoScaling::AutoScalingGroup', { CreationPolicy: { ResourceSignal: { Count: 1, Timeout: 'PT12H', }, }, - }, ResourcePart.CompleteDefinition)); + }); expect(() => { new StaticPrivateIpServer(stack, 'InstanceFail', { vpc, diff --git a/packages/aws-rfdk/lib/core/test/tag-helpers.ts b/packages/aws-rfdk/lib/core/test/tag-helpers.ts index 2a7f70de3..dcb24b3a6 100644 --- a/packages/aws-rfdk/lib/core/test/tag-helpers.ts +++ b/packages/aws-rfdk/lib/core/test/tag-helpers.ts @@ -3,14 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { - arrayWith, - countResourcesLike, - expect as expectCDK, -} from '@aws-cdk/assert'; import { Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib'; +import { + Match, +} from 'aws-cdk-lib/assertions'; + +import { resourcePropertiesCountIs } from './test-helper'; /** * The name of the tag that RFDK is expected to use @@ -67,18 +67,18 @@ export function resourceTagMatcher(resourceType: string, tagName: string, tagVal }; } else if (resourceType === 'AWS::AutoScaling::AutoScalingGroup') { return { - Tags: arrayWith({ + Tags: Match.arrayWith([{ Key: tagName, PropagateAtLaunch: true, Value: tagValue, - }), + }]), }; } else { return { - Tags: arrayWith({ + Tags: Match.arrayWith([{ Key: tagName, Value: tagValue, - }), + }]), }; } } @@ -137,6 +137,6 @@ export function testConstructTags(args: TestConstructTagsArgs) { const stack = createConstruct(); // THEN - expectCDK(stack).to(countResourcesLike(resourceType, expectedCount, expectedProps)); + resourcePropertiesCountIs(stack, resourceType, expectedProps, expectedCount); }); } \ No newline at end of file diff --git a/packages/aws-rfdk/lib/core/test/test-helper.ts b/packages/aws-rfdk/lib/core/test/test-helper.ts new file mode 100644 index 000000000..1b30c1b95 --- /dev/null +++ b/packages/aws-rfdk/lib/core/test/test-helper.ts @@ -0,0 +1,20 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + Stack, +} from 'aws-cdk-lib'; +import { + Match, + Template, +} from 'aws-cdk-lib/assertions'; + + +// CDKv2's assertion module doesn't have a Template.resourcePropertiesCountIs that would count +// the number of resources with the given properties. We add that here. +export function resourcePropertiesCountIs(stack: Stack, type: string, props: any, count: number): void { + const resources = Template.fromStack(stack).findResources(type, Match.objectLike({ Properties: props })); + expect(Object.keys(resources)).toHaveLength(count); +} \ No newline at end of file diff --git a/packages/aws-rfdk/lib/core/test/x509-certificate.test.ts b/packages/aws-rfdk/lib/core/test/x509-certificate.test.ts index 9c491bc90..8e29e1df0 100644 --- a/packages/aws-rfdk/lib/core/test/x509-certificate.test.ts +++ b/packages/aws-rfdk/lib/core/test/x509-certificate.test.ts @@ -4,19 +4,20 @@ */ import { - anything, - expect as expectCDK, - haveResource, - haveResourceLike, - InspectionFailure, -} from '@aws-cdk/assert'; + Lazy, + Stack, +} from 'aws-cdk-lib'; +import { + Annotations, + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { Role, ServicePrincipal, -} from '@aws-cdk/aws-iam'; -import { Key } from '@aws-cdk/aws-kms'; -import { CfnSecret } from '@aws-cdk/aws-secretsmanager'; -import { Stack } from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-iam'; +import { Key } from 'aws-cdk-lib/aws-kms'; +import { CfnSecret } from 'aws-cdk-lib/aws-secretsmanager'; import { X509CertificatePem, @@ -31,33 +32,32 @@ test('Generate cert', () => { const cert = new X509CertificatePem(stack, 'Cert', { subject, }); - const certPassphraseID = stack.getLogicalId(cert.passphrase.node.defaultChild as CfnSecret); // Expect the custom resource for cert generation - expectCDK(stack).to(haveResourceLike('Custom::RFDK_X509Generator', { + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_X509Generator', { DistinguishedName: { CN: 'testCN', O: 'AWS', OU: 'Thinkbox', }, - })); + }); // Cannot have a CertificateValidFor property if not given one. Adding one // would cause existing certificates to be re-generated on re-deploy, and thus // risk breaking customer's setups. - expectCDK(stack).notTo(haveResourceLike('Custom::RFDK_X509Generator', { - CertificateValidFor: anything(), + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_X509Generator', Match.not({ + CertificateValidFor: Match.anyValue(), })); // Expect the resource for converting to PKCS #12 not to be created - expectCDK(stack).notTo(haveResource('Custom::RFDK_X509_PKCS12')); + Template.fromStack(stack).resourceCountIs('Custom::RFDK_X509_PKCS12', 0); // Expect the DynamoDB table used for custom resource tracking - expectCDK(stack).to(haveResource('AWS::DynamoDB::Table')); - // Expect a Secret used to store the cert - expectCDK(stack).to(haveResource('AWS::SecretsManager::Secret')); + Template.fromStack(stack).resourceCountIs('AWS::DynamoDB::Table', 1); + // Expect a Secret used to store the cert passphrase + Template.fromStack(stack).resourceCountIs('AWS::SecretsManager::Secret', 1); // Expect a policy that can interact with DynamoDB and SecretsManager - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: [ - { + Statement: Match.arrayWith([ + Match.objectLike({ Action: [ 'dynamodb:BatchGetItem', 'dynamodb:GetRecords', @@ -70,21 +70,22 @@ test('Generate cert', () => { 'dynamodb:PutItem', 'dynamodb:UpdateItem', 'dynamodb:DeleteItem', + 'dynamodb:DescribeTable', ], - }, - { + }), + Match.objectLike({ Action: 'dynamodb:DescribeTable', - }, - { + }), + Match.objectLike({ Action: [ 'secretsmanager:GetSecretValue', 'secretsmanager:DescribeSecret', ], Resource: { - Ref: certPassphraseID, + Ref: Match.stringLikeRegexp('^CertPassphrase.*'), }, - }, - { + }), + Match.objectLike({ Action: [ 'secretsmanager:CreateSecret', 'secretsmanager:DeleteSecret', @@ -96,43 +97,31 @@ test('Generate cert', () => { 'secretsmanager:ResourceTag/X509SecretGrant-F53F5427': 'f53f5427b2e9eb4739661fcc0b249b6e', }, }, - }, - ], + }), + ]), }, - })); + }); // Expect no KMS key for encryption - expectCDK(stack).notTo(haveResource('AWS::KMS::Key')); + Template.fromStack(stack).resourceCountIs('AWS::KMS::Key', 0); // Expect Lambda for doing the cert generation to use the generate() handler and openssl layer - expectCDK(stack).to(haveResourceLike('AWS::Lambda::Function', (props: any, error: InspectionFailure): boolean => { - if (!props.Handler || props.Handler !== 'x509-certificate.generate') { - error.failureReason = 'x509-certificate.generate handler not found'; - error.resource = props.Handler; - return false; - } - // Our test for the correct openssl lambda layer does not include the version, so we use a filter - // function to do a partial match - const filterOpensslArn = (value: string) => { - return value.toString().includes('arn:aws:lambda:us-west-2:224375009292:layer:openssl-al2:'); - }; - if (!props.Layers - || !Array.isArray(props.Layers) - || Array.of(props.Layers).filter(filterOpensslArn).length === 0) { - error.failureReason = 'openssl Lambda Layer missing'; - error.resource = props.Layers; - return false; - } - if (!props.Environment - || !props.Environment.Variables - || !props.Environment.Variables.DATABASE) { - error.failureReason = 'DATABASE environment variable not set'; - error.resource = props.Environment?.Variables?.DATABASE; - return false; - } - return true; - })); + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { + Handler: 'x509-certificate.generate', + Layers: Match.arrayWith([ + Match.stringLikeRegexp('^arn:aws:lambda:us-west-2:224375009292:layer:openssl-al2:.*'), + ]), + Environment: { + Variables: { + DATABASE: { + Ref: Match.stringLikeRegexp('^CertTable.*'), + }, + }, + }, + }); // Should not be any errors. - expect(cert.node.metadataEntry.length).toBe(0); + Annotations.fromStack(stack).hasNoInfo(`/${cert.node.path}`, Match.anyValue()); + Annotations.fromStack(stack).hasNoWarning(`/${cert.node.path}`, Match.anyValue()); + Annotations.fromStack(stack).hasNoError(`/${cert.node.path}`, Match.anyValue()); }); test('Generate cert, all options set', () => { @@ -144,19 +133,16 @@ test('Generate cert, all options set', () => { }; const encryptionKey = new Key(stack, 'Key'); const signingCertificate = new X509CertificatePem(stack, 'SigningCert', { subject }); - const signingCertPassphraseID = stack.getLogicalId(signingCertificate.passphrase.node.defaultChild as CfnSecret); - const cert = new X509CertificatePem(stack, 'Cert', { + new X509CertificatePem(stack, 'Cert', { subject, encryptionKey, signingCertificate, validFor: 3000, }); - const certPassphraseID = stack.getLogicalId(cert.passphrase.node.defaultChild as CfnSecret); - // Expect the custom resource for cert generation - expectCDK(stack).to(haveResourceLike('Custom::RFDK_X509Generator', { + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_X509Generator', { DistinguishedName: { CN: 'testCN', O: 'testO', @@ -176,25 +162,19 @@ test('Generate cert, all options set', () => { ], }, Passphrase: { - Ref: signingCertPassphraseID, + Ref: Match.stringLikeRegexp('^SigningCertPassphrase.*'), }, CertChain: '', }, CertificateValidFor: '3000', - })); + }); // Expect the resource for converting to PKCS #12 not to be created - expectCDK(stack).notTo(haveResource('Custom::RFDK_X509_PKCS12')); - // Expect the DynamoDB table used for custom resource tracking - expectCDK(stack).to(haveResource('AWS::DynamoDB::Table')); - // Expect a Secret used to store the cert - expectCDK(stack).to(haveResource('AWS::SecretsManager::Secret')); - // Expect a KMS key for encryption - expectCDK(stack).to(haveResource('AWS::KMS::Key')); + Template.fromStack(stack).resourceCountIs('Custom::RFDK_X509_PKCS12', 0); // Expect a policy that can interact with DynamoDB and SecretsManager for the signing cert's custom resource - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: [ - { + Statement: Match.arrayWith([ + Match.objectLike({ Action: [ 'dynamodb:BatchGetItem', 'dynamodb:GetRecords', @@ -207,28 +187,29 @@ test('Generate cert, all options set', () => { 'dynamodb:PutItem', 'dynamodb:UpdateItem', 'dynamodb:DeleteItem', + 'dynamodb:DescribeTable', ], - }, - { + }), + Match.objectLike({ Action: 'dynamodb:DescribeTable', - }, - { + }), + Match.objectLike({ Action: [ 'kms:Encrypt', 'kms:ReEncrypt*', 'kms:GenerateDataKey*', ], - }, - { + }), + Match.objectLike({ Action: [ 'secretsmanager:GetSecretValue', 'secretsmanager:DescribeSecret', ], Resource: { - Ref: certPassphraseID, + Ref: Match.stringLikeRegexp('^CertPassphrase.*'), }, - }, - { + }), + Match.objectLike({ Action: [ 'secretsmanager:CreateSecret', 'secretsmanager:DeleteSecret', @@ -240,8 +221,8 @@ test('Generate cert, all options set', () => { 'secretsmanager:ResourceTag/X509SecretGrant-B2B09A60': 'b2b09a6086e87fe14005f4e0b800e4f0', }, }, - }, - { + }), + Match.objectLike({ Action: [ 'secretsmanager:GetSecretValue', 'secretsmanager:DescribeSecret', @@ -252,8 +233,8 @@ test('Generate cert, all options set', () => { 'Cert', ], }, - }, - { + }), + Match.objectLike({ Action: [ 'secretsmanager:GetSecretValue', 'secretsmanager:DescribeSecret', @@ -264,8 +245,8 @@ test('Generate cert, all options set', () => { 'Key', ], }, - }, - { + }), + Match.objectLike({ Action: [ 'secretsmanager:GetSecretValue', 'secretsmanager:DescribeSecret', @@ -273,15 +254,15 @@ test('Generate cert, all options set', () => { Resource: { Ref: 'SigningCertPassphrase42F0BC4F', }, - }, - ], + }), + ]), }, - })); + }); // Expect a policy that can interact with DynamoDB and SecretsManager for the cert's custom resource - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { - PolicyDocument: { - Statement: [ - { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: Match.objectLike({ + Statement: Match.arrayWith([ + Match.objectLike({ Action: [ 'dynamodb:BatchGetItem', 'dynamodb:GetRecords', @@ -294,21 +275,22 @@ test('Generate cert, all options set', () => { 'dynamodb:PutItem', 'dynamodb:UpdateItem', 'dynamodb:DeleteItem', + 'dynamodb:DescribeTable', ], - }, - { + }), + Match.objectLike({ Action: 'dynamodb:DescribeTable', - }, - { + }), + Match.objectLike({ Action: [ 'secretsmanager:GetSecretValue', 'secretsmanager:DescribeSecret', ], Resource: { - Ref: signingCertPassphraseID, + Ref: Match.stringLikeRegexp('^SigningCertPassphrase.*'), }, - }, - { + }), + Match.objectLike({ Action: [ 'secretsmanager:CreateSecret', 'secretsmanager:DeleteSecret', @@ -320,14 +302,14 @@ test('Generate cert, all options set', () => { 'secretsmanager:ResourceTag/X509SecretGrant-BA0FA489': 'ba0fa4898b2088c5b25f15075f605300', }, }, - }, - ], - }, - })); + }), + ]), + }), + }); // Expect Lambda for doing the cert generation to use the generate() handler - expectCDK(stack).to(haveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'x509-certificate.generate', - })); + }); }); test('Grant cert read', () => { @@ -344,15 +326,15 @@ test('Grant cert read', () => { cert.grantCertRead(grantable); // Expect the custom resource to be created - expectCDK(stack).to(haveResourceLike('Custom::RFDK_X509Generator', { + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_X509Generator', { DistinguishedName: { CN: 'testCN', O: 'AWS', OU: 'Thinkbox', }, - })); + }); // Expect the grantCertRead() to add this policy - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -370,12 +352,12 @@ test('Grant cert read', () => { }, ], }, - })); + }); // Expect the grantCertRead() not to add this full read policy - expectCDK(stack).notTo(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', Match.not({ PolicyDocument: { - Statement: [ - { + Statement: Match.arrayWith([ + Match.objectLike({ Action: 'secretsmanager:GetSecretValue', Effect: 'Allow', Resource: { @@ -384,8 +366,8 @@ test('Grant cert read', () => { 'Cert', ], }, - }, - { + }), + Match.objectLike({ Action: 'secretsmanager:GetSecretValue', Effect: 'Allow', Resource: { @@ -394,19 +376,19 @@ test('Grant cert read', () => { 'Key', ], }, - }, - { + }), + Match.objectLike({ Action: 'secretsmanager:GetSecretValue', Effect: 'Allow', Resource: { Ref: certPassphraseID, }, - }, - ], + }), + ]), }, })); // Expect the PKCS #12 generator not to be created - expectCDK(stack).notTo(haveResource('Custom::RFDK_X509_PKCS12')); + Template.fromStack(stack).resourceCountIs('Custom::RFDK_X509_PKCS12', 0); }); test('Grant full read', () => { @@ -423,18 +405,18 @@ test('Grant full read', () => { cert.grantFullRead(grantable); // Expect the custom resource to be created - expectCDK(stack).to(haveResourceLike('Custom::RFDK_X509Generator', { + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_X509Generator', { DistinguishedName: { CN: 'testCN', O: 'AWS', OU: 'Thinkbox', }, - })); + }); // Expect the grantFullRead() to add this policy - expectCDK(stack).notTo(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', Match.not({ PolicyDocument: { - Statement: [ - { + Statement: Match.arrayWith([ + Match.objectLike({ Action: 'secretsmanager:GetSecretValue', Effect: 'Allow', Resource: { @@ -443,8 +425,8 @@ test('Grant full read', () => { 'Cert', ], }, - }, - { + }), + Match.objectLike({ Action: 'secretsmanager:GetSecretValue', Effect: 'Allow', Resource: { @@ -453,19 +435,19 @@ test('Grant full read', () => { 'Key', ], }, - }, - { + }), + Match.objectLike({ Action: 'secretsmanager:GetSecretValue', Effect: 'Allow', Resource: { Ref: certPassphraseID, }, - }, - ], + }), + ]), }, })); // Expect the PKCS #12 generator not to be created - expectCDK(stack).notTo(haveResource('Custom::RFDK_X509_PKCS12')); + Template.fromStack(stack).resourceCountIs('Custom::RFDK_X509_PKCS12', 0); }); test('Validating expiry', () => { @@ -480,24 +462,28 @@ test('Validating expiry', () => { }); // THEN - expect(cert.node.metadataEntry.length).toBe(1); + Annotations.fromStack(stack).hasError(`/${cert.node.path}`, 'Certificates must be valid for at least one day.'); }); test('Validating expiry with token', () => { // GIVEN const stack = new Stack(undefined, 'Stack', { env: { region: 'us-west-2' } }); const subject = { cn: 'testCN' }; - // A numeric CDK token (see: https://docs.aws.amazon.com/cdk/latest/guide/tokens.html#tokens_number) - const CDK_NUMERIC_TOKEN = -1.8881545897087626e+289; // WHEN const cert = new X509CertificatePem(stack, 'Cert', { subject, - validFor: CDK_NUMERIC_TOKEN, + validFor: Lazy.number({ + produce() { + return 0; + }, + }), }); // THEN - expect(cert.node.metadataEntry.length).toBe(0); + Annotations.fromStack(stack).hasNoInfo(`/${cert.node.path}`, Match.anyValue()); + Annotations.fromStack(stack).hasNoWarning(`/${cert.node.path}`, Match.anyValue()); + Annotations.fromStack(stack).hasNoError(`/${cert.node.path}`, Match.anyValue()); }); test('Convert to PKCS #12', () => { @@ -510,7 +496,7 @@ test('Convert to PKCS #12', () => { const pkcs12CertPassphraseID = stack.getLogicalId(pkcs12Cert.passphrase.node.defaultChild as CfnSecret); // Expect the PKCS #12 custom resource - expectCDK(stack).to(haveResourceLike('Custom::RFDK_X509_PKCS12', { + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_X509_PKCS12', { Passphrase: { Ref: 'CertPkcs12Passphrase1E3DF360', }, @@ -541,11 +527,11 @@ test('Convert to PKCS #12', () => { Ref: certPassphraseID, }, }, - })); + }); // Expect the source certificate (custom resource) - expectCDK(stack).to(haveResource('Custom::RFDK_X509Generator')); + Template.fromStack(stack).resourceCountIs('Custom::RFDK_X509Generator', 1); // Expect the PKCS #12 to have a password secret - expectCDK(stack).to(haveResourceLike('AWS::SecretsManager::Secret', { + Template.fromStack(stack).hasResourceProperties('AWS::SecretsManager::Secret', { Description: 'Passphrase for the private key of the X509Certificate CertPkcs12', GenerateSecretString: { ExcludeCharacters: '"()$\'', @@ -554,12 +540,12 @@ test('Convert to PKCS #12', () => { PasswordLength: 24, RequireEachIncludedType: true, }, - })); + }); // Expect the PKCS #12 resource to have a policy with access to the X.509 resource - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { - PolicyDocument: { - Statement: [ - { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: Match.objectLike({ + Statement: Match.arrayWith([ + Match.objectLike({ Action: [ 'dynamodb:BatchGetItem', 'dynamodb:GetRecords', @@ -572,12 +558,13 @@ test('Convert to PKCS #12', () => { 'dynamodb:PutItem', 'dynamodb:UpdateItem', 'dynamodb:DeleteItem', + 'dynamodb:DescribeTable', ], - }, - { + }), + Match.objectLike({ Action: 'dynamodb:DescribeTable', - }, - { + }), + Match.objectLike({ Action: [ 'secretsmanager:GetSecretValue', 'secretsmanager:DescribeSecret', @@ -585,8 +572,8 @@ test('Convert to PKCS #12', () => { Resource: { Ref: pkcs12CertPassphraseID, }, - }, - { + }), + Match.objectLike({ Action: [ 'secretsmanager:CreateSecret', 'secretsmanager:DeleteSecret', @@ -598,8 +585,8 @@ test('Convert to PKCS #12', () => { 'secretsmanager:ResourceTag/X509SecretGrant-71090F78': '71090f7809ce64f7c970cb645d4d473c', }, }, - }, - { + }), + Match.objectLike({ Action: [ 'secretsmanager:GetSecretValue', 'secretsmanager:DescribeSecret', @@ -611,8 +598,8 @@ test('Convert to PKCS #12', () => { 'Cert', ], }, - }, - { + }), + Match.objectLike({ Action: [ 'secretsmanager:GetSecretValue', 'secretsmanager:DescribeSecret', @@ -624,8 +611,8 @@ test('Convert to PKCS #12', () => { 'Key', ], }, - }, - { + }), + Match.objectLike({ Action: [ 'secretsmanager:GetSecretValue', 'secretsmanager:DescribeSecret', @@ -634,16 +621,16 @@ test('Convert to PKCS #12', () => { Resource: { Ref: certPassphraseID, }, - }, - ], - }, - })); + }), + ]), + }), + }); // Expect no KMS key - expectCDK(stack).notTo(haveResource('AWS::KMS::Key')); + Template.fromStack(stack).resourceCountIs('AWS::KMS::Key', 0); // Expect the Lambda for converting the PEM to PKCS 12 - expectCDK(stack).to(haveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'x509-certificate.convert', - })); + }); }); test('Convert to PKCS #12, use KMS', () => { @@ -659,7 +646,7 @@ test('Convert to PKCS #12, use KMS', () => { }); // Expect the PKCS #12 custom resource - expectCDK(stack).to(haveResourceLike('Custom::RFDK_X509_PKCS12', { + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_X509_PKCS12', { Passphrase: { Ref: 'CertPkcs12Passphrase1E3DF360', }, @@ -690,11 +677,11 @@ test('Convert to PKCS #12, use KMS', () => { Ref: certPassphraseID, }, }, - })); + }); // Expect the source certificate (custom resource) - expectCDK(stack).to(haveResource('Custom::RFDK_X509Generator')); + Template.fromStack(stack).resourceCountIs('Custom::RFDK_X509Generator', 1); // Expect the PKCS #12 to have a password secret - expectCDK(stack).to(haveResourceLike('AWS::SecretsManager::Secret', { + Template.fromStack(stack).hasResourceProperties('AWS::SecretsManager::Secret', { Description: 'Passphrase for the private key of the X509Certificate CertPkcs12', GenerateSecretString: { ExcludeCharacters: '"()$\'', @@ -703,11 +690,11 @@ test('Convert to PKCS #12, use KMS', () => { PasswordLength: 24, RequireEachIncludedType: true, }, - })); + }); // Expect a KMS key for encryption - expectCDK(stack).to(haveResource('AWS::KMS::Key')); + Template.fromStack(stack).resourceCountIs('AWS::KMS::Key', 1); // Expect the Lambda for converting the PEM to PKCS #12 - expectCDK(stack).to(haveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'x509-certificate.convert', - })); + }); }); diff --git a/packages/aws-rfdk/lib/deadline/lib/configure-spot-event-plugin.ts b/packages/aws-rfdk/lib/deadline/lib/configure-spot-event-plugin.ts index beaf22b74..51aa13334 100644 --- a/packages/aws-rfdk/lib/deadline/lib/configure-spot-event-plugin.ts +++ b/packages/aws-rfdk/lib/deadline/lib/configure-spot-event-plugin.ts @@ -5,31 +5,31 @@ import * as path from 'path'; +import { + Annotations, + CustomResource, + Duration, + IResolvable, + Lazy, + Stack, +} from 'aws-cdk-lib'; import { IVpc, SubnetSelection, SubnetType, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { Role, Policy, PolicyStatement, -} from '@aws-cdk/aws-iam'; +} from 'aws-cdk-lib/aws-iam'; import { Code, Function as LambdaFunction, Runtime, -} from '@aws-cdk/aws-lambda'; -import { RetentionDays } from '@aws-cdk/aws-logs'; -import { - Annotations, - Construct, - CustomResource, - Duration, - IResolvable, - Lazy, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-lambda'; +import { RetentionDays } from 'aws-cdk-lib/aws-logs'; +import { Construct } from 'constructs'; import { PluginSettings, @@ -123,15 +123,15 @@ export enum SpotEventPluginPreJobTaskMode { export enum SpotEventPluginDisplayInstanceStatus { DISABLED = 'Disabled', EXTRA_INFO_0 = 'ExtraInfo0', - EXTRA_INFO_1 = 'ExtraInfo0', - EXTRA_INFO_2 = 'ExtraInfo0', - EXTRA_INFO_3 = 'ExtraInfo0', - EXTRA_INFO_4 = 'ExtraInfo0', - EXTRA_INFO_5 = 'ExtraInfo0', - EXTRA_INFO_6 = 'ExtraInfo0', - EXTRA_INFO_7 = 'ExtraInfo0', - EXTRA_INFO_8 = 'ExtraInfo0', - EXTRA_INFO_9 = 'ExtraInfo0', + EXTRA_INFO_1 = 'ExtraInfo1', + EXTRA_INFO_2 = 'ExtraInfo2', + EXTRA_INFO_3 = 'ExtraInfo3', + EXTRA_INFO_4 = 'ExtraInfo4', + EXTRA_INFO_5 = 'ExtraInfo5', + EXTRA_INFO_6 = 'ExtraInfo6', + EXTRA_INFO_7 = 'ExtraInfo7', + EXTRA_INFO_8 = 'ExtraInfo8', + EXTRA_INFO_9 = 'ExtraInfo9', } /** @@ -275,7 +275,7 @@ export interface ConfigureSpotEventPluginProps { * * ```ts * import { App, Stack, Vpc } from '@aws-rfdk/core'; - * import { InstanceClass, InstanceSize, InstanceType } from '@aws-cdk/aws-ec2'; + * import { InstanceClass, InstanceSize, InstanceType } from 'aws-cdk-lib/aws-ec2'; * import { AwsThinkboxEulaAcceptance, ConfigureSpotEventPlugin, RenderQueue, Repository, SpotEventPluginFleet, ThinkboxDockerImages, VersionQuery } from '@aws-rfdk/deadline'; * const app = new App(); * const stack = new Stack(app, 'Stack'); diff --git a/packages/aws-rfdk/lib/deadline/lib/database-connection.ts b/packages/aws-rfdk/lib/deadline/lib/database-connection.ts index 2021f41d8..b0c9bdcf0 100644 --- a/packages/aws-rfdk/lib/deadline/lib/database-connection.ts +++ b/packages/aws-rfdk/lib/deadline/lib/database-connection.ts @@ -4,31 +4,31 @@ */ import * as path from 'path'; +import { + Annotations, + Stack, +} from 'aws-cdk-lib'; import { CfnDBCluster, CfnDBInstance, DatabaseCluster, IDatabaseCluster, -} from '@aws-cdk/aws-docdb'; +} from 'aws-cdk-lib/aws-docdb'; import { IConnectable, ISecurityGroup, OperatingSystemType, Port, Volume, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { IGrantable, -} from '@aws-cdk/aws-iam'; +} from 'aws-cdk-lib/aws-iam'; import { ISecret, -} from '@aws-cdk/aws-secretsmanager'; -import { - Annotations, - Construct, - IConstruct, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-secretsmanager'; +import { Construct, IConstruct } from 'constructs'; + import { IMongoDb, IX509CertificatePkcs12, diff --git a/packages/aws-rfdk/lib/deadline/lib/host-ref.ts b/packages/aws-rfdk/lib/deadline/lib/host-ref.ts index 7c7c230f0..8968334b5 100644 --- a/packages/aws-rfdk/lib/deadline/lib/host-ref.ts +++ b/packages/aws-rfdk/lib/deadline/lib/host-ref.ts @@ -3,8 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {IConnectable} from '@aws-cdk/aws-ec2'; -import {IConstruct} from '@aws-cdk/core'; +import {IConnectable} from 'aws-cdk-lib/aws-ec2'; +import {IConstruct} from 'constructs'; import {IScriptHost} from '../../core'; /** diff --git a/packages/aws-rfdk/lib/deadline/lib/render-queue-ref.ts b/packages/aws-rfdk/lib/deadline/lib/render-queue-ref.ts index 410d469cf..8f870ab06 100644 --- a/packages/aws-rfdk/lib/deadline/lib/render-queue-ref.ts +++ b/packages/aws-rfdk/lib/deadline/lib/render-queue-ref.ts @@ -3,34 +3,34 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { Duration } from 'aws-cdk-lib'; import { ICertificate, -} from '@aws-cdk/aws-certificatemanager'; +} from 'aws-cdk-lib/aws-certificatemanager'; import { InstanceType, ISecurityGroup, IVpc, SubnetSelection, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { ContainerImage, -} from '@aws-cdk/aws-ecs'; +} from 'aws-cdk-lib/aws-ecs'; import { ApplicationProtocol, -} from '@aws-cdk/aws-elasticloadbalancingv2'; +} from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import { IGrantable, -} from '@aws-cdk/aws-iam'; +} from 'aws-cdk-lib/aws-iam'; import { IPrivateHostedZone, -} from '@aws-cdk/aws-route53'; +} from 'aws-cdk-lib/aws-route53'; import { IBucket, -} from '@aws-cdk/aws-s3'; +} from 'aws-cdk-lib/aws-s3'; import { ISecret, -} from '@aws-cdk/aws-secretsmanager'; -import { Duration } from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-secretsmanager'; import { IX509CertificatePem, LogGroupFactoryProps, diff --git a/packages/aws-rfdk/lib/deadline/lib/render-queue.ts b/packages/aws-rfdk/lib/deadline/lib/render-queue.ts index 291757522..3546c55dc 100644 --- a/packages/aws-rfdk/lib/deadline/lib/render-queue.ts +++ b/packages/aws-rfdk/lib/deadline/lib/render-queue.ts @@ -6,14 +6,17 @@ import { join, } from 'path'; +import { + Stack, +} from 'aws-cdk-lib'; import { AutoScalingGroup, BlockDeviceVolume, UpdatePolicy, -} from '@aws-cdk/aws-autoscaling'; +} from 'aws-cdk-lib/aws-autoscaling'; import { ICertificate, -} from '@aws-cdk/aws-certificatemanager'; +} from 'aws-cdk-lib/aws-certificatemanager'; import { Connections, IConnectable, @@ -23,7 +26,7 @@ import { Port, SubnetSelection, SubnetType, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { Cluster, ContainerImage, @@ -32,36 +35,32 @@ import { PlacementConstraint, Scope, UlimitName, -} from '@aws-cdk/aws-ecs'; +} from 'aws-cdk-lib/aws-ecs'; import { ApplicationLoadBalancedEc2Service, -} from '@aws-cdk/aws-ecs-patterns'; +} from 'aws-cdk-lib/aws-ecs-patterns'; import { ApplicationListener, ApplicationLoadBalancer, ApplicationProtocol, ApplicationTargetGroup, CfnTargetGroup, -} from '@aws-cdk/aws-elasticloadbalancingv2'; +} from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import { IGrantable, IPrincipal, ManagedPolicy, PolicyStatement, ServicePrincipal, -} from '@aws-cdk/aws-iam'; +} from 'aws-cdk-lib/aws-iam'; import { ILogGroup, -} from '@aws-cdk/aws-logs'; -import { IHostedZone, IPrivateHostedZone, PrivateHostedZone } from '@aws-cdk/aws-route53'; +} from 'aws-cdk-lib/aws-logs'; +import { IHostedZone, IPrivateHostedZone, PrivateHostedZone } from 'aws-cdk-lib/aws-route53'; import { ISecret, -} from '@aws-cdk/aws-secretsmanager'; -import { - Construct, - IConstruct, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-secretsmanager'; +import { Construct, IConstruct } from 'constructs'; import { ECSConnectOptions, @@ -447,7 +446,7 @@ export class RenderQueue extends RenderQueueBase implements IGrantable { // We want the volume to be encrypted. The default AMI size is 30-GiB. volume: BlockDeviceVolume.ebs(30, { encrypted: true }), }], - updateType: undefined, // Workaround -- See: https://github.com/aws/aws-cdk/issues/11581 + ...{ updateType: undefined }, // Workaround -- See: https://github.com/aws/aws-cdk/issues/11581 updatePolicy: UpdatePolicy.rollingUpdate(), // addCapacity doesn't specifically take a securityGroup, but it passes on its properties to the ASG it creates, // so this security group will get applied there @@ -523,7 +522,7 @@ export class RenderQueue extends RenderQueueBase implements IGrantable { this.pattern = new ApplicationLoadBalancedEc2Service(this, 'AlbEc2ServicePattern', { certificate: this.clientCert, cluster: this.cluster, - desiredCount: this.renderQueueSize?.desired, + desiredCount: this.renderQueueSize?.desired ?? minCapacity, domainZone, domainName: loadBalancerFQDN, listenerPort: externalPortNumber, @@ -629,22 +628,25 @@ export class RenderQueue extends RenderQueueBase implements IGrantable { // Tag deployed resources with RFDK meta-data tagConstruct(this); - } - - protected onValidate(): string[] { - const validationErrors = []; - // Using the output of VersionQuery across stacks can cause issues. CloudFormation stack outputs cannot change if - // a resource in another stack is referencing it. - if (this.version instanceof VersionQuery) { - const versionStack = Stack.of(this.version); - const thisStack = Stack.of(this); - if (versionStack != thisStack) { - validationErrors.push('A VersionQuery can not be supplied from a different stack'); - } - } - - return validationErrors; + const thisConstruct = this; + this.node.addValidation({ + validate(): string[] { + const validationErrors = []; + + // Using the output of VersionQuery across stacks can cause issues. CloudFormation stack outputs cannot change if + // a resource in another stack is referencing it. + if (thisConstruct.version instanceof VersionQuery) { + const versionStack = Stack.of(thisConstruct.version); + const thisStack = Stack.of(thisConstruct); + if (versionStack != thisStack) { + validationErrors.push('A VersionQuery can not be supplied from a different stack'); + } + } + + return validationErrors; + }, + }); } /** @@ -976,6 +978,7 @@ export class RenderQueue extends RenderQueueBase implements IGrantable { securityGroup: this.backendConnections.securityGroups[0], vpc: this.props.vpc, vpcSubnets: this.props.vpcSubnets ?? RenderQueue.DEFAULT_VPC_SUBNETS_OTHER, + logGroupProps: this.props.logGroupProps, }); } else if (deploymentInstanceNode instanceof DeploymentInstance) { return deploymentInstanceNode; diff --git a/packages/aws-rfdk/lib/deadline/lib/repository.ts b/packages/aws-rfdk/lib/deadline/lib/repository.ts index 901cf32cb..c2474be7d 100644 --- a/packages/aws-rfdk/lib/deadline/lib/repository.ts +++ b/packages/aws-rfdk/lib/deadline/lib/repository.ts @@ -8,17 +8,27 @@ import { pathToFileURL, } from 'url'; +import { + Annotations, + Duration, + RemovalPolicy, + Names, + Size, + Stack, + Tags, + Token, +} from 'aws-cdk-lib'; import { AutoScalingGroup, Signals, UpdatePolicy, -} from '@aws-cdk/aws-autoscaling'; +} from 'aws-cdk-lib/aws-autoscaling'; import { CfnDBInstance, DatabaseCluster, CfnDBCluster, ClusterParameterGroup, -} from '@aws-cdk/aws-docdb'; +} from 'aws-cdk-lib/aws-docdb'; import { AmazonLinuxGeneration, AmazonLinuxImage, @@ -30,37 +40,26 @@ import { OperatingSystemType, SubnetSelection, SubnetType, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { MountPoint, TaskDefinition, -} from '@aws-cdk/aws-ecs'; +} from 'aws-cdk-lib/aws-ecs'; import { FileSystem as EfsFileSystem, LifecyclePolicy as EfsLifecyclePolicy, -} from '@aws-cdk/aws-efs'; +} from 'aws-cdk-lib/aws-efs'; import { PolicyStatement, -} from '@aws-cdk/aws-iam'; +} from 'aws-cdk-lib/aws-iam'; import { Asset, -} from '@aws-cdk/aws-s3-assets'; +} from 'aws-cdk-lib/aws-s3-assets'; import { ISecret, Secret, -} from '@aws-cdk/aws-secretsmanager'; -import { - Annotations, - Construct, - Duration, - IConstruct, - RemovalPolicy, - Names, - Size, - Stack, - Tags, - Token, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-secretsmanager'; +import { Construct, IConstruct } from 'constructs'; import { CloudWatchAgent, CloudWatchConfigBuilder, @@ -783,22 +782,25 @@ export class Repository extends Construct implements IRepository { // Tag deployed resources with RFDK meta-data tagConstruct(this); - } - protected onValidate(): string[] { - const validationErrors = []; - - // Using the output of VersionQuery across stacks can cause issues. CloudFormation stack outputs cannot change if - // a resource in another stack is referencing it. - if (this.version instanceof VersionQuery) { - const versionStack = Stack.of(this.version); - const thisStack = Stack.of(this); - if (versionStack != thisStack) { - validationErrors.push('A VersionQuery can not be supplied from a different stack'); - } - } - - return validationErrors; + const thisConstruct = this; + this.node.addValidation({ + validate(): string[] { + const validationErrors = []; + + // Using the output of VersionQuery across stacks can cause issues. CloudFormation stack outputs cannot change if + // a resource in another stack is referencing it. + if (thisConstruct.version instanceof VersionQuery) { + const versionStack = Stack.of(thisConstruct.version); + const thisStack = Stack.of(thisConstruct); + if (versionStack != thisStack) { + validationErrors.push('A VersionQuery can not be supplied from a different stack'); + } + } + + return validationErrors; + }, + }); } /** diff --git a/packages/aws-rfdk/lib/deadline/lib/rq-connection.ts b/packages/aws-rfdk/lib/deadline/lib/rq-connection.ts index e62e58704..d31e9b493 100644 --- a/packages/aws-rfdk/lib/deadline/lib/rq-connection.ts +++ b/packages/aws-rfdk/lib/deadline/lib/rq-connection.ts @@ -5,10 +5,10 @@ import * as path from 'path'; -import { OperatingSystemType } from '@aws-cdk/aws-ec2'; -import { Asset } from '@aws-cdk/aws-s3-assets'; -import { ISecret } from '@aws-cdk/aws-secretsmanager'; -import { Stack } from '@aws-cdk/core'; +import { Stack } from 'aws-cdk-lib'; +import { OperatingSystemType } from 'aws-cdk-lib/aws-ec2'; +import { Asset } from 'aws-cdk-lib/aws-s3-assets'; +import { ISecret } from 'aws-cdk-lib/aws-secretsmanager'; import { ConnectableApplicationEndpoint } from '../../core'; diff --git a/packages/aws-rfdk/lib/deadline/lib/secrets-management-ref.ts b/packages/aws-rfdk/lib/deadline/lib/secrets-management-ref.ts index 5f93229fa..2d93ca2d7 100644 --- a/packages/aws-rfdk/lib/deadline/lib/secrets-management-ref.ts +++ b/packages/aws-rfdk/lib/deadline/lib/secrets-management-ref.ts @@ -6,8 +6,8 @@ import { IVpc, SubnetSelection, -} from '@aws-cdk/aws-ec2'; -import { Construct } from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; +import { Construct } from 'constructs'; /** * Deadline Secrets Management roles. diff --git a/packages/aws-rfdk/lib/deadline/lib/secrets-management.ts b/packages/aws-rfdk/lib/deadline/lib/secrets-management.ts index ab3a774c3..beced9f3d 100644 --- a/packages/aws-rfdk/lib/deadline/lib/secrets-management.ts +++ b/packages/aws-rfdk/lib/deadline/lib/secrets-management.ts @@ -5,16 +5,16 @@ import * as path from 'path'; -import { SelectedSubnets } from '@aws-cdk/aws-ec2'; -import { PolicyStatement } from '@aws-cdk/aws-iam'; -import { ISecret } from '@aws-cdk/aws-secretsmanager'; import { - Construct, Lazy, Stack, Fn, Annotations, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib'; +import { SelectedSubnets } from 'aws-cdk-lib/aws-ec2'; +import { PolicyStatement } from 'aws-cdk-lib/aws-iam'; +import { ISecret } from 'aws-cdk-lib/aws-secretsmanager'; +import { Construct } from 'constructs'; import { IRepository, diff --git a/packages/aws-rfdk/lib/deadline/lib/spot-event-plugin-fleet.ts b/packages/aws-rfdk/lib/deadline/lib/spot-event-plugin-fleet.ts index af8f407f9..929ae6499 100644 --- a/packages/aws-rfdk/lib/deadline/lib/spot-event-plugin-fleet.ts +++ b/packages/aws-rfdk/lib/deadline/lib/spot-event-plugin-fleet.ts @@ -3,9 +3,17 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { + Annotations, + Expiration, + Stack, + TagManager, + Tags, + TagType, +} from 'aws-cdk-lib'; import { BlockDevice, -} from '@aws-cdk/aws-autoscaling'; +} from 'aws-cdk-lib/aws-autoscaling'; import { Connections, EbsDeviceVolumeType, @@ -23,7 +31,7 @@ import { SubnetSelection, SubnetType, UserData, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { CfnInstanceProfile, IGrantable, @@ -32,16 +40,8 @@ import { ManagedPolicy, Role, ServicePrincipal, -} from '@aws-cdk/aws-iam'; -import { - Annotations, - Construct, - Expiration, - Stack, - TagManager, - Tags, - TagType, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-iam'; +import { Construct } from 'constructs'; import { IScriptHost, LogGroupFactoryProps, diff --git a/packages/aws-rfdk/lib/deadline/lib/stage.ts b/packages/aws-rfdk/lib/deadline/lib/stage.ts index 3fdbe77db..6ef842b35 100644 --- a/packages/aws-rfdk/lib/deadline/lib/stage.ts +++ b/packages/aws-rfdk/lib/deadline/lib/stage.ts @@ -6,8 +6,8 @@ import * as fs from 'fs'; import * as path from 'path'; -import { DockerImageAsset } from '@aws-cdk/aws-ecr-assets'; -import { Construct } from '@aws-cdk/core'; +import { DockerImageAsset } from 'aws-cdk-lib/aws-ecr-assets'; +import { Construct } from 'constructs'; import { IVersion, diff --git a/packages/aws-rfdk/lib/deadline/lib/thinkbox-docker-images.ts b/packages/aws-rfdk/lib/deadline/lib/thinkbox-docker-images.ts index 562e2017d..a30ebf186 100644 --- a/packages/aws-rfdk/lib/deadline/lib/thinkbox-docker-images.ts +++ b/packages/aws-rfdk/lib/deadline/lib/thinkbox-docker-images.ts @@ -6,23 +6,23 @@ import { randomBytes } from 'crypto'; import * as path from 'path'; +import { + CustomResource, + Duration, + Stack, + Token, +} from 'aws-cdk-lib'; import { ContainerImage, RepositoryImage, -} from '@aws-cdk/aws-ecs'; +} from 'aws-cdk-lib/aws-ecs'; import { Code, SingletonFunction, Runtime, -} from '@aws-cdk/aws-lambda'; -import { RetentionDays } from '@aws-cdk/aws-logs'; -import { - Construct, - CustomResource, - Duration, - Stack, - Token, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-lambda'; +import { RetentionDays } from 'aws-cdk-lib/aws-logs'; +import { Construct } from 'constructs'; import { IVersion, @@ -217,26 +217,29 @@ AWS Thinkbox EULA. this.remoteConnectionServer = this.ecrImageForRecipe(ThinkboxManagedDeadlineDockerRecipes.REMOTE_CONNECTION_SERVER); this.licenseForwarder = this.ecrImageForRecipe(ThinkboxManagedDeadlineDockerRecipes.LICENSE_FORWARDER); - } - - protected onValidate() { - const errors: string[] = []; - - // Users must accept the AWS Thinkbox EULA to use the container images - if (this.userAwsThinkboxEulaAcceptance !== AwsThinkboxEulaAcceptance.USER_ACCEPTS_AWS_THINKBOX_EULA) { - errors.push(ThinkboxDockerImages.AWS_THINKBOX_EULA_MESSAGE); - } - // Using the output of VersionQuery across stacks can cause issues. CloudFormation stack outputs cannot change if - // a resource in another stack is referencing it. - if (this.version instanceof VersionQuery) { - const versionStack = Stack.of(this.version); - const thisStack = Stack.of(this); - if (versionStack != thisStack) { - errors.push('A VersionQuery can not be supplied from a different stack'); - } - } - return errors; + const thisConstruct = this; + this.node.addValidation({ + validate(): string[] { + const errors: string[] = []; + + // Users must accept the AWS Thinkbox EULA to use the container images + if (thisConstruct.userAwsThinkboxEulaAcceptance !== AwsThinkboxEulaAcceptance.USER_ACCEPTS_AWS_THINKBOX_EULA) { + errors.push(ThinkboxDockerImages.AWS_THINKBOX_EULA_MESSAGE); + } + + // Using the output of VersionQuery across stacks can cause issues. CloudFormation stack outputs cannot change if + // a resource in another stack is referencing it. + if (thisConstruct.version instanceof VersionQuery) { + const versionStack = Stack.of(thisConstruct.version); + const thisStack = Stack.of(thisConstruct); + if (versionStack != thisStack) { + errors.push('A VersionQuery can not be supplied from a different stack'); + } + } + return errors; + }, + }); } private ecrImageForRecipe(recipe: ThinkboxManagedDeadlineDockerRecipes): RepositoryImage { diff --git a/packages/aws-rfdk/lib/deadline/lib/thinkbox-docker-recipes.ts b/packages/aws-rfdk/lib/deadline/lib/thinkbox-docker-recipes.ts index a19cfa4f4..3e437a15f 100644 --- a/packages/aws-rfdk/lib/deadline/lib/thinkbox-docker-recipes.ts +++ b/packages/aws-rfdk/lib/deadline/lib/thinkbox-docker-recipes.ts @@ -3,10 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { DockerImageAsset } from '@aws-cdk/aws-ecr-assets'; -import { ContainerImage } from '@aws-cdk/aws-ecs'; -import { Asset } from '@aws-cdk/aws-s3-assets'; -import { Construct } from '@aws-cdk/core'; +import { DockerImageAsset } from 'aws-cdk-lib/aws-ecr-assets'; +import { ContainerImage } from 'aws-cdk-lib/aws-ecs'; +import { Asset } from 'aws-cdk-lib/aws-s3-assets'; +import { Construct } from 'constructs'; import { Installer, diff --git a/packages/aws-rfdk/lib/deadline/lib/usage-based-licensing.ts b/packages/aws-rfdk/lib/deadline/lib/usage-based-licensing.ts index e7e07f83f..15db1cb45 100644 --- a/packages/aws-rfdk/lib/deadline/lib/usage-based-licensing.ts +++ b/packages/aws-rfdk/lib/deadline/lib/usage-based-licensing.ts @@ -3,10 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { + Annotations, +} from 'aws-cdk-lib'; import { AutoScalingGroup, BlockDeviceVolume, -} from '@aws-cdk/aws-autoscaling'; +} from 'aws-cdk-lib/aws-autoscaling'; import { IConnectable, InstanceClass, @@ -17,7 +20,7 @@ import { Port, SubnetSelection, SubnetType, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { CfnService, Cluster, @@ -29,16 +32,13 @@ import { PlacementConstraint, TaskDefinition, UlimitName, -} from '@aws-cdk/aws-ecs'; +} from 'aws-cdk-lib/aws-ecs'; import { IGrantable, IPrincipal, -} from '@aws-cdk/aws-iam'; -import { ISecret } from '@aws-cdk/aws-secretsmanager'; -import { - Annotations, - Construct, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-iam'; +import { ISecret } from 'aws-cdk-lib/aws-secretsmanager'; +import { Construct } from 'constructs'; import { SecretsManagementRegistrationStatus, diff --git a/packages/aws-rfdk/lib/deadline/lib/version-query.ts b/packages/aws-rfdk/lib/deadline/lib/version-query.ts index fad726784..9471361d1 100644 --- a/packages/aws-rfdk/lib/deadline/lib/version-query.ts +++ b/packages/aws-rfdk/lib/deadline/lib/version-query.ts @@ -6,21 +6,21 @@ import { randomBytes } from 'crypto'; import { join } from 'path'; +import { + CustomResource, + Duration, + Token, +} from 'aws-cdk-lib'; import { Code, SingletonFunction, Runtime, -} from '@aws-cdk/aws-lambda'; -import { RetentionDays } from '@aws-cdk/aws-logs'; +} from 'aws-cdk-lib/aws-lambda'; +import { RetentionDays } from 'aws-cdk-lib/aws-logs'; import { Bucket, -} from '@aws-cdk/aws-s3'; -import { - Construct, - CustomResource, - Duration, - Token, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-s3'; +import { Construct } from 'constructs'; import { IVersionProviderResourceProperties, diff --git a/packages/aws-rfdk/lib/deadline/lib/version-ref.ts b/packages/aws-rfdk/lib/deadline/lib/version-ref.ts index 064944f80..c589f758f 100644 --- a/packages/aws-rfdk/lib/deadline/lib/version-ref.ts +++ b/packages/aws-rfdk/lib/deadline/lib/version-ref.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { IBucket } from '@aws-cdk/aws-s3'; +import { IBucket } from 'aws-cdk-lib/aws-s3'; import { Version } from './version'; /** diff --git a/packages/aws-rfdk/lib/deadline/lib/wait-for-stable-service.ts b/packages/aws-rfdk/lib/deadline/lib/wait-for-stable-service.ts index 546458961..f71a2d1fe 100644 --- a/packages/aws-rfdk/lib/deadline/lib/wait-for-stable-service.ts +++ b/packages/aws-rfdk/lib/deadline/lib/wait-for-stable-service.ts @@ -6,7 +6,11 @@ import { randomBytes } from 'crypto'; import * as path from 'path'; -import { Ec2Service } from '@aws-cdk/aws-ecs'; +import { + CustomResource, + Duration, +} from 'aws-cdk-lib'; +import { Ec2Service } from 'aws-cdk-lib/aws-ecs'; import { Effect, ManagedPolicy, @@ -14,18 +18,14 @@ import { PolicyStatement, Role, ServicePrincipal, -} from '@aws-cdk/aws-iam'; +} from 'aws-cdk-lib/aws-iam'; import { Code, Function as LambdaFunction, Runtime, -} from '@aws-cdk/aws-lambda'; -import { RetentionDays } from '@aws-cdk/aws-logs'; -import { - Construct, - CustomResource, - Duration, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-lambda'; +import { RetentionDays } from 'aws-cdk-lib/aws-logs'; +import { Construct } from 'constructs'; import { WaitForStableServiceResourceProps } from '../../lambdas/nodejs/wait-for-stable-service'; /** diff --git a/packages/aws-rfdk/lib/deadline/lib/worker-configuration.ts b/packages/aws-rfdk/lib/deadline/lib/worker-configuration.ts index f001bf810..f8771143e 100644 --- a/packages/aws-rfdk/lib/deadline/lib/worker-configuration.ts +++ b/packages/aws-rfdk/lib/deadline/lib/worker-configuration.ts @@ -6,13 +6,13 @@ import * as path from 'path'; import { - OperatingSystemType, -} from '@aws-cdk/aws-ec2'; -import { Asset } from '@aws-cdk/aws-s3-assets'; -import { - Construct, Duration, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib'; +import { + OperatingSystemType, +} from 'aws-cdk-lib/aws-ec2'; +import { Asset } from 'aws-cdk-lib/aws-s3-assets'; +import { Construct } from 'constructs'; import { CloudWatchAgent, CloudWatchConfigBuilder, diff --git a/packages/aws-rfdk/lib/deadline/lib/worker-fleet.ts b/packages/aws-rfdk/lib/deadline/lib/worker-fleet.ts index 5b229babe..2ec30b9e1 100644 --- a/packages/aws-rfdk/lib/deadline/lib/worker-fleet.ts +++ b/packages/aws-rfdk/lib/deadline/lib/worker-fleet.ts @@ -4,14 +4,18 @@ */ import * as path from 'path'; +import { + Annotations, + Duration, +} from 'aws-cdk-lib'; import { AutoScalingGroup, BlockDevice, CfnAutoScalingGroup, HealthCheck, Signals, -} from '@aws-cdk/aws-autoscaling'; -import {IMetric, Metric} from '@aws-cdk/aws-cloudwatch'; +} from 'aws-cdk-lib/aws-autoscaling'; +import {IMetric, Metric} from 'aws-cdk-lib/aws-cloudwatch'; import { Connections, IConnectable, @@ -24,8 +28,8 @@ import { Port, SubnetSelection, SubnetType, -} from '@aws-cdk/aws-ec2'; -import {IApplicationLoadBalancerTarget} from '@aws-cdk/aws-elasticloadbalancingv2'; +} from 'aws-cdk-lib/aws-ec2'; +import {IApplicationLoadBalancerTarget} from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import { IGrantable, IPolicy, @@ -33,13 +37,8 @@ import { IRole, Policy, PolicyStatement, -} from '@aws-cdk/aws-iam'; -import { - Annotations, - Construct, - Duration, - IConstruct, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-iam'; +import { Construct, IConstruct } from 'constructs'; import { HealthCheckConfig, diff --git a/packages/aws-rfdk/lib/deadline/test/asset-constants.ts b/packages/aws-rfdk/lib/deadline/test/asset-constants.ts index d7fb7e023..008f35d9f 100644 --- a/packages/aws-rfdk/lib/deadline/test/asset-constants.ts +++ b/packages/aws-rfdk/lib/deadline/test/asset-constants.ts @@ -3,1174 +3,64 @@ * SPDX-License-Identifier: Apache-2.0 */ -// TODO: Properly import from aws-rfdk. Not ideal -// to use a relative path here. -import { stringLike } from '@aws-cdk/assert'; -import { - CWA_ASSET_LINUX, - CWA_ASSET_WINDOWS, -} from '../../core/test/asset-constants'; - -export { - CWA_ASSET_LINUX, - CWA_ASSET_WINDOWS, +// configureRespositoryDirectConnect.sh +export const CONFIG_REPO_DIRECT_CONNECT_LINUX = { + Bucket: 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}', + Key: 'c4ee7f2045a95cb6858f1fdf35253ca27103511dffd97ac97dfe2a8aae85d7fc', }; // configureWorker.sh export const CONFIG_WORKER_ASSET_LINUX = { - Bucket: 'AssetParameters1cfdffe73bb016717ba1f43d64fe528af27b3784f524a97bb36533a6e6d057ffS3Bucket9FBDD688', - Key: 'AssetParameters1cfdffe73bb016717ba1f43d64fe528af27b3784f524a97bb36533a6e6d057ffS3VersionKey02A3157B', + Bucket: 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}', + Key: '1cfdffe73bb016717ba1f43d64fe528af27b3784f524a97bb36533a6e6d057ff', }; // configureWorker.ps1 export const CONFIG_WORKER_ASSET_WINDOWS = { - Bucket: 'AssetParametersa10d67420c8758e35d8dae5fa406c7acb92b1bd40924167d5564aa0037b4a980S3Bucket953E30DC', - Key: 'AssetParametersa10d67420c8758e35d8dae5fa406c7acb92b1bd40924167d5564aa0037b4a980S3VersionKeyAFB97BD6', + Bucket: 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}', + Key: 'a10d67420c8758e35d8dae5fa406c7acb92b1bd40924167d5564aa0037b4a980', +}; + +// configureWorkerHealthCheck.sh +export const CONFIG_WORKER_HEALTHCHECK_LINUX = { + Bucket: 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}', + Key: '3e16ffda458a50d2a032ef783202a85bf4677f19b92a38d3605d6cd750879f75', +}; + +// configureWorkerHealthCheck.ps1 +export const CONFIG_WORKER_HEALTHCHECK_WINDOWS = { + Bucket: 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}', + Key: '8b91f35e39a1b222c8ef7ab0e30da88713339023ac547dc7894f5ea60833df97', +}; + + +export const CONFIG_WORKER_PORT_ASSET_LINUX = { + Bucket: 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}', + Key: 'a10d67420c8758e35d8dae5fa406c7acb92b1bd40924167d5564aa0037b4a980', }; export const CONFIG_WORKER_PORT_ASSET_WINDOWS = { - Bucket: 'AssetParameters3227efc256da3ae31791b7c80e1532cac975116846f179f118a20843e0c2ee80S3Bucket6583BE37', - Key: 'AssetParameters3227efc256da3ae31791b7c80e1532cac975116846f179f118a20843e0c2ee80S3VersionKey6C80977B', + Bucket: 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}', + Key: '3227efc256da3ae31791b7c80e1532cac975116846f179f118a20843e0c2ee80', }; -// installDeadlineRepository.sh -export const INSTALL_REPOSITORY_ASSET_LINUX = { - Bucket: stringLike('AssetParameters*S3Bucket8EB24E17'), +// getSecretToFile.sh +export const GET_SECRET_TO_FILE_SCRIPT_LINUX = { + Bucket: 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}', + Key: '2245b375c979246094a6a47007b55e51f117e987be5de9791c0799cddc3f1c2e', }; -// test.file -export const TEST_ASSET = { - Bucket: stringLike('AssetParameters*S3Bucket5D5509D9'), - Key: stringLike('AssetParameters*S3VersionKeyF19FF080'), +// installDeadlineRepository.sh +export const INSTALL_REPOSITORY_ASSET_LINUX = { + Bucket: 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}', }; // installRepostitoryDirectConnection export const REPO_DC_ASSET = { - Bucket: stringLike('AssetParameters*S3Bucket87338EBD'), - Key: stringLike('AssetParameters*S3VersionKeyB7FF7B3C'), + Bucket: 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}', }; export const RQ_CONNECTION_ASSET = { - Bucket: 'AssetParametersb61797635329f0b0ec0b710b31d49f0e41c1936849266d8a9aed82e1616c9077S3Bucket4D5EEE4A', - Key: 'AssetParametersb61797635329f0b0ec0b710b31d49f0e41c1936849266d8a9aed82e1616c9077S3VersionKey9B7B46A0', + Bucket: 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}', + Key: 'b61797635329f0b0ec0b710b31d49f0e41c1936849266d8a9aed82e1616c9077', }; - -export function linuxCloudWatchScriptBoilerplate(scriptParams: string) { - return [ - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - "')\naws s3 cp 's3://", - { - Ref: CWA_ASSET_LINUX.Bucket, - }, - '/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - "' '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - "'\nset -e\nchmod +x '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - "'\n'/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - "' -i ", - { - Ref: 'AWS::Region', - }, - ' ', - { - Ref: 'ConfigStringParameterC2BE550F', - }, - "\nmkdir -p $(dirname '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - "')\naws s3 cp 's3://", - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Bucket}, - '/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - "' '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - "'\nmkdir -p $(dirname '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - '\')\naws s3 cp \'s3://', - {Ref: CONFIG_WORKER_ASSET_LINUX.Bucket}, - '/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - '\' \'/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - '\'\n' + - 'set -e\n' + - 'chmod +x \'/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - '\'\n\'/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - scriptParams, - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - ]; -} - -export function linuxConfigureWorkerScriptBoilerplate(scriptParams: string) { - return [ - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - "')\naws s3 cp 's3://", - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Bucket}, - '/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - "' '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - "'\nmkdir -p $(dirname '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - '\')\naws s3 cp \'s3://', - {Ref: CONFIG_WORKER_ASSET_LINUX.Bucket}, - '/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - '\' \'/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - '\'\n' + - 'set -e\n' + - 'chmod +x \'/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - '\'\n\'/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - scriptParams, - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - ]; -} - -export function windowsCloudWatchScriptBoilerplate(scriptParams: string) { - return [ - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - "' ) -ea 0\nRead-S3Object -BucketName '", - { Ref: CWA_ASSET_WINDOWS.Bucket }, - "' -key '", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - "' -file 'C:/temp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - "' -ErrorAction Stop\n&'C:/temp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - "' -i ", - { Ref: 'AWS::Region' }, - ' ', - { Ref: 'ConfigStringParameterC2BE550F' }, - "\nif (!$?) { Write-Error 'Failed to execute the file \"C:/temp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - "\"' -ErrorAction Stop }\nmkdir (Split-Path -Path 'C:/temp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - '\' ) -ea 0\nRead-S3Object -BucketName \'', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Bucket}, - '\' -key \'', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - '\' -file \'C:/temp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - "' -ErrorAction Stop\nmkdir (Split-Path -Path 'C:/temp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - "' ) -ea 0\nRead-S3Object -BucketName '", - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Bucket}, - "' -key '", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - "' -file 'C:/temp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - '\' -ErrorAction Stop\n&\'C:/temp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - scriptParams, - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { - Ref: CONFIG_WORKER_ASSET_WINDOWS.Key, - }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { - Ref: CONFIG_WORKER_ASSET_WINDOWS.Key, - }, - ], - }, - ], - }, - '\nif (!$?) { Write-Error \'Failed to execute the file \"C:/temp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - ]; -} - -export function windowsConfigureWorkerScriptBoilerplate(scriptParams: string) { - return [ - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - '\' ) -ea 0\nRead-S3Object -BucketName \'', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Bucket}, - '\' -key \'', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - '\' -file \'C:/temp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - "' -ErrorAction Stop\nmkdir (Split-Path -Path 'C:/temp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - "' ) -ea 0\nRead-S3Object -BucketName '", - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Bucket}, - "' -key '", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - "' -file 'C:/temp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - '\' -ErrorAction Stop\n&\'C:/temp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - scriptParams, - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { - Ref: CONFIG_WORKER_ASSET_WINDOWS.Key, - }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { - Ref: CONFIG_WORKER_ASSET_WINDOWS.Key, - }, - ], - }, - ], - }, - '\nif (!$?) { Write-Error \'Failed to execute the file \"C:/temp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - ]; -} diff --git a/packages/aws-rfdk/lib/deadline/test/configure-spot-event-plugin.test.ts b/packages/aws-rfdk/lib/deadline/test/configure-spot-event-plugin.test.ts index 947c81041..bc907032a 100644 --- a/packages/aws-rfdk/lib/deadline/test/configure-spot-event-plugin.test.ts +++ b/packages/aws-rfdk/lib/deadline/test/configure-spot-event-plugin.test.ts @@ -4,14 +4,16 @@ */ import { - expect as cdkExpect, - countResources, - haveResourceLike, - objectLike, - arrayWith, - countResourcesLike, - ABSENT, -} from '@aws-cdk/assert'; + App, + Duration, + Expiration, + Stack, +} from 'aws-cdk-lib'; +import { + Annotations, + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { GenericWindowsImage, InstanceClass, @@ -19,18 +21,12 @@ import { InstanceType, SubnetType, Vpc, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { ContainerImage, -} from '@aws-cdk/aws-ecs'; -import { ManagedPolicy } from '@aws-cdk/aws-iam'; -import { PrivateHostedZone } from '@aws-cdk/aws-route53'; -import { - App, - Duration, - Expiration, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ecs'; +import { ManagedPolicy } from 'aws-cdk-lib/aws-iam'; +import { PrivateHostedZone } from 'aws-cdk-lib/aws-route53'; import { X509CertificatePem } from '../../core'; import { tagFields } from '../../core/lib/runtime-info'; import { @@ -51,6 +47,8 @@ import { SpotEventPluginFleet, } from '../lib/spot-event-plugin-fleet'; +import { resourcePropertiesCountIs } from './test-helper'; + describe('ConfigureSpotEventPlugin', () => { let stack: Stack; let vpc: Vpc; @@ -116,8 +114,8 @@ describe('ConfigureSpotEventPlugin', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('Custom::RFDK_ConfigureSpotEventPlugin', objectLike({ - spotPluginConfigurations: objectLike({ + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_ConfigureSpotEventPlugin', Match.objectLike({ + spotPluginConfigurations: Match.objectLike({ AWSInstanceStatus: 'Disabled', DeleteInterruptedSlaves: false, DeleteTerminatedSlaves: false, @@ -130,7 +128,7 @@ describe('ConfigureSpotEventPlugin', () => { State: 'Global Enabled', StrictHardCap: false, }), - }))); + })); }); test('with custom spot event plugin properties', () => { @@ -160,8 +158,8 @@ describe('ConfigureSpotEventPlugin', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('Custom::RFDK_ConfigureSpotEventPlugin', objectLike({ - spotPluginConfigurations: objectLike({ + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_ConfigureSpotEventPlugin', Match.objectLike({ + spotPluginConfigurations: Match.objectLike({ AWSInstanceStatus: 'ExtraInfo0', DeleteInterruptedSlaves: true, DeleteTerminatedSlaves: true, @@ -174,7 +172,7 @@ describe('ConfigureSpotEventPlugin', () => { State: 'Disabled', StrictHardCap: true, }), - }))); + })); }); test('without spot fleets', () => { @@ -185,9 +183,9 @@ describe('ConfigureSpotEventPlugin', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('Custom::RFDK_ConfigureSpotEventPlugin', { - spotFleetRequestConfigurations: ABSENT, - })); + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_ConfigureSpotEventPlugin', { + spotFleetRequestConfigurations: Match.absent(), + }); }); test('provides RQ connection parameters to custom resource', () => { @@ -201,13 +199,13 @@ describe('ConfigureSpotEventPlugin', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('Custom::RFDK_ConfigureSpotEventPlugin', objectLike({ - connection: objectLike({ + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_ConfigureSpotEventPlugin', Match.objectLike({ + connection: Match.objectLike({ hostname: stack.resolve(renderQueue.endpoint.hostname), port: stack.resolve(renderQueue.endpoint.portAsString()), protocol: stack.resolve(renderQueue.endpoint.applicationProtocol.toString()), }), - }))); + })); }); test('with default spot fleet request configuration', () => { @@ -222,33 +220,33 @@ describe('ConfigureSpotEventPlugin', () => { const rfdkTag = tagFields(fleet); // THEN - cdkExpect(stack).to(haveResourceLike('Custom::RFDK_ConfigureSpotEventPlugin', { + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_ConfigureSpotEventPlugin', { spotFleetRequestConfigurations: { [groupName]: { AllocationStrategy: 'lowestPrice', IamFleetRole: stack.resolve(fleet.fleetRole.roleArn), - LaunchTemplateConfigs: [ - { + LaunchTemplateConfigs: Match.arrayWith([ + Match.objectLike({ LaunchTemplateSpecification: { Version: '$Latest', LaunchTemplateId: stack.resolve(fleet.launchTemplate.launchTemplateId), }, - }, - ], - TagSpecifications: arrayWith( - objectLike({ + }), + ]), + TagSpecifications: Match.arrayWith([ + Match.objectLike({ ResourceType: 'spot-fleet-request', - Tags: arrayWith( + Tags: Match.arrayWith([ { Key: rfdkTag.name, Value: rfdkTag.value, }, - ), + ]), }), - ), + ]), }, }, - })); + }); }); test('adds policies to the render queue', () => { @@ -262,14 +260,14 @@ describe('ConfigureSpotEventPlugin', () => { }); // THEN - cdkExpect(stack).to(countResourcesLike('AWS::IAM::Role', 1, { - ManagedPolicyArns: arrayWith( + resourcePropertiesCountIs(stack, 'AWS::IAM::Role', { + ManagedPolicyArns: Match.arrayWith([ stack.resolve(ManagedPolicy.fromAwsManagedPolicyName('AWSThinkboxDeadlineSpotEventPluginAdminPolicy').managedPolicyArn), stack.resolve(ManagedPolicy.fromAwsManagedPolicyName('AWSThinkboxDeadlineResourceTrackerAdminPolicy').managedPolicyArn), - ), - })); + ]), + }, 1); - cdkExpect(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -298,7 +296,7 @@ describe('ConfigureSpotEventPlugin', () => { Roles: [{ Ref: 'RQRCSTaskTaskRole00DC9B43', }], - })); + }); }); test('adds resource tracker policy even if rt disabled', () => { @@ -315,11 +313,11 @@ describe('ConfigureSpotEventPlugin', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('AWS::IAM::Role', { - ManagedPolicyArns: arrayWith( + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { + ManagedPolicyArns: Match.arrayWith([ stack.resolve(ManagedPolicy.fromAwsManagedPolicyName('AWSThinkboxDeadlineResourceTrackerAdminPolicy').managedPolicyArn), - ), - })); + ]), + }); }); test.each([ @@ -334,18 +332,18 @@ describe('ConfigureSpotEventPlugin', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('Custom::RFDK_ConfigureSpotEventPlugin', objectLike({ - spotFleetRequestConfigurations: ABSENT, - }))); + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_ConfigureSpotEventPlugin', Match.objectLike({ + spotFleetRequestConfigurations: Match.absent(), + })); - cdkExpect(stack).notTo(haveResourceLike('AWS::IAM::Role', { - ManagedPolicyArns: arrayWith( + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', Match.not({ + ManagedPolicyArns: Match.arrayWith([ stack.resolve(ManagedPolicy.fromAwsManagedPolicyName('AWSThinkboxDeadlineSpotEventPluginAdminPolicy').managedPolicyArn), stack.resolve(ManagedPolicy.fromAwsManagedPolicyName('AWSThinkboxDeadlineResourceTrackerAdminPolicy').managedPolicyArn), - ), + ]), })); - cdkExpect(stack).notTo(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', Match.not({ PolicyDocument: { Statement: [ { @@ -401,13 +399,13 @@ describe('ConfigureSpotEventPlugin', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('Custom::RFDK_ConfigureSpotEventPlugin', objectLike({ - spotFleetRequestConfigurations: objectLike({ - [groupName]: objectLike({ + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_ConfigureSpotEventPlugin', Match.objectLike({ + spotFleetRequestConfigurations: Match.objectLike({ + [groupName]: Match.objectLike({ ValidUntil: validUntil.date.toISOString(), }), }), - }))); + })); }); }); @@ -468,7 +466,7 @@ describe('ConfigureSpotEventPlugin', () => { }); // THEN - cdkExpect(stack).to(countResources('Custom::RFDK_ConfigureSpotEventPlugin', 2)); + Template.fromStack(stack).resourceCountIs('Custom::RFDK_ConfigureSpotEventPlugin', 2); }); test('throws with not supported render queue', () => { @@ -568,7 +566,7 @@ describe('ConfigureSpotEventPlugin', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -586,7 +584,7 @@ describe('ConfigureSpotEventPlugin', () => { Ref: 'ConfigureSpotEventPluginConfiguratorServiceRole341B4735', }, ], - })); + }); }); test('creates a custom resource with connection', () => { @@ -600,14 +598,14 @@ describe('ConfigureSpotEventPlugin', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('Custom::RFDK_ConfigureSpotEventPlugin', objectLike({ - connection: objectLike({ + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_ConfigureSpotEventPlugin', Match.objectLike({ + connection: Match.objectLike({ hostname: stack.resolve(renderQueueWithTls.endpoint.hostname), port: stack.resolve(renderQueueWithTls.endpoint.portAsString()), protocol: stack.resolve(renderQueueWithTls.endpoint.applicationProtocol.toString()), caCertificateArn: stack.resolve((renderQueueWithTls as RenderQueue).certChain!.secretArn), }), - }))); + })); }); }); @@ -648,14 +646,14 @@ describe('ConfigureSpotEventPlugin', () => { }); // THEN - cdkExpect(stack).to(haveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'configure-spot-event-plugin.configureSEP', VpcConfig: { SubnetIds: [ stack.resolve(vpc.privateSubnets[0].subnetId), ], }, - })); + }); }); describe('throws with wrong deadline version', () => { @@ -781,10 +779,10 @@ describe('ConfigureSpotEventPlugin', () => { }); // THEN - expect(fleet.node.metadataEntry).toContainEqual(expect.objectContaining({ - type: 'aws:cdk:warning', - data: 'Deadline Secrets Management is enabled on the Repository and VPC subnets have not been supplied. Using dedicated subnets is recommended. See https://github.com/aws/aws-rfdk/blobs/release/packages/aws-rfdk/lib/deadline/README.md#using-dedicated-subnets-for-deadline-components', - })); + Annotations.fromStack(stack).hasWarning( + `/${fleet.node.path}`, + 'Deadline Secrets Management is enabled on the Repository and VPC subnets have not been supplied. Using dedicated subnets is recommended. See https://github.com/aws/aws-rfdk/blobs/release/packages/aws-rfdk/lib/deadline/README.md#using-dedicated-subnets-for-deadline-components', + ); }); test('a fleet with vpcSubnets specified => does not warn about dedicated subnets', () => { @@ -813,10 +811,7 @@ describe('ConfigureSpotEventPlugin', () => { }); // THEN - expect(fleet.node.metadataEntry).not.toContainEqual(expect.objectContaining({ - type: 'aws:cdk:warning', - data: expect.stringMatching(/dedicated subnet/i), - })); + Annotations.fromStack(stack).hasNoWarning(`/${fleet.node.path}`, Match.stringLikeRegexp('.*dedicated subnet.*')); }); }); }); diff --git a/packages/aws-rfdk/lib/deadline/test/database-connection.test.ts b/packages/aws-rfdk/lib/deadline/test/database-connection.test.ts index 897a241ea..6adea5605 100644 --- a/packages/aws-rfdk/lib/deadline/test/database-connection.test.ts +++ b/packages/aws-rfdk/lib/deadline/test/database-connection.test.ts @@ -4,16 +4,21 @@ */ import { - expect as expectCDK, - haveResource, - haveResourceLike, - ResourcePart, -} from '@aws-cdk/assert'; + Duration, + Resource, + ResourceEnvironment, + Stack, +} from 'aws-cdk-lib'; +import { + Annotations, + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { DatabaseCluster, Endpoint, IDatabaseCluster, -} from '@aws-cdk/aws-docdb'; +} from 'aws-cdk-lib/aws-docdb'; import { AmazonLinuxGeneration, Connections, @@ -27,26 +32,20 @@ import { Volume, Vpc, WindowsVersion, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { AccountRootPrincipal, Role, -} from '@aws-cdk/aws-iam'; +} from 'aws-cdk-lib/aws-iam'; import { IPrivateHostedZone, PrivateHostedZone, -} from '@aws-cdk/aws-route53'; +} from 'aws-cdk-lib/aws-route53'; import { Secret, SecretAttachmentTargetProps, -} from '@aws-cdk/aws-secretsmanager'; -import { - Construct, - Duration, - Resource, - ResourceEnvironment, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-secretsmanager'; +import {Construct} from 'constructs'; import * as sinon from 'sinon'; import { @@ -63,6 +62,10 @@ import { DatabaseConnection, } from '../lib'; +import { + GET_SECRET_TO_FILE_SCRIPT_LINUX, +} from './asset-constants'; + describe('DocumentDB', () => { let stack: Stack; let vpc: Vpc; @@ -105,7 +108,7 @@ describe('DocumentDB', () => { connection.grantRead(role); // THEN - expectCDK(stack).to(haveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Version: '2012-10-17', Statement: [{ @@ -117,7 +120,7 @@ describe('DocumentDB', () => { Resource: {Ref: 'DbClusterSecretAttachment4201A1ED'}, }], }, - })); + }); }); test('addInstallerDBArgs defines required elements', () => { @@ -150,7 +153,7 @@ describe('DocumentDB', () => { connection.allowConnectionsFrom(securityGroup); // THEN - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', FromPort: { 'Fn::GetAtt': [ @@ -170,7 +173,7 @@ describe('DocumentDB', () => { 'Port', ], }, - })); + }); }); test('add child dependency', () => { @@ -186,12 +189,12 @@ describe('DocumentDB', () => { connection.addChildDependency(instance); // THEN - expectCDK(stack).to(haveResourceLike('AWS::EC2::Instance', { + Template.fromStack(stack).hasResource('AWS::EC2::Instance', { DependsOn: [ 'DbClusterInstance155835CE5', 'InstanceInstanceRoleE9785DE5', ], - }, ResourcePart.CompleteDefinition)); + }); }); test('add child dependency to attributes', () => { @@ -218,11 +221,11 @@ describe('DocumentDB', () => { connection.addChildDependency(instance); // THEN - expectCDK(stack).to(haveResourceLike('AWS::EC2::Instance', { + Template.fromStack(stack).hasResource('AWS::EC2::Instance', { DependsOn: [ 'InstanceInstanceRoleE9785DE5', ], - }, ResourcePart.CompleteDefinition)); + }); }); test('add child dependency throws when cluster implementation changed', () => { @@ -306,13 +309,11 @@ describe('DocumentDB', () => { connection.addSecurityGroup(securityGroup); // THEN - expect(fakeDatabase.node.metadataEntry).toEqual(expect.arrayContaining([ - expect.objectContaining({ - type: 'aws:cdk:warning', - data: expect.stringMatching(new RegExp(`Failed to add the following security groups to ${fakeDatabase.node.id}: .*\\. ` + - 'The \\"database\\" property passed to this class is not an instance of AWS CDK\'s DocumentDB cluster construct.')), - }), - ])); + Annotations.fromStack(stack).hasWarning( + `/${fakeDatabase.node.path}`, + Match.stringLikeRegexp(`Failed to add the following security groups to ${fakeDatabase.node.id}: .*\\. ` + + 'The \\"database\\" property passed to this class is not an instance of AWS CDK\'s DocumentDB cluster construct.'), + ); }); // This test can be removed once the following CDK PR is merged: @@ -329,13 +330,11 @@ describe('DocumentDB', () => { connection.addSecurityGroup(securityGroup); // THEN - expect(database.node.metadataEntry).toEqual(expect.arrayContaining([ - expect.objectContaining({ - type: 'aws:cdk:warning', - data: expect.stringMatching(new RegExp(`Failed to add the following security groups to ${database.node.id}: .*\\. ` + - 'The internal implementation of AWS CDK\'s DocumentDB cluster construct has changed.')), - }), - ])); + Annotations.fromStack(stack).hasWarning( + `/${database.node.path}`, + Match.stringLikeRegexp(`Failed to add the following security groups to ${database.node.id}: .*\\. ` + + 'The internal implementation of AWS CDK\'s DocumentDB cluster construct has changed.'), + ); }); test('Document DB connection is pointed to correct construct', () => { @@ -380,7 +379,9 @@ describe('DocumentDB Version Checks', () => { DatabaseConnection.forDocDB({database, login: database.secret!}); // THEN - expect(database.node.metadataEntry.length).toBe(0); + Annotations.fromStack(stack).hasNoInfo(`/${database.node.path}`, Match.anyValue()); + Annotations.fromStack(stack).hasNoWarning(`/${database.node.path}`, Match.anyValue()); + Annotations.fromStack(stack).hasNoError(`/${database.node.path}`, Match.anyValue()); }); test('When from attributes', () => { @@ -403,7 +404,9 @@ describe('DocumentDB Version Checks', () => { const databaseConnection = DatabaseConnection.forDocDB({database, login: secret}); // THEN - expect(database.node.metadataEntry.length).toBe(0); + Annotations.fromStack(stack).hasNoInfo(`/${database.node.path}`, Match.anyValue()); + Annotations.fromStack(stack).hasNoWarning(`/${database.node.path}`, Match.anyValue()); + Annotations.fromStack(stack).hasNoError(`/${database.node.path}`, Match.anyValue()); expect(databaseConnection.databaseConstruct).toBeUndefined(); }); @@ -431,13 +434,9 @@ describe('DocumentDB Version Checks', () => { DatabaseConnection.forDocDB({database, login: database.secret!}); // THEN - expect(database.node.metadataEntry).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - type: 'aws:cdk:error', - data: 'engineVersion must be 3.6.0 to be compatible with Deadline', - }), - ]), + Annotations.fromStack(stack).hasError( + `/${database.node.path}`, + 'engineVersion must be 3.6.0 to be compatible with Deadline', ); }); @@ -466,13 +465,9 @@ describe('DocumentDB Version Checks', () => { DatabaseConnection.forDocDB({database, login: database.secret!}); // THEN - expect(database.node.metadataEntry).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - type: 'aws:cdk:error', - data: 'engineVersion must be 3.6.0 to be compatible with Deadline', - }), - ]), + Annotations.fromStack(stack).hasError( + `/${database.node.path}`, + 'engineVersion must be 3.6.0 to be compatible with Deadline', ); }); }); @@ -534,7 +529,7 @@ describe('MongoDB', () => { connection.grantRead(role); // THEN - expectCDK(stack).to(haveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Version: '2012-10-17', Statement: [ @@ -563,7 +558,7 @@ describe('MongoDB', () => { }, ], }, - })); + }); }); test('addInstallerDBArgs defines required elements', () => { @@ -581,7 +576,7 @@ describe('MongoDB', () => { // THEN const token = '${Token[TOKEN.\\d+]}'; - expect(userData).toMatch(new RegExp(escapeTokenRegex('\'/tmp/' + token + token + '\' ' + token + ' /opt/Thinkbox/certs/mongo_client.pfx'))); + expect(userData).toMatch(new RegExp(escapeTokenRegex(`'/tmp/${GET_SECRET_TO_FILE_SCRIPT_LINUX.Key}.sh' ${token} /opt/Thinkbox/certs/mongo_client.pfx`))); expect(userData).toContain('configure_database_installation_args(){\n'); expect(userData).toContain('\nexport -f configure_database_installation_args'); expect(userData).toContain('{ set +x; } 2>/dev/null'); @@ -607,7 +602,7 @@ describe('MongoDB', () => { // THEN const token = '${Token[TOKEN.\\d+]}'; - expect(userData).toMatch(new RegExp(escapeTokenRegex('\'/tmp/' + token + token + '\' ' + token + ' /opt/Thinkbox/certs/mongo_client.pfx'))); + expect(userData).toMatch(new RegExp(escapeTokenRegex(`'/tmp/${GET_SECRET_TO_FILE_SCRIPT_LINUX.Key}.sh' ${token} /opt/Thinkbox/certs/mongo_client.pfx`))); expect(userData).toContain('configure_deadline_database(){\n'); expect(userData).toContain('\nexport -f configure_deadline_database'); expect(userData).toContain('{ set +x; } 2>/dev/null'); @@ -635,7 +630,7 @@ describe('MongoDB', () => { connection.allowConnectionsFrom(securityGroup); // THEN - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', FromPort: 27017, ToPort: 27017, @@ -651,7 +646,7 @@ describe('MongoDB', () => { 'GroupId', ], }, - })); + }); }); test('add child dependency', () => { @@ -667,12 +662,12 @@ describe('MongoDB', () => { connection.addChildDependency(instance); // THEN - expectCDK(stack).to(haveResourceLike('AWS::EC2::Instance', { + Template.fromStack(stack).hasResource('AWS::EC2::Instance', { DependsOn: [ 'InstanceInstanceRoleE9785DE5', 'MongoDbServerAsgASG47B3D94E', ], - }, ResourcePart.CompleteDefinition)); + }); }); test('asserts linux-only', () => { diff --git a/packages/aws-rfdk/lib/deadline/test/render-queue.test.ts b/packages/aws-rfdk/lib/deadline/test/render-queue.test.ts index 76c7bd68f..5ebf64a8c 100644 --- a/packages/aws-rfdk/lib/deadline/test/render-queue.test.ts +++ b/packages/aws-rfdk/lib/deadline/test/render-queue.test.ts @@ -4,25 +4,21 @@ */ import { - ABSENT, - arrayWith, - countResources, - countResourcesLike, - deepObjectLike, - expect as expectCDK, - haveResource, - haveResourceLike, - not, - objectLike, - ResourcePart, - SynthUtils, -} from '@aws-cdk/assert'; + App, + CfnElement, + CustomResource, + Stack, +} from 'aws-cdk-lib'; +import { + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { CfnLaunchConfiguration, -} from '@aws-cdk/aws-autoscaling'; +} from 'aws-cdk-lib/aws-autoscaling'; import { Certificate, -} from '@aws-cdk/aws-certificatemanager'; +} from 'aws-cdk-lib/aws-certificatemanager'; import { AmazonLinuxGeneration, AmazonLinuxImage, @@ -38,40 +34,35 @@ import { SubnetType, Vpc, WindowsVersion, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { ContainerImage, Ec2TaskDefinition, TaskDefinition, -} from '@aws-cdk/aws-ecs'; +} from 'aws-cdk-lib/aws-ecs'; import { ApplicationProtocol, -} from '@aws-cdk/aws-elasticloadbalancingv2'; +} from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import { AccountRootPrincipal, Role, -} from '@aws-cdk/aws-iam'; +} from 'aws-cdk-lib/aws-iam'; import { PrivateHostedZone, -} from '@aws-cdk/aws-route53'; +} from 'aws-cdk-lib/aws-route53'; import { Bucket, -} from '@aws-cdk/aws-s3'; +} from 'aws-cdk-lib/aws-s3'; import { CfnSecret, Secret, -} from '@aws-cdk/aws-secretsmanager'; -import { - App, - CfnElement, - CustomResource, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-secretsmanager'; import { ImportedAcmCertificate, X509CertificatePem, } from '../..'; +import { DeploymentInstance } from '../../core/lib/deployment-instance'; import { testConstructTags, } from '../../core/test/tag-helpers'; @@ -91,6 +82,9 @@ import { SecretsManagementIdentityRegistration } from '../lib/secrets-management import { RQ_CONNECTION_ASSET, } from './asset-constants'; +import { + resourcePropertiesCountIs, +} from './test-helper'; describe('RenderQueue', () => { let app: App; @@ -100,423 +94,491 @@ describe('RenderQueue', () => { let rcsImage: ContainerImage; let images: RenderQueueImages; - let repository: Repository; let version: IVersion; let renderQueueVersion: IVersion; - let renderQueueCommon: RenderQueue; - // GIVEN beforeEach(() => { app = new App(); dependencyStack = new Stack(app, 'DepStack'); vpc = new Vpc(dependencyStack, 'Vpc'); version = new VersionQuery(dependencyStack, 'Version'); - repository = new Repository(dependencyStack, 'Repo', { - version, - vpc, - }); + stack = new Stack(app, 'Stack'); rcsImage = ContainerImage.fromAsset(__dirname); images = { remoteConnectionServer: rcsImage, }; renderQueueVersion = new VersionQuery(stack, 'Version'); - renderQueueCommon = new RenderQueue(stack, 'RenderQueueCommon', { - images, - repository, - version: renderQueueVersion, - vpc, - }); }); afterEach(() => { jest.resetAllMocks(); }); - test('creates cluster', () => { - // THEN - expectCDK(stack).to(haveResource('AWS::ECS::Cluster')); - }); + describe('basic', () => { + let repository: Repository; + let renderQueue: RenderQueue; - test('creates service', () => { - // THEN - expectCDK(stack).to(haveResource('AWS::ECS::Service')); - }); + beforeEach(() => { + repository = new Repository(dependencyStack, 'Repo', { + version, + vpc, + }); + renderQueue = new RenderQueue(stack, 'RenderQueue', { + images, + repository, + version: renderQueueVersion, + vpc, + }); + }); - test('creates task definition', () => { - // THEN - expectCDK(stack).to(haveResource('AWS::ECS::TaskDefinition')); - }); + test('creates cluster', () => { + // THEN + Template.fromStack(stack).resourceCountIs('AWS::ECS::Cluster', 1); + }); - test('closed ingress by default', () => { - // THEN - expectCDK(stack).notTo(haveResource('AWS::EC2::SecurityGroup', { - // The openListener=true option would create an ingress rule in the listener's SG. - // make sure that we don't have that. - SecurityGroupIngress: arrayWith(objectLike({})), - })); - }); + test('creates service', () => { + // THEN + Template.fromStack(stack).resourceCountIs('AWS::ECS::Service', 1); + }); - test('creates load balancer with default values', () => { - // THEN - expectCDK(stack).to(countResourcesLike('AWS::ElasticLoadBalancingV2::LoadBalancer', 1, { - LoadBalancerAttributes: [ - { - Key: 'deletion_protection.enabled', - Value: 'true', - }, - ], - Scheme: 'internal', - })); - }); + test('creates task definition', () => { + // THEN + Template.fromStack(stack).resourceCountIs('AWS::ECS::TaskDefinition', 1); + }); - test('creates a log group with default prefix of "/renderfarm/"', () => { - // THEN - expectCDK(stack).to(haveResourceLike('Custom::LogRetention', { - LogGroupName: '/renderfarm/RenderQueueCommon', - RetentionInDays: 3, - })); - }); + test('closed ingress by default', () => { + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', Match.not({ + // The openListener=true option would create an ingress rule in the listener's SG. + // make sure that we don't have that. + // DDN - intentionally broke + SecurityGroupIngress: Match.anyValue(), + })); + }); - test('configure the container log driver', () => { - // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::TaskDefinition', { - ContainerDefinitions: [ - objectLike({ - LogConfiguration: { - LogDriver: 'awslogs', - Options: { - 'awslogs-group': { - 'Fn::GetAtt': [ - 'RenderQueueCommonLogGroupWrapperA0EF7057', - 'LogGroupName', - ], + test('creates load balancer with default values', () => { + // THEN + resourcePropertiesCountIs(stack, 'AWS::ElasticLoadBalancingV2::LoadBalancer', { + LoadBalancerAttributes: Match.arrayWith([ + { + Key: 'deletion_protection.enabled', + Value: 'true', + }, + ]), + Scheme: 'internal', + }, 1); + }); + + test('creates a log group with default prefix of "/renderfarm/"', () => { + // THEN + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { + LogGroupName: '/renderfarm/RenderQueue', + RetentionInDays: 3, + }); + }); + + test('configure the container log driver', () => { + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { + ContainerDefinitions: [ + Match.objectLike({ + LogConfiguration: { + LogDriver: 'awslogs', + Options: { + 'awslogs-group': { + 'Fn::GetAtt': [ + Match.stringLikeRegexp('^RenderQueueLogGroupWrapper.*'), + 'LogGroupName', + ], + }, + 'awslogs-stream-prefix': 'RCS', + 'awslogs-region': { Ref: 'AWS::Region' }, }, - 'awslogs-stream-prefix': 'RCS', - 'awslogs-region': { Ref: 'AWS::Region' }, }, - }, - }), - ], - })); - }); + }), + ], + }); + }); - test('child dependencies added', () => { - // GIVEN - const host = new Instance(stack, 'Host', { - vpc, - instanceType: InstanceType.of( - InstanceClass.R4, - InstanceSize.LARGE, - ), - machineImage: MachineImage.latestAmazonLinux({ generation: AmazonLinuxGeneration.AMAZON_LINUX_2 }), + test('child dependencies added', () => { + // GIVEN + const host = new Instance(stack, 'Host', { + vpc, + instanceType: InstanceType.of( + InstanceClass.R4, + InstanceSize.LARGE, + ), + machineImage: MachineImage.latestAmazonLinux({ generation: AmazonLinuxGeneration.AMAZON_LINUX_2 }), + }); + + // WHEN + renderQueue.addChildDependency(host); + + // THEN + Template.fromStack(stack).hasResource('AWS::EC2::Instance', { + DependsOn: Match.arrayWith([ + 'RenderQueueAlbEc2ServicePatternService5B6692FB', + 'RenderQueueLBPublicListenerBBF15D5F', + 'RenderQueueRCSTaskA9AE70D3', + 'RenderQueueWaitForStableService4B92A8D2', + ]), + }); }); - // WHEN - renderQueueCommon.addChildDependency(host); + describe('renderQueueSize.min', () => { + describe('defaults to 1', () => { + function assertSpecifiesMinSize(stackToAssert: Stack) { + Template.fromStack(stackToAssert).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { + MinSize: '1', + }); + } - // THEN - expectCDK(stack).to(haveResourceLike('AWS::EC2::Instance', { - DependsOn: arrayWith( - 'RenderQueueCommonLBPublicListener935F5635', - 'RenderQueueCommonRCSTask2A4D5EA5', - 'RenderQueueCommonAlbEc2ServicePatternService42BEFF4C', - 'RenderQueueCommonWaitForStableServiceDB53E266', - ), - }, ResourcePart.CompleteDefinition)); - }); + test('renderQueueSize unspecified', () => { + // THEN + assertSpecifiesMinSize(stack); + }); - describe('renderQueueSize.min', () => { - describe('defaults to 1', () => { - function assertSpecifiesMinSize(stackToAssert: Stack) { - expectCDK(stackToAssert).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { - MinSize: '1', - })); - } + test('renderQueueSize.min unspecified', () => { + // GIVEN + const isolatedStack = new Stack(app, 'IsolatedStack'); - test('renderQueueSize unspecified', () => { - // THEN - assertSpecifiesMinSize(stack); + // WHEN + new RenderQueue(isolatedStack, 'RenderQueue', { + images, + repository, + version: new VersionQuery(isolatedStack, 'Version'), + vpc, + renderQueueSize: {}, + }); + + // THEN + assertSpecifiesMinSize(isolatedStack); + }); }); - test('renderQueueSize.min unspecified', () => { + // Asserts that at least one RCS container and ASG instance must be created. + test('throws error when minimum size is 0', () => { // GIVEN - const isolatedStack = new Stack(app, 'IsolatedStack'); + const props: RenderQueueProps = { + images, + repository, + version: renderQueueVersion, + vpc, + renderQueueSize: { + min: 0, + }, + }; // WHEN - new RenderQueue(isolatedStack, 'RenderQueue', { + expect(() => { + new RenderQueue(stack, 'RenderQueueTest', props); + }) + // THEN + .toThrow('renderQueueSize.min capacity must be at least 1: got 0'); + }); + + // Deadline before 10.1.10 requires that successive API requests are serviced by a single RCS. + test('validates Deadline pre 10.1.10 has min value of at most 1', () => { + // GIVEN + const min = 2; + const newStack = new Stack(app, 'NewStack'); + const versionOld = new VersionQuery(newStack, 'VersionOld', {version: '10.1.9'}); + const props: RenderQueueProps = { images, repository, - version: new VersionQuery(isolatedStack, 'Version'), + version: versionOld, vpc, - renderQueueSize: {}, - }); + renderQueueSize: { + min, + }, + }; + // WHEN + expect(() => { + new RenderQueue(newStack, 'RenderQueueTest', props); + }) // THEN - assertSpecifiesMinSize(isolatedStack); + .toThrow(`renderQueueSize.min for Deadline version less than 10.1.10.0 cannot be greater than 1 - got ${min}`); }); - }); - // Asserts that at least one RCS container and ASG instance must be created. - test('throws error when minimum size is 0', () => { - // GIVEN - const props: RenderQueueProps = { - images, - repository, - version: renderQueueVersion, - vpc, - renderQueueSize: { - min: 0, - }, - }; + // Asserts that when the renderQueueSize.min prop is specified, the underlying ASG's min property is set accordingly. + test.each([ + [1], + [2], + [10], + ])('configures minimum number of ASG instances to %d', (min: number) => { + // GIVEN + const isolatedStack = new Stack(app, 'IsolatedStack'); + const props: RenderQueueProps = { + images, + repository, + version: new VersionQuery(isolatedStack, 'Version'), + vpc, + renderQueueSize: { + min, + }, + }; + + // WHEN + new RenderQueue(isolatedStack, 'RenderQueue', props); - // WHEN - expect(() => { - new RenderQueue(stack, 'RenderQueue', props); - }) // THEN - .toThrow('renderQueueSize.min capacity must be at least 1: got 0'); + Template.fromStack(isolatedStack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { + MinSize: min.toString(), + }); + }); }); - // Deadline before 10.1.10 requires that successive API requests are serviced by a single RCS. - test('validates Deadline pre 10.1.10 has min value of at most 1', () => { - // GIVEN - const min = 2; - const newStack = new Stack(app, 'NewStack'); - const versionOld = new VersionQuery(newStack, 'VersionOld', {version: '10.1.9'}); - const props: RenderQueueProps = { - images, - repository, - version: versionOld, - vpc, - renderQueueSize: { - min, - }, - }; + describe('renderQueueSize.max', () => { + describe('defaults to 1', () => { + function assertSpecifiesMaxSize(stackToAssert: Stack) { + Template.fromStack(stackToAssert).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { + MaxSize: '1', + }); + } - // WHEN - expect(() => { - new RenderQueue(newStack, 'RenderQueue', props); - }) - // THEN - .toThrow(`renderQueueSize.min for Deadline version less than 10.1.10.0 cannot be greater than 1 - got ${min}`); - }); + test('renderQueueSize unspecified', () => { + // THEN + assertSpecifiesMaxSize(stack); + }); - // Asserts that when the renderQueueSize.min prop is specified, the underlying ASG's min property is set accordingly. - test.each([ - [1], - [2], - [10], - ])('configures minimum number of ASG instances to %d', (min: number) => { - // GIVEN - const isolatedStack = new Stack(app, 'IsolatedStack'); - const props: RenderQueueProps = { - images, - repository, - version: new VersionQuery(isolatedStack, 'Version'), - vpc, - renderQueueSize: { - min, - }, - }; + test('renderQueueSize.max unspecified', () => { + // GIVEN + const isolatedStack = new Stack(app, 'IsolatedStack'); - // WHEN - new RenderQueue(isolatedStack, 'RenderQueue', props); + // WHEN + new RenderQueue(isolatedStack, 'RenderQueue', { + images, + repository, + version: new VersionQuery(isolatedStack, 'Version'), + vpc, + renderQueueSize: {}, + }); - // THEN - expectCDK(isolatedStack).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { - MinSize: min.toString(), - })); - }); - }); + // THEN + assertSpecifiesMaxSize(isolatedStack); + }); + }); - describe('renderQueueSize.max', () => { - describe('defaults to 1', () => { - function assertSpecifiesMaxSize(stackToAssert: Stack) { - expectCDK(stackToAssert).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { - MaxSize: '1', - })); - } + // Deadline before 10.1.10 requires that successive API requests are serviced by a single RCS. + test('validates Deadline pre 10.1.10 has max value of at most 1', () => { + // GIVEN + const max = 2; + const newStack = new Stack(app, 'NewStack'); + const versionOld = new VersionQuery(newStack, 'VersionOld', {version: '10.1.9'}); + const props: RenderQueueProps = { + images, + repository, + version: versionOld, + vpc, + renderQueueSize: { + max, + }, + }; - test('renderQueueSize unspecified', () => { + // WHEN + expect(() => { + new RenderQueue(newStack, 'RenderQueue', props); + }) // THEN - assertSpecifiesMaxSize(stack); + .toThrow(`renderQueueSize.max for Deadline version less than 10.1.10.0 cannot be greater than 1 - got ${max}`); }); - test('renderQueueSize.max unspecified', () => { + // Asserts that when the renderQueueSize.max prop is specified, the underlying ASG's max property is set accordingly. + test.each([ + [1], + [2], + [10], + ])('configures maximum number of ASG instances to %d', (max: number) => { // GIVEN const isolatedStack = new Stack(app, 'IsolatedStack'); - - // WHEN - new RenderQueue(isolatedStack, 'RenderQueue', { + const props: RenderQueueProps = { images, repository, version: new VersionQuery(isolatedStack, 'Version'), vpc, - renderQueueSize: {}, - }); + renderQueueSize: { + max, + }, + }; + + // WHEN + new RenderQueue(isolatedStack, 'RenderQueue', props); // THEN - assertSpecifiesMaxSize(isolatedStack); + Template.fromStack(isolatedStack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { + MaxSize: max.toString(), + }); }); }); - // Deadline before 10.1.10 requires that successive API requests are serviced by a single RCS. - test('validates Deadline pre 10.1.10 has max value of at most 1', () => { - // GIVEN - const max = 2; - const newStack = new Stack(app, 'NewStack'); - const versionOld = new VersionQuery(newStack, 'VersionOld', {version: '10.1.9'}); - const props: RenderQueueProps = { - images, - repository, - version: versionOld, - vpc, - renderQueueSize: { - max, - }, - }; + describe('renderQueueSize.desired', () => { + describe('defaults', () => { + test('unset ASG desired', () => { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { + DesiredCapacity: Match.absent(), + }); + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { + DesiredCount: 1, + }); + }); + }); - // WHEN - expect(() => { - new RenderQueue(newStack, 'RenderQueue', props); - }) - // THEN - .toThrow(`renderQueueSize.max for Deadline version less than 10.1.10.0 cannot be greater than 1 - got ${max}`); - }); + test('validates Deadline pre 10.1.10 has desired value of at most 1', () => { + // GIVEN + const desired = 2; + const newStack = new Stack(app, 'NewStack'); + const versionOld = new VersionQuery(newStack, 'VersionOld', {version: '10.1.9'}); + const props: RenderQueueProps = { + images, + repository, + version: versionOld, + vpc, + renderQueueSize: { + desired, + }, + }; - // Asserts that when the renderQueueSize.max prop is specified, the underlying ASG's max property is set accordingly. - test.each([ - [1], - [2], - [10], - ])('configures maximum number of ASG instances to %d', (max: number) => { - // GIVEN - const isolatedStack = new Stack(app, 'IsolatedStack'); - const props: RenderQueueProps = { - images, - repository, - version: new VersionQuery(isolatedStack, 'Version'), - vpc, - renderQueueSize: { - max, - }, - }; + // WHEN + expect(() => { + new RenderQueue(newStack, 'RenderQueue', props); + }) + // THEN + .toThrow(`renderQueueSize.desired for Deadline version less than 10.1.10.0 cannot be greater than 1 - got ${desired}`); + }); - // WHEN - new RenderQueue(isolatedStack, 'RenderQueue', props); + test.each([ + [1], + [2], + [10], + ])('is specified to %d', (desired: number) => { + // GIVEN + const isolatedStack = new Stack(app, 'IsolatedStack'); + const props: RenderQueueProps = { + images, + repository, + version: new VersionQuery(isolatedStack, 'Version'), + vpc, + renderQueueSize: { + desired, + }, + }; + + // WHEN + new RenderQueue(isolatedStack, 'RenderQueue', props); - // THEN - expectCDK(isolatedStack).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { - MaxSize: max.toString(), - })); + // THEN + Template.fromStack(isolatedStack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { + DesiredCapacity: desired.toString(), + }); + // THEN + Template.fromStack(isolatedStack).hasResourceProperties('AWS::ECS::Service', { + DesiredCount: desired, + }); + }); }); - }); - describe('renderQueueSize.desired', () => { - describe('defaults', () => { - test('unset ASG desired', () => { - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { - DesiredCapacity: ABSENT, - })); - expectCDK(stack).to(haveResourceLike('AWS::ECS::Service', { - DesiredCount: 1, - })); + test('creates WaitForStableService by default', () => { + // THEN + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_WaitForStableService', { + cluster: stack.resolve(renderQueue.cluster.clusterArn), + // eslint-disable-next-line dot-notation + services: [stack.resolve(renderQueue['pattern'].service.serviceArn)], }); }); - test('validates Deadline pre 10.1.10 has desired value of at most 1', () => { - // GIVEN - const desired = 2; - const newStack = new Stack(app, 'NewStack'); - const versionOld = new VersionQuery(newStack, 'VersionOld', {version: '10.1.9'}); - const props: RenderQueueProps = { - images, - repository, - version: versionOld, - vpc, - renderQueueSize: { - desired, + test('Does not enable filesystem cache by default', () => { + resourcePropertiesCountIs(stack, 'AWS::AutoScaling::LaunchConfiguration', { + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + Match.arrayWith([ + Match.stringLikeRegexp('.*# RenderQueue file caching enabled.*'), + ]), + ], + }, }, - }; + }, 0); + }); - // WHEN - expect(() => { - new RenderQueue(newStack, 'RenderQueue', props); - }) - // THEN - .toThrow(`renderQueueSize.desired for Deadline version less than 10.1.10.0 cannot be greater than 1 - got ${desired}`); + test('runs as RCS user', () => { + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { + ContainerDefinitions: Match.arrayWith([ + Match.objectLike({ User: '1000:1000' }), + ]), + }); }); - test.each([ - [1], - [2], - [10], - ])('is specified to %d', (desired: number) => { + test('.backendConnections is associated with ASG security group rules', () => { // GIVEN - const isolatedStack = new Stack(app, 'IsolatedStack'); - const props: RenderQueueProps = { - images, - repository, - version: new VersionQuery(isolatedStack, 'Version'), + const instance = new Instance(dependencyStack, 'BackendConnectionInstance', { + instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.MICRO), + machineImage: MachineImage.latestAmazonLinux(), vpc, - renderQueueSize: { - desired, - }, - }; + }); + const portNumber = 5555; + const port = Port.tcp(portNumber); + const asgSecurityGroup = renderQueue.asg.connections.securityGroups[0]; // WHEN - new RenderQueue(isolatedStack, 'RenderQueue', props); + renderQueue.backendConnections.allowFrom(instance, port); // THEN - expectCDK(isolatedStack).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { - DesiredCapacity: desired.toString(), - })); - // THEN - expectCDK(isolatedStack).to(haveResourceLike('AWS::ECS::Service', { - DesiredCount: desired, - })); + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { + IpProtocol: 'tcp', + Description: `from ${instance.connections.securityGroups[0].uniqueId}:${portNumber}`, + GroupId: stack.resolve(asgSecurityGroup.securityGroupId), + SourceSecurityGroupId: stack.resolve(instance.connections.securityGroups[0].securityGroupId), + FromPort: portNumber, + ToPort: portNumber, + }); }); }); describe('trafficEncryption', () => { describe('defaults', () => { - let isolatedStack: Stack; + let repository: Repository; beforeEach(() => { // GIVEN - isolatedStack = new Stack(app, 'IsolatedStack'); + repository = new Repository(dependencyStack, 'Repo', { + version, + vpc, + }); const props: RenderQueueProps = { images, repository, - version: new VersionQuery(isolatedStack, 'Version'), + version: renderQueueVersion, vpc, trafficEncryption: {}, }; // WHEN - new RenderQueue(isolatedStack, 'RenderQueue', props); + new RenderQueue(stack, 'RenderQueue', props); }); // THEN test('to HTTPS internally between ALB and RCS', () => { - expectCDK(isolatedStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::TargetGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::TargetGroup', { Protocol: 'HTTPS', Port: 4433, - })); + }); }); test('to HTTPS externally between clients and ALB', () => { - expectCDK(isolatedStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::Listener', { + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::Listener', { Protocol: 'HTTPS', Port: 4433, - })); + }); }); }); describe('when interalProtocol is HTTPS', () => { - let isolatedStack: Stack; + let repository: Repository; let renderQueue: RenderQueue; let caCertPemLogicalId: string; let caCertPkcsLogicalId: string; @@ -524,11 +586,14 @@ describe('RenderQueue', () => { beforeEach(() => { // GIVEN - isolatedStack = new Stack(app, 'IsolatedStack'); + repository = new Repository(dependencyStack, 'Repo', { + version, + vpc, + }); const props: RenderQueueProps = { images, repository, - version: new VersionQuery(isolatedStack, 'Version'), + version: renderQueueVersion, vpc, trafficEncryption: { internalProtocol: ApplicationProtocol.HTTPS, @@ -536,43 +601,43 @@ describe('RenderQueue', () => { }; // WHEN - renderQueue = new RenderQueue(isolatedStack, 'RenderQueue', props); + renderQueue = new RenderQueue(stack, 'RenderQueue', props); - caCertPemLogicalId = isolatedStack.getLogicalId( + caCertPemLogicalId = stack.getLogicalId( renderQueue.node.findChild('TlsCaCertPem').node.defaultChild as CfnElement, ); const caCertPkcs = renderQueue.node.findChild('TlsRcsCertBundle'); const caCertPkcsPassphrase = caCertPkcs.node.findChild('Passphrase'); - caCertPkcsLogicalId = isolatedStack.getLogicalId(caCertPkcs.node.defaultChild as CfnElement); - caCertPkcsPassphraseLogicalId = isolatedStack.getLogicalId(caCertPkcsPassphrase.node.defaultChild as CfnElement); + caCertPkcsLogicalId = stack.getLogicalId(caCertPkcs.node.defaultChild as CfnElement); + caCertPkcsPassphraseLogicalId = stack.getLogicalId(caCertPkcsPassphrase.node.defaultChild as CfnElement); }); // THEN test('ALB connects with HTTPS to port 4433', () => { - expectCDK(isolatedStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::TargetGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::TargetGroup', { Protocol: 'HTTPS', Port: 4433, - })); + }); }); test('creates RCS cert', () => { - expectCDK(isolatedStack).to(haveResourceLike('Custom::RFDK_X509Generator', { + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_X509Generator', { ServiceToken: { - 'Fn::GetAtt': arrayWith('Arn'), + 'Fn::GetAtt': Match.arrayWith(['Arn']), }, DistinguishedName: { CN: 'renderfarm.local' }, Secret: { - NamePrefix: 'IsolatedStack/RenderQueue/TlsCaCertPem', + NamePrefix: 'Stack/RenderQueue/TlsCaCertPem', }, - })); + }); }); test('grants read access to secrets containing the certs and passphrase', () => { const taskDef = renderQueue.node.findChild('RCSTask') as TaskDefinition; - const taskRoleLogicalId = isolatedStack.getLogicalId((taskDef.taskRole as Role).node.defaultChild as CfnElement); - expectCDK(isolatedStack).to(haveResourceLike('AWS::IAM::Policy', { + const taskRoleLogicalId = stack.getLogicalId((taskDef.taskRole as Role).node.defaultChild as CfnElement); + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: [ 'secretsmanager:GetSecretValue', @@ -607,60 +672,61 @@ describe('RenderQueue', () => { Effect: 'Allow', Resource: { Ref: caCertPkcsPassphraseLogicalId }, }, - ), + ]), Version: '2012-10-17', }, - Roles: arrayWith({ Ref: taskRoleLogicalId }), - })); + Roles: Match.arrayWith([{ Ref: taskRoleLogicalId }]), + }); }); test('configures environment variables for cert secret URIs', () => { - expectCDK(isolatedStack).to(haveResourceLike('AWS::ECS::TaskDefinition', { - ContainerDefinitions: arrayWith(deepObjectLike({ - Environment: arrayWith( - { - Name: 'RCS_TLS_CA_CERT_URI', - Value: { - 'Fn::GetAtt': [ - caCertPemLogicalId, - 'Cert', - ], + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { + ContainerDefinitions: Match.arrayWith([ + Match.objectLike({ + Environment: Match.arrayWith([ + { + Name: 'RCS_TLS_CA_CERT_URI', + Value: { + 'Fn::GetAtt': [ + caCertPemLogicalId, + 'Cert', + ], + }, }, - }, - { - Name: 'RCS_TLS_CERT_URI', - Value: { - 'Fn::GetAtt': [ - caCertPkcsLogicalId, - 'Cert', - ], + { + Name: 'RCS_TLS_CERT_URI', + Value: { + 'Fn::GetAtt': [ + caCertPkcsLogicalId, + 'Cert', + ], + }, }, - }, - { - Name: 'RCS_TLS_CERT_PASSPHRASE_URI', - Value: { Ref: caCertPkcsPassphraseLogicalId }, - }, - ), - })), - })); + { + Name: 'RCS_TLS_CERT_PASSPHRASE_URI', + Value: { Ref: caCertPkcsPassphraseLogicalId }, + }, + ]), + }), + ]), + }); }); }); describe('when internal protocol is HTTP', () => { - let isolatedStack: Stack; + let repository: Repository; beforeEach(() => { // GIVEN - isolatedStack = new Stack(app, 'IsolatedStack'); - const nonSmRepository = new Repository(dependencyStack, 'NonSMRepository', { + repository = new Repository(dependencyStack, 'NonSMRepository', { vpc, version, secretsManagementSettings: { enabled: false }, }); const props: RenderQueueProps = { images, - repository: nonSmRepository, - version: new VersionQuery(isolatedStack, 'Version'), + repository: repository, + version: renderQueueVersion, vpc, trafficEncryption: { internalProtocol: ApplicationProtocol.HTTP, @@ -669,39 +735,45 @@ describe('RenderQueue', () => { }; // WHEN - new RenderQueue(isolatedStack, 'RenderQueue', props); + new RenderQueue(stack, 'RenderQueue', props); }); // THEN test('no certs are created', () => { - expectCDK(isolatedStack).notTo(haveResource('Custom::RFDK_X509Generator')); + Template.fromStack(stack).resourceCountIs('Custom::RFDK_X509Generator', 0); }); test('ALB connects with HTTP to port 8080', () => { - expectCDK(isolatedStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::TargetGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::TargetGroup', { Protocol: 'HTTP', Port: 8080, - })); + }); }); }); describe('externalProtocol is HTTPS', () => { - let isolatedStack: Stack; + let repository: Repository; const CERT_ARN = 'certarn'; const CA_ARN = 'arn:aws:secretsmanager:123456789012:secret:ca/arn'; const ZONE_NAME = 'renderfarm.local'; beforeEach(() => { // GIVEN - isolatedStack = new Stack(app, 'IsolatedStack'); - const zone = new PrivateHostedZone(isolatedStack, 'RenderQueueZone', { + repository = new Repository(dependencyStack, 'Repo', { + version, + vpc, + // Cannot have secrets management unless external TLS is enabled on the RQ, + // so we disable it to allow for testing. + secretsManagementSettings: { enabled: false }, + }); + const zone = new PrivateHostedZone(stack, 'RenderQueueZone', { vpc, zoneName: ZONE_NAME, }); const props: RenderQueueProps = { images, repository, - version: new VersionQuery(isolatedStack, 'Version'), + version: renderQueueVersion, vpc, trafficEncryption: { externalTLS: { @@ -716,30 +788,30 @@ describe('RenderQueue', () => { }; // WHEN - new RenderQueue(isolatedStack, 'RenderQueue', props); + new RenderQueue(stack, 'RenderQueue', props); }); test('sets the listener port to 4433', () => { // THEN - expectCDK(isolatedStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::Listener', { + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::Listener', { Port: 4433, - })); + }); }); test('sets the listener protocol to HTTPS', () => { // THEN - expectCDK(isolatedStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::Listener', { + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::Listener', { Protocol: 'HTTPS', - })); + }); }); test('configures the ALB listener to use the specified ACM certificate', () => { - expectCDK(isolatedStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::Listener', { + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::Listener', { Protocol: 'HTTPS', - Certificates: arrayWith({ + Certificates: Match.arrayWith([{ CertificateArn: CERT_ARN, - }), - })); + }]), + }); }); test('raises an error when a cert is specified without a hosted zone', () => { @@ -759,7 +831,7 @@ describe('RenderQueue', () => { // WHEN expect(() => { - new RenderQueue(stack, 'RenderQueue', props); + new RenderQueue(stack, 'RenderQueueTest', props); }) // THEN .toThrow(/The hostname for the render queue must be defined if supplying your own certificates./); @@ -767,7 +839,7 @@ describe('RenderQueue', () => { test('raises an error when a cert is specified without a hostname', () => { // GIVEN - const zone = new PrivateHostedZone(isolatedStack, 'RenderQueueZoneNoName', { + const zone = new PrivateHostedZone(stack, 'RenderQueueZoneNoName', { vpc, zoneName: ZONE_NAME, }); @@ -788,7 +860,7 @@ describe('RenderQueue', () => { // WHEN expect(() => { - new RenderQueue(stack, 'RenderQueue', props); + new RenderQueue(stack, 'RenderQueueTest', props); }) // THEN .toThrow(/A hostname must be supplied if a certificate is supplied, with the common name of the certificate matching the hostname \+ domain name/); @@ -797,40 +869,42 @@ describe('RenderQueue', () => { describe('externalProtocol is HTTPS importing cert', () => { describe('passing cases', () => { - let isolatedStack: Stack; + let repository: Repository; let zone: PrivateHostedZone; const ZONE_NAME = 'renderfarm.local'; const HOSTNAME = 'server'; beforeEach(() => { // GIVEN - isolatedStack = new Stack(app, 'IsolatedStack'); - zone = new PrivateHostedZone(isolatedStack, 'RenderQueueZone', { + repository = new Repository(dependencyStack, 'NonSMRepository', { + vpc, + version, + // Cannot have secrets management unless external TLS is enabled on the RQ, + // so we disable it to allow for testing. + secretsManagementSettings: { enabled: false }, + }); + + zone = new PrivateHostedZone(stack, 'RenderQueueZone', { vpc, zoneName: ZONE_NAME, }); - const caCert = new X509CertificatePem(isolatedStack, 'CaCert', { + const caCert = new X509CertificatePem(stack, 'CaCert', { subject: { cn: `ca.${ZONE_NAME}`, }, }); - const serverCert = new X509CertificatePem(isolatedStack, 'ServerCert', { + const serverCert = new X509CertificatePem(stack, 'ServerCert', { subject: { cn: `${HOSTNAME}.${ZONE_NAME}`, }, signingCertificate: caCert, }); - const nonSmRepository = new Repository(dependencyStack, 'NonSMRepository', { - vpc, - version, - secretsManagementSettings: { enabled: false }, - }); const props: RenderQueueProps = { images, - repository: nonSmRepository, - version: new VersionQuery(isolatedStack, 'Version'), + repository, + version: renderQueueVersion, vpc, trafficEncryption: { externalTLS: { @@ -845,26 +919,26 @@ describe('RenderQueue', () => { }; // WHEN - new RenderQueue(isolatedStack, 'RenderQueue', props); + new RenderQueue(stack, 'RenderQueue', props); }); test('sets the listener port to 4433', () => { // THEN - expectCDK(isolatedStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::Listener', { + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::Listener', { Port: 4433, - })); + }); }); test('sets the listener protocol to HTTPS', () => { // THEN - expectCDK(isolatedStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::Listener', { + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::Listener', { Protocol: 'HTTPS', - })); + }); }); test('Imports Cert to ACM', () => { // THEN - expectCDK(isolatedStack).to(haveResourceLike('Custom::RFDK_AcmImportedCertificate', { + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_AcmImportedCertificate', { X509CertificatePem: { Cert: { 'Fn::GetAtt': [ @@ -888,7 +962,7 @@ describe('RenderQueue', () => { ], }, }, - })); + }); }); }); @@ -897,13 +971,16 @@ describe('RenderQueue', () => { const ZONE_NAME = 'renderfarm.local'; const HOSTNAME = 'server'; // GIVEN - const isolatedStack = new Stack(app, 'IsolatedStack'); - const zone = new PrivateHostedZone(isolatedStack, 'RenderQueueZone', { + const repository = new Repository(dependencyStack, 'Repo', { + version, + vpc, + }); + const zone = new PrivateHostedZone(stack, 'RenderQueueZone', { vpc, zoneName: ZONE_NAME, }); - const rootCert = new X509CertificatePem(isolatedStack, 'RootCert', { + const rootCert = new X509CertificatePem(stack, 'RootCert', { subject: { cn: `ca.${ZONE_NAME}`, }, @@ -912,7 +989,7 @@ describe('RenderQueue', () => { const props: RenderQueueProps = { images, repository, - version: new VersionQuery(isolatedStack, 'Version'), + version: renderQueueVersion, vpc, trafficEncryption: { externalTLS: { @@ -928,7 +1005,7 @@ describe('RenderQueue', () => { // WHEN expect(() => { - new RenderQueue(isolatedStack, 'RenderQueue', props); + new RenderQueue(stack, 'RenderQueue', props); }) // THEN .toThrow(/Provided rfdkCertificate does not contain a certificate chain/); @@ -938,12 +1015,15 @@ describe('RenderQueue', () => { test('Creates default RFDK cert if no cert given', () => { // GIVEN - const isolatedStack = new Stack(app, 'IsolatedStack'); + const repository = new Repository(dependencyStack, 'Repo', { + version, + vpc, + }); const props: RenderQueueProps = { images, repository, - version: new VersionQuery(isolatedStack, 'Version'), + version: renderQueueVersion, vpc, trafficEncryption: { externalTLS: { @@ -951,66 +1031,69 @@ describe('RenderQueue', () => { }, }; - const rq = new RenderQueue(isolatedStack, 'RenderQueue', props); + const rq = new RenderQueue(stack, 'RenderQueue', props); - const rootCa = rq.node.findChild('RootCA').node.defaultChild as X509CertificatePem; + const rootCa = rq.node.findChild('RootCA') as X509CertificatePem; const rootCaGen = rootCa.node.defaultChild as CustomResource; - const rfdkCert = rq.node.findChild('RenderQueuePemCert').node.defaultChild as X509CertificatePem; + const rfdkCert = rq.node.findChild('RenderQueuePemCert') as X509CertificatePem; const rfdkCertGen = rfdkCert.node.defaultChild as CustomResource; - const acmCert = rq.node.findChild('AcmCert').node.defaultChild as ImportedAcmCertificate; + const acmCert = rq.node.findChild('AcmCert') as ImportedAcmCertificate; - expectCDK(isolatedStack).to(haveResourceLike('Custom::RFDK_X509Generator', { - Passphrase: isolatedStack.resolve(rootCa.passphrase), - })); + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_X509Generator', { + Passphrase: stack.resolve(rootCa.passphrase.secretArn), + }); - expectCDK(isolatedStack).to(haveResourceLike('Custom::RFDK_X509Generator', { - Passphrase: isolatedStack.resolve(rfdkCert.passphrase), + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_X509Generator', { + Passphrase: stack.resolve(rfdkCert.passphrase.secretArn), SigningCertificate: { - Cert: isolatedStack.resolve(rootCaGen.getAtt('Cert')), - Key: isolatedStack.resolve(rootCaGen.getAtt('Key')), - Passphrase: isolatedStack.resolve(rootCa.passphrase), + Cert: stack.resolve(rootCaGen.getAtt('Cert')), + Key: stack.resolve(rootCaGen.getAtt('Key')), + Passphrase: stack.resolve(rootCa.passphrase.secretArn), CertChain: '', }, - })); + }); - expectCDK(isolatedStack).to(countResources('Custom::RFDK_AcmImportedCertificate', 1)); - expectCDK(isolatedStack).to(haveResourceLike('Custom::RFDK_AcmImportedCertificate', { + Template.fromStack(stack).resourceCountIs('Custom::RFDK_AcmImportedCertificate', 1); + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_AcmImportedCertificate', { X509CertificatePem: { - Cert: isolatedStack.resolve(rfdkCertGen.getAtt('Cert')), - Key: isolatedStack.resolve(rfdkCertGen.getAtt('Key')), - Passphrase: isolatedStack.resolve(rfdkCert.passphrase), - CertChain: isolatedStack.resolve(rfdkCertGen.getAtt('CertChain')), + Cert: stack.resolve(rfdkCertGen.getAtt('Cert')), + Key: stack.resolve(rfdkCertGen.getAtt('Key')), + Passphrase: stack.resolve(rfdkCert.passphrase.secretArn), + CertChain: stack.resolve(rfdkCertGen.getAtt('CertChain')), }, - })); + }); - expectCDK(isolatedStack).to(countResources('AWS::ElasticLoadBalancingV2::Listener', 1)); - expectCDK(isolatedStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::Listener', { + Template.fromStack(stack).resourceCountIs('AWS::ElasticLoadBalancingV2::Listener', 1); + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::Listener', { Certificates: [ { - CertificateArn: isolatedStack.resolve(acmCert.certificateArn), + CertificateArn: stack.resolve(acmCert.certificateArn), }, ], - })); + }); }); test('Throws if given ACM cert and RFDK Cert', () => { // GIVEN - const isolatedStack = new Stack(app, 'IsolatedStack'); const ZONE_NAME = 'renderfarm.local'; const CERT_ARN = 'certArn'; const CA_ARN = 'arn:aws:secretsmanager:123456789012:secret:ca/arn'; - const zone = new PrivateHostedZone(isolatedStack, 'RenderQueueZone', { + const repository = new Repository(dependencyStack, 'Repo', { + version, + vpc, + }); + const zone = new PrivateHostedZone(stack, 'RenderQueueZone', { vpc, zoneName: ZONE_NAME, }); - const caCert = new X509CertificatePem(isolatedStack, 'CaCert', { + const caCert = new X509CertificatePem(stack, 'CaCert', { subject: { cn: `ca.${ZONE_NAME}`, }, }); - const serverCert = new X509CertificatePem(isolatedStack, 'ServerCert', { + const serverCert = new X509CertificatePem(stack, 'ServerCert', { subject: { cn: `server.${ZONE_NAME}`, }, @@ -1020,12 +1103,12 @@ describe('RenderQueue', () => { const props: RenderQueueProps = { images, repository, - version: new VersionQuery(isolatedStack, 'Version'), + version: renderQueueVersion, vpc, trafficEncryption: { externalTLS: { - acmCertificate: Certificate.fromCertificateArn(isolatedStack, 'Certificate', CERT_ARN), - acmCertificateChain: Secret.fromSecretPartialArn(isolatedStack, 'CA_Cert', CA_ARN), + acmCertificate: Certificate.fromCertificateArn(stack, 'Certificate', CERT_ARN), + acmCertificateChain: Secret.fromSecretPartialArn(stack, 'CA_Cert', CA_ARN), rfdkCertificate: serverCert, }, }, @@ -1036,7 +1119,7 @@ describe('RenderQueue', () => { // WHEN expect(() => { - new RenderQueue(isolatedStack, 'RenderQueue', props); + new RenderQueue(stack, 'RenderQueue', props); }) // THEN .toThrow(/Exactly one of externalTLS.acmCertificate and externalTLS.rfdkCertificate must be provided when using externalTLS/); @@ -1044,12 +1127,16 @@ describe('RenderQueue', () => { test('Throws if ACM Cert is given without a cert chain', () => { // GIVEN - const isolatedStack = new Stack(app, 'IsolatedStack'); const HOSTNAME = 'renderqueue'; const ZONE_NAME = 'renderfarm.local'; const CERT_ARN = 'certArn'; - const zone = new PrivateHostedZone(isolatedStack, 'RenderQueueZone', { + const repository = new Repository(dependencyStack, 'Repo', { + version, + vpc, + }); + + const zone = new PrivateHostedZone(stack, 'RenderQueueZone', { vpc, zoneName: ZONE_NAME, }); @@ -1057,11 +1144,11 @@ describe('RenderQueue', () => { const props: RenderQueueProps = { images, repository, - version: new VersionQuery(isolatedStack, 'Version'), + version: renderQueueVersion, vpc, trafficEncryption: { externalTLS: { - acmCertificate: Certificate.fromCertificateArn(isolatedStack, 'Certificate', CERT_ARN), + acmCertificate: Certificate.fromCertificateArn(stack, 'Certificate', CERT_ARN), }, }, hostname: { @@ -1072,7 +1159,7 @@ describe('RenderQueue', () => { // WHEN expect(() => { - new RenderQueue(isolatedStack, 'RenderQueue', props); + new RenderQueue(stack, 'RenderQueue', props); }) // THEN .toThrow(/externalTLS.acmCertificateChain must be provided when using externalTLS.acmCertificate./); @@ -1081,27 +1168,29 @@ describe('RenderQueue', () => { describe('Client Connection', () => { describe('externalProtocol is http', () => { - let isolatedStack: Stack; + let repository: Repository; + let renderQueue: RenderQueue; let zone: PrivateHostedZone; const ZONE_NAME = 'renderfarm.local'; - let rq: RenderQueue; beforeEach(() => { // GIVEN - isolatedStack = new Stack(app, 'IsolatedStack'); - zone = new PrivateHostedZone(isolatedStack, 'RenderQueueZone', { - vpc, - zoneName: ZONE_NAME, - }); - const nonSmRepository = new Repository(dependencyStack, 'NonSMRepository', { + repository = new Repository(dependencyStack, 'NonSMRepository', { vpc, version, + // Cannot have secrets management unless external TLS is enabled on the RQ, + // so we disable it to allow for testing. secretsManagementSettings: { enabled: false }, }); + zone = new PrivateHostedZone(stack, 'RenderQueueZone', { + vpc, + zoneName: ZONE_NAME, + }); + const props: RenderQueueProps = { images, - repository: nonSmRepository, - version: new VersionQuery(isolatedStack, 'Version'), + repository, + version: renderQueueVersion, vpc, hostname: { zone, @@ -1110,223 +1199,115 @@ describe('RenderQueue', () => { }; // WHEN - rq = new RenderQueue(isolatedStack, 'RenderQueue', props); + renderQueue = new RenderQueue(stack, 'RenderQueue', props); }); test('ECS can connect', () => { - // WHEN - const hosts = [new Instance(isolatedStack, 'Host', { - vpc, - instanceType: InstanceType.of( - InstanceClass.R4, - InstanceSize.LARGE, - ), - machineImage: MachineImage.latestAmazonLinux({ generation: AmazonLinuxGeneration.AMAZON_LINUX_2 }), - })]; - const role = new Role(isolatedStack, 'Role', {assumedBy: new AccountRootPrincipal()}); - - const env = rq.configureClientECS({ - hosts, - grantee: role, - }); - - // THEN - expect(env).toHaveProperty('RENDER_QUEUE_URI'); - expect(env.RENDER_QUEUE_URI).toMatch(/http:\/\/.*:8080$/); - - expectCDK(isolatedStack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { - IpProtocol: 'tcp', - ToPort: 8080, - SourceSecurityGroupId: { - 'Fn::GetAtt': [ - isolatedStack.getLogicalId(hosts[0].connections.securityGroups[0].node.defaultChild as CfnElement), - 'GroupId', - ], - }, - })); - - expectCDK(isolatedStack).to(haveResourceLike('AWS::EC2::Instance', { - DependsOn: arrayWith( - 'RenderQueueLBPublicListenerBBF15D5F', - 'RenderQueueRCSTaskA9AE70D3', - ), - }, ResourcePart.CompleteDefinition)); - }); - - test('Linux Instance can connect', () => { - // WHEN - const host = new Instance(isolatedStack, 'Host', { - vpc, - instanceType: InstanceType.of( - InstanceClass.R4, - InstanceSize.LARGE, - ), - machineImage: MachineImage.latestAmazonLinux({ generation: AmazonLinuxGeneration.AMAZON_LINUX_2 }), - }); - - rq.configureClientInstance({ - host, - }); - - // THEN - const userData = isolatedStack.resolve(host.userData.render()); - expect(userData).toStrictEqual({ - 'Fn::Join': [ - '', - [ - "#!/bin/bash\nmkdir -p $(dirname '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - '\')\naws s3 cp \'s3://', - { Ref: RQ_CONNECTION_ASSET.Bucket }, - '/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - '\' \'/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - '\'\n' + - 'if [ -f \"/etc/profile.d/deadlineclient.sh\" ]; then\n' + - ' source \"/etc/profile.d/deadlineclient.sh\"\n' + - 'fi\n' + - '"${DEADLINE_PATH}/deadlinecommand" -executeScriptNoGui "/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - `" --render-queue "http://renderqueue.${ZONE_NAME}:8080" \n` + - 'rm -f "/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, + // WHEN + const hosts = [new Instance(stack, 'Host', { + vpc, + instanceType: InstanceType.of( + InstanceClass.R4, + InstanceSize.LARGE, + ), + machineImage: MachineImage.latestAmazonLinux({ generation: AmazonLinuxGeneration.AMAZON_LINUX_2 }), + })]; + const role = new Role(stack, 'Role', {assumedBy: new AccountRootPrincipal()}); + + const env = renderQueue.configureClientECS({ + hosts, + grantee: role, + }); + + // THEN + expect(env).toHaveProperty('RENDER_QUEUE_URI'); + expect(env.RENDER_QUEUE_URI).toMatch(/http:\/\/.*:8080$/); + + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { + IpProtocol: 'tcp', + ToPort: 8080, + SourceSecurityGroupId: { + 'Fn::GetAtt': [ + stack.getLogicalId(hosts[0].connections.securityGroups[0].node.defaultChild as CfnElement), + 'GroupId', + ], + }, + }); + + Template.fromStack(stack).hasResource('AWS::EC2::Instance', { + DependsOn: Match.arrayWith([ + 'RenderQueueLBPublicListenerBBF15D5F', + 'RenderQueueRCSTaskA9AE70D3', + ]), + }); + }); + + test('Linux Instance can connect', () => { + // WHEN + const host = new Instance(stack, 'Host', { + vpc, + instanceType: InstanceType.of( + InstanceClass.R4, + InstanceSize.LARGE, + ), + machineImage: MachineImage.latestAmazonLinux({ generation: AmazonLinuxGeneration.AMAZON_LINUX_2 }), + }); + + renderQueue.configureClientInstance({ + host, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + [ + '#!/bin/bash\n' + + `mkdir -p $(dirname '/tmp/${RQ_CONNECTION_ASSET.Key}.py')\n` + + 'aws s3 cp \'s3://', { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], + 'Fn::Sub': RQ_CONNECTION_ASSET.Bucket, }, + `/${RQ_CONNECTION_ASSET.Key}.py' '/tmp/${RQ_CONNECTION_ASSET.Key}.py'\n` + + 'if [ -f "/etc/profile.d/deadlineclient.sh" ]; then\n' + + ' source "/etc/profile.d/deadlineclient.sh"\n' + + 'fi\n' + + `"\${DEADLINE_PATH}/deadlinecommand" -executeScriptNoGui "/tmp/${RQ_CONNECTION_ASSET.Key}.py" --render-queue "http://renderqueue.${ZONE_NAME}:8080" \n` + + `rm -f "/tmp/${RQ_CONNECTION_ASSET.Key}.py"\n` + + 'if service --status-all | grep -q "Deadline 10 Launcher"; then\n' + + ' service deadline10launcher restart\n' + + 'fi', ], - }, - '"\n' + - 'if service --status-all | grep -q "Deadline 10 Launcher"; then\n' + - ' service deadline10launcher restart\n' + - 'fi', - ], - ], + ], + }, + }, }); // Make sure we execute the script with the correct args - expectCDK(isolatedStack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', ToPort: 8080, SourceSecurityGroupId: { 'Fn::GetAtt': [ - isolatedStack.getLogicalId(host.connections.securityGroups[0].node.defaultChild as CfnElement), + stack.getLogicalId(host.connections.securityGroups[0].node.defaultChild as CfnElement), 'GroupId', ], }, - })); + }); - expectCDK(isolatedStack).to(haveResourceLike('AWS::EC2::Instance', { - DependsOn: arrayWith( + Template.fromStack(stack).hasResource('AWS::EC2::Instance', { + DependsOn: Match.arrayWith([ 'RenderQueueLBPublicListenerBBF15D5F', 'RenderQueueRCSTaskA9AE70D3', - ), - }, ResourcePart.CompleteDefinition)); + ]), + }); }); test('Windows Instance can connect', () => { // WHEN - const host = new Instance(isolatedStack, 'Host', { + const host = new Instance(stack, 'Host', { vpc, instanceType: InstanceType.of( InstanceClass.R4, @@ -1335,174 +1316,63 @@ describe('RenderQueue', () => { machineImage: MachineImage.latestWindows( WindowsVersion.WINDOWS_SERVER_2019_ENGLISH_CORE_BASE), }); - rq.configureClientInstance({ + renderQueue.configureClientInstance({ host, }); // THEN - const userData = isolatedStack.resolve(host.userData.render()); - expect(userData).toStrictEqual({ - 'Fn::Join': [ - '', - [ - 'mkdir (Split-Path -Path \'C:/temp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + [ + `mkdir (Split-Path -Path 'C:/temp/${RQ_CONNECTION_ASSET.Key}.py' ) -ea 0\n` + + 'Read-S3Object -BucketName \'', { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - '\' ) -ea 0\n' + - 'Read-S3Object -BucketName \'', - { Ref: RQ_CONNECTION_ASSET.Bucket }, - '\' -key \'', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - '\' -file \'C:/temp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - '\' -ErrorAction Stop\n' + - '$ErrorActionPreference = "Stop"\n' + - '$DEADLINE_PATH = (get-item env:"DEADLINE_PATH").Value\n' + - '& "$DEADLINE_PATH/deadlinecommand.exe" -executeScriptNoGui "C:/temp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - `" --render-queue "http://renderqueue.${ZONE_NAME}:8080" 2>&1\n` + - 'Remove-Item -Path "C:/temp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], + 'Fn::Sub': RQ_CONNECTION_ASSET.Bucket, }, + `' -key '${RQ_CONNECTION_ASSET.Key}.py' -file 'C:/temp/${RQ_CONNECTION_ASSET.Key}.py' -ErrorAction Stop\n` + + '$ErrorActionPreference = "Stop"\n' + + '$DEADLINE_PATH = (get-item env:"DEADLINE_PATH").Value\n' + + `& "$DEADLINE_PATH/deadlinecommand.exe" -executeScriptNoGui "C:/temp/${RQ_CONNECTION_ASSET.Key}.py" --render-queue "http://renderqueue.${ZONE_NAME}:8080" 2>&1\n` + + `Remove-Item -Path "C:/temp/${RQ_CONNECTION_ASSET.Key}.py"\n` + + 'If (Get-Service "deadline10launcherservice" -ErrorAction SilentlyContinue) {\n' + + ' Restart-Service "deadline10launcherservice"\n' + + '} Else {\n' + + ' & "$DEADLINE_PATH/deadlinelauncher.exe" -shutdownall 2>&1\n' + + ' & "$DEADLINE_PATH/deadlinelauncher.exe" -nogui 2>&1\n' + + '}', ], - }, - '"\n' + - 'If (Get-Service "deadline10launcherservice" -ErrorAction SilentlyContinue) {\n' + - ' Restart-Service "deadline10launcherservice"\n' + - '} Else {\n' + - ' & "$DEADLINE_PATH/deadlinelauncher.exe" -shutdownall 2>&1\n' + - ' & "$DEADLINE_PATH/deadlinelauncher.exe" -nogui 2>&1\n' + - '}', - ], - ], + ], + }, + }, }); // Make sure we execute the script with the correct args - expectCDK(isolatedStack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', ToPort: 8080, SourceSecurityGroupId: { 'Fn::GetAtt': [ - isolatedStack.getLogicalId(host.connections.securityGroups[0].node.defaultChild as CfnElement), + stack.getLogicalId(host.connections.securityGroups[0].node.defaultChild as CfnElement), 'GroupId', ], }, - })); + }); - expectCDK(isolatedStack).to(haveResourceLike('AWS::EC2::Instance', { - DependsOn: arrayWith( + Template.fromStack(stack).hasResource('AWS::EC2::Instance', { + DependsOn: Match.arrayWith([ 'RenderQueueLBPublicListenerBBF15D5F', 'RenderQueueRCSTaskA9AE70D3', - ), - }, ResourcePart.CompleteDefinition)); + ]), + }); }); }); describe('externalProtocol is https', () => { - let isolatedStack: Stack; let zone: PrivateHostedZone; - let rq: RenderQueue; + let renderQueue: RenderQueue; const HOSTNAME = 'renderqueue'; const ZONE_NAME = 'renderfarm.local'; const CERT_ARN = 'arn:a:b:c:dcertarn'; @@ -1510,15 +1380,18 @@ describe('RenderQueue', () => { beforeEach(() => { // GIVEN - isolatedStack = new Stack(app, 'IsolatedStack'); - zone = new PrivateHostedZone(isolatedStack, 'RenderQueueZone', { + const repository = new Repository(dependencyStack, 'Repo', { + version, + vpc, + }); + zone = new PrivateHostedZone(stack, 'RenderQueueZone', { vpc, zoneName: ZONE_NAME, }); const props: RenderQueueProps = { images, repository, - version: new VersionQuery(isolatedStack, 'Version'), + version: renderQueueVersion, vpc, hostname: { hostname: HOSTNAME, @@ -1533,12 +1406,12 @@ describe('RenderQueue', () => { }; // WHEN - rq = new RenderQueue(isolatedStack, 'RenderQueue', props); + renderQueue = new RenderQueue(stack, 'RenderQueue', props); }); test('ECS can connect', () => { // WHEN - const hosts = [new Instance(isolatedStack, 'Host', { + const hosts = [new Instance(stack, 'Host', { vpc, instanceType: InstanceType.of( InstanceClass.R4, @@ -1546,9 +1419,9 @@ describe('RenderQueue', () => { ), machineImage: MachineImage.latestAmazonLinux({ generation: AmazonLinuxGeneration.AMAZON_LINUX_2 }), })]; - const role = new Role(isolatedStack, 'Role', {assumedBy: new AccountRootPrincipal()}); + const role = new Role(stack, 'Role', {assumedBy: new AccountRootPrincipal()}); - const env = rq.configureClientECS({ + const env = renderQueue.configureClientECS({ hosts, grantee: role, }); @@ -1558,21 +1431,21 @@ describe('RenderQueue', () => { expect(env.RENDER_QUEUE_URI).toMatch(/https:\/\/.*:4433$/); expect(env).toHaveProperty('RENDER_QUEUE_TLS_CA_CERT_URI', CA_ARN); - expectCDK(isolatedStack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', ToPort: 4433, SourceSecurityGroupId: { 'Fn::GetAtt': [ - isolatedStack.getLogicalId(hosts[0].connections.securityGroups[0].node.defaultChild as CfnElement), + stack.getLogicalId(hosts[0].connections.securityGroups[0].node.defaultChild as CfnElement), 'GroupId', ], }, - })); + }); }); test('Linux Instance can connect', () => { // WHEN - const host = new Instance(isolatedStack, 'Host', { + const host = new Instance(stack, 'Host', { vpc, instanceType: InstanceType.of( InstanceClass.R4, @@ -1581,162 +1454,54 @@ describe('RenderQueue', () => { machineImage: MachineImage.latestAmazonLinux({ generation: AmazonLinuxGeneration.AMAZON_LINUX_2 }), }); - rq.configureClientInstance({ + renderQueue.configureClientInstance({ host, }); // THEN - const userData = isolatedStack.resolve(host.userData.render()); - expect(userData).toStrictEqual({ - 'Fn::Join': [ - '', - [ - "#!/bin/bash\nmkdir -p $(dirname '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - '\')\naws s3 cp \'s3://', - { Ref: RQ_CONNECTION_ASSET.Bucket }, - '/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - '\' \'/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - '\'\n' + - 'if [ -f \"/etc/profile.d/deadlineclient.sh\" ]; then\n' + - ' source \"/etc/profile.d/deadlineclient.sh\"\n' + - 'fi\n' + - '"${DEADLINE_PATH}/deadlinecommand" -executeScriptNoGui "/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - `" --render-queue "https://renderqueue.${ZONE_NAME}:4433" --tls-ca "${CA_ARN}"\n` + - 'rm -f "/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + [ + '#!/bin/bash\n' + + `mkdir -p $(dirname '/tmp/${RQ_CONNECTION_ASSET.Key}.py')\n` + + 'aws s3 cp \'s3://', { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], + 'Fn::Sub': RQ_CONNECTION_ASSET.Bucket, }, + `/${RQ_CONNECTION_ASSET.Key}.py' '/tmp/${RQ_CONNECTION_ASSET.Key}.py'\n` + + 'if [ -f "/etc/profile.d/deadlineclient.sh" ]; then\n' + + ' source "/etc/profile.d/deadlineclient.sh"\n' + + 'fi\n' + + `"\${DEADLINE_PATH}/deadlinecommand" -executeScriptNoGui "/tmp/${RQ_CONNECTION_ASSET.Key}.py" --render-queue "https://renderqueue.${ZONE_NAME}:4433" --tls-ca "${CA_ARN}"\n` + + `rm -f "/tmp/${RQ_CONNECTION_ASSET.Key}.py"\n` + + 'if service --status-all | grep -q "Deadline 10 Launcher"; then\n' + + ' service deadline10launcher restart\n' + + 'fi', ], - }, - '"\n' + - 'if service --status-all | grep -q "Deadline 10 Launcher"; then\n' + - ' service deadline10launcher restart\n' + - 'fi', - ], - ], + ], + }, + }, }); // Make sure we execute the script with the correct args - expectCDK(isolatedStack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', ToPort: 4433, SourceSecurityGroupId: { 'Fn::GetAtt': [ - isolatedStack.getLogicalId(host.connections.securityGroups[0].node.defaultChild as CfnElement), + stack.getLogicalId(host.connections.securityGroups[0].node.defaultChild as CfnElement), 'GroupId', ], }, - })); + }); }); test('Windows Instance can connect', () => { // WHEN - const host = new Instance(isolatedStack, 'Host', { + const host = new Instance(stack, 'Host', { vpc, instanceType: InstanceType.of( InstanceClass.R4, @@ -1745,160 +1510,49 @@ describe('RenderQueue', () => { machineImage: MachineImage.latestWindows( WindowsVersion.WINDOWS_SERVER_2019_ENGLISH_CORE_BASE), }); - rq.configureClientInstance({ + renderQueue.configureClientInstance({ host, }); // THEN - const userData = isolatedStack.resolve(host.userData.render()); - expect(userData).toStrictEqual({ - 'Fn::Join': [ - '', - [ - 'mkdir (Split-Path -Path \'C:/temp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - '\' ) -ea 0\n' + - 'Read-S3Object -BucketName \'', - { Ref: RQ_CONNECTION_ASSET.Bucket }, - '\' -key \'', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - '\' -file \'C:/temp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - '\' -ErrorAction Stop\n' + - '$ErrorActionPreference = "Stop"\n' + - '$DEADLINE_PATH = (get-item env:"DEADLINE_PATH").Value\n' + - '& "$DEADLINE_PATH/deadlinecommand.exe" -executeScriptNoGui "C:/temp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - `" --render-queue "https://renderqueue.${ZONE_NAME}:4433" --tls-ca \"${CA_ARN}\" 2>&1\n` + - 'Remove-Item -Path "C:/temp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + [ + `mkdir (Split-Path -Path 'C:/temp/${RQ_CONNECTION_ASSET.Key}.py' ) -ea 0\n` + + 'Read-S3Object -BucketName \'', { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], + 'Fn::Sub': RQ_CONNECTION_ASSET.Bucket, }, + `' -key '${RQ_CONNECTION_ASSET.Key}.py' -file 'C:/temp/${RQ_CONNECTION_ASSET.Key}.py' -ErrorAction Stop\n$ErrorActionPreference = "Stop"\n` + + '$DEADLINE_PATH = (get-item env:"DEADLINE_PATH").Value\n' + + `& "$DEADLINE_PATH/deadlinecommand.exe" -executeScriptNoGui "C:/temp/${RQ_CONNECTION_ASSET.Key}.py" --render-queue "https://renderqueue.${ZONE_NAME}:4433" --tls-ca "${CA_ARN}" 2>&1\n` + + `Remove-Item -Path "C:/temp/${RQ_CONNECTION_ASSET.Key}.py"\n` + + 'If (Get-Service "deadline10launcherservice" -ErrorAction SilentlyContinue) {\n' + + ' Restart-Service "deadline10launcherservice"\n' + + '} Else {\n' + + ' & "$DEADLINE_PATH/deadlinelauncher.exe" -shutdownall 2>&1\n' + + ' & "$DEADLINE_PATH/deadlinelauncher.exe" -nogui 2>&1\n' + + '}', ], - }, - '"\n' + - 'If (Get-Service "deadline10launcherservice" -ErrorAction SilentlyContinue) {\n' + - ' Restart-Service "deadline10launcherservice"\n' + - '} Else {\n' + - ' & "$DEADLINE_PATH/deadlinelauncher.exe" -shutdownall 2>&1\n' + - ' & "$DEADLINE_PATH/deadlinelauncher.exe" -nogui 2>&1\n' + - '}', - ], - ], + ], + }, + }, }); // Make sure we execute the script with the correct args - expectCDK(isolatedStack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', ToPort: 4433, SourceSecurityGroupId: { 'Fn::GetAtt': [ - isolatedStack.getLogicalId(host.connections.securityGroups[0].node.defaultChild as CfnElement), + stack.getLogicalId(host.connections.securityGroups[0].node.defaultChild as CfnElement), 'GroupId', ], }, - })); + }); }); }); }); @@ -1915,11 +1569,14 @@ describe('RenderQueue', () => { availabilityZone: 'us-west-2b', }), ]; - const isolatedStack = new Stack(app, 'IsolatedStack'); + const repository = new Repository(dependencyStack, 'Repo', { + version, + vpc, + }); const props: RenderQueueProps = { images, repository, - version: new VersionQuery(isolatedStack, 'Version'), + version: renderQueueVersion, vpc, vpcSubnets: { subnets, @@ -1930,134 +1587,144 @@ describe('RenderQueue', () => { }; // WHEN - new RenderQueue(isolatedStack, 'RenderQueue', props); + new RenderQueue(stack, 'RenderQueue', props); - expectCDK(isolatedStack).to(haveResource('AWS::AutoScaling::AutoScalingGroup', { - VPCZoneIdentifier: arrayWith( + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { + VPCZoneIdentifier: Match.arrayWith([ 'SubnetID1', 'SubnetID2', - ), - })); - expectCDK(isolatedStack).to(haveResource('AWS::ElasticLoadBalancingV2::LoadBalancer', { + ]), + }); + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', { Subnets: [ 'SubnetID1', 'SubnetID2', ], - })); + }); }); test('can specify instance type', () => { // GIVEN - const isolatedStack = new Stack(app, 'IsolatedStack'); + const repository = new Repository(dependencyStack, 'Repo', { + version, + vpc, + }); const props: RenderQueueProps = { images, instanceType: InstanceType.of(InstanceClass.C5, InstanceSize.LARGE), repository, - version: new VersionQuery(isolatedStack, 'Version'), + version: renderQueueVersion, vpc, }; // WHEN - new RenderQueue(isolatedStack, 'RenderQueue', props); + new RenderQueue(stack, 'RenderQueue', props); // THEN - expectCDK(isolatedStack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { InstanceType: 'c5.large', - })); + }); }); test('no deletion protection', () => { // GIVEN - const isolatedStack = new Stack(app, 'IsolatedStack'); + const repository = new Repository(dependencyStack, 'Repo', { + version, + vpc, + }); const props: RenderQueueProps = { images, repository, - version: new VersionQuery(isolatedStack, 'Version'), + version: renderQueueVersion, vpc, deletionProtection: false, }; // WHEN - new RenderQueue(isolatedStack, 'RenderQueue', props); + new RenderQueue(stack, 'RenderQueue', props); // THEN - expectCDK(isolatedStack).to(not(haveResourceLike('AWS::ElasticLoadBalancingV2::LoadBalancer', { - LoadBalancerAttributes: arrayWith( + resourcePropertiesCountIs(stack, 'AWS::ElasticLoadBalancingV2::LoadBalancer', { + LoadBalancerAttributes: Match.arrayWith([ { Key: 'deletion_protection.enabled', Value: 'true', }, - ), - Scheme: ABSENT, - Type: ABSENT, - }))); + ]), + Scheme: Match.absent(), + Type: Match.absent(), + }, 0); }); test('drop invalid http header fields enabled', () => { // GIVEN - const isolatedStack = new Stack(app, 'IsolatedStack'); + const repository = new Repository(dependencyStack, 'Repo', { + version, + vpc, + }); const props: RenderQueueProps = { images, repository, - version: new VersionQuery(isolatedStack, 'Version'), + version: renderQueueVersion, vpc, }; // WHEN - new RenderQueue(isolatedStack, 'RenderQueue', props); + new RenderQueue(stack, 'RenderQueue', props); // THEN - expectCDK(isolatedStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::LoadBalancer', { - LoadBalancerAttributes: arrayWith( + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', { + LoadBalancerAttributes: Match.arrayWith([ { Key: 'routing.http.drop_invalid_header_fields.enabled', Value: 'true', }, - ), - })); + ]), + }); }); describe('hostname', () => { // GIVEN const zoneName = 'mydomain.local'; + let repository: Repository; - describe('not specified, with no TLS', () => { - let isolatedStack: Stack; + beforeEach(() => { + repository = new Repository(dependencyStack, 'Repo', { + version, + vpc, + // Cannot have secrets management unless external TLS is enabled on the RQ, + // so we disable it to allow for testing. + secretsManagementSettings: { enabled: false }, + }); + }); + describe('not specified, with no TLS', () => { beforeEach(() => { // GIVEN - isolatedStack = new Stack(app, 'IsolatedStack'); - const nonSmRepository = new Repository(dependencyStack, 'NonSMRepository', { - vpc, - version, - secretsManagementSettings: { enabled: false }, - }); const props: RenderQueueProps = { images, - repository: nonSmRepository, - trafficEncryption: { externalTLS: { enabled: false } }, - version: new VersionQuery(isolatedStack, 'Version'), + repository, + version: renderQueueVersion, vpc, + trafficEncryption: { externalTLS: { enabled: false } }, }; // WHEN - new RenderQueue(isolatedStack, 'RenderQueue', props); + new RenderQueue(stack, 'RenderQueue', props); }); // THEN test('does not create a record set', () => { - expectCDK(isolatedStack).notTo(haveResource('AWS::Route53::RecordSet')); + Template.fromStack(stack).resourceCountIs('AWS::Route53::RecordSet', 0); }); }); test('not specified, with TLS', () => { // GIVEN - const isolatedStack = new Stack(app, 'IsolatedStack'); - const props: RenderQueueProps = { images, repository, - version: new VersionQuery(isolatedStack, 'Version'), + version: renderQueueVersion, vpc, trafficEncryption: { externalTLS: { @@ -2065,20 +1732,19 @@ describe('RenderQueue', () => { }, }; - const renderQueue = new RenderQueue(isolatedStack, 'RenderQueue', props); + const renderQueue = new RenderQueue(stack, 'RenderQueue', props); - expectCDK(isolatedStack).to(haveResource('AWS::Route53::RecordSet', { + Template.fromStack(stack).hasResourceProperties('AWS::Route53::RecordSet', { Name: 'renderqueue.aws-rfdk.com.', Type: 'A', - AliasTarget: objectLike({ - HostedZoneId: isolatedStack.resolve(renderQueue.loadBalancer.loadBalancerCanonicalHostedZoneId), + AliasTarget: Match.objectLike({ + HostedZoneId: stack.resolve(renderQueue.loadBalancer.loadBalancerCanonicalHostedZoneId), }), - })); + }); }); describe('specified with zone but no hostname', () => { let zone: PrivateHostedZone; - let isolatedStack: Stack; let renderQueue: RenderQueue; beforeEach(() => { @@ -2087,11 +1753,10 @@ describe('RenderQueue', () => { vpc, zoneName, }); - isolatedStack = new Stack(app, 'IsolatedStack'); const props: RenderQueueProps = { images, repository, - version: new VersionQuery(isolatedStack, 'Version'), + version: renderQueueVersion, vpc, hostname: { zone, @@ -2099,7 +1764,7 @@ describe('RenderQueue', () => { }; // WHEN - renderQueue = new RenderQueue(isolatedStack, 'RenderQueue', props); + renderQueue = new RenderQueue(stack, 'RenderQueue', props); }); // THEN @@ -2107,10 +1772,10 @@ describe('RenderQueue', () => { const loadBalancerLogicalId = dependencyStack.getLogicalId( renderQueue.loadBalancer.node.defaultChild as CfnElement, ); - expectCDK(isolatedStack).to(haveResource('AWS::Route53::RecordSet', { + Template.fromStack(stack).hasResourceProperties('AWS::Route53::RecordSet', { Name: `renderqueue.${zoneName}.`, Type: 'A', - AliasTarget: objectLike({ + AliasTarget: Match.objectLike({ HostedZoneId: { 'Fn::GetAtt': [ loadBalancerLogicalId, @@ -2118,7 +1783,7 @@ describe('RenderQueue', () => { ], }, }), - })); + }); }); }); @@ -2132,16 +1797,10 @@ describe('RenderQueue', () => { zoneName, }); const hostname = 'testrq'; - const isolatedStack = new Stack(app, 'IsolatedStack'); - const nonSmRepository = new Repository(dependencyStack, 'NonSMRepository', { - vpc, - version, - secretsManagementSettings: { enabled: false }, - }); const props: RenderQueueProps = { images, - repository: nonSmRepository, - version: new VersionQuery(isolatedStack, 'Version'), + repository, + version: renderQueueVersion, vpc, hostname: { hostname, @@ -2153,16 +1812,16 @@ describe('RenderQueue', () => { }; // WHEN - const renderQueue = new RenderQueue(isolatedStack, 'RenderQueue', props); + const renderQueue = new RenderQueue(stack, 'RenderQueue', props); // THEN const loadBalancerLogicalId = dependencyStack.getLogicalId( renderQueue.loadBalancer.node.defaultChild as CfnElement, ); - expectCDK(isolatedStack).to(haveResource('AWS::Route53::RecordSet', { + Template.fromStack(stack).hasResourceProperties('AWS::Route53::RecordSet', { Name: `${hostname}.${zoneName}.`, Type: 'A', - AliasTarget: objectLike({ + AliasTarget: Match.objectLike({ HostedZoneId: { 'Fn::GetAtt': [ loadBalancerLogicalId, @@ -2170,7 +1829,7 @@ describe('RenderQueue', () => { ], }, }), - })); + }); }); test.each([ @@ -2209,11 +1868,8 @@ describe('RenderQueue', () => { describe('Access Logs', () => { let isolatedStack: Stack; - let isolatedVpc: Vpc; - let isolatedRepository: Repository; - let isolatedVersion: IVersion; - let isolatedimages: RenderQueueImages; - + let repository: Repository; + let renderQueueProps: RenderQueueProps; let accessBucket: Bucket; beforeEach(() => { @@ -2223,29 +1879,29 @@ describe('RenderQueue', () => { region: 'us-east-1', }, }); - isolatedVpc = new Vpc(isolatedStack, 'Vpc'); - isolatedVersion = new VersionQuery(isolatedStack, 'Version'); - - isolatedRepository = new Repository(isolatedStack, 'Repo', { - version: isolatedVersion, - vpc: isolatedVpc, - }); - - isolatedimages = { + const localVpc = new Vpc(isolatedStack, 'Vpc'); + const localVersion = new VersionQuery(isolatedStack, 'Version'); + const localImages = { remoteConnectionServer: rcsImage, }; + repository = new Repository(isolatedStack, 'Repo', { + version: localVersion, + vpc: localVpc, + }); accessBucket = new Bucket(isolatedStack, 'AccessBucket'); - + renderQueueProps = { + images: localImages, + repository, + version: localVersion, + vpc: localVpc, + }; }); test('enabling access logs sets attributes and policies', () => { // GIVEN const props: RenderQueueProps = { - images: isolatedimages, - repository: isolatedRepository, - version: isolatedVersion, - vpc: isolatedVpc, + ...renderQueueProps, accessLogs: { destinationBucket: accessBucket, }, @@ -2255,8 +1911,8 @@ describe('RenderQueue', () => { new RenderQueue(isolatedStack, 'RenderQueue', props); // THEN - expectCDK(isolatedStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::LoadBalancer', { - LoadBalancerAttributes: arrayWith( + Template.fromStack(isolatedStack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', { + LoadBalancerAttributes: Match.arrayWith([ { Key: 'access_logs.s3.enabled', Value: 'true', @@ -2267,15 +1923,15 @@ describe('RenderQueue', () => { Ref: 'AccessBucketE2803D76', }, }, - ), - })); + ]), + }); - expectCDK(isolatedStack).to(haveResourceLike('AWS::S3::BucketPolicy', { + Template.fromStack(isolatedStack).hasResourceProperties('AWS::S3::BucketPolicy', { Bucket: { Ref: 'AccessBucketE2803D76', }, PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: 's3:PutObject', Condition: { @@ -2317,7 +1973,11 @@ describe('RenderQueue', () => { }, { Action: [ - 's3:PutObject*', + 's3:PutObject', + 's3:PutObjectLegalHold', + 's3:PutObjectRetention', + 's3:PutObjectTagging', + 's3:PutObjectVersionTagging', 's3:Abort*', ], Effect: 'Allow', @@ -2354,18 +2014,45 @@ describe('RenderQueue', () => { ], }, }, - ), + { + Action: 's3:PutObject', + Condition: { + StringEquals: { + 's3:x-amz-acl': 'bucket-owner-full-control', + }, + }, + Effect: 'Allow', + Principal: { + Service: 'delivery.logs.amazonaws.com', + }, + Resource: { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': [ + 'AccessBucketE2803D76', + 'Arn', + ], + }, + '/AWSLogs/', + { + Ref: 'AWS::AccountId', + }, + '/*', + ], + ], + }, + }, + ]), }, - })); + }); }); test('enabling access logs works with prefix', () => { // GIVEN const props: RenderQueueProps = { - images: isolatedimages, - repository: isolatedRepository, - version: isolatedVersion, - vpc: isolatedVpc, + ...renderQueueProps, accessLogs: { destinationBucket: accessBucket, prefix: 'PREFIX_STRING', @@ -2376,8 +2063,8 @@ describe('RenderQueue', () => { new RenderQueue(isolatedStack, 'RenderQueue', props); // THEN - expectCDK(isolatedStack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::LoadBalancer', { - LoadBalancerAttributes: arrayWith( + Template.fromStack(isolatedStack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', { + LoadBalancerAttributes: Match.arrayWith([ { Key: 'access_logs.s3.enabled', Value: 'true', @@ -2392,15 +2079,15 @@ describe('RenderQueue', () => { Key: 'access_logs.s3.prefix', Value: 'PREFIX_STRING', }, - ), - })); + ]), + }); - expectCDK(isolatedStack).to(haveResourceLike('AWS::S3::BucketPolicy', { + Template.fromStack(isolatedStack).hasResourceProperties('AWS::S3::BucketPolicy', { Bucket: { Ref: 'AccessBucketE2803D76', }, PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: 's3:PutObject', Condition: { @@ -2442,7 +2129,11 @@ describe('RenderQueue', () => { }, { Action: [ - 's3:PutObject*', + 's3:PutObject', + 's3:PutObjectLegalHold', + 's3:PutObjectRetention', + 's3:PutObjectTagging', + 's3:PutObjectVersionTagging', 's3:Abort*', ], Effect: 'Allow', @@ -2479,13 +2170,61 @@ describe('RenderQueue', () => { ], }, }, - ), + { + Action: 's3:PutObject', + Condition: { + StringEquals: { + 's3:x-amz-acl': 'bucket-owner-full-control', + }, + }, + Effect: 'Allow', + Principal: { + Service: 'delivery.logs.amazonaws.com', + }, + Resource: { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': [ + 'AccessBucketE2803D76', + 'Arn', + ], + }, + '/PREFIX_STRING/AWSLogs/', + { + Ref: 'AWS::AccountId', + }, + '/*', + ], + ], + }, + }, + ]), }, - })); + }); }); }); describe('tagging', () => { + let repository: Repository; + + beforeEach(() => { + repository = new Repository(dependencyStack, 'NonSMRepository', { + vpc, + version, + }); + const props: RenderQueueProps = { + images, + repository, + version: renderQueueVersion, + vpc, + }; + + // WHEN + new RenderQueue(stack, 'RenderQueue', props); + }); + testConstructTags({ constructName: 'RenderQueue', createConstruct: () => { @@ -2509,13 +2248,31 @@ describe('RenderQueue', () => { }); describe('SEP Policies', () => { + let repository: Repository; + let renderQueue: RenderQueue; + + beforeEach(() => { + // GIVEN + repository = new Repository(dependencyStack, 'NonSMRepository', { + vpc, + version, + }); + const props: RenderQueueProps = { + images, + repository, + version: renderQueueVersion, + vpc, + }; + renderQueue = new RenderQueue(stack, 'RenderQueue', props); + }); + test('with resource tracker', () => { // WHEN - renderQueueCommon.addSEPPolicies(); + renderQueue.addSEPPolicies(); // THEN - expectCDK(stack).to(countResourcesLike('AWS::IAM::Role', 1, { - ManagedPolicyArns: arrayWith( + resourcePropertiesCountIs(stack, 'AWS::IAM::Role', { + ManagedPolicyArns: Match.arrayWith([ { 'Fn::Join': [ '', @@ -2540,17 +2297,17 @@ describe('RenderQueue', () => { ], ], }, - ), - })); + ]), + }, 1); }); test('no resource tracker', () => { // WHEN - renderQueueCommon.addSEPPolicies(false); + renderQueue.addSEPPolicies(false); // THEN - expectCDK(stack).to(haveResourceLike('AWS::IAM::Role', { - ManagedPolicyArns: arrayWith( + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { + ManagedPolicyArns: Match.arrayWith([ { 'Fn::Join': [ '', @@ -2563,10 +2320,10 @@ describe('RenderQueue', () => { ], ], }, - ), - })); - expectCDK(stack).notTo(haveResourceLike('AWS::IAM::Role', { - ManagedPolicyArns: arrayWith( + ]), + }); + resourcePropertiesCountIs(stack, 'AWS::IAM::Role', { + ManagedPolicyArns: Match.arrayWith([ { 'Fn::Join': [ '', @@ -2579,25 +2336,21 @@ describe('RenderQueue', () => { ], ], }, - ), - })); + ]), + }, 0); }); }); - test('creates WaitForStableService by default', () => { - // THEN - expectCDK(stack).to(haveResourceLike('Custom::RFDK_WaitForStableService', { - cluster: stack.resolve(renderQueueCommon.cluster.clusterArn), - // eslint-disable-next-line dot-notation - services: [stack.resolve(renderQueueCommon['pattern'].service.serviceArn)], - })); - }); - describe('Security Groups', () => { + let repository: Repository; let backendSecurityGroup: SecurityGroup; let frontendSecurityGroup: SecurityGroup; beforeEach(() => { + repository = new Repository(dependencyStack, 'Repo', { + version, + vpc, + }); backendSecurityGroup = new SecurityGroup(stack, 'ASGSecurityGroup', { vpc }); frontendSecurityGroup = new SecurityGroup(stack, 'LBSecurityGroup', { vpc }); }); @@ -2675,42 +2428,45 @@ describe('RenderQueue', () => { // THEN // Existing LoadBalancer security groups shouldn't have the ingress rule added - expectCDK(stack).notTo(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + resourcePropertiesCountIs(stack, 'AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', FromPort: 22, ToPort: 22, GroupId: stack.resolve(frontendSecurityGroup.securityGroupId), SourceSecurityGroupId: stack.resolve(peerSecurityGroup.securityGroupId), - })); + }, 0); // Existing AutoScalingGroup security groups shouldn't have the ingress rule added - expectCDK(stack).notTo(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + resourcePropertiesCountIs(stack, 'AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', FromPort: 22, ToPort: 22, GroupId: stack.resolve(backendSecurityGroup.securityGroupId), SourceSecurityGroupId: stack.resolve(peerSecurityGroup.securityGroupId), - })); + }, 0); }); function assertSecurityGroupsWereAdded(securityGroups: RenderQueueSecurityGroups) { if (securityGroups.backend !== undefined) { - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { - SecurityGroups: arrayWith(stack.resolve(securityGroups.backend.securityGroupId)), - })); + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { + SecurityGroups: Match.arrayWith([stack.resolve(securityGroups.backend.securityGroupId)]), + }); } if (securityGroups.frontend !== undefined) { - expectCDK(stack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::LoadBalancer', { - SecurityGroups: arrayWith(stack.resolve(securityGroups.frontend.securityGroupId)), - })); + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', { + SecurityGroups: Match.arrayWith([stack.resolve(securityGroups.frontend.securityGroupId)]), + }); } } }); test('validates VersionQuery is not in a different stack', () => { // GIVEN - const newStack = new Stack(app, 'NewStack'); + const repository = new Repository(dependencyStack, 'Repo', { + version, + vpc, + }); // WHEN - new RenderQueue(newStack, 'RenderQueueNew', { + new RenderQueue(stack, 'RenderQueue', { images, repository, version, @@ -2719,32 +2475,24 @@ describe('RenderQueue', () => { // WHEN function synth() { - SynthUtils.synthesize(newStack); + app.synth(); } // THEN expect(synth).toThrow('A VersionQuery can not be supplied from a different stack'); }); - test('Does not enable filesystem cache by default', () => { - expectCDK(stack).notTo(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { - UserData: { - 'Fn::Base64': { - 'Fn::Join': arrayWith(arrayWith(' >> /etc/ecs/ecs.config\nsudo iptables --insert FORWARD 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP\nsudo service iptables save\necho ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config\nyum install -yq awscli unzip\n# RenderQueue file caching enabled\nmkdir -p $(dirname \'/tmp/')), - }, - }, - })); - }); - test('Enables filesystem cache if required', () => { // GIVEN - const isolatedStack = new Stack(app, 'IsolatedStack'); - + const repository = new Repository(dependencyStack, 'Repo', { + version, + vpc, + }); // WHEN - new RenderQueue(isolatedStack, 'RenderQueue', { + new RenderQueue(stack, 'RenderQueue', { images, repository, - version: new VersionQuery(isolatedStack, 'Version'), + version: renderQueueVersion, vpc, enableLocalFileCaching: true, }); @@ -2753,28 +2501,32 @@ describe('RenderQueue', () => { // Note: If this test breaks/fails, then it is probable that the // 'Does not enable filesystem cache by default' test above will also require // updating/fixing. - expectCDK(isolatedStack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { UserData: { 'Fn::Base64': { - 'Fn::Join': arrayWith(arrayWith(' >> /etc/ecs/ecs.config\nsudo iptables --insert FORWARD 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP\nsudo service iptables save\necho ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config\nyum install -yq awscli unzip\n# RenderQueue file caching enabled\nmkdir -p $(dirname \'/tmp/')), + 'Fn::Join': [ + '', + Match.arrayWith([ + Match.stringLikeRegexp('.*# RenderQueue file caching enabled.*'), + ]), + ], }, }, - })); - }); - - test('runs as RCS user', () => { - // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::TaskDefinition', { - ContainerDefinitions: arrayWith( - objectLike({ User: '1000:1000' }), - ), - })); + }); }); describe('Secrets Management', () => { + let repository: Repository; let rqSecretsManagementProps: RenderQueueProps; beforeEach(() => { + repository = new Repository(dependencyStack, 'Repo', { + version, + vpc, + secretsManagementSettings: { + enabled: true, + }, + }); rqSecretsManagementProps = { vpc, images, @@ -2850,19 +2602,19 @@ describe('RenderQueue', () => { const rq = new RenderQueue(stack, 'SecretsManagementRenderQueue', rqSecretsManagementProps); // THEN - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { - PolicyDocument: objectLike({ - Statement: arrayWith({ + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: Match.objectLike({ + Statement: Match.arrayWith([{ Action: [ 'secretsmanager:GetSecretValue', 'secretsmanager:DescribeSecret', ], Effect: 'Allow', Resource: stack.resolve((repository.secretsManagementSettings.credentials!.node.defaultChild as CfnSecret).ref), - }), + }]), }), Roles: [stack.resolve((rq.node.tryFindChild('RCSTask') as Ec2TaskDefinition).taskRole.roleName)], - })); + }); }); test('defines secrets management credentials environment variable', () => { @@ -2870,14 +2622,18 @@ describe('RenderQueue', () => { new RenderQueue(stack, 'SecretsManagementRenderQueue', rqSecretsManagementProps); // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::TaskDefinition', { - ContainerDefinitions: arrayWith(objectLike({ - Environment: arrayWith({ - Name: 'RCS_SM_CREDENTIALS_URI', - Value: stack.resolve((repository.secretsManagementSettings.credentials!.node.defaultChild as CfnSecret).ref), + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { + ContainerDefinitions: Match.arrayWith([ + Match.objectLike({ + Environment: Match.arrayWith([ + { + Name: 'RCS_SM_CREDENTIALS_URI', + Value: stack.resolve((repository.secretsManagementSettings.credentials!.node.defaultChild as CfnSecret).ref), + }, + ]), }), - })), - })); + ]), + }); }); test('creates and mounts docker volume for deadline key pairs', () => { @@ -2885,53 +2641,89 @@ describe('RenderQueue', () => { new RenderQueue(stack, 'SecretsManagementRenderQueue', rqSecretsManagementProps); // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::TaskDefinition', { - ContainerDefinitions: arrayWith(objectLike({ - MountPoints: arrayWith({ - ContainerPath: '/home/ec2-user/.config/.mono/keypairs', - ReadOnly: false, - SourceVolume: 'deadline-user-keypairs', + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { + ContainerDefinitions: Match.arrayWith([ + Match.objectLike({ + MountPoints: Match.arrayWith([ + { + ContainerPath: '/home/ec2-user/.config/.mono/keypairs', + ReadOnly: false, + SourceVolume: 'deadline-user-keypairs', + }, + ]), }), - })), - Volumes: arrayWith({ - DockerVolumeConfiguration: { - Autoprovision: true, - Driver: 'local', - Scope: 'shared', + ]), + Volumes: Match.arrayWith([ + { + DockerVolumeConfiguration: { + Autoprovision: true, + Driver: 'local', + Scope: 'shared', + }, + Name: 'deadline-user-keypairs', }, - Name: 'deadline-user-keypairs', - }), - })); + ]), + }); }); test('DeploymentInstance uses specified backend security group', () => { // GIVEN const backendSecurityGroupId = 'backend-sg-id'; const backendSecurityGroup = SecurityGroup.fromSecurityGroupId(stack, 'BackendSG', backendSecurityGroupId); - rqSecretsManagementProps = { + + // WHEN + const renderQueue = new RenderQueue(stack, 'SecretsManagementRenderQueue', { ...rqSecretsManagementProps, securityGroups: { backend: backendSecurityGroup, }, + }); + // Force creation of the DeploymentInstance + // eslint-disable-next-line dot-notation + renderQueue['deploymentInstance']; + + // THEN + const deploymentInstance = renderQueue.node.findChild('ConfigureRepository') as DeploymentInstance; + expect(deploymentInstance.connections.securityGroups[0].securityGroupId).toEqual(backendSecurityGroupId); + }); + + test('DeploymentInstance uses RQ\'s log group prefix', () => { + // GIVEN + rqSecretsManagementProps = { + ...rqSecretsManagementProps, + logGroupProps: { + logGroupPrefix: '/customPrefix/', + }, }; // WHEN - const renderQueue = new RenderQueue(stack, 'SecretsManagementRenderQueue', rqSecretsManagementProps); + const renderQueue = new RenderQueue(stack, 'SecretsManagementRenderQueue', { + ...rqSecretsManagementProps, + logGroupProps: { + logGroupPrefix: '/customPrefix/', + }, + }); + // Force creation of the DeploymentInstance + // eslint-disable-next-line dot-notation + renderQueue['deploymentInstance']; // THEN - // eslint-disable-next-line dot-notation - expect(renderQueue['deploymentInstance'].connections.securityGroups[0].securityGroupId).toEqual(backendSecurityGroupId); + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { + LogGroupName: '/customPrefix/ConfigureRepository', + }); }); test('DeploymentInstance uses implicitly created backend security group', () => { // WHEN const renderQueue = new RenderQueue(stack, 'SecretsManagementRenderQueue', rqSecretsManagementProps); + // Force creation of the DeploymentInstance + // eslint-disable-next-line dot-notation + renderQueue['deploymentInstance']; // THEN - // eslint-disable-next-line dot-notation - expect(renderQueue['deploymentInstance'].connections.securityGroups[0]).toBe(renderQueue.backendConnections.securityGroups[0]); - // eslint-disable-next-line dot-notation - expect(renderQueue['deploymentInstance'].connections.securityGroups[0]).toBe(renderQueue.asg.connections.securityGroups[0]); + const deploymentInstance = renderQueue.node.findChild('ConfigureRepository') as DeploymentInstance; + expect(deploymentInstance.connections.securityGroups[0]).toBe(renderQueue.backendConnections.securityGroups[0]); + expect(deploymentInstance.connections.securityGroups[0]).toBe(renderQueue.asg.connections.securityGroups[0]); }); describe('client calls .configureSecretsManagementAutoRegistration()', () => { @@ -2995,38 +2787,14 @@ describe('RenderQueue', () => { test('deployment instance is created using specified subnets', () => { // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { LaunchConfigurationName: stack.resolve(launchConfiguration.ref), - VPCZoneIdentifier: arrayWith( + VPCZoneIdentifier: Match.arrayWith([ ...RQ_SUBNET_IDS, - ), - })); + ]), + }); }); }); }); - test('.backendConnections is associated with ASG security group rules', () => { - // GIVEN - const instance = new Instance(dependencyStack, 'BackendConnectionInstance', { - instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.MICRO), - machineImage: MachineImage.latestAmazonLinux(), - vpc, - }); - const portNumber = 5555; - const port = Port.tcp(portNumber); - const asgSecurityGroup = renderQueueCommon.asg.connections.securityGroups[0]; - - // WHEN - renderQueueCommon.backendConnections.allowFrom(instance, port); - - // THEN - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { - IpProtocol: 'tcp', - Description: `from ${instance.connections.securityGroups[0].uniqueId}:${portNumber}`, - GroupId: stack.resolve(asgSecurityGroup.securityGroupId), - SourceSecurityGroupId: stack.resolve(instance.connections.securityGroups[0].securityGroupId), - FromPort: portNumber, - ToPort: portNumber, - })); - }); }); diff --git a/packages/aws-rfdk/lib/deadline/test/repository.test.ts b/packages/aws-rfdk/lib/deadline/test/repository.test.ts index 7bc8e3d26..3b375c45f 100644 --- a/packages/aws-rfdk/lib/deadline/test/repository.test.ts +++ b/packages/aws-rfdk/lib/deadline/test/repository.test.ts @@ -4,16 +4,20 @@ */ import { - arrayWith, - countResourcesLike, - expect as expectCDK, - haveResource, - haveResourceLike, - ResourcePart, - SynthUtils, -} from '@aws-cdk/assert'; -import {AutoScalingGroup} from '@aws-cdk/aws-autoscaling'; -import {DatabaseCluster} from '@aws-cdk/aws-docdb'; + App, + CfnElement, + Duration, + Names, + RemovalPolicy, + Stack, +} from 'aws-cdk-lib'; +import { + Annotations, + Match, + Template, +} from 'aws-cdk-lib/assertions'; +import {AutoScalingGroup} from 'aws-cdk-lib/aws-autoscaling'; +import {DatabaseCluster} from 'aws-cdk-lib/aws-docdb'; import { AmazonLinuxGeneration, Instance, @@ -28,34 +32,26 @@ import { SubnetType, Vpc, WindowsVersion, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { AccessPoint, CfnFileSystem, FileSystem as EfsFileSystem, -} from '@aws-cdk/aws-efs'; -import { CfnRole } from '@aws-cdk/aws-iam'; -import { Bucket } from '@aws-cdk/aws-s3'; -import { Asset } from '@aws-cdk/aws-s3-assets'; -import { Secret } from '@aws-cdk/aws-secretsmanager'; -import { - App, - CfnElement, - Duration, - Names, - RemovalPolicy, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-efs'; +import { CfnRole } from 'aws-cdk-lib/aws-iam'; +import { Bucket } from 'aws-cdk-lib/aws-s3'; +import { Asset } from 'aws-cdk-lib/aws-s3-assets'; +import { Secret } from 'aws-cdk-lib/aws-secretsmanager'; import { MountableEfs, } from '../../core'; +import { + CWA_ASSET_LINUX, +} from '../../core/test/asset-constants'; import { testConstructTags, } from '../../core/test/tag-helpers'; -import { - CWA_ASSET_LINUX, -} from '../../deadline/test/asset-constants'; import { DatabaseConnection, IVersion, @@ -65,8 +61,12 @@ import { PlatformInstallers, } from '../lib'; import { + CONFIG_REPO_DIRECT_CONNECT_LINUX, REPO_DC_ASSET, } from './asset-constants'; +import { + resourcePropertiesCountIs, +} from './test-helper'; let app: App; let stack: Stack; @@ -145,7 +145,7 @@ test('repository installer instance is created correctly', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(stack).hasResource('AWS::AutoScaling::AutoScalingGroup', { Properties: { MaxSize: '1', MinSize: '1', @@ -172,15 +172,15 @@ test('repository installer instance is created correctly', () => { IgnoreUnmodifiedGroupSizeProperties: true, }, }, - DependsOn: [ + DependsOn: Match.arrayWith([ 'repositoryInstallerDocumentDatabaseInstance11A6F8C8E', - ], - }, ResourcePart.CompleteDefinition)); - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + ]), + }); + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { InstanceType: 't3.large', - })); + }); - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', FromPort: 2049, ToPort: 2049, @@ -196,7 +196,7 @@ test('repository installer instance is created correctly', () => { 'GroupId', ], }, - })); + }); }); test('repository installer honors vpcSubnet', () => { @@ -217,9 +217,9 @@ test('repository installer honors vpcSubnet', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { VPCZoneIdentifier: isolatedSubnetIds, - })); + }); }); test('repository installer security groups created correctly', () => { @@ -230,7 +230,7 @@ test('repository installer security groups created correctly', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', FromPort: 2049, ToPort: 2049, @@ -246,8 +246,8 @@ test('repository installer security groups created correctly', () => { 'GroupId', ], }, - })); - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + }); + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', FromPort: { 'Fn::GetAtt': [ @@ -273,7 +273,7 @@ test('repository installer security groups created correctly', () => { 'GroupId', ], }, - })); + }); }); /* @@ -314,9 +314,9 @@ test('repository installer iam permissions: db secret access', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith({ + Statement: Match.arrayWith([{ Action: [ 'secretsmanager:GetSecretValue', 'secretsmanager:DescribeSecret', @@ -325,9 +325,10 @@ test('repository installer iam permissions: db secret access', () => { Resource: { Ref: 'repositoryInstallerDocumentDatabaseSecretAttachment29753B7C', }, - }), + }]), }, - })); + PolicyName: Match.stringLikeRegexp('^repositoryInstallerInstanceRoleDefaultPolicy.*'), + }); }); test('repository installer iam permissions: installer get', () => { @@ -338,9 +339,9 @@ test('repository installer iam permissions: installer get', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: [ 's3:GetObject*', @@ -348,7 +349,7 @@ test('repository installer iam permissions: installer get', () => { 's3:List*', ], Effect: 'Allow', - Resource: arrayWith( + Resource: Match.arrayWith([ { 'Fn::Join': [ '', @@ -359,7 +360,7 @@ test('repository installer iam permissions: installer get', () => { }, ':s3:::', { - Ref: CWA_ASSET_LINUX.Bucket, + 'Fn::Sub': CWA_ASSET_LINUX.Bucket, }, ], ], @@ -374,17 +375,18 @@ test('repository installer iam permissions: installer get', () => { }, ':s3:::', { - Ref: CWA_ASSET_LINUX.Bucket, + 'Fn::Sub': CWA_ASSET_LINUX.Bucket, }, '/*', ], ], }, - ), + ]), }, - ), + ]), }, - })); + PolicyName: Match.stringLikeRegexp('^repositoryInstallerInstanceRoleDefaultPolicy.*'), + }); }); test('default repository installer log group created correctly', () => { @@ -395,10 +397,10 @@ test('default repository installer log group created correctly', () => { }); // THEN - expectCDK(stack).to(haveResource('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { RetentionInDays: 3, LogGroupName: '/renderfarm/repositoryInstaller', - })); + }); }); test('repository installer logs all required files', () => { @@ -412,7 +414,7 @@ test('repository installer logs all required files', () => { // The CloudWatchAgent stores the agent configuration in an SSM Parameter. Check it for the required setup. // Note: This would be better implemented using the tools in: https://github.com/aws/aws-cdk/pull/8444 // but that is not yet available. - expectCDK(stack).to(haveResourceLike('AWS::SSM::Parameter', { + Template.fromStack(stack).hasResourceProperties('AWS::SSM::Parameter', { Type: 'String', Value: { 'Fn::Join': [ @@ -426,7 +428,7 @@ test('repository installer logs all required files', () => { ], ], }, - })); + }); }); test('repository mounts repository filesystem', () => { @@ -458,9 +460,9 @@ test.each([ }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::DocDB::DBCluster', { + Template.fromStack(stack).hasResource('AWS::DocDB::DBCluster', { DeletionPolicy: expected, - }, ResourcePart.CompleteDefinition)); + }); }); test.each([ @@ -478,9 +480,9 @@ test.each([ }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::EFS::FileSystem', { + Template.fromStack(stack).hasResource('AWS::EFS::FileSystem', { DeletionPolicy: expected, - }, ResourcePart.CompleteDefinition)); + }); }); test('repository warns if removal policy for filesystem when filesystem provided', () => { @@ -507,13 +509,9 @@ test('repository warns if removal policy for filesystem when filesystem provided }); // THEN - expect(repo.node.metadataEntry).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - type: 'aws:cdk:warning', - data: 'RemovalPolicy for filesystem will not be applied since a filesystem is not being created by this construct', - }), - ]), + Annotations.fromStack(stack).hasWarning( + `/${repo.node.path}`, + 'RemovalPolicy for filesystem will not be applied since a filesystem is not being created by this construct', ); }); @@ -545,13 +543,9 @@ test('repository warns if removal policy for database when database provided', ( }); // THEN - expect(repo.node.metadataEntry).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - type: 'aws:cdk:warning', - data: 'RemovalPolicy for database will not be applied since a database is not being created by this construct', - }), - ]), + Annotations.fromStack(stack).hasWarning( + `/${repo.node.path}`, + Match.stringLikeRegexp('RemovalPolicy for database will not be applied since a database is not being created by this construct.*'), ); }); @@ -575,19 +569,19 @@ test('repository creates deadlineDatabase if none provided', () => { }); // THEN - expectCDK(stack).to(haveResource('AWS::DocDB::DBCluster')); - expectCDK(stack).to(haveResource('AWS::DocDB::DBInstance')); - expectCDK(stack).to(haveResourceLike('AWS::DocDB::DBCluster', { + Template.fromStack(stack).resourceCountIs('AWS::DocDB::DBCluster', 1); + Template.fromStack(stack).resourceCountIs('AWS::DocDB::DBInstance', 1); + Template.fromStack(stack).hasResourceProperties('AWS::DocDB::DBCluster', { EnableCloudwatchLogsExports: [ 'audit' ], - }, ResourcePart.Properties)); - expectCDK(stack).to(haveResourceLike('AWS::DocDB::DBClusterParameterGroup', { + }); + Template.fromStack(stack).hasResourceProperties('AWS::DocDB::DBClusterParameterGroup', { Parameters: { audit_logs: 'enabled', }, - }, ResourcePart.Properties)); - expectCDK(stack).to(haveResourceLike('AWS::DocDB::DBInstance', { + }); + Template.fromStack(stack).hasResourceProperties('AWS::DocDB::DBInstance', { AutoMinorVersionUpgrade: true, - })); + }); }); test('disabling Audit logging does not enable Cloudwatch audit logs', () => { @@ -611,15 +605,15 @@ test('disabling Audit logging does not enable Cloudwatch audit logs', () => { }); // THEN - expectCDK(stack).to(haveResource('AWS::DocDB::DBCluster')); - expectCDK(stack).notTo(haveResourceLike('AWS::DocDB::DBCluster', { - EnableCloudwatchLogsExports: [ 'audit' ], - }, ResourcePart.Properties)); - expectCDK(stack).notTo(haveResourceLike('AWS::DocDB::DBClusterParameterGroup', { + Template.fromStack(stack).resourceCountIs('AWS::DocDB::DBCluster', 1); + resourcePropertiesCountIs(stack, 'AWS::DocDB::DBCluster', { + EnableCloudwatchLogsExports: Match.arrayWith([ 'audit' ]), + }, 0); + resourcePropertiesCountIs(stack, 'AWS::DocDB::DBClusterParameterGroup', { Parameters: { audit_logs: 'enabled', }, - }, ResourcePart.Properties)); + }, 0); }); test('repository warns if databaseAuditLogging defined and database is specified', () => { @@ -654,14 +648,7 @@ test('repository warns if databaseAuditLogging defined and database is specified 'Please ensure that the Database provided is configured correctly.'; // THEN - expect(repo.node.metadataEntry).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - type: 'aws:cdk:warning', - data: warningMsg, - }), - ]), - ); + Annotations.fromStack(stack).hasWarning(`/${repo.node.path}`, warningMsg); }); test('honors subnet specification', () => { @@ -691,14 +678,14 @@ test('honors subnet specification', () => { }); // THEN - expectCDK(isolatedStack).to(haveResourceLike('AWS::DocDB::DBSubnetGroup', { + Template.fromStack(isolatedStack).hasResourceProperties('AWS::DocDB::DBSubnetGroup', { SubnetIds: [ 'SubnetID1', 'SubnetID2', ], - })); - expectCDK(isolatedStack).to(haveResourceLike('AWS::EFS::MountTarget', { SubnetId: 'SubnetID1' })); - expectCDK(isolatedStack).to(haveResourceLike('AWS::EFS::MountTarget', { SubnetId: 'SubnetID2' })); + }); + Template.fromStack(isolatedStack).hasResourceProperties('AWS::EFS::MountTarget', { SubnetId: 'SubnetID1' }); + Template.fromStack(isolatedStack).hasResourceProperties('AWS::EFS::MountTarget', { SubnetId: 'SubnetID2' }); }); test('repository honors database instance count', () => { @@ -713,9 +700,9 @@ test('repository honors database instance count', () => { }); // THEN - expectCDK(stack).to(countResourcesLike('AWS::DocDB::DBInstance', instanceCount, { + resourcePropertiesCountIs(stack, 'AWS::DocDB::DBInstance', { AutoMinorVersionUpgrade: true, - })); + }, instanceCount); }); test('repository honors database retention period', () => { @@ -732,9 +719,9 @@ test('repository honors database retention period', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::DocDB::DBCluster', { + Template.fromStack(stack).hasResourceProperties('AWS::DocDB::DBCluster', { BackupRetentionPeriod: period, - })); + }); }); test('warns if both retention period and database provided', () => { @@ -765,13 +752,9 @@ test('warns if both retention period and database provided', () => { }); // THEN - expect(repo.node.metadataEntry).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - type: 'aws:cdk:warning', - data: 'Backup retention for database will not be applied since a database is not being created by this construct', - }), - ]), + Annotations.fromStack(stack).hasWarning( + `/${repo.node.path}`, + 'Backup retention for database will not be applied since a database is not being created by this construct', ); }); @@ -807,8 +790,8 @@ test('repository creates filesystem if none provided', () => { }); // THEN - expectCDK(stack).to(haveResource('AWS::EFS::FileSystem')); - expectCDK(stack).to(haveResource('AWS::EFS::MountTarget')); + Template.fromStack(stack).resourceCountIs('AWS::EFS::FileSystem', 1); + Template.fromStack(stack).resourceCountIs('AWS::EFS::MountTarget', 2); expect(repo.node.tryFindChild('PadEfsStorage')).toBeDefined(); expect(repo.node.findChild('FileSystem').node.tryFindChild('PaddingAccessPoint')).toBeDefined(); }); @@ -845,14 +828,14 @@ test('repository instance is created with user defined timeout', () => { }); // THEN - expectCDK(stack).to(haveResource('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(stack).hasResource('AWS::AutoScaling::AutoScalingGroup', { CreationPolicy: { ResourceSignal: { Count: 1, Timeout: 'PT30M', }, }, - }, ResourcePart.CompleteDefinition)); + }); }); test('repository instance is created with correct installer path version', () => { @@ -884,9 +867,9 @@ test.each([ }); // THEN - expectCDK(stack).to(haveResource('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { LogGroupName: testPrefix + id, - })); + }); }); test('validate instance self-termination', () => { @@ -902,9 +885,9 @@ test('validate instance self-termination', () => { const asgLogicalIdToken = escapeTokenRegex('${Token[Stack.repositoryInstaller.Installer.ASG.LogicalID.\\d+]}'); const expectedString = `function exitTrap\\(\\)\\{\nexitCode=\\$\\?\nsleep 1m\nTOKEN=\\$\\(curl -X PUT "http:\\/\\/169\\.254\\.169\\.254\\/latest\\/api\\/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 30" 2> \\/dev\\/null\\)\nINSTANCE="\\$\\(curl -s -H "X-aws-ec2-metadata-token: \\$TOKEN" http:\\/\\/169\\.254\\.169\\.254\\/latest\\/meta-data\\/instance-id 2> \\/dev\\/null\\)"\nASG="\\$\\(aws --region ${regionToken} ec2 describe-tags --filters "Name=resource-id,Values=\\$\\{INSTANCE\\}" "Name=key,Values=aws:autoscaling:groupName" --query "Tags\\[0\\]\\.Value" --output text\\)"\naws --region ${regionToken} autoscaling update-auto-scaling-group --auto-scaling-group-name \\$\\{ASG\\} --min-size 0 --max-size 0 --desired-capacity 0\n\\/opt\\/aws\\/bin\\/cfn-signal --stack ${stack.stackName} --resource ${asgLogicalIdToken} --region ${regionToken} -e \\$exitCode \\|\\| echo 'Failed to send Cloudformation Signal'\n\\}`; expect((repo.node.defaultChild as AutoScalingGroup).userData.render()).toMatch(new RegExp(expectedString)); - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: 'autoscaling:UpdateAutoScalingGroup', Condition: { @@ -920,9 +903,9 @@ test('validate instance self-termination', () => { Effect: 'Allow', Resource: '*', }, - ), + ]), }, - })); + }); }); test('repository configure client instance', () => { @@ -962,25 +945,24 @@ test('repository configure client instance', () => { expect(userData).toMatch(/.*export -f configure_deadline_database.*/); // Make sure we call the configureRepositoryDirectConnect script with appropriate argument. - const regex = new RegExp(escapeTokenRegex('\'/tmp/${Token[TOKEN.\\d+]}${Token[TOKEN.\\d+]}\' \\"/mnt/repository/DeadlineRepository\\"')); - expect(userData).toMatch(regex); + expect(userData).toContain(`'/tmp/${CONFIG_REPO_DIRECT_CONNECT_LINUX.Key}.sh' "/mnt/repository/DeadlineRepository"`); // Assert the IAM instance profile is given read access to the database credentials secret - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith({ + Statement: Match.arrayWith([{ Action: [ 'secretsmanager:GetSecretValue', 'secretsmanager:DescribeSecret', ], Effect: 'Allow', Resource: stack.resolve(db.secret!.secretArn), - }), + }]), }, Roles: [ stack.resolve(instanceRole.ref), ], - })); + }); }); test('configureClientInstance uses singleton for repo config script', () => { @@ -1015,9 +997,9 @@ test('configureClientInstance uses singleton for repo config script', () => { // THEN // Make sure that both instances have access to the same Asset for the configureRepositoryDirectConnect script - expectCDK(stack).to(countResourcesLike('AWS::IAM::Policy', 2, { - PolicyDocument: { - Statement: arrayWith( + resourcePropertiesCountIs(stack, 'AWS::IAM::Policy', { + PolicyDocument: Match.objectLike({ + Statement: Match.arrayWith([ { Effect: 'Allow', Action: [ @@ -1036,7 +1018,7 @@ test('configureClientInstance uses singleton for repo config script', () => { }, ':s3:::', { - Ref: REPO_DC_ASSET.Bucket, + 'Fn::Sub': REPO_DC_ASSET.Bucket, }, ], ], @@ -1051,7 +1033,7 @@ test('configureClientInstance uses singleton for repo config script', () => { }, ':s3:::', { - Ref: REPO_DC_ASSET.Bucket, + 'Fn::Sub': REPO_DC_ASSET.Bucket, }, '/*', ], @@ -1059,9 +1041,10 @@ test('configureClientInstance uses singleton for repo config script', () => { }, ], }, - ), - }, - })); + ]), + }), + PolicyName: Match.stringLikeRegexp('Instance[1-2]InstanceRoleDefaultPolicy.*'), + }, 2); }); test('windows client cannot direct connect to repository', () => { @@ -1132,9 +1115,9 @@ describe('Security Groups', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::DocDB::DBCluster', { - VpcSecurityGroupIds: arrayWith(stack.resolve(repositorySecurityGroup.securityGroupId)), - })); + Template.fromStack(stack).hasResourceProperties('AWS::DocDB::DBCluster', { + VpcSecurityGroupIds: Match.arrayWith([stack.resolve(repositorySecurityGroup.securityGroupId)]), + }); }); }); @@ -1153,9 +1136,9 @@ describe('Security Groups', () => { // THEN // The EFS construct adds the security group to each mount target, and one mount target is generated per subnet. const numMountTargets = vpc.selectSubnets().subnets.length; - expectCDK(stack).to(countResourcesLike('AWS::EFS::MountTarget', numMountTargets, { - SecurityGroups: arrayWith(stack.resolve(repositorySecurityGroup.securityGroupId)), - })); + resourcePropertiesCountIs(stack, 'AWS::EFS::MountTarget', { + SecurityGroups: Match.arrayWith([stack.resolve(repositorySecurityGroup.securityGroupId)]), + }, numMountTargets); }); }); @@ -1172,9 +1155,9 @@ describe('Security Groups', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { - SecurityGroups: arrayWith(stack.resolve(repositorySecurityGroup.securityGroupId)), - })); + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { + SecurityGroups: Match.arrayWith([stack.resolve(repositorySecurityGroup.securityGroupId)]), + }); }); }); @@ -1191,7 +1174,7 @@ test('validates VersionQuery is not in a different stack', () => { // WHEN function synth() { - SynthUtils.synthesize(newStack); + app.synth(); } // THEN @@ -1207,14 +1190,14 @@ test('creates an EFS AccessPoint when no filesystem is supplied', () => { // THEN const efsResource = (repo.node.findChild('FileSystem') as CfnElement).node.defaultChild as CfnFileSystem; - expectCDK(stack).to(haveResource('AWS::EFS::AccessPoint', { + Template.fromStack(stack).hasResourceProperties('AWS::EFS::AccessPoint', { FileSystemId: stack.resolve(efsResource.ref), PosixUser: { Gid: '0', Uid: '0', }, RootDirectory: {}, - })); + }); }); test('throws an error if supplied a MountableEfs with no Access Point', () => { @@ -1291,7 +1274,9 @@ test('imports repository settings', () => { // THEN const installerGroup = repository.node.tryFindChild('Installer') as AutoScalingGroup; - expect(installerGroup.userData.render()).toContain(`aws s3 cp '${repositorySettings.s3ObjectUrl}'`); + // Note: The repostory settings is the js file that this compiles in to. The hash for that is fragile in that any + // change to this file will change it. So, we search for an s3 cp of a js file (this is the only one). + expect(installerGroup.userData.render()).toMatch(new RegExp('aws s3 cp \'s3://[^\']+/[a-f0-9]+.js\'')); }); test('IMountableLinuxFilesystem.usesUserPosixPermissions() = true changes ownership of repository files', () => { diff --git a/packages/aws-rfdk/lib/deadline/test/secrets-management.test.ts b/packages/aws-rfdk/lib/deadline/test/secrets-management.test.ts index 3122f398f..9ef3039f6 100644 --- a/packages/aws-rfdk/lib/deadline/test/secrets-management.test.ts +++ b/packages/aws-rfdk/lib/deadline/test/secrets-management.test.ts @@ -3,14 +3,17 @@ * SPDX-License-Identifier: Apache-2.0 */ -import * as fs from 'fs'; - import { - arrayWith, - expect as expectCDK, - haveResourceLike, - SynthUtils, -} from '@aws-cdk/assert'; + App, + Fn, + Resource, + Stack, +} from 'aws-cdk-lib'; +import { + Annotations, + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { ExecuteFileOptions, IVpc, @@ -20,16 +23,10 @@ import { SubnetType, UserData, Vpc, -} from '@aws-cdk/aws-ec2'; -import { CfnRole } from '@aws-cdk/aws-iam'; -import { Asset } from '@aws-cdk/aws-s3-assets'; -import { - App, - Construct, - Fn, - Resource, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ec2'; +import { CfnRole } from 'aws-cdk-lib/aws-iam'; +import { Asset } from 'aws-cdk-lib/aws-s3-assets'; +import { Construct } from 'constructs'; import { DeploymentInstance, DeploymentInstanceProps } from '../../core/lib/deployment-instance'; @@ -79,12 +76,6 @@ class MockDeploymentInstance extends DeploymentInstance { return this.mockUserData; } } - -function writeSynthedTemplate(stack: Stack, outputFile: string) { - const template = SynthUtils.synthesize(stack).template; - fs.writeFileSync(outputFile, JSON.stringify(template, null, 2), { encoding: 'utf8' }); -} - const DEADLINE_CLIENT_SUBNET_NAME = 'DeadlineClient'; const RENDER_QUEUE_ALB_SUBNET_NAME = 'RenderQueueALB'; @@ -101,12 +92,6 @@ describe('SecretsManagementIdentityRegistration', () => { let renderQueueSubnets: SelectedSubnets; let target: SecretsManagementIdentityRegistration; - // @ts-ignore - function writeSynthedTemplates() { - writeSynthedTemplate(deploymentInstanceStack, 'deployment-instance-stack.json'); - writeSynthedTemplate(stack, 'secrets-management-stack.json'); - } - beforeEach(() => { app = new App(); dependencyStack = new Stack(app, 'DependencyStack'); @@ -173,9 +158,9 @@ describe('SecretsManagementIdentityRegistration', () => { createTarget(); // THEN - expectCDK(deploymentInstanceStack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(deploymentInstanceStack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: [ 's3:GetObject*', @@ -183,17 +168,17 @@ describe('SecretsManagementIdentityRegistration', () => { 's3:List*', ], Effect: 'Allow', - Resource: arrayWith(...deploymentInstanceStack.resolve([ + Resource: Match.arrayWith([...deploymentInstanceStack.resolve([ version.linuxInstallers.client.s3Bucket.bucketArn, version.linuxInstallers.client.s3Bucket.arnForObjects(version.linuxInstallers.client.objectKey), - ])), + ])]), }, - ), + ]), }, Roles: [ deploymentInstanceStack.resolve(deploymentInstanceRole.ref), ], - })); + }); }); test('downloads and executes Client installer', () => { @@ -235,18 +220,18 @@ describe('SecretsManagementIdentityRegistration', () => { createTarget(); // THEN - expectCDK(deploymentInstanceStack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(deploymentInstanceStack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: 'ec2:DescribeSubnets', Effect: 'Allow', Resource: '*', }, - ), + ]), }, Roles: [stack.resolve(deploymentInstanceRole.ref)], - })); + }); }); test('configures direct repository connection', () => { @@ -265,9 +250,9 @@ describe('SecretsManagementIdentityRegistration', () => { createTarget(); // THEN - expectCDK(deploymentInstanceStack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(deploymentInstanceStack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: [ 'secretsmanager:GetSecretValue', @@ -276,12 +261,12 @@ describe('SecretsManagementIdentityRegistration', () => { Effect: 'Allow', Resource: deploymentInstanceStack.resolve(repository.secretsManagementSettings.credentials!.secretArn), }, - ), + ]), }, Roles: [ deploymentInstanceStack.resolve(deploymentInstanceRole.ref), ], - })); + }); }); describe('Identity registration settings script', () => { @@ -295,9 +280,9 @@ describe('SecretsManagementIdentityRegistration', () => { const identityRegistrationSettingsScript = getIdentityRegistrationSettingsScript(); // THEN - expectCDK(deploymentInstanceStack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(deploymentInstanceStack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: [ 's3:GetObject*', @@ -310,10 +295,10 @@ describe('SecretsManagementIdentityRegistration', () => { identityRegistrationSettingsScript.bucket.arnForObjects('*'), ]), }, - ), + ]), }, Roles: [deploymentInstanceStack.resolve(deploymentInstanceRole.ref)], - })); + }); }); test('DeploymentInstance downloads script', () => { @@ -595,10 +580,10 @@ describe('SecretsManagementIdentityRegistration', () => { vpcSubnets, }); - expect(dependent.node.metadataEntry).toContainEqual(expect.objectContaining({ - type: 'aws:cdk:warning', - data: `Deadline Secrets Management is enabled on the Repository and VPC subnets of the Render Queue match the subnets of ${dependent.node.path}. Using dedicated subnets is recommended. See https://github.com/aws/aws-rfdk/blobs/release/packages/aws-rfdk/lib/deadline/README.md#using-dedicated-subnets-for-deadline-components`, - })); + Annotations.fromStack(stack).hasWarning( + `/${dependent.node.path}`, + `Deadline Secrets Management is enabled on the Repository and VPC subnets of the Render Queue match the subnets of ${dependent.node.path}. Using dedicated subnets is recommended. See https://github.com/aws/aws-rfdk/blobs/release/packages/aws-rfdk/lib/deadline/README.md#using-dedicated-subnets-for-deadline-components`, + ); }); }); diff --git a/packages/aws-rfdk/lib/deadline/test/spot-event-plugin-fleet.test.ts b/packages/aws-rfdk/lib/deadline/test/spot-event-plugin-fleet.test.ts index 59287de7f..3bca35ef3 100644 --- a/packages/aws-rfdk/lib/deadline/test/spot-event-plugin-fleet.test.ts +++ b/packages/aws-rfdk/lib/deadline/test/spot-event-plugin-fleet.test.ts @@ -8,18 +8,20 @@ /* eslint-disable dot-notation */ import { - arrayWith, - countResources, - countResourcesLike, - expect as expectCDK, - haveResource, - haveResourceLike, - objectLike, -} from '@aws-cdk/assert'; + App, + CfnElement, + Stack, + Tags, +} from 'aws-cdk-lib'; +import { + Annotations, + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { BlockDeviceVolume, EbsDeviceVolumeType, -} from '@aws-cdk/aws-autoscaling'; +} from 'aws-cdk-lib/aws-autoscaling'; import { GenericLinuxImage, InstanceClass, @@ -31,23 +33,16 @@ import { SubnetSelection, SubnetType, Vpc, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { AssetImage, ContainerImage, -} from '@aws-cdk/aws-ecs'; +} from 'aws-cdk-lib/aws-ecs'; import { ManagedPolicy, Role, ServicePrincipal, -} from '@aws-cdk/aws-iam'; -import { ArtifactMetadataEntryType } from '@aws-cdk/cloud-assembly-schema'; -import { - App, - CfnElement, - Stack, - Tags, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-iam'; import { tagFields } from '../../core/lib/runtime-info'; import { escapeTokenRegex, @@ -64,6 +59,7 @@ import { SpotFleetAllocationStrategy, SpotFleetResourceType, } from '../lib'; +import { resourcePropertiesCountIs } from './test-helper'; let app: App; let stack: Stack; @@ -128,7 +124,7 @@ describe('SpotEventPluginFleet', () => { // THEN expect(fleet.securityGroups).toBeDefined(); expect(fleet.securityGroups.length).toBe(1); - expectCDK(spotFleetStack).to(countResources('AWS::EC2::SecurityGroup', 1)); + Template.fromStack(spotFleetStack).resourceCountIs('AWS::EC2::SecurityGroup', 1); }); test('allows connection to the render queue', () => { @@ -143,11 +139,11 @@ describe('SpotEventPluginFleet', () => { }); // THEN - expectCDK(spotFleetStack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(spotFleetStack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', ToPort: parseInt(renderQueue.endpoint.portAsString(), 10), SourceSecurityGroupId: spotFleetStack.resolve(fleet.connections.securityGroups[0].securityGroupId), - })); + }); }); test('creates a spot fleet instance role', () => { @@ -163,9 +159,9 @@ describe('SpotEventPluginFleet', () => { // THEN expect(fleet.fleetInstanceRole).toBeDefined(); - expectCDK(spotFleetStack).to(haveResourceLike('AWS::IAM::Role', { - AssumeRolePolicyDocument: objectLike({ - Statement: [objectLike({ + Template.fromStack(spotFleetStack).hasResourceProperties('AWS::IAM::Role', { + AssumeRolePolicyDocument: Match.objectLike({ + Statement: [Match.objectLike({ Action: 'sts:AssumeRole', Effect: 'Allow', Principal: { @@ -173,10 +169,10 @@ describe('SpotEventPluginFleet', () => { }, })], }), - ManagedPolicyArns: arrayWith( + ManagedPolicyArns: Match.arrayWith([ spotFleetStack.resolve(ManagedPolicy.fromAwsManagedPolicyName('AWSThinkboxDeadlineSpotEventPluginWorkerPolicy').managedPolicyArn), - ), - })); + ]), + }); }); test('creates an instance profile', () => { @@ -192,11 +188,11 @@ describe('SpotEventPluginFleet', () => { // THEN expect(fleet.instanceProfile).toBeDefined(); - expectCDK(spotFleetStack).to(haveResourceLike('AWS::IAM::InstanceProfile', { - Roles: arrayWith({ + Template.fromStack(spotFleetStack).hasResourceProperties('AWS::IAM::InstanceProfile', { + Roles: Match.arrayWith([{ Ref: spotFleetStack.getLogicalId(fleet.fleetInstanceRole.node.defaultChild as CfnElement), - }), - })); + }]), + }); }); test('creates a spot fleet role', () => { @@ -212,9 +208,9 @@ describe('SpotEventPluginFleet', () => { // THEN expect(fleet.fleetRole).toBeDefined(); - expectCDK(spotFleetStack).to(haveResourceLike('AWS::IAM::Role', { - AssumeRolePolicyDocument: objectLike({ - Statement: [objectLike({ + Template.fromStack(spotFleetStack).hasResourceProperties('AWS::IAM::Role', { + AssumeRolePolicyDocument: Match.objectLike({ + Statement: [Match.objectLike({ Action: 'sts:AssumeRole', Effect: 'Allow', Principal: { @@ -222,10 +218,10 @@ describe('SpotEventPluginFleet', () => { }, })], }), - ManagedPolicyArns: arrayWith( + ManagedPolicyArns: Match.arrayWith([ spotFleetStack.resolve(ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonEC2SpotFleetTaggingRole').managedPolicyArn), - ), - })); + ]), + }); }); test('adds group names to user data', () => { @@ -259,14 +255,14 @@ describe('SpotEventPluginFleet', () => { // THEN expect(fleet.tags).toBeDefined(); - expectCDK(spotFleetStack).to(haveResourceLike('AWS::EC2::SecurityGroup', { - Tags: arrayWith( - objectLike({ + Template.fromStack(spotFleetStack).hasResourceProperties('AWS::EC2::SecurityGroup', { + Tags: Match.arrayWith([ + Match.objectLike({ Key: rfdkTag.name, Value: rfdkTag.value, }), - ), - })); + ]), + }); }); test('uses default LogGroup prefix %s', () => { @@ -283,10 +279,10 @@ describe('SpotEventPluginFleet', () => { maxCapacity, }); - expectCDK(stack).to(haveResource('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { RetentionInDays: 3, LogGroupName: '/renderfarm/' + id, - })); + }); }); test('sets default allocation strategy', () => { @@ -407,17 +403,21 @@ describe('SpotEventPluginFleet', () => { }); // THEN - expectCDK(spotFleetStack).to(haveResourceLike('AWS::EC2::LaunchTemplate', { - LaunchTemplateData: objectLike({ - TagSpecifications: arrayWith({ - ResourceType: 'instance', - Tags: arrayWith({ - Key: 'DeadlineTrackedAWSResource', - Value: 'SpotEventPlugin', - }), - }), + Template.fromStack(spotFleetStack).hasResourceProperties('AWS::EC2::LaunchTemplate', { + LaunchTemplateData: Match.objectLike({ + TagSpecifications: Match.arrayWith([ + { + ResourceType: 'instance', + Tags: Match.arrayWith([ + { + Key: 'DeadlineTrackedAWSResource', + Value: 'SpotEventPlugin', + }, + ]), + }, + ]), }), - })); + }); }); test('adds multiple fleet security groups to launch template', () => { @@ -439,11 +439,11 @@ describe('SpotEventPluginFleet', () => { }); // THEN - expectCDK(spotFleetStack).to(haveResourceLike('AWS::EC2::LaunchTemplate', { - LaunchTemplateData: objectLike({ + Template.fromStack(spotFleetStack).hasResourceProperties('AWS::EC2::LaunchTemplate', { + LaunchTemplateData: Match.objectLike({ SecurityGroupIds: securityGroups.map(sg => spotFleetStack.resolve(sg.securityGroupId)), }), - })); + }); }); test('adds fleet tags to launch template', () => { @@ -465,17 +465,19 @@ describe('SpotEventPluginFleet', () => { Tags.of(fleet).add(tag.key, tag.value); // THEN - expectCDK(spotFleetStack).to(haveResourceLike('AWS::EC2::LaunchTemplate', { - LaunchTemplateData: objectLike({ - TagSpecifications: arrayWith({ + Template.fromStack(spotFleetStack).hasResourceProperties('AWS::EC2::LaunchTemplate', { + LaunchTemplateData: Match.objectLike({ + TagSpecifications: Match.arrayWith([{ ResourceType: SpotFleetResourceType.INSTANCE.toString(), - Tags: arrayWith({ - Key: tag.key, - Value: tag.value, - }), - }), + Tags: Match.arrayWith([ + { + Key: tag.key, + Value: tag.value, + }, + ]), + }]), }), - })); + }); }); }); @@ -519,7 +521,7 @@ describe('SpotEventPluginFleet', () => { }); // THEN - expectCDK(spotFleetStack).notTo(haveResource('AWS::EC2::SecurityGroup')); + Template.fromStack(spotFleetStack).resourceCountIs('AWS::EC2::SecurityGroup', 0); expect(fleet.securityGroups.length).toBe(1); expect(fleet.securityGroups).toContainEqual(sg); }); @@ -548,7 +550,7 @@ describe('SpotEventPluginFleet', () => { }); // THEN - expectCDK(spotFleetStack).notTo(haveResource('AWS::EC2::SecurityGroup')); + Template.fromStack(spotFleetStack).resourceCountIs('AWS::EC2::SecurityGroup', 0); expect(fleet.securityGroups.length).toBe(2); expect(fleet.securityGroups).toContainEqual(sg1); expect(fleet.securityGroups).toContainEqual(sg2); @@ -601,20 +603,22 @@ describe('SpotEventPluginFleet', () => { // THEN expect(fleet.fleetInstanceRole).toBe(spotFleetInstanceRole); - expectCDK(spotFleetStack).to(countResourcesLike('AWS::IAM::Role', 1, { - AssumeRolePolicyDocument: objectLike({ - Statement: [objectLike({ - Action: 'sts:AssumeRole', - Effect: 'Allow', - Principal: { - Service: 'ec2.amazonaws.com', - }, - })], + resourcePropertiesCountIs(spotFleetStack, 'AWS::IAM::Role', { + AssumeRolePolicyDocument: Match.objectLike({ + Statement: Match.arrayWith([ + Match.objectLike({ + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + Service: 'ec2.amazonaws.com', + }, + }), + ]), }), - ManagedPolicyArns: arrayWith( + ManagedPolicyArns: Match.arrayWith([ spotFleetStack.resolve(ManagedPolicy.fromAwsManagedPolicyName('AWSThinkboxDeadlineSpotEventPluginWorkerPolicy').managedPolicyArn), - ), - })); + ]), + }, 1); }); test('throws if provided spot fleet instance role is not from the same stack', () => { @@ -668,20 +672,22 @@ describe('SpotEventPluginFleet', () => { // THEN expect(fleet.fleetRole).toBe(fleetRole); - expectCDK(spotFleetStack).notTo(haveResourceLike('AWS::IAM::Role', { - AssumeRolePolicyDocument: objectLike({ - Statement: [objectLike({ - Action: 'sts:AssumeRole', - Effect: 'Allow', - Principal: { - Service: 'spotfleet.amazonaws.com', - }, - })], + resourcePropertiesCountIs(spotFleetStack, 'AWS::IAM::Role', { + AssumeRolePolicyDocument: Match.objectLike({ + Statement: Match.arrayWith([ + Match.objectLike({ + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + Service: 'spotfleet.amazonaws.com', + }, + }), + ]), }), - ManagedPolicyArns: arrayWith( + ManagedPolicyArns: Match.arrayWith([ stack.resolve(ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonEC2SpotFleetTaggingRole').managedPolicyArn), - ), - })); + ]), + }, 0); }); test('tags resources deployed by CDK', () => { @@ -701,14 +707,14 @@ describe('SpotEventPluginFleet', () => { Tags.of(fleet).add(tagName, tagValue); // THEN - expectCDK(spotFleetStack).to(haveResourceLike('AWS::EC2::SecurityGroup', { - Tags: arrayWith( - objectLike({ + Template.fromStack(spotFleetStack).hasResourceProperties('AWS::EC2::SecurityGroup', { + Tags: Match.arrayWith([ + Match.objectLike({ Key: tagName, Value: tagValue, }), - ), - })); + ]), + }); }); test('uses provided subnets', () => { @@ -895,10 +901,10 @@ describe('SpotEventPluginFleet', () => { }); // THEN - expectCDK(stack).to(haveResource('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { RetentionInDays: 3, LogGroupName: testPrefix + id, - })); + }); }); test('adds tag indicating resource tracker is not enabled', () => { @@ -914,17 +920,19 @@ describe('SpotEventPluginFleet', () => { }); // THEN - expectCDK(spotFleetStack).to(haveResourceLike('AWS::EC2::LaunchTemplate', { - LaunchTemplateData: objectLike({ - TagSpecifications: arrayWith({ + Template.fromStack(spotFleetStack).hasResourceProperties('AWS::EC2::LaunchTemplate', { + LaunchTemplateData: Match.objectLike({ + TagSpecifications: Match.arrayWith([{ ResourceType: 'instance', - Tags: arrayWith({ - Key: 'DeadlineResourceTracker', - Value: 'SpotEventPlugin', - }), - }), + Tags: Match.arrayWith([ + { + Key: 'DeadlineResourceTracker', + Value: 'SpotEventPlugin', + }, + ]), + }]), }), - })); + }); }); }); @@ -947,7 +955,7 @@ describe('SpotEventPluginFleet', () => { fleet.allowRemoteControlFrom(Peer.ipv4('127.0.0.1/24')); // THEN - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { SecurityGroupEgress: [{ CidrIp: '0.0.0.0/0' }], SecurityGroupIngress: [ { @@ -958,7 +966,7 @@ describe('SpotEventPluginFleet', () => { ToPort: fromPort + maxWorkersPerHost, }, ], - })); + }); }); test('to CIDR', () => { @@ -979,7 +987,7 @@ describe('SpotEventPluginFleet', () => { fleet.allowRemoteControlTo(Peer.ipv4('127.0.0.1/24')); // THEN - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { SecurityGroupEgress: [{ CidrIp: '0.0.0.0/0' }], SecurityGroupIngress: [ { @@ -990,7 +998,7 @@ describe('SpotEventPluginFleet', () => { ToPort: fromPort + maxWorkersPerHost, }, ], - })); + }); }); test('from SecurityGroup', () => { @@ -1012,12 +1020,12 @@ describe('SpotEventPluginFleet', () => { fleet.allowRemoteControlFrom(securityGroup); // THEN - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { FromPort: fromPort, IpProtocol: 'tcp', SourceSecurityGroupId: 'sg-123456789', ToPort: fromPort + maxWorkersPerHost, - })); + }); }); test('to SecurityGroup', () => { @@ -1039,12 +1047,12 @@ describe('SpotEventPluginFleet', () => { fleet.allowRemoteControlTo(securityGroup); // THEN - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { FromPort: fromPort, IpProtocol: 'tcp', SourceSecurityGroupId: 'sg-123456789', ToPort: fromPort + maxWorkersPerHost, - })); + }); }); test('from other stack', () => { @@ -1069,12 +1077,12 @@ describe('SpotEventPluginFleet', () => { fleet.allowRemoteControlFrom(securityGroup); // THEN - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { FromPort: fromPort, IpProtocol: 'tcp', SourceSecurityGroupId: 'sg-123456789', ToPort: fromPort + maxWorkersPerHost, - })); + }); }); test('to other stack', () => { @@ -1099,12 +1107,12 @@ describe('SpotEventPluginFleet', () => { fleet.allowRemoteControlTo(securityGroup); // THEN - expectCDK(otherStack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(otherStack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { FromPort: fromPort, IpProtocol: 'tcp', SourceSecurityGroupId: 'sg-123456789', ToPort: fromPort + maxWorkersPerHost, - })); + }); }); }); @@ -1171,8 +1179,10 @@ describe('SpotEventPluginFleet', () => { }); // THEN - expect(fleet.node.metadataEntry[0].type).toMatch(ArtifactMetadataEntryType.ERROR); - expect(fleet.node.metadataEntry[0].data).toMatch(/Did not find any subnets matching/); + Annotations.fromStack(spotFleetStack).hasError( + `/${fleet.node.path}`, + Match.stringLikeRegexp('Did not find any subnets matching.*'), + ); }); }); @@ -1296,8 +1306,10 @@ describe('SpotEventPluginFleet', () => { }); // THEN - expect(fleet.node.metadataEntry[0].type).toMatch(ArtifactMetadataEntryType.WARN); - expect(fleet.node.metadataEntry[0].data).toMatch('being created without being provided any block devices so the Source AMI\'s devices will be used. Workers can have access to sensitive data so it is recommended to either explicitly encrypt the devices on the worker fleet or to ensure the source AMI\'s Drives are encrypted.'); + Annotations.fromStack(spotFleetStack).hasWarning( + `/${fleet.node.path}`, + Match.stringLikeRegexp('.*being created without being provided any block devices so the Source AMI\'s devices will be used. Workers can have access to sensitive data so it is recommended to either explicitly encrypt the devices on the worker fleet or to ensure the source AMI\'s Drives are encrypted.'), + ); }); test('No Warnings if Encrypted BlockDevices Provided', () => { @@ -1318,7 +1330,9 @@ describe('SpotEventPluginFleet', () => { }); //THEN - expect(fleet.node.metadataEntry).toHaveLength(0); + Annotations.fromStack(spotFleetStack).hasNoInfo(`/${fleet.node.path}`, Match.anyValue()); + Annotations.fromStack(spotFleetStack).hasNoWarning(`/${fleet.node.path}`, Match.anyValue()); + Annotations.fromStack(spotFleetStack).hasNoError(`/${fleet.node.path}`, Match.anyValue()); }); test('Warnings if non-Encrypted BlockDevices Provided', () => { @@ -1341,8 +1355,10 @@ describe('SpotEventPluginFleet', () => { }); //THEN - expect(fleet.node.metadataEntry[0].type).toMatch(ArtifactMetadataEntryType.WARN); - expect(fleet.node.metadataEntry[0].data).toMatch(`The BlockDevice \"${DEVICE_NAME}\" on the spot-fleet ${id} is not encrypted. Workers can have access to sensitive data so it is recommended to encrypt the devices on the worker fleet.`); + Annotations.fromStack(spotFleetStack).hasWarning( + `/${fleet.node.path}`, + `The BlockDevice \"${DEVICE_NAME}\" on the spot-fleet ${id} is not encrypted. Workers can have access to sensitive data so it is recommended to encrypt the devices on the worker fleet.`, + ); }); test('Warnings for BlockDevices without encryption specified', () => { @@ -1365,8 +1381,10 @@ describe('SpotEventPluginFleet', () => { }); //THEN - expect(fleet.node.metadataEntry[0].type).toMatch(ArtifactMetadataEntryType.WARN); - expect(fleet.node.metadataEntry[0].data).toMatch(`The BlockDevice \"${DEVICE_NAME}\" on the spot-fleet ${id} is not encrypted. Workers can have access to sensitive data so it is recommended to encrypt the devices on the worker fleet.`); + Annotations.fromStack(spotFleetStack).hasWarning( + `/${fleet.node.path}`, + `The BlockDevice \"${DEVICE_NAME}\" on the spot-fleet ${id} is not encrypted. Workers can have access to sensitive data so it is recommended to encrypt the devices on the worker fleet.`, + ); }); test('No warnings for Ephemeral blockDeviceVolumes', () => { @@ -1387,7 +1405,9 @@ describe('SpotEventPluginFleet', () => { }); //THEN - expect(fleet.node.metadataEntry).toHaveLength(0); + Annotations.fromStack(spotFleetStack).hasNoInfo(`/${fleet.node.path}`, Match.anyValue()); + Annotations.fromStack(spotFleetStack).hasNoWarning(`/${fleet.node.path}`, Match.anyValue()); + Annotations.fromStack(spotFleetStack).hasNoError(`/${fleet.node.path}`, Match.anyValue()); }); test('No warnings for Suppressed blockDeviceVolumes', () => { @@ -1408,7 +1428,9 @@ describe('SpotEventPluginFleet', () => { }); //THEN - expect(fleet.node.metadataEntry).toHaveLength(0); + Annotations.fromStack(spotFleetStack).hasNoInfo(`/${fleet.node.path}`, Match.anyValue()); + Annotations.fromStack(spotFleetStack).hasNoWarning(`/${fleet.node.path}`, Match.anyValue()); + Annotations.fromStack(spotFleetStack).hasNoError(`/${fleet.node.path}`, Match.anyValue()); }); test('throws if block devices without iops and wrong volume type', () => { @@ -1472,8 +1494,10 @@ describe('SpotEventPluginFleet', () => { }); // THEN - expect(fleet.node.metadataEntry[0].type).toMatch(ArtifactMetadataEntryType.WARN); - expect(fleet.node.metadataEntry[0].data).toMatch('iops will be ignored without volumeType: EbsDeviceVolumeType.IO1'); + Annotations.fromStack(stack).hasWarning( + `/${fleet.node.path}`, + 'iops will be ignored without volumeType: EbsDeviceVolumeType.IO1', + ); }); }); }); diff --git a/packages/aws-rfdk/lib/deadline/test/stage.test.ts b/packages/aws-rfdk/lib/deadline/test/stage.test.ts index 7c9c14980..109f225b9 100644 --- a/packages/aws-rfdk/lib/deadline/test/stage.test.ts +++ b/packages/aws-rfdk/lib/deadline/test/stage.test.ts @@ -6,15 +6,14 @@ import * as fs from 'fs'; import * as path from 'path'; -import { - expect as expectCDK, - haveResourceLike, - stringLike, -} from '@aws-cdk/assert'; import { App, Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib'; +import { + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { Manifest, @@ -298,7 +297,7 @@ describe('Stage', () => { test('creates DockerImageAssets from existing recipes', () => { jest.resetModules(); const mockDockerImageAssetConstructor = jest.fn(); - jest.mock('@aws-cdk/aws-ecr-assets', () => { + jest.mock('aws-cdk-lib/aws-ecr-assets', () => { class DockerImageAsset { constructor(...args: [any]) { @@ -398,10 +397,10 @@ describe('Stage', () => { // WHEN stage.getVersion(stack, 'Version'); - expectCDK(stack).to(haveResourceLike('Custom::RFDK_DEADLINE_INSTALLERS', { - forceRun: stringLike('*'), + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_DEADLINE_INSTALLERS', { + forceRun: Match.anyValue(), versionString: '10.1.9', - })); + }); }); }); }); diff --git a/packages/aws-rfdk/lib/deadline/test/test-helper.ts b/packages/aws-rfdk/lib/deadline/test/test-helper.ts new file mode 100644 index 000000000..1b30c1b95 --- /dev/null +++ b/packages/aws-rfdk/lib/deadline/test/test-helper.ts @@ -0,0 +1,20 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + Stack, +} from 'aws-cdk-lib'; +import { + Match, + Template, +} from 'aws-cdk-lib/assertions'; + + +// CDKv2's assertion module doesn't have a Template.resourcePropertiesCountIs that would count +// the number of resources with the given properties. We add that here. +export function resourcePropertiesCountIs(stack: Stack, type: string, props: any, count: number): void { + const resources = Template.fromStack(stack).findResources(type, Match.objectLike({ Properties: props })); + expect(Object.keys(resources)).toHaveLength(count); +} \ No newline at end of file diff --git a/packages/aws-rfdk/lib/deadline/test/thinkbox-docker-images.test.ts b/packages/aws-rfdk/lib/deadline/test/thinkbox-docker-images.test.ts index 27771b463..4a1fc7f59 100644 --- a/packages/aws-rfdk/lib/deadline/test/thinkbox-docker-images.test.ts +++ b/packages/aws-rfdk/lib/deadline/test/thinkbox-docker-images.test.ts @@ -4,25 +4,21 @@ */ import { - arrayWith, - expect as expectCDK, - haveResource, - objectLike, - stringLike, - SynthUtils, -} from '@aws-cdk/assert'; + App, + CustomResource, + Stack, + Token, +} from 'aws-cdk-lib'; +import { + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { Compatibility, ContainerDefinition, ContainerImage, TaskDefinition, -} from '@aws-cdk/aws-ecs'; -import { - App, - CustomResource, - Stack, - Token, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ecs'; import { AwsThinkboxEulaAcceptance, @@ -79,7 +75,7 @@ AWS Thinkbox EULA. // WHEN function synth() { - SynthUtils.synthesize(newStack); + app.synth(); } // THEN @@ -88,9 +84,9 @@ AWS Thinkbox EULA. test('creates Custom::RFDK_ECR_PROVIDER', () => { // THEN - expectCDK(stack).to(haveResource('Custom::RFDK_EcrProvider', { - ForceRun: stringLike('*'), - })); + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_EcrProvider', { + ForceRun: Match.anyValue(), + }); }); describe('provides container images for', () => { @@ -127,11 +123,11 @@ AWS Thinkbox EULA. }); // THEN - expectCDK(taskDefStack).to(haveResource('AWS::ECS::TaskDefinition', { - ContainerDefinitions: arrayWith(objectLike({ + Template.fromStack(taskDefStack).hasResourceProperties('AWS::ECS::TaskDefinition', { + ContainerDefinitions: Match.arrayWith([Match.objectLike({ Image: taskDefStack.resolve(expectedImage), - })), - })); + })]), + }); }); }); @@ -222,11 +218,11 @@ AWS Thinkbox EULA. }); // THEN - expectCDK(taskDefStack).to(haveResource('AWS::ECS::TaskDefinition', { - ContainerDefinitions: arrayWith(objectLike({ + Template.fromStack(taskDefStack).hasResourceProperties('AWS::ECS::TaskDefinition', { + ContainerDefinitions: Match.arrayWith([Match.objectLike({ Image: taskDefStack.resolve(expectedImage), - })), - })); + })]), + }); }); }); @@ -240,7 +236,7 @@ AWS Thinkbox EULA. // WHEN function synth() { - SynthUtils.synthesize(newStack); + app.synth(); } // THEN diff --git a/packages/aws-rfdk/lib/deadline/test/thinkbox-docker-recipes.test.ts b/packages/aws-rfdk/lib/deadline/test/thinkbox-docker-recipes.test.ts index 7e2e55791..2d920fbd8 100644 --- a/packages/aws-rfdk/lib/deadline/test/thinkbox-docker-recipes.test.ts +++ b/packages/aws-rfdk/lib/deadline/test/thinkbox-docker-recipes.test.ts @@ -5,18 +5,16 @@ import * as path from 'path'; -import { - expect as expectCDK, - haveResource, - haveResourceLike, - stringLike, -} from '@aws-cdk/assert'; -import { DockerImageAsset } from '@aws-cdk/aws-ecr-assets'; -import { Asset } from '@aws-cdk/aws-s3-assets'; import { App, Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib'; +import { + Match, + Template, +} from 'aws-cdk-lib/assertions'; +import { DockerImageAsset } from 'aws-cdk-lib/aws-ecr-assets'; +import { Asset } from 'aws-cdk-lib/aws-s3-assets'; import { DeadlineDockerRecipes, @@ -150,10 +148,10 @@ describe('ThinkboxDockerRecipes', () => { // WHEN recipes.version; - expectCDK(stack).to(haveResourceLike('Custom::RFDK_DEADLINE_INSTALLERS', { - forceRun: stringLike('*'), + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_DEADLINE_INSTALLERS', { + forceRun: Match.anyValue(), versionString: RELEASE_VERSION_STRING, - })); + }); }); test('does not create a VersionQuery when not referenced', () => { @@ -162,7 +160,7 @@ describe('ThinkboxDockerRecipes', () => { stage, }); - expectCDK(stack).notTo(haveResource('Custom::RFDK_DEADLINE_INSTALLERS')); + Template.fromStack(stack).resourceCountIs('Custom::RFDK_DEADLINE_INSTALLERS', 0); }); test('.linuxInstallers.client creates an Asset using the client installer', () => { diff --git a/packages/aws-rfdk/lib/deadline/test/usage-based-licensing.test.ts b/packages/aws-rfdk/lib/deadline/test/usage-based-licensing.test.ts index 92bfd4870..a38bf1e27 100644 --- a/packages/aws-rfdk/lib/deadline/test/usage-based-licensing.test.ts +++ b/packages/aws-rfdk/lib/deadline/test/usage-based-licensing.test.ts @@ -4,12 +4,15 @@ */ import { - arrayWith, - expect as expectCDK, - haveResource, - haveResourceLike, - stringLike, -} from '@aws-cdk/assert'; + App, + CfnElement, + Stack, +} from 'aws-cdk-lib'; +import { + Annotations, + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { GenericWindowsImage, IVpc, @@ -17,26 +20,21 @@ import { SubnetSelection, SubnetType, Vpc, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { DockerImageAsset, -} from '@aws-cdk/aws-ecr-assets'; +} from 'aws-cdk-lib/aws-ecr-assets'; import { CfnService, ContainerImage, -} from '@aws-cdk/aws-ecs'; +} from 'aws-cdk-lib/aws-ecs'; import { ILogGroup, -} from '@aws-cdk/aws-logs'; +} from 'aws-cdk-lib/aws-logs'; import { ISecret, Secret, -} from '@aws-cdk/aws-secretsmanager'; -import { - App, - CfnElement, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-secretsmanager'; import { testConstructTags, @@ -133,10 +131,9 @@ describe('UsageBasedLicensing', () => { }); // THEN - expect(ubl.node.metadataEntry).not.toContainEqual(expect.objectContaining({ - type: 'aws:cdk:warning', - data: expect.stringMatching(/dedicated subnet/i), - })); + Annotations.fromStack(stack).hasNoInfo(`/${ubl.node.path}`, Match.anyValue()); + Annotations.fromStack(stack).hasNoWarning(`/${ubl.node.path}`, Match.anyValue()); + Annotations.fromStack(stack).hasNoError(`/${ubl.node.path}`, Match.anyValue()); }); test('vpcSubnets not specified => emits warning about dedicated subnets', () => { @@ -144,10 +141,10 @@ describe('UsageBasedLicensing', () => { const ubl = createUbl(); // THEN - expect(ubl.node.metadataEntry).toContainEqual(expect.objectContaining({ - type: 'aws:cdk:warning', - data: 'Deadline Secrets Management is enabled on the Repository and VPC subnets have not been supplied. Using dedicated subnets is recommended. See https://github.com/aws/aws-rfdk/blobs/release/packages/aws-rfdk/lib/deadline/README.md#using-dedicated-subnets-for-deadline-components', - })); + Annotations.fromStack(stack).hasWarning( + `/${ubl.node.path}`, + 'Deadline Secrets Management is enabled on the Repository and VPC subnets have not been supplied. Using dedicated subnets is recommended. See https://github.com/aws/aws-rfdk/blobs/release/packages/aws-rfdk/lib/deadline/README.md#using-dedicated-subnets-for-deadline-components', + ); }); describe('configures auto registration', () => { @@ -197,7 +194,7 @@ describe('UsageBasedLicensing', () => { createUbl(); // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::Cluster')); + Template.fromStack(stack).resourceCountIs('AWS::ECS::Cluster', 1); }); describe('creates an ASG', () => { @@ -206,18 +203,18 @@ describe('UsageBasedLicensing', () => { createUbl(); // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { MinSize: '1', MaxSize: '1', VPCZoneIdentifier: [ { - 'Fn::ImportValue': stringLike(`${dependencyStack.stackName}:ExportsOutputRefVPCPrivateSubnet1Subnet*`), + 'Fn::ImportValue': Match.stringLikeRegexp(`${dependencyStack.stackName}:ExportsOutputRefVPCPrivateSubnet1Subnet.*`), }, { - 'Fn::ImportValue': stringLike(`${dependencyStack.stackName}:ExportsOutputRefVPCPrivateSubnet2Subnet*`), + 'Fn::ImportValue': Match.stringLikeRegexp(`${dependencyStack.stackName}:ExportsOutputRefVPCPrivateSubnet2Subnet.*`), }, ], - })); + }); }); test('capacity can be specified', () => { @@ -227,10 +224,10 @@ describe('UsageBasedLicensing', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { MinSize: '2', MaxSize: '2', - })); + }); }); test('gives write access to log group', () => { @@ -242,24 +239,24 @@ describe('UsageBasedLicensing', () => { const asgRoleLogicalId = Stack.of(ubl).getLogicalId(ubl.asg.role.node.defaultChild as CfnElement); // THEN - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { - Action: arrayWith( + Action: Match.arrayWith([ 'logs:CreateLogStream', 'logs:PutLogEvents', - ), + ]), Effect: 'Allow', Resource: stack.resolve(logGroup.logGroupArn), }, - ), + ]), Version: '2012-10-17', }, - Roles: arrayWith( + Roles: Match.arrayWith([ { Ref: asgRoleLogicalId }, - ), - })); + ]), + }); }); test('uses the supplied security group', () => { @@ -272,9 +269,9 @@ describe('UsageBasedLicensing', () => { createUbl({ securityGroup }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { - SecurityGroups: arrayWith(stack.resolve(securityGroup.securityGroupId)), - })); + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { + SecurityGroups: Match.arrayWith([stack.resolve(securityGroup.securityGroupId)]), + }); }); }); @@ -284,9 +281,9 @@ describe('UsageBasedLicensing', () => { const ubl = createUbl(); // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { Cluster: { Ref: stack.getLogicalId(ubl.cluster.node.defaultChild as CfnElement) }, - })); + }); }); describe('DesiredCount', () => { @@ -295,9 +292,9 @@ describe('UsageBasedLicensing', () => { createUbl(); // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { DesiredCount: 1, - })); + }); }); test('can be specified', () => { @@ -308,9 +305,9 @@ describe('UsageBasedLicensing', () => { createUbl({ desiredCount }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { DesiredCount: desiredCount, - })); + }); }); }); @@ -319,9 +316,9 @@ describe('UsageBasedLicensing', () => { createUbl(); // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { LaunchType: 'EC2', - })); + }); }); test('sets distinct instance placement constraint', () => { @@ -329,11 +326,11 @@ describe('UsageBasedLicensing', () => { createUbl(); // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::Service', { - PlacementConstraints: arrayWith( + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { + PlacementConstraints: Match.arrayWith([ { Type: 'distinctInstance' }, - ), - })); + ]), + }); }); test('uses the task definition', () => { @@ -341,9 +338,9 @@ describe('UsageBasedLicensing', () => { const ubl = createUbl(); // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { TaskDefinition: { Ref: stack.getLogicalId(ubl.service.taskDefinition.node.defaultChild as CfnElement) }, - })); + }); }); test('with the correct deployment configuration', () => { @@ -351,12 +348,12 @@ describe('UsageBasedLicensing', () => { createUbl(); // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { DeploymentConfiguration: { MaximumPercent: 100, MinimumHealthyPercent: 0, }, - })); + }); }); }); @@ -366,13 +363,13 @@ describe('UsageBasedLicensing', () => { createUbl(); // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { Name: 'LicenseForwarderContainer', }, ], - })); + }); }); test('container is marked essential', () => { @@ -380,13 +377,13 @@ describe('UsageBasedLicensing', () => { createUbl(); // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { Essential: true, }, ], - })); + }); }); test('with increased ulimits', () => { @@ -394,7 +391,7 @@ describe('UsageBasedLicensing', () => { createUbl(); // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { Ulimits: [ @@ -411,7 +408,7 @@ describe('UsageBasedLicensing', () => { ], }, ], - })); + }); }); test('with awslogs log driver', () => { @@ -419,7 +416,7 @@ describe('UsageBasedLicensing', () => { createUbl(); // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { LogConfiguration: { @@ -432,7 +429,7 @@ describe('UsageBasedLicensing', () => { }, }, ], - })); + }); }); test('configures UBL certificates', () => { @@ -443,15 +440,15 @@ describe('UsageBasedLicensing', () => { const taskRoleLogicalId = Stack.of(ubl).getLogicalId(ubl.service.taskDefinition.taskRole.node.defaultChild as CfnElement); // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { - Environment: arrayWith( + Environment: Match.arrayWith([ { Name: 'UBL_CERTIFICATES_URI', Value: certificateSecret.secretArn, }, - ), + ]), }, ], TaskRoleArn: { @@ -460,11 +457,11 @@ describe('UsageBasedLicensing', () => { 'Arn', ], }, - })); + }); - expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: [ 'secretsmanager:GetSecretValue', @@ -473,13 +470,13 @@ describe('UsageBasedLicensing', () => { Effect: 'Allow', Resource: certificateSecret.secretArn, }, - ), + ]), Version: '2012-10-17', }, Roles: [ { Ref: Stack.of(ubl).getLogicalId(ubl.service.taskDefinition.taskRole.node.defaultChild as CfnElement) }, ], - })); + }); }); test('uses host networking', () => { @@ -487,9 +484,9 @@ describe('UsageBasedLicensing', () => { createUbl(); // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { NetworkMode: 'host', - })); + }); }); test('is marked EC2 compatible only', () => { @@ -497,9 +494,9 @@ describe('UsageBasedLicensing', () => { createUbl(); // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { RequiresCompatibilities: [ 'EC2' ], - })); + }); }); }); @@ -519,9 +516,9 @@ describe('UsageBasedLicensing', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { VPCZoneIdentifier: publicSubnetIds, - })); + }); }); test.each([ @@ -539,9 +536,9 @@ describe('UsageBasedLicensing', () => { }); // THEN - expectCDK(stack).to(haveResource('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { LogGroupName: testPrefix + id, - })); + }); }); describe('license limits', () => { @@ -555,18 +552,18 @@ describe('UsageBasedLicensing', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { - Environment: arrayWith( + Environment: Match.arrayWith([ { Name: 'UBL_LIMITS', Value: 'maya:10;vray:10', }, - ), + ]), }, ], - })); + }); }); test.each([ @@ -606,14 +603,14 @@ describe('UsageBasedLicensing', () => { // THEN ports.forEach( port => { - expectCDK(workerStack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(workerStack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', ToPort: port, GroupId: { - 'Fn::ImportValue': stringLike(`${Stack.of(ubl).stackName}:ExportsOutputFnGetAttUBLClusterASGInstanceSecurityGroup*`), + 'Fn::ImportValue': Match.stringLikeRegexp(`${Stack.of(ubl).stackName}:ExportsOutputFnGetAttUBLClusterASGInstanceSecurityGroup.*`), }, SourceSecurityGroupId: 'sg-123456789', - })); + }); }); }); @@ -634,13 +631,13 @@ describe('UsageBasedLicensing', () => { const ubl = createUbl(); const ublSecurityGroup = ubl.connections.securityGroups[0]; - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', FromPort: 4433, ToPort: 4433, GroupId: stack.resolve(renderQueueSecurityGroup.securityGroupId), SourceSecurityGroupId: stack.resolve(ublSecurityGroup.securityGroupId), - })); + }); }); test('adds ingress rule from RenderQueue ASG to UsageBasedLicensing ASG', () => { @@ -651,13 +648,13 @@ describe('UsageBasedLicensing', () => { const ubl = createUbl(); const ublSecurityGroup = ubl.connections.securityGroups[0]; - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', FromPort: 17004, ToPort: 17004, GroupId: stack.resolve(ublSecurityGroup.securityGroupId), SourceSecurityGroupId: stack.resolve(renderQueueSecurityGroup.securityGroupId), - })); + }); }); test('sets RENDER_QUEUE_URI environment variable', () => { @@ -665,18 +662,18 @@ describe('UsageBasedLicensing', () => { createUbl(); // THEN - expectCDK(stack).to(haveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { - Environment: arrayWith( + Environment: Match.arrayWith([ { Name: 'RENDER_QUEUE_URI', Value: stack.resolve(`${renderQueue.endpoint.applicationProtocol.toLowerCase()}://${renderQueue.endpoint.socketAddress}`), }, - ), + ]), }, ], - })); + }); }); }); diff --git a/packages/aws-rfdk/lib/deadline/test/version-query.test.ts b/packages/aws-rfdk/lib/deadline/test/version-query.test.ts index aa0b158af..29e16ab10 100644 --- a/packages/aws-rfdk/lib/deadline/test/version-query.test.ts +++ b/packages/aws-rfdk/lib/deadline/test/version-query.test.ts @@ -3,17 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { - ABSENT, - expect as expectCDK, - haveResourceLike, - stringLike, -} from '@aws-cdk/assert'; import { App, CustomResource, Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib'; +import { + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { Installer, @@ -25,11 +23,11 @@ test('VersionQuery constructor full version', () => { const stack = new Stack(app, 'Stack'); new VersionQuery(stack, 'VersionQuery', { version: '10.1.9.2'}); - expectCDK(stack).to(haveResourceLike('Custom::RFDK_DEADLINE_INSTALLERS', { - forceRun: ABSENT, + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_DEADLINE_INSTALLERS', { + forceRun: Match.absent(), versionString: '10.1.9.2', - })); - expectCDK(stack).to(haveResourceLike('AWS::IAM::Role', { + }); + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { AssumeRolePolicyDocument: { Statement: [ { @@ -55,17 +53,17 @@ test('VersionQuery constructor full version', () => { ], }, ], - })); - expectCDK(stack).to(haveResourceLike('AWS::Lambda::Function', { + }); + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'version-provider.handler', Role: { 'Fn::GetAtt': [ - stringLike('SingletonLambda*ServiceRole*'), + Match.stringLikeRegexp('SingletonLambda.*ServiceRole.*'), 'Arn', ], }, Runtime: 'nodejs16.x', - })); + }); }); test('VersionQuery constructor no versionString', () => { @@ -73,10 +71,10 @@ test('VersionQuery constructor no versionString', () => { const stack = new Stack(app, 'Stack'); new VersionQuery(stack, 'VersionQuery'); - expectCDK(stack).to(haveResourceLike('Custom::RFDK_DEADLINE_INSTALLERS', { - forceRun: stringLike('*'), - versionString: ABSENT, - })); + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_DEADLINE_INSTALLERS', { + forceRun: Match.anyValue(), + versionString: Match.absent(), + }); }); test.each([ @@ -88,10 +86,10 @@ test.each([ const stack = new Stack(app, 'Stack'); new VersionQuery(stack, 'VersionQuery', { version }); - expectCDK(stack).to(haveResourceLike('Custom::RFDK_DEADLINE_INSTALLERS', { + Template.fromStack(stack).hasResourceProperties('Custom::RFDK_DEADLINE_INSTALLERS', { versionString: version, - forceRun: stringLike('*'), - })); + forceRun: Match.anyValue(), + }); }); describe('VersionQuery.linuxInstallers', () => { diff --git a/packages/aws-rfdk/lib/deadline/test/wait-for-stable-service.test.ts b/packages/aws-rfdk/lib/deadline/test/wait-for-stable-service.test.ts index 7155a780c..67e846b26 100644 --- a/packages/aws-rfdk/lib/deadline/test/wait-for-stable-service.test.ts +++ b/packages/aws-rfdk/lib/deadline/test/wait-for-stable-service.test.ts @@ -4,34 +4,32 @@ */ import { - arrayWith, - countResourcesLike, - expect as cdkExpect, - haveResourceLike, - objectLike, -} from '@aws-cdk/assert'; + App, + Stack, +} from 'aws-cdk-lib'; +import { + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { InstanceClass, InstanceSize, InstanceType, SubnetType, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { Cluster, ContainerImage, Ec2Service, Ec2TaskDefinition, -} from '@aws-cdk/aws-ecs'; +} from 'aws-cdk-lib/aws-ecs'; import { ManagedPolicy, -} from '@aws-cdk/aws-iam'; -import { - App, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-iam'; import { WaitForStableService, } from '../lib/wait-for-stable-service'; +import { resourcePropertiesCountIs } from './test-helper'; describe('WaitForStableService', () => { let app: App; @@ -70,10 +68,10 @@ describe('WaitForStableService', () => { }); // THEN - cdkExpect(isolatedStack).to(haveResourceLike('Custom::RFDK_WaitForStableService', { + Template.fromStack(isolatedStack).hasResourceProperties('Custom::RFDK_WaitForStableService', { cluster: isolatedStack.resolve(cluster.clusterArn), services: [isolatedStack.resolve(service.serviceArn)], - })); + }); }); test('creates lambda correctly', () => { @@ -82,7 +80,7 @@ describe('WaitForStableService', () => { service, }); - cdkExpect(isolatedStack).to(countResourcesLike('AWS::Lambda::Function', 1, { + resourcePropertiesCountIs(isolatedStack, 'AWS::Lambda::Function', { Handler: 'wait-for-stable-service.wait', Environment: { Variables: { @@ -91,7 +89,7 @@ describe('WaitForStableService', () => { }, Runtime: 'nodejs16.x', Timeout: 900, - })); + }, 1); }); test('adds policies to the lambda role', () => { @@ -101,22 +99,22 @@ describe('WaitForStableService', () => { }); // THEN - cdkExpect(isolatedStack).to(haveResourceLike('AWS::IAM::Role', { - ManagedPolicyArns: arrayWith( + Template.fromStack(isolatedStack).hasResourceProperties('AWS::IAM::Role', { + ManagedPolicyArns: Match.arrayWith([ isolatedStack.resolve(ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole').managedPolicyArn), - ), + ]), Policies: [{ - PolicyDocument: objectLike({ + PolicyDocument: Match.objectLike({ Statement: [{ Action: 'ecs:DescribeServices', Effect: 'Allow', - Resource: arrayWith( + Resource: Match.arrayWith([ isolatedStack.resolve(cluster.clusterArn), isolatedStack.resolve(service.serviceArn), - ), + ]), }], }), }], - })); + }); }); }); diff --git a/packages/aws-rfdk/lib/deadline/test/worker-configuration.test.ts b/packages/aws-rfdk/lib/deadline/test/worker-configuration.test.ts index 20a0d75f9..15861eb81 100644 --- a/packages/aws-rfdk/lib/deadline/test/worker-configuration.test.ts +++ b/packages/aws-rfdk/lib/deadline/test/worker-configuration.test.ts @@ -6,10 +6,12 @@ /* eslint-disable dot-notation */ import { - expect as expectCDK, - haveResource, - haveResourceLike, -} from '@aws-cdk/assert'; + Stack, +} from 'aws-cdk-lib'; +import { + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { AmazonLinuxGeneration, Instance, @@ -19,19 +21,20 @@ import { SecurityGroup, Vpc, WindowsVersion, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { ContainerImage, -} from '@aws-cdk/aws-ecs'; +} from 'aws-cdk-lib/aws-ecs'; import { ILogGroup, -} from '@aws-cdk/aws-logs'; -import { - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-logs'; import { LogGroupFactoryProps, } from '../../core/lib'; +import { + CWA_ASSET_LINUX, + CWA_ASSET_WINDOWS, +} from '../../core/test/asset-constants'; import { RenderQueue, Repository, @@ -40,10 +43,10 @@ import { WorkerInstanceConfiguration, } from '../lib'; import { - linuxConfigureWorkerScriptBoilerplate, - linuxCloudWatchScriptBoilerplate, - windowsConfigureWorkerScriptBoilerplate, - windowsCloudWatchScriptBoilerplate, + CONFIG_WORKER_ASSET_LINUX, + CONFIG_WORKER_ASSET_WINDOWS, + CONFIG_WORKER_PORT_ASSET_LINUX, + CONFIG_WORKER_PORT_ASSET_WINDOWS, } from './asset-constants'; describe('Test WorkerInstanceConfiguration for Linux', () => { @@ -66,18 +69,32 @@ describe('Test WorkerInstanceConfiguration for Linux', () => { new WorkerInstanceConfiguration(stack, 'Config', { worker: instance, }); - const userData = stack.resolve(instance.userData.render()); - - // // THEN - expect(userData).toStrictEqual({ - 'Fn::Join': [ - '', - [ - '#!/bin/bash\nmkdir -p $(dirname \'/tmp/', - ...linuxConfigureWorkerScriptBoilerplate( - `\' \'\' \'\' \'\' \'${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}\' ${WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT']} /tmp/`), - ], - ], + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + [ + '#!/bin/bash\n' + + `mkdir -p $(dirname '/tmp/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py')\naws s3 cp 's3://`, + { + 'Fn::Sub': CONFIG_WORKER_PORT_ASSET_LINUX.Bucket, + }, + `/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py' '/tmp/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py'\n` + + `mkdir -p $(dirname '/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh')\naws s3 cp 's3://`, + { + 'Fn::Sub': CONFIG_WORKER_ASSET_LINUX.Bucket, + }, + `/${CONFIG_WORKER_ASSET_LINUX.Key}.sh' '/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh'\n` + + 'set -e\n' + + `chmod +x '/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh'\n` + + `'/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh' '' '' '' '${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}' ${WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT']} /tmp/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py`, + ], + ], + }, + }, }); }); @@ -91,17 +108,32 @@ describe('Test WorkerInstanceConfiguration for Linux', () => { listenerPort: otherListenerPort, }, }); - const userData = stack.resolve(instance.userData.render()); - - // // THEN - expect(userData).toStrictEqual({ - 'Fn::Join': [ - '', - [ - '#!/bin/bash\nmkdir -p $(dirname \'/tmp/', - ...linuxConfigureWorkerScriptBoilerplate(`\' \'\' \'\' \'\' \'${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}\' ${otherListenerPort} /tmp/`), - ], - ], + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + [ + '#!/bin/bash\n' + + `mkdir -p $(dirname '/tmp/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py')\naws s3 cp 's3://`, + { + 'Fn::Sub': CONFIG_WORKER_PORT_ASSET_LINUX.Bucket, + }, + `/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py' '/tmp/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py'\n` + + `mkdir -p $(dirname '/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh')\naws s3 cp 's3://`, + { + 'Fn::Sub': CONFIG_WORKER_ASSET_LINUX.Bucket, + }, + `/${CONFIG_WORKER_ASSET_LINUX.Key}.sh' '/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh'\n` + + 'set -e\n' + + `chmod +x '/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh'\n` + + `'/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh' '' '' '' '${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}' ${otherListenerPort} /tmp/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py`, + ], + ], + }, + }, }); }); @@ -115,18 +147,32 @@ describe('Test WorkerInstanceConfiguration for Linux', () => { region: 'r1', }, }); - const userData = stack.resolve(instance.userData.render()); - - // // THEN - expect(userData).toStrictEqual({ - 'Fn::Join': [ - '', - [ - '#!/bin/bash\nmkdir -p $(dirname \'/tmp/', - ...linuxConfigureWorkerScriptBoilerplate( - `\' \'g1,g2\' \'p1,p2\' \'r1\' \'${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}\' ${WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT']} /tmp/`), - ], - ], + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + [ + '#!/bin/bash\n' + + `mkdir -p $(dirname '/tmp/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py')\naws s3 cp 's3://`, + { + 'Fn::Sub': CONFIG_WORKER_PORT_ASSET_LINUX.Bucket, + }, + `/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py' '/tmp/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py'\n` + + `mkdir -p $(dirname '/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh')\naws s3 cp 's3://`, + { + 'Fn::Sub': CONFIG_WORKER_ASSET_LINUX.Bucket, + }, + `/${CONFIG_WORKER_ASSET_LINUX.Key}.sh' '/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh'\n` + + 'set -e\n' + + `chmod +x '/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh'\n` + + `'/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh' 'g1,g2' 'p1,p2' 'r1' '${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}' ${WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT']} /tmp/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py`, + ], + ], + }, + }, }); }); @@ -141,23 +187,48 @@ describe('Test WorkerInstanceConfiguration for Linux', () => { worker: instance, cloudWatchLogSettings: logGroupProps, }); - const logGroup = config.node.findChild('ConfigLogGroupWrapper'); - const logGroupName = stack.resolve((logGroup as ILogGroup).logGroupName); - const userData = stack.resolve(instance.userData.render()); + const logGroup = config.node.findChild('ConfigLogGroup') as ILogGroup; + const logGroupName = stack.resolve(logGroup.logGroupName); // THEN - expect(userData).toStrictEqual({ - 'Fn::Join': [ - '', - [ - '#!/bin/bash\nmkdir -p $(dirname \'/tmp/', - ...linuxCloudWatchScriptBoilerplate( - `\' \'\' \'\' \'\' \'${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}\' ${WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT']} /tmp/`), - ], - ], + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + [ + `#!/bin/bash\nmkdir -p $(dirname '/tmp/${CWA_ASSET_LINUX.Key}.sh')\naws s3 cp 's3://`, + { + 'Fn::Sub': CWA_ASSET_LINUX.Bucket, + }, + `/${CWA_ASSET_LINUX.Key}.sh' '/tmp/${CWA_ASSET_LINUX.Key}.sh'\nset -e\nchmod +x '/tmp/${CWA_ASSET_LINUX.Key}.sh'\n'/tmp/${CWA_ASSET_LINUX.Key}.sh' -i `, + { + Ref: 'AWS::Region', + }, + ' ', + { + Ref: Match.stringLikeRegexp('^ConfigStringParameter.*'), + }, + `\nmkdir -p $(dirname '/tmp/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py')\naws s3 cp 's3://`, + { + 'Fn::Sub': CONFIG_WORKER_PORT_ASSET_LINUX.Bucket, + }, + `/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py' '/tmp/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py'\n` + + `mkdir -p $(dirname '/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh')\naws s3 cp 's3://`, + { + 'Fn::Sub': CONFIG_WORKER_ASSET_LINUX.Bucket, + }, + `/${CONFIG_WORKER_ASSET_LINUX.Key}.sh' '/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh'\n` + + 'set -e\n' + + `chmod +x '/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh'\n` + + `'/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh' '' '' '' '${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}' ${WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT']} /tmp/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py`, + ], + ], + }, + }, }); - expectCDK(stack).to(haveResource('AWS::SSM::Parameter', { + Template.fromStack(stack).hasResourceProperties('AWS::SSM::Parameter', { Value: { 'Fn::Join': [ '', @@ -172,7 +243,7 @@ describe('Test WorkerInstanceConfiguration for Linux', () => { ], ], }, - })); + }); }); }); @@ -196,19 +267,30 @@ describe('Test WorkerInstanceConfiguration for Windows', () => { new WorkerInstanceConfiguration(stack, 'Config', { worker: instance, }); - const userData = stack.resolve(instance.userData.render()); // THEN - expect(userData).toStrictEqual({ - 'Fn::Join': [ - '', - [ - 'mkdir (Split-Path -Path \'C:/temp/', - ...windowsConfigureWorkerScriptBoilerplate( - `\' \'\' \'\' \'\' \'${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}\' ${WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT']} C:/temp/`), - '\"\' -ErrorAction Stop }', - ], - ], + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + [ + `mkdir (Split-Path -Path 'C:/temp/${CONFIG_WORKER_ASSET_WINDOWS.Key}.py' ) -ea 0\nRead-S3Object -BucketName '`, + { + 'Fn::Sub': CONFIG_WORKER_ASSET_WINDOWS.Bucket, + }, + `' -key '${CONFIG_WORKER_ASSET_WINDOWS.Key}.py' -file 'C:/temp/${CONFIG_WORKER_ASSET_WINDOWS.Key}.py' -ErrorAction Stop\n` + + `mkdir (Split-Path -Path 'C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' ) -ea 0\nRead-S3Object -BucketName '`, + { + 'Fn::Sub': CONFIG_WORKER_PORT_ASSET_WINDOWS.Bucket, + }, + `' -key '${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' -file 'C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' -ErrorAction Stop\n` + + `&'C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' '' '' '' '${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}' ${WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT']} C:/temp/${CONFIG_WORKER_ASSET_WINDOWS.Key}.py\n` + + `if (!$?) { Write-Error 'Failed to execute the file \"C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1\"' -ErrorAction Stop }`, + ], + ], + }, + }, }); }); @@ -222,19 +304,30 @@ describe('Test WorkerInstanceConfiguration for Windows', () => { region: 'r1', }, }); - const userData = stack.resolve(instance.userData.render()); // THEN - expect(userData).toStrictEqual({ - 'Fn::Join': [ - '', - [ - 'mkdir (Split-Path -Path \'C:/temp/', - ...windowsConfigureWorkerScriptBoilerplate( - `\' \'g1,g2\' \'p1,p2\' \'r1\' \'${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}\' ${WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT']} C:/temp/`), - '\"\' -ErrorAction Stop }', - ], - ], + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + [ + `mkdir (Split-Path -Path 'C:/temp/${CONFIG_WORKER_ASSET_WINDOWS.Key}.py' ) -ea 0\nRead-S3Object -BucketName '`, + { + 'Fn::Sub': CONFIG_WORKER_ASSET_WINDOWS.Bucket, + }, + `' -key '${CONFIG_WORKER_ASSET_WINDOWS.Key}.py' -file 'C:/temp/${CONFIG_WORKER_ASSET_WINDOWS.Key}.py' -ErrorAction Stop\n` + + `mkdir (Split-Path -Path 'C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' ) -ea 0\nRead-S3Object -BucketName '`, + { + 'Fn::Sub': CONFIG_WORKER_PORT_ASSET_WINDOWS.Bucket, + }, + `' -key '${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' -file 'C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' -ErrorAction Stop\n` + + `&'C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' 'g1,g2' 'p1,p2' 'r1' '${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}' ${WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT']} C:/temp/${CONFIG_WORKER_ASSET_WINDOWS.Key}.py\n` + + `if (!$?) { Write-Error 'Failed to execute the file \"C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1\"' -ErrorAction Stop }`, + ], + ], + }, + }, }); }); @@ -247,19 +340,30 @@ describe('Test WorkerInstanceConfiguration for Windows', () => { listenerPort: otherListenerPort, }, }); - const userData = stack.resolve(instance.userData.render()); // THEN - expect(userData).toStrictEqual({ - 'Fn::Join': [ - '', - [ - 'mkdir (Split-Path -Path \'C:/temp/', - ...windowsConfigureWorkerScriptBoilerplate( - `\' \'\' \'\' \'\' \'${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}\' ${otherListenerPort} C:/temp/`), - '\"\' -ErrorAction Stop }', - ], - ], + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + [ + `mkdir (Split-Path -Path 'C:/temp/${CONFIG_WORKER_ASSET_WINDOWS.Key}.py' ) -ea 0\nRead-S3Object -BucketName '`, + { + 'Fn::Sub': CONFIG_WORKER_ASSET_WINDOWS.Bucket, + }, + `' -key '${CONFIG_WORKER_ASSET_WINDOWS.Key}.py' -file 'C:/temp/${CONFIG_WORKER_ASSET_WINDOWS.Key}.py' -ErrorAction Stop\n` + + `mkdir (Split-Path -Path 'C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' ) -ea 0\nRead-S3Object -BucketName '`, + { + 'Fn::Sub': CONFIG_WORKER_PORT_ASSET_WINDOWS.Bucket, + }, + `' -key '${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' -file 'C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' -ErrorAction Stop\n` + + `&'C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' '' '' '' '${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}' ${otherListenerPort} C:/temp/${CONFIG_WORKER_ASSET_WINDOWS.Key}.py\n` + + `if (!$?) { Write-Error 'Failed to execute the file \"C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1\"' -ErrorAction Stop }`, + ], + ], + }, + }, }); }); @@ -274,24 +378,48 @@ describe('Test WorkerInstanceConfiguration for Windows', () => { worker: instance, cloudWatchLogSettings: logGroupProps, }); - const logGroup = config.node.findChild('ConfigLogGroupWrapper'); - const logGroupName = stack.resolve((logGroup as ILogGroup).logGroupName); - const userData = stack.resolve(instance.userData.render()); + const logGroup = config.node.findChild('ConfigLogGroup') as ILogGroup; + const logGroupName = stack.resolve(logGroup.logGroupName); // THEN - expect(userData).toStrictEqual({ - 'Fn::Join': [ - '', - [ - 'mkdir (Split-Path -Path \'C:/temp/', - ...windowsCloudWatchScriptBoilerplate( - `\' \'\' \'\' \'\' \'${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}\' ${WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT']} C:/temp/`), - '\"\' -ErrorAction Stop }', - ], - ], + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + [ + `mkdir (Split-Path -Path 'C:/temp/${CWA_ASSET_WINDOWS.Key}.ps1' ) -ea 0\nRead-S3Object -BucketName '`, + { + 'Fn::Sub': CWA_ASSET_WINDOWS.Bucket, + }, + `' -key '${CWA_ASSET_WINDOWS.Key}.ps1' -file 'C:/temp/${CWA_ASSET_WINDOWS.Key}.ps1' -ErrorAction Stop\n&'C:/temp/${CWA_ASSET_WINDOWS.Key}.ps1' -i `, + { + Ref: 'AWS::Region', + }, + ' ', + { + Ref: Match.stringLikeRegexp('^ConfigStringParameter.*'), + }, + `\nif (!$?) { Write-Error 'Failed to execute the file \"C:/temp/${CWA_ASSET_WINDOWS.Key}.ps1\"' -ErrorAction Stop }\n` + + `mkdir (Split-Path -Path 'C:/temp/${CONFIG_WORKER_ASSET_WINDOWS.Key}.py' ) -ea 0\nRead-S3Object -BucketName '`, + { + 'Fn::Sub': CONFIG_WORKER_ASSET_WINDOWS.Bucket, + }, + `' -key '${CONFIG_WORKER_ASSET_WINDOWS.Key}.py' -file 'C:/temp/${CONFIG_WORKER_ASSET_WINDOWS.Key}.py' -ErrorAction Stop\n` + + `mkdir (Split-Path -Path 'C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' ) -ea 0\nRead-S3Object -BucketName '`, + { + 'Fn::Sub': CONFIG_WORKER_PORT_ASSET_WINDOWS.Bucket, + }, + `' -key '${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' -file 'C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' -ErrorAction Stop\n` + + `&'C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' '' '' '' '${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}' ${WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT']} C:/temp/${CONFIG_WORKER_ASSET_WINDOWS.Key}.py\n` + + `if (!$?) { Write-Error 'Failed to execute the file \"C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1\"' -ErrorAction Stop }`, + ], + ], + }, + }, }); - expectCDK(stack).to(haveResource('AWS::SSM::Parameter', { + Template.fromStack(stack).hasResourceProperties('AWS::SSM::Parameter', { Value: { 'Fn::Join': [ '', @@ -306,7 +434,7 @@ describe('Test WorkerInstanceConfiguration for Windows', () => { ], ], }, - })); + }); }); }); @@ -355,12 +483,12 @@ describe('Test WorkerInstanceConfiguration connect to RenderQueue', () => { // THEN // Open-box testing. We know that we invoked the connection method on the // render queue if the security group for the instance has an ingress rule to the RQ. - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', ToPort: 8080, SourceSecurityGroupId: instanceSGId, GroupId: renderQueueSGId, - })); + }); }); test('For Windows', () => { @@ -382,11 +510,11 @@ describe('Test WorkerInstanceConfiguration connect to RenderQueue', () => { // THEN // Open-box testing. We know that we invoked the connection method on the // render queue if the security group for the instance has an ingress rule to the RQ. - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', ToPort: 8080, SourceSecurityGroupId: instanceSGId, GroupId: renderQueueSGId, - })); + }); }); }); \ No newline at end of file diff --git a/packages/aws-rfdk/lib/deadline/test/worker-fleet.test.ts b/packages/aws-rfdk/lib/deadline/test/worker-fleet.test.ts index 69ca51df4..c8ee5eab4 100644 --- a/packages/aws-rfdk/lib/deadline/test/worker-fleet.test.ts +++ b/packages/aws-rfdk/lib/deadline/test/worker-fleet.test.ts @@ -6,16 +6,18 @@ /* eslint-disable dot-notation */ import { - ABSENT, - expect as expectCDK, - haveResource, - haveResourceLike, - objectLike, - ResourcePart, -} from '@aws-cdk/assert'; + App, + CfnElement, + Stack, +} from 'aws-cdk-lib'; +import { + Annotations, + Match, + Template, +} from 'aws-cdk-lib/assertions'; import { BlockDeviceVolume, -} from '@aws-cdk/aws-autoscaling'; +} from 'aws-cdk-lib/aws-autoscaling'; import { GenericLinuxImage, GenericWindowsImage, @@ -27,27 +29,22 @@ import { SecurityGroup, SubnetType, Vpc, -} from '@aws-cdk/aws-ec2'; +} from 'aws-cdk-lib/aws-ec2'; import { AssetImage, ContainerImage, -} from '@aws-cdk/aws-ecs'; -import { ArtifactMetadataEntryType } from '@aws-cdk/cloud-assembly-schema'; -import { - App, - CfnElement, - Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib/aws-ecs'; import { HealthMonitor, } from '../../core/lib'; +import { + CWA_ASSET_LINUX, + CWA_ASSET_WINDOWS, +} from '../../core/test/asset-constants'; import { testConstructTags, } from '../../core/test/tag-helpers'; -import { - escapeTokenRegex, -} from '../../core/test/token-regex-helpers'; import { IHost, InstanceUserDataProvider, @@ -63,9 +60,13 @@ import { import { CONFIG_WORKER_ASSET_LINUX, CONFIG_WORKER_ASSET_WINDOWS, - CWA_ASSET_LINUX, + CONFIG_WORKER_HEALTHCHECK_LINUX, + CONFIG_WORKER_HEALTHCHECK_WINDOWS, + CONFIG_WORKER_PORT_ASSET_LINUX, + CONFIG_WORKER_PORT_ASSET_WINDOWS, RQ_CONNECTION_ASSET, } from './asset-constants'; +import { resourcePropertiesCountIs } from './test-helper'; let app: App; let stack: Stack; @@ -113,12 +114,24 @@ test('default worker fleet is created correctly', () => { }); // THEN - expectCDK(wfstack).to(haveResource('AWS::AutoScaling::AutoScalingGroup')); - expectCDK(wfstack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(wfstack).resourceCountIs('AWS::AutoScaling::AutoScalingGroup', 1); + Template.fromStack(wfstack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { InstanceType: 't2.large', - spotPrice: ABSENT, - })); - expectCDK(wfstack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + IamInstanceProfile: { + Ref: Match.stringLikeRegexp('^workerFleetInstanceProfile.*'), + }, + ImageId: 'ami-any', + SecurityGroups: [ + { + 'Fn::GetAtt': [ + Match.stringLikeRegexp('^workerFleetInstanceSecurityGroup.*'), + 'GroupId', + ], + }, + ], + spotPrice: Match.absent(), + }); + Template.fromStack(wfstack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', ToPort: parseInt(renderQueue.endpoint.portAsString(), 10), SourceSecurityGroupId: { @@ -130,15 +143,19 @@ test('default worker fleet is created correctly', () => { GroupId: { 'Fn::ImportValue': 'infraStack:ExportsOutputFnGetAttRQLBSecurityGroupAC643AEDGroupId8F9F7830', }, - })); - expectCDK(wfstack).to(haveResource('Custom::LogRetention', { + }); + Template.fromStack(wfstack).hasResourceProperties('Custom::LogRetention', { RetentionInDays: 3, LogGroupName: '/renderfarm/workerFleet', - })); - expect(fleet.node.metadataEntry[0].type).toMatch(ArtifactMetadataEntryType.WARN); - expect(fleet.node.metadataEntry[0].data).toMatch('being created without being provided any block devices so the Source AMI\'s devices will be used. Workers can have access to sensitive data so it is recommended to either explicitly encrypt the devices on the worker fleet or to ensure the source AMI\'s Drives are encrypted.'); - expect(fleet.node.metadataEntry[1].type).toMatch(ArtifactMetadataEntryType.WARN); - expect(fleet.node.metadataEntry[1].data).toContain('being created without a health monitor attached to it. This means that the fleet will not automatically scale-in to 0 if the workers are unhealthy'); + }); + Annotations.fromStack(wfstack).hasWarning( + `/${fleet.node.path}`, + Match.stringLikeRegexp('.*being created without being provided any block devices so the Source AMI\'s devices will be used. Workers can have access to sensitive data so it is recommended to either explicitly encrypt the devices on the worker fleet or to ensure the source AMI\'s Drives are encrypted.'), + ); + Annotations.fromStack(wfstack).hasWarning( + `/${fleet.node.path}`, + Match.stringLikeRegexp('.*being created without a health monitor attached to it. This means that the fleet will not automatically scale-in to 0 if the workers are unhealthy'), + ); }); test('security group is added to fleet after its creation', () => { @@ -156,7 +173,7 @@ test('security group is added to fleet after its creation', () => { })); // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { SecurityGroups: [ { 'Fn::GetAtt': [ @@ -166,7 +183,7 @@ test('security group is added to fleet after its creation', () => { }, 'sg-123456789', ], - })); + }); }); test('WorkerFleet uses given security group', () => { @@ -183,11 +200,11 @@ test('WorkerFleet uses given security group', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { SecurityGroups: [ 'sg-123456789', ], - })); + }); }); describe('allowing log listener port', () => { @@ -204,7 +221,7 @@ describe('allowing log listener port', () => { fleet.allowListenerPortFrom(Peer.ipv4('127.0.0.1/24').connections); // THEN - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { SecurityGroupEgress: [{ CidrIp: '0.0.0.0/0' }], SecurityGroupIngress: [ { @@ -215,7 +232,7 @@ describe('allowing log listener port', () => { ToPort: WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT'] + WorkerInstanceFleet['MAX_WORKERS_PER_HOST'], }, ], - })); + }); }); test('to CIDR', () => { @@ -231,7 +248,7 @@ describe('allowing log listener port', () => { fleet.allowListenerPortTo(Peer.ipv4('127.0.0.1/24').connections); // THEN - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { SecurityGroupEgress: [{ CidrIp: '0.0.0.0/0' }], SecurityGroupIngress: [ { @@ -242,7 +259,7 @@ describe('allowing log listener port', () => { ToPort: WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT'] + WorkerInstanceFleet['MAX_WORKERS_PER_HOST'], }, ], - })); + }); }); test('from SecurityGroup', () => { @@ -259,12 +276,12 @@ describe('allowing log listener port', () => { fleet.allowListenerPortFrom(securityGroup); // THEN - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { FromPort: WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT'], IpProtocol: 'tcp', SourceSecurityGroupId: 'sg-123456789', ToPort: WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT'] + WorkerInstanceFleet['MAX_WORKERS_PER_HOST'], - })); + }); }); test('to SecurityGroup', () => { @@ -281,12 +298,12 @@ describe('allowing log listener port', () => { fleet.allowListenerPortTo(securityGroup); // THEN - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { FromPort: WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT'], IpProtocol: 'tcp', SourceSecurityGroupId: 'sg-123456789', ToPort: WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT'] + WorkerInstanceFleet['MAX_WORKERS_PER_HOST'], - })); + }); }); test('from other stack', () => { @@ -307,12 +324,12 @@ describe('allowing log listener port', () => { fleet.allowListenerPortFrom(securityGroup); // THEN - expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { FromPort: WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT'], IpProtocol: 'tcp', SourceSecurityGroupId: 'sg-123456789', ToPort: WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT'] + WorkerInstanceFleet['MAX_WORKERS_PER_HOST'], - })); + }); }); test('to other stack', () => { @@ -333,12 +350,12 @@ describe('allowing log listener port', () => { fleet.allowListenerPortTo(securityGroup); // THEN - expectCDK(otherStack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(otherStack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { FromPort: WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT'], IpProtocol: 'tcp', SourceSecurityGroupId: 'sg-123456789', ToPort: WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT'] + WorkerInstanceFleet['MAX_WORKERS_PER_HOST'], - })); + }); }); }); @@ -347,14 +364,31 @@ test('default worker fleet is created correctly with linux image', () => { new WorkerInstanceFleet(stack, 'workerFleet', { vpc, workerMachineImage: new GenericLinuxImage({ - 'us-east-1': '123', + 'us-east-1': 'ami-any', }), renderQueue, }); // THEN - expectCDK(stack).to(haveResource('AWS::AutoScaling::AutoScalingGroup')); - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration')); + // 3 = repository + renderqueue + worker fleet + Template.fromStack(stack).resourceCountIs('AWS::AutoScaling::AutoScalingGroup', 3); + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { + InstanceType: 't2.large', + IamInstanceProfile: { + Ref: Match.stringLikeRegexp('^workerFleetInstanceProfile.*'), + }, + ImageId: 'ami-any', + SecurityGroups: [ + { + 'Fn::GetAtt': [ + Match.stringLikeRegexp('^workerFleetInstanceSecurityGroup.*'), + 'GroupId', + ], + }, + ], + spotPrice: Match.absent(), + }); + }); test('default worker fleet is created correctly with spot config', () => { @@ -369,10 +403,10 @@ test('default worker fleet is created correctly with spot config', () => { }); // THEN - expectCDK(wfstack).to(haveResource('AWS::AutoScaling::AutoScalingGroup')); - expectCDK(wfstack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(wfstack).resourceCountIs('AWS::AutoScaling::AutoScalingGroup', 1); + Template.fromStack(wfstack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { SpotPrice: '2.5', - })); + }); }); test('default worker fleet is not created with incorrect spot config', () => { @@ -413,9 +447,9 @@ test('default worker fleet is created correctly custom Instance type', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { InstanceType: 't2.medium', - })); + }); }); test.each([ @@ -437,19 +471,19 @@ test.each([ }, }); - expectCDK(stack).to(haveResource('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { RetentionInDays: 3, LogGroupName: testPrefix + id, - })); + }); }); -test('default worker fleet is created correctly custom subnet values', () => { +test('default linux worker fleet is created correctly custom subnet values', () => { vpc = new Vpc(stack, 'VPC1Az', { maxAzs: 1, }); // WHEN - const workers = new WorkerInstanceFleet(stack, 'workerFleet', { + new WorkerInstanceFleet(stack, 'workerFleet', { vpc, workerMachineImage: new GenericLinuxImage({ 'us-east-1': '123', @@ -465,480 +499,148 @@ test('default worker fleet is created correctly custom subnet values', () => { }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { VPCZoneIdentifier: [{ Ref: 'VPC1AzPublicSubnet1Subnet9649CC17', }], - })); - const userData = stack.resolve(workers.fleet.userData.render()); - expect(userData).toStrictEqual({ - 'Fn::Join': [ - '', - [ - '#!/bin/bash\nfunction exitTrap(){\nexitCode=$?\n/opt/aws/bin/cfn-signal --stack infraStack --resource workerFleetASG25520D69 --region us-east-1 -e $exitCode || echo \'Failed to send Cloudformation Signal\'\n}\ntrap exitTrap EXIT\nmkdir -p $(dirname \'/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - "\')\naws s3 cp 's3://", - { Ref: CWA_ASSET_LINUX.Bucket }, - '/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - "' '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - '\'\n' + - 'set -e\n' + - 'chmod +x \'/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - '\'\n\'/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CWA_ASSET_LINUX.Key }, - ], - }, - ], - }, - '\' -i us-east-1 ', - {Ref: 'workerFleetStringParameterDB3717DA'}, - '\nmkdir -p $(dirname \'/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - '\')\naws s3 cp \'s3://', - { Ref: RQ_CONNECTION_ASSET.Bucket }, - '/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - "' '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - '\'\n' + - 'if [ -f \"/etc/profile.d/deadlineclient.sh\" ]; then\n' + - ' source \"/etc/profile.d/deadlineclient.sh\"\n' + - 'fi\n' + - '"${DEADLINE_PATH}/deadlinecommand" -executeScriptNoGui "/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - '" --render-queue "http://', - { - 'Fn::GetAtt': [ - 'RQLB3B7B1CBC', - 'DNSName', - ], - }, - ':8080" \n' + - 'rm -f "/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: RQ_CONNECTION_ASSET.Key }, - ], - }, - ], - }, - '\"\n' + - "mkdir -p $(dirname '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - '\')\naws s3 cp \'s3://', - { Ref: CONFIG_WORKER_ASSET_WINDOWS.Bucket }, - '/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - '\' \'/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - "'\nmkdir -p $(dirname '/tmp/", - { - 'Fn::Select': [ - 0, + }); + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { + InstanceType: 't2.medium', + IamInstanceProfile: { + Ref: Match.stringLikeRegexp('workerFleetInstanceProfile.*'), + }, + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + [ + '#!/bin/bash\n' + + 'function exitTrap(){\nexitCode=$?\n/opt/aws/bin/cfn-signal --stack infraStack --resource workerFleetASG25520D69 --region us-east-1 -e $exitCode || echo \'Failed to send Cloudformation Signal\'\n}\n' + + 'trap exitTrap EXIT\n' + + `mkdir -p $(dirname '/tmp/${CWA_ASSET_LINUX.Key}.sh')\naws s3 cp 's3://`, { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_LINUX.Key }, - ], + 'Fn::Sub': CWA_ASSET_LINUX.Bucket.replace('${AWS::Region}', 'us-east-1'), }, - ], - }, - { - 'Fn::Select': [ - 1, + `/${CWA_ASSET_LINUX.Key}.sh' '/tmp/${CWA_ASSET_LINUX.Key}.sh'\n` + + `set -e\nchmod +x '/tmp/${CWA_ASSET_LINUX.Key}.sh'\n'/tmp/${CWA_ASSET_LINUX.Key}.sh' -i us-east-1 `, { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_LINUX.Key }, - ], + Ref: Match.stringLikeRegexp('^workerFleetStringParameter.*'), }, - ], - }, - "')\naws s3 cp 's3://", - { Ref: CONFIG_WORKER_ASSET_LINUX.Bucket }, - '/', - { - 'Fn::Select': [ - 0, + `\nmkdir -p $(dirname '/tmp/${RQ_CONNECTION_ASSET.Key}.py')\naws s3 cp 's3://`, { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_LINUX.Key }, - ], + 'Fn::Sub': RQ_CONNECTION_ASSET.Bucket.replace('${AWS::Region}', 'us-east-1'), }, - ], - }, - { - 'Fn::Select': [ - 1, + `/${RQ_CONNECTION_ASSET.Key}.py' '/tmp/${RQ_CONNECTION_ASSET.Key}.py'\n` + + 'if [ -f "/etc/profile.d/deadlineclient.sh" ]; then\n source "/etc/profile.d/deadlineclient.sh"\nfi\n' + + `"\${DEADLINE_PATH}/deadlinecommand" -executeScriptNoGui "/tmp/${RQ_CONNECTION_ASSET.Key}.py" --render-queue "http://`, { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_LINUX.Key }, + 'Fn::GetAtt': [ + 'RQLB3B7B1CBC', + 'DNSName', ], }, - ], - }, - "' '/tmp/", - { - 'Fn::Select': [ - 0, + `:8080" \nrm -f "/tmp/${RQ_CONNECTION_ASSET.Key}.py"` + + `\nmkdir -p $(dirname '/tmp/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py')\naws s3 cp 's3://`, { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_LINUX.Key }, - ], + 'Fn::Sub': CONFIG_WORKER_PORT_ASSET_LINUX.Bucket.replace('${AWS::Region}', 'us-east-1'), }, - ], - }, - { - 'Fn::Select': [ - 1, + `/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py' '/tmp/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py'\n` + + `mkdir -p $(dirname '/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh')\naws s3 cp 's3://`, { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_LINUX.Key }, - ], + 'Fn::Sub': CONFIG_WORKER_ASSET_LINUX.Bucket.replace('${AWS::Region}', 'us-east-1'), }, + `/${CONFIG_WORKER_ASSET_LINUX.Key}.sh' '/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh'\n` + + 'set -e\n' + + `chmod +x '/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh'\n` + + `'/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh' '' '' '' '${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}' ${WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT']} /tmp/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py`, ], - }, - "'\nset -e\nchmod +x '/tmp/", - { - 'Fn::Select': [ - 0, + ], + }, + }, + }); +}); + +test('default windows worker fleet is created correctly custom subnet values', () => { + vpc = new Vpc(stack, 'VPC1Az', { + maxAzs: 1, + }); + + // WHEN + new WorkerInstanceFleet(stack, 'workerFleet', { + vpc, + workerMachineImage: new GenericWindowsImage({ + 'us-east-1': '123', + }), + renderQueue, + instanceType: InstanceType.of(InstanceClass.T2, InstanceSize.MEDIUM), + vpcSubnets: { + subnetType: SubnetType.PUBLIC, + }, + healthCheckConfig: { + port: 6161, + }, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { + VPCZoneIdentifier: [{ + Ref: 'VPC1AzPublicSubnet1Subnet9649CC17', + }], + }); + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { + InstanceType: 't2.medium', + IamInstanceProfile: { + Ref: Match.stringLikeRegexp('workerFleetInstanceProfile.*'), + }, + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + [ + 'trap {\n$success=($PSItem.Exception.Message -eq "Success")\n' + + 'cfn-signal --stack infraStack --resource workerFleetASG25520D69 --region us-east-1 --success ($success.ToString().ToLower())\nbreak\n}\n' + + `mkdir (Split-Path -Path 'C:/temp/${CWA_ASSET_WINDOWS.Key}.ps1' ) -ea 0\nRead-S3Object -BucketName '`, { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_LINUX.Key }, - ], + 'Fn::Sub': CWA_ASSET_WINDOWS.Bucket.replace('${AWS::Region}', 'us-east-1'), }, - ], - }, - { - 'Fn::Select': [ - 1, + `' -key '${CWA_ASSET_WINDOWS.Key}.ps1' -file 'C:/temp/${CWA_ASSET_WINDOWS.Key}.ps1' -ErrorAction Stop\n&'C:/temp/${CWA_ASSET_WINDOWS.Key}.ps1' -i us-east-1 `, { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_LINUX.Key }, - ], + Ref: Match.stringLikeRegexp('^workerFleetStringParameter.*'), }, - ], - }, - "'\n'/tmp/", - { - 'Fn::Select': [ - 0, + `\nif (!$?) { Write-Error 'Failed to execute the file \"C:/temp/${CWA_ASSET_WINDOWS.Key}.ps1\"' -ErrorAction Stop }\n` + + `mkdir (Split-Path -Path 'C:/temp/${RQ_CONNECTION_ASSET.Key}.py' ) -ea 0\nRead-S3Object -BucketName '`, { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_LINUX.Key }, - ], + 'Fn::Sub': RQ_CONNECTION_ASSET.Bucket.replace('${AWS::Region}', 'us-east-1'), }, - ], - }, - { - 'Fn::Select': [ - 1, + `' -key '${RQ_CONNECTION_ASSET.Key}.py' -file 'C:/temp/${RQ_CONNECTION_ASSET.Key}.py' -ErrorAction Stop\n` + + '$ErrorActionPreference = "Stop"\n' + + '$DEADLINE_PATH = (get-item env:"DEADLINE_PATH").Value\n' + + `& "$DEADLINE_PATH/deadlinecommand.exe" -executeScriptNoGui "C:/temp/${RQ_CONNECTION_ASSET.Key}.py" --render-queue "http://`, { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_LINUX.Key }, + 'Fn::GetAtt': [ + 'RQLB3B7B1CBC', + 'DNSName', ], }, - ], - }, - `' '' '' '' '${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION}' ${WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT']} /tmp/`, - { - 'Fn::Select': [ - 0, + ':8080" 2>&1\n' + + `Remove-Item -Path "C:/temp/${RQ_CONNECTION_ASSET.Key}.py"\n` + + `mkdir (Split-Path -Path 'C:/temp/${CONFIG_WORKER_ASSET_WINDOWS.Key}.py' ) -ea 0\nRead-S3Object -BucketName '`, { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_WINDOWS.Key }, - ], + 'Fn::Sub': CONFIG_WORKER_ASSET_WINDOWS.Bucket.replace('${AWS::Region}', 'us-east-1'), }, - ], - }, - { - 'Fn::Select': [ - 1, + `' -key '${CONFIG_WORKER_ASSET_WINDOWS.Key}.py' -file 'C:/temp/${CONFIG_WORKER_ASSET_WINDOWS.Key}.py' -ErrorAction Stop\n` + + `mkdir (Split-Path -Path 'C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' ) -ea 0\nRead-S3Object -BucketName '`, { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_WINDOWS.Key }, - ], + 'Fn::Sub': CONFIG_WORKER_PORT_ASSET_WINDOWS.Bucket.replace('${AWS::Region}', 'us-east-1'), }, + `' -key '${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' -file 'C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' -ErrorAction Stop\n` + + `&'C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1' '' '' '' '${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}' ${WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT']} C:/temp/${CONFIG_WORKER_ASSET_WINDOWS.Key}.py\n` + + `if (!$?) { Write-Error 'Failed to execute the file \"C:/temp/${CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}.ps1\"' -ErrorAction Stop }\n` + + 'throw \"Success\"', ], - }, - ], - ], + ], + }, + }, }); }); @@ -948,7 +650,7 @@ test('default worker fleet is created correctly with groups, pools and region', }); // WHEN - const workers = new WorkerInstanceFleet(stack, 'workerFleet', { + new WorkerInstanceFleet(stack, 'workerFleet', { vpc, workerMachineImage: new GenericLinuxImage({ 'us-east-1': '123', @@ -958,486 +660,65 @@ test('default worker fleet is created correctly with groups, pools and region', vpcSubnets: { subnetType: SubnetType.PUBLIC, }, - groups: ['A', 'B'], - pools: ['C', 'D'], + groups: ['A', 'B'], // We want to make sure that these are converted to lowercase + pools: ['C', 'D'], // We want to make sure that these are converted to lowercase region: 'E', }); // THEN - const userData = stack.resolve(workers.fleet.userData.render()); - expect(userData).toStrictEqual({ - 'Fn::Join': ['', [ - '#!/bin/bash\nfunction exitTrap(){\nexitCode=$?\n/opt/aws/bin/cfn-signal --stack infraStack --resource workerFleetASG25520D69 --region us-east-1 -e $exitCode || echo \'Failed to send Cloudformation Signal\'\n}\ntrap exitTrap EXIT\nmkdir -p $(dirname \'/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CWA_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CWA_ASSET_LINUX.Key}, - ], - }, - ], - }, - '\')\naws s3 cp \'s3://', - {Ref: CWA_ASSET_LINUX.Bucket}, - '/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CWA_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CWA_ASSET_LINUX.Key}, - ], - }, - ], - }, - "' '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CWA_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CWA_ASSET_LINUX.Key}, - ], - }, - ], - }, - "'\nset -e\nchmod +x '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CWA_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CWA_ASSET_LINUX.Key}, - ], - }, - ], - }, - "'\n'/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CWA_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CWA_ASSET_LINUX.Key}, - ], - }, - ], - }, - "' -i us-east-1 ", - {Ref: 'workerFleetStringParameterDB3717DA'}, - '\nmkdir -p $(dirname \'/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: RQ_CONNECTION_ASSET.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: RQ_CONNECTION_ASSET.Key}, - ], - }, - ], - }, - '\')\naws s3 cp \'s3://', - {Ref: RQ_CONNECTION_ASSET.Bucket}, - '/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: RQ_CONNECTION_ASSET.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: RQ_CONNECTION_ASSET.Key}, - ], - }, - ], - }, - "' '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: RQ_CONNECTION_ASSET.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: RQ_CONNECTION_ASSET.Key}, - ], - }, - ], - }, - '\'\n' + - 'if [ -f \"/etc/profile.d/deadlineclient.sh\" ]; then\n' + - ' source \"/etc/profile.d/deadlineclient.sh\"\n' + - 'fi\n' + - '"${DEADLINE_PATH}/deadlinecommand" -executeScriptNoGui "/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: RQ_CONNECTION_ASSET.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: RQ_CONNECTION_ASSET.Key}, - ], - }, - ], - }, - '" --render-queue "http://', - { - 'Fn::GetAtt': [ - 'RQLB3B7B1CBC', - 'DNSName', - ], - }, - ':8080" \n' + - 'rm -f "/tmp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: RQ_CONNECTION_ASSET.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: RQ_CONNECTION_ASSET.Key}, - ], - }, - ], - }, - '\"\n' + - "mkdir -p $(dirname '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { - Ref: CONFIG_WORKER_ASSET_WINDOWS.Key, - }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { - Ref: CONFIG_WORKER_ASSET_WINDOWS.Key, - }, - ], - }, - ], - }, - "')\naws s3 cp 's3://", - { - Ref: CONFIG_WORKER_ASSET_WINDOWS.Bucket, - }, - '/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - "' '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { Ref: CONFIG_WORKER_ASSET_WINDOWS.Key }, - ], - }, - ], - }, - "'\nmkdir -p $(dirname '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - "')\naws s3 cp 's3://", - {Ref: CONFIG_WORKER_ASSET_LINUX.Bucket}, - '/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - "' '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - "'\nset -e\nchmod +x '/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - "'\n'/tmp/", - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, - ], - }, - ], - }, - `' 'a,b' 'c,d' 'E' '${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION}' ${WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT']} /tmp/`, - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { - Ref: CONFIG_WORKER_ASSET_WINDOWS.Key, - }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - { - Ref: CONFIG_WORKER_ASSET_WINDOWS.Key, - }, - ], - }, + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { + InstanceType: 't2.medium', + IamInstanceProfile: { + Ref: Match.stringLikeRegexp('workerFleetInstanceProfile.*'), + }, + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + [ + '#!/bin/bash\n' + + 'function exitTrap(){\nexitCode=$?\n/opt/aws/bin/cfn-signal --stack infraStack --resource workerFleetASG25520D69 --region us-east-1 -e $exitCode || echo \'Failed to send Cloudformation Signal\'\n}\n' + + 'trap exitTrap EXIT\n' + + `mkdir -p $(dirname '/tmp/${CWA_ASSET_LINUX.Key}.sh')\naws s3 cp 's3://`, + { + 'Fn::Sub': CWA_ASSET_LINUX.Bucket.replace('${AWS::Region}', 'us-east-1'), + }, + `/${CWA_ASSET_LINUX.Key}.sh' '/tmp/${CWA_ASSET_LINUX.Key}.sh'\n` + + `set -e\nchmod +x '/tmp/${CWA_ASSET_LINUX.Key}.sh'\n'/tmp/${CWA_ASSET_LINUX.Key}.sh' -i us-east-1 `, + { + Ref: Match.stringLikeRegexp('^workerFleetStringParameter.*'), + }, + `\nmkdir -p $(dirname '/tmp/${RQ_CONNECTION_ASSET.Key}.py')\naws s3 cp 's3://`, + { + 'Fn::Sub': RQ_CONNECTION_ASSET.Bucket.replace('${AWS::Region}', 'us-east-1'), + }, + `/${RQ_CONNECTION_ASSET.Key}.py' '/tmp/${RQ_CONNECTION_ASSET.Key}.py'\n` + + 'if [ -f "/etc/profile.d/deadlineclient.sh" ]; then\n source "/etc/profile.d/deadlineclient.sh"\nfi\n' + + `"\${DEADLINE_PATH}/deadlinecommand" -executeScriptNoGui "/tmp/${RQ_CONNECTION_ASSET.Key}.py" --render-queue "http://`, + { + 'Fn::GetAtt': [ + 'RQLB3B7B1CBC', + 'DNSName', + ], + }, + `:8080" \nrm -f "/tmp/${RQ_CONNECTION_ASSET.Key}.py"` + + `\nmkdir -p $(dirname '/tmp/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py')\naws s3 cp 's3://`, + { + 'Fn::Sub': CONFIG_WORKER_PORT_ASSET_LINUX.Bucket.replace('${AWS::Region}', 'us-east-1'), + }, + `/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py' '/tmp/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py'\n` + + `mkdir -p $(dirname '/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh')\naws s3 cp 's3://`, + { + 'Fn::Sub': CONFIG_WORKER_ASSET_LINUX.Bucket.replace('${AWS::Region}', 'us-east-1'), + }, + `/${CONFIG_WORKER_ASSET_LINUX.Key}.sh' '/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh'\n` + + 'set -e\n' + + `chmod +x '/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh'\n` + + `'/tmp/${CONFIG_WORKER_ASSET_LINUX.Key}.sh' 'a,b' 'c,d' 'E' '${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}' ${WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT']} /tmp/${CONFIG_WORKER_PORT_ASSET_LINUX.Key}.py`, + ], ], }, - ]], + }, }); }); @@ -1585,8 +866,10 @@ describe('Block Device Tests', () => { renderQueue, healthMonitor, }); - expect(fleet.node.metadataEntry[0].type).toMatch(ArtifactMetadataEntryType.WARN); - expect(fleet.node.metadataEntry[0].data).toMatch('being created without being provided any block devices so the Source AMI\'s devices will be used. Workers can have access to sensitive data so it is recommended to either explicitly encrypt the devices on the worker fleet or to ensure the source AMI\'s Drives are encrypted.'); + Annotations.fromStack(wfstack).hasWarning( + `/${fleet.node.path}`, + Match.stringLikeRegexp('.*being created without being provided any block devices so the Source AMI\'s devices will be used. Workers can have access to sensitive data so it is recommended to either explicitly encrypt the devices on the worker fleet or to ensure the source AMI\'s Drives are encrypted.'), + ); }); test('No Warnings if Encrypted BlockDevices Provided', () => { @@ -1607,7 +890,7 @@ describe('Block Device Tests', () => { }); //THEN - expectCDK(wfstack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(wfstack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { BlockDeviceMappings: [ { Ebs: { @@ -1616,9 +899,11 @@ describe('Block Device Tests', () => { }, }, ], - })); + }); - expect(fleet.node.metadataEntry).toHaveLength(0); + Annotations.fromStack(wfstack).hasNoInfo(`/${fleet.node.path}`, Match.anyValue()); + Annotations.fromStack(wfstack).hasNoWarning(`/${fleet.node.path}`, Match.anyValue()); + Annotations.fromStack(wfstack).hasNoError(`/${fleet.node.path}`, Match.anyValue()); }); test('Warnings if non-Encrypted BlockDevices Provided', () => { @@ -1640,7 +925,7 @@ describe('Block Device Tests', () => { }); //THEN - expectCDK(wfstack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(wfstack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { BlockDeviceMappings: [ { Ebs: { @@ -1649,10 +934,12 @@ describe('Block Device Tests', () => { }, }, ], - })); + }); - expect(fleet.node.metadataEntry[0].type).toMatch(ArtifactMetadataEntryType.WARN); - expect(fleet.node.metadataEntry[0].data).toMatch(`The BlockDevice \"${DEVICE_NAME}\" on the worker-fleet workerFleet is not encrypted. Workers can have access to sensitive data so it is recommended to encrypt the devices on the worker fleet.`); + Annotations.fromStack(wfstack).hasWarning( + `/${fleet.node.path}`, + Match.stringLikeRegexp(`The BlockDevice \"${DEVICE_NAME}\" on the worker-fleet workerFleet is not encrypted. Workers can have access to sensitive data so it is recommended to encrypt the devices on the worker fleet.`), + ); }); test('Warnings for BlockDevices without encryption specified', () => { @@ -1674,7 +961,7 @@ describe('Block Device Tests', () => { }); //THEN - expectCDK(wfstack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(wfstack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { BlockDeviceMappings: [ { Ebs: { @@ -1682,10 +969,12 @@ describe('Block Device Tests', () => { }, }, ], - })); + }); - expect(fleet.node.metadataEntry[0].type).toMatch(ArtifactMetadataEntryType.WARN); - expect(fleet.node.metadataEntry[0].data).toMatch(`The BlockDevice \"${DEVICE_NAME}\" on the worker-fleet workerFleet is not encrypted. Workers can have access to sensitive data so it is recommended to encrypt the devices on the worker fleet.`); + Annotations.fromStack(wfstack).hasWarning( + `/${fleet.node.path}`, + Match.stringLikeRegexp(`The BlockDevice \"${DEVICE_NAME}\" on the worker-fleet workerFleet is not encrypted. Workers can have access to sensitive data so it is recommended to encrypt the devices on the worker fleet.`), + ); }); test('No warnings for Ephemeral blockDeviceVolumes', () => { @@ -1706,16 +995,18 @@ describe('Block Device Tests', () => { }); //THEN - expectCDK(wfstack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(wfstack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { BlockDeviceMappings: [ { DeviceName: DEVICE_NAME, VirtualName: 'ephemeral0', }, ], - })); + }); - expect(fleet.node.metadataEntry).toHaveLength(0); + Annotations.fromStack(wfstack).hasNoInfo(`/${fleet.node.path}`, Match.anyValue()); + Annotations.fromStack(wfstack).hasNoWarning(`/${fleet.node.path}`, Match.anyValue()); + Annotations.fromStack(wfstack).hasNoError(`/${fleet.node.path}`, Match.anyValue()); }); test('No warnings for Suppressed blockDeviceVolumes', () => { @@ -1736,15 +1027,17 @@ describe('Block Device Tests', () => { }); //THEN - expectCDK(wfstack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(wfstack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { BlockDeviceMappings: [ { DeviceName: DEVICE_NAME, }, ], - })); + }); - expect(fleet.node.metadataEntry).toHaveLength(0); + Annotations.fromStack(wfstack).hasNoInfo(`/${fleet.node.path}`, Match.anyValue()); + Annotations.fromStack(wfstack).hasNoWarning(`/${fleet.node.path}`, Match.anyValue()); + Annotations.fromStack(wfstack).hasNoError(`/${fleet.node.path}`, Match.anyValue()); }); }); @@ -1772,18 +1065,18 @@ describe('HealthMonitor Tests', () => { // THEN // Ensure the configuration script is executed with the expected arguments. - expect(userData).toMatch(new RegExp(escapeTokenRegex('&\'C:/temp/${Token[TOKEN.\\d+]}${Token[TOKEN.\\d+]}\' \'63415\' \'10.1.9.2\''))); + expect(userData).toContain(`&'C:/temp/${CONFIG_WORKER_HEALTHCHECK_WINDOWS.Key}.ps1' '63415' '${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}'`); // Ensure that the health monitor target group has been set up. // Note: It's sufficient to just check for any resource created by the HealthMonitor registration. // The HealthMonitor tests cover ensuring that all of the resources are set up. - expectCDK(wfstack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::TargetGroup', { + Template.fromStack(wfstack).hasResourceProperties('AWS::ElasticLoadBalancingV2::TargetGroup', { HealthCheckIntervalSeconds: 300, HealthCheckPort: '63415', HealthCheckProtocol: 'HTTP', Port: 8081, Protocol: 'HTTP', TargetType: 'instance', - })); + }); }); test('Monitor is configured for Linux', () => { @@ -1800,18 +1093,18 @@ describe('HealthMonitor Tests', () => { // THEN // Ensure the configuration script is executed with the expected arguments. - expect(userData).toMatch(new RegExp(escapeTokenRegex('\'/tmp/${Token[TOKEN.\\d+]}${Token[TOKEN.\\d+]}\' \'63415\' \'10.1.9.2\''))); + expect(userData).toContain(`'/tmp/${CONFIG_WORKER_HEALTHCHECK_LINUX.Key}.sh' '63415' '${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}'`); // Ensure that the health monitor target group has been set up. // Note: It's sufficient to just check for any resource created by the HealthMonitor registration. // The HealthMonitor tests cover ensuring that all of the resources are set up. - expectCDK(wfstack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::TargetGroup', { + Template.fromStack(wfstack).hasResourceProperties('AWS::ElasticLoadBalancingV2::TargetGroup', { HealthCheckIntervalSeconds: 300, HealthCheckPort: '63415', HealthCheckProtocol: 'HTTP', Port: 8081, Protocol: 'HTTP', TargetType: 'instance', - })); + }); }); test('UserData is added', () => { @@ -1906,15 +1199,22 @@ test('worker fleet signals when non-zero minCapacity', () => { // THEN expect(userData).toContain('cfn-signal'); - expectCDK(wfstack).to(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(wfstack).hasResource('AWS::AutoScaling::AutoScalingGroup', { CreationPolicy: { ResourceSignal: { Count: 1, }, }, - }, ResourcePart.CompleteDefinition)); - // [0] = warning about block devices. [1] = warning about no health monitor - expect(fleet.node.metadataEntry).toHaveLength(2); + }); + Annotations.fromStack(wfstack).hasWarning( + `/${fleet.node.path}`, + Match.stringLikeRegexp('.*being created without being provided any block devices so the Source AMI\'s devices will be used. Workers can have access to sensitive data so it is recommended to either explicitly encrypt the devices on the worker fleet or to ensure the source AMI\'s Drives are encrypted.'), + ); + Annotations.fromStack(wfstack).hasWarning( + `/${fleet.node.path}`, + Match.stringLikeRegexp('.*being created without a health monitor attached to it. This means that the fleet will not automatically scale-in to 0 if the workers are unhealthy'), + ); + }); test('worker fleet does not signal when zero minCapacity', () => { @@ -1935,14 +1235,21 @@ test('worker fleet does not signal when zero minCapacity', () => { // There should be no cfn-signal call in the UserData. expect(userData).not.toContain('cfn-signal'); // Make sure we don't have a CreationPolicy - expectCDK(wfstack).notTo(haveResourceLike('AWS::AutoScaling::AutoScalingGroup', { - CreationPolicy: objectLike({}), - }, ResourcePart.CompleteDefinition)); - // There should be a warning in the construct's metadata about deploying with no capacity. - expect(fleet.node.metadataEntry).toHaveLength(3); - // [0] = warning about block devices. [2] = warning about no health monitor - expect(fleet.node.metadataEntry[1].type).toMatch(ArtifactMetadataEntryType.WARN); - expect(fleet.node.metadataEntry[1].data).toMatch(/Deploying with 0 minimum capacity./); + resourcePropertiesCountIs(wfstack, 'AWS::AutoScaling::AutoScalingGroup', { + CreationPolicy: Match.anyValue(), + }, 0); + Annotations.fromStack(wfstack).hasWarning( + `/${fleet.node.path}`, + Match.stringLikeRegexp('.*Deploying with 0 minimum capacity\..*'), + ); + Annotations.fromStack(wfstack).hasWarning( + `/${fleet.node.path}`, + Match.stringLikeRegexp('.*being created without being provided any block devices so the Source AMI\'s devices will be used. Workers can have access to sensitive data so it is recommended to either explicitly encrypt the devices on the worker fleet or to ensure the source AMI\'s Drives are encrypted.'), + ); + Annotations.fromStack(wfstack).hasWarning( + `/${fleet.node.path}`, + Match.stringLikeRegexp('.*being created without a health monitor attached to it. This means that the fleet will not automatically scale-in to 0 if the workers are unhealthy'), + ); }); describe('secrets management enabled', () => { @@ -1977,10 +1284,10 @@ describe('secrets management enabled', () => { const workerInstanceFleet = new WorkerInstanceFleet(wfstack, 'WorkerInstanceFleet', props); // THEN - expect(workerInstanceFleet.node.metadataEntry).toContainEqual(expect.objectContaining({ - type: 'aws:cdk:warning', - data: 'Deadline Secrets Management is enabled on the Repository and VPC subnets have not been supplied. Using dedicated subnets is recommended. See https://github.com/aws/aws-rfdk/blobs/release/packages/aws-rfdk/lib/deadline/README.md#using-dedicated-subnets-for-deadline-components', - })); + Annotations.fromStack(wfstack).hasWarning( + `/${workerInstanceFleet.node.path}`, + 'Deadline Secrets Management is enabled on the Repository and VPC subnets have not been supplied. Using dedicated subnets is recommended. See https://github.com/aws/aws-rfdk/blobs/release/packages/aws-rfdk/lib/deadline/README.md#using-dedicated-subnets-for-deadline-components', + ); }); test('vpc subnets specified => does not emit dedicated subnets warning', () => { @@ -1993,9 +1300,9 @@ describe('secrets management enabled', () => { }); // THEN - expect(workerInstanceFleet.node.metadataEntry).not.toContainEqual(expect.objectContaining({ - type: 'aws:cdk:warning', - data: expect.stringMatching(/dedicated subnet/i), - })); + Annotations.fromStack(wfstack).hasNoWarning( + `/${workerInstanceFleet.node.path}`, + Match.stringLikeRegexp('.*dedicated subnet.*'), + ); }); }); diff --git a/packages/aws-rfdk/lib/lambdas/nodejs/configure-spot-event-plugin/test/handler.test.ts b/packages/aws-rfdk/lib/lambdas/nodejs/configure-spot-event-plugin/test/handler.test.ts index 95654a8f2..08228f8bb 100644 --- a/packages/aws-rfdk/lib/lambdas/nodejs/configure-spot-event-plugin/test/handler.test.ts +++ b/packages/aws-rfdk/lib/lambdas/nodejs/configure-spot-event-plugin/test/handler.test.ts @@ -3,14 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { - LaunchTemplate, -} from '@aws-cdk/aws-ec2'; import { App, Expiration, Stack, -} from '@aws-cdk/core'; +} from 'aws-cdk-lib'; +import { + LaunchTemplate, +} from 'aws-cdk-lib/aws-ec2'; import * as AWS from 'aws-sdk'; import { SpotEventPluginDisplayInstanceStatus, diff --git a/packages/aws-rfdk/package.json b/packages/aws-rfdk/package.json index 581c115a6..6f158f959 100644 --- a/packages/aws-rfdk/package.json +++ b/packages/aws-rfdk/package.json @@ -41,6 +41,11 @@ "jsii/dotnet" ] }, + "awslint": { + "exclude": [ + "duration-prop-type:aws-rfdk.StaticPrivateIpServerProps.resourceSignalTimeout" + ] + }, "scripts": { "awslint": "cdk-awslint", "build": "cdk-build", @@ -64,224 +69,25 @@ "deadline" ], "devDependencies": { - "@aws-cdk/assert": "1.160.0", - "@aws-cdk/assets": "1.160.0", - "@aws-cdk/aws-acmpca": "1.160.0", - "@aws-cdk/aws-apigateway": "1.160.0", - "@aws-cdk/aws-apigatewayv2": "1.160.0", - "@aws-cdk/aws-apigatewayv2-integrations": "1.160.0", - "@aws-cdk/aws-applicationautoscaling": "1.160.0", - "@aws-cdk/aws-autoscaling": "1.160.0", - "@aws-cdk/aws-autoscaling-common": "1.160.0", - "@aws-cdk/aws-autoscaling-hooktargets": "1.160.0", - "@aws-cdk/aws-batch": "1.160.0", - "@aws-cdk/aws-certificatemanager": "1.160.0", - "@aws-cdk/aws-cloudformation": "1.160.0", - "@aws-cdk/aws-cloudfront": "1.160.0", - "@aws-cdk/aws-cloudwatch": "1.160.0", - "@aws-cdk/aws-cloudwatch-actions": "1.160.0", - "@aws-cdk/aws-codebuild": "1.160.0", - "@aws-cdk/aws-codecommit": "1.160.0", - "@aws-cdk/aws-codeguruprofiler": "1.160.0", - "@aws-cdk/aws-codepipeline": "1.160.0", - "@aws-cdk/aws-codestarnotifications": "1.160.0", - "@aws-cdk/aws-cognito": "1.160.0", - "@aws-cdk/aws-databrew": "1.160.0", - "@aws-cdk/aws-docdb": "1.160.0", - "@aws-cdk/aws-dynamodb": "1.160.0", - "@aws-cdk/aws-ec2": "1.160.0", - "@aws-cdk/aws-ecr": "1.160.0", - "@aws-cdk/aws-ecr-assets": "1.160.0", - "@aws-cdk/aws-ecs": "1.160.0", - "@aws-cdk/aws-ecs-patterns": "1.160.0", - "@aws-cdk/aws-efs": "1.160.0", - "@aws-cdk/aws-eks": "1.160.0", - "@aws-cdk/aws-elasticloadbalancing": "1.160.0", - "@aws-cdk/aws-elasticloadbalancingv2": "1.160.0", - "@aws-cdk/aws-events": "1.160.0", - "@aws-cdk/aws-events-targets": "1.160.0", - "@aws-cdk/aws-fsx": "1.160.0", - "@aws-cdk/aws-globalaccelerator": "1.160.0", - "@aws-cdk/aws-glue": "1.160.0", - "@aws-cdk/aws-iam": "1.160.0", - "@aws-cdk/aws-kinesis": "1.160.0", - "@aws-cdk/aws-kinesisfirehose": "1.160.0", - "@aws-cdk/aws-kms": "1.160.0", - "@aws-cdk/aws-lambda": "1.160.0", - "@aws-cdk/aws-lambda-nodejs": "1.160.0", - "@aws-cdk/aws-logs": "1.160.0", - "@aws-cdk/aws-route53": "1.160.0", - "@aws-cdk/aws-route53-targets": "1.160.0", - "@aws-cdk/aws-s3": "1.160.0", - "@aws-cdk/aws-s3-assets": "1.160.0", - "@aws-cdk/aws-sam": "1.160.0", - "@aws-cdk/aws-secretsmanager": "1.160.0", - "@aws-cdk/aws-servicediscovery": "1.160.0", - "@aws-cdk/aws-signer": "1.160.0", - "@aws-cdk/aws-sns": "1.160.0", - "@aws-cdk/aws-sns-subscriptions": "1.160.0", - "@aws-cdk/aws-sqs": "1.160.0", - "@aws-cdk/aws-ssm": "1.160.0", - "@aws-cdk/aws-stepfunctions": "1.160.0", - "@aws-cdk/aws-stepfunctions-tasks": "1.160.0", - "@aws-cdk/cloud-assembly-schema": "1.160.0", - "@aws-cdk/core": "1.160.0", - "@aws-cdk/custom-resources": "1.160.0", - "@aws-cdk/cx-api": "1.160.0", - "@aws-cdk/lambda-layer-awscli": "1.160.0", - "@aws-cdk/lambda-layer-kubectl": "1.160.0", - "@aws-cdk/lambda-layer-node-proxy-agent": "1.160.0", - "@aws-cdk/region-info": "1.160.0", "@types/aws-lambda": "^8.10.100", "@types/jest": "^27.5.2", "@types/sinon": "^10.0.11", "aws-sdk": "^2.1155.0", "aws-sdk-mock": "5.5.0", "cdk-build-tools": "0.42.0", - "constructs": "^3.3.69", + "aws-cdk-lib": "2.33.0", + "constructs": "^10.0.0", "dynalite": "^3.2.2", "pkglint": "0.42.0", "sinon": "^14.0.0" }, "dependencies": { - "@aws-cdk/assets": "1.160.0", - "@aws-cdk/aws-acmpca": "1.160.0", - "@aws-cdk/aws-apigateway": "1.160.0", - "@aws-cdk/aws-apigatewayv2": "1.160.0", - "@aws-cdk/aws-apigatewayv2-integrations": "1.160.0", - "@aws-cdk/aws-applicationautoscaling": "1.160.0", - "@aws-cdk/aws-autoscaling": "1.160.0", - "@aws-cdk/aws-autoscaling-common": "1.160.0", - "@aws-cdk/aws-autoscaling-hooktargets": "1.160.0", - "@aws-cdk/aws-batch": "1.160.0", - "@aws-cdk/aws-certificatemanager": "1.160.0", - "@aws-cdk/aws-cloudformation": "1.160.0", - "@aws-cdk/aws-cloudfront": "1.160.0", - "@aws-cdk/aws-cloudwatch": "1.160.0", - "@aws-cdk/aws-cloudwatch-actions": "1.160.0", - "@aws-cdk/aws-codebuild": "1.160.0", - "@aws-cdk/aws-codecommit": "1.160.0", - "@aws-cdk/aws-codeguruprofiler": "1.160.0", - "@aws-cdk/aws-codepipeline": "1.160.0", - "@aws-cdk/aws-codestarnotifications": "1.160.0", - "@aws-cdk/aws-cognito": "1.160.0", - "@aws-cdk/aws-databrew": "1.160.0", - "@aws-cdk/aws-docdb": "1.160.0", - "@aws-cdk/aws-dynamodb": "1.160.0", - "@aws-cdk/aws-ec2": "1.160.0", - "@aws-cdk/aws-ecr": "1.160.0", - "@aws-cdk/aws-ecr-assets": "1.160.0", - "@aws-cdk/aws-ecs": "1.160.0", - "@aws-cdk/aws-ecs-patterns": "1.160.0", - "@aws-cdk/aws-efs": "1.160.0", - "@aws-cdk/aws-eks": "1.160.0", - "@aws-cdk/aws-elasticloadbalancing": "1.160.0", - "@aws-cdk/aws-elasticloadbalancingv2": "1.160.0", - "@aws-cdk/aws-events": "1.160.0", - "@aws-cdk/aws-events-targets": "1.160.0", - "@aws-cdk/aws-fsx": "1.160.0", - "@aws-cdk/aws-globalaccelerator": "1.160.0", - "@aws-cdk/aws-glue": "1.160.0", - "@aws-cdk/aws-iam": "1.160.0", - "@aws-cdk/aws-kinesis": "1.160.0", - "@aws-cdk/aws-kinesisfirehose": "1.160.0", - "@aws-cdk/aws-kms": "1.160.0", - "@aws-cdk/aws-lambda": "1.160.0", - "@aws-cdk/aws-lambda-nodejs": "1.160.0", - "@aws-cdk/aws-logs": "1.160.0", - "@aws-cdk/aws-route53": "1.160.0", - "@aws-cdk/aws-route53-targets": "1.160.0", - "@aws-cdk/aws-s3": "1.160.0", - "@aws-cdk/aws-s3-assets": "1.160.0", - "@aws-cdk/aws-sam": "1.160.0", - "@aws-cdk/aws-secretsmanager": "1.160.0", - "@aws-cdk/aws-servicediscovery": "1.160.0", - "@aws-cdk/aws-signer": "1.160.0", - "@aws-cdk/aws-sns": "1.160.0", - "@aws-cdk/aws-sns-subscriptions": "1.160.0", - "@aws-cdk/aws-sqs": "1.160.0", - "@aws-cdk/aws-ssm": "1.160.0", - "@aws-cdk/aws-stepfunctions": "1.160.0", - "@aws-cdk/aws-stepfunctions-tasks": "1.160.0", - "@aws-cdk/cloud-assembly-schema": "1.160.0", - "@aws-cdk/core": "1.160.0", - "@aws-cdk/custom-resources": "1.160.0", - "@aws-cdk/cx-api": "1.160.0", - "@aws-cdk/lambda-layer-awscli": "1.160.0", - "@aws-cdk/lambda-layer-kubectl": "1.160.0", - "@aws-cdk/lambda-layer-node-proxy-agent": "1.160.0", - "@aws-cdk/region-info": "1.160.0", - "constructs": "^3.3.69" + "aws-cdk-lib": "2.33.0", + "constructs": "^10.0.0" }, "peerDependencies": { - "@aws-cdk/assets": "1.160.0", - "@aws-cdk/aws-acmpca": "1.160.0", - "@aws-cdk/aws-apigateway": "1.160.0", - "@aws-cdk/aws-apigatewayv2": "1.160.0", - "@aws-cdk/aws-apigatewayv2-integrations": "1.160.0", - "@aws-cdk/aws-applicationautoscaling": "1.160.0", - "@aws-cdk/aws-autoscaling": "1.160.0", - "@aws-cdk/aws-autoscaling-common": "1.160.0", - "@aws-cdk/aws-autoscaling-hooktargets": "1.160.0", - "@aws-cdk/aws-batch": "1.160.0", - "@aws-cdk/aws-certificatemanager": "1.160.0", - "@aws-cdk/aws-cloudformation": "1.160.0", - "@aws-cdk/aws-cloudfront": "1.160.0", - "@aws-cdk/aws-cloudwatch": "1.160.0", - "@aws-cdk/aws-cloudwatch-actions": "1.160.0", - "@aws-cdk/aws-codebuild": "1.160.0", - "@aws-cdk/aws-codecommit": "1.160.0", - "@aws-cdk/aws-codeguruprofiler": "1.160.0", - "@aws-cdk/aws-codepipeline": "1.160.0", - "@aws-cdk/aws-codestarnotifications": "1.160.0", - "@aws-cdk/aws-cognito": "1.160.0", - "@aws-cdk/aws-databrew": "1.160.0", - "@aws-cdk/aws-docdb": "1.160.0", - "@aws-cdk/aws-dynamodb": "1.160.0", - "@aws-cdk/aws-ec2": "1.160.0", - "@aws-cdk/aws-ecr": "1.160.0", - "@aws-cdk/aws-ecr-assets": "1.160.0", - "@aws-cdk/aws-ecs": "1.160.0", - "@aws-cdk/aws-ecs-patterns": "1.160.0", - "@aws-cdk/aws-efs": "1.160.0", - "@aws-cdk/aws-eks": "1.160.0", - "@aws-cdk/aws-elasticloadbalancing": "1.160.0", - "@aws-cdk/aws-elasticloadbalancingv2": "1.160.0", - "@aws-cdk/aws-events": "1.160.0", - "@aws-cdk/aws-events-targets": "1.160.0", - "@aws-cdk/aws-fsx": "1.160.0", - "@aws-cdk/aws-globalaccelerator": "1.160.0", - "@aws-cdk/aws-glue": "1.160.0", - "@aws-cdk/aws-iam": "1.160.0", - "@aws-cdk/aws-kinesis": "1.160.0", - "@aws-cdk/aws-kinesisfirehose": "1.160.0", - "@aws-cdk/aws-kms": "1.160.0", - "@aws-cdk/aws-lambda": "1.160.0", - "@aws-cdk/aws-lambda-nodejs": "1.160.0", - "@aws-cdk/aws-logs": "1.160.0", - "@aws-cdk/aws-route53": "1.160.0", - "@aws-cdk/aws-route53-targets": "1.160.0", - "@aws-cdk/aws-s3": "1.160.0", - "@aws-cdk/aws-s3-assets": "1.160.0", - "@aws-cdk/aws-sam": "1.160.0", - "@aws-cdk/aws-secretsmanager": "1.160.0", - "@aws-cdk/aws-servicediscovery": "1.160.0", - "@aws-cdk/aws-signer": "1.160.0", - "@aws-cdk/aws-sns": "1.160.0", - "@aws-cdk/aws-sns-subscriptions": "1.160.0", - "@aws-cdk/aws-sqs": "1.160.0", - "@aws-cdk/aws-ssm": "1.160.0", - "@aws-cdk/aws-stepfunctions": "1.160.0", - "@aws-cdk/aws-stepfunctions-tasks": "1.160.0", - "@aws-cdk/cloud-assembly-schema": "1.160.0", - "@aws-cdk/core": "1.160.0", - "@aws-cdk/custom-resources": "1.160.0", - "@aws-cdk/cx-api": "1.160.0", - "@aws-cdk/lambda-layer-awscli": "1.160.0", - "@aws-cdk/lambda-layer-kubectl": "1.160.0", - "@aws-cdk/lambda-layer-node-proxy-agent": "1.160.0", - "@aws-cdk/region-info": "1.160.0", - "constructs": "^3.3.69" + "aws-cdk-lib": "2.33.0", + "constructs": "^10.0.0" }, "engines": { "node": ">= 14.15.0" diff --git a/tools/cdk-build-tools/package.json b/tools/cdk-build-tools/package.json index 8a3a41a4b..893c5d07a 100644 --- a/tools/cdk-build-tools/package.json +++ b/tools/cdk-build-tools/package.json @@ -43,7 +43,7 @@ "dependencies": { "@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/parser": "^4.33.0", - "awslint": "1.160.0", + "awslint": "2.33.0", "colors": "1.4.0", "eslint": "^7.32.0", "eslint-import-resolver-node": "^0.3.6", diff --git a/tools/pkglint/lib/rules.ts b/tools/pkglint/lib/rules.ts index ef91d7e40..411fffb53 100644 --- a/tools/pkglint/lib/rules.ts +++ b/tools/pkglint/lib/rules.ts @@ -934,7 +934,7 @@ export class ConstructsDependency extends ValidationRule { public readonly name = 'constructs/dependency'; public validate(pkg: PackageJson) { - const REQUIRED_VERSION = '^3.3.69'; + const REQUIRED_VERSION = '^10.0.0'; if (pkg.devDependencies?.constructs && pkg.devDependencies?.constructs !== REQUIRED_VERSION) { pkg.report({ diff --git a/yarn.lock b/yarn.lock index e0fb36e64..377dca2ba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,945 +10,6 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" -"@aws-cdk/assert@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/assert/-/assert-1.160.0.tgz#b43544d3acd54ae853e7333bf8b7314a1031981d" - integrity sha512-UIdBNpFg+lmFncoqWD28Ri1r8r7jbdvLkhEhipgVCMv8kqKYDBb0VgDBdd+uEB486kU2TIflftHa1q/135gOdg== - dependencies: - "@aws-cdk/cloudformation-diff" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/cx-api" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/assets@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/assets/-/assets-1.160.0.tgz#db87791b9f629c665535c90f5056660ab19b40a4" - integrity sha512-GpJF8s0jkwhTvMTUVjW+x733uNEm2lc8C7gsBHkupqrlZmwtkfB5U4Rp4ebvdXWM/5ZdUTkI8fBJjrhg0bIlbw== - dependencies: - "@aws-cdk/core" "1.160.0" - "@aws-cdk/cx-api" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-acmpca@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-acmpca/-/aws-acmpca-1.160.0.tgz#8380488a933a3d9d3a469a28a3338ec856585ed6" - integrity sha512-3CFODMgFeriiBsczF/MnTnr7GqkRUD+/sASPYNcxxBZA1Zqz+9O7/T85X9lTnKXiTJg40CPC/jOB6aMBKtyU7Q== - dependencies: - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-apigateway@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-apigateway/-/aws-apigateway-1.160.0.tgz#dd2b8a67404fd62a55a903332ba78a700d26e44e" - integrity sha512-6P7ry309HuLlTrTtMFfNc/StjwnvHqh5DZqnJpZ0H4ChI7vwoJryiLvn/aEuKQ5yI/ZkcPZZ01PCjDVdyqNQ/A== - dependencies: - "@aws-cdk/aws-certificatemanager" "1.160.0" - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-cognito" "1.160.0" - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-elasticloadbalancingv2" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/aws-logs" "1.160.0" - "@aws-cdk/aws-s3" "1.160.0" - "@aws-cdk/aws-s3-assets" "1.160.0" - "@aws-cdk/aws-stepfunctions" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/cx-api" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-apigatewayv2-integrations@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-apigatewayv2-integrations/-/aws-apigatewayv2-integrations-1.160.0.tgz#c625e4ca5ef8dddfcaa817fcc4370a929506fad7" - integrity sha512-EYkNs9ciXXymB/8PRNaGnpfjI2I7zqY9X08N94jPFrbsvw9ekr8LfejgqwGcaJm46x7eJ9tQNIp5xJuiPjjOhA== - dependencies: - "@aws-cdk/aws-apigatewayv2" "1.160.0" - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-elasticloadbalancingv2" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/aws-servicediscovery" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-apigatewayv2@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-apigatewayv2/-/aws-apigatewayv2-1.160.0.tgz#bd32233557a237d670a43c4a8ab8fba0c7d171d6" - integrity sha512-/YcnrLkX0Y2Zh0eoIkwoVbXBCyVhCyls0xSI9O7H5G/jvBNGDUVrWle6P0/pbN8YVjPN/7Injvjs71sE7ohijA== - dependencies: - "@aws-cdk/aws-certificatemanager" "1.160.0" - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-s3" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-applicationautoscaling@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-applicationautoscaling/-/aws-applicationautoscaling-1.160.0.tgz#67c438fd4d3b0f8da2fb6e2ac44a1aa8584db0d9" - integrity sha512-Olx6kOdPh4C5i78EzyS9lKr7lNib3W+yXLBL88GcV/3CGzTavOpinn1nuzCVLDFKYONpQAh7ULorxNilEoK6Qw== - dependencies: - "@aws-cdk/aws-autoscaling-common" "1.160.0" - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-autoscaling-common@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-autoscaling-common/-/aws-autoscaling-common-1.160.0.tgz#17fa34a4706f7c237114fc2f51420215b3dd362a" - integrity sha512-XGn7xbOMB973pDTQlXjfrK4iPYlq3tcHPSf5l3ROkVuN3mtxPTTITekf6cORJ7YYAA+8MC3la4ivzJ7onT2O1g== - dependencies: - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-autoscaling-hooktargets@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-autoscaling-hooktargets/-/aws-autoscaling-hooktargets-1.160.0.tgz#ac13aadaf6ff47b41ab418be453b3d798ad81e46" - integrity sha512-Zq2YwLGMGIQpZ9ii6+gSs+788/daHPYerjZzFPI8rf7D7CeMkILsWKoMr5xZOZIfYihZokU+ebTVkotRgUkihQ== - dependencies: - "@aws-cdk/aws-autoscaling" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/aws-sns" "1.160.0" - "@aws-cdk/aws-sns-subscriptions" "1.160.0" - "@aws-cdk/aws-sqs" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-autoscaling@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-autoscaling/-/aws-autoscaling-1.160.0.tgz#76b924f7e1a886bfc5a6d62f178bf41d6a6d7c80" - integrity sha512-SGRuCGH4zfjsWcrgb5dWzOBE4dL077N3L8m1CDp/MttWoxdD4IlSqktcsgTFkbt2WqOUwFZkBJHfbctEtepP2A== - dependencies: - "@aws-cdk/aws-autoscaling-common" "1.160.0" - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-elasticloadbalancing" "1.160.0" - "@aws-cdk/aws-elasticloadbalancingv2" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-sns" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-batch@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-batch/-/aws-batch-1.160.0.tgz#a7d3045e72b1e378e0408a307f4aa33d944d52d3" - integrity sha512-+cYMFqxOtJpUfMj72d/KDfEwiHoWJiADA4HiOEWTbXk8pd5cXlFJJncbUGtxLyn5di+LInpfTwRC3IcbTAyuuQ== - dependencies: - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-ecr" "1.160.0" - "@aws-cdk/aws-ecs" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-secretsmanager" "1.160.0" - "@aws-cdk/aws-ssm" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-certificatemanager@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-certificatemanager/-/aws-certificatemanager-1.160.0.tgz#b32119d7034a5bc92ddbe9298965728bee6fe697" - integrity sha512-5QiIDfYugPxGV7NLoxzwX4B2zDdTlSqXSARUdYji3zwdVCzjD8Utd33WwdX1FyO/niXAWVCc8jmSARt4oYC8mA== - dependencies: - "@aws-cdk/aws-acmpca" "1.160.0" - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/aws-route53" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-cloudformation@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-cloudformation/-/aws-cloudformation-1.160.0.tgz#e12ad6013982578fd6341cabb8d43cb05187c04a" - integrity sha512-NE+XuKyiqInKYe7X6cJeXbIRwnajxyzubjqpSgYEBVsFkVtuB/D+Sheiwxl6D5yZ6xtZHgDegyn9oSanSP32tw== - dependencies: - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/aws-s3" "1.160.0" - "@aws-cdk/aws-sns" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/cx-api" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-cloudfront@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-cloudfront/-/aws-cloudfront-1.160.0.tgz#7bb9ac0a278b315345a4fa24703754d732b4d219" - integrity sha512-C+xYpDz3BdJ/Fn16nqnYzKkMUAqVe5WS0Pfrtg6Z5+2VeUsuGeomommJBI6Ns3m/vkUmjLzauZx89gAXOgHMew== - dependencies: - "@aws-cdk/aws-certificatemanager" "1.160.0" - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/aws-s3" "1.160.0" - "@aws-cdk/aws-ssm" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/cx-api" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-cloudwatch-actions@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-cloudwatch-actions/-/aws-cloudwatch-actions-1.160.0.tgz#cb69abd00db2fe09a9b1317c3162de85a218ca06" - integrity sha512-C9g5VIyawf4jQHvj+oXQmhnSeQPVXHDkcKNHcm47G7d0rExlksKS9AfMo9Ea2f/OAa4H6nX/cyy3I+4oqYZw3A== - dependencies: - "@aws-cdk/aws-applicationautoscaling" "1.160.0" - "@aws-cdk/aws-autoscaling" "1.160.0" - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-sns" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-cloudwatch@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-cloudwatch/-/aws-cloudwatch-1.160.0.tgz#6f1b99743112086d7dd3c6bbeda7a081908e0fb5" - integrity sha512-9wxLH07K4N0jGwFRNLge2EgyFPnI9+S9b37yNtbni4U2xyeZjdvkP1HAb3u1Bxn4kEDeKwwFlQf4Emp/Es+AjQ== - dependencies: - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-codebuild@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-codebuild/-/aws-codebuild-1.160.0.tgz#6af194afbc671100c329527f57dd6bcbaa573be1" - integrity sha512-PglnJHQnU8avEYcWbj2nTmK7V9EgeUWAACQzNUmDGUKvuXGRfTSF/Vdy9gjvTqeEuwGiOfVZPZnYmmGm744GLQ== - dependencies: - "@aws-cdk/assets" "1.160.0" - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-codecommit" "1.160.0" - "@aws-cdk/aws-codestarnotifications" "1.160.0" - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-ecr" "1.160.0" - "@aws-cdk/aws-ecr-assets" "1.160.0" - "@aws-cdk/aws-events" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-logs" "1.160.0" - "@aws-cdk/aws-s3" "1.160.0" - "@aws-cdk/aws-s3-assets" "1.160.0" - "@aws-cdk/aws-secretsmanager" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/region-info" "1.160.0" - constructs "^3.3.69" - yaml "1.10.2" - -"@aws-cdk/aws-codecommit@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-codecommit/-/aws-codecommit-1.160.0.tgz#c2c38dcefb2635e10b280eab5c411ccf5a191469" - integrity sha512-n7WNnTeYO7pxEE20zmFGUrXQRJvMyQGF2Upen0oIY8VvVa11qVDFIs0tseKwFBWBMSx9sCHvUioo5cnMYWVtvw== - dependencies: - "@aws-cdk/aws-codestarnotifications" "1.160.0" - "@aws-cdk/aws-events" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-s3-assets" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-codeguruprofiler@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-codeguruprofiler/-/aws-codeguruprofiler-1.160.0.tgz#8d911268d86016d2eb57043b4bdcfaad8e445495" - integrity sha512-d8iNt8qJ8cfjp3NOuzHBVl4RtJDSgQ+fG1DHlbvlpUu5lzAOXHfS35WjI49yHTpdsge/UvwKb3aCPi8QJobqnA== - dependencies: - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-codepipeline@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-codepipeline/-/aws-codepipeline-1.160.0.tgz#663fd2fdc462ea1d07939a729bd7c61c8c37add4" - integrity sha512-7MZqXn4ho9ufkRG0sI9JsahxJFz6SadJWm0+w51Avd1y9Y0EhL8ManHQ5wu61HtkP3ZohhmWzsKatLu1ZFyiuA== - dependencies: - "@aws-cdk/aws-codestarnotifications" "1.160.0" - "@aws-cdk/aws-events" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-s3" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-codestarnotifications@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-codestarnotifications/-/aws-codestarnotifications-1.160.0.tgz#29e2b985e2bdd39120a4f66bbd61868d8a9b683e" - integrity sha512-zOyjApE1aU2UzuC9iOeJzuEMQFBhpYwqv03JD/pChFk1u2Ck3Ckww8Ix1MBDj0feGd4U54nza2R5crvSf+UdJQ== - dependencies: - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-cognito@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-cognito/-/aws-cognito-1.160.0.tgz#e68c71a352156011b9c8f1b87dd77f19a9e49c2a" - integrity sha512-6WVpl7VsX9muZjI5COrS8GkbXBsR2vcXzweD7/NHBF213jKH7Y0KIYCEjkZtrXt301Nh8LkOyCHY88+YkEIxFQ== - dependencies: - "@aws-cdk/aws-certificatemanager" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/custom-resources" "1.160.0" - constructs "^3.3.69" - punycode "^2.1.1" - -"@aws-cdk/aws-databrew@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-databrew/-/aws-databrew-1.160.0.tgz#af3f1d73542aedf57afbf72e1826f0991da201a2" - integrity sha512-b1xQvFYQNFVlG9LyN9B1i0+UxdbJPIokaL42MMdNaCb/UAiSg7zB6KyAv+rTaK1VIzM+w1p/tIvYHqm7RhWuig== - dependencies: - "@aws-cdk/core" "1.160.0" - -"@aws-cdk/aws-docdb@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-docdb/-/aws-docdb-1.160.0.tgz#59ac92e3ddef5b975c893ee94ce6db6541753894" - integrity sha512-dFp9tkbZ0HPxJxRwBjpzRsKZxKDwfxURIzt57zGWi3mQrI4ndU7gdNvGyxHUk5lqwl0dx3tjCQ5xxw1OHKU0uA== - dependencies: - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-efs" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-logs" "1.160.0" - "@aws-cdk/aws-secretsmanager" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-dynamodb@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-dynamodb/-/aws-dynamodb-1.160.0.tgz#f50bf78745d96f91c845e013811f35c9e6241d6d" - integrity sha512-1G1Hy8PJsewvWQIChGox5IYhTYExmwar1icNYlv++WDAnu5ztkLuV02GW2090Cevw/TEZgMQaBI+/MgWi73C6g== - dependencies: - "@aws-cdk/aws-applicationautoscaling" "1.160.0" - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kinesis" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/custom-resources" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-ec2@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-ec2/-/aws-ec2-1.160.0.tgz#f0e25c660459b82d29b6afdcf1f8c48990e8bc4f" - integrity sha512-S8qbJyFhk1nB2YWlFn6VQWWuUq8rds323cUsrHnvRUdyIt9dgRFzIRnaD0jOiBndfjUylhEe0zvoYWfntajmTw== - dependencies: - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-logs" "1.160.0" - "@aws-cdk/aws-s3" "1.160.0" - "@aws-cdk/aws-s3-assets" "1.160.0" - "@aws-cdk/aws-ssm" "1.160.0" - "@aws-cdk/cloud-assembly-schema" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/cx-api" "1.160.0" - "@aws-cdk/region-info" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-ecr-assets@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-ecr-assets/-/aws-ecr-assets-1.160.0.tgz#84efc6c67b15a619255999848a44cd7f21ca15d2" - integrity sha512-vIWi/Iudn/y1JaG1q3QxD0dsf+9Hz3rzpmm2ZzwbWTAbtUtZ7beDMc2smIGUMSFMpHZnvAdhiwsGf6q2mObEhw== - dependencies: - "@aws-cdk/assets" "1.160.0" - "@aws-cdk/aws-ecr" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-s3" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/cx-api" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-ecr@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-ecr/-/aws-ecr-1.160.0.tgz#e0c730e0902e40e7a83d2b587ca33f4109326e25" - integrity sha512-B0R5WNKptVWk2od5Lww/1TYw5amUJMQJgIrLJl1WLvDmhj9tVDO7S9AOpLKvK38tKSEvHTSNcXdI1+ftMav+kA== - dependencies: - "@aws-cdk/aws-events" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-ecs-patterns@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-ecs-patterns/-/aws-ecs-patterns-1.160.0.tgz#de9c5eeb868123a932d3016054175874de072c0f" - integrity sha512-gg/oulzbpsinF75q6mshlP0QoMyKm8WZ7Bi4lr5OLyr/kl4pfePx7gbjkhtlsW2YFttGOCmfHgQP+6aYnW3/xQ== - dependencies: - "@aws-cdk/aws-applicationautoscaling" "1.160.0" - "@aws-cdk/aws-autoscaling" "1.160.0" - "@aws-cdk/aws-certificatemanager" "1.160.0" - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-ecs" "1.160.0" - "@aws-cdk/aws-elasticloadbalancingv2" "1.160.0" - "@aws-cdk/aws-events" "1.160.0" - "@aws-cdk/aws-events-targets" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-route53" "1.160.0" - "@aws-cdk/aws-route53-targets" "1.160.0" - "@aws-cdk/aws-servicediscovery" "1.160.0" - "@aws-cdk/aws-sqs" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/cx-api" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-ecs@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-ecs/-/aws-ecs-1.160.0.tgz#71824286831682f72ad402c611d30262f7801263" - integrity sha512-1rRyvwGXgITItHVauGYC4XSvNRQgaq7MnDy2a2AeJ5SHZBasTtQROM1D4Ub/YL1Ss8Q1vBxbC2Rxg6mg3IUmoQ== - dependencies: - "@aws-cdk/aws-applicationautoscaling" "1.160.0" - "@aws-cdk/aws-autoscaling" "1.160.0" - "@aws-cdk/aws-autoscaling-hooktargets" "1.160.0" - "@aws-cdk/aws-certificatemanager" "1.160.0" - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-ecr" "1.160.0" - "@aws-cdk/aws-ecr-assets" "1.160.0" - "@aws-cdk/aws-elasticloadbalancing" "1.160.0" - "@aws-cdk/aws-elasticloadbalancingv2" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/aws-logs" "1.160.0" - "@aws-cdk/aws-route53" "1.160.0" - "@aws-cdk/aws-route53-targets" "1.160.0" - "@aws-cdk/aws-s3" "1.160.0" - "@aws-cdk/aws-s3-assets" "1.160.0" - "@aws-cdk/aws-secretsmanager" "1.160.0" - "@aws-cdk/aws-servicediscovery" "1.160.0" - "@aws-cdk/aws-sns" "1.160.0" - "@aws-cdk/aws-sqs" "1.160.0" - "@aws-cdk/aws-ssm" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/cx-api" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-efs@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-efs/-/aws-efs-1.160.0.tgz#c5e51906e307b7b01ba39d48d49a777328d2140c" - integrity sha512-R7ef5g1i0mNrVA/CkuBgDhd2lvhABTqQukraT+fr7aBQt6rbcC7cjEtIhVat+STF+7TBhl8p+Qa5LKOUviU15Q== - dependencies: - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/cloud-assembly-schema" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/cx-api" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-eks@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-eks/-/aws-eks-1.160.0.tgz#d20d7a7270c7a9b8008a7e5af2c72e5c5407730a" - integrity sha512-zXWBe6lMXHIzP/3/x/2ztXP5X7dfa6aKUHS1+JGNgKEebXxcmuhYrH2cLOBWIvU2shNUIfTGeSARQZxExnzNJA== - dependencies: - "@aws-cdk/aws-autoscaling" "1.160.0" - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/aws-s3-assets" "1.160.0" - "@aws-cdk/aws-ssm" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/custom-resources" "1.160.0" - "@aws-cdk/lambda-layer-awscli" "1.160.0" - "@aws-cdk/lambda-layer-kubectl" "1.160.0" - "@aws-cdk/lambda-layer-node-proxy-agent" "1.160.0" - constructs "^3.3.69" - yaml "1.10.2" - -"@aws-cdk/aws-elasticloadbalancing@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-elasticloadbalancing/-/aws-elasticloadbalancing-1.160.0.tgz#f3348bc5784d31e78a542d4f7793ddf2a05d0a07" - integrity sha512-OYzHJnrhXzzwkEgZdARaKUnqWOCCsMB/TVo38TQcC5obLmQtsi6XKNhV9ol9h26y3fXBfupMT6dB9AT2cdxF0w== - dependencies: - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-elasticloadbalancingv2@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-elasticloadbalancingv2/-/aws-elasticloadbalancingv2-1.160.0.tgz#7f925e660d03a732b6235361995d159e847050d8" - integrity sha512-arAQ9LvdHuxGJmCxnpNR/19dV7zkNw7/mq2e6mjv5nfXlYDAwY6kJFrbLnIyVwwGnhNehZBE0Cq3CjRkFzPaMw== - dependencies: - "@aws-cdk/aws-certificatemanager" "1.160.0" - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/aws-route53" "1.160.0" - "@aws-cdk/aws-s3" "1.160.0" - "@aws-cdk/cloud-assembly-schema" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/cx-api" "1.160.0" - "@aws-cdk/region-info" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-events-targets@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-events-targets/-/aws-events-targets-1.160.0.tgz#6839121e2af3ee1e0a7017f198c58a84ffe97b19" - integrity sha512-bXnKRgK1e4DBsIh4T3K/ZsNkAluYhHaBydPiCjlI6GpwZV4+IOanonYhOpTOA7AQqMtb26UIvG8axf3PhxCodA== - dependencies: - "@aws-cdk/aws-apigateway" "1.160.0" - "@aws-cdk/aws-autoscaling" "1.160.0" - "@aws-cdk/aws-codebuild" "1.160.0" - "@aws-cdk/aws-codepipeline" "1.160.0" - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-ecs" "1.160.0" - "@aws-cdk/aws-events" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kinesis" "1.160.0" - "@aws-cdk/aws-kinesisfirehose" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/aws-logs" "1.160.0" - "@aws-cdk/aws-sns" "1.160.0" - "@aws-cdk/aws-sns-subscriptions" "1.160.0" - "@aws-cdk/aws-sqs" "1.160.0" - "@aws-cdk/aws-stepfunctions" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/custom-resources" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-events@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-events/-/aws-events-1.160.0.tgz#9f06e1004baf5428a76a7202bd6bd654547a0895" - integrity sha512-p+IGVC5YLxFI3Sr+mqpsH+FOJNIZfrbH7Bn7HCSZX/LT4s/OOpYFRsVYKEAvUsZU06vdRKBYv51p+OdlDXYOOQ== - dependencies: - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-fsx@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-fsx/-/aws-fsx-1.160.0.tgz#208e5b4e7041baaf0aaaf0e2a0fd546208280537" - integrity sha512-Z++vHEY65i0nELJaPQKmxZ2ALhVsLHK5kr7lxjg0KX3yNoB4yEupf+DGqwt1TTd48u22ZgPF+E+HG2xdbilN/Q== - dependencies: - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-globalaccelerator@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-globalaccelerator/-/aws-globalaccelerator-1.160.0.tgz#041a098c2cb977c6593e5ed5fe9a3b1930feb178" - integrity sha512-epXMyJ/Xs4+uPqe4j3C/fyKZxmBqOXo60tRG0+qNMC0A6aaDIzOIBKSKsZm60hK1o9MbB/9qYIR4IKOXNX3Zog== - dependencies: - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/custom-resources" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-glue@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-glue/-/aws-glue-1.160.0.tgz#376277041a2c380541029c1a700c120046b91a09" - integrity sha512-01m8hUJDVeBOx2g7x+T4vjtosnMMyAvGKY2O1+p/wNmI0gEsXu5pIan5tRgCiWyPkyMretSN07zlSZorM+curg== - dependencies: - "@aws-cdk/assets" "1.160.0" - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-events" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-logs" "1.160.0" - "@aws-cdk/aws-s3" "1.160.0" - "@aws-cdk/aws-s3-assets" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/custom-resources" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-iam@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-iam/-/aws-iam-1.160.0.tgz#08e8238449fa5ac901ba85ac0f3fd1c9483e9986" - integrity sha512-XLRceC64dNRFlegfW6dlmW/K7DWcN12h5dycTO0fRvmkuc+ZqNvU/8Zb133jiKWBh/OaBG4SS3HxpN1anpbT/w== - dependencies: - "@aws-cdk/core" "1.160.0" - "@aws-cdk/cx-api" "1.160.0" - "@aws-cdk/region-info" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-imagebuilder@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-imagebuilder/-/aws-imagebuilder-1.160.0.tgz#fb592d004ee3af8923863f7154edd66562417338" - integrity sha512-bWCYZgpPIvN0zNFJ9pxksl8pL2rJzmRHPNiGgrsPFmoSHflC1QBZo4m7bn46rL8tF5BgnkVt3uggMmddJ7qrfw== - dependencies: - "@aws-cdk/core" "1.160.0" - -"@aws-cdk/aws-kinesis@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-kinesis/-/aws-kinesis-1.160.0.tgz#67ffb208d6666532cbcd6e464e472ae0ce51f24f" - integrity sha512-Y7IfyprIaPJKmOck2R0c+m9Iw6VNZgBV05lajL5iltAlBsuLCudXE2l5sZwOTe7ebz61clpQUjYUL/QgjoPqrg== - dependencies: - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-logs" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-kinesisfirehose@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-kinesisfirehose/-/aws-kinesisfirehose-1.160.0.tgz#2a135df625affda2356d39c83c005d4eb6b526a5" - integrity sha512-Lz9Zrd17kZyxLktHlSaraYEZJxcOlU8RUrw077saFe40vcVODgZOCih9rdln0EeTuOPcRCoOgw/NEu3aFfF0zA== - dependencies: - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kinesis" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/aws-logs" "1.160.0" - "@aws-cdk/aws-s3" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/region-info" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-kms@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-kms/-/aws-kms-1.160.0.tgz#b01ef82ff9b748c736854e12c50542dd512a5d0a" - integrity sha512-HVn+Nfy4/99NB4MgsAfCpoD4aMEL0G0YQXPxF0yhv8qGJuqaUpyUX5yPHEKeOSlWJStKo/WbjkMYaw7s5kW5Iw== - dependencies: - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/cloud-assembly-schema" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/cx-api" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-lambda-nodejs@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-lambda-nodejs/-/aws-lambda-nodejs-1.160.0.tgz#ec6c8411da48f6f92b2cc60943b58107a9b25dc4" - integrity sha512-w56YDyhsoAvOa6GG5m0cxrItcdspbk9bVzc8iisq48d3MThv+es9zTAeugIk/OqnTEAah1aWf3ladzGeXe/LCA== - dependencies: - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-lambda@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-lambda/-/aws-lambda-1.160.0.tgz#96d4fad46ce35cce08bf1df7ff5b366d45dbc6f2" - integrity sha512-5YnB5OFiHvAHWq7B0rdWNPRixJs4QokqKnxVvWoBxRrRO4ZcS/nuVXt9imVKKshpWH+9h8S7+EG387lH1RFRcA== - dependencies: - "@aws-cdk/aws-applicationautoscaling" "1.160.0" - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-codeguruprofiler" "1.160.0" - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-ecr" "1.160.0" - "@aws-cdk/aws-ecr-assets" "1.160.0" - "@aws-cdk/aws-efs" "1.160.0" - "@aws-cdk/aws-events" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-logs" "1.160.0" - "@aws-cdk/aws-s3" "1.160.0" - "@aws-cdk/aws-s3-assets" "1.160.0" - "@aws-cdk/aws-signer" "1.160.0" - "@aws-cdk/aws-sns" "1.160.0" - "@aws-cdk/aws-sqs" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/cx-api" "1.160.0" - "@aws-cdk/region-info" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-logs@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-logs/-/aws-logs-1.160.0.tgz#44eb743baf1f6962b47aa1b179d3e7c374be09fd" - integrity sha512-Akj2DzISmQM1KnLFFb6M+xk3UptVzMyjUn5MVYGIzSd7/UCJ7OlyUyXbST9fb3UxxmeklM4moIZ7fZCW3uUNOg== - dependencies: - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-s3-assets" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/cx-api" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-route53-targets@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-route53-targets/-/aws-route53-targets-1.160.0.tgz#d1b40499c51236f34d7afa7bb72333f7f93d5bf6" - integrity sha512-iRQIoUmIVKi6zevLVPL4ldpYEfxU3T2qFAExB819SQMajV7L/Yf6+XTvQ7NR/X87rP4Z6eAa8dUHbPSjkqX1kg== - dependencies: - "@aws-cdk/aws-apigateway" "1.160.0" - "@aws-cdk/aws-cloudfront" "1.160.0" - "@aws-cdk/aws-cognito" "1.160.0" - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-elasticloadbalancing" "1.160.0" - "@aws-cdk/aws-elasticloadbalancingv2" "1.160.0" - "@aws-cdk/aws-globalaccelerator" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-route53" "1.160.0" - "@aws-cdk/aws-s3" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/region-info" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-route53@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-route53/-/aws-route53-1.160.0.tgz#b842ac671326ace41f401a2403f92d671afd5870" - integrity sha512-aHh8OFJ44y0xw9+eQtgqqA81a9f+oWIrIeBidCMIF9IHAGIZBM1OMyV3Tr2jS1qRztL3xXwlLHPhzt/XOCAwAA== - dependencies: - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-logs" "1.160.0" - "@aws-cdk/cloud-assembly-schema" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/custom-resources" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-s3-assets@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-s3-assets/-/aws-s3-assets-1.160.0.tgz#e8156a3f28cbc985a92be8f271caa15da0a2f8f3" - integrity sha512-jJZhOTL6FYXLDCIVZBv3QMPzhGto3AiYZvZnX9Fl4dMh2X/rlhdvlwLJ9BULZsy0D7nLUDIYuY5X8uuSpaKw/w== - dependencies: - "@aws-cdk/assets" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-s3" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/cx-api" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-s3@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-s3/-/aws-s3-1.160.0.tgz#0f8a24dac482bf1d91c0fbe8af2b79f2db650a83" - integrity sha512-VLzQwAZrH0p78DrSHEVuxgnK0q+VvBeKuNQMXjP/BA6j1QmkD4QKcVnHKlVoA3WXB2i8uaM8bQFdcIhbdU6CCw== - dependencies: - "@aws-cdk/aws-events" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/cx-api" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-sam@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-sam/-/aws-sam-1.160.0.tgz#e0f84f50e530433a745696e7c131b221efb39c31" - integrity sha512-bUcG4nnDomqnDdqdCh/kAX7Lz1jflUj073qMH/dClp5RafrTZbjhf0Ctwy+nNj+KSMZ1vG9XDNsXz0PZGuKZxQ== - dependencies: - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-secretsmanager@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-secretsmanager/-/aws-secretsmanager-1.160.0.tgz#6ddbf67027469e89e5ed0f9072e91663c5e10621" - integrity sha512-uNtU79k0K08v+beFwmt9R7tRBeAemkaPCAJtUZ6adkDJf63o6q9hBA+zO5hysTweQsupJzfknqooQ3WETbcwpQ== - dependencies: - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/aws-sam" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/cx-api" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-servicediscovery@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-servicediscovery/-/aws-servicediscovery-1.160.0.tgz#e42031f1b21cc38390c057fcc0e4be55c707b844" - integrity sha512-QYVq5hM79zLguHZrHy09rSbIRbV86NC5bS68wKWvbdMSO3jR8qxG+cqKWC7T2hOGIuGkXvC31tvP7OFo5AgpJg== - dependencies: - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-elasticloadbalancingv2" "1.160.0" - "@aws-cdk/aws-route53" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-signer@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-signer/-/aws-signer-1.160.0.tgz#85882e90431baa321a909f84da03d541cb52e382" - integrity sha512-HDylh604EV4U8VIG9LwP/3Kgj31F+cH0Ued0wwGm6OUlP2ISN4RNLaRe7krx9tvLpxi1TBHmnMTDz0RTFMA9lQ== - dependencies: - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-sns-subscriptions@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-sns-subscriptions/-/aws-sns-subscriptions-1.160.0.tgz#dea229b9a3415e00daebc07cb364a7701ef63626" - integrity sha512-myaSG1MPOzqqljIzTD71t7y2MvBgawXO5Y4UZ6F5xbEOs2j503AjKtKKnRcE10LgDDhtM4hMEt0lEavviOWt0w== - dependencies: - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/aws-sns" "1.160.0" - "@aws-cdk/aws-sqs" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-sns@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-sns/-/aws-sns-1.160.0.tgz#f0d1b995dff06edd6766ff851663a4ad701657f4" - integrity sha512-IDFM41sPGcaxgalH2MHjGamKDv19hQygm+w8vceqyCEnZRhnDCVWhxzaHM8VB6T9KnVLwkPVFbSEbbiWQSgxgQ== - dependencies: - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-codestarnotifications" "1.160.0" - "@aws-cdk/aws-events" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-sqs" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-sqs@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-sqs/-/aws-sqs-1.160.0.tgz#fdc007a6a3bc12a23cb1c15ea61cc7ca0e1bab7f" - integrity sha512-hAWV077dzlQMo/WaceNZj18yfO/uuLgMrARxKxExnOTG61+OKo1OtFEWm/+EQ5VzFWiUqEUPTaPFMkujgbQ1Mw== - dependencies: - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-ssm@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-ssm/-/aws-ssm-1.160.0.tgz#d4a1bfbfc28d89320d766da6d126d1d8454d5112" - integrity sha512-5FVZyXg+YJg4VlpGRrS7G22FMUAdaiOxBFGq3EIvmBxIJQgFPXoKqFwaWRsauUFuDT99QgX1fWryZ4tAU7FA5g== - dependencies: - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/cloud-assembly-schema" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-stepfunctions-tasks@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-stepfunctions-tasks/-/aws-stepfunctions-tasks-1.160.0.tgz#2806cb785ff081fdd407187d8c9eff193e45e606" - integrity sha512-in4H2cspDBNxjbGwck+BFrtkWBVF2D9jJyGDDSOpjSIovu27guMTNkU2TZhaTx3u7JR1AbB70t9BFWpLYIkHpA== - dependencies: - "@aws-cdk/aws-apigateway" "1.160.0" - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-codebuild" "1.160.0" - "@aws-cdk/aws-dynamodb" "1.160.0" - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-ecr" "1.160.0" - "@aws-cdk/aws-ecr-assets" "1.160.0" - "@aws-cdk/aws-ecs" "1.160.0" - "@aws-cdk/aws-eks" "1.160.0" - "@aws-cdk/aws-events" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-kms" "1.160.0" - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/aws-logs" "1.160.0" - "@aws-cdk/aws-s3" "1.160.0" - "@aws-cdk/aws-sns" "1.160.0" - "@aws-cdk/aws-sqs" "1.160.0" - "@aws-cdk/aws-stepfunctions" "1.160.0" - "@aws-cdk/core" "1.160.0" - "@aws-cdk/custom-resources" "1.160.0" - "@aws-cdk/lambda-layer-awscli" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/aws-stepfunctions@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-stepfunctions/-/aws-stepfunctions-1.160.0.tgz#904a7ff004ff3ff6dd4b1368098396dc1a5936b3" - integrity sha512-E+Pomi0rBNCGZ3rkRYnl5UjpsN/SAuav/SVhRhVifM5/IO+BQrdSJHSRq1V8WLy3OiGAKvezhzM+D1rdY3ETww== - dependencies: - "@aws-cdk/aws-cloudwatch" "1.160.0" - "@aws-cdk/aws-events" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-logs" "1.160.0" - "@aws-cdk/aws-s3" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/cfnspec@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/cfnspec/-/cfnspec-1.160.0.tgz#787f37a3d538001f3c1557ec2f192064bd0c250b" - integrity sha512-jnIgLLM0EFwS3eO3UcAaJ16M8cMgLw9FjlVQb34QNh9adaHgcRpGAcet8VrUTy7TUdHqR0fx78jIK01G/5Lrug== - dependencies: - fs-extra "^9.1.0" - md5 "^2.3.0" - -"@aws-cdk/cloud-assembly-schema@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-1.160.0.tgz#1f692f72569e76de7a46920e165ded4ba4eba690" - integrity sha512-/2LftwkGKZ+k7L1rBXFfNB0Fd+4NYv43VLon37+7RgZsxXC9/DPICajiF33WyAEF3xRjAcpYeiMzcQNtyoFECQ== - dependencies: - jsonschema "^1.4.1" - semver "^7.3.7" - -"@aws-cdk/cloudformation-diff@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/cloudformation-diff/-/cloudformation-diff-1.160.0.tgz#ac432e1029a1fef33bc90d45b2ba57f6e89ad381" - integrity sha512-rPmRUUyoX1PN2MLQQX/taJg5jk8pIvAXfKK/xJNN5Om17mpGNRuRLAxU1PDZitoDXOn8T3qR/T+dHe6J1vtkdw== - dependencies: - "@aws-cdk/cfnspec" "1.160.0" - "@types/node" "^10.17.60" - chalk "^4" - diff "^5.1.0" - fast-deep-equal "^3.1.3" - string-width "^4.2.3" - table "^6.8.0" - -"@aws-cdk/core@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/core/-/core-1.160.0.tgz#28d76a01e0a0c4811ab2b276de267be7e1408abd" - integrity sha512-cS2YALqAJ6GHoTcBKhMnOzPxjKF+LgwEDbLFBYnBUGoaAVh8b1pvr442AM1eg8n7gxVAkDdehrgPabekpspu+A== - dependencies: - "@aws-cdk/cloud-assembly-schema" "1.160.0" - "@aws-cdk/cx-api" "1.160.0" - "@aws-cdk/region-info" "1.160.0" - "@balena/dockerignore" "^1.0.2" - constructs "^3.3.69" - fs-extra "^9.1.0" - ignore "^5.2.0" - minimatch "^3.1.2" - -"@aws-cdk/custom-resources@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/custom-resources/-/custom-resources-1.160.0.tgz#314a594cceb8cdbc3c278509212289c8e383d7f2" - integrity sha512-MuINir6HfwHprnrgWtheWzRXJoI1ZjlAEVrKJGM/By7d3lws2ftp44eteqIzrNBEpF9Xt9woW0+Z2XTN9NRqUA== - dependencies: - "@aws-cdk/aws-cloudformation" "1.160.0" - "@aws-cdk/aws-ec2" "1.160.0" - "@aws-cdk/aws-iam" "1.160.0" - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/aws-logs" "1.160.0" - "@aws-cdk/aws-sns" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/cx-api@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/cx-api/-/cx-api-1.160.0.tgz#debcb085fdfe1658e7deca95d9492e2e4e4cc242" - integrity sha512-najDj4d1ombMIziL8v3vUGvsL/Rcq/1gkIL9IKMb9h3KzWPL6y51Vo7A8tTvt/QcPpsxF4A7UL3OGNmukT3bSw== - dependencies: - "@aws-cdk/cloud-assembly-schema" "1.160.0" - semver "^7.3.7" - -"@aws-cdk/lambda-layer-awscli@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/lambda-layer-awscli/-/lambda-layer-awscli-1.160.0.tgz#71527fe321b1be5cbd3b78891ccd666ef6c16d85" - integrity sha512-QSC+f8TDEkd+YD6IMzy4fBFS/yYB2YdzcANnq+IFqBGyw+as4CjtNDZ6zoyvA6DPFuBtf5P9MOuVr660eRQarA== - dependencies: - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/lambda-layer-kubectl@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/lambda-layer-kubectl/-/lambda-layer-kubectl-1.160.0.tgz#246d2f66422bdae58ca83a6e74aa56459cc2e0e7" - integrity sha512-pZduDZmGaHtFlbbZEsaMttYCoOaxdyIfFIKfaqKj3t72oZ2EAsWKJ6shu6jGX+dv9G8Pz9clJ3B+WnOozytNhQ== - dependencies: - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/lambda-layer-node-proxy-agent@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/lambda-layer-node-proxy-agent/-/lambda-layer-node-proxy-agent-1.160.0.tgz#3266af5a86d5b4e2fd18659b472e97baf7760ad3" - integrity sha512-SC/eFwDJdtHjKJMRsjd1y0wtaMdV3Q2pDP1VkRf2+kIu2M28TsY41o0//9PUT9Imf+rHJwrDpL6FmNojf9g2FA== - dependencies: - "@aws-cdk/aws-lambda" "1.160.0" - "@aws-cdk/core" "1.160.0" - constructs "^3.3.69" - -"@aws-cdk/region-info@1.160.0": - version "1.160.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/region-info/-/region-info-1.160.0.tgz#aefeb9acfa02ba9baceeb167a0c2dbb44340e491" - integrity sha512-B6esadtyghIMaiBP+Jgy7U8S26oOzqKDYdXBRx5E+2UsO6aXzntowx5B0J67otnPZIjUqatYXe6uyOb1txDxLQ== - "@aws-crypto/ie11-detection@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@aws-crypto/ie11-detection/-/ie11-detection-2.0.0.tgz#bb6c2facf8f03457e949dcf0921477397ffa4c6e" @@ -1004,377 +65,377 @@ "@aws-sdk/util-utf8-browser" "^3.0.0" tslib "^1.11.1" -"@aws-sdk/abort-controller@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/abort-controller/-/abort-controller-3.110.0.tgz#15b493b776ec4f7236c6ad6134a6fe87e9dc5292" - integrity sha512-zok/WEVuK7Jh6V9YeA56pNZtxUASon9LTkS7vE65A4UFmNkPGNBCNgoiBcbhWfxwrZ8wtXcQk6rtUut39831mA== +"@aws-sdk/abort-controller@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/abort-controller/-/abort-controller-3.127.0.tgz#60c98bffdb185d8eb5d3e43f30f57a32cc8687d6" + integrity sha512-G77FLYcl9egUoD3ZmR6TX94NMqBMeT53hBGrEE3uVUJV1CwfGKfaF007mPpRZnIB3avnJBQGEK6MrwlCfv2qAw== dependencies: - "@aws-sdk/types" "3.110.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" "@aws-sdk/client-cloudformation@^3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-cloudformation/-/client-cloudformation-3.110.0.tgz#c789604972f6bd3cc63bd5996c0d6a459e7b19c0" - integrity sha512-rjzU7TvV6lHFErx7XwBBUNtxKvSVO3bwBWkaI/712/6ipr8Muhedw2OLJLEY/td/0ldKWjtTi2xmDXwOHvIadQ== + version "3.131.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-cloudformation/-/client-cloudformation-3.131.0.tgz#bc388172ee6f42657d3127cfaa33e327c670e3e6" + integrity sha512-9P5NCjTLflpzHPjiwJH+EGNi5X2fVCG/yTQlERg2b64B+IBx/j1sxkkloXBPvP+WGASf4kPHtr7a4iB+CnC0WA== dependencies: "@aws-crypto/sha256-browser" "2.0.0" "@aws-crypto/sha256-js" "2.0.0" - "@aws-sdk/client-sts" "3.110.0" - "@aws-sdk/config-resolver" "3.110.0" - "@aws-sdk/credential-provider-node" "3.110.0" - "@aws-sdk/fetch-http-handler" "3.110.0" - "@aws-sdk/hash-node" "3.110.0" - "@aws-sdk/invalid-dependency" "3.110.0" - "@aws-sdk/middleware-content-length" "3.110.0" - "@aws-sdk/middleware-host-header" "3.110.0" - "@aws-sdk/middleware-logger" "3.110.0" - "@aws-sdk/middleware-recursion-detection" "3.110.0" - "@aws-sdk/middleware-retry" "3.110.0" - "@aws-sdk/middleware-serde" "3.110.0" - "@aws-sdk/middleware-signing" "3.110.0" - "@aws-sdk/middleware-stack" "3.110.0" - "@aws-sdk/middleware-user-agent" "3.110.0" - "@aws-sdk/node-config-provider" "3.110.0" - "@aws-sdk/node-http-handler" "3.110.0" - "@aws-sdk/protocol-http" "3.110.0" - "@aws-sdk/smithy-client" "3.110.0" - "@aws-sdk/types" "3.110.0" - "@aws-sdk/url-parser" "3.110.0" + "@aws-sdk/client-sts" "3.131.0" + "@aws-sdk/config-resolver" "3.130.0" + "@aws-sdk/credential-provider-node" "3.131.0" + "@aws-sdk/fetch-http-handler" "3.131.0" + "@aws-sdk/hash-node" "3.127.0" + "@aws-sdk/invalid-dependency" "3.127.0" + "@aws-sdk/middleware-content-length" "3.127.0" + "@aws-sdk/middleware-host-header" "3.127.0" + "@aws-sdk/middleware-logger" "3.127.0" + "@aws-sdk/middleware-recursion-detection" "3.127.0" + "@aws-sdk/middleware-retry" "3.127.0" + "@aws-sdk/middleware-serde" "3.127.0" + "@aws-sdk/middleware-signing" "3.130.0" + "@aws-sdk/middleware-stack" "3.127.0" + "@aws-sdk/middleware-user-agent" "3.127.0" + "@aws-sdk/node-config-provider" "3.127.0" + "@aws-sdk/node-http-handler" "3.127.0" + "@aws-sdk/protocol-http" "3.127.0" + "@aws-sdk/smithy-client" "3.127.0" + "@aws-sdk/types" "3.127.0" + "@aws-sdk/url-parser" "3.127.0" "@aws-sdk/util-base64-browser" "3.109.0" "@aws-sdk/util-base64-node" "3.55.0" "@aws-sdk/util-body-length-browser" "3.55.0" "@aws-sdk/util-body-length-node" "3.55.0" - "@aws-sdk/util-defaults-mode-browser" "3.110.0" - "@aws-sdk/util-defaults-mode-node" "3.110.0" - "@aws-sdk/util-user-agent-browser" "3.110.0" - "@aws-sdk/util-user-agent-node" "3.110.0" + "@aws-sdk/util-defaults-mode-browser" "3.127.0" + "@aws-sdk/util-defaults-mode-node" "3.130.0" + "@aws-sdk/util-user-agent-browser" "3.127.0" + "@aws-sdk/util-user-agent-node" "3.127.0" "@aws-sdk/util-utf8-browser" "3.109.0" "@aws-sdk/util-utf8-node" "3.109.0" - "@aws-sdk/util-waiter" "3.110.0" + "@aws-sdk/util-waiter" "3.127.0" entities "2.2.0" fast-xml-parser "3.19.0" tslib "^2.3.1" uuid "^8.3.2" "@aws-sdk/client-cloudwatch-logs@^3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.110.0.tgz#567d8925bedf5d11cb060831ef17ab97b25b18ae" - integrity sha512-GwGd60OReAF2W0tIAfmFT0KchF/wnU+AV8ZhepkCXp4uZtey8lTNDvnFJvZ00853NjtWv66Xr0URAqA9zNgoYA== + version "3.131.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.131.0.tgz#fe68ad8eed8689d2867e85aba6f9df721df578ff" + integrity sha512-uxB4BzFVjv2UFhufY3alDbTYh8NeN0V6okSjH2M5Oi/4XUbLnyWQrziHKFXMxgW1H5ki9cT/paSY5v89mbjUnQ== dependencies: "@aws-crypto/sha256-browser" "2.0.0" "@aws-crypto/sha256-js" "2.0.0" - "@aws-sdk/client-sts" "3.110.0" - "@aws-sdk/config-resolver" "3.110.0" - "@aws-sdk/credential-provider-node" "3.110.0" - "@aws-sdk/fetch-http-handler" "3.110.0" - "@aws-sdk/hash-node" "3.110.0" - "@aws-sdk/invalid-dependency" "3.110.0" - "@aws-sdk/middleware-content-length" "3.110.0" - "@aws-sdk/middleware-host-header" "3.110.0" - "@aws-sdk/middleware-logger" "3.110.0" - "@aws-sdk/middleware-recursion-detection" "3.110.0" - "@aws-sdk/middleware-retry" "3.110.0" - "@aws-sdk/middleware-serde" "3.110.0" - "@aws-sdk/middleware-signing" "3.110.0" - "@aws-sdk/middleware-stack" "3.110.0" - "@aws-sdk/middleware-user-agent" "3.110.0" - "@aws-sdk/node-config-provider" "3.110.0" - "@aws-sdk/node-http-handler" "3.110.0" - "@aws-sdk/protocol-http" "3.110.0" - "@aws-sdk/smithy-client" "3.110.0" - "@aws-sdk/types" "3.110.0" - "@aws-sdk/url-parser" "3.110.0" + "@aws-sdk/client-sts" "3.131.0" + "@aws-sdk/config-resolver" "3.130.0" + "@aws-sdk/credential-provider-node" "3.131.0" + "@aws-sdk/fetch-http-handler" "3.131.0" + "@aws-sdk/hash-node" "3.127.0" + "@aws-sdk/invalid-dependency" "3.127.0" + "@aws-sdk/middleware-content-length" "3.127.0" + "@aws-sdk/middleware-host-header" "3.127.0" + "@aws-sdk/middleware-logger" "3.127.0" + "@aws-sdk/middleware-recursion-detection" "3.127.0" + "@aws-sdk/middleware-retry" "3.127.0" + "@aws-sdk/middleware-serde" "3.127.0" + "@aws-sdk/middleware-signing" "3.130.0" + "@aws-sdk/middleware-stack" "3.127.0" + "@aws-sdk/middleware-user-agent" "3.127.0" + "@aws-sdk/node-config-provider" "3.127.0" + "@aws-sdk/node-http-handler" "3.127.0" + "@aws-sdk/protocol-http" "3.127.0" + "@aws-sdk/smithy-client" "3.127.0" + "@aws-sdk/types" "3.127.0" + "@aws-sdk/url-parser" "3.127.0" "@aws-sdk/util-base64-browser" "3.109.0" "@aws-sdk/util-base64-node" "3.55.0" "@aws-sdk/util-body-length-browser" "3.55.0" "@aws-sdk/util-body-length-node" "3.55.0" - "@aws-sdk/util-defaults-mode-browser" "3.110.0" - "@aws-sdk/util-defaults-mode-node" "3.110.0" - "@aws-sdk/util-user-agent-browser" "3.110.0" - "@aws-sdk/util-user-agent-node" "3.110.0" + "@aws-sdk/util-defaults-mode-browser" "3.127.0" + "@aws-sdk/util-defaults-mode-node" "3.130.0" + "@aws-sdk/util-user-agent-browser" "3.127.0" + "@aws-sdk/util-user-agent-node" "3.127.0" "@aws-sdk/util-utf8-browser" "3.109.0" "@aws-sdk/util-utf8-node" "3.109.0" tslib "^2.3.1" "@aws-sdk/client-secrets-manager@^3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.110.0.tgz#862916f5fd6c79884e19b4865f56eac9829da895" - integrity sha512-pIP0ozGiXf8cMiwHWm6+l+Bc/pZ154iSz/xKkqxfd1JXUDl1fnbe0caCBtWeTaNFhazW6nEAQc9KdDOgj09VWw== + version "3.131.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.131.0.tgz#8d120a9105a7f147e44b344add5115777003c45e" + integrity sha512-ZYfOdfIgxbjmAenJrhiZzWc2tbIMoZi3luuOoaDWBXnyEAsZtBZ9zdSwv2aRylVdv4Zb3o2XWvsjmgjcT40Xcg== dependencies: "@aws-crypto/sha256-browser" "2.0.0" "@aws-crypto/sha256-js" "2.0.0" - "@aws-sdk/client-sts" "3.110.0" - "@aws-sdk/config-resolver" "3.110.0" - "@aws-sdk/credential-provider-node" "3.110.0" - "@aws-sdk/fetch-http-handler" "3.110.0" - "@aws-sdk/hash-node" "3.110.0" - "@aws-sdk/invalid-dependency" "3.110.0" - "@aws-sdk/middleware-content-length" "3.110.0" - "@aws-sdk/middleware-host-header" "3.110.0" - "@aws-sdk/middleware-logger" "3.110.0" - "@aws-sdk/middleware-recursion-detection" "3.110.0" - "@aws-sdk/middleware-retry" "3.110.0" - "@aws-sdk/middleware-serde" "3.110.0" - "@aws-sdk/middleware-signing" "3.110.0" - "@aws-sdk/middleware-stack" "3.110.0" - "@aws-sdk/middleware-user-agent" "3.110.0" - "@aws-sdk/node-config-provider" "3.110.0" - "@aws-sdk/node-http-handler" "3.110.0" - "@aws-sdk/protocol-http" "3.110.0" - "@aws-sdk/smithy-client" "3.110.0" - "@aws-sdk/types" "3.110.0" - "@aws-sdk/url-parser" "3.110.0" + "@aws-sdk/client-sts" "3.131.0" + "@aws-sdk/config-resolver" "3.130.0" + "@aws-sdk/credential-provider-node" "3.131.0" + "@aws-sdk/fetch-http-handler" "3.131.0" + "@aws-sdk/hash-node" "3.127.0" + "@aws-sdk/invalid-dependency" "3.127.0" + "@aws-sdk/middleware-content-length" "3.127.0" + "@aws-sdk/middleware-host-header" "3.127.0" + "@aws-sdk/middleware-logger" "3.127.0" + "@aws-sdk/middleware-recursion-detection" "3.127.0" + "@aws-sdk/middleware-retry" "3.127.0" + "@aws-sdk/middleware-serde" "3.127.0" + "@aws-sdk/middleware-signing" "3.130.0" + "@aws-sdk/middleware-stack" "3.127.0" + "@aws-sdk/middleware-user-agent" "3.127.0" + "@aws-sdk/node-config-provider" "3.127.0" + "@aws-sdk/node-http-handler" "3.127.0" + "@aws-sdk/protocol-http" "3.127.0" + "@aws-sdk/smithy-client" "3.127.0" + "@aws-sdk/types" "3.127.0" + "@aws-sdk/url-parser" "3.127.0" "@aws-sdk/util-base64-browser" "3.109.0" "@aws-sdk/util-base64-node" "3.55.0" "@aws-sdk/util-body-length-browser" "3.55.0" "@aws-sdk/util-body-length-node" "3.55.0" - "@aws-sdk/util-defaults-mode-browser" "3.110.0" - "@aws-sdk/util-defaults-mode-node" "3.110.0" - "@aws-sdk/util-user-agent-browser" "3.110.0" - "@aws-sdk/util-user-agent-node" "3.110.0" + "@aws-sdk/util-defaults-mode-browser" "3.127.0" + "@aws-sdk/util-defaults-mode-node" "3.130.0" + "@aws-sdk/util-user-agent-browser" "3.127.0" + "@aws-sdk/util-user-agent-node" "3.127.0" "@aws-sdk/util-utf8-browser" "3.109.0" "@aws-sdk/util-utf8-node" "3.109.0" tslib "^2.3.1" uuid "^8.3.2" "@aws-sdk/client-ssm@^3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-ssm/-/client-ssm-3.110.0.tgz#507489821f676a1540cb4629505a1c76ea93008f" - integrity sha512-QV7lgbnN53+Y2oR98OR/KaB6dvQwFdqyNFFm8h8Qgi9mHS+xLAp6sj8B66d6jJ4318IUq2bfKfAR+wDyFFTTKw== + version "3.131.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-ssm/-/client-ssm-3.131.0.tgz#abecd46bdd444a2a9c8f29bd5c8df8ef9eb5d58a" + integrity sha512-cV0Whc1yBgyGONdVc3tVzyQp3Cj6fAdAoAkKMGLF8wXrjN0MUlLVMUqEh4F0ybkc99oIiFILOGAiNN9k+B6acA== dependencies: "@aws-crypto/sha256-browser" "2.0.0" "@aws-crypto/sha256-js" "2.0.0" - "@aws-sdk/client-sts" "3.110.0" - "@aws-sdk/config-resolver" "3.110.0" - "@aws-sdk/credential-provider-node" "3.110.0" - "@aws-sdk/fetch-http-handler" "3.110.0" - "@aws-sdk/hash-node" "3.110.0" - "@aws-sdk/invalid-dependency" "3.110.0" - "@aws-sdk/middleware-content-length" "3.110.0" - "@aws-sdk/middleware-host-header" "3.110.0" - "@aws-sdk/middleware-logger" "3.110.0" - "@aws-sdk/middleware-recursion-detection" "3.110.0" - "@aws-sdk/middleware-retry" "3.110.0" - "@aws-sdk/middleware-serde" "3.110.0" - "@aws-sdk/middleware-signing" "3.110.0" - "@aws-sdk/middleware-stack" "3.110.0" - "@aws-sdk/middleware-user-agent" "3.110.0" - "@aws-sdk/node-config-provider" "3.110.0" - "@aws-sdk/node-http-handler" "3.110.0" - "@aws-sdk/protocol-http" "3.110.0" - "@aws-sdk/smithy-client" "3.110.0" - "@aws-sdk/types" "3.110.0" - "@aws-sdk/url-parser" "3.110.0" + "@aws-sdk/client-sts" "3.131.0" + "@aws-sdk/config-resolver" "3.130.0" + "@aws-sdk/credential-provider-node" "3.131.0" + "@aws-sdk/fetch-http-handler" "3.131.0" + "@aws-sdk/hash-node" "3.127.0" + "@aws-sdk/invalid-dependency" "3.127.0" + "@aws-sdk/middleware-content-length" "3.127.0" + "@aws-sdk/middleware-host-header" "3.127.0" + "@aws-sdk/middleware-logger" "3.127.0" + "@aws-sdk/middleware-recursion-detection" "3.127.0" + "@aws-sdk/middleware-retry" "3.127.0" + "@aws-sdk/middleware-serde" "3.127.0" + "@aws-sdk/middleware-signing" "3.130.0" + "@aws-sdk/middleware-stack" "3.127.0" + "@aws-sdk/middleware-user-agent" "3.127.0" + "@aws-sdk/node-config-provider" "3.127.0" + "@aws-sdk/node-http-handler" "3.127.0" + "@aws-sdk/protocol-http" "3.127.0" + "@aws-sdk/smithy-client" "3.127.0" + "@aws-sdk/types" "3.127.0" + "@aws-sdk/url-parser" "3.127.0" "@aws-sdk/util-base64-browser" "3.109.0" "@aws-sdk/util-base64-node" "3.55.0" "@aws-sdk/util-body-length-browser" "3.55.0" "@aws-sdk/util-body-length-node" "3.55.0" - "@aws-sdk/util-defaults-mode-browser" "3.110.0" - "@aws-sdk/util-defaults-mode-node" "3.110.0" - "@aws-sdk/util-user-agent-browser" "3.110.0" - "@aws-sdk/util-user-agent-node" "3.110.0" + "@aws-sdk/util-defaults-mode-browser" "3.127.0" + "@aws-sdk/util-defaults-mode-node" "3.130.0" + "@aws-sdk/util-user-agent-browser" "3.127.0" + "@aws-sdk/util-user-agent-node" "3.127.0" "@aws-sdk/util-utf8-browser" "3.109.0" "@aws-sdk/util-utf8-node" "3.109.0" - "@aws-sdk/util-waiter" "3.110.0" + "@aws-sdk/util-waiter" "3.127.0" tslib "^2.3.1" uuid "^8.3.2" -"@aws-sdk/client-sso@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.110.0.tgz#3945b1145bd780653fd7acb1d8aefa7fd309938f" - integrity sha512-Mzj8bfHaB+Ajghf0iMDdbpzL6jY+GbRDKATpmUOAswBDy72JifoBq7qUAV+NwhjUdF+jUzXkdCAAIaai2kglrg== +"@aws-sdk/client-sso@3.131.0": + version "3.131.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.131.0.tgz#2a1177854092a64e976720a7e69bbab0d72e0855" + integrity sha512-6fbjqLdVZF7mvGpHjWX5YsqBE/99MilNtGUFlwuf4/KnmYy49V16A6Dltnd43Hu6HVGxJ8caH9nCkIdNp3YZcQ== dependencies: "@aws-crypto/sha256-browser" "2.0.0" "@aws-crypto/sha256-js" "2.0.0" - "@aws-sdk/config-resolver" "3.110.0" - "@aws-sdk/fetch-http-handler" "3.110.0" - "@aws-sdk/hash-node" "3.110.0" - "@aws-sdk/invalid-dependency" "3.110.0" - "@aws-sdk/middleware-content-length" "3.110.0" - "@aws-sdk/middleware-host-header" "3.110.0" - "@aws-sdk/middleware-logger" "3.110.0" - "@aws-sdk/middleware-recursion-detection" "3.110.0" - "@aws-sdk/middleware-retry" "3.110.0" - "@aws-sdk/middleware-serde" "3.110.0" - "@aws-sdk/middleware-stack" "3.110.0" - "@aws-sdk/middleware-user-agent" "3.110.0" - "@aws-sdk/node-config-provider" "3.110.0" - "@aws-sdk/node-http-handler" "3.110.0" - "@aws-sdk/protocol-http" "3.110.0" - "@aws-sdk/smithy-client" "3.110.0" - "@aws-sdk/types" "3.110.0" - "@aws-sdk/url-parser" "3.110.0" + "@aws-sdk/config-resolver" "3.130.0" + "@aws-sdk/fetch-http-handler" "3.131.0" + "@aws-sdk/hash-node" "3.127.0" + "@aws-sdk/invalid-dependency" "3.127.0" + "@aws-sdk/middleware-content-length" "3.127.0" + "@aws-sdk/middleware-host-header" "3.127.0" + "@aws-sdk/middleware-logger" "3.127.0" + "@aws-sdk/middleware-recursion-detection" "3.127.0" + "@aws-sdk/middleware-retry" "3.127.0" + "@aws-sdk/middleware-serde" "3.127.0" + "@aws-sdk/middleware-stack" "3.127.0" + "@aws-sdk/middleware-user-agent" "3.127.0" + "@aws-sdk/node-config-provider" "3.127.0" + "@aws-sdk/node-http-handler" "3.127.0" + "@aws-sdk/protocol-http" "3.127.0" + "@aws-sdk/smithy-client" "3.127.0" + "@aws-sdk/types" "3.127.0" + "@aws-sdk/url-parser" "3.127.0" "@aws-sdk/util-base64-browser" "3.109.0" "@aws-sdk/util-base64-node" "3.55.0" "@aws-sdk/util-body-length-browser" "3.55.0" "@aws-sdk/util-body-length-node" "3.55.0" - "@aws-sdk/util-defaults-mode-browser" "3.110.0" - "@aws-sdk/util-defaults-mode-node" "3.110.0" - "@aws-sdk/util-user-agent-browser" "3.110.0" - "@aws-sdk/util-user-agent-node" "3.110.0" + "@aws-sdk/util-defaults-mode-browser" "3.127.0" + "@aws-sdk/util-defaults-mode-node" "3.130.0" + "@aws-sdk/util-user-agent-browser" "3.127.0" + "@aws-sdk/util-user-agent-node" "3.127.0" "@aws-sdk/util-utf8-browser" "3.109.0" "@aws-sdk/util-utf8-node" "3.109.0" tslib "^2.3.1" -"@aws-sdk/client-sts@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.110.0.tgz#cab709b17af4a6ce4b79c154ae2c22d98d84fc46" - integrity sha512-BJD0fxCoqqL7eA/tRRj7z5n4/P8tIZZgOOWJqd6euf6t90uPssz/MJw01bFJBljMl4BtMGvLXHKkyzWtVezI0w== +"@aws-sdk/client-sts@3.131.0": + version "3.131.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.131.0.tgz#5867be8c1e9cf71c9abad90e3a67c8d10a5aa89b" + integrity sha512-D9GAnF8n3VwFhaE+jxXH035ZZ24WxpY36DUxszCRwXbA7qFazY1BTs1WoKFr8tDH4/iUUqCXd8NuA1l4RiwnqQ== dependencies: "@aws-crypto/sha256-browser" "2.0.0" "@aws-crypto/sha256-js" "2.0.0" - "@aws-sdk/config-resolver" "3.110.0" - "@aws-sdk/credential-provider-node" "3.110.0" - "@aws-sdk/fetch-http-handler" "3.110.0" - "@aws-sdk/hash-node" "3.110.0" - "@aws-sdk/invalid-dependency" "3.110.0" - "@aws-sdk/middleware-content-length" "3.110.0" - "@aws-sdk/middleware-host-header" "3.110.0" - "@aws-sdk/middleware-logger" "3.110.0" - "@aws-sdk/middleware-recursion-detection" "3.110.0" - "@aws-sdk/middleware-retry" "3.110.0" - "@aws-sdk/middleware-sdk-sts" "3.110.0" - "@aws-sdk/middleware-serde" "3.110.0" - "@aws-sdk/middleware-signing" "3.110.0" - "@aws-sdk/middleware-stack" "3.110.0" - "@aws-sdk/middleware-user-agent" "3.110.0" - "@aws-sdk/node-config-provider" "3.110.0" - "@aws-sdk/node-http-handler" "3.110.0" - "@aws-sdk/protocol-http" "3.110.0" - "@aws-sdk/smithy-client" "3.110.0" - "@aws-sdk/types" "3.110.0" - "@aws-sdk/url-parser" "3.110.0" + "@aws-sdk/config-resolver" "3.130.0" + "@aws-sdk/credential-provider-node" "3.131.0" + "@aws-sdk/fetch-http-handler" "3.131.0" + "@aws-sdk/hash-node" "3.127.0" + "@aws-sdk/invalid-dependency" "3.127.0" + "@aws-sdk/middleware-content-length" "3.127.0" + "@aws-sdk/middleware-host-header" "3.127.0" + "@aws-sdk/middleware-logger" "3.127.0" + "@aws-sdk/middleware-recursion-detection" "3.127.0" + "@aws-sdk/middleware-retry" "3.127.0" + "@aws-sdk/middleware-sdk-sts" "3.130.0" + "@aws-sdk/middleware-serde" "3.127.0" + "@aws-sdk/middleware-signing" "3.130.0" + "@aws-sdk/middleware-stack" "3.127.0" + "@aws-sdk/middleware-user-agent" "3.127.0" + "@aws-sdk/node-config-provider" "3.127.0" + "@aws-sdk/node-http-handler" "3.127.0" + "@aws-sdk/protocol-http" "3.127.0" + "@aws-sdk/smithy-client" "3.127.0" + "@aws-sdk/types" "3.127.0" + "@aws-sdk/url-parser" "3.127.0" "@aws-sdk/util-base64-browser" "3.109.0" "@aws-sdk/util-base64-node" "3.55.0" "@aws-sdk/util-body-length-browser" "3.55.0" "@aws-sdk/util-body-length-node" "3.55.0" - "@aws-sdk/util-defaults-mode-browser" "3.110.0" - "@aws-sdk/util-defaults-mode-node" "3.110.0" - "@aws-sdk/util-user-agent-browser" "3.110.0" - "@aws-sdk/util-user-agent-node" "3.110.0" + "@aws-sdk/util-defaults-mode-browser" "3.127.0" + "@aws-sdk/util-defaults-mode-node" "3.130.0" + "@aws-sdk/util-user-agent-browser" "3.127.0" + "@aws-sdk/util-user-agent-node" "3.127.0" "@aws-sdk/util-utf8-browser" "3.109.0" "@aws-sdk/util-utf8-node" "3.109.0" entities "2.2.0" fast-xml-parser "3.19.0" tslib "^2.3.1" -"@aws-sdk/config-resolver@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/config-resolver/-/config-resolver-3.110.0.tgz#93de506934aa06dd973e5e3dab95b629697372f9" - integrity sha512-7VvtKy4CL63BAktQ2vgsjhWDSXpkXO5YdiI56LQnHztrvSuJBBaxJ7R1p/k0b2tEUhYKUziAIW8EKE/7EGPR4g== +"@aws-sdk/config-resolver@3.130.0": + version "3.130.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/config-resolver/-/config-resolver-3.130.0.tgz#ba0fa915fa5613e87051a9826531e59cab4387b1" + integrity sha512-7dkCHHI9kRcHW6YNr9/2Ub6XkvU9Fu6H/BnlKbaKlDR8jq7QpaFhPhctOVi5D/NDpxJgALifexFne0dvo3piTw== dependencies: - "@aws-sdk/signature-v4" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/signature-v4" "3.130.0" + "@aws-sdk/types" "3.127.0" "@aws-sdk/util-config-provider" "3.109.0" - "@aws-sdk/util-middleware" "3.110.0" + "@aws-sdk/util-middleware" "3.127.0" tslib "^2.3.1" -"@aws-sdk/credential-provider-env@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.110.0.tgz#c95552fc0a3ae857ced0e171e53082cf3c84bc74" - integrity sha512-oFU3IYk/Bl5tdsz1qigtm3I25a9cvXPqlE8VjYjxVDdLujF5zd/4HLbhP4GQWhpEwZmM1ijcSNfLcyywVevTZg== +"@aws-sdk/credential-provider-env@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.127.0.tgz#06eb67461f7df8feb14abd3b459f682544d78e43" + integrity sha512-Ig7XhUikRBlnRTYT5JBGzWfYZp68X5vkFVIFCmsHHt/qVy0Nz9raZpmDHicdS1u67yxDkWgCPn/bNevWnM0GFg== dependencies: - "@aws-sdk/property-provider" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/property-provider" "3.127.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/credential-provider-imds@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.110.0.tgz#ba4f178ccab65c5760bce38e7f694584dad3fd74" - integrity sha512-atl+7/dAB+8fG9XI2fYyCgXKYDbOzot65VAwis+14bOEUCVp7PCJifBEZ/L8GEq564p+Fa2p1IpV0wuQXxqFUQ== +"@aws-sdk/credential-provider-imds@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.127.0.tgz#1fc7b40bf21adcc2a897e47b72796bd8ebcc7d86" + integrity sha512-I6KlIBBzmJn/U1KikiC50PK3SspT9G5lkVLBaW5a6YfOcijqVTXfAN3kYzqhfeS0j4IgfJEwKVsjsZfmprJO5A== dependencies: - "@aws-sdk/node-config-provider" "3.110.0" - "@aws-sdk/property-provider" "3.110.0" - "@aws-sdk/types" "3.110.0" - "@aws-sdk/url-parser" "3.110.0" + "@aws-sdk/node-config-provider" "3.127.0" + "@aws-sdk/property-provider" "3.127.0" + "@aws-sdk/types" "3.127.0" + "@aws-sdk/url-parser" "3.127.0" tslib "^2.3.1" -"@aws-sdk/credential-provider-ini@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.110.0.tgz#88e3c00da31634f219b5d7036a150d5819210836" - integrity sha512-DVbCWGnvXBvxdf0XGB0nVQjZNwEJc7OhhBFUfF/bP2LXwyZX7n2w4NGNpi2fLnwrgbySoPNbBpp8X3NhVvK14g== - dependencies: - "@aws-sdk/credential-provider-env" "3.110.0" - "@aws-sdk/credential-provider-imds" "3.110.0" - "@aws-sdk/credential-provider-sso" "3.110.0" - "@aws-sdk/credential-provider-web-identity" "3.110.0" - "@aws-sdk/property-provider" "3.110.0" - "@aws-sdk/shared-ini-file-loader" "3.110.0" - "@aws-sdk/types" "3.110.0" +"@aws-sdk/credential-provider-ini@3.131.0": + version "3.131.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.131.0.tgz#fa22aebeb65804b8ec1c4a7167292a80ea7d8131" + integrity sha512-0hA2ZwRUDmG5Wp/1t5BLvju2kZft1T3b3KC068ZY3t1+t/O46R6R9vINKEodohKTbfmGddu+aGY58Ai+N7O5Xw== + dependencies: + "@aws-sdk/credential-provider-env" "3.127.0" + "@aws-sdk/credential-provider-imds" "3.127.0" + "@aws-sdk/credential-provider-sso" "3.131.0" + "@aws-sdk/credential-provider-web-identity" "3.127.0" + "@aws-sdk/property-provider" "3.127.0" + "@aws-sdk/shared-ini-file-loader" "3.127.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/credential-provider-node@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.110.0.tgz#263a8f7f0bac1645c1ef09ff94bbb7efd5163042" - integrity sha512-6AE97H6KDwOYTRjzP7dIyEg4jUd33ZLehgmtaBbJ1GhchtU3L8W0+Mh7ICpwKX/cYMJcKJKzT27BwYVWtOtCDA== - dependencies: - "@aws-sdk/credential-provider-env" "3.110.0" - "@aws-sdk/credential-provider-imds" "3.110.0" - "@aws-sdk/credential-provider-ini" "3.110.0" - "@aws-sdk/credential-provider-process" "3.110.0" - "@aws-sdk/credential-provider-sso" "3.110.0" - "@aws-sdk/credential-provider-web-identity" "3.110.0" - "@aws-sdk/property-provider" "3.110.0" - "@aws-sdk/shared-ini-file-loader" "3.110.0" - "@aws-sdk/types" "3.110.0" +"@aws-sdk/credential-provider-node@3.131.0": + version "3.131.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.131.0.tgz#df76ef73c90320121a9d63d3c85e1579d58b9125" + integrity sha512-nVQ6P91nd7i/G+iEnKWVwRRsQZIdY0qfza2+v70fOphjv0vzgDN7Xbn1GiYQVbxBiuxMSjQqg1r/p9PdRmt6QA== + dependencies: + "@aws-sdk/credential-provider-env" "3.127.0" + "@aws-sdk/credential-provider-imds" "3.127.0" + "@aws-sdk/credential-provider-ini" "3.131.0" + "@aws-sdk/credential-provider-process" "3.127.0" + "@aws-sdk/credential-provider-sso" "3.131.0" + "@aws-sdk/credential-provider-web-identity" "3.127.0" + "@aws-sdk/property-provider" "3.127.0" + "@aws-sdk/shared-ini-file-loader" "3.127.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/credential-provider-process@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.110.0.tgz#1f4543edd532beb4b690e6f3aaf74d00af3be5c4" - integrity sha512-JJcZePvRTfQHYj/+EEY13yItnZH/e8exlARFUjN0L13UrgHpOJtDQBa+YBHXo6MbTFQh+re25z2kzc+zOYSMNQ== +"@aws-sdk/credential-provider-process@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.127.0.tgz#6046a20013a3edd58b631668ed1d73dfd63a931c" + integrity sha512-6v0m2lqkO9J5fNlTl+HjriQNIdfg8mjVST544+5y9EnC/FVmTnIz64vfHveWdNkP/fehFx7wTimNENtoSqCn3A== dependencies: - "@aws-sdk/property-provider" "3.110.0" - "@aws-sdk/shared-ini-file-loader" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/property-provider" "3.127.0" + "@aws-sdk/shared-ini-file-loader" "3.127.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/credential-provider-sso@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.110.0.tgz#2a9c21eb4c7033d465c0c42f91af648a7fae1a7c" - integrity sha512-fXV9mc/2U2M5pP5E61uBSFdQXIMgNO4yebitkqNiseI3lg5dJVkYGfiWlvw6qGo6BNxKiEmvJD5Mu6/laYIvbw== +"@aws-sdk/credential-provider-sso@3.131.0": + version "3.131.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.131.0.tgz#263694373bb9ee87d622d32a3e79d4e0ff4e9787" + integrity sha512-3LVan87e6NqnwUrpmjM5dbx8LbZyGG7Gdzf68YL0tZFptCFh1mR/kTJCToGX/hm7Jf3SRU3wtUWJ6G72yP72Sw== dependencies: - "@aws-sdk/client-sso" "3.110.0" - "@aws-sdk/property-provider" "3.110.0" - "@aws-sdk/shared-ini-file-loader" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/client-sso" "3.131.0" + "@aws-sdk/property-provider" "3.127.0" + "@aws-sdk/shared-ini-file-loader" "3.127.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/credential-provider-web-identity@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.110.0.tgz#236e192826c3856e1f2b8eaa1ad126affd641082" - integrity sha512-e4e5u7v3fsUFZsMcFMhMy1NdJBQpunYcLwpYlszm3OEICwTTekQ+hVvnVRd134doHvzepE4yp9sAop0Cj+IRVQ== +"@aws-sdk/credential-provider-web-identity@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.127.0.tgz#a56c390bf0148f20573abd022930b28df345043a" + integrity sha512-85ahDZnLYB3dqkW+cQ0bWt+NVqOoxomTrJoq3IC2q6muebeFrJ0pyf0JEW/RNRzBiUvvsZujzGdWifzWyQKfVg== dependencies: - "@aws-sdk/property-provider" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/property-provider" "3.127.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/fetch-http-handler@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.110.0.tgz#0b6d552659b779c49ba0f99c78a57755864bf1b0" - integrity sha512-vk+K4GeCZL2J2rtvKO+T0Q7i3MDpEGZBMg5K2tj9sMcEQwty0BF0aFnP7Eu2l4/Zif2z1mWuUFM2WcZI6DVnbw== +"@aws-sdk/fetch-http-handler@3.131.0": + version "3.131.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.131.0.tgz#426721ba3c4e7687a6c12ce10bdc661900325815" + integrity sha512-eNxmPZQX2IUeBGWHNC7eNTekWn9VIPLYEMKJbKYUBJryxuTJ7TtLeyEK5oakUjMwP1AUvWT+CV7C+8L7uG1omQ== dependencies: - "@aws-sdk/protocol-http" "3.110.0" - "@aws-sdk/querystring-builder" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/protocol-http" "3.127.0" + "@aws-sdk/querystring-builder" "3.127.0" + "@aws-sdk/types" "3.127.0" "@aws-sdk/util-base64-browser" "3.109.0" tslib "^2.3.1" -"@aws-sdk/hash-node@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/hash-node/-/hash-node-3.110.0.tgz#b225bfd16596b6485c1c610e8fef8de1e40931c4" - integrity sha512-wakl+kP2O8wTGYiQ3InZy+CVfGrIpFfq9fo4zif9PZac0BbUbguUU1dkY34uZiaf+4o2/9MoDYrHU2HYeXKxWw== +"@aws-sdk/hash-node@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/hash-node/-/hash-node-3.127.0.tgz#2fbbeb509a515e6a5cfd6846c02cc1967961a40b" + integrity sha512-wx7DKlXdKebH4JcMsOevdsm2oDNMVm36kuMm0XWRIrFWQ/oq7OquDpEMJzWvGqWF/IfFUpb7FhAWZZpALwlcwA== dependencies: - "@aws-sdk/types" "3.110.0" + "@aws-sdk/types" "3.127.0" "@aws-sdk/util-buffer-from" "3.55.0" tslib "^2.3.1" -"@aws-sdk/invalid-dependency@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/invalid-dependency/-/invalid-dependency-3.110.0.tgz#9104dfd40e35b6737dc7ab01f4e79c76c1109c44" - integrity sha512-O8J1InmtJkoiUMbQDtxBfOzgigBp9iSVsNXQrhs2qHh3826cJOfE7NGT3u+NMw73Pk5j2cfmOh1+7k/76IqxOg== +"@aws-sdk/invalid-dependency@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/invalid-dependency/-/invalid-dependency-3.127.0.tgz#3a99603e1969f67278495b827243e9a391b8cfc4" + integrity sha512-bxvmtmJ6gIRfOHvh1jAPZBH2mzppEblPjEOFo4mOzXz4U3qPIxeuukCjboMnGK9QEpV2wObWcYYld0vxoRrfiA== dependencies: - "@aws-sdk/types" "3.110.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" "@aws-sdk/is-array-buffer@3.55.0": @@ -1384,204 +445,199 @@ dependencies: tslib "^2.3.1" -"@aws-sdk/middleware-content-length@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-content-length/-/middleware-content-length-3.110.0.tgz#f4dc3508952c5fae9740f172d3b76135dd4dba37" - integrity sha512-hKU+zdqfAJQg22LXMVu/z35nNIHrVAKpVKPe9+WYVdL/Z7JKUPK7QymqKGOyDuDbzW6OxyulC1zKGEX12zGmdA== +"@aws-sdk/middleware-content-length@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-content-length/-/middleware-content-length-3.127.0.tgz#662c1971fdb2dd7d34a9945ebd8da52578900434" + integrity sha512-AFmMaIEW3Rzg0TaKB9l/RENLowd7ZEEOpm0trYw1CgUUORWW/ydCsDT7pekPlC25CPbhUmWXCSA4xPFSYOVnDw== dependencies: - "@aws-sdk/protocol-http" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/protocol-http" "3.127.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/middleware-host-header@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.110.0.tgz#a28115e2797b86c2fb583000593b723a51313b92" - integrity sha512-/Cknn1vL2LTlclI0MX2RzmtdPlCJ5palCRXxm/mod1oHwg4oNTKRlUX3LUD+L8g7JuJ4h053Ch9KS/A0vanE5Q== +"@aws-sdk/middleware-host-header@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.127.0.tgz#679f685bd8b4f221ed2c11e90b381d6904034ef9" + integrity sha512-e2gTLJb5lYP9lRV7hN3rKY2l4jv8OygOoHElZJ3Z8KPZskjHelYPcQ8XbdfhSXXxC3vc/0QqN0ResFt3W3Pplg== dependencies: - "@aws-sdk/protocol-http" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/protocol-http" "3.127.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/middleware-logger@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.110.0.tgz#69eb0b2d0d9833f6fdbe33eb1876254e7cee53ec" - integrity sha512-+pz+a+8dfTnzLj79nHrv3aONMp/N36/erMd+7JXeR84QEosVLrFBUwKA8x5x6O3s1iBbQzRKMYEIuja9xn1BPA== +"@aws-sdk/middleware-logger@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.127.0.tgz#b62fd148888f418bd74b0c9d76b80588224ee98f" + integrity sha512-jMNLcZB/ECA7OfkNBLNeAlrLRehyfnUeNQJHW3kcxs9h1+6VxaF6wY+WKozszLI7/3OBzQrFHBQCfRZV7ykSLg== dependencies: - "@aws-sdk/types" "3.110.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/middleware-recursion-detection@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.110.0.tgz#8daa2bc9f62cbf499d9c615726cf2a51f46e70ff" - integrity sha512-Wav782zd7bcd1e6txRob76CDOdVOaUQ8HXoywiIm/uFrEEUZvhs2mgnXjVUVCMBUehdNgnL99z420aS13JeL/Q== +"@aws-sdk/middleware-recursion-detection@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.127.0.tgz#84949efd4a05a4d00da3e9242825e3c9d715f800" + integrity sha512-tB6WX+Z1kUKTnn5h38XFrTCzoqPKjUZLUjN4Wb27/cbeSiTSKGAZcCXHOJm36Ukorl5arlybQTqGe689EU00Hw== dependencies: - "@aws-sdk/protocol-http" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/protocol-http" "3.127.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/middleware-retry@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-retry/-/middleware-retry-3.110.0.tgz#3bdbd66d06dcbddbdf684d1d81c6d5fd7746f03b" - integrity sha512-lwLAQQveCiUqymQvVYjCee6QOXw3Zqbc9yq+pxYdXbs1Cv1XMA6PeJeUU5r5KEVuSceBLyyrnl6E0R1l1om1MQ== +"@aws-sdk/middleware-retry@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-retry/-/middleware-retry-3.127.0.tgz#bcd0741ed676588101739083c6bd141d5c1911e1" + integrity sha512-ZSvg/AyGUacWnf3i8ZbyImtiCH+NyafF8uV7bITP7JkwPrG+VdNocJZOr88GRM0c1A0jfkOf7+oq+fInPwwiNA== dependencies: - "@aws-sdk/protocol-http" "3.110.0" - "@aws-sdk/service-error-classification" "3.110.0" - "@aws-sdk/types" "3.110.0" - "@aws-sdk/util-middleware" "3.110.0" + "@aws-sdk/protocol-http" "3.127.0" + "@aws-sdk/service-error-classification" "3.127.0" + "@aws-sdk/types" "3.127.0" + "@aws-sdk/util-middleware" "3.127.0" tslib "^2.3.1" uuid "^8.3.2" -"@aws-sdk/middleware-sdk-sts@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.110.0.tgz#8c1e34b72355c5e63495927a01839f210327f0c1" - integrity sha512-EjY/YFdlr5jECde6qIrTIyGBbn/34CKcQGKvmvRd31+3qaClIJLAwNuHfcVzWvCUGbAslsfvdbOpLju33pSQRA== +"@aws-sdk/middleware-sdk-sts@3.130.0": + version "3.130.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.130.0.tgz#b8dc87c25db048ae8b91962459dfaec5d5b48a8f" + integrity sha512-FDfs7+ohbhEK3eH3Dshr6JDiL8P72bp3ffeNpPBXuURFqwt4pCmjHuX3SqQR0JIJ2cl3aIdxc17rKaZJfOjtPw== dependencies: - "@aws-sdk/middleware-signing" "3.110.0" - "@aws-sdk/property-provider" "3.110.0" - "@aws-sdk/protocol-http" "3.110.0" - "@aws-sdk/signature-v4" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/middleware-signing" "3.130.0" + "@aws-sdk/property-provider" "3.127.0" + "@aws-sdk/protocol-http" "3.127.0" + "@aws-sdk/signature-v4" "3.130.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/middleware-serde@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-serde/-/middleware-serde-3.110.0.tgz#603dcc1f68d78e9123f9b696150374a8357de6c3" - integrity sha512-brVupxgEAmcZ9cZvdHEH8zncjvGKIiud8pOe4fiimp5NpHmjBLew4jUbnOKNZNAjaidcKUtz//cxtutD6yXEww== +"@aws-sdk/middleware-serde@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-serde/-/middleware-serde-3.127.0.tgz#8732d71ed0d28c43e609fcc156b1a1ac307c0d5f" + integrity sha512-xmWMYV/t9M+b9yHjqaD1noDNJJViI2QwOH7TQZ9VbbrvdVtDrFuS9Sf9He80TBCJqeHShwQN9783W1I3Pu/8kw== dependencies: - "@aws-sdk/types" "3.110.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/middleware-signing@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.110.0.tgz#8faa6acdaedb1c29614fe7ba88a74534db38f3bb" - integrity sha512-y6ZKrGYfgDlFMzWhZmoq5J1UctBgZOUvMmnU9sSeZ020IlEPiOxFMvR0Zu6TcYThp8uy3P0wyjQtGYeTl9Z/kA== +"@aws-sdk/middleware-signing@3.130.0": + version "3.130.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.130.0.tgz#10c5606cf6cd32cf9afa857b0ff32659460902a7" + integrity sha512-JePq5XLR9TfRN3RQ0d7Za/bEW5D3xgtD1FNAwHeenWALeozMuQgRPjM5RroCnL/5jY3wuvCZI7cSXeqhawWqmA== dependencies: - "@aws-sdk/property-provider" "3.110.0" - "@aws-sdk/protocol-http" "3.110.0" - "@aws-sdk/signature-v4" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/property-provider" "3.127.0" + "@aws-sdk/protocol-http" "3.127.0" + "@aws-sdk/signature-v4" "3.130.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/middleware-stack@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-stack/-/middleware-stack-3.110.0.tgz#5a531c83ec375adf9d7f1bd80b725cebf7b2f01d" - integrity sha512-iaLHw6ctOuGa9UxNueU01Xes+15dR+mqioRpUOUZ9Zx+vhXVpD7C8lnNqhRnYeFXs10/rNIzASgsIrAHTlnlIQ== +"@aws-sdk/middleware-stack@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-stack/-/middleware-stack-3.127.0.tgz#d569d964256cdd4a5afd149de325296cf19762f6" + integrity sha512-S1IoUE5o1vCmjsF5nIE8zlItNOM1UE+lhmZeigF7knXJ9+a6ewMB6POAj/s4eoi0wcn0eSnAGsqJCWMSUjOPLA== dependencies: tslib "^2.3.1" -"@aws-sdk/middleware-user-agent@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.110.0.tgz#52f32e99ecb641babcd59bb010527d5614e908f4" - integrity sha512-Y6FgiZr99DilYq6AjeaaWcNwVlSQpNGKrILzvV4Tmz03OaBIspe4KL+8EZ2YA/sAu5Lpw80vItdezqDOwGAlnQ== +"@aws-sdk/middleware-user-agent@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.127.0.tgz#f676aac4ddaba64bb12b6d69b0ed7328479cf798" + integrity sha512-CHxgswoOzdkOEoIq7Oyob3Sx/4FYUv6BhUesAX7MNshaDDsTQPbSWjw5bqZDiL/gO+X/34fvqCVVpVD2GvxW/g== dependencies: - "@aws-sdk/protocol-http" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/protocol-http" "3.127.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/node-config-provider@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/node-config-provider/-/node-config-provider-3.110.0.tgz#7d032082b85458ea4959f744d473e328be024359" - integrity sha512-46p4dCPGYctuybTQTwLpjenA1QFHeyJw/OyggGbtUJUy+833+ldnAwcPVML2aXJKUKv3APGI8vq1kaloyNku3Q== +"@aws-sdk/node-config-provider@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/node-config-provider/-/node-config-provider-3.127.0.tgz#43a460526f0c24a661264189712e0ff5475e9b45" + integrity sha512-bAHkASMhLZHT1yv2TX6OJGFV9Lc3t1gKfTMEKdXM2O2YhGfSx9A/qLeJm79oDfnILWQtSS2NicxlRDI2lYGf4g== dependencies: - "@aws-sdk/property-provider" "3.110.0" - "@aws-sdk/shared-ini-file-loader" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/property-provider" "3.127.0" + "@aws-sdk/shared-ini-file-loader" "3.127.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/node-http-handler@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/node-http-handler/-/node-http-handler-3.110.0.tgz#b29ba034558ec3cddae69860d49766a27ee73354" - integrity sha512-/rP+hY516DpP8fZhwFW5xM/ElH0w6lxw/15VvZCoY5EnOLAF5XIsJdzscWPSEW2FHCylBM4SNrKhGar14BDXhA== +"@aws-sdk/node-http-handler@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/node-http-handler/-/node-http-handler-3.127.0.tgz#81c0a34061b233027bc673f3359c36555c0688d7" + integrity sha512-pyMKvheK8eDwWLgYIRsWy8wiyhsbYYcqkZQs3Eh6upI4E8iCY7eMmhWvHYCibvsO+UjsOwa4cAMOfwnv/Z9s8A== dependencies: - "@aws-sdk/abort-controller" "3.110.0" - "@aws-sdk/protocol-http" "3.110.0" - "@aws-sdk/querystring-builder" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/abort-controller" "3.127.0" + "@aws-sdk/protocol-http" "3.127.0" + "@aws-sdk/querystring-builder" "3.127.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/property-provider@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/property-provider/-/property-provider-3.110.0.tgz#ea60c33a8e243246fc21d478ff009063825b9abd" - integrity sha512-7NkpmYeOkK3mhWBNU+/zSDqwzeaSPH1qrq4L//WV7WS/weYyE/jusQeZoOxVsuZQnQEXHt5O2hKVeUwShl12xA== +"@aws-sdk/property-provider@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/property-provider/-/property-provider-3.127.0.tgz#3b70d23354c35ea04c29c97f05cc4108c2e194ba" + integrity sha512-JxenxlTEkWfLrtJqIjaXaJzAVQbbscoCb5bNjmdud07ESLVfWRKJx2nAJdecHKYp2M5NQyqBuFhQ1ELSFYQKCA== dependencies: - "@aws-sdk/types" "3.110.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/protocol-http@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/protocol-http/-/protocol-http-3.110.0.tgz#ff3cffa5b1eb7c8564a9e9019a8842b429c7f85c" - integrity sha512-qdi2gCbJiyPyLn+afebPNp/5nVCRh1X7t7IRIFl3FHVEC+o54u/ojay/MLZ4M/+X9Fa4Zxsb0Wpp3T0xAHVDBg== +"@aws-sdk/protocol-http@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/protocol-http/-/protocol-http-3.127.0.tgz#c1d7bb20f09f9e86fd885d3effb33850b618e549" + integrity sha512-UG83PVuKX40wilG2uRU0Fvz4OY8Bt+bSPOG776DFjwIXYzK7BwpJm9H2XI2HLhS5WxrJHhwrLBRgW6UiykMnFw== dependencies: - "@aws-sdk/types" "3.110.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/querystring-builder@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-builder/-/querystring-builder-3.110.0.tgz#c7f63262e898ab38cdbbbfcd03ddbfde346c9595" - integrity sha512-7V3CDXj519izmbBn9ZE68ymASwGriA+Aq+cb/yHSVtffnvXjPtvONNw7G/5iVblisGLSCUe2hSvpYtcaXozbHw== +"@aws-sdk/querystring-builder@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-builder/-/querystring-builder-3.127.0.tgz#50a100d13bd13bb06ee92dcd9568e21a37fb9c49" + integrity sha512-tsoyp4lLPsASPDYWsezGAHD8VJsZbjUNATNAzTCFdH6p+4SKBK83Q5kfXCzxt13M+l3oKbxxIWLvS0kVQFyltQ== dependencies: - "@aws-sdk/types" "3.110.0" + "@aws-sdk/types" "3.127.0" "@aws-sdk/util-uri-escape" "3.55.0" tslib "^2.3.1" -"@aws-sdk/querystring-parser@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-parser/-/querystring-parser-3.110.0.tgz#0551efb7aaa867d3b6705f62d798a45247f5f44b" - integrity sha512-//pJHH7hrhdDMZGBPKXKymmC/tJM7gFT0w/qbu/yd3Wm4W2fMB+8gkmj6EZctx7jrsWlfRQuvFejKqEfapur/g== +"@aws-sdk/querystring-parser@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-parser/-/querystring-parser-3.127.0.tgz#d485db0d24005e95bb4c9c478691cd805e5fc0f4" + integrity sha512-Vn/Dv+PqUSepp/DzLqq0LJJD8HdPefJCnLbO5WcHCARHSGlyGlZUFEM45k/oEHpTvgMXj/ORaP3A+tLwLu0AmA== dependencies: - "@aws-sdk/types" "3.110.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/service-error-classification@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/service-error-classification/-/service-error-classification-3.110.0.tgz#09398517d4ad9787bd0d904816bfe0ffd68b1f5f" - integrity sha512-ccgCE0pU/4RmXR6CP3fLAdhPAve7bK/yXBbGzpSHGAQOXqNxYzOsAvQ30Jg6X+qjLHsI/HR2pLIE65z4k6tynw== +"@aws-sdk/service-error-classification@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/service-error-classification/-/service-error-classification-3.127.0.tgz#64b69215b2525e3b6806856187ef54b00c0f85d1" + integrity sha512-wjZY9rnlA8SPrICUumTYicEKtK4/yKB62iadUk66hxe8MrH8JhuHH2NqIad0Pt/bK/YtNVhd3yb4pRapOeY5qQ== -"@aws-sdk/shared-ini-file-loader@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.110.0.tgz#f91b66e7084312df2b337cc990c9585e832fc2fc" - integrity sha512-E1ERoqEoG206XNBYWCKLgHkzCbTxdpDEGbsLET2DnvjFsT0s9p2dPvVux3bYl7JVAhyGduE+qcqWk7MzhFCBNQ== +"@aws-sdk/shared-ini-file-loader@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.127.0.tgz#019c5512bf92f954f6aca6f6811e38fe048aadf6" + integrity sha512-S3Nn4KRTqoJsB/TbRZSWBBUrkckNMR0Juqz7bOB+wupVvddKP6IcpspSC/GX9zgJjVMV8iGisZ6AUsYsC5r+cA== dependencies: tslib "^2.3.1" -"@aws-sdk/signature-v4@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4/-/signature-v4-3.110.0.tgz#9dba5d06345fa756b4c23deeec7086f6148a5bf1" - integrity sha512-utxxdllOnmQDhbpipnFAbuQ4c2pwefZ+2hi48jKvQRULQ2PO4nxLmdZm6B0FXaTijbKsyO7GrMik+EZ6mi3ARQ== +"@aws-sdk/signature-v4@3.130.0": + version "3.130.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4/-/signature-v4-3.130.0.tgz#152085234311610a350fdcd9a7f877a83aa44cf1" + integrity sha512-g5G1a1NHL2uOoFfC2zQdZcj+wbjgBQPkx6xGdtqNKf9v2kS0n6ap5JUGEaqWE02lUlmWHsoMsS73hXtzwXaBRQ== dependencies: "@aws-sdk/is-array-buffer" "3.55.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/types" "3.127.0" "@aws-sdk/util-hex-encoding" "3.109.0" - "@aws-sdk/util-middleware" "3.110.0" + "@aws-sdk/util-middleware" "3.127.0" "@aws-sdk/util-uri-escape" "3.55.0" tslib "^2.3.1" -"@aws-sdk/smithy-client@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/smithy-client/-/smithy-client-3.110.0.tgz#397c0e7ef56ffa058469c641b586978400c09dd7" - integrity sha512-gNLYrmdAe/1hVF2Nv2LF4OkL1A0a1o708pEMZHzql9xP164omRDaLrGDhz9tH7tsJEgLz+Bf4E8nTuISeDwvGg== +"@aws-sdk/smithy-client@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/smithy-client/-/smithy-client-3.127.0.tgz#64bbdedc3f8ef8a9b908b109833c458f24f58a13" + integrity sha512-sfcAJ+7a41CJMtsv6HRIjA91155Yk013RvMUdG2EMSo3cpLq/QmTJ1EGw4ByDZs5HLpXAaRoLI+bA2ovriGQnQ== dependencies: - "@aws-sdk/middleware-stack" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/middleware-stack" "3.127.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/types@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.110.0.tgz#09404533b507925eadf9acf9c4356667048e45bd" - integrity sha512-dLVoqODU3laaqNFPyN1QLtlQnwX4gNPMXptEBIt/iJpuZf66IYJe6WCzVZGt4Zfa1CnUmrlA428AzdcA/KCr2A== - -"@aws-sdk/types@^3.1.0": - version "3.55.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.55.0.tgz#d524d567e2b2722f2d6be83e2417dd6d46ce1490" - integrity sha512-wrDZjuy1CVAYxDCbm3bWQIKMGfNs7XXmG0eG4858Ixgqmq2avsIn5TORy8ynBxcXn9aekV/+tGEQ7BBSYzIVNQ== +"@aws-sdk/types@3.127.0", "@aws-sdk/types@^3.1.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.127.0.tgz#a7bafc47ee2328eee2453087521e6c3a39e7278d" + integrity sha512-e0wtx2IkOl7rwfKfLH5pPTzQ+d45V7b1WrjeL0WDI8kOu6w+sXmhNxI6uM2kf0k4NiTLN84lW290AEWupey9Og== -"@aws-sdk/url-parser@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/url-parser/-/url-parser-3.110.0.tgz#87d5c0a6f6d2f29027c747c65d8a2846302bc792" - integrity sha512-tILFB8/Q73yzgO0dErJNnELmmBszd0E6FucwAnG3hfDefjqCBe09Q/1yhu2aARXyRmZa4AKp0sWcdwIWHc8dnA== +"@aws-sdk/url-parser@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/url-parser/-/url-parser-3.127.0.tgz#7a5c6186e83dc6f823c989c0575aebe384e676b0" + integrity sha512-njZ7zn41JHRpNfr3BCesVXCLZE0zcWSfEdtRV0ICw0cU1FgYcKELSuY9+gLUB4ci6uc7gq7mPE8+w30FcM4QeA== dependencies: - "@aws-sdk/querystring-parser" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/querystring-parser" "3.127.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" "@aws-sdk/util-base64-browser@3.109.0": @@ -1628,26 +684,26 @@ dependencies: tslib "^2.3.1" -"@aws-sdk/util-defaults-mode-browser@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.110.0.tgz#b72331874da2c5e8a366cd98828a06fe19b52ae5" - integrity sha512-Y2dcOOD20S3bv/IjUqpdKIiDt6995SXNG5Pu/LeSdXNyLCOIm9rX4gHTxl9fC1KK5M/gR9fGJ362f67WwqEEqw== +"@aws-sdk/util-defaults-mode-browser@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.127.0.tgz#4fa9fe802e4296c0ab2e63a6a3c7c787ac5286df" + integrity sha512-e/vBm+EYSJ0R79591EPiCPE3aR5RKk5CjOkQjNxZIX8UPnIlo7xohTcebfR/iugSTxNrpfrFv+o4H5GjzAuhLA== dependencies: - "@aws-sdk/property-provider" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/property-provider" "3.127.0" + "@aws-sdk/types" "3.127.0" bowser "^2.11.0" tslib "^2.3.1" -"@aws-sdk/util-defaults-mode-node@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.110.0.tgz#52b4c84fc7aa06838ea6bb29d216a2d7615b9036" - integrity sha512-Cr3Z5nyrw1KowjbW76xp8hkT/zJtYjAVZ9PS4l84KxIicbVvDOBpxG3yNddkuQcavmlH6G4wH9uM5DcnpKDncg== +"@aws-sdk/util-defaults-mode-node@3.130.0": + version "3.130.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.130.0.tgz#4347aeabccf7b3d04aecd7545e904781ac9c0be1" + integrity sha512-0BWx7C6GhHBrjPUuSgMnRA4InxYisX6MIGs5yIHk2OArYkQLJMdeORYXXz1y40ahMihmtjD/Ap5xQGBm2vyffA== dependencies: - "@aws-sdk/config-resolver" "3.110.0" - "@aws-sdk/credential-provider-imds" "3.110.0" - "@aws-sdk/node-config-provider" "3.110.0" - "@aws-sdk/property-provider" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/config-resolver" "3.130.0" + "@aws-sdk/credential-provider-imds" "3.127.0" + "@aws-sdk/node-config-provider" "3.127.0" + "@aws-sdk/property-provider" "3.127.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" "@aws-sdk/util-hex-encoding@3.109.0": @@ -1664,10 +720,10 @@ dependencies: tslib "^2.3.1" -"@aws-sdk/util-middleware@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-middleware/-/util-middleware-3.110.0.tgz#00a727273974f54424954235867c1ddb0f6dad56" - integrity sha512-PTVWrI5fA9d5hHJs6RzX2dIS2jRQ3uW073Fm0BePpQeDdZrEk+S5KNwRhUtpN6sdSV45vm6S9rrjZUG51qwGmA== +"@aws-sdk/util-middleware@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-middleware/-/util-middleware-3.127.0.tgz#266d6160886f272cb3e3c3eb5266abbac0c033bc" + integrity sha512-EwAPPed9TNqh+Wov2VStLn2NuJ/Wyt7IkZCbCsBuSNp3BFZ1V4gfwTjqtKCtB2LQgQ48MTgWgNCvrH0zjCSPGg== dependencies: tslib "^2.3.1" @@ -1678,38 +734,31 @@ dependencies: tslib "^2.3.1" -"@aws-sdk/util-user-agent-browser@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.110.0.tgz#e0643e6047aab5137540259a42fbfdc37ae4abee" - integrity sha512-rNdhmHDMV5dNJctqlBWimkZLJRB+x03DB+61pm+SKSFk6gPIVIvc1WNXqDFphkiswT4vA13ZUkGHzt+N4+noQQ== +"@aws-sdk/util-user-agent-browser@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.127.0.tgz#dc6c4c9049ebf238c321883593b2cd3d82b5e755" + integrity sha512-uO2oHmJswuYKJS+GiMdYI8izhpC9M7/jFFvnAmLlTEVwpEi1VX9KePAOF+u5AaBC2kzITo/7dg141XfRHZloIQ== dependencies: - "@aws-sdk/types" "3.110.0" + "@aws-sdk/types" "3.127.0" bowser "^2.11.0" tslib "^2.3.1" -"@aws-sdk/util-user-agent-node@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.110.0.tgz#750abd6bb14f25a11e09d764f724b0d0e1c1248b" - integrity sha512-OQ915TPCCBwZWz5Np8zkNWn7U6KvrTZfFoCOy/VIemK3dUqmnBZ7HqGpuZx8SwJ2R9JE1x+j0niYSJ5fWJZZKA== +"@aws-sdk/util-user-agent-node@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.127.0.tgz#368dc0c0e1160e8ca9e5ca21f3857004509aa06e" + integrity sha512-3P/M4ZDD2qMeeoCk7TE/Mw7cG5IjB87F6BP8nI8/oHuaz7j6fsI7D49SNpyjl8JApRynZ122Ad6hwQwRj3isYw== dependencies: - "@aws-sdk/node-config-provider" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/node-config-provider" "3.127.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" -"@aws-sdk/util-utf8-browser@3.109.0": +"@aws-sdk/util-utf8-browser@3.109.0", "@aws-sdk/util-utf8-browser@^3.0.0": version "3.109.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.109.0.tgz#d013272e1981b23a4c84ac06f154db686c0cf84e" integrity sha512-FmcGSz0v7Bqpl1SE8G1Gc0CtDpug+rvqNCG/szn86JApD/f5x8oByjbEiAyTU2ZH2VevUntx6EW68ulHyH+x+w== dependencies: tslib "^2.3.1" -"@aws-sdk/util-utf8-browser@^3.0.0": - version "3.55.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.55.0.tgz#a045bf1a93f6e0ff9c846631b168ea55bbb37668" - integrity sha512-ljzqJcyjfJpEVSIAxwtIS8xMRUly84BdjlBXyp6cu4G8TUufgjNS31LWdhyGhgmW5vYBNr+LTz0Kwf6J+ou7Ug== - dependencies: - tslib "^2.3.1" - "@aws-sdk/util-utf8-node@3.109.0": version "3.109.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-node/-/util-utf8-node-3.109.0.tgz#89e06d916f5b246c7265f59bac742973ac0767ac" @@ -1718,13 +767,13 @@ "@aws-sdk/util-buffer-from" "3.55.0" tslib "^2.3.1" -"@aws-sdk/util-waiter@3.110.0": - version "3.110.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-waiter/-/util-waiter-3.110.0.tgz#fa1321024f4ffb270f4b09b703802b1730220f0e" - integrity sha512-8dE6W6XYfjk1gx/aeb8NeLfMMLkLFhlV1lmKpFSBJhY8msajU8aQahTuykq5JW8QT/wCGbqbu7dH35SdX7kO+A== +"@aws-sdk/util-waiter@3.127.0": + version "3.127.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-waiter/-/util-waiter-3.127.0.tgz#3485ebb614cc417fee397daf61ba4ca3aa5bbedb" + integrity sha512-E5qrRpBJS8dmClqSDW1pWVMKzCG/mxabG6jVUtlW/WLHnl/znxGaOQc6tnnwKik0nEq/4DpT9fEfPUz9JiLrkw== dependencies: - "@aws-sdk/abort-controller" "3.110.0" - "@aws-sdk/types" "3.110.0" + "@aws-sdk/abort-controller" "3.127.0" + "@aws-sdk/types" "3.127.0" tslib "^2.3.1" "@babel/code-frame@7.12.11": @@ -2520,13 +1569,28 @@ chalk "^4.1.2" semver "^7.3.7" -"@jsii/spec@1.61.0", "@jsii/spec@^1.60.0", "@jsii/spec@^1.61.0": +"@jsii/check-node@1.62.0": + version "1.62.0" + resolved "https://registry.yarnpkg.com/@jsii/check-node/-/check-node-1.62.0.tgz#3d3353d37ed1537acdfb63ea3e1506d82adb09b1" + integrity sha512-jYmY12Vrz3/0MJ9GTEfIxf4yh/7fsgYmuBp2UQfDLSfx+eaBvOG4xbjvsoa/AvfWF5VU95QqKAJLBDMOQK4z1g== + dependencies: + chalk "^4.1.2" + semver "^7.3.7" + +"@jsii/spec@1.61.0", "@jsii/spec@^1.61.0": version "1.61.0" resolved "https://registry.yarnpkg.com/@jsii/spec/-/spec-1.61.0.tgz#0529432d2bf6963374e3bfd6c36d95800defbefb" integrity sha512-pv1jAZY+gez62BCiHwfdCnjl2reye88QOKsD5IlCf7XbmvyQ4xFXVV2EnFzv4HUUtr+yuBj/tZz0HjOFsEBUQw== dependencies: ajv "^8.11.0" +"@jsii/spec@^1.62.0": + version "1.62.0" + resolved "https://registry.yarnpkg.com/@jsii/spec/-/spec-1.62.0.tgz#d673c6891171b19bd25d0f4c7676e5ee5e235a70" + integrity sha512-KR2ttOgZjyNHKkPDLFUnOnLPml0KLjwfYNEQTtYQKjhhIrlZZwnc1azYZ4GapLTgnklZVNgsDsbBW0sXKYJIhA== + dependencies: + ajv "^8.11.0" + "@lerna/add@5.1.4": version "5.1.4" resolved "https://registry.yarnpkg.com/@lerna/add/-/add-5.1.4.tgz#ddd21385b0a2f427b1bf1dd193e7e56f77bb3544" @@ -3696,11 +2760,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.7.tgz#4a53d8332bb65a45470a2f9e2611f1ced637a5cb" integrity sha512-1QUk+WAUD4t8iR+Oj+UgI8oJa6yyxaB8a8pHaC8uqM6RrS1qbL7bf3Pwl5rHv0psm2CuDErgho6v5N+G+5fwtQ== -"@types/node@^10.17.60": - version "10.17.60" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" - integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== - "@types/node@^18.0.0": version "18.0.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.0.tgz#67c7b724e1bcdd7a8821ce0d5ee184d3b4dd525a" @@ -4184,10 +3243,25 @@ at-least-node@^1.0.0: resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== -aws-cdk@1.160.0: - version "1.160.0" - resolved "https://registry.yarnpkg.com/aws-cdk/-/aws-cdk-1.160.0.tgz#525f4a31e83e07bcd623522713b3f57e34b234c0" - integrity sha512-WJu0Y1igEV0/RnVm+ppynYdlrqA1wD7mN9SNXJJA6VTozeboIZF9ZskwDkFZ6o1VXmvW/i8K2heSNLv2HuDZNQ== +aws-cdk-lib@2.33.0, aws-cdk-lib@^2.33.0: + version "2.33.0" + resolved "https://registry.yarnpkg.com/aws-cdk-lib/-/aws-cdk-lib-2.33.0.tgz#cd9cc7ab097a80833f3d63aa1a704d401d85fc10" + integrity sha512-+aV6+P3RROFndkw9/mtXCciL1RL2tHssju6kgwmml0XIqcnjJ8qyCR23fE8MEq49Q+6dQ8sBN2HtrdKHw/sgnw== + dependencies: + "@balena/dockerignore" "^1.0.2" + case "1.6.3" + fs-extra "^9.1.0" + ignore "^5.2.0" + jsonschema "^1.4.1" + minimatch "^3.1.2" + punycode "^2.1.1" + semver "^7.3.7" + yaml "1.10.2" + +aws-cdk@2.33.0: + version "2.33.0" + resolved "https://registry.yarnpkg.com/aws-cdk/-/aws-cdk-2.33.0.tgz#be867e5e49a5b84c5839f408ea4c26adef015298" + integrity sha512-pwqqXzdkyBraKARdyZ6OqMIbEHlnM0x5LJ08zFYQGcrC+jk/e3Y3XWGJrapC6sAKNwQNF78dcJbTSNBjjLXMdQ== optionalDependencies: fsevents "2.3.2" @@ -4215,16 +3289,16 @@ aws-sdk@^2.1155.0, aws-sdk@^2.928.0: uuid "8.0.0" xml2js "0.4.19" -awslint@1.160.0: - version "1.160.0" - resolved "https://registry.yarnpkg.com/awslint/-/awslint-1.160.0.tgz#e1e5429a004fb063d65f8d4718c19985527d6d9b" - integrity sha512-5TyMeYXatCB7aPN9liu+JxDILGr8juT1XSnw1IPdAJ4vEqAILK+1KmA2535yQh3fqD1/eTtPnnFXEH2k+LzC6A== +awslint@2.33.0: + version "2.33.0" + resolved "https://registry.yarnpkg.com/awslint/-/awslint-2.33.0.tgz#e000b80792469eddcf9928647ea0510776e3071c" + integrity sha512-zSwubnmarwetE7j4QCT12G45ZbHTcuxdHv8iog21rbeRiKc6DPI9hMyVLacolZ0MY3PeLPmAzkSdXLUpe+Vd/w== dependencies: - "@jsii/spec" "^1.60.0" + "@jsii/spec" "^1.62.0" camelcase "^6.3.0" chalk "^4" fs-extra "^9.1.0" - jsii-reflect "^1.60.0" + jsii-reflect "^1.62.0" yargs "^16.2.0" babel-jest@^27.5.1: @@ -4537,7 +3611,7 @@ caniuse-lite@^1.0.30001349: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001354.tgz#95c5efdb64148bb4870771749b9a619304755ce5" integrity sha512-mImKeCkyGDAHNywYFA4bqnLAzTUvVkqPvhY4DV47X+Gl2c5Z8c3KNETnXp14GQt11LvxE8AwjzGxJ+rsikiOzg== -case@^1.6.3: +case@1.6.3, case@^1.6.3: version "1.6.3" resolved "https://registry.yarnpkg.com/case/-/case-1.6.3.tgz#0a4386e3e9825351ca2e6216c60467ff5f1ea1c9" integrity sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ== @@ -4569,11 +3643,6 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -charenc@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" - integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= - chownr@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" @@ -4786,10 +3855,10 @@ console-control-strings@^1.1.0: resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== -constructs@^3.3.69: - version "3.3.161" - resolved "https://registry.yarnpkg.com/constructs/-/constructs-3.3.161.tgz#9726b1d450f3b9aca7907230f2248e3fd4058ce4" - integrity sha512-/27vW3fo0iyb3py4vKI1BduEYmv8vv8uJgLXvI+5F0Jbnn0/E+As2wkGMa7bumhzCd0Ckv/USkAXstGYVXTYQA== +constructs@^10.0.0: + version "10.1.54" + resolved "https://registry.yarnpkg.com/constructs/-/constructs-10.1.54.tgz#569849c9bb20f5626efff1fd44c91f65247ba08c" + integrity sha512-zpHUVzv/FaEdZzdbz8N0H6kXxpvJaAqaLVD/OpCMzVyqqAkv/CAi9N/zFuFwuc/EJZLmDY9Kx4uNIQYX/NI3jA== conventional-changelog-angular@^5.0.12: version "5.0.13" @@ -5000,11 +4069,6 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -crypt@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" - integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= - cssom@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" @@ -5219,11 +4283,6 @@ diff@^5.0.0: resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== -diff@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" - integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== - dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -6422,11 +5481,6 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-buffer@~1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - is-callable@^1.1.4, is-callable@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" @@ -7224,6 +6278,18 @@ jsii-reflect@^1.60.0, jsii-reflect@^1.61.0: oo-ascii-tree "^1.61.0" yargs "^16.2.0" +jsii-reflect@^1.62.0: + version "1.62.0" + resolved "https://registry.yarnpkg.com/jsii-reflect/-/jsii-reflect-1.62.0.tgz#2a116e50d91f0cfe42b1501ef15cd2e95902a7be" + integrity sha512-oMNxK1sctAl635m6IyCV9GWAljWjN5bE29Jn2+H4hiPVbNaWgGiyl74DqVTWJlPcrqVaHP+56ZmuYqputWaMOw== + dependencies: + "@jsii/check-node" "1.62.0" + "@jsii/spec" "^1.62.0" + chalk "^4" + fs-extra "^10.1.0" + oo-ascii-tree "^1.62.0" + yargs "^16.2.0" + jsii-rosetta@^1.61.0: version "1.61.0" resolved "https://registry.yarnpkg.com/jsii-rosetta/-/jsii-rosetta-1.61.0.tgz#ea82332545481aa373ac5b4826a303d16ec46b13" @@ -7718,15 +6784,6 @@ map-obj@^4.0.0: resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== -md5@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" - integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g== - dependencies: - charenc "0.0.2" - crypt "0.0.2" - is-buffer "~1.1.6" - mdurl@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" @@ -8301,6 +7358,11 @@ oo-ascii-tree@^1.61.0: resolved "https://registry.yarnpkg.com/oo-ascii-tree/-/oo-ascii-tree-1.61.0.tgz#06e151afdc3c3051635e94380d7a53512e4e59c1" integrity sha512-/7aCOm8qkHUdr4iy9qPs3ZbRoWN8FaShpII56LgSFy/YitvskT3SOx92KwcsE5Mipu/X43YcUYFWCS8nUlR3Xw== +oo-ascii-tree@^1.62.0: + version "1.62.0" + resolved "https://registry.yarnpkg.com/oo-ascii-tree/-/oo-ascii-tree-1.62.0.tgz#6e1944a409885c0af1d6e7b8245be8d432c40e4f" + integrity sha512-i0TzJUeAZmo9Hqv5rgfXiMkvqNbugaCz7y8jofgApb3p8oMe5+D8aaHKY45vG+NMI97nk69vOm9z3dZZ9i1Fqg== + optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -9560,7 +8622,7 @@ symbol-tree@^3.2.4: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== -table@^6.0.9, table@^6.8.0: +table@^6.0.9: version "6.8.0" resolved "https://registry.yarnpkg.com/table/-/table-6.8.0.tgz#87e28f14fa4321c3377ba286f07b79b281a3b3ca" integrity sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==