UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

766 lines 97.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const client_lambda_1 = require("@aws-sdk/client-lambda"); const setup = require("./hotswap-test-setup"); const common_1 = require("../../../lib/api/hotswap/common"); const s3_bucket_deployments_1 = require("../../../lib/api/hotswap/s3-bucket-deployments"); const mock_sdk_1 = require("../../util/mock-sdk"); const silent_1 = require("../../util/silent"); let hotswapMockSdkProvider; const payloadWithoutCustomResProps = { RequestType: 'Update', ResponseURL: s3_bucket_deployments_1.REQUIRED_BY_CFN, PhysicalResourceId: s3_bucket_deployments_1.REQUIRED_BY_CFN, StackId: s3_bucket_deployments_1.REQUIRED_BY_CFN, RequestId: s3_bucket_deployments_1.REQUIRED_BY_CFN, LogicalResourceId: s3_bucket_deployments_1.REQUIRED_BY_CFN, }; beforeEach(() => { hotswapMockSdkProvider = setup.setupHotswapTests(); }); describe.each([common_1.HotswapMode.FALL_BACK, common_1.HotswapMode.HOTSWAP_ONLY])('%p mode', (hotswapMode) => { (0, silent_1.silentTest)('calls the lambdaInvoke() API when it receives only an asset difference in an S3 bucket deployment and evaluates CFN expressions in S3 Deployment Properties', async () => { // GIVEN setup.setCurrentCfnStackTemplate({ Resources: { S3Deployment: { Type: 'Custom::CDKBucketDeployment', Properties: { ServiceToken: 'a-lambda-arn', SourceBucketNames: ['src-bucket'], SourceObjectKeys: ['src-key-old'], DestinationBucketName: 'dest-bucket', DestinationBucketKeyPrefix: 'my-key/some-old-prefix', }, }, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Resources: { S3Deployment: { Type: 'Custom::CDKBucketDeployment', Properties: { ServiceToken: 'a-lambda-arn', SourceBucketNames: ['src-bucket'], SourceObjectKeys: { 'Fn::Split': ['-', 'key1-key2-key3'], }, DestinationBucketName: 'dest-bucket', DestinationBucketKeyPrefix: 'my-key/some-new-prefix', }, }, }, }, }); // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).not.toBeUndefined(); expect(mock_sdk_1.mockLambdaClient).toHaveReceivedCommandWith(client_lambda_1.InvokeCommand, { FunctionName: 'a-lambda-arn', Payload: JSON.stringify({ ...payloadWithoutCustomResProps, ResourceProperties: { SourceBucketNames: ['src-bucket'], SourceObjectKeys: ['key1', 'key2', 'key3'], DestinationBucketName: 'dest-bucket', DestinationBucketKeyPrefix: 'my-key/some-new-prefix', }, }), }); }); (0, silent_1.silentTest)('does not call the invoke() API when a resource with type that is not Custom::CDKBucketDeployment but has the same properties is changed', async () => { // GIVEN setup.setCurrentCfnStackTemplate({ Resources: { S3Deployment: { Type: 'Custom::NotCDKBucketDeployment', Properties: { SourceObjectKeys: ['src-key-old'], }, }, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Resources: { S3Deployment: { Type: 'Custom::NotCDKBucketDeployment', Properties: { SourceObjectKeys: ['src-key-new'], }, }, }, }, }); if (hotswapMode === common_1.HotswapMode.FALL_BACK) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).toBeUndefined(); expect(mock_sdk_1.mockLambdaClient).not.toHaveReceivedCommand(client_lambda_1.InvokeCommand); } else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).not.toBeUndefined(); expect(deployStackResult?.noOp).toEqual(true); expect(mock_sdk_1.mockLambdaClient).not.toHaveReceivedCommand(client_lambda_1.InvokeCommand); } }); (0, silent_1.silentTest)('does not call the invokeLambda() api if the updated Policy has no Roles in CLASSIC mode but does in HOTSWAP_ONLY mode', async () => { // GIVEN setup.setCurrentCfnStackTemplate({ Parameters: { WebsiteBucketParamOld: { Type: 'String' }, WebsiteBucketParamNew: { Type: 'String' }, }, Resources: { S3Deployment: { Type: 'Custom::CDKBucketDeployment', Properties: { ServiceToken: 'a-lambda-arn', SourceObjectKeys: ['src-key-old'], SourceBucketNames: ['src-bucket'], DestinationBucketName: 'dest-bucket', }, }, Policy: { Type: 'AWS::IAM::Policy', Properties: { PolicyName: 'my-policy', PolicyDocument: { Statement: [ { Action: ['s3:GetObject*'], Effect: 'Allow', Resource: { Ref: 'WebsiteBucketParamOld', }, }, ], }, }, }, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Parameters: { WebsiteBucketParamOld: { Type: 'String' }, WebsiteBucketParamNew: { Type: 'String' }, }, Resources: { S3Deployment: { Type: 'Custom::CDKBucketDeployment', Properties: { ServiceToken: 'a-lambda-arn', SourceObjectKeys: ['src-key-new'], SourceBucketNames: ['src-bucket'], DestinationBucketName: 'dest-bucket', }, }, Policy: { Type: 'AWS::IAM::Policy', Properties: { PolicyName: 'my-policy', PolicyDocument: { Statement: [ { Action: ['s3:GetObject*'], Effect: 'Allow', Resource: { Ref: 'WebsiteBucketParamNew', }, }, ], }, }, }, }, }, }); if (hotswapMode === common_1.HotswapMode.FALL_BACK) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).toBeUndefined(); expect(mock_sdk_1.mockLambdaClient).not.toHaveReceivedCommand(client_lambda_1.InvokeCommand); } else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).not.toBeUndefined(); expect(mock_sdk_1.mockLambdaClient).toHaveReceivedCommandWith(client_lambda_1.InvokeCommand, { FunctionName: 'a-lambda-arn', Payload: JSON.stringify({ ...payloadWithoutCustomResProps, ResourceProperties: { SourceObjectKeys: ['src-key-new'], SourceBucketNames: ['src-bucket'], DestinationBucketName: 'dest-bucket', }, }), }); } }); (0, silent_1.silentTest)('throws an error when the serviceToken fails evaluation in the template', async () => { // GIVEN setup.setCurrentCfnStackTemplate({ Resources: { S3Deployment: { Type: 'Custom::CDKBucketDeployment', Properties: { ServiceToken: { Ref: 'BadLamba', }, SourceBucketNames: ['src-bucket'], SourceObjectKeys: ['src-key-old'], DestinationBucketName: 'dest-bucket', }, }, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Resources: { S3Deployment: { Type: 'Custom::CDKBucketDeployment', Properties: { ServiceToken: { Ref: 'BadLamba', }, SourceBucketNames: ['src-bucket'], SourceObjectKeys: ['src-key-new'], DestinationBucketName: 'dest-bucket', }, }, }, }, }); // WHEN await expect(() => hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact)).rejects.toThrow(/Parameter or resource 'BadLamba' could not be found for evaluation/); expect(mock_sdk_1.mockLambdaClient).not.toHaveReceivedCommand(client_lambda_1.InvokeCommand); }); describe('old-style synthesis', () => { const parameters = { WebsiteBucketParamOld: { Type: 'String' }, WebsiteBucketParamNew: { Type: 'String' }, DifferentBucketParamNew: { Type: 'String' }, }; const serviceRole = { Type: 'AWS::IAM::Role', Properties: { AssumeRolePolicyDocument: { Statement: [ { Action: 'sts:AssumeRole', Effect: 'Allow', Principal: { Service: 'lambda.amazonaws.com', }, }, ], Version: '2012-10-17', }, }, }; const policyOld = { Type: 'AWS::IAM::Policy', Properties: { PolicyName: 'my-policy-old', Roles: [{ Ref: 'ServiceRole' }], PolicyDocument: { Statement: [ { Action: ['s3:GetObject*'], Effect: 'Allow', Resource: { Ref: 'WebsiteBucketParamOld', }, }, ], }, }, }; const policyNew = { Type: 'AWS::IAM::Policy', Properties: { PolicyName: 'my-policy-new', Roles: [{ Ref: 'ServiceRole' }], PolicyDocument: { Statement: [ { Action: ['s3:GetObject*'], Effect: 'Allow', Resource: { Ref: 'WebsiteBucketParamNew', }, }, ], }, }, }; const policy2Old = { Type: 'AWS::IAM::Policy', Properties: { PolicyName: 'my-policy-old-2', Roles: [{ Ref: 'ServiceRole' }], PolicyDocument: { Statement: [ { Action: ['s3:GetObject*'], Effect: 'Allow', Resource: { Ref: 'WebsiteBucketParamOld', }, }, ], }, }, }; const policy2New = { Type: 'AWS::IAM::Policy', Properties: { PolicyName: 'my-policy-new-2', Roles: [{ Ref: 'ServiceRole2' }], PolicyDocument: { Statement: [ { Action: ['s3:GetObject*'], Effect: 'Allow', Resource: { Ref: 'DifferentBucketParamOld', }, }, ], }, }, }; const deploymentLambda = { Type: 'AWS::Lambda::Function', Role: { 'Fn::GetAtt': ['ServiceRole', 'Arn'], }, }; const s3DeploymentOld = { Type: 'Custom::CDKBucketDeployment', Properties: { ServiceToken: { 'Fn::GetAtt': ['S3DeploymentLambda', 'Arn'], }, SourceBucketNames: ['src-bucket-old'], SourceObjectKeys: ['src-key-old'], DestinationBucketName: 'WebsiteBucketOld', }, }; const s3DeploymentNew = { Type: 'Custom::CDKBucketDeployment', Properties: { ServiceToken: { 'Fn::GetAtt': ['S3DeploymentLambda', 'Arn'], }, SourceBucketNames: ['src-bucket-new'], SourceObjectKeys: ['src-key-new'], DestinationBucketName: 'WebsiteBucketNew', }, }; beforeEach(() => { setup.pushStackResourceSummaries(setup.stackSummaryOf('S3DeploymentLambda', 'AWS::Lambda::Function', 'my-deployment-lambda'), setup.stackSummaryOf('ServiceRole', 'AWS::IAM::Role', 'my-service-role')); }); (0, silent_1.silentTest)('calls the lambdaInvoke() API when it receives an asset difference in an S3 bucket deployment and an IAM Policy difference using old-style synthesis', async () => { // GIVEN setup.setCurrentCfnStackTemplate({ Resources: { Parameters: parameters, ServiceRole: serviceRole, Policy: policyOld, S3DeploymentLambda: deploymentLambda, S3Deployment: s3DeploymentOld, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Resources: { Parameters: parameters, ServiceRole: serviceRole, Policy: policyNew, S3DeploymentLambda: deploymentLambda, S3Deployment: s3DeploymentNew, }, }, }); // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact, { WebsiteBucketParamOld: 'WebsiteBucketOld', WebsiteBucketParamNew: 'WebsiteBucketNew', }); // THEN expect(deployStackResult).not.toBeUndefined(); expect(mock_sdk_1.mockLambdaClient).toHaveReceivedCommandWith(client_lambda_1.InvokeCommand, { FunctionName: 'arn:swa:lambda:here:123456789012:function:my-deployment-lambda', Payload: JSON.stringify({ ...payloadWithoutCustomResProps, ResourceProperties: { SourceBucketNames: ['src-bucket-new'], SourceObjectKeys: ['src-key-new'], DestinationBucketName: 'WebsiteBucketNew', }, }), }); }); (0, silent_1.silentTest)(`does not call the lambdaInvoke() API when the difference in the S3 deployment is referred to in one IAM policy change but not another in CLASSIC mode but does in HOTSWAP_ONLY`, async () => { // GIVEN setup.setCurrentCfnStackTemplate({ Resources: { ServiceRole: serviceRole, Policy1: policyOld, Policy2: policy2Old, S3DeploymentLambda: deploymentLambda, S3Deployment: s3DeploymentOld, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Resources: { ServiceRole: serviceRole, Policy1: policyNew, Policy2: { Properties: { Roles: [{ Ref: 'ServiceRole' }, 'different-role'], PolicyDocument: { Statement: [ { Action: ['s3:GetObject*'], Effect: 'Allow', Resource: { 'Fn::GetAtt': ['DifferentBucketNew', 'Arn'], }, }, ], }, }, }, S3DeploymentLambda: deploymentLambda, S3Deployment: s3DeploymentNew, }, }, }); if (hotswapMode === common_1.HotswapMode.FALL_BACK) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).toBeUndefined(); expect(mock_sdk_1.mockLambdaClient).not.toHaveReceivedCommand(client_lambda_1.InvokeCommand); } else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).not.toBeUndefined(); expect(mock_sdk_1.mockLambdaClient).toHaveReceivedCommandWith(client_lambda_1.InvokeCommand, { FunctionName: 'arn:swa:lambda:here:123456789012:function:my-deployment-lambda', Payload: JSON.stringify({ ...payloadWithoutCustomResProps, ResourceProperties: { SourceBucketNames: ['src-bucket-new'], SourceObjectKeys: ['src-key-new'], DestinationBucketName: 'WebsiteBucketNew', }, }), }); } }); (0, silent_1.silentTest)(`does not call the lambdaInvoke() API when the lambda that references the role is referred to by something other than an S3 deployment in CLASSIC mode but does in HOTSWAP_ONLY mode`, async () => { // GIVEN setup.setCurrentCfnStackTemplate({ Resources: { ServiceRole: serviceRole, Policy: policyOld, S3DeploymentLambda: deploymentLambda, S3Deployment: s3DeploymentOld, Endpoint: { Type: 'AWS::Lambda::Permission', Properties: { Action: 'lambda:InvokeFunction', FunctionName: { 'Fn::GetAtt': ['S3DeploymentLambda', 'Arn'], }, Principal: 'apigateway.amazonaws.com', }, }, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Resources: { ServiceRole: serviceRole, Policy: policyNew, S3DeploymentLambda: deploymentLambda, S3Deployment: s3DeploymentNew, Endpoint: { Type: 'AWS::Lambda::Permission', Properties: { Action: 'lambda:InvokeFunction', FunctionName: { 'Fn::GetAtt': ['S3DeploymentLambda', 'Arn'], }, Principal: 'apigateway.amazonaws.com', }, }, }, }, }); if (hotswapMode === common_1.HotswapMode.FALL_BACK) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).toBeUndefined(); expect(mock_sdk_1.mockLambdaClient).not.toHaveReceivedCommand(client_lambda_1.InvokeCommand); } else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).not.toBeUndefined(); expect(mock_sdk_1.mockLambdaClient).toHaveReceivedCommandWith(client_lambda_1.InvokeCommand, { FunctionName: 'arn:swa:lambda:here:123456789012:function:my-deployment-lambda', Payload: JSON.stringify({ ...payloadWithoutCustomResProps, ResourceProperties: { SourceBucketNames: ['src-bucket-new'], SourceObjectKeys: ['src-key-new'], DestinationBucketName: 'WebsiteBucketNew', }, }), }); } }); (0, silent_1.silentTest)('calls the lambdaInvoke() API when it receives an asset difference in two S3 bucket deployments and IAM Policy differences using old-style synthesis', async () => { // GIVEN const deploymentLambda2Old = { Type: 'AWS::Lambda::Function', Role: { 'Fn::GetAtt': ['ServiceRole', 'Arn'], }, }; const deploymentLambda2New = { Type: 'AWS::Lambda::Function', Role: { 'Fn::GetAtt': ['ServiceRole2', 'Arn'], }, }; const s3Deployment2Old = { Type: 'Custom::CDKBucketDeployment', Properties: { ServiceToken: { 'Fn::GetAtt': ['S3DeploymentLambda2', 'Arn'], }, SourceBucketNames: ['src-bucket-old'], SourceObjectKeys: ['src-key-old'], DestinationBucketName: 'DifferentBucketOld', }, }; const s3Deployment2New = { Type: 'Custom::CDKBucketDeployment', Properties: { ServiceToken: { 'Fn::GetAtt': ['S3DeploymentLambda2', 'Arn'], }, SourceBucketNames: ['src-bucket-new'], SourceObjectKeys: ['src-key-new'], DestinationBucketName: 'DifferentBucketNew', }, }; setup.setCurrentCfnStackTemplate({ Resources: { ServiceRole: serviceRole, ServiceRole2: serviceRole, Policy1: policyOld, Policy2: policy2Old, S3DeploymentLambda: deploymentLambda, S3DeploymentLambda2: deploymentLambda2Old, S3Deployment: s3DeploymentOld, S3Deployment2: s3Deployment2Old, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Resources: { Parameters: parameters, ServiceRole: serviceRole, ServiceRole2: serviceRole, Policy1: policyNew, Policy2: policy2New, S3DeploymentLambda: deploymentLambda, S3DeploymentLambda2: deploymentLambda2New, S3Deployment: s3DeploymentNew, S3Deployment2: s3Deployment2New, }, }, }); // WHEN setup.pushStackResourceSummaries(setup.stackSummaryOf('S3DeploymentLambda2', 'AWS::Lambda::Function', 'my-deployment-lambda-2'), setup.stackSummaryOf('ServiceRole2', 'AWS::IAM::Role', 'my-service-role-2')); const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact, { WebsiteBucketParamOld: 'WebsiteBucketOld', WebsiteBucketParamNew: 'WebsiteBucketNew', DifferentBucketParamNew: 'WebsiteBucketNew', }); // THEN expect(deployStackResult).not.toBeUndefined(); expect(mock_sdk_1.mockLambdaClient).toHaveReceivedCommandWith(client_lambda_1.InvokeCommand, { FunctionName: 'arn:swa:lambda:here:123456789012:function:my-deployment-lambda', Payload: JSON.stringify({ ...payloadWithoutCustomResProps, ResourceProperties: { SourceBucketNames: ['src-bucket-new'], SourceObjectKeys: ['src-key-new'], DestinationBucketName: 'WebsiteBucketNew', }, }), }); expect(mock_sdk_1.mockLambdaClient).toHaveReceivedCommandWith(client_lambda_1.InvokeCommand, { FunctionName: 'arn:swa:lambda:here:123456789012:function:my-deployment-lambda-2', Payload: JSON.stringify({ ...payloadWithoutCustomResProps, ResourceProperties: { SourceBucketNames: ['src-bucket-new'], SourceObjectKeys: ['src-key-new'], DestinationBucketName: 'DifferentBucketNew', }, }), }); }); (0, silent_1.silentTest)(`does not call the lambdaInvoke() API when it receives an asset difference in an S3 bucket deployment that references two different policies in CLASSIC mode but does in HOTSWAP_ONLY mode`, async () => { // GIVEN setup.setCurrentCfnStackTemplate({ Resources: { ServiceRole: serviceRole, Policy1: policyOld, Policy2: policy2Old, S3DeploymentLambda: deploymentLambda, S3Deployment: s3DeploymentOld, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Resources: { ServiceRole: serviceRole, Policy1: policyNew, Policy2: { Properties: { Roles: [{ Ref: 'ServiceRole' }], PolicyDocument: { Statement: [ { Action: ['s3:GetObject*'], Effect: 'Allow', Resource: { 'Fn::GetAtt': ['DifferentBucketNew', 'Arn'], }, }, ], }, }, }, S3DeploymentLambda: deploymentLambda, S3Deployment: s3DeploymentNew, }, }, }); if (hotswapMode === common_1.HotswapMode.FALL_BACK) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).toBeUndefined(); expect(mock_sdk_1.mockLambdaClient).not.toHaveReceivedCommand(client_lambda_1.InvokeCommand); } else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).not.toBeUndefined(); expect(mock_sdk_1.mockLambdaClient).toHaveReceivedCommandWith(client_lambda_1.InvokeCommand, { FunctionName: 'arn:swa:lambda:here:123456789012:function:my-deployment-lambda', Payload: JSON.stringify({ ...payloadWithoutCustomResProps, ResourceProperties: { SourceBucketNames: ['src-bucket-new'], SourceObjectKeys: ['src-key-new'], DestinationBucketName: 'WebsiteBucketNew', }, }), }); } }); (0, silent_1.silentTest)(`does not call the lambdaInvoke() API when a policy is referenced by a resource that is not an S3 deployment in CLASSIC mode but does in HOTSWAP_ONLY mode`, async () => { // GIVEN setup.setCurrentCfnStackTemplate({ Resources: { ServiceRole: serviceRole, Policy1: policyOld, S3DeploymentLambda: deploymentLambda, S3Deployment: s3DeploymentOld, NotADeployment: { Type: 'AWS::Not::S3Deployment', Properties: { Prop: { Ref: 'ServiceRole', }, }, }, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Resources: { ServiceRole: serviceRole, Policy1: policyNew, S3DeploymentLambda: deploymentLambda, S3Deployment: s3DeploymentNew, NotADeployment: { Type: 'AWS::Not::S3Deployment', Properties: { Prop: { Ref: 'ServiceRole', }, }, }, }, }, }); if (hotswapMode === common_1.HotswapMode.FALL_BACK) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).toBeUndefined(); expect(mock_sdk_1.mockLambdaClient).not.toHaveReceivedCommand(client_lambda_1.InvokeCommand); } else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).not.toBeUndefined(); expect(mock_sdk_1.mockLambdaClient).toHaveReceivedCommandWith(client_lambda_1.InvokeCommand, { FunctionName: 'arn:swa:lambda:here:123456789012:function:my-deployment-lambda', Payload: JSON.stringify({ ...payloadWithoutCustomResProps, ResourceProperties: { SourceBucketNames: ['src-bucket-new'], SourceObjectKeys: ['src-key-new'], DestinationBucketName: 'WebsiteBucketNew', }, }), }); } }); }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiczMtYnVja2V0LWhvdHN3YXAtZGVwbG95bWVudHMudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInMzLWJ1Y2tldC1ob3Rzd2FwLWRlcGxveW1lbnRzLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSwwREFBdUQ7QUFDdkQsOENBQThDO0FBQzlDLDREQUE4RDtBQUM5RCwwRkFBaUY7QUFDakYsa0RBQXVEO0FBQ3ZELDhDQUErQztBQUUvQyxJQUFJLHNCQUFvRCxDQUFDO0FBRXpELE1BQU0sNEJBQTRCLEdBQUc7SUFDbkMsV0FBVyxFQUFFLFFBQVE7SUFDckIsV0FBVyxFQUFFLHVDQUFlO0lBQzVCLGtCQUFrQixFQUFFLHVDQUFlO0lBQ25DLE9BQU8sRUFBRSx1Q0FBZTtJQUN4QixTQUFTLEVBQUUsdUNBQWU7SUFDMUIsaUJBQWlCLEVBQUUsdUNBQWU7Q0FDbkMsQ0FBQztBQUVGLFVBQVUsQ0FBQyxHQUFHLEVBQUU7SUFDZCxzQkFBc0IsR0FBRyxLQUFLLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztBQUNyRCxDQUFDLENBQUMsQ0FBQztBQUVILFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxvQkFBVyxDQUFDLFNBQVMsRUFBRSxvQkFBVyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUMsV0FBVyxFQUFFLEVBQUU7SUFDMUYsSUFBQSxtQkFBVSxFQUNSLDZKQUE2SixFQUM3SixLQUFLLElBQUksRUFBRTtRQUNULFFBQVE7UUFDUixLQUFLLENBQUMsMEJBQTBCLENBQUM7WUFDL0IsU0FBUyxFQUFFO2dCQUNULFlBQVksRUFBRTtvQkFDWixJQUFJLEVBQUUsNkJBQTZCO29CQUNuQyxVQUFVLEVBQUU7d0JBQ1YsWUFBWSxFQUFFLGNBQWM7d0JBQzVCLGlCQUFpQixFQUFFLENBQUMsWUFBWSxDQUFDO3dCQUNqQyxnQkFBZ0IsRUFBRSxDQUFDLGFBQWEsQ0FBQzt3QkFDakMscUJBQXFCLEVBQUUsYUFBYTt3QkFD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