@aws-cdk-testing/cli-integ 3.29.2 → 3.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -39,7 +39,7 @@
39
39
  "organization": true
40
40
  },
41
41
  "devDependencies": {
42
- "@aws-cdk/toolkit-lib": "1.21.3",
42
+ "@aws-cdk/toolkit-lib": "1.22.0",
43
43
  "@aws-cdk/yarn-cling": "0.0.0",
44
44
  "@cdklabs/eslint-plugin": "^2.0.0",
45
45
  "@stylistic/eslint-plugin": "^3",
@@ -124,7 +124,7 @@
124
124
  "publishConfig": {
125
125
  "access": "public"
126
126
  },
127
- "version": "3.29.2",
127
+ "version": "3.30.0",
128
128
  "packageManager": "yarn@4.13.0",
129
129
  "types": "lib/index.d.ts",
130
130
  "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"yarn projen\"."
@@ -33,6 +33,9 @@ if (process.env.PACKAGE_LAYOUT_VERSION === '1') {
33
33
  aws_ecr_assets: docker,
34
34
  aws_appsync: appsync,
35
35
  aws_bedrockagentcore: bedrockagentcore,
36
+ aws_events: events,
37
+ aws_dynamodb: dynamodb,
38
+ aws_bedrock: bedrock,
36
39
  Stack
37
40
  } = require('aws-cdk-lib');
38
41
  }
@@ -711,6 +714,59 @@ class AgentCoreHotswapStack extends cdk.Stack {
711
714
  }
712
715
  }
713
716
 
717
+ class CloudControlHotswapStack extends cdk.Stack {
718
+ constructor(parent, id, props) {
719
+ super(parent, id, props);
720
+
721
+ // DynamoDB table — a dependency that other resources reference
722
+ const table = new dynamodb.Table(this, 'Table', {
723
+ partitionKey: { name: 'pk', type: dynamodb.AttributeType.STRING },
724
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
725
+ });
726
+
727
+ // ElastiCache serverless cache — another dependency resource
728
+ const cache = new cdk.CfnResource(this, 'Cache', {
729
+ type: 'AWS::ElastiCache::ServerlessCache',
730
+ properties: {
731
+ Engine: 'valkey',
732
+ ServerlessCacheName: `${cdk.Stack.of(this).stackName}-cache`.substring(0, 40).toLowerCase(),
733
+ },
734
+ });
735
+
736
+ // SQS Queue — hotswapped via CCAPI, references the DynamoDB table ARN in its tag
737
+ const queue = new sqs.Queue(this, 'Queue', {
738
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
739
+ });
740
+ cdk.Tags.of(queue).add('DynamoTableArn', table.tableArn);
741
+ cdk.Tags.of(queue).add('DynamicTag', process.env.DYNAMIC_CC_PROPERTY_VALUE ?? 'original');
742
+
743
+ // Bedrock Agent — hotswapped via CCAPI, references the DynamoDB table name
744
+ const agentRole = new iam.Role(this, 'AgentRole', {
745
+ assumedBy: new iam.ServicePrincipal('bedrock.amazonaws.com'),
746
+ });
747
+ const agent = new bedrock.CfnAgent(this, 'Agent', {
748
+ agentName: `${cdk.Stack.of(this).stackName}-agent`.substring(0, 40),
749
+ agentResourceRoleArn: agentRole.roleArn,
750
+ instruction: process.env.DYNAMIC_CC_PROPERTY_VALUE
751
+ ? `You help query the table ${table.tableName}. ${process.env.DYNAMIC_CC_PROPERTY_VALUE}`
752
+ : `You help query the table ${table.tableName}. original`,
753
+ foundationModel: 'anthropic.claude-instant-v1',
754
+ });
755
+
756
+ // Events Rule — hotswapped via CCAPI, references the ElastiCache cache ARN
757
+ const rule = new events.Rule(this, 'Rule', {
758
+ schedule: events.Schedule.rate(cdk.Duration.hours(1)),
759
+ description: process.env.DYNAMIC_CC_PROPERTY_VALUE
760
+ ? `Rule for cache ${cache.getAtt('ARN')}. ${process.env.DYNAMIC_CC_PROPERTY_VALUE}`
761
+ : `Rule for cache ${cache.getAtt('ARN')}. original`,
762
+ });
763
+
764
+ new cdk.CfnOutput(this, 'QueueUrl', { value: queue.queueUrl });
765
+ new cdk.CfnOutput(this, 'AgentName', { value: agent.ref });
766
+ new cdk.CfnOutput(this, 'RuleName', { value: rule.ruleName });
767
+ }
768
+ }
769
+
714
770
  class DockerStack extends cdk.Stack {
715
771
  constructor(parent, id, props) {
716
772
  super(parent, id, props);
@@ -990,6 +1046,7 @@ switch (stackSet) {
990
1046
  new LambdaHotswapStack(app, `${stackPrefix}-lambda-hotswap`);
991
1047
  new EcsHotswapStack(app, `${stackPrefix}-ecs-hotswap`);
992
1048
  new AgentCoreHotswapStack(app, `${stackPrefix}-agentcore-hotswap`);
1049
+ new CloudControlHotswapStack(app, `${stackPrefix}-cc-hotswap`);
993
1050
  new AppSyncHotswapStack(app, `${stackPrefix}-appsync-hotswap`);
994
1051
  new DockerStack(app, `${stackPrefix}-docker`);
995
1052
  new DockerInUseStack(app, `${stackPrefix}-docker-in-use`);
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const client_cloudformation_1 = require("@aws-sdk/client-cloudformation");
4
+ const lib_1 = require("../../../lib");
5
+ jest.setTimeout(2 * 60 * 60_000); // Includes the time to acquire locks, worst-case single-threaded runtime
6
+ (0, lib_1.integTest)('hotswap deployment supports CloudControl-based resources with attribute resolution', (0, lib_1.withDefaultFixture)(async (fixture) => {
7
+ // GIVEN
8
+ const stackName = 'cc-hotswap';
9
+ await fixture.cdkDeploy(stackName, {
10
+ captureStderr: false,
11
+ modEnv: {
12
+ DYNAMIC_CC_PROPERTY_VALUE: 'original value',
13
+ },
14
+ });
15
+ // WHEN
16
+ const deployOutput = await fixture.cdkDeploy(stackName, {
17
+ options: ['--hotswap'],
18
+ captureStderr: true,
19
+ onlyStderr: true,
20
+ modEnv: {
21
+ DYNAMIC_CC_PROPERTY_VALUE: 'new value',
22
+ },
23
+ });
24
+ const response = await fixture.aws.cloudFormation.send(new client_cloudformation_1.DescribeStacksCommand({
25
+ StackName: fixture.fullStackName(stackName),
26
+ }));
27
+ const queueUrl = response.Stacks?.[0].Outputs?.find((output) => output.OutputKey === 'QueueUrl')?.OutputValue;
28
+ const agentName = response.Stacks?.[0].Outputs?.find((output) => output.OutputKey === 'AgentName')?.OutputValue;
29
+ const ruleName = response.Stacks?.[0].Outputs?.find((output) => output.OutputKey === 'RuleName')?.OutputValue;
30
+ // THEN
31
+ // The deployment should not trigger a full deployment, thus the stack's status must remain
32
+ // "CREATE_COMPLETE"
33
+ expect(response.Stacks?.[0].StackStatus).toEqual('CREATE_COMPLETE');
34
+ // Verify hotswap was used
35
+ expect(deployOutput).toMatch(/hotswapped!/);
36
+ // Verify all three CCAPI-based resources were hotswapped
37
+ expect(queueUrl).toBeDefined();
38
+ expect(agentName).toBeDefined();
39
+ expect(ruleName).toBeDefined();
40
+ }));
41
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2RrLWhvdHN3YXAtZGVwbG95bWVudC1zdXBwb3J0cy1jbG91ZGNvbnRyb2wtYmFzZWQtcmVzb3VyY2VzLmludGVndGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNkay1ob3Rzd2FwLWRlcGxveW1lbnQtc3VwcG9ydHMtY2xvdWRjb250cm9sLWJhc2VkLXJlc291cmNlcy5pbnRlZ3Rlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSwwRUFBdUU7QUFDdkUsc0NBQTZEO0FBRTdELElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLHlFQUF5RTtBQUUzRyxJQUFBLGVBQVMsRUFDUCxvRkFBb0YsRUFDcEYsSUFBQSx3QkFBa0IsRUFBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7SUFDbkMsUUFBUTtJQUNSLE1BQU0sU0FBUyxHQUFHLFlBQVksQ0FBQztJQUMvQixNQUFNLE9BQU8sQ0FBQyxTQUFTLENBQUMsU0FBUyxFQUFFO1FBQ2pDLGFBQWEsRUFBRSxLQUFLO1FBQ3BCLE1BQU0sRUFBRTtZQUNOLHlCQUF5QixFQUFFLGdCQUFnQjtTQUM1QztLQUNGLENBQUMsQ0FBQztJQUVILE9BQU87SUFDUCxNQUFNLFlBQVksR0FBRyxNQUFNLE9BQU8sQ0FBQyxTQUFTLENBQUMsU0FBUyxFQUFFO1FBQ3RELE9BQU8sRUFBRSxDQUFDLFdBQVcsQ0FBQztRQUN0QixhQUFhLEVBQUUsSUFBSTtRQUNuQixVQUFVLEVBQUUsSUFBSTtRQUNoQixNQUFNLEVBQUU7WUFDTix5QkFBeUIsRUFBRSxXQUFXO1NBQ3ZDO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsTUFBTSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQ3BELElBQUksNkNBQXFCLENBQUM7UUFDeEIsU0FBUyxFQUFFLE9BQU8sQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDO0tBQzVDLENBQUMsQ0FDSCxDQUFDO0lBRUYsTUFBTSxRQUFRLEdBQUcsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEtBQUssVUFBVSxDQUFDLEVBQUUsV0FBVyxDQUFDO0lBQzlHLE1BQU0sU0FBUyxHQUFHLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsU0FBUyxLQUFLLFdBQVcsQ0FBQyxFQUFFLFdBQVcsQ0FBQztJQUNoSCxNQUFNLFFBQVEsR0FBRyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLFNBQVMsS0FBSyxVQUFVLENBQUMsRUFBRSxXQUFXLENBQUM7SUFFOUcsT0FBTztJQUVQLDJGQUEyRjtJQUMzRixvQkFBb0I7SUFDcEIsTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUNwRSwwQkFBMEI7SUFDMUIsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUM1Qyx5REFBeUQ7SUFDekQsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQy9CLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUNoQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7QUFDakMsQ0FBQyxDQUFDLENBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERlc2NyaWJlU3RhY2tzQ29tbWFuZCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1jbG91ZGZvcm1hdGlvbic7XG5pbXBvcnQgeyBpbnRlZ1Rlc3QsIHdpdGhEZWZhdWx0Rml4dHVyZSB9IGZyb20gJy4uLy4uLy4uL2xpYic7XG5cbmplc3Quc2V0VGltZW91dCgyICogNjAgKiA2MF8wMDApOyAvLyBJbmNsdWRlcyB0aGUgdGltZSB0byBhY3F1aXJlIGxvY2tzLCB3b3JzdC1jYXNlIHNpbmdsZS10aHJlYWRlZCBydW50aW1lXG5cbmludGVnVGVzdChcbiAgJ2hvdHN3YXAgZGVwbG95bWVudCBzdXBwb3J0cyBDbG91ZENvbnRyb2wtYmFzZWQgcmVzb3VyY2VzIHdpdGggYXR0cmlidXRlIHJlc29sdXRpb24nLFxuICB3aXRoRGVmYXVsdEZpeHR1cmUoYXN5bmMgKGZpeHR1cmUpID0+IHtcbiAgICAvLyBHSVZFTlxuICAgIGNvbnN0IHN0YWNrTmFtZSA9ICdjYy1ob3Rzd2FwJztcbiAgICBhd2FpdCBmaXh0dXJlLmNka0RlcGxveShzdGFja05hbWUsIHtcbiAgICAgIGNhcHR1cmVTdGRlcnI6IGZhbHNlLFxuICAgICAgbW9kRW52OiB7XG4gICAgICAgIERZTkFNSUNfQ0NfUFJPUEVSVFlfVkFMVUU6ICdvcmlnaW5hbCB2YWx1ZScsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8gV0hFTlxuICAgIGNvbnN0IGRlcGxveU91dHB1dCA9IGF3YWl0IGZpeHR1cmUuY2RrRGVwbG95KHN0YWNrTmFtZSwge1xuICAgICAgb3B0aW9uczogWyctLWhvdHN3YXAnXSxcbiAgICAgIGNhcHR1cmVTdGRlcnI6IHRydWUsXG4gICAgICBvbmx5U3RkZXJyOiB0cnVlLFxuICAgICAgbW9kRW52OiB7XG4gICAgICAgIERZTkFNSUNfQ0NfUFJPUEVSVFlfVkFMVUU6ICduZXcgdmFsdWUnLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZml4dHVyZS5hd3MuY2xvdWRGb3JtYXRpb24uc2VuZChcbiAgICAgIG5ldyBEZXNjcmliZVN0YWNrc0NvbW1hbmQoe1xuICAgICAgICBTdGFja05hbWU6IGZpeHR1cmUuZnVsbFN0YWNrTmFtZShzdGFja05hbWUpLFxuICAgICAgfSksXG4gICAgKTtcblxuICAgIGNvbnN0IHF1ZXVlVXJsID0gcmVzcG9uc2UuU3RhY2tzPy5bMF0uT3V0cHV0cz8uZmluZCgob3V0cHV0KSA9PiBvdXRwdXQuT3V0cHV0S2V5ID09PSAnUXVldWVVcmwnKT8uT3V0cHV0VmFsdWU7XG4gICAgY29uc3QgYWdlbnROYW1lID0gcmVzcG9uc2UuU3RhY2tzPy5bMF0uT3V0cHV0cz8uZmluZCgob3V0cHV0KSA9PiBvdXRwdXQuT3V0cHV0S2V5ID09PSAnQWdlbnROYW1lJyk/Lk91dHB1dFZhbHVlO1xuICAgIGNvbnN0IHJ1bGVOYW1lID0gcmVzcG9uc2UuU3RhY2tzPy5bMF0uT3V0cHV0cz8uZmluZCgob3V0cHV0KSA9PiBvdXRwdXQuT3V0cHV0S2V5ID09PSAnUnVsZU5hbWUnKT8uT3V0cHV0VmFsdWU7XG5cbiAgICAvLyBUSEVOXG5cbiAgICAvLyBUaGUgZGVwbG95bWVudCBzaG91bGQgbm90IHRyaWdnZXIgYSBmdWxsIGRlcGxveW1lbnQsIHRodXMgdGhlIHN0YWNrJ3Mgc3RhdHVzIG11c3QgcmVtYWluXG4gICAgLy8gXCJDUkVBVEVfQ09NUExFVEVcIlxuICAgIGV4cGVjdChyZXNwb25zZS5TdGFja3M/LlswXS5TdGFja1N0YXR1cykudG9FcXVhbCgnQ1JFQVRFX0NPTVBMRVRFJyk7XG4gICAgLy8gVmVyaWZ5IGhvdHN3YXAgd2FzIHVzZWRcbiAgICBleHBlY3QoZGVwbG95T3V0cHV0KS50b01hdGNoKC9ob3Rzd2FwcGVkIS8pO1xuICAgIC8vIFZlcmlmeSBhbGwgdGhyZWUgQ0NBUEktYmFzZWQgcmVzb3VyY2VzIHdlcmUgaG90c3dhcHBlZFxuICAgIGV4cGVjdChxdWV1ZVVybCkudG9CZURlZmluZWQoKTtcbiAgICBleHBlY3QoYWdlbnROYW1lKS50b0JlRGVmaW5lZCgpO1xuICAgIGV4cGVjdChydWxlTmFtZSkudG9CZURlZmluZWQoKTtcbiAgfSksXG4pO1xuIl19