diff --git a/packages/@aws-cdk/aws-cognito/README.md b/packages/@aws-cdk/aws-cognito/README.md index 137cd1d214e10..e8766a08b56cd 100644 --- a/packages/@aws-cdk/aws-cognito/README.md +++ b/packages/@aws-cdk/aws-cognito/README.md @@ -528,6 +528,7 @@ The following third-party identity providers are currently supported in the CDK - [Google Login](https://developers.google.com/identity/sign-in/web/sign-in) - [Sign In With Apple](https://developer.apple.com/sign-in-with-apple/get-started/) - [OpenID Connect](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-oidc-idp.html) +- [SAML](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-saml-idp.html) The following code configures a user pool to federate with the third party provider, 'Login with Amazon'. The identity provider needs to be configured with a set of credentials that the Cognito backend can use to federate with the diff --git a/packages/@aws-cdk/aws-cognito/lib/user-pool-idps/index.ts b/packages/@aws-cdk/aws-cognito/lib/user-pool-idps/index.ts index fd7ad04af70fe..b99422478a85d 100644 --- a/packages/@aws-cdk/aws-cognito/lib/user-pool-idps/index.ts +++ b/packages/@aws-cdk/aws-cognito/lib/user-pool-idps/index.ts @@ -4,3 +4,4 @@ export * from './amazon'; export * from './facebook'; export * from './google'; export * from './oidc'; +export * from './saml'; diff --git a/packages/@aws-cdk/aws-cognito/lib/user-pool-idps/saml.ts b/packages/@aws-cdk/aws-cognito/lib/user-pool-idps/saml.ts new file mode 100644 index 0000000000000..3c8846b904693 --- /dev/null +++ b/packages/@aws-cdk/aws-cognito/lib/user-pool-idps/saml.ts @@ -0,0 +1,132 @@ +import { Names, Token } from '@aws-cdk/core'; +import { Construct } from 'constructs'; +import { CfnUserPoolIdentityProvider } from '../cognito.generated'; +import { UserPoolIdentityProviderProps } from './base'; +import { UserPoolIdentityProviderBase } from './private/user-pool-idp-base'; + +/** + * Properties to initialize UserPoolIdentityProviderSaml. + */ +export interface UserPoolIdentityProviderSamlProps extends UserPoolIdentityProviderProps { + /** + * The name of the provider. Must be between 3 and 32 characters. + * + * @default - the unique ID of the construct + */ + readonly name?: string; + + /** + * Identifiers + * + * Identifiers can be used to redirect users to the correct IdP in multitenant apps. + * + * @default - no identifiers used + */ + readonly identifiers?: string[] + + /** + * The SAML metadata. + */ + readonly metadata: UserPoolIdentityProviderSamlMetadata; + + /** + * Whether to enable the "Sign-out flow" feature. + * + * @default - false + */ + readonly idpSignout?: boolean; +} + +/** + * Metadata types that can be used for a SAML user pool identity provider. + */ +export enum UserPoolIdentityProviderSamlMetadataType { + /** Metadata provided via a URL. */ + URL = 'url', + + /** Metadata provided via the contents of a file. */ + FILE = 'file', +} + +/** + * Metadata for a SAML user pool identity provider. + */ +export class UserPoolIdentityProviderSamlMetadata { + + /** + * Specify SAML metadata via a URL. + */ + public static url(url: string): UserPoolIdentityProviderSamlMetadata { + return new UserPoolIdentityProviderSamlMetadata(url, UserPoolIdentityProviderSamlMetadataType.URL); + } + + /** + * Specify SAML metadata via the contents of a file. + */ + public static file(fileContent: string): UserPoolIdentityProviderSamlMetadata { + return new UserPoolIdentityProviderSamlMetadata(fileContent, UserPoolIdentityProviderSamlMetadataType.FILE); + } + + /** + * Construct the metadata for a SAML identity provider. + * + * @param metadataContent A URL hosting SAML metadata, or the content of a file containing SAML metadata. + * @param metadataType The type of metadata, either a URL or file content. + */ + private constructor(public readonly metadataContent: string, public readonly metadataType: UserPoolIdentityProviderSamlMetadataType) { + } +} + +/** + * Represents a identity provider that integrates with SAML. + * @resource AWS::Cognito::UserPoolIdentityProvider + */ +export class UserPoolIdentityProviderSaml extends UserPoolIdentityProviderBase { + public readonly providerName: string; + + constructor(scope: Construct, id: string, props: UserPoolIdentityProviderSamlProps) { + super(scope, id, props); + + this.validateName(props.name); + + const { metadataType, metadataContent } = props.metadata; + + const resource = new CfnUserPoolIdentityProvider(this, 'Resource', { + userPoolId: props.userPool.userPoolId, + providerName: this.getProviderName(props.name), + providerType: 'SAML', + providerDetails: { + IDPSignout: props.idpSignout ?? false, + MetadataURL: metadataType === UserPoolIdentityProviderSamlMetadataType.URL ? metadataContent : undefined, + MetadataFile: metadataType === UserPoolIdentityProviderSamlMetadataType.FILE ? metadataContent : undefined, + }, + idpIdentifiers: props.identifiers, + attributeMapping: super.configureAttributeMapping(), + }); + + this.providerName = super.getResourceNameAttribute(resource.ref); + } + + private getProviderName(name?: string): string { + if (name) { + this.validateName(name); + return name; + } + + const uniqueName = Names.uniqueResourceName(this, { + maxLength: 32, + }); + + if (uniqueName.length < 3) { + return `${uniqueName}saml`; + } + + return uniqueName; + } + + private validateName(name?: string) { + if (name && !Token.isUnresolved(name) && (name.length < 3 || name.length > 32)) { + throw new Error(`Expected provider name to be between 3 and 32 characters, received ${name} (${name.length} characters)`); + } + } +} diff --git a/packages/@aws-cdk/aws-cognito/package.json b/packages/@aws-cdk/aws-cognito/package.json index 633a3b5195fa2..d7e78bfc5cb27 100644 --- a/packages/@aws-cdk/aws-cognito/package.json +++ b/packages/@aws-cdk/aws-cognito/package.json @@ -83,6 +83,7 @@ "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/integ-runner": "0.0.0", + "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2", @@ -126,7 +127,8 @@ "props-physical-name:@aws-cdk/aws-cognito.UserPoolIdentityProviderAmazonProps", "props-physical-name:@aws-cdk/aws-cognito.UserPoolIdentityProviderGoogleProps", "props-physical-name:@aws-cdk/aws-cognito.UserPoolIdentityProviderAppleProps", - "props-physical-name:@aws-cdk/aws-cognito.UserPoolIdentityProviderOidcProps" + "props-physical-name:@aws-cdk/aws-cognito.UserPoolIdentityProviderOidcProps", + "props-physical-name:@aws-cdk/aws-cognito.UserPoolIdentityProviderSamlProps" ] }, "stability": "stable", diff --git a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-idp.saml.ts b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-idp.saml.ts new file mode 100644 index 0000000000000..fd1de9dd1fc77 --- /dev/null +++ b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-idp.saml.ts @@ -0,0 +1,40 @@ +import { App, CfnOutput, RemovalPolicy, Stack } from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; +import { Construct } from 'constructs'; +import { UserPool, UserPoolIdentityProviderSaml, UserPoolIdentityProviderSamlMetadata } from '../lib'; + +class TestStack extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + const userpool = new UserPool(this, 'pool', { + removalPolicy: RemovalPolicy.DESTROY, + }); + + new UserPoolIdentityProviderSaml(this, 'cdk', { + userPool: userpool, + name: 'cdk', + metadata: UserPoolIdentityProviderSamlMetadata.url('https://fujifish.github.io/samling/public/metadata.xml'), + }); + + const client = userpool.addClient('client'); + + const domain = userpool.addDomain('domain', { + cognitoDomain: { + domainPrefix: 'cdk-test-pool', + }, + }); + + new CfnOutput(this, 'SignInLink', { + value: domain.signInUrl(client, { + redirectUri: 'https://example.com', + }), + }); + } +} + +const app = new App(); +const testCase = new TestStack(app, 'integ-user-pool-identity-provider-saml-stack'); + +new IntegTest(app, 'integ-user-pool-identity-provider-saml-test', { + testCases: [testCase], +}); diff --git a/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/integ-user-pool-identity-provider-saml-stack.assets.json b/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/integ-user-pool-identity-provider-saml-stack.assets.json new file mode 100644 index 0000000000000..8e65975b437d9 --- /dev/null +++ b/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/integ-user-pool-identity-provider-saml-stack.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "6f6f07786415216f13b738979cec5ad81dbab3283fae83b99324965935cc1d60": { + "source": { + "path": "integ-user-pool-identity-provider-saml-stack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "6f6f07786415216f13b738979cec5ad81dbab3283fae83b99324965935cc1d60.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/integ-user-pool-identity-provider-saml-stack.template.json b/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/integ-user-pool-identity-provider-saml-stack.template.json new file mode 100644 index 0000000000000..56cb33a5c739f --- /dev/null +++ b/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/integ-user-pool-identity-provider-saml-stack.template.json @@ -0,0 +1,145 @@ +{ + "Resources": { + "pool056F3F7E": { + "Type": "AWS::Cognito::UserPool", + "Properties": { + "AccountRecoverySetting": { + "RecoveryMechanisms": [ + { + "Name": "verified_phone_number", + "Priority": 1 + }, + { + "Name": "verified_email", + "Priority": 2 + } + ] + }, + "AdminCreateUserConfig": { + "AllowAdminCreateUserOnly": true + }, + "EmailVerificationMessage": "The verification code to your new account is {####}", + "EmailVerificationSubject": "Verify your new account", + "SmsVerificationMessage": "The verification code to your new account is {####}", + "VerificationMessageTemplate": { + "DefaultEmailOption": "CONFIRM_WITH_CODE", + "EmailMessage": "The verification code to your new account is {####}", + "EmailSubject": "Verify your new account", + "SmsMessage": "The verification code to your new account is {####}" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "poolclient2623294C": { + "Type": "AWS::Cognito::UserPoolClient", + "Properties": { + "UserPoolId": { + "Ref": "pool056F3F7E" + }, + "AllowedOAuthFlows": [ + "implicit", + "code" + ], + "AllowedOAuthFlowsUserPoolClient": true, + "AllowedOAuthScopes": [ + "profile", + "phone", + "email", + "openid", + "aws.cognito.signin.user.admin" + ], + "CallbackURLs": [ + "https://example.com" + ], + "SupportedIdentityProviders": [ + { + "Ref": "cdk52888317" + }, + "COGNITO" + ] + } + }, + "pooldomain430FA744": { + "Type": "AWS::Cognito::UserPoolDomain", + "Properties": { + "Domain": "cdk-test-pool", + "UserPoolId": { + "Ref": "pool056F3F7E" + } + } + }, + "cdk52888317": { + "Type": "AWS::Cognito::UserPoolIdentityProvider", + "Properties": { + "ProviderName": "cdk", + "ProviderType": "SAML", + "UserPoolId": { + "Ref": "pool056F3F7E" + }, + "ProviderDetails": { + "IDPSignout": false, + "MetadataURL": "https://fujifish.github.io/samling/public/metadata.xml" + } + } + } + }, + "Outputs": { + "SignInLink": { + "Value": { + "Fn::Join": [ + "", + [ + "https://", + { + "Ref": "pooldomain430FA744" + }, + ".auth.", + { + "Ref": "AWS::Region" + }, + ".amazoncognito.com/login?client_id=", + { + "Ref": "poolclient2623294C" + }, + "&response_type=code&redirect_uri=https://example.com" + ] + ] + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/integ.json b/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/integ.json new file mode 100644 index 0000000000000..eb9199222282a --- /dev/null +++ b/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "21.0.0", + "testCases": { + "integ-user-pool-identity-provider-saml-test/DefaultTest": { + "stacks": [ + "integ-user-pool-identity-provider-saml-stack" + ], + "assertionStack": "integ-user-pool-identity-provider-saml-test/DefaultTest/DeployAssert", + "assertionStackName": "integuserpoolidentityprovidersamltestDefaultTestDeployAssert97F09C26" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/integuserpoolidentityprovidersamltestDefaultTestDeployAssert97F09C26.assets.json b/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/integuserpoolidentityprovidersamltestDefaultTestDeployAssert97F09C26.assets.json new file mode 100644 index 0000000000000..39aac6c49fa80 --- /dev/null +++ b/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/integuserpoolidentityprovidersamltestDefaultTestDeployAssert97F09C26.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integuserpoolidentityprovidersamltestDefaultTestDeployAssert97F09C26.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/integuserpoolidentityprovidersamltestDefaultTestDeployAssert97F09C26.template.json b/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/integuserpoolidentityprovidersamltestDefaultTestDeployAssert97F09C26.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/integuserpoolidentityprovidersamltestDefaultTestDeployAssert97F09C26.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/manifest.json new file mode 100644 index 0000000000000..dc88fad953da5 --- /dev/null +++ b/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/manifest.json @@ -0,0 +1,135 @@ +{ + "version": "21.0.0", + "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "integ-user-pool-identity-provider-saml-stack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integ-user-pool-identity-provider-saml-stack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integ-user-pool-identity-provider-saml-stack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integ-user-pool-identity-provider-saml-stack.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/6f6f07786415216f13b738979cec5ad81dbab3283fae83b99324965935cc1d60.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integ-user-pool-identity-provider-saml-stack.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integ-user-pool-identity-provider-saml-stack.assets" + ], + "metadata": { + "/integ-user-pool-identity-provider-saml-stack/pool/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "pool056F3F7E" + } + ], + "/integ-user-pool-identity-provider-saml-stack/pool/client/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "poolclient2623294C" + } + ], + "/integ-user-pool-identity-provider-saml-stack/pool/domain/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "pooldomain430FA744" + } + ], + "/integ-user-pool-identity-provider-saml-stack/cdk/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "cdk52888317" + } + ], + "/integ-user-pool-identity-provider-saml-stack/SignInLink": [ + { + "type": "aws:cdk:logicalId", + "data": "SignInLink" + } + ], + "/integ-user-pool-identity-provider-saml-stack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-user-pool-identity-provider-saml-stack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-user-pool-identity-provider-saml-stack" + }, + "integuserpoolidentityprovidersamltestDefaultTestDeployAssert97F09C26.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integuserpoolidentityprovidersamltestDefaultTestDeployAssert97F09C26.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integuserpoolidentityprovidersamltestDefaultTestDeployAssert97F09C26": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integuserpoolidentityprovidersamltestDefaultTestDeployAssert97F09C26.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integuserpoolidentityprovidersamltestDefaultTestDeployAssert97F09C26.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integuserpoolidentityprovidersamltestDefaultTestDeployAssert97F09C26.assets" + ], + "metadata": { + "/integ-user-pool-identity-provider-saml-test/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-user-pool-identity-provider-saml-test/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-user-pool-identity-provider-saml-test/DefaultTest/DeployAssert" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/tree.json b/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/tree.json new file mode 100644 index 0000000000000..65caa4df4b09b --- /dev/null +++ b/packages/@aws-cdk/aws-cognito/test/user-pool-idp.saml.integ.snapshot/tree.json @@ -0,0 +1,228 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.92" + } + }, + "integ-user-pool-identity-provider-saml-stack": { + "id": "integ-user-pool-identity-provider-saml-stack", + "path": "integ-user-pool-identity-provider-saml-stack", + "children": { + "pool": { + "id": "pool", + "path": "integ-user-pool-identity-provider-saml-stack/pool", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-user-pool-identity-provider-saml-stack/pool/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Cognito::UserPool", + "aws:cdk:cloudformation:props": { + "accountRecoverySetting": { + "recoveryMechanisms": [ + { + "name": "verified_phone_number", + "priority": 1 + }, + { + "name": "verified_email", + "priority": 2 + } + ] + }, + "adminCreateUserConfig": { + "allowAdminCreateUserOnly": true + }, + "emailVerificationMessage": "The verification code to your new account is {####}", + "emailVerificationSubject": "Verify your new account", + "smsVerificationMessage": "The verification code to your new account is {####}", + "verificationMessageTemplate": { + "defaultEmailOption": "CONFIRM_WITH_CODE", + "emailMessage": "The verification code to your new account is {####}", + "emailSubject": "Verify your new account", + "smsMessage": "The verification code to your new account is {####}" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-cognito.CfnUserPool", + "version": "0.0.0" + } + }, + "client": { + "id": "client", + "path": "integ-user-pool-identity-provider-saml-stack/pool/client", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-user-pool-identity-provider-saml-stack/pool/client/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Cognito::UserPoolClient", + "aws:cdk:cloudformation:props": { + "userPoolId": { + "Ref": "pool056F3F7E" + }, + "allowedOAuthFlows": [ + "implicit", + "code" + ], + "allowedOAuthFlowsUserPoolClient": true, + "allowedOAuthScopes": [ + "profile", + "phone", + "email", + "openid", + "aws.cognito.signin.user.admin" + ], + "callbackUrLs": [ + "https://example.com" + ], + "supportedIdentityProviders": [ + { + "Ref": "cdk52888317" + }, + "COGNITO" + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-cognito.CfnUserPoolClient", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-cognito.UserPoolClient", + "version": "0.0.0" + } + }, + "domain": { + "id": "domain", + "path": "integ-user-pool-identity-provider-saml-stack/pool/domain", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-user-pool-identity-provider-saml-stack/pool/domain/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Cognito::UserPoolDomain", + "aws:cdk:cloudformation:props": { + "domain": "cdk-test-pool", + "userPoolId": { + "Ref": "pool056F3F7E" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-cognito.CfnUserPoolDomain", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-cognito.UserPoolDomain", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-cognito.UserPool", + "version": "0.0.0" + } + }, + "cdk": { + "id": "cdk", + "path": "integ-user-pool-identity-provider-saml-stack/cdk", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-user-pool-identity-provider-saml-stack/cdk/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Cognito::UserPoolIdentityProvider", + "aws:cdk:cloudformation:props": { + "providerName": "cdk", + "providerType": "SAML", + "userPoolId": { + "Ref": "pool056F3F7E" + }, + "providerDetails": { + "IDPSignout": false, + "MetadataURL": "https://fujifish.github.io/samling/public/metadata.xml" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-cognito.CfnUserPoolIdentityProvider", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-cognito.UserPoolIdentityProviderSaml", + "version": "0.0.0" + } + }, + "SignInLink": { + "id": "SignInLink", + "path": "integ-user-pool-identity-provider-saml-stack/SignInLink", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "integ-user-pool-identity-provider-saml-test": { + "id": "integ-user-pool-identity-provider-saml-test", + "path": "integ-user-pool-identity-provider-saml-test", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integ-user-pool-identity-provider-saml-test/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integ-user-pool-identity-provider-saml-test/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.92" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integ-user-pool-identity-provider-saml-test/DefaultTest/DeployAssert", + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito/test/user-pool-idps/saml.test.ts b/packages/@aws-cdk/aws-cognito/test/user-pool-idps/saml.test.ts new file mode 100644 index 0000000000000..464bd66396ca3 --- /dev/null +++ b/packages/@aws-cdk/aws-cognito/test/user-pool-idps/saml.test.ts @@ -0,0 +1,184 @@ +import { Template, Match } from '@aws-cdk/assertions'; +import { Stack } from '@aws-cdk/core'; +import { ProviderAttribute, UserPool, UserPoolIdentityProviderSaml, UserPoolIdentityProviderSamlMetadata } from '../../lib'; + +describe('UserPoolIdentityProvider', () => { + describe('saml', () => { + test('metadata URL', () => { + // GIVEN + const stack = new Stack(); + const pool = new UserPool(stack, 'userpool'); + + // WHEN + new UserPoolIdentityProviderSaml(stack, 'userpoolidp', { + userPool: pool, + metadata: UserPoolIdentityProviderSamlMetadata.url('https://my-metadata-url.com'), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolIdentityProvider', { + ProviderName: 'userpoolidp', + ProviderType: 'SAML', + ProviderDetails: { + MetadataURL: 'https://my-metadata-url.com', + IDPSignout: false, + }, + }); + }); + + test('metadata file', () => { + // GIVEN + const stack = new Stack(); + const pool = new UserPool(stack, 'userpool'); + + // WHEN + new UserPoolIdentityProviderSaml(stack, 'userpoolidp', { + userPool: pool, + metadata: UserPoolIdentityProviderSamlMetadata.file('my-file-contents'), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolIdentityProvider', { + ProviderName: 'userpoolidp', + ProviderType: 'SAML', + ProviderDetails: { + MetadataFile: 'my-file-contents', + IDPSignout: false, + }, + }); + }); + + test('idpSignout', () => { + // GIVEN + const stack = new Stack(); + const pool = new UserPool(stack, 'userpool'); + + // WHEN + new UserPoolIdentityProviderSaml(stack, 'userpoolidp', { + userPool: pool, + metadata: UserPoolIdentityProviderSamlMetadata.file('my-file-contents'), + idpSignout: true, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolIdentityProvider', { + ProviderName: 'userpoolidp', + ProviderType: 'SAML', + ProviderDetails: { + MetadataFile: 'my-file-contents', + IDPSignout: true, + }, + }); + }); + + test('registered with user pool', () => { + // GIVEN + const stack = new Stack(); + const pool = new UserPool(stack, 'userpool'); + + // WHEN + const provider = new UserPoolIdentityProviderSaml(stack, 'userpoolidp', { + userPool: pool, + metadata: UserPoolIdentityProviderSamlMetadata.file('my-file-contents'), + }); + + // THEN + expect(pool.identityProviders).toContain(provider); + }); + + test('attribute mapping', () => { + // GIVEN + const stack = new Stack(); + const pool = new UserPool(stack, 'userpool'); + + // WHEN + new UserPoolIdentityProviderSaml(stack, 'userpoolidp', { + userPool: pool, + metadata: UserPoolIdentityProviderSamlMetadata.file('my-file-contents'), + attributeMapping: { + familyName: ProviderAttribute.other('family_name'), + givenName: ProviderAttribute.other('given_name'), + custom: { + customAttr1: ProviderAttribute.other('email'), + customAttr2: ProviderAttribute.other('sub'), + }, + }, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolIdentityProvider', { + AttributeMapping: { + family_name: 'family_name', + given_name: 'given_name', + customAttr1: 'email', + customAttr2: 'sub', + }, + }); + }); + + test('with provider name', () => { + // GIVEN + const stack = new Stack(); + const pool = new UserPool(stack, 'userpool'); + + // WHEN + new UserPoolIdentityProviderSaml(stack, 'userpoolidp', { + userPool: pool, + name: 'my-provider', + metadata: UserPoolIdentityProviderSamlMetadata.file('my-file-contents'), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolIdentityProvider', { + ProviderName: 'my-provider', + }); + }); + + test('throws with invalid provider name', () => { + // GIVEN + const stack = new Stack(); + const pool = new UserPool(stack, 'userpool'); + + // THEN + expect(() => new UserPoolIdentityProviderSaml(stack, 'userpoolidp', { + userPool: pool, + name: 'xy', + metadata: UserPoolIdentityProviderSamlMetadata.file('my-file-contents'), + })).toThrow(/Expected provider name to be between 3 and 32 characters/); + }); + + test('generates a valid name when unique id is too short', () => { + // GIVEN + const stack = new Stack(); + const pool = new UserPool(stack, 'userpool'); + + // WHEN + new UserPoolIdentityProviderSaml(stack, 'xy', { + userPool: pool, + metadata: UserPoolIdentityProviderSamlMetadata.file('my-file-contents'), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolIdentityProvider', { + ProviderName: 'xysaml', + }); + }); + + test('generates a valid name when unique id is too long', () => { + // GIVEN + const stack = new Stack(); + const pool = new UserPool(stack, 'userpool'); + + // WHEN + new UserPoolIdentityProviderSaml(stack, `${'saml'.repeat(10)}xyz`, { + userPool: pool, + metadata: UserPoolIdentityProviderSamlMetadata.file('my-file-contents'), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolIdentityProvider', { + ProviderName: Match.stringLikeRegexp('^\\w{3,32}$'), + }); + }); + }); +}); diff --git a/packages/@aws-cdk/aws-lambda-event-sources/lib/sqs.ts b/packages/@aws-cdk/aws-lambda-event-sources/lib/sqs.ts index 0e4f39c7e3858..105a7faf66766 100644 --- a/packages/@aws-cdk/aws-lambda-event-sources/lib/sqs.ts +++ b/packages/@aws-cdk/aws-lambda-event-sources/lib/sqs.ts @@ -39,6 +39,13 @@ export interface SqsEventSourceProps { * @default true */ readonly enabled?: boolean; + + /** + * Add filter criteria option + * + * @default - None + */ + readonly filters?: Array<{[key: string]: any}>; } /** @@ -73,6 +80,7 @@ export class SqsEventSource implements lambda.IEventSource { reportBatchItemFailures: this.props.reportBatchItemFailures, enabled: this.props.enabled, eventSourceArn: this.queue.queueArn, + filters: this.props.filters, }); this._eventSourceMappingId = eventSourceMapping.eventSourceMappingId; diff --git a/packages/@aws-cdk/aws-lambda-event-sources/lib/stream.ts b/packages/@aws-cdk/aws-lambda-event-sources/lib/stream.ts index e8f7f2a40de3e..acf0f55cb793d 100644 --- a/packages/@aws-cdk/aws-lambda-event-sources/lib/stream.ts +++ b/packages/@aws-cdk/aws-lambda-event-sources/lib/stream.ts @@ -107,6 +107,13 @@ export interface StreamEventSourceProps extends BaseStreamEventSourceProps { * @default - discarded records are ignored */ readonly onFailure?: lambda.IEventSourceDlq; + + /** + * Add filter criteria option + * + * @default - None + */ + readonly filters?: Array<{[key: string]: any}>; } /** @@ -132,6 +139,7 @@ export abstract class StreamEventSource implements lambda.IEventSource { onFailure: this.props.onFailure, tumblingWindow: this.props.tumblingWindow, enabled: this.props.enabled, + filters: this.props.filters, }; } } diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamo.test.ts b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamo.test.ts index a4b210156aae6..214ea8612274b 100644 --- a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamo.test.ts +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamo.test.ts @@ -243,6 +243,57 @@ describe('DynamoEventSource', () => { }); + test('adding filter criteria', () => { + // GIVEN + const stack = new cdk.Stack(); + const fn = new TestFunction(stack, 'Fn'); + const table = new dynamodb.Table(stack, 'T', { + partitionKey: { + name: 'id', + type: dynamodb.AttributeType.STRING, + }, + stream: dynamodb.StreamViewType.NEW_IMAGE, + }); + + // WHEN + fn.addEventSource(new sources.DynamoEventSource(table, { + startingPosition: lambda.StartingPosition.LATEST, + filters: [ + lambda.FilterCriteria.filter({ + eventName: lambda.FilterRule.isEqual('INSERT'), + dynamodb: { + Keys: { + id: { + S: lambda.FilterRule.exists(), + }, + }, + }, + }), + ], + })); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::EventSourceMapping', { + 'EventSourceArn': { + 'Fn::GetAtt': [ + 'TD925BC7E', + 'StreamArn', + ], + }, + 'FunctionName': { + 'Ref': 'Fn9270CBC0', + }, + 'FilterCriteria': { + 'Filters': [ + { + 'Pattern': '{"eventName":["INSERT"],"dynamodb":{"Keys":{"id":{"S":[{"exists":true}]}}}}', + }, + ], + }, + 'StartingPosition': 'LATEST', + }); + }); + test('specific maxBatchingWindow', () => { // GIVEN const stack = new cdk.Stack(); diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.assets.json b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.assets.json new file mode 100644 index 0000000000000..7bbad778ecd94 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.template.json b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/integ.json b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/integ.json new file mode 100644 index 0000000000000..b6cc14632ae83 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "21.0.0", + "testCases": { + "DynamoDBFilterCriteria/DefaultTest": { + "stacks": [ + "lambda-event-source-filter-criteria-dynamodb" + ], + "assertionStack": "DynamoDBFilterCriteria/DefaultTest/DeployAssert", + "assertionStackName": "DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-dynamodb.assets.json b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-dynamodb.assets.json new file mode 100644 index 0000000000000..ab5dd103772f8 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-dynamodb.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "8ddecd300b64f1e8196cec45f3e0f752e4a04060a8cd32fbcd88c192b14499fc": { + "source": { + "path": "lambda-event-source-filter-criteria-dynamodb.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "8ddecd300b64f1e8196cec45f3e0f752e4a04060a8cd32fbcd88c192b14499fc.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-dynamodb.template.json b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-dynamodb.template.json new file mode 100644 index 0000000000000..5d859d58bc0bf --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-dynamodb.template.json @@ -0,0 +1,173 @@ +{ + "Resources": { + "FServiceRole3AC82EE1": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "FServiceRoleDefaultPolicy17A19BFA": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "dynamodb:ListStreams", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "dynamodb:DescribeStream", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "TD925BC7E", + "StreamArn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "FServiceRoleDefaultPolicy17A19BFA", + "Roles": [ + { + "Ref": "FServiceRole3AC82EE1" + } + ] + } + }, + "FC4345940": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async function handler(event) {\n console.log('event:', JSON.stringify(event, undefined, 2));\n return { event };\n}" + }, + "Role": { + "Fn::GetAtt": [ + "FServiceRole3AC82EE1", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "FServiceRoleDefaultPolicy17A19BFA", + "FServiceRole3AC82EE1" + ] + }, + "FDynamoDBEventSourcelambdaeventsourcefiltercriteriadynamodbT9CFE7D0657833F11": { + "Type": "AWS::Lambda::EventSourceMapping", + "Properties": { + "FunctionName": { + "Ref": "FC4345940" + }, + "BatchSize": 5, + "EventSourceArn": { + "Fn::GetAtt": [ + "TD925BC7E", + "StreamArn" + ] + }, + "FilterCriteria": { + "Filters": [ + { + "Pattern": "{\"eventName\":[\"INSERT\"],\"dynamodb\":{\"Keys\":{\"id\":{\"S\":[{\"exists\":true}]}}}}" + } + ] + }, + "StartingPosition": "LATEST" + } + }, + "TD925BC7E": { + "Type": "AWS::DynamoDB::Table", + "Properties": { + "KeySchema": [ + { + "AttributeName": "id", + "KeyType": "HASH" + } + ], + "AttributeDefinitions": [ + { + "AttributeName": "id", + "AttributeType": "S" + } + ], + "ProvisionedThroughput": { + "ReadCapacityUnits": 5, + "WriteCapacityUnits": 5 + }, + "StreamSpecification": { + "StreamViewType": "NEW_IMAGE" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/manifest.json new file mode 100644 index 0000000000000..40f80338882b3 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/manifest.json @@ -0,0 +1,135 @@ +{ + "version": "21.0.0", + "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "lambda-event-source-filter-criteria-dynamodb.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "lambda-event-source-filter-criteria-dynamodb.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "lambda-event-source-filter-criteria-dynamodb": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "lambda-event-source-filter-criteria-dynamodb.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/8ddecd300b64f1e8196cec45f3e0f752e4a04060a8cd32fbcd88c192b14499fc.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "lambda-event-source-filter-criteria-dynamodb.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "lambda-event-source-filter-criteria-dynamodb.assets" + ], + "metadata": { + "/lambda-event-source-filter-criteria-dynamodb/F/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FServiceRole3AC82EE1" + } + ], + "/lambda-event-source-filter-criteria-dynamodb/F/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FServiceRoleDefaultPolicy17A19BFA" + } + ], + "/lambda-event-source-filter-criteria-dynamodb/F/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FC4345940" + } + ], + "/lambda-event-source-filter-criteria-dynamodb/F/DynamoDBEventSource:lambdaeventsourcefiltercriteriadynamodbT9CFE7D06/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FDynamoDBEventSourcelambdaeventsourcefiltercriteriadynamodbT9CFE7D0657833F11" + } + ], + "/lambda-event-source-filter-criteria-dynamodb/T/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "TD925BC7E" + } + ], + "/lambda-event-source-filter-criteria-dynamodb/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/lambda-event-source-filter-criteria-dynamodb/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "lambda-event-source-filter-criteria-dynamodb" + }, + "DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.assets" + ], + "metadata": { + "/DynamoDBFilterCriteria/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/DynamoDBFilterCriteria/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "DynamoDBFilterCriteria/DefaultTest/DeployAssert" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/tree.json b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/tree.json new file mode 100644 index 0000000000000..17aee7db14441 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/tree.json @@ -0,0 +1,294 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.92" + } + }, + "lambda-event-source-filter-criteria-dynamodb": { + "id": "lambda-event-source-filter-criteria-dynamodb", + "path": "lambda-event-source-filter-criteria-dynamodb", + "children": { + "F": { + "id": "F", + "path": "lambda-event-source-filter-criteria-dynamodb/F", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "lambda-event-source-filter-criteria-dynamodb/F/ServiceRole", + "children": { + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-dynamodb/F/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "lambda-event-source-filter-criteria-dynamodb/F/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-dynamodb/F/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "dynamodb:ListStreams", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "dynamodb:DescribeStream", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "TD925BC7E", + "StreamArn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "FServiceRoleDefaultPolicy17A19BFA", + "roles": [ + { + "Ref": "FServiceRole3AC82EE1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-dynamodb/F/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "exports.handler = async function handler(event) {\n console.log('event:', JSON.stringify(event, undefined, 2));\n return { event };\n}" + }, + "role": { + "Fn::GetAtt": [ + "FServiceRole3AC82EE1", + "Arn" + ] + }, + "handler": "index.handler", + "runtime": "nodejs14.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + }, + "DynamoDBEventSource:lambdaeventsourcefiltercriteriadynamodbT9CFE7D06": { + "id": "DynamoDBEventSource:lambdaeventsourcefiltercriteriadynamodbT9CFE7D06", + "path": "lambda-event-source-filter-criteria-dynamodb/F/DynamoDBEventSource:lambdaeventsourcefiltercriteriadynamodbT9CFE7D06", + "children": { + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-dynamodb/F/DynamoDBEventSource:lambdaeventsourcefiltercriteriadynamodbT9CFE7D06/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::EventSourceMapping", + "aws:cdk:cloudformation:props": { + "functionName": { + "Ref": "FC4345940" + }, + "batchSize": 5, + "eventSourceArn": { + "Fn::GetAtt": [ + "TD925BC7E", + "StreamArn" + ] + }, + "filterCriteria": { + "filters": [ + { + "pattern": "{\"eventName\":[\"INSERT\"],\"dynamodb\":{\"Keys\":{\"id\":{\"S\":[{\"exists\":true}]}}}}" + } + ] + }, + "startingPosition": "LATEST" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnEventSourceMapping", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.EventSourceMapping", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "T": { + "id": "T", + "path": "lambda-event-source-filter-criteria-dynamodb/T", + "children": { + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-dynamodb/T/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::DynamoDB::Table", + "aws:cdk:cloudformation:props": { + "keySchema": [ + { + "attributeName": "id", + "keyType": "HASH" + } + ], + "attributeDefinitions": [ + { + "attributeName": "id", + "attributeType": "S" + } + ], + "provisionedThroughput": { + "readCapacityUnits": 5, + "writeCapacityUnits": 5 + }, + "streamSpecification": { + "streamViewType": "NEW_IMAGE" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-dynamodb.CfnTable", + "version": "0.0.0" + } + }, + "ScalingRole": { + "id": "ScalingRole", + "path": "lambda-event-source-filter-criteria-dynamodb/T/ScalingRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-dynamodb.Table", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "DynamoDBFilterCriteria": { + "id": "DynamoDBFilterCriteria", + "path": "DynamoDBFilterCriteria", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "DynamoDBFilterCriteria/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "DynamoDBFilterCriteria/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.92" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "DynamoDBFilterCriteria/DefaultTest/DeployAssert", + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/integ.dynamodb-with-filter-criteria.ts b/packages/@aws-cdk/aws-lambda-event-sources/test/integ.dynamodb-with-filter-criteria.ts new file mode 100644 index 0000000000000..082964ef26518 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/integ.dynamodb-with-filter-criteria.ts @@ -0,0 +1,43 @@ +import * as dynamodb from '@aws-cdk/aws-dynamodb'; +import * as lambda from '@aws-cdk/aws-lambda'; +import * as cdk from '@aws-cdk/core'; +import * as integ from '@aws-cdk/integ-tests'; +import { DynamoEventSource } from '../lib'; +import { TestFunction } from './test-function'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'lambda-event-source-filter-criteria-dynamodb'); + +const fn = new TestFunction(stack, 'F'); +const table = new dynamodb.Table(stack, 'T', { + partitionKey: { + name: 'id', + type: dynamodb.AttributeType.STRING, + }, + stream: dynamodb.StreamViewType.NEW_IMAGE, + removalPolicy: cdk.RemovalPolicy.DESTROY, +}); + +fn.addEventSource(new DynamoEventSource(table, { + batchSize: 5, + startingPosition: lambda.StartingPosition.LATEST, + filters: [ + lambda.FilterCriteria.filter({ + eventName: lambda.FilterRule.isEqual('INSERT'), + dynamodb: { + Keys: { + id: { + S: lambda.FilterRule.exists(), + }, + }, + }, + }), + ], +})); + +new integ.IntegTest(app, 'DynamoDBFilterCriteria', { + testCases: [stack], +}); + +app.synth(); diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/integ.sqs-with-filter-criteria.ts b/packages/@aws-cdk/aws-lambda-event-sources/test/integ.sqs-with-filter-criteria.ts new file mode 100644 index 0000000000000..b180736709fe9 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/integ.sqs-with-filter-criteria.ts @@ -0,0 +1,30 @@ +import * as lambda from '@aws-cdk/aws-lambda'; +import * as sqs from '@aws-cdk/aws-sqs'; +import * as cdk from '@aws-cdk/core'; +import * as integ from '@aws-cdk/integ-tests'; +import { SqsEventSource } from '../lib'; +import { TestFunction } from './test-function'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'lambda-event-source-filter-criteria-sqs'); + +const fn = new TestFunction(stack, 'F'); +const queue = new sqs.Queue(stack, 'Q'); + +fn.addEventSource(new SqsEventSource(queue, { + batchSize: 5, + filters: [ + lambda.FilterCriteria.filter({ + body: { + id: lambda.FilterRule.exists(), + }, + }), + ], +})); + +new integ.IntegTest(app, 'SQSFilterCriteria', { + testCases: [stack], +}); + +app.synth(); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/SQSFilterCriteriaDefaultTestDeployAssert70A9A808.assets.json b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/SQSFilterCriteriaDefaultTestDeployAssert70A9A808.assets.json new file mode 100644 index 0000000000000..d64b21f030971 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/SQSFilterCriteriaDefaultTestDeployAssert70A9A808.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "SQSFilterCriteriaDefaultTestDeployAssert70A9A808.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/SQSFilterCriteriaDefaultTestDeployAssert70A9A808.template.json b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/SQSFilterCriteriaDefaultTestDeployAssert70A9A808.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/SQSFilterCriteriaDefaultTestDeployAssert70A9A808.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/integ.json b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/integ.json new file mode 100644 index 0000000000000..2026729f3374b --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "21.0.0", + "testCases": { + "SQSFilterCriteria/DefaultTest": { + "stacks": [ + "lambda-event-source-filter-criteria-sqs" + ], + "assertionStack": "SQSFilterCriteria/DefaultTest/DeployAssert", + "assertionStackName": "SQSFilterCriteriaDefaultTestDeployAssert70A9A808" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-sqs.assets.json b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-sqs.assets.json new file mode 100644 index 0000000000000..af98b5f96579d --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-sqs.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "879ea05cb693492da58c7a50d14e304f03f420185f19e668345fbee2bcf9fe44": { + "source": { + "path": "lambda-event-source-filter-criteria-sqs.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "879ea05cb693492da58c7a50d14e304f03f420185f19e668345fbee2bcf9fe44.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-sqs.template.json b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-sqs.template.json new file mode 100644 index 0000000000000..07811e3edcdbc --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-sqs.template.json @@ -0,0 +1,148 @@ +{ + "Resources": { + "FServiceRole3AC82EE1": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "FServiceRoleDefaultPolicy17A19BFA": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "sqs:ChangeMessageVisibility", + "sqs:DeleteMessage", + "sqs:GetQueueAttributes", + "sqs:GetQueueUrl", + "sqs:ReceiveMessage" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "Q63C6E3AB", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "FServiceRoleDefaultPolicy17A19BFA", + "Roles": [ + { + "Ref": "FServiceRole3AC82EE1" + } + ] + } + }, + "FC4345940": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async function handler(event) {\n console.log('event:', JSON.stringify(event, undefined, 2));\n return { event };\n}" + }, + "Role": { + "Fn::GetAtt": [ + "FServiceRole3AC82EE1", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "FServiceRoleDefaultPolicy17A19BFA", + "FServiceRole3AC82EE1" + ] + }, + "FSqsEventSourcelambdaeventsourcefiltercriteriasqsQA0FC5C93EBF98B38": { + "Type": "AWS::Lambda::EventSourceMapping", + "Properties": { + "FunctionName": { + "Ref": "FC4345940" + }, + "BatchSize": 5, + "EventSourceArn": { + "Fn::GetAtt": [ + "Q63C6E3AB", + "Arn" + ] + }, + "FilterCriteria": { + "Filters": [ + { + "Pattern": "{\"body\":{\"id\":[{\"exists\":true}]}}" + } + ] + } + } + }, + "Q63C6E3AB": { + "Type": "AWS::SQS::Queue", + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/manifest.json new file mode 100644 index 0000000000000..37b440978a5bb --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/manifest.json @@ -0,0 +1,135 @@ +{ + "version": "21.0.0", + "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "lambda-event-source-filter-criteria-sqs.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "lambda-event-source-filter-criteria-sqs.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "lambda-event-source-filter-criteria-sqs": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "lambda-event-source-filter-criteria-sqs.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/879ea05cb693492da58c7a50d14e304f03f420185f19e668345fbee2bcf9fe44.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "lambda-event-source-filter-criteria-sqs.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "lambda-event-source-filter-criteria-sqs.assets" + ], + "metadata": { + "/lambda-event-source-filter-criteria-sqs/F/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FServiceRole3AC82EE1" + } + ], + "/lambda-event-source-filter-criteria-sqs/F/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FServiceRoleDefaultPolicy17A19BFA" + } + ], + "/lambda-event-source-filter-criteria-sqs/F/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FC4345940" + } + ], + "/lambda-event-source-filter-criteria-sqs/F/SqsEventSource:lambdaeventsourcefiltercriteriasqsQA0FC5C93/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FSqsEventSourcelambdaeventsourcefiltercriteriasqsQA0FC5C93EBF98B38" + } + ], + "/lambda-event-source-filter-criteria-sqs/Q/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Q63C6E3AB" + } + ], + "/lambda-event-source-filter-criteria-sqs/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/lambda-event-source-filter-criteria-sqs/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "lambda-event-source-filter-criteria-sqs" + }, + "SQSFilterCriteriaDefaultTestDeployAssert70A9A808.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "SQSFilterCriteriaDefaultTestDeployAssert70A9A808.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "SQSFilterCriteriaDefaultTestDeployAssert70A9A808": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "SQSFilterCriteriaDefaultTestDeployAssert70A9A808.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "SQSFilterCriteriaDefaultTestDeployAssert70A9A808.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "SQSFilterCriteriaDefaultTestDeployAssert70A9A808.assets" + ], + "metadata": { + "/SQSFilterCriteria/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/SQSFilterCriteria/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "SQSFilterCriteria/DefaultTest/DeployAssert" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/tree.json b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/tree.json new file mode 100644 index 0000000000000..0655a941d1334 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/tree.json @@ -0,0 +1,262 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.92" + } + }, + "lambda-event-source-filter-criteria-sqs": { + "id": "lambda-event-source-filter-criteria-sqs", + "path": "lambda-event-source-filter-criteria-sqs", + "children": { + "F": { + "id": "F", + "path": "lambda-event-source-filter-criteria-sqs/F", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "lambda-event-source-filter-criteria-sqs/F/ServiceRole", + "children": { + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-sqs/F/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "lambda-event-source-filter-criteria-sqs/F/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-sqs/F/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "sqs:ChangeMessageVisibility", + "sqs:DeleteMessage", + "sqs:GetQueueAttributes", + "sqs:GetQueueUrl", + "sqs:ReceiveMessage" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "Q63C6E3AB", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "FServiceRoleDefaultPolicy17A19BFA", + "roles": [ + { + "Ref": "FServiceRole3AC82EE1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-sqs/F/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "exports.handler = async function handler(event) {\n console.log('event:', JSON.stringify(event, undefined, 2));\n return { event };\n}" + }, + "role": { + "Fn::GetAtt": [ + "FServiceRole3AC82EE1", + "Arn" + ] + }, + "handler": "index.handler", + "runtime": "nodejs14.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + }, + "SqsEventSource:lambdaeventsourcefiltercriteriasqsQA0FC5C93": { + "id": "SqsEventSource:lambdaeventsourcefiltercriteriasqsQA0FC5C93", + "path": "lambda-event-source-filter-criteria-sqs/F/SqsEventSource:lambdaeventsourcefiltercriteriasqsQA0FC5C93", + "children": { + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-sqs/F/SqsEventSource:lambdaeventsourcefiltercriteriasqsQA0FC5C93/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::EventSourceMapping", + "aws:cdk:cloudformation:props": { + "functionName": { + "Ref": "FC4345940" + }, + "batchSize": 5, + "eventSourceArn": { + "Fn::GetAtt": [ + "Q63C6E3AB", + "Arn" + ] + }, + "filterCriteria": { + "filters": [ + { + "pattern": "{\"body\":{\"id\":[{\"exists\":true}]}}" + } + ] + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnEventSourceMapping", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.EventSourceMapping", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "Q": { + "id": "Q", + "path": "lambda-event-source-filter-criteria-sqs/Q", + "children": { + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-sqs/Q/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SQS::Queue", + "aws:cdk:cloudformation:props": {} + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sqs.CfnQueue", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sqs.Queue", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "SQSFilterCriteria": { + "id": "SQSFilterCriteria", + "path": "SQSFilterCriteria", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "SQSFilterCriteria/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "SQSFilterCriteria/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.92" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "SQSFilterCriteria/DefaultTest/DeployAssert", + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs.test.ts b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs.test.ts index 06a834f2f8c36..24d9dd307e14a 100644 --- a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs.test.ts +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs.test.ts @@ -394,4 +394,33 @@ describe('SQSEventSource', () => { }, }); }); + + test('adding filter criteria', () => { + // GIVEN + const stack = new cdk.Stack(); + const fn = new TestFunction(stack, 'Fn'); + const q = new sqs.Queue(stack, 'Q'); + + // WHEN + fn.addEventSource(new sources.SqsEventSource(q, { + filters: [ + lambda.FilterCriteria.filter({ + body: { + id: lambda.FilterRule.exists(), + }, + }), + ], + })); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::EventSourceMapping', { + 'FilterCriteria': { + 'Filters': [ + { + 'Pattern': '{"body":{"id":[{"exists":true}]}}', + }, + ], + }, + }); + }); }); diff --git a/packages/@aws-cdk/aws-lambda-python/lib/bundling.ts b/packages/@aws-cdk/aws-lambda-python/lib/bundling.ts index 27c8d24f83558..4790b8f08e0eb 100644 --- a/packages/@aws-cdk/aws-lambda-python/lib/bundling.ts +++ b/packages/@aws-cdk/aws-lambda-python/lib/bundling.ts @@ -91,11 +91,12 @@ export class Bundling implements CdkBundlingOptions { private createBundlingCommand(options: BundlingCommandOptions): string[] { const packaging = Packaging.fromEntry(options.entry); let bundlingCommands: string[] = []; + bundlingCommands.push(`cp -rTL ${options.inputDir}/ ${options.outputDir}`); + bundlingCommands.push(`cd ${options.outputDir}`); bundlingCommands.push(packaging.exportCommand ?? ''); if (packaging.dependenciesFile) { bundlingCommands.push(`python -m pip install -r ${DependenciesFile.PIP} -t ${options.outputDir}`); } - bundlingCommands.push(`cp -rT ${options.inputDir}/ ${options.outputDir}`); return bundlingCommands; } } diff --git a/packages/@aws-cdk/aws-lambda-python/test/bundling.test.ts b/packages/@aws-cdk/aws-lambda-python/test/bundling.test.ts index 8c9bc93d08cfc..e9c598d795af7 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/bundling.test.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/bundling.test.ts @@ -37,7 +37,7 @@ test('Bundling a function without dependencies', () => { bundling: expect.objectContaining({ command: [ 'bash', '-c', - 'cp -rT /asset-input/ /asset-output', + 'cp -rTL /asset-input/ /asset-output && cd /asset-output', ], }), })); @@ -66,7 +66,7 @@ test('Bundling a function with requirements.txt', () => { bundling: expect.objectContaining({ command: [ 'bash', '-c', - 'python -m pip install -r requirements.txt -t /asset-output && cp -rT /asset-input/ /asset-output', + 'cp -rTL /asset-input/ /asset-output && cd /asset-output && python -m pip install -r requirements.txt -t /asset-output', ], }), })); @@ -89,7 +89,7 @@ test('Bundling Python 2.7 with requirements.txt installed', () => { bundling: expect.objectContaining({ command: [ 'bash', '-c', - 'python -m pip install -r requirements.txt -t /asset-output && cp -rT /asset-input/ /asset-output', + 'cp -rTL /asset-input/ /asset-output && cd /asset-output && python -m pip install -r requirements.txt -t /asset-output', ], }), })); @@ -109,7 +109,7 @@ test('Bundling a layer with dependencies', () => { bundling: expect.objectContaining({ command: [ 'bash', '-c', - 'python -m pip install -r requirements.txt -t /asset-output/python && cp -rT /asset-input/ /asset-output/python', + 'cp -rTL /asset-input/ /asset-output/python && cd /asset-output/python && python -m pip install -r requirements.txt -t /asset-output/python', ], }), })); @@ -129,7 +129,7 @@ test('Bundling a python code layer', () => { bundling: expect.objectContaining({ command: [ 'bash', '-c', - 'cp -rT /asset-input/ /asset-output/python', + 'cp -rTL /asset-input/ /asset-output/python && cd /asset-output/python', ], }), })); @@ -149,7 +149,7 @@ test('Bundling a function with pipenv dependencies', () => { bundling: expect.objectContaining({ command: [ 'bash', '-c', - 'PIPENV_VENV_IN_PROJECT=1 pipenv lock -r > requirements.txt && rm -rf .venv && python -m pip install -r requirements.txt -t /asset-output/python && cp -rT /asset-input/ /asset-output/python', + 'cp -rTL /asset-input/ /asset-output/python && cd /asset-output/python && PIPENV_VENV_IN_PROJECT=1 pipenv lock -r > requirements.txt && rm -rf .venv && python -m pip install -r requirements.txt -t /asset-output/python', ], }), })); @@ -176,7 +176,7 @@ test('Bundling a function with poetry dependencies', () => { bundling: expect.objectContaining({ command: [ 'bash', '-c', - 'poetry export --with-credentials --format requirements.txt --output requirements.txt && python -m pip install -r requirements.txt -t /asset-output/python && cp -rT /asset-input/ /asset-output/python', + 'cp -rTL /asset-input/ /asset-output/python && cd /asset-output/python && poetry export --with-credentials --format requirements.txt --output requirements.txt && python -m pip install -r requirements.txt -t /asset-output/python', ], }), })); @@ -206,7 +206,7 @@ test('Bundling a function with custom bundling image', () => { image, command: [ 'bash', '-c', - 'python -m pip install -r requirements.txt -t /asset-output/python && cp -rT /asset-input/ /asset-output/python', + 'cp -rTL /asset-input/ /asset-output/python && cd /asset-output/python && python -m pip install -r requirements.txt -t /asset-output/python', ], }), })); diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js new file mode 100644 index 0000000000000..ba956d47f51fe --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js @@ -0,0 +1,612 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// lib/assertions/providers/lambda-handler/index.ts +var lambda_handler_exports = {}; +__export(lambda_handler_exports, { + handler: () => handler +}); +module.exports = __toCommonJS(lambda_handler_exports); + +// ../assertions/lib/matcher.ts +var Matcher = class { + static isMatcher(x) { + return x && x instanceof Matcher; + } +}; +var MatchResult = class { + constructor(target) { + this.failures = []; + this.captures = /* @__PURE__ */ new Map(); + this.finalized = false; + this.target = target; + } + push(matcher, path, message) { + return this.recordFailure({ matcher, path, message }); + } + recordFailure(failure) { + this.failures.push(failure); + return this; + } + hasFailed() { + return this.failures.length !== 0; + } + get failCount() { + return this.failures.length; + } + compose(id, inner) { + const innerF = inner.failures; + this.failures.push(...innerF.map((f) => { + return { path: [id, ...f.path], message: f.message, matcher: f.matcher }; + })); + inner.captures.forEach((vals, capture) => { + vals.forEach((value) => this.recordCapture({ capture, value })); + }); + return this; + } + finished() { + if (this.finalized) { + return this; + } + if (this.failCount === 0) { + this.captures.forEach((vals, cap) => cap._captured.push(...vals)); + } + this.finalized = true; + return this; + } + toHumanStrings() { + return this.failures.map((r) => { + const loc = r.path.length === 0 ? "" : ` at ${r.path.join("")}`; + return "" + r.message + loc + ` (using ${r.matcher.name} matcher)`; + }); + } + recordCapture(options) { + let values = this.captures.get(options.capture); + if (values === void 0) { + values = []; + } + values.push(options.value); + this.captures.set(options.capture, values); + } +}; + +// ../assertions/lib/private/matchers/absent.ts +var AbsentMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual !== void 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Received ${actual}, but key should be absent` + }); + } + return result; + } +}; + +// ../assertions/lib/private/type.ts +function getType(obj) { + return Array.isArray(obj) ? "array" : typeof obj; +} + +// ../assertions/lib/match.ts +var Match = class { + static absent() { + return new AbsentMatch("absent"); + } + static arrayWith(pattern) { + return new ArrayMatch("arrayWith", pattern); + } + static arrayEquals(pattern) { + return new ArrayMatch("arrayEquals", pattern, { subsequence: false }); + } + static exact(pattern) { + return new LiteralMatch("exact", pattern, { partialObjects: false }); + } + static objectLike(pattern) { + return new ObjectMatch("objectLike", pattern); + } + static objectEquals(pattern) { + return new ObjectMatch("objectEquals", pattern, { partial: false }); + } + static not(pattern) { + return new NotMatch("not", pattern); + } + static serializedJson(pattern) { + return new SerializedJson("serializedJson", pattern); + } + static anyValue() { + return new AnyMatch("anyValue"); + } + static stringLikeRegexp(pattern) { + return new StringLikeRegexpMatch("stringLikeRegexp", pattern); + } +}; +var LiteralMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partialObjects = options.partialObjects ?? false; + if (Matcher.isMatcher(this.pattern)) { + throw new Error("LiteralMatch cannot directly contain another matcher. Remove the top-level matcher or nest it more deeply."); + } + } + test(actual) { + if (Array.isArray(this.pattern)) { + return new ArrayMatch(this.name, this.pattern, { subsequence: false, partialObjects: this.partialObjects }).test(actual); + } + if (typeof this.pattern === "object") { + return new ObjectMatch(this.name, this.pattern, { partial: this.partialObjects }).test(actual); + } + const result = new MatchResult(actual); + if (typeof this.pattern !== typeof actual) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected type ${typeof this.pattern} but received ${getType(actual)}` + }); + return result; + } + if (actual !== this.pattern) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected ${this.pattern} but received ${actual}` + }); + } + return result; + } +}; +var ArrayMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.subsequence = options.subsequence ?? true; + this.partialObjects = options.partialObjects ?? false; + } + test(actual) { + if (!Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type array but received ${getType(actual)}` + }); + } + if (!this.subsequence && this.pattern.length !== actual.length) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected array of length ${this.pattern.length} but received ${actual.length}` + }); + } + let patternIdx = 0; + let actualIdx = 0; + const result = new MatchResult(actual); + while (patternIdx < this.pattern.length && actualIdx < actual.length) { + const patternElement = this.pattern[patternIdx]; + const matcher = Matcher.isMatcher(patternElement) ? patternElement : new LiteralMatch(this.name, patternElement, { partialObjects: this.partialObjects }); + const matcherName = matcher.name; + if (this.subsequence && (matcherName == "absent" || matcherName == "anyValue")) { + throw new Error(`The Matcher ${matcherName}() cannot be nested within arrayWith()`); + } + const innerResult = matcher.test(actual[actualIdx]); + if (!this.subsequence || !innerResult.hasFailed()) { + result.compose(`[${actualIdx}]`, innerResult); + patternIdx++; + actualIdx++; + } else { + actualIdx++; + } + } + for (; patternIdx < this.pattern.length; patternIdx++) { + const pattern = this.pattern[patternIdx]; + const element = Matcher.isMatcher(pattern) || typeof pattern === "object" ? " " : ` [${pattern}] `; + result.recordFailure({ + matcher: this, + path: [], + message: `Missing element${element}at pattern index ${patternIdx}` + }); + } + return result; + } +}; +var ObjectMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partial = options.partial ?? true; + } + test(actual) { + if (typeof actual !== "object" || Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type object but received ${getType(actual)}` + }); + } + const result = new MatchResult(actual); + if (!this.partial) { + for (const a of Object.keys(actual)) { + if (!(a in this.pattern)) { + result.recordFailure({ + matcher: this, + path: [`/${a}`], + message: "Unexpected key" + }); + } + } + } + for (const [patternKey, patternVal] of Object.entries(this.pattern)) { + if (!(patternKey in actual) && !(patternVal instanceof AbsentMatch)) { + result.recordFailure({ + matcher: this, + path: [`/${patternKey}`], + message: `Missing key '${patternKey}' among {${Object.keys(actual).join(",")}}` + }); + continue; + } + const matcher = Matcher.isMatcher(patternVal) ? patternVal : new LiteralMatch(this.name, patternVal, { partialObjects: this.partial }); + const inner = matcher.test(actual[patternKey]); + result.compose(`/${patternKey}`, inner); + } + return result; + } +}; +var SerializedJson = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + if (getType(actual) !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected JSON as a string but found ${getType(actual)}` + }); + return result; + } + let parsed; + try { + parsed = JSON.parse(actual); + } catch (err) { + if (err instanceof SyntaxError) { + result.recordFailure({ + matcher: this, + path: [], + message: `Invalid JSON string: ${actual}` + }); + return result; + } else { + throw err; + } + } + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(parsed); + result.compose(`(${this.name})`, innerResult); + return result; + } +}; +var NotMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(actual); + const result = new MatchResult(actual); + if (innerResult.failCount === 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Found unexpected match: ${JSON.stringify(actual, void 0, 2)}` + }); + } + return result; + } +}; +var AnyMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual == null) { + result.recordFailure({ + matcher: this, + path: [], + message: "Expected a value but found none" + }); + } + return result; + } +}; +var StringLikeRegexpMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + const regex = new RegExp(this.pattern, "gm"); + if (typeof actual !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected a string, but got '${typeof actual}'` + }); + } + if (!regex.test(actual)) { + result.recordFailure({ + matcher: this, + path: [], + message: `String '${actual}' did not match pattern '${this.pattern}'` + }); + } + return result; + } +}; + +// lib/assertions/providers/lambda-handler/base.ts +var https = __toESM(require("https")); +var url = __toESM(require("url")); +var CustomResourceHandler = class { + constructor(event, context) { + this.event = event; + this.context = context; + this.timedOut = false; + this.timeout = setTimeout(async () => { + await this.respond({ + status: "FAILED", + reason: "Lambda Function Timeout", + data: this.context.logStreamName + }); + this.timedOut = true; + }, context.getRemainingTimeInMillis() - 1200); + this.event = event; + this.physicalResourceId = extractPhysicalResourceId(event); + } + async handle() { + try { + console.log(`Event: ${JSON.stringify({ ...this.event, ResponseURL: "..." })}`); + const response = await this.processEvent(this.event.ResourceProperties); + console.log(`Event output : ${JSON.stringify(response)}`); + await this.respond({ + status: "SUCCESS", + reason: "OK", + data: response + }); + } catch (e) { + console.log(e); + await this.respond({ + status: "FAILED", + reason: e.message ?? "Internal Error" + }); + } finally { + clearTimeout(this.timeout); + } + } + respond(response) { + if (this.timedOut) { + return; + } + const cfResponse = { + Status: response.status, + Reason: response.reason, + PhysicalResourceId: this.physicalResourceId, + StackId: this.event.StackId, + RequestId: this.event.RequestId, + LogicalResourceId: this.event.LogicalResourceId, + NoEcho: false, + Data: response.data + }; + const responseBody = JSON.stringify(cfResponse); + console.log("Responding to CloudFormation", responseBody); + const parsedUrl = url.parse(this.event.ResponseURL); + const requestOptions = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: "PUT", + headers: { "content-type": "", "content-length": responseBody.length } + }; + return new Promise((resolve, reject) => { + try { + const request2 = https.request(requestOptions, resolve); + request2.on("error", reject); + request2.write(responseBody); + request2.end(); + } catch (e) { + reject(e); + } + }); + } +}; +function extractPhysicalResourceId(event) { + switch (event.RequestType) { + case "Create": + return event.LogicalResourceId; + case "Update": + case "Delete": + return event.PhysicalResourceId; + } +} + +// lib/assertions/providers/lambda-handler/assertion.ts +var AssertionHandler = class extends CustomResourceHandler { + async processEvent(request2) { + let actual = decodeCall(request2.actual); + const expected = decodeCall(request2.expected); + let result; + const matcher = new MatchCreator(expected).getMatcher(); + console.log(`Testing equality between ${JSON.stringify(request2.actual)} and ${JSON.stringify(request2.expected)}`); + const matchResult = matcher.test(actual); + matchResult.finished(); + if (matchResult.hasFailed()) { + result = { + data: JSON.stringify({ + status: "fail", + message: [ + ...matchResult.toHumanStrings(), + JSON.stringify(matchResult.target, void 0, 2) + ].join("\n") + }) + }; + if (request2.failDeployment) { + throw new Error(result.data); + } + } else { + result = { + data: JSON.stringify({ + status: "success" + }) + }; + } + return result; + } +}; +var MatchCreator = class { + constructor(obj) { + this.parsedObj = { + matcher: obj + }; + } + getMatcher() { + try { + const final = JSON.parse(JSON.stringify(this.parsedObj), function(_k, v) { + const nested = Object.keys(v)[0]; + switch (nested) { + case "$ArrayWith": + return Match.arrayWith(v[nested]); + case "$ObjectLike": + return Match.objectLike(v[nested]); + case "$StringLike": + return Match.stringLikeRegexp(v[nested]); + default: + return v; + } + }); + if (Matcher.isMatcher(final.matcher)) { + return final.matcher; + } + return Match.exact(final.matcher); + } catch { + return Match.exact(this.parsedObj.matcher); + } + } +}; +function decodeCall(call) { + if (!call) { + return void 0; + } + try { + const parsed = JSON.parse(call); + return parsed; + } catch (e) { + return call; + } +} + +// lib/assertions/providers/lambda-handler/utils.ts +function decode(object) { + return JSON.parse(JSON.stringify(object), (_k, v) => { + switch (v) { + case "TRUE:BOOLEAN": + return true; + case "FALSE:BOOLEAN": + return false; + default: + return v; + } + }); +} + +// lib/assertions/providers/lambda-handler/sdk.ts +function flatten(object) { + return Object.assign( + {}, + ...function _flatten(child, path = []) { + return [].concat(...Object.keys(child).map((key) => { + const childKey = Buffer.isBuffer(child[key]) ? child[key].toString("utf8") : child[key]; + return typeof childKey === "object" && childKey !== null ? _flatten(childKey, path.concat([key])) : { [path.concat([key]).join(".")]: childKey }; + })); + }(object) + ); +} +var AwsApiCallHandler = class extends CustomResourceHandler { + async processEvent(request2) { + const AWS = require("aws-sdk"); + console.log(`AWS SDK VERSION: ${AWS.VERSION}`); + const service = new AWS[request2.service](); + const response = await service[request2.api](request2.parameters && decode(request2.parameters)).promise(); + console.log(`SDK response received ${JSON.stringify(response)}`); + delete response.ResponseMetadata; + const respond = { + apiCallResponse: response + }; + const flatData = { + ...flatten(respond) + }; + return request2.flattenResponse === "true" ? flatData : respond; + } +}; + +// lib/assertions/providers/lambda-handler/types.ts +var ASSERT_RESOURCE_TYPE = "Custom::DeployAssert@AssertEquals"; +var SDK_RESOURCE_TYPE_PREFIX = "Custom::DeployAssert@SdkCall"; + +// lib/assertions/providers/lambda-handler/index.ts +async function handler(event, context) { + const provider = createResourceHandler(event, context); + await provider.handle(); +} +function createResourceHandler(event, context) { + if (event.ResourceType.startsWith(SDK_RESOURCE_TYPE_PREFIX)) { + return new AwsApiCallHandler(event, context); + } + switch (event.ResourceType) { + case ASSERT_RESOURCE_TYPE: + return new AssertionHandler(event, context); + default: + throw new Error(`Unsupported resource type "${event.ResourceType}`); + } +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + handler +}); diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/asset.ab9c2b6025059cecbb1d54da74eb950315bc9fee8233e18822cefc8cff5806a0/Dockerfile b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/asset.ab9c2b6025059cecbb1d54da74eb950315bc9fee8233e18822cefc8cff5806a0/Dockerfile deleted file mode 100644 index 4204e9e4e3bd8..0000000000000 --- a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/asset.ab9c2b6025059cecbb1d54da74eb950315bc9fee8233e18822cefc8cff5806a0/Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -FROM public.ecr.aws/sam/build-python3.7 - -CMD [ "python" ] diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/asset.ab9c2b6025059cecbb1d54da74eb950315bc9fee8233e18822cefc8cff5806a0/index.py b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/asset.ab9c2b6025059cecbb1d54da74eb950315bc9fee8233e18822cefc8cff5806a0/index.py deleted file mode 100644 index 04f99eb108b30..0000000000000 --- a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/asset.ab9c2b6025059cecbb1d54da74eb950315bc9fee8233e18822cefc8cff5806a0/index.py +++ /dev/null @@ -1,8 +0,0 @@ -import requests - -def handler(event, context): - response = requests.get('https://a0.awsstatic.com/main/images/logos/aws_smile-header-desktop-en-white_59x35.png', stream=True) - - print(response.status_code) - - return response.status_code diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/cdk-integ-lambda-custom-build.assets.json b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/cdk-integ-lambda-custom-build.assets.json index be29726ec9194..2746f376dbc10 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/cdk-integ-lambda-custom-build.assets.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/cdk-integ-lambda-custom-build.assets.json @@ -1,20 +1,20 @@ { - "version": "20.0.0", + "version": "21.0.0", "files": { - "89ca5c5b2234f7dbbadd142cad0414d3cdf1293dc1edfa1618f4eac392958c82": { + "ba7fde4a6e034e2591e4b55fb4371a38236de097c96f5bba56c3fba49d3f18fa": { "source": { - "path": "asset.89ca5c5b2234f7dbbadd142cad0414d3cdf1293dc1edfa1618f4eac392958c82", + "path": "asset.ba7fde4a6e034e2591e4b55fb4371a38236de097c96f5bba56c3fba49d3f18fa", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "89ca5c5b2234f7dbbadd142cad0414d3cdf1293dc1edfa1618f4eac392958c82.zip", + "objectKey": "ba7fde4a6e034e2591e4b55fb4371a38236de097c96f5bba56c3fba49d3f18fa.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "a55d53ade2b8a8371454f5560cd4016fc7558d30dded2109b5ad4221bccced10": { + "d323c84453a473bd19a2e7a0be4c3333c23ce2c5ffd51914bd3de042bb9b3966": { "source": { "path": "cdk-integ-lambda-custom-build.template.json", "packaging": "file" @@ -22,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "a55d53ade2b8a8371454f5560cd4016fc7558d30dded2109b5ad4221bccced10.json", + "objectKey": "d323c84453a473bd19a2e7a0be4c3333c23ce2c5ffd51914bd3de042bb9b3966.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/cdk-integ-lambda-custom-build.template.json b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/cdk-integ-lambda-custom-build.template.json index fc438cec9e9ca..f6bbfba487760 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/cdk-integ-lambda-custom-build.template.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/cdk-integ-lambda-custom-build.template.json @@ -38,7 +38,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "89ca5c5b2234f7dbbadd142cad0414d3cdf1293dc1edfa1618f4eac392958c82.zip" + "S3Key": "ba7fde4a6e034e2591e4b55fb4371a38236de097c96f5bba56c3fba49d3f18fa.zip" }, "Role": { "Fn::GetAtt": [ @@ -55,12 +55,12 @@ } }, "Outputs": { - "FunctionArn": { + "ExportsOutputRefmyhandlerD202FA8E369E8804": { "Value": { - "Fn::GetAtt": [ - "myhandlerD202FA8E", - "Arn" - ] + "Ref": "myhandlerD202FA8E" + }, + "Export": { + "Name": "cdk-integ-lambda-custom-build:ExportsOutputRefmyhandlerD202FA8E369E8804" } } }, diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/cdk.out index 588d7b269d34f..8ecc185e9dbee 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/integ.json b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/integ.json index c8a882d15b805..d5df57a441edd 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/integ.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/integ.json @@ -1,14 +1,13 @@ { - "version": "20.0.0", + "version": "21.0.0", "testCases": { - "integ.function.custom-build": { + "lambda-python-custom-build/DefaultTest": { "stacks": [ "cdk-integ-lambda-custom-build" ], - "diffAssets": false, - "stackUpdateWorkflow": false + "stackUpdateWorkflow": false, + "assertionStack": "lambda-python-custom-build/DefaultTest/DeployAssert", + "assertionStackName": "lambdapythoncustombuildDefaultTestDeployAssert3F59C307" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/lambdapythoncustombuildDefaultTestDeployAssert3F59C307.assets.json b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/lambdapythoncustombuildDefaultTestDeployAssert3F59C307.assets.json new file mode 100644 index 0000000000000..d4618bec8843a --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/lambdapythoncustombuildDefaultTestDeployAssert3F59C307.assets.json @@ -0,0 +1,32 @@ +{ + "version": "21.0.0", + "files": { + "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7": { + "source": { + "path": "asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "6beacef24c1aedda67c91937d03e9a75f0ac3628ce3a6454581350bd880618b2": { + "source": { + "path": "lambdapythoncustombuildDefaultTestDeployAssert3F59C307.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "6beacef24c1aedda67c91937d03e9a75f0ac3628ce3a6454581350bd880618b2.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/lambdapythoncustombuildDefaultTestDeployAssert3F59C307.template.json b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/lambdapythoncustombuildDefaultTestDeployAssert3F59C307.template.json new file mode 100644 index 0000000000000..c59286e5e0921 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/lambdapythoncustombuildDefaultTestDeployAssert3F59C307.template.json @@ -0,0 +1,198 @@ +{ + "Resources": { + "LambdaInvoke431773224924ebf10c8a31d363a6bf16": { + "Type": "Custom::DeployAssert@SdkCallLambdainvoke", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "service": "Lambda", + "api": "invoke", + "parameters": { + "FunctionName": { + "Fn::ImportValue": "cdk-integ-lambda-custom-build:ExportsOutputRefmyhandlerD202FA8E369E8804" + } + }, + "flattenResponse": "false", + "salt": "1662650920315" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "LambdaInvoke431773224924ebf10c8a31d363a6bf16Invoke9BC0E67F": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::ImportValue": "cdk-integ-lambda-custom-build:ExportsOutputRefmyhandlerD202FA8E369E8804" + }, + "Principal": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + }, + "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B": { + "Type": "Custom::DeployAssert@AssertEquals", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "actual": { + "Fn::GetAtt": [ + "LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "apiCallResponse" + ] + }, + "expected": "{\"$ObjectLike\":{\"Payload\":\"200\"}}", + "salt": "1662650920316" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "lambda:Invoke" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":lambda:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":function:", + { + "Fn::ImportValue": "cdk-integ-lambda-custom-build:ExportsOutputRefmyhandlerD202FA8E369E8804" + } + ] + ] + } + ] + } + ] + } + } + ] + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Runtime": "nodejs14.x", + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip" + }, + "Timeout": 120, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + } + }, + "Outputs": { + "AssertionResultsAssertEqualsLambdainvokef5fe78069daba2e1e1326b4e96756d0b": { + "Value": { + "Fn::GetAtt": [ + "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B", + "data" + ] + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/manifest.json index 6633a91a6d8f2..0079eddaeea82 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "21.0.0", "artifacts": { "Tree": { "type": "cdk:tree", @@ -23,7 +23,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/a55d53ade2b8a8371454f5560cd4016fc7558d30dded2109b5ad4221bccced10.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/d323c84453a473bd19a2e7a0be4c3333c23ce2c5ffd51914bd3de042bb9b3966.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -51,10 +51,10 @@ "data": "myhandlerD202FA8E" } ], - "/cdk-integ-lambda-custom-build/FunctionArn": [ + "/cdk-integ-lambda-custom-build/Exports/Output{\"Ref\":\"myhandlerD202FA8E\"}": [ { "type": "aws:cdk:logicalId", - "data": "FunctionArn" + "data": "ExportsOutputRefmyhandlerD202FA8E369E8804" } ], "/cdk-integ-lambda-custom-build/BootstrapVersion": [ @@ -68,9 +68,111 @@ "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } + ], + "myhandler2ServiceRole0C463495": [ + { + "type": "aws:cdk:logicalId", + "data": "myhandler2ServiceRole0C463495", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ], + "myhandler292D4927D": [ + { + "type": "aws:cdk:logicalId", + "data": "myhandler292D4927D", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } ] }, "displayName": "cdk-integ-lambda-custom-build" + }, + "lambdapythoncustombuildDefaultTestDeployAssert3F59C307.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "lambdapythoncustombuildDefaultTestDeployAssert3F59C307.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "lambdapythoncustombuildDefaultTestDeployAssert3F59C307": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "lambdapythoncustombuildDefaultTestDeployAssert3F59C307.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/6beacef24c1aedda67c91937d03e9a75f0ac3628ce3a6454581350bd880618b2.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "lambdapythoncustombuildDefaultTestDeployAssert3F59C307.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "cdk-integ-lambda-custom-build", + "lambdapythoncustombuildDefaultTestDeployAssert3F59C307.assets" + ], + "metadata": { + "/lambda-python-custom-build/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16" + } + ], + "/lambda-python-custom-build/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Invoke": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16Invoke9BC0E67F" + } + ], + "/lambda-python-custom-build/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B" + } + ], + "/lambda-python-custom-build/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionResults": [ + { + "type": "aws:cdk:logicalId", + "data": "AssertionResultsAssertEqualsLambdainvokef5fe78069daba2e1e1326b4e96756d0b" + } + ], + "/lambda-python-custom-build/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73" + } + ], + "/lambda-python-custom-build/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F" + } + ], + "/lambda-python-custom-build/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/lambda-python-custom-build/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "lambda-python-custom-build/DefaultTest/DeployAssert" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/tree.json b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/tree.json index 1e0f36c20cfea..7f21f4010b842 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } }, "cdk-integ-lambda-custom-build": { @@ -77,8 +77,8 @@ "id": "Stage", "path": "cdk-integ-lambda-custom-build/my_handler/Code/Stage", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "AssetBucket": { @@ -105,7 +105,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "89ca5c5b2234f7dbbadd142cad0414d3cdf1293dc1edfa1618f4eac392958c82.zip" + "s3Key": "ba7fde4a6e034e2591e4b55fb4371a38236de097c96f5bba56c3fba49d3f18fa.zip" }, "role": { "Fn::GetAtt": [ @@ -128,24 +128,214 @@ "version": "0.0.0" } }, - "FunctionArn": { - "id": "FunctionArn", - "path": "cdk-integ-lambda-custom-build/FunctionArn", + "Exports": { + "id": "Exports", + "path": "cdk-integ-lambda-custom-build/Exports", + "children": { + "Output{\"Ref\":\"myhandlerD202FA8E\"}": { + "id": "Output{\"Ref\":\"myhandlerD202FA8E\"}", + "path": "cdk-integ-lambda-custom-build/Exports/Output{\"Ref\":\"myhandlerD202FA8E\"}", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "lambda-python-custom-build": { + "id": "lambda-python-custom-build", + "path": "lambda-python-custom-build", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "lambda-python-custom-build/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "lambda-python-custom-build/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "lambda-python-custom-build/DefaultTest/DeployAssert", + "children": { + "LambdaInvoke431773224924ebf10c8a31d363a6bf16": { + "id": "LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "path": "lambda-python-custom-build/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "children": { + "SdkProvider": { + "id": "SdkProvider", + "path": "lambda-python-custom-build/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/SdkProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "lambda-python-custom-build/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/SdkProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.AssertionsProvider", + "version": "0.0.0" + } + }, + "Default": { + "id": "Default", + "path": "lambda-python-custom-build/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default", + "children": { + "Default": { + "id": "Default", + "path": "lambda-python-custom-build/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "Invoke": { + "id": "Invoke", + "path": "lambda-python-custom-build/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Invoke", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "AssertEqualsLambdainvoke": { + "id": "AssertEqualsLambdainvoke", + "path": "lambda-python-custom-build/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke", + "children": { + "AssertionProvider": { + "id": "AssertionProvider", + "path": "lambda-python-custom-build/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "lambda-python-custom-build/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.AssertionsProvider", + "version": "0.0.0" + } + }, + "Default": { + "id": "Default", + "path": "lambda-python-custom-build/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default", + "children": { + "Default": { + "id": "Default", + "path": "lambda-python-custom-build/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "AssertionResults": { + "id": "AssertionResults", + "path": "lambda-python-custom-build/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionResults", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.EqualsAssertion", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.LambdaInvokeFunction", + "version": "0.0.0" + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81": { + "id": "SingletonFunction1488541a7b23466481b69b4408076b81", + "path": "lambda-python-custom-build/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81", + "children": { + "Staging": { + "id": "Staging", + "path": "lambda-python-custom-build/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Staging", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "lambda-python-custom-build/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "lambda-python-custom-build/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js new file mode 100644 index 0000000000000..ba956d47f51fe --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js @@ -0,0 +1,612 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// lib/assertions/providers/lambda-handler/index.ts +var lambda_handler_exports = {}; +__export(lambda_handler_exports, { + handler: () => handler +}); +module.exports = __toCommonJS(lambda_handler_exports); + +// ../assertions/lib/matcher.ts +var Matcher = class { + static isMatcher(x) { + return x && x instanceof Matcher; + } +}; +var MatchResult = class { + constructor(target) { + this.failures = []; + this.captures = /* @__PURE__ */ new Map(); + this.finalized = false; + this.target = target; + } + push(matcher, path, message) { + return this.recordFailure({ matcher, path, message }); + } + recordFailure(failure) { + this.failures.push(failure); + return this; + } + hasFailed() { + return this.failures.length !== 0; + } + get failCount() { + return this.failures.length; + } + compose(id, inner) { + const innerF = inner.failures; + this.failures.push(...innerF.map((f) => { + return { path: [id, ...f.path], message: f.message, matcher: f.matcher }; + })); + inner.captures.forEach((vals, capture) => { + vals.forEach((value) => this.recordCapture({ capture, value })); + }); + return this; + } + finished() { + if (this.finalized) { + return this; + } + if (this.failCount === 0) { + this.captures.forEach((vals, cap) => cap._captured.push(...vals)); + } + this.finalized = true; + return this; + } + toHumanStrings() { + return this.failures.map((r) => { + const loc = r.path.length === 0 ? "" : ` at ${r.path.join("")}`; + return "" + r.message + loc + ` (using ${r.matcher.name} matcher)`; + }); + } + recordCapture(options) { + let values = this.captures.get(options.capture); + if (values === void 0) { + values = []; + } + values.push(options.value); + this.captures.set(options.capture, values); + } +}; + +// ../assertions/lib/private/matchers/absent.ts +var AbsentMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual !== void 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Received ${actual}, but key should be absent` + }); + } + return result; + } +}; + +// ../assertions/lib/private/type.ts +function getType(obj) { + return Array.isArray(obj) ? "array" : typeof obj; +} + +// ../assertions/lib/match.ts +var Match = class { + static absent() { + return new AbsentMatch("absent"); + } + static arrayWith(pattern) { + return new ArrayMatch("arrayWith", pattern); + } + static arrayEquals(pattern) { + return new ArrayMatch("arrayEquals", pattern, { subsequence: false }); + } + static exact(pattern) { + return new LiteralMatch("exact", pattern, { partialObjects: false }); + } + static objectLike(pattern) { + return new ObjectMatch("objectLike", pattern); + } + static objectEquals(pattern) { + return new ObjectMatch("objectEquals", pattern, { partial: false }); + } + static not(pattern) { + return new NotMatch("not", pattern); + } + static serializedJson(pattern) { + return new SerializedJson("serializedJson", pattern); + } + static anyValue() { + return new AnyMatch("anyValue"); + } + static stringLikeRegexp(pattern) { + return new StringLikeRegexpMatch("stringLikeRegexp", pattern); + } +}; +var LiteralMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partialObjects = options.partialObjects ?? false; + if (Matcher.isMatcher(this.pattern)) { + throw new Error("LiteralMatch cannot directly contain another matcher. Remove the top-level matcher or nest it more deeply."); + } + } + test(actual) { + if (Array.isArray(this.pattern)) { + return new ArrayMatch(this.name, this.pattern, { subsequence: false, partialObjects: this.partialObjects }).test(actual); + } + if (typeof this.pattern === "object") { + return new ObjectMatch(this.name, this.pattern, { partial: this.partialObjects }).test(actual); + } + const result = new MatchResult(actual); + if (typeof this.pattern !== typeof actual) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected type ${typeof this.pattern} but received ${getType(actual)}` + }); + return result; + } + if (actual !== this.pattern) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected ${this.pattern} but received ${actual}` + }); + } + return result; + } +}; +var ArrayMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.subsequence = options.subsequence ?? true; + this.partialObjects = options.partialObjects ?? false; + } + test(actual) { + if (!Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type array but received ${getType(actual)}` + }); + } + if (!this.subsequence && this.pattern.length !== actual.length) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected array of length ${this.pattern.length} but received ${actual.length}` + }); + } + let patternIdx = 0; + let actualIdx = 0; + const result = new MatchResult(actual); + while (patternIdx < this.pattern.length && actualIdx < actual.length) { + const patternElement = this.pattern[patternIdx]; + const matcher = Matcher.isMatcher(patternElement) ? patternElement : new LiteralMatch(this.name, patternElement, { partialObjects: this.partialObjects }); + const matcherName = matcher.name; + if (this.subsequence && (matcherName == "absent" || matcherName == "anyValue")) { + throw new Error(`The Matcher ${matcherName}() cannot be nested within arrayWith()`); + } + const innerResult = matcher.test(actual[actualIdx]); + if (!this.subsequence || !innerResult.hasFailed()) { + result.compose(`[${actualIdx}]`, innerResult); + patternIdx++; + actualIdx++; + } else { + actualIdx++; + } + } + for (; patternIdx < this.pattern.length; patternIdx++) { + const pattern = this.pattern[patternIdx]; + const element = Matcher.isMatcher(pattern) || typeof pattern === "object" ? " " : ` [${pattern}] `; + result.recordFailure({ + matcher: this, + path: [], + message: `Missing element${element}at pattern index ${patternIdx}` + }); + } + return result; + } +}; +var ObjectMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partial = options.partial ?? true; + } + test(actual) { + if (typeof actual !== "object" || Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type object but received ${getType(actual)}` + }); + } + const result = new MatchResult(actual); + if (!this.partial) { + for (const a of Object.keys(actual)) { + if (!(a in this.pattern)) { + result.recordFailure({ + matcher: this, + path: [`/${a}`], + message: "Unexpected key" + }); + } + } + } + for (const [patternKey, patternVal] of Object.entries(this.pattern)) { + if (!(patternKey in actual) && !(patternVal instanceof AbsentMatch)) { + result.recordFailure({ + matcher: this, + path: [`/${patternKey}`], + message: `Missing key '${patternKey}' among {${Object.keys(actual).join(",")}}` + }); + continue; + } + const matcher = Matcher.isMatcher(patternVal) ? patternVal : new LiteralMatch(this.name, patternVal, { partialObjects: this.partial }); + const inner = matcher.test(actual[patternKey]); + result.compose(`/${patternKey}`, inner); + } + return result; + } +}; +var SerializedJson = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + if (getType(actual) !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected JSON as a string but found ${getType(actual)}` + }); + return result; + } + let parsed; + try { + parsed = JSON.parse(actual); + } catch (err) { + if (err instanceof SyntaxError) { + result.recordFailure({ + matcher: this, + path: [], + message: `Invalid JSON string: ${actual}` + }); + return result; + } else { + throw err; + } + } + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(parsed); + result.compose(`(${this.name})`, innerResult); + return result; + } +}; +var NotMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(actual); + const result = new MatchResult(actual); + if (innerResult.failCount === 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Found unexpected match: ${JSON.stringify(actual, void 0, 2)}` + }); + } + return result; + } +}; +var AnyMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual == null) { + result.recordFailure({ + matcher: this, + path: [], + message: "Expected a value but found none" + }); + } + return result; + } +}; +var StringLikeRegexpMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + const regex = new RegExp(this.pattern, "gm"); + if (typeof actual !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected a string, but got '${typeof actual}'` + }); + } + if (!regex.test(actual)) { + result.recordFailure({ + matcher: this, + path: [], + message: `String '${actual}' did not match pattern '${this.pattern}'` + }); + } + return result; + } +}; + +// lib/assertions/providers/lambda-handler/base.ts +var https = __toESM(require("https")); +var url = __toESM(require("url")); +var CustomResourceHandler = class { + constructor(event, context) { + this.event = event; + this.context = context; + this.timedOut = false; + this.timeout = setTimeout(async () => { + await this.respond({ + status: "FAILED", + reason: "Lambda Function Timeout", + data: this.context.logStreamName + }); + this.timedOut = true; + }, context.getRemainingTimeInMillis() - 1200); + this.event = event; + this.physicalResourceId = extractPhysicalResourceId(event); + } + async handle() { + try { + console.log(`Event: ${JSON.stringify({ ...this.event, ResponseURL: "..." })}`); + const response = await this.processEvent(this.event.ResourceProperties); + console.log(`Event output : ${JSON.stringify(response)}`); + await this.respond({ + status: "SUCCESS", + reason: "OK", + data: response + }); + } catch (e) { + console.log(e); + await this.respond({ + status: "FAILED", + reason: e.message ?? "Internal Error" + }); + } finally { + clearTimeout(this.timeout); + } + } + respond(response) { + if (this.timedOut) { + return; + } + const cfResponse = { + Status: response.status, + Reason: response.reason, + PhysicalResourceId: this.physicalResourceId, + StackId: this.event.StackId, + RequestId: this.event.RequestId, + LogicalResourceId: this.event.LogicalResourceId, + NoEcho: false, + Data: response.data + }; + const responseBody = JSON.stringify(cfResponse); + console.log("Responding to CloudFormation", responseBody); + const parsedUrl = url.parse(this.event.ResponseURL); + const requestOptions = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: "PUT", + headers: { "content-type": "", "content-length": responseBody.length } + }; + return new Promise((resolve, reject) => { + try { + const request2 = https.request(requestOptions, resolve); + request2.on("error", reject); + request2.write(responseBody); + request2.end(); + } catch (e) { + reject(e); + } + }); + } +}; +function extractPhysicalResourceId(event) { + switch (event.RequestType) { + case "Create": + return event.LogicalResourceId; + case "Update": + case "Delete": + return event.PhysicalResourceId; + } +} + +// lib/assertions/providers/lambda-handler/assertion.ts +var AssertionHandler = class extends CustomResourceHandler { + async processEvent(request2) { + let actual = decodeCall(request2.actual); + const expected = decodeCall(request2.expected); + let result; + const matcher = new MatchCreator(expected).getMatcher(); + console.log(`Testing equality between ${JSON.stringify(request2.actual)} and ${JSON.stringify(request2.expected)}`); + const matchResult = matcher.test(actual); + matchResult.finished(); + if (matchResult.hasFailed()) { + result = { + data: JSON.stringify({ + status: "fail", + message: [ + ...matchResult.toHumanStrings(), + JSON.stringify(matchResult.target, void 0, 2) + ].join("\n") + }) + }; + if (request2.failDeployment) { + throw new Error(result.data); + } + } else { + result = { + data: JSON.stringify({ + status: "success" + }) + }; + } + return result; + } +}; +var MatchCreator = class { + constructor(obj) { + this.parsedObj = { + matcher: obj + }; + } + getMatcher() { + try { + const final = JSON.parse(JSON.stringify(this.parsedObj), function(_k, v) { + const nested = Object.keys(v)[0]; + switch (nested) { + case "$ArrayWith": + return Match.arrayWith(v[nested]); + case "$ObjectLike": + return Match.objectLike(v[nested]); + case "$StringLike": + return Match.stringLikeRegexp(v[nested]); + default: + return v; + } + }); + if (Matcher.isMatcher(final.matcher)) { + return final.matcher; + } + return Match.exact(final.matcher); + } catch { + return Match.exact(this.parsedObj.matcher); + } + } +}; +function decodeCall(call) { + if (!call) { + return void 0; + } + try { + const parsed = JSON.parse(call); + return parsed; + } catch (e) { + return call; + } +} + +// lib/assertions/providers/lambda-handler/utils.ts +function decode(object) { + return JSON.parse(JSON.stringify(object), (_k, v) => { + switch (v) { + case "TRUE:BOOLEAN": + return true; + case "FALSE:BOOLEAN": + return false; + default: + return v; + } + }); +} + +// lib/assertions/providers/lambda-handler/sdk.ts +function flatten(object) { + return Object.assign( + {}, + ...function _flatten(child, path = []) { + return [].concat(...Object.keys(child).map((key) => { + const childKey = Buffer.isBuffer(child[key]) ? child[key].toString("utf8") : child[key]; + return typeof childKey === "object" && childKey !== null ? _flatten(childKey, path.concat([key])) : { [path.concat([key]).join(".")]: childKey }; + })); + }(object) + ); +} +var AwsApiCallHandler = class extends CustomResourceHandler { + async processEvent(request2) { + const AWS = require("aws-sdk"); + console.log(`AWS SDK VERSION: ${AWS.VERSION}`); + const service = new AWS[request2.service](); + const response = await service[request2.api](request2.parameters && decode(request2.parameters)).promise(); + console.log(`SDK response received ${JSON.stringify(response)}`); + delete response.ResponseMetadata; + const respond = { + apiCallResponse: response + }; + const flatData = { + ...flatten(respond) + }; + return request2.flattenResponse === "true" ? flatData : respond; + } +}; + +// lib/assertions/providers/lambda-handler/types.ts +var ASSERT_RESOURCE_TYPE = "Custom::DeployAssert@AssertEquals"; +var SDK_RESOURCE_TYPE_PREFIX = "Custom::DeployAssert@SdkCall"; + +// lib/assertions/providers/lambda-handler/index.ts +async function handler(event, context) { + const provider = createResourceHandler(event, context); + await provider.handle(); +} +function createResourceHandler(event, context) { + if (event.ResourceType.startsWith(SDK_RESOURCE_TYPE_PREFIX)) { + return new AwsApiCallHandler(event, context); + } + switch (event.ResourceType) { + case ASSERT_RESOURCE_TYPE: + return new AssertionHandler(event, context); + default: + throw new Error(`Unsupported resource type "${event.ResourceType}`); + } +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + handler +}); diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/asset.e3d888d855ebd2b6173af510e2eba9e1542084655559f4bb05adbb2e6ca63b73/index.py b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/asset.e3d888d855ebd2b6173af510e2eba9e1542084655559f4bb05adbb2e6ca63b73/index.py deleted file mode 100644 index 04f99eb108b30..0000000000000 --- a/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/asset.e3d888d855ebd2b6173af510e2eba9e1542084655559f4bb05adbb2e6ca63b73/index.py +++ /dev/null @@ -1,8 +0,0 @@ -import requests - -def handler(event, context): - response = requests.get('https://a0.awsstatic.com/main/images/logos/aws_smile-header-desktop-en-white_59x35.png', stream=True) - - print(response.status_code) - - return response.status_code diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/asset.e3d888d855ebd2b6173af510e2eba9e1542084655559f4bb05adbb2e6ca63b73/requirements.txt b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/asset.e3d888d855ebd2b6173af510e2eba9e1542084655559f4bb05adbb2e6ca63b73/requirements.txt deleted file mode 100644 index 4fcd85719fe3a..0000000000000 --- a/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/asset.e3d888d855ebd2b6173af510e2eba9e1542084655559f4bb05adbb2e6ca63b73/requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -# Lock versions of pip packages -certifi==2020.6.20 -chardet==3.0.4 -idna==2.10 -urllib3==1.26.7 -# Requests used by this lambda -requests==2.26.0 diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/cdk.out index 588d7b269d34f..8ecc185e9dbee 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/cdk-integ-lambda-python.assets.json b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/integ-lambda-python-function.assets.json similarity index 60% rename from packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/cdk-integ-lambda-python.assets.json rename to packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/integ-lambda-python-function.assets.json index e9b1b142625f1..43f3d57a184f8 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/cdk-integ-lambda-python.assets.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/integ-lambda-python-function.assets.json @@ -1,28 +1,28 @@ { - "version": "20.0.0", + "version": "21.0.0", "files": { - "15c6226da35cc14f12fdaece3b3d66dde7401588e7d26238ecd92d6200f19231": { + "75eef6be4f79fab5d65ef63569aac0de3aab47ca778c063cdea466e47c4ea755": { "source": { - "path": "asset.15c6226da35cc14f12fdaece3b3d66dde7401588e7d26238ecd92d6200f19231", + "path": "asset.75eef6be4f79fab5d65ef63569aac0de3aab47ca778c063cdea466e47c4ea755", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "15c6226da35cc14f12fdaece3b3d66dde7401588e7d26238ecd92d6200f19231.zip", + "objectKey": "75eef6be4f79fab5d65ef63569aac0de3aab47ca778c063cdea466e47c4ea755.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "3ac51f034af66ed4cf5ec29e168dc5079869d2f535647dc8ce28de4fe50c9dfe": { + "d759a2959a657473cc039ac933b56005d266cfc872bb8a2cb0b6a4c07aafff56": { "source": { - "path": "cdk-integ-lambda-python.template.json", + "path": "integ-lambda-python-function.template.json", "packaging": "file" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "3ac51f034af66ed4cf5ec29e168dc5079869d2f535647dc8ce28de4fe50c9dfe.json", + "objectKey": "d759a2959a657473cc039ac933b56005d266cfc872bb8a2cb0b6a4c07aafff56.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/cdk-integ-lambda-python.template.json b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/integ-lambda-python-function.template.json similarity index 86% rename from packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/cdk-integ-lambda-python.template.json rename to packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/integ-lambda-python-function.template.json index 06f084806a477..154f82a3e4dd6 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/cdk-integ-lambda-python.template.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/integ-lambda-python-function.template.json @@ -38,7 +38,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7641c95c909cbd220aa45f8b7dca8606bd48b9a84f0c5d28fa697c90c810983b.zip" + "S3Key": "75eef6be4f79fab5d65ef63569aac0de3aab47ca778c063cdea466e47c4ea755.zip" }, "Role": { "Fn::GetAtt": [ @@ -62,6 +62,14 @@ "Arn" ] } + }, + "ExportsOutputRefmyhandlerD202FA8E369E8804": { + "Value": { + "Ref": "myhandlerD202FA8E" + }, + "Export": { + "Name": "integ-lambda-python-function:ExportsOutputRefmyhandlerD202FA8E369E8804" + } } }, "Parameters": { diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/integ.json b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/integ.json index 7e46b862a610b..c9e27957a3b6a 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/integ.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/integ.json @@ -1,14 +1,13 @@ { - "version": "20.0.0", + "version": "21.0.0", "testCases": { - "integ.function": { + "lambda-python-function/DefaultTest": { "stacks": [ - "cdk-integ-lambda-python" + "integ-lambda-python-function" ], - "diffAssets": false, - "stackUpdateWorkflow": false + "stackUpdateWorkflow": false, + "assertionStack": "lambda-python-function/DefaultTest/DeployAssert", + "assertionStackName": "lambdapythonfunctionDefaultTestDeployAssertC9C6EE6F" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/lambdapythonfunctionDefaultTestDeployAssertC9C6EE6F.assets.json b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/lambdapythonfunctionDefaultTestDeployAssertC9C6EE6F.assets.json new file mode 100644 index 0000000000000..3197f8c05ca02 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/lambdapythonfunctionDefaultTestDeployAssertC9C6EE6F.assets.json @@ -0,0 +1,32 @@ +{ + "version": "21.0.0", + "files": { + "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7": { + "source": { + "path": "asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "f6fe40c0c1113210f5fd8c07b8e5ded3f7c35a6cfb554b207fc1523f10d9eaa9": { + "source": { + "path": "lambdapythonfunctionDefaultTestDeployAssertC9C6EE6F.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "f6fe40c0c1113210f5fd8c07b8e5ded3f7c35a6cfb554b207fc1523f10d9eaa9.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/lambdapythonfunctionDefaultTestDeployAssertC9C6EE6F.template.json b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/lambdapythonfunctionDefaultTestDeployAssertC9C6EE6F.template.json new file mode 100644 index 0000000000000..e35047e6cae8d --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/lambdapythonfunctionDefaultTestDeployAssertC9C6EE6F.template.json @@ -0,0 +1,198 @@ +{ + "Resources": { + "LambdaInvoke431773224924ebf10c8a31d363a6bf16": { + "Type": "Custom::DeployAssert@SdkCallLambdainvoke", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "service": "Lambda", + "api": "invoke", + "parameters": { + "FunctionName": { + "Fn::ImportValue": "integ-lambda-python-function:ExportsOutputRefmyhandlerD202FA8E369E8804" + } + }, + "flattenResponse": "false", + "salt": "1662643989220" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "LambdaInvoke431773224924ebf10c8a31d363a6bf16Invoke9BC0E67F": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::ImportValue": "integ-lambda-python-function:ExportsOutputRefmyhandlerD202FA8E369E8804" + }, + "Principal": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + }, + "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B": { + "Type": "Custom::DeployAssert@AssertEquals", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "actual": { + "Fn::GetAtt": [ + "LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "apiCallResponse" + ] + }, + "expected": "{\"$ObjectLike\":{\"Payload\":\"200\"}}", + "salt": "1662643989220" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "lambda:Invoke" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":lambda:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":function:", + { + "Fn::ImportValue": "integ-lambda-python-function:ExportsOutputRefmyhandlerD202FA8E369E8804" + } + ] + ] + } + ] + } + ] + } + } + ] + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Runtime": "nodejs14.x", + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip" + }, + "Timeout": 120, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + } + }, + "Outputs": { + "AssertionResultsAssertEqualsLambdainvoke64d766e0ddfdf2e2979fef994a5cd2aa": { + "Value": { + "Fn::GetAtt": [ + "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B", + "data" + ] + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/manifest.json index f636be5ffadca..1e64a7aae2f14 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "21.0.0", "artifacts": { "Tree": { "type": "cdk:tree", @@ -7,27 +7,27 @@ "file": "tree.json" } }, - "cdk-integ-lambda-python.assets": { + "integ-lambda-python-function.assets": { "type": "cdk:asset-manifest", "properties": { - "file": "cdk-integ-lambda-python.assets.json", + "file": "integ-lambda-python-function.assets.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" } }, - "cdk-integ-lambda-python": { + "integ-lambda-python-function": { "type": "aws:cloudformation:stack", "environment": "aws://unknown-account/unknown-region", "properties": { - "templateFile": "cdk-integ-lambda-python.template.json", + "templateFile": "integ-lambda-python-function.template.json", "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/477af51f71509ffb829d8b6113fc09006db7cbb48fb4a8e5427edd2caf847b43.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/d759a2959a657473cc039ac933b56005d266cfc872bb8a2cb0b6a4c07aafff56.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ - "cdk-integ-lambda-python.assets" + "integ-lambda-python-function.assets" ], "lookupRole": { "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", @@ -36,41 +36,131 @@ } }, "dependencies": [ - "cdk-integ-lambda-python.assets" + "integ-lambda-python-function.assets" ], "metadata": { - "/cdk-integ-lambda-python/my_handler/ServiceRole/Resource": [ + "/integ-lambda-python-function/my_handler/ServiceRole/Resource": [ { "type": "aws:cdk:logicalId", "data": "myhandlerServiceRole77891068" } ], - "/cdk-integ-lambda-python/my_handler/Resource": [ + "/integ-lambda-python-function/my_handler/Resource": [ { "type": "aws:cdk:logicalId", "data": "myhandlerD202FA8E" } ], - "/cdk-integ-lambda-python/FunctionArn": [ + "/integ-lambda-python-function/FunctionArn": [ { "type": "aws:cdk:logicalId", "data": "FunctionArn" } ], - "/cdk-integ-lambda-python/BootstrapVersion": [ + "/integ-lambda-python-function/Exports/Output{\"Ref\":\"myhandlerD202FA8E\"}": [ + { + "type": "aws:cdk:logicalId", + "data": "ExportsOutputRefmyhandlerD202FA8E369E8804" + } + ], + "/integ-lambda-python-function/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-lambda-python-function/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-lambda-python-function" + }, + "lambdapythonfunctionDefaultTestDeployAssertC9C6EE6F.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "lambdapythonfunctionDefaultTestDeployAssertC9C6EE6F.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "lambdapythonfunctionDefaultTestDeployAssertC9C6EE6F": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "lambdapythonfunctionDefaultTestDeployAssertC9C6EE6F.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/f6fe40c0c1113210f5fd8c07b8e5ded3f7c35a6cfb554b207fc1523f10d9eaa9.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "lambdapythonfunctionDefaultTestDeployAssertC9C6EE6F.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integ-lambda-python-function", + "lambdapythonfunctionDefaultTestDeployAssertC9C6EE6F.assets" + ], + "metadata": { + "/lambda-python-function/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16" + } + ], + "/lambda-python-function/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Invoke": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16Invoke9BC0E67F" + } + ], + "/lambda-python-function/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B" + } + ], + "/lambda-python-function/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionResults": [ + { + "type": "aws:cdk:logicalId", + "data": "AssertionResultsAssertEqualsLambdainvoke64d766e0ddfdf2e2979fef994a5cd2aa" + } + ], + "/lambda-python-function/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73" + } + ], + "/lambda-python-function/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F" + } + ], + "/lambda-python-function/DefaultTest/DeployAssert/BootstrapVersion": [ { "type": "aws:cdk:logicalId", "data": "BootstrapVersion" } ], - "/cdk-integ-lambda-python/CheckBootstrapVersion": [ + "/lambda-python-function/DefaultTest/DeployAssert/CheckBootstrapVersion": [ { "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } ] }, - "displayName": "cdk-integ-lambda-python" + "displayName": "lambda-python-function/DefaultTest/DeployAssert" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/tree.json b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/tree.json index 430541f9b0e5e..fb6f36cb47f0c 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/tree.json @@ -9,24 +9,24 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } }, - "cdk-integ-lambda-python": { - "id": "cdk-integ-lambda-python", - "path": "cdk-integ-lambda-python", + "integ-lambda-python-function": { + "id": "integ-lambda-python-function", + "path": "integ-lambda-python-function", "children": { "my_handler": { "id": "my_handler", - "path": "cdk-integ-lambda-python/my_handler", + "path": "integ-lambda-python-function/my_handler", "children": { "ServiceRole": { "id": "ServiceRole", - "path": "cdk-integ-lambda-python/my_handler/ServiceRole", + "path": "integ-lambda-python-function/my_handler/ServiceRole", "children": { "Resource": { "id": "Resource", - "path": "cdk-integ-lambda-python/my_handler/ServiceRole/Resource", + "path": "integ-lambda-python-function/my_handler/ServiceRole/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::IAM::Role", "aws:cdk:cloudformation:props": { @@ -71,19 +71,19 @@ }, "Code": { "id": "Code", - "path": "cdk-integ-lambda-python/my_handler/Code", + "path": "integ-lambda-python-function/my_handler/Code", "children": { "Stage": { "id": "Stage", - "path": "cdk-integ-lambda-python/my_handler/Code/Stage", + "path": "integ-lambda-python-function/my_handler/Code/Stage", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "AssetBucket": { "id": "AssetBucket", - "path": "cdk-integ-lambda-python/my_handler/Code/AssetBucket", + "path": "integ-lambda-python-function/my_handler/Code/AssetBucket", "constructInfo": { "fqn": "@aws-cdk/aws-s3.BucketBase", "version": "0.0.0" @@ -97,7 +97,7 @@ }, "Resource": { "id": "Resource", - "path": "cdk-integ-lambda-python/my_handler/Resource", + "path": "integ-lambda-python-function/my_handler/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { @@ -105,7 +105,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7641c95c909cbd220aa45f8b7dca8606bd48b9a84f0c5d28fa697c90c810983b.zip" + "s3Key": "75eef6be4f79fab5d65ef63569aac0de3aab47ca778c063cdea466e47c4ea755.zip" }, "role": { "Fn::GetAtt": [ @@ -130,22 +130,220 @@ }, "FunctionArn": { "id": "FunctionArn", - "path": "cdk-integ-lambda-python/FunctionArn", + "path": "integ-lambda-python-function/FunctionArn", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "Exports": { + "id": "Exports", + "path": "integ-lambda-python-function/Exports", + "children": { + "Output{\"Ref\":\"myhandlerD202FA8E\"}": { + "id": "Output{\"Ref\":\"myhandlerD202FA8E\"}", + "path": "integ-lambda-python-function/Exports/Output{\"Ref\":\"myhandlerD202FA8E\"}", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "lambda-python-function": { + "id": "lambda-python-function", + "path": "lambda-python-function", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "lambda-python-function/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "lambda-python-function/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "lambda-python-function/DefaultTest/DeployAssert", + "children": { + "LambdaInvoke431773224924ebf10c8a31d363a6bf16": { + "id": "LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "path": "lambda-python-function/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "children": { + "SdkProvider": { + "id": "SdkProvider", + "path": "lambda-python-function/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/SdkProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "lambda-python-function/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/SdkProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "Default": { + "id": "Default", + "path": "lambda-python-function/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default", + "children": { + "Default": { + "id": "Default", + "path": "lambda-python-function/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "Invoke": { + "id": "Invoke", + "path": "lambda-python-function/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Invoke", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "AssertEqualsLambdainvoke": { + "id": "AssertEqualsLambdainvoke", + "path": "lambda-python-function/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke", + "children": { + "AssertionProvider": { + "id": "AssertionProvider", + "path": "lambda-python-function/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "lambda-python-function/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "Default": { + "id": "Default", + "path": "lambda-python-function/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default", + "children": { + "Default": { + "id": "Default", + "path": "lambda-python-function/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "AssertionResults": { + "id": "AssertionResults", + "path": "lambda-python-function/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionResults", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81": { + "id": "SingletonFunction1488541a7b23466481b69b4408076b81", + "path": "lambda-python-function/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81", + "children": { + "Staging": { + "id": "Staging", + "path": "lambda-python-function/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Staging", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "lambda-python-function/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "lambda-python-function/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/asset.288e5ca58229165a54fd3bfcfd7765b7726ba2acc91b765d7e92b70bbd91a859/index.py b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/asset.288e5ca58229165a54fd3bfcfd7765b7726ba2acc91b765d7e92b70bbd91a859/index.py deleted file mode 100644 index d7b2ce8db00e9..0000000000000 --- a/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/asset.288e5ca58229165a54fd3bfcfd7765b7726ba2acc91b765d7e92b70bbd91a859/index.py +++ /dev/null @@ -1,5 +0,0 @@ -from http import HTTPStatus - -def handler(event, context): - print('No dependencies') - return HTTPStatus.OK.value diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js new file mode 100644 index 0000000000000..ba956d47f51fe --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js @@ -0,0 +1,612 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// lib/assertions/providers/lambda-handler/index.ts +var lambda_handler_exports = {}; +__export(lambda_handler_exports, { + handler: () => handler +}); +module.exports = __toCommonJS(lambda_handler_exports); + +// ../assertions/lib/matcher.ts +var Matcher = class { + static isMatcher(x) { + return x && x instanceof Matcher; + } +}; +var MatchResult = class { + constructor(target) { + this.failures = []; + this.captures = /* @__PURE__ */ new Map(); + this.finalized = false; + this.target = target; + } + push(matcher, path, message) { + return this.recordFailure({ matcher, path, message }); + } + recordFailure(failure) { + this.failures.push(failure); + return this; + } + hasFailed() { + return this.failures.length !== 0; + } + get failCount() { + return this.failures.length; + } + compose(id, inner) { + const innerF = inner.failures; + this.failures.push(...innerF.map((f) => { + return { path: [id, ...f.path], message: f.message, matcher: f.matcher }; + })); + inner.captures.forEach((vals, capture) => { + vals.forEach((value) => this.recordCapture({ capture, value })); + }); + return this; + } + finished() { + if (this.finalized) { + return this; + } + if (this.failCount === 0) { + this.captures.forEach((vals, cap) => cap._captured.push(...vals)); + } + this.finalized = true; + return this; + } + toHumanStrings() { + return this.failures.map((r) => { + const loc = r.path.length === 0 ? "" : ` at ${r.path.join("")}`; + return "" + r.message + loc + ` (using ${r.matcher.name} matcher)`; + }); + } + recordCapture(options) { + let values = this.captures.get(options.capture); + if (values === void 0) { + values = []; + } + values.push(options.value); + this.captures.set(options.capture, values); + } +}; + +// ../assertions/lib/private/matchers/absent.ts +var AbsentMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual !== void 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Received ${actual}, but key should be absent` + }); + } + return result; + } +}; + +// ../assertions/lib/private/type.ts +function getType(obj) { + return Array.isArray(obj) ? "array" : typeof obj; +} + +// ../assertions/lib/match.ts +var Match = class { + static absent() { + return new AbsentMatch("absent"); + } + static arrayWith(pattern) { + return new ArrayMatch("arrayWith", pattern); + } + static arrayEquals(pattern) { + return new ArrayMatch("arrayEquals", pattern, { subsequence: false }); + } + static exact(pattern) { + return new LiteralMatch("exact", pattern, { partialObjects: false }); + } + static objectLike(pattern) { + return new ObjectMatch("objectLike", pattern); + } + static objectEquals(pattern) { + return new ObjectMatch("objectEquals", pattern, { partial: false }); + } + static not(pattern) { + return new NotMatch("not", pattern); + } + static serializedJson(pattern) { + return new SerializedJson("serializedJson", pattern); + } + static anyValue() { + return new AnyMatch("anyValue"); + } + static stringLikeRegexp(pattern) { + return new StringLikeRegexpMatch("stringLikeRegexp", pattern); + } +}; +var LiteralMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partialObjects = options.partialObjects ?? false; + if (Matcher.isMatcher(this.pattern)) { + throw new Error("LiteralMatch cannot directly contain another matcher. Remove the top-level matcher or nest it more deeply."); + } + } + test(actual) { + if (Array.isArray(this.pattern)) { + return new ArrayMatch(this.name, this.pattern, { subsequence: false, partialObjects: this.partialObjects }).test(actual); + } + if (typeof this.pattern === "object") { + return new ObjectMatch(this.name, this.pattern, { partial: this.partialObjects }).test(actual); + } + const result = new MatchResult(actual); + if (typeof this.pattern !== typeof actual) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected type ${typeof this.pattern} but received ${getType(actual)}` + }); + return result; + } + if (actual !== this.pattern) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected ${this.pattern} but received ${actual}` + }); + } + return result; + } +}; +var ArrayMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.subsequence = options.subsequence ?? true; + this.partialObjects = options.partialObjects ?? false; + } + test(actual) { + if (!Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type array but received ${getType(actual)}` + }); + } + if (!this.subsequence && this.pattern.length !== actual.length) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected array of length ${this.pattern.length} but received ${actual.length}` + }); + } + let patternIdx = 0; + let actualIdx = 0; + const result = new MatchResult(actual); + while (patternIdx < this.pattern.length && actualIdx < actual.length) { + const patternElement = this.pattern[patternIdx]; + const matcher = Matcher.isMatcher(patternElement) ? patternElement : new LiteralMatch(this.name, patternElement, { partialObjects: this.partialObjects }); + const matcherName = matcher.name; + if (this.subsequence && (matcherName == "absent" || matcherName == "anyValue")) { + throw new Error(`The Matcher ${matcherName}() cannot be nested within arrayWith()`); + } + const innerResult = matcher.test(actual[actualIdx]); + if (!this.subsequence || !innerResult.hasFailed()) { + result.compose(`[${actualIdx}]`, innerResult); + patternIdx++; + actualIdx++; + } else { + actualIdx++; + } + } + for (; patternIdx < this.pattern.length; patternIdx++) { + const pattern = this.pattern[patternIdx]; + const element = Matcher.isMatcher(pattern) || typeof pattern === "object" ? " " : ` [${pattern}] `; + result.recordFailure({ + matcher: this, + path: [], + message: `Missing element${element}at pattern index ${patternIdx}` + }); + } + return result; + } +}; +var ObjectMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partial = options.partial ?? true; + } + test(actual) { + if (typeof actual !== "object" || Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type object but received ${getType(actual)}` + }); + } + const result = new MatchResult(actual); + if (!this.partial) { + for (const a of Object.keys(actual)) { + if (!(a in this.pattern)) { + result.recordFailure({ + matcher: this, + path: [`/${a}`], + message: "Unexpected key" + }); + } + } + } + for (const [patternKey, patternVal] of Object.entries(this.pattern)) { + if (!(patternKey in actual) && !(patternVal instanceof AbsentMatch)) { + result.recordFailure({ + matcher: this, + path: [`/${patternKey}`], + message: `Missing key '${patternKey}' among {${Object.keys(actual).join(",")}}` + }); + continue; + } + const matcher = Matcher.isMatcher(patternVal) ? patternVal : new LiteralMatch(this.name, patternVal, { partialObjects: this.partial }); + const inner = matcher.test(actual[patternKey]); + result.compose(`/${patternKey}`, inner); + } + return result; + } +}; +var SerializedJson = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + if (getType(actual) !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected JSON as a string but found ${getType(actual)}` + }); + return result; + } + let parsed; + try { + parsed = JSON.parse(actual); + } catch (err) { + if (err instanceof SyntaxError) { + result.recordFailure({ + matcher: this, + path: [], + message: `Invalid JSON string: ${actual}` + }); + return result; + } else { + throw err; + } + } + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(parsed); + result.compose(`(${this.name})`, innerResult); + return result; + } +}; +var NotMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(actual); + const result = new MatchResult(actual); + if (innerResult.failCount === 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Found unexpected match: ${JSON.stringify(actual, void 0, 2)}` + }); + } + return result; + } +}; +var AnyMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual == null) { + result.recordFailure({ + matcher: this, + path: [], + message: "Expected a value but found none" + }); + } + return result; + } +}; +var StringLikeRegexpMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + const regex = new RegExp(this.pattern, "gm"); + if (typeof actual !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected a string, but got '${typeof actual}'` + }); + } + if (!regex.test(actual)) { + result.recordFailure({ + matcher: this, + path: [], + message: `String '${actual}' did not match pattern '${this.pattern}'` + }); + } + return result; + } +}; + +// lib/assertions/providers/lambda-handler/base.ts +var https = __toESM(require("https")); +var url = __toESM(require("url")); +var CustomResourceHandler = class { + constructor(event, context) { + this.event = event; + this.context = context; + this.timedOut = false; + this.timeout = setTimeout(async () => { + await this.respond({ + status: "FAILED", + reason: "Lambda Function Timeout", + data: this.context.logStreamName + }); + this.timedOut = true; + }, context.getRemainingTimeInMillis() - 1200); + this.event = event; + this.physicalResourceId = extractPhysicalResourceId(event); + } + async handle() { + try { + console.log(`Event: ${JSON.stringify({ ...this.event, ResponseURL: "..." })}`); + const response = await this.processEvent(this.event.ResourceProperties); + console.log(`Event output : ${JSON.stringify(response)}`); + await this.respond({ + status: "SUCCESS", + reason: "OK", + data: response + }); + } catch (e) { + console.log(e); + await this.respond({ + status: "FAILED", + reason: e.message ?? "Internal Error" + }); + } finally { + clearTimeout(this.timeout); + } + } + respond(response) { + if (this.timedOut) { + return; + } + const cfResponse = { + Status: response.status, + Reason: response.reason, + PhysicalResourceId: this.physicalResourceId, + StackId: this.event.StackId, + RequestId: this.event.RequestId, + LogicalResourceId: this.event.LogicalResourceId, + NoEcho: false, + Data: response.data + }; + const responseBody = JSON.stringify(cfResponse); + console.log("Responding to CloudFormation", responseBody); + const parsedUrl = url.parse(this.event.ResponseURL); + const requestOptions = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: "PUT", + headers: { "content-type": "", "content-length": responseBody.length } + }; + return new Promise((resolve, reject) => { + try { + const request2 = https.request(requestOptions, resolve); + request2.on("error", reject); + request2.write(responseBody); + request2.end(); + } catch (e) { + reject(e); + } + }); + } +}; +function extractPhysicalResourceId(event) { + switch (event.RequestType) { + case "Create": + return event.LogicalResourceId; + case "Update": + case "Delete": + return event.PhysicalResourceId; + } +} + +// lib/assertions/providers/lambda-handler/assertion.ts +var AssertionHandler = class extends CustomResourceHandler { + async processEvent(request2) { + let actual = decodeCall(request2.actual); + const expected = decodeCall(request2.expected); + let result; + const matcher = new MatchCreator(expected).getMatcher(); + console.log(`Testing equality between ${JSON.stringify(request2.actual)} and ${JSON.stringify(request2.expected)}`); + const matchResult = matcher.test(actual); + matchResult.finished(); + if (matchResult.hasFailed()) { + result = { + data: JSON.stringify({ + status: "fail", + message: [ + ...matchResult.toHumanStrings(), + JSON.stringify(matchResult.target, void 0, 2) + ].join("\n") + }) + }; + if (request2.failDeployment) { + throw new Error(result.data); + } + } else { + result = { + data: JSON.stringify({ + status: "success" + }) + }; + } + return result; + } +}; +var MatchCreator = class { + constructor(obj) { + this.parsedObj = { + matcher: obj + }; + } + getMatcher() { + try { + const final = JSON.parse(JSON.stringify(this.parsedObj), function(_k, v) { + const nested = Object.keys(v)[0]; + switch (nested) { + case "$ArrayWith": + return Match.arrayWith(v[nested]); + case "$ObjectLike": + return Match.objectLike(v[nested]); + case "$StringLike": + return Match.stringLikeRegexp(v[nested]); + default: + return v; + } + }); + if (Matcher.isMatcher(final.matcher)) { + return final.matcher; + } + return Match.exact(final.matcher); + } catch { + return Match.exact(this.parsedObj.matcher); + } + } +}; +function decodeCall(call) { + if (!call) { + return void 0; + } + try { + const parsed = JSON.parse(call); + return parsed; + } catch (e) { + return call; + } +} + +// lib/assertions/providers/lambda-handler/utils.ts +function decode(object) { + return JSON.parse(JSON.stringify(object), (_k, v) => { + switch (v) { + case "TRUE:BOOLEAN": + return true; + case "FALSE:BOOLEAN": + return false; + default: + return v; + } + }); +} + +// lib/assertions/providers/lambda-handler/sdk.ts +function flatten(object) { + return Object.assign( + {}, + ...function _flatten(child, path = []) { + return [].concat(...Object.keys(child).map((key) => { + const childKey = Buffer.isBuffer(child[key]) ? child[key].toString("utf8") : child[key]; + return typeof childKey === "object" && childKey !== null ? _flatten(childKey, path.concat([key])) : { [path.concat([key]).join(".")]: childKey }; + })); + }(object) + ); +} +var AwsApiCallHandler = class extends CustomResourceHandler { + async processEvent(request2) { + const AWS = require("aws-sdk"); + console.log(`AWS SDK VERSION: ${AWS.VERSION}`); + const service = new AWS[request2.service](); + const response = await service[request2.api](request2.parameters && decode(request2.parameters)).promise(); + console.log(`SDK response received ${JSON.stringify(response)}`); + delete response.ResponseMetadata; + const respond = { + apiCallResponse: response + }; + const flatData = { + ...flatten(respond) + }; + return request2.flattenResponse === "true" ? flatData : respond; + } +}; + +// lib/assertions/providers/lambda-handler/types.ts +var ASSERT_RESOURCE_TYPE = "Custom::DeployAssert@AssertEquals"; +var SDK_RESOURCE_TYPE_PREFIX = "Custom::DeployAssert@SdkCall"; + +// lib/assertions/providers/lambda-handler/index.ts +async function handler(event, context) { + const provider = createResourceHandler(event, context); + await provider.handle(); +} +function createResourceHandler(event, context) { + if (event.ResourceType.startsWith(SDK_RESOURCE_TYPE_PREFIX)) { + return new AwsApiCallHandler(event, context); + } + switch (event.ResourceType) { + case ASSERT_RESOURCE_TYPE: + return new AssertionHandler(event, context); + default: + throw new Error(`Unsupported resource type "${event.ResourceType}`); + } +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + handler +}); diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/asset.8c24af4ca0853fa9cd2372aa99864ccd1554740ac76e69773c82ba334df77f04/index.py b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/asset.8c24af4ca0853fa9cd2372aa99864ccd1554740ac76e69773c82ba334df77f04/index.py deleted file mode 100644 index d7b2ce8db00e9..0000000000000 --- a/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/asset.8c24af4ca0853fa9cd2372aa99864ccd1554740ac76e69773c82ba334df77f04/index.py +++ /dev/null @@ -1,5 +0,0 @@ -from http import HTTPStatus - -def handler(event, context): - print('No dependencies') - return HTTPStatus.OK.value diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/cdk.out index 588d7b269d34f..8ecc185e9dbee 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/cdk-integ-lambda-python.assets.json b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/integ-lambda-python-nodeps.assets.json similarity index 60% rename from packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/cdk-integ-lambda-python.assets.json rename to packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/integ-lambda-python-nodeps.assets.json index 99c7bfe99ecce..773a6dfface53 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.integ.snapshot/cdk-integ-lambda-python.assets.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/integ-lambda-python-nodeps.assets.json @@ -1,28 +1,28 @@ { - "version": "20.0.0", + "version": "21.0.0", "files": { - "7641c95c909cbd220aa45f8b7dca8606bd48b9a84f0c5d28fa697c90c810983b": { + "12865c7bd1f821f245cacee7dc33770eae9ee5949892a310a41215c18f7981ba": { "source": { - "path": "asset.7641c95c909cbd220aa45f8b7dca8606bd48b9a84f0c5d28fa697c90c810983b", + "path": "asset.12865c7bd1f821f245cacee7dc33770eae9ee5949892a310a41215c18f7981ba", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "7641c95c909cbd220aa45f8b7dca8606bd48b9a84f0c5d28fa697c90c810983b.zip", + "objectKey": "12865c7bd1f821f245cacee7dc33770eae9ee5949892a310a41215c18f7981ba.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "477af51f71509ffb829d8b6113fc09006db7cbb48fb4a8e5427edd2caf847b43": { + "6c83238cbeaebf4555ddfb62f76638b6e1b8cb26ea7f6d8d74b17829b772a2a9": { "source": { - "path": "cdk-integ-lambda-python.template.json", + "path": "integ-lambda-python-nodeps.template.json", "packaging": "file" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "477af51f71509ffb829d8b6113fc09006db7cbb48fb4a8e5427edd2caf847b43.json", + "objectKey": "6c83238cbeaebf4555ddfb62f76638b6e1b8cb26ea7f6d8d74b17829b772a2a9.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/cdk-integ-lambda-python.template.json b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/integ-lambda-python-nodeps.template.json similarity index 86% rename from packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/cdk-integ-lambda-python.template.json rename to packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/integ-lambda-python-nodeps.template.json index f924f6b715805..a3a1475d783ff 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/cdk-integ-lambda-python.template.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/integ-lambda-python-nodeps.template.json @@ -38,7 +38,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "8c24af4ca0853fa9cd2372aa99864ccd1554740ac76e69773c82ba334df77f04.zip" + "S3Key": "12865c7bd1f821f245cacee7dc33770eae9ee5949892a310a41215c18f7981ba.zip" }, "Role": { "Fn::GetAtt": [ @@ -62,6 +62,14 @@ "Arn" ] } + }, + "ExportsOutputRefmyhandlerD202FA8E369E8804": { + "Value": { + "Ref": "myhandlerD202FA8E" + }, + "Export": { + "Name": "integ-lambda-python-nodeps:ExportsOutputRefmyhandlerD202FA8E369E8804" + } } }, "Parameters": { diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/integ.json b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/integ.json index 9c2b4f90fafc5..91644289f1c9b 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/integ.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/integ.json @@ -1,14 +1,13 @@ { - "version": "20.0.0", + "version": "21.0.0", "testCases": { - "integ.function.nodeps": { + "lambda-python-nodeps/DefaultTest": { "stacks": [ - "cdk-integ-lambda-python" + "integ-lambda-python-nodeps" ], - "diffAssets": false, - "stackUpdateWorkflow": true + "stackUpdateWorkflow": false, + "assertionStack": "lambda-python-nodeps/DefaultTest/DeployAssert", + "assertionStackName": "lambdapythonnodepsDefaultTestDeployAssert72A584F7" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/lambdapythonnodepsDefaultTestDeployAssert72A584F7.assets.json b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/lambdapythonnodepsDefaultTestDeployAssert72A584F7.assets.json new file mode 100644 index 0000000000000..25987fbfff275 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/lambdapythonnodepsDefaultTestDeployAssert72A584F7.assets.json @@ -0,0 +1,32 @@ +{ + "version": "21.0.0", + "files": { + "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7": { + "source": { + "path": "asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "f932a81c9e35cee37f730db7ffdbfc20701787edba3b3ed67a6792c204e969f2": { + "source": { + "path": "lambdapythonnodepsDefaultTestDeployAssert72A584F7.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "f932a81c9e35cee37f730db7ffdbfc20701787edba3b3ed67a6792c204e969f2.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/lambdapythonnodepsDefaultTestDeployAssert72A584F7.template.json b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/lambdapythonnodepsDefaultTestDeployAssert72A584F7.template.json new file mode 100644 index 0000000000000..6121cf793e527 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/lambdapythonnodepsDefaultTestDeployAssert72A584F7.template.json @@ -0,0 +1,198 @@ +{ + "Resources": { + "LambdaInvoke431773224924ebf10c8a31d363a6bf16": { + "Type": "Custom::DeployAssert@SdkCallLambdainvoke", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "service": "Lambda", + "api": "invoke", + "parameters": { + "FunctionName": { + "Fn::ImportValue": "integ-lambda-python-nodeps:ExportsOutputRefmyhandlerD202FA8E369E8804" + } + }, + "flattenResponse": "false", + "salt": "1662643910889" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "LambdaInvoke431773224924ebf10c8a31d363a6bf16Invoke9BC0E67F": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::ImportValue": "integ-lambda-python-nodeps:ExportsOutputRefmyhandlerD202FA8E369E8804" + }, + "Principal": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + }, + "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B": { + "Type": "Custom::DeployAssert@AssertEquals", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "actual": { + "Fn::GetAtt": [ + "LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "apiCallResponse" + ] + }, + "expected": "{\"$ObjectLike\":{\"Payload\":\"200\"}}", + "salt": "1662643910889" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "lambda:Invoke" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":lambda:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":function:", + { + "Fn::ImportValue": "integ-lambda-python-nodeps:ExportsOutputRefmyhandlerD202FA8E369E8804" + } + ] + ] + } + ] + } + ] + } + } + ] + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Runtime": "nodejs14.x", + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip" + }, + "Timeout": 120, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + } + }, + "Outputs": { + "AssertionResultsAssertEqualsLambdainvoke355665d3c1afb350a666dab592942021": { + "Value": { + "Fn::GetAtt": [ + "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B", + "data" + ] + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/manifest.json index da2874f130c5e..dc728215f0233 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "21.0.0", "artifacts": { "Tree": { "type": "cdk:tree", @@ -7,27 +7,27 @@ "file": "tree.json" } }, - "cdk-integ-lambda-python.assets": { + "integ-lambda-python-nodeps.assets": { "type": "cdk:asset-manifest", "properties": { - "file": "cdk-integ-lambda-python.assets.json", + "file": "integ-lambda-python-nodeps.assets.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" } }, - "cdk-integ-lambda-python": { + "integ-lambda-python-nodeps": { "type": "aws:cloudformation:stack", "environment": "aws://unknown-account/unknown-region", "properties": { - "templateFile": "cdk-integ-lambda-python.template.json", + "templateFile": "integ-lambda-python-nodeps.template.json", "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/281037e987baf7d3abbb443b0ceb1c7e3a6eaaade8bb12ca2c25c236a3c065d7.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/6c83238cbeaebf4555ddfb62f76638b6e1b8cb26ea7f6d8d74b17829b772a2a9.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ - "cdk-integ-lambda-python.assets" + "integ-lambda-python-nodeps.assets" ], "lookupRole": { "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", @@ -36,41 +36,131 @@ } }, "dependencies": [ - "cdk-integ-lambda-python.assets" + "integ-lambda-python-nodeps.assets" ], "metadata": { - "/cdk-integ-lambda-python/my_handler/ServiceRole/Resource": [ + "/integ-lambda-python-nodeps/my_handler/ServiceRole/Resource": [ { "type": "aws:cdk:logicalId", "data": "myhandlerServiceRole77891068" } ], - "/cdk-integ-lambda-python/my_handler/Resource": [ + "/integ-lambda-python-nodeps/my_handler/Resource": [ { "type": "aws:cdk:logicalId", "data": "myhandlerD202FA8E" } ], - "/cdk-integ-lambda-python/FunctionArn": [ + "/integ-lambda-python-nodeps/FunctionArn": [ { "type": "aws:cdk:logicalId", "data": "FunctionArn" } ], - "/cdk-integ-lambda-python/BootstrapVersion": [ + "/integ-lambda-python-nodeps/Exports/Output{\"Ref\":\"myhandlerD202FA8E\"}": [ + { + "type": "aws:cdk:logicalId", + "data": "ExportsOutputRefmyhandlerD202FA8E369E8804" + } + ], + "/integ-lambda-python-nodeps/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-lambda-python-nodeps/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-lambda-python-nodeps" + }, + "lambdapythonnodepsDefaultTestDeployAssert72A584F7.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "lambdapythonnodepsDefaultTestDeployAssert72A584F7.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "lambdapythonnodepsDefaultTestDeployAssert72A584F7": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "lambdapythonnodepsDefaultTestDeployAssert72A584F7.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/f932a81c9e35cee37f730db7ffdbfc20701787edba3b3ed67a6792c204e969f2.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "lambdapythonnodepsDefaultTestDeployAssert72A584F7.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integ-lambda-python-nodeps", + "lambdapythonnodepsDefaultTestDeployAssert72A584F7.assets" + ], + "metadata": { + "/lambda-python-nodeps/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16" + } + ], + "/lambda-python-nodeps/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Invoke": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16Invoke9BC0E67F" + } + ], + "/lambda-python-nodeps/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B" + } + ], + "/lambda-python-nodeps/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionResults": [ + { + "type": "aws:cdk:logicalId", + "data": "AssertionResultsAssertEqualsLambdainvoke355665d3c1afb350a666dab592942021" + } + ], + "/lambda-python-nodeps/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73" + } + ], + "/lambda-python-nodeps/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F" + } + ], + "/lambda-python-nodeps/DefaultTest/DeployAssert/BootstrapVersion": [ { "type": "aws:cdk:logicalId", "data": "BootstrapVersion" } ], - "/cdk-integ-lambda-python/CheckBootstrapVersion": [ + "/lambda-python-nodeps/DefaultTest/DeployAssert/CheckBootstrapVersion": [ { "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } ] }, - "displayName": "cdk-integ-lambda-python" + "displayName": "lambda-python-nodeps/DefaultTest/DeployAssert" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/tree.json b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/tree.json index 54c5c82dcfdac..88a2a88bdaf1e 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/tree.json @@ -9,24 +9,24 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } }, - "cdk-integ-lambda-python": { - "id": "cdk-integ-lambda-python", - "path": "cdk-integ-lambda-python", + "integ-lambda-python-nodeps": { + "id": "integ-lambda-python-nodeps", + "path": "integ-lambda-python-nodeps", "children": { "my_handler": { "id": "my_handler", - "path": "cdk-integ-lambda-python/my_handler", + "path": "integ-lambda-python-nodeps/my_handler", "children": { "ServiceRole": { "id": "ServiceRole", - "path": "cdk-integ-lambda-python/my_handler/ServiceRole", + "path": "integ-lambda-python-nodeps/my_handler/ServiceRole", "children": { "Resource": { "id": "Resource", - "path": "cdk-integ-lambda-python/my_handler/ServiceRole/Resource", + "path": "integ-lambda-python-nodeps/my_handler/ServiceRole/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::IAM::Role", "aws:cdk:cloudformation:props": { @@ -71,19 +71,19 @@ }, "Code": { "id": "Code", - "path": "cdk-integ-lambda-python/my_handler/Code", + "path": "integ-lambda-python-nodeps/my_handler/Code", "children": { "Stage": { "id": "Stage", - "path": "cdk-integ-lambda-python/my_handler/Code/Stage", + "path": "integ-lambda-python-nodeps/my_handler/Code/Stage", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "AssetBucket": { "id": "AssetBucket", - "path": "cdk-integ-lambda-python/my_handler/Code/AssetBucket", + "path": "integ-lambda-python-nodeps/my_handler/Code/AssetBucket", "constructInfo": { "fqn": "@aws-cdk/aws-s3.BucketBase", "version": "0.0.0" @@ -97,7 +97,7 @@ }, "Resource": { "id": "Resource", - "path": "cdk-integ-lambda-python/my_handler/Resource", + "path": "integ-lambda-python-nodeps/my_handler/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { @@ -105,7 +105,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "8c24af4ca0853fa9cd2372aa99864ccd1554740ac76e69773c82ba334df77f04.zip" + "s3Key": "12865c7bd1f821f245cacee7dc33770eae9ee5949892a310a41215c18f7981ba.zip" }, "role": { "Fn::GetAtt": [ @@ -130,22 +130,220 @@ }, "FunctionArn": { "id": "FunctionArn", - "path": "cdk-integ-lambda-python/FunctionArn", + "path": "integ-lambda-python-nodeps/FunctionArn", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "Exports": { + "id": "Exports", + "path": "integ-lambda-python-nodeps/Exports", + "children": { + "Output{\"Ref\":\"myhandlerD202FA8E\"}": { + "id": "Output{\"Ref\":\"myhandlerD202FA8E\"}", + "path": "integ-lambda-python-nodeps/Exports/Output{\"Ref\":\"myhandlerD202FA8E\"}", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "lambda-python-nodeps": { + "id": "lambda-python-nodeps", + "path": "lambda-python-nodeps", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "lambda-python-nodeps/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "lambda-python-nodeps/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "lambda-python-nodeps/DefaultTest/DeployAssert", + "children": { + "LambdaInvoke431773224924ebf10c8a31d363a6bf16": { + "id": "LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "path": "lambda-python-nodeps/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "children": { + "SdkProvider": { + "id": "SdkProvider", + "path": "lambda-python-nodeps/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/SdkProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "lambda-python-nodeps/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/SdkProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "Default": { + "id": "Default", + "path": "lambda-python-nodeps/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default", + "children": { + "Default": { + "id": "Default", + "path": "lambda-python-nodeps/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "Invoke": { + "id": "Invoke", + "path": "lambda-python-nodeps/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Invoke", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "AssertEqualsLambdainvoke": { + "id": "AssertEqualsLambdainvoke", + "path": "lambda-python-nodeps/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke", + "children": { + "AssertionProvider": { + "id": "AssertionProvider", + "path": "lambda-python-nodeps/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "lambda-python-nodeps/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "Default": { + "id": "Default", + "path": "lambda-python-nodeps/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default", + "children": { + "Default": { + "id": "Default", + "path": "lambda-python-nodeps/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "AssertionResults": { + "id": "AssertionResults", + "path": "lambda-python-nodeps/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionResults", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81": { + "id": "SingletonFunction1488541a7b23466481b69b4408076b81", + "path": "lambda-python-nodeps/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81", + "children": { + "Staging": { + "id": "Staging", + "path": "lambda-python-nodeps/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Staging", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "lambda-python-nodeps/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "lambda-python-nodeps/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js new file mode 100644 index 0000000000000..ba956d47f51fe --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js @@ -0,0 +1,612 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// lib/assertions/providers/lambda-handler/index.ts +var lambda_handler_exports = {}; +__export(lambda_handler_exports, { + handler: () => handler +}); +module.exports = __toCommonJS(lambda_handler_exports); + +// ../assertions/lib/matcher.ts +var Matcher = class { + static isMatcher(x) { + return x && x instanceof Matcher; + } +}; +var MatchResult = class { + constructor(target) { + this.failures = []; + this.captures = /* @__PURE__ */ new Map(); + this.finalized = false; + this.target = target; + } + push(matcher, path, message) { + return this.recordFailure({ matcher, path, message }); + } + recordFailure(failure) { + this.failures.push(failure); + return this; + } + hasFailed() { + return this.failures.length !== 0; + } + get failCount() { + return this.failures.length; + } + compose(id, inner) { + const innerF = inner.failures; + this.failures.push(...innerF.map((f) => { + return { path: [id, ...f.path], message: f.message, matcher: f.matcher }; + })); + inner.captures.forEach((vals, capture) => { + vals.forEach((value) => this.recordCapture({ capture, value })); + }); + return this; + } + finished() { + if (this.finalized) { + return this; + } + if (this.failCount === 0) { + this.captures.forEach((vals, cap) => cap._captured.push(...vals)); + } + this.finalized = true; + return this; + } + toHumanStrings() { + return this.failures.map((r) => { + const loc = r.path.length === 0 ? "" : ` at ${r.path.join("")}`; + return "" + r.message + loc + ` (using ${r.matcher.name} matcher)`; + }); + } + recordCapture(options) { + let values = this.captures.get(options.capture); + if (values === void 0) { + values = []; + } + values.push(options.value); + this.captures.set(options.capture, values); + } +}; + +// ../assertions/lib/private/matchers/absent.ts +var AbsentMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual !== void 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Received ${actual}, but key should be absent` + }); + } + return result; + } +}; + +// ../assertions/lib/private/type.ts +function getType(obj) { + return Array.isArray(obj) ? "array" : typeof obj; +} + +// ../assertions/lib/match.ts +var Match = class { + static absent() { + return new AbsentMatch("absent"); + } + static arrayWith(pattern) { + return new ArrayMatch("arrayWith", pattern); + } + static arrayEquals(pattern) { + return new ArrayMatch("arrayEquals", pattern, { subsequence: false }); + } + static exact(pattern) { + return new LiteralMatch("exact", pattern, { partialObjects: false }); + } + static objectLike(pattern) { + return new ObjectMatch("objectLike", pattern); + } + static objectEquals(pattern) { + return new ObjectMatch("objectEquals", pattern, { partial: false }); + } + static not(pattern) { + return new NotMatch("not", pattern); + } + static serializedJson(pattern) { + return new SerializedJson("serializedJson", pattern); + } + static anyValue() { + return new AnyMatch("anyValue"); + } + static stringLikeRegexp(pattern) { + return new StringLikeRegexpMatch("stringLikeRegexp", pattern); + } +}; +var LiteralMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partialObjects = options.partialObjects ?? false; + if (Matcher.isMatcher(this.pattern)) { + throw new Error("LiteralMatch cannot directly contain another matcher. Remove the top-level matcher or nest it more deeply."); + } + } + test(actual) { + if (Array.isArray(this.pattern)) { + return new ArrayMatch(this.name, this.pattern, { subsequence: false, partialObjects: this.partialObjects }).test(actual); + } + if (typeof this.pattern === "object") { + return new ObjectMatch(this.name, this.pattern, { partial: this.partialObjects }).test(actual); + } + const result = new MatchResult(actual); + if (typeof this.pattern !== typeof actual) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected type ${typeof this.pattern} but received ${getType(actual)}` + }); + return result; + } + if (actual !== this.pattern) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected ${this.pattern} but received ${actual}` + }); + } + return result; + } +}; +var ArrayMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.subsequence = options.subsequence ?? true; + this.partialObjects = options.partialObjects ?? false; + } + test(actual) { + if (!Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type array but received ${getType(actual)}` + }); + } + if (!this.subsequence && this.pattern.length !== actual.length) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected array of length ${this.pattern.length} but received ${actual.length}` + }); + } + let patternIdx = 0; + let actualIdx = 0; + const result = new MatchResult(actual); + while (patternIdx < this.pattern.length && actualIdx < actual.length) { + const patternElement = this.pattern[patternIdx]; + const matcher = Matcher.isMatcher(patternElement) ? patternElement : new LiteralMatch(this.name, patternElement, { partialObjects: this.partialObjects }); + const matcherName = matcher.name; + if (this.subsequence && (matcherName == "absent" || matcherName == "anyValue")) { + throw new Error(`The Matcher ${matcherName}() cannot be nested within arrayWith()`); + } + const innerResult = matcher.test(actual[actualIdx]); + if (!this.subsequence || !innerResult.hasFailed()) { + result.compose(`[${actualIdx}]`, innerResult); + patternIdx++; + actualIdx++; + } else { + actualIdx++; + } + } + for (; patternIdx < this.pattern.length; patternIdx++) { + const pattern = this.pattern[patternIdx]; + const element = Matcher.isMatcher(pattern) || typeof pattern === "object" ? " " : ` [${pattern}] `; + result.recordFailure({ + matcher: this, + path: [], + message: `Missing element${element}at pattern index ${patternIdx}` + }); + } + return result; + } +}; +var ObjectMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partial = options.partial ?? true; + } + test(actual) { + if (typeof actual !== "object" || Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type object but received ${getType(actual)}` + }); + } + const result = new MatchResult(actual); + if (!this.partial) { + for (const a of Object.keys(actual)) { + if (!(a in this.pattern)) { + result.recordFailure({ + matcher: this, + path: [`/${a}`], + message: "Unexpected key" + }); + } + } + } + for (const [patternKey, patternVal] of Object.entries(this.pattern)) { + if (!(patternKey in actual) && !(patternVal instanceof AbsentMatch)) { + result.recordFailure({ + matcher: this, + path: [`/${patternKey}`], + message: `Missing key '${patternKey}' among {${Object.keys(actual).join(",")}}` + }); + continue; + } + const matcher = Matcher.isMatcher(patternVal) ? patternVal : new LiteralMatch(this.name, patternVal, { partialObjects: this.partial }); + const inner = matcher.test(actual[patternKey]); + result.compose(`/${patternKey}`, inner); + } + return result; + } +}; +var SerializedJson = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + if (getType(actual) !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected JSON as a string but found ${getType(actual)}` + }); + return result; + } + let parsed; + try { + parsed = JSON.parse(actual); + } catch (err) { + if (err instanceof SyntaxError) { + result.recordFailure({ + matcher: this, + path: [], + message: `Invalid JSON string: ${actual}` + }); + return result; + } else { + throw err; + } + } + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(parsed); + result.compose(`(${this.name})`, innerResult); + return result; + } +}; +var NotMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(actual); + const result = new MatchResult(actual); + if (innerResult.failCount === 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Found unexpected match: ${JSON.stringify(actual, void 0, 2)}` + }); + } + return result; + } +}; +var AnyMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual == null) { + result.recordFailure({ + matcher: this, + path: [], + message: "Expected a value but found none" + }); + } + return result; + } +}; +var StringLikeRegexpMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + const regex = new RegExp(this.pattern, "gm"); + if (typeof actual !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected a string, but got '${typeof actual}'` + }); + } + if (!regex.test(actual)) { + result.recordFailure({ + matcher: this, + path: [], + message: `String '${actual}' did not match pattern '${this.pattern}'` + }); + } + return result; + } +}; + +// lib/assertions/providers/lambda-handler/base.ts +var https = __toESM(require("https")); +var url = __toESM(require("url")); +var CustomResourceHandler = class { + constructor(event, context) { + this.event = event; + this.context = context; + this.timedOut = false; + this.timeout = setTimeout(async () => { + await this.respond({ + status: "FAILED", + reason: "Lambda Function Timeout", + data: this.context.logStreamName + }); + this.timedOut = true; + }, context.getRemainingTimeInMillis() - 1200); + this.event = event; + this.physicalResourceId = extractPhysicalResourceId(event); + } + async handle() { + try { + console.log(`Event: ${JSON.stringify({ ...this.event, ResponseURL: "..." })}`); + const response = await this.processEvent(this.event.ResourceProperties); + console.log(`Event output : ${JSON.stringify(response)}`); + await this.respond({ + status: "SUCCESS", + reason: "OK", + data: response + }); + } catch (e) { + console.log(e); + await this.respond({ + status: "FAILED", + reason: e.message ?? "Internal Error" + }); + } finally { + clearTimeout(this.timeout); + } + } + respond(response) { + if (this.timedOut) { + return; + } + const cfResponse = { + Status: response.status, + Reason: response.reason, + PhysicalResourceId: this.physicalResourceId, + StackId: this.event.StackId, + RequestId: this.event.RequestId, + LogicalResourceId: this.event.LogicalResourceId, + NoEcho: false, + Data: response.data + }; + const responseBody = JSON.stringify(cfResponse); + console.log("Responding to CloudFormation", responseBody); + const parsedUrl = url.parse(this.event.ResponseURL); + const requestOptions = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: "PUT", + headers: { "content-type": "", "content-length": responseBody.length } + }; + return new Promise((resolve, reject) => { + try { + const request2 = https.request(requestOptions, resolve); + request2.on("error", reject); + request2.write(responseBody); + request2.end(); + } catch (e) { + reject(e); + } + }); + } +}; +function extractPhysicalResourceId(event) { + switch (event.RequestType) { + case "Create": + return event.LogicalResourceId; + case "Update": + case "Delete": + return event.PhysicalResourceId; + } +} + +// lib/assertions/providers/lambda-handler/assertion.ts +var AssertionHandler = class extends CustomResourceHandler { + async processEvent(request2) { + let actual = decodeCall(request2.actual); + const expected = decodeCall(request2.expected); + let result; + const matcher = new MatchCreator(expected).getMatcher(); + console.log(`Testing equality between ${JSON.stringify(request2.actual)} and ${JSON.stringify(request2.expected)}`); + const matchResult = matcher.test(actual); + matchResult.finished(); + if (matchResult.hasFailed()) { + result = { + data: JSON.stringify({ + status: "fail", + message: [ + ...matchResult.toHumanStrings(), + JSON.stringify(matchResult.target, void 0, 2) + ].join("\n") + }) + }; + if (request2.failDeployment) { + throw new Error(result.data); + } + } else { + result = { + data: JSON.stringify({ + status: "success" + }) + }; + } + return result; + } +}; +var MatchCreator = class { + constructor(obj) { + this.parsedObj = { + matcher: obj + }; + } + getMatcher() { + try { + const final = JSON.parse(JSON.stringify(this.parsedObj), function(_k, v) { + const nested = Object.keys(v)[0]; + switch (nested) { + case "$ArrayWith": + return Match.arrayWith(v[nested]); + case "$ObjectLike": + return Match.objectLike(v[nested]); + case "$StringLike": + return Match.stringLikeRegexp(v[nested]); + default: + return v; + } + }); + if (Matcher.isMatcher(final.matcher)) { + return final.matcher; + } + return Match.exact(final.matcher); + } catch { + return Match.exact(this.parsedObj.matcher); + } + } +}; +function decodeCall(call) { + if (!call) { + return void 0; + } + try { + const parsed = JSON.parse(call); + return parsed; + } catch (e) { + return call; + } +} + +// lib/assertions/providers/lambda-handler/utils.ts +function decode(object) { + return JSON.parse(JSON.stringify(object), (_k, v) => { + switch (v) { + case "TRUE:BOOLEAN": + return true; + case "FALSE:BOOLEAN": + return false; + default: + return v; + } + }); +} + +// lib/assertions/providers/lambda-handler/sdk.ts +function flatten(object) { + return Object.assign( + {}, + ...function _flatten(child, path = []) { + return [].concat(...Object.keys(child).map((key) => { + const childKey = Buffer.isBuffer(child[key]) ? child[key].toString("utf8") : child[key]; + return typeof childKey === "object" && childKey !== null ? _flatten(childKey, path.concat([key])) : { [path.concat([key]).join(".")]: childKey }; + })); + }(object) + ); +} +var AwsApiCallHandler = class extends CustomResourceHandler { + async processEvent(request2) { + const AWS = require("aws-sdk"); + console.log(`AWS SDK VERSION: ${AWS.VERSION}`); + const service = new AWS[request2.service](); + const response = await service[request2.api](request2.parameters && decode(request2.parameters)).promise(); + console.log(`SDK response received ${JSON.stringify(response)}`); + delete response.ResponseMetadata; + const respond = { + apiCallResponse: response + }; + const flatData = { + ...flatten(respond) + }; + return request2.flattenResponse === "true" ? flatData : respond; + } +}; + +// lib/assertions/providers/lambda-handler/types.ts +var ASSERT_RESOURCE_TYPE = "Custom::DeployAssert@AssertEquals"; +var SDK_RESOURCE_TYPE_PREFIX = "Custom::DeployAssert@SdkCall"; + +// lib/assertions/providers/lambda-handler/index.ts +async function handler(event, context) { + const provider = createResourceHandler(event, context); + await provider.handle(); +} +function createResourceHandler(event, context) { + if (event.ResourceType.startsWith(SDK_RESOURCE_TYPE_PREFIX)) { + return new AwsApiCallHandler(event, context); + } + switch (event.ResourceType) { + case ASSERT_RESOURCE_TYPE: + return new AssertionHandler(event, context); + default: + throw new Error(`Unsupported resource type "${event.ResourceType}`); + } +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + handler +}); diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/asset.c1175cf2b10c78c2687560b17053e3d51a3636b7aac017e713e5a586470606ff/Pipfile b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/asset.c1175cf2b10c78c2687560b17053e3d51a3636b7aac017e713e5a586470606ff/Pipfile deleted file mode 100644 index 78d783bc4b9b0..0000000000000 --- a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/asset.c1175cf2b10c78c2687560b17053e3d51a3636b7aac017e713e5a586470606ff/Pipfile +++ /dev/null @@ -1,7 +0,0 @@ -[[source]] -name = "pypi" -url = "https://pypi.org/simple" -verify_ssl = true - -[packages] -requests = "==2.26.0" diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/asset.c1175cf2b10c78c2687560b17053e3d51a3636b7aac017e713e5a586470606ff/Pipfile.lock b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/asset.c1175cf2b10c78c2687560b17053e3d51a3636b7aac017e713e5a586470606ff/Pipfile.lock deleted file mode 100644 index 441acc679505f..0000000000000 --- a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/asset.c1175cf2b10c78c2687560b17053e3d51a3636b7aac017e713e5a586470606ff/Pipfile.lock +++ /dev/null @@ -1,58 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "6cfaa5a495be5cf47942a14b04d50e639f14743101e621684e86449dbac8da61" - }, - "pipfile-spec": 6, - "requires": {}, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "certifi": { - "hashes": [ - "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872", - "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569" - ], - "version": "==2021.10.8" - }, - "charset-normalizer": { - "hashes": [ - "sha256:876d180e9d7432c5d1dfd4c5d26b72f099d503e8fcc0feb7532c9289be60fcbd", - "sha256:cb957888737fc0bbcd78e3df769addb41fd1ff8cf950dc9e7ad7793f1bf44455" - ], - "markers": "python_version >= '3'", - "version": "==2.0.10" - }, - "idna": { - "hashes": [ - "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", - "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" - ], - "markers": "python_version >= '3'", - "version": "==3.3" - }, - "requests": { - "hashes": [ - "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24", - "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7" - ], - "index": "pypi", - "version": "==2.26.0" - }, - "urllib3": { - "hashes": [ - "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed", - "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", - "version": "==1.26.8" - } - }, - "develop": {} -} diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/asset.c1175cf2b10c78c2687560b17053e3d51a3636b7aac017e713e5a586470606ff/index.py b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/asset.c1175cf2b10c78c2687560b17053e3d51a3636b7aac017e713e5a586470606ff/index.py deleted file mode 100644 index 04f99eb108b30..0000000000000 --- a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/asset.c1175cf2b10c78c2687560b17053e3d51a3636b7aac017e713e5a586470606ff/index.py +++ /dev/null @@ -1,8 +0,0 @@ -import requests - -def handler(event, context): - response = requests.get('https://a0.awsstatic.com/main/images/logos/aws_smile-header-desktop-en-white_59x35.png', stream=True) - - print(response.status_code) - - return response.status_code diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/asset.c1175cf2b10c78c2687560b17053e3d51a3636b7aac017e713e5a586470606ff/requirements.txt b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/asset.c1175cf2b10c78c2687560b17053e3d51a3636b7aac017e713e5a586470606ff/requirements.txt deleted file mode 100644 index e206b765533cc..0000000000000 --- a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/asset.c1175cf2b10c78c2687560b17053e3d51a3636b7aac017e713e5a586470606ff/requirements.txt +++ /dev/null @@ -1,13 +0,0 @@ -# -# These requirements were autogenerated by pipenv -# To regenerate from the project's Pipfile, run: -# -# pipenv lock --requirements -# - --i https://pypi.org/simple -certifi==2021.10.8 -charset-normalizer==2.0.10; python_version >= '3' -idna==3.3; python_version >= '3' -requests==2.26.0 -urllib3==1.26.8; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4' diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/cdk-integ-lambda-python.assets.json b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/cdk-integ-lambda-python.assets.json deleted file mode 100644 index 466a50355cf31..0000000000000 --- a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/cdk-integ-lambda-python.assets.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "version": "20.0.0", - "files": { - "8d7289aede51c7665a9df0be604eabacb55f0dc5979ea64c70fe3686e60ae5ae": { - "source": { - "path": "asset.8d7289aede51c7665a9df0be604eabacb55f0dc5979ea64c70fe3686e60ae5ae", - "packaging": "zip" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "8d7289aede51c7665a9df0be604eabacb55f0dc5979ea64c70fe3686e60ae5ae.zip", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "48df79eafe4c27c7b40259916623d0b5a9722e315827d20e6f2dd91c5103352a": { - "source": { - "path": "asset.48df79eafe4c27c7b40259916623d0b5a9722e315827d20e6f2dd91c5103352a", - "packaging": "zip" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "48df79eafe4c27c7b40259916623d0b5a9722e315827d20e6f2dd91c5103352a.zip", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "0a79cd3b6ac700ba99344c3dcf151ca901b64ee2635bb30d90e9f9cabd809612": { - "source": { - "path": "cdk-integ-lambda-python.template.json", - "packaging": "file" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "0a79cd3b6ac700ba99344c3dcf151ca901b64ee2635bb30d90e9f9cabd809612.json", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - } - }, - "dockerImages": {} -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/cdk.out index 588d7b269d34f..8ecc185e9dbee 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/cdk-integ-lambda-python.assets.json b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/integ-lambda-python-pipenv.assets.json similarity index 60% rename from packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/cdk-integ-lambda-python.assets.json rename to packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/integ-lambda-python-pipenv.assets.json index 59b1159d82b6e..06fc3c46efd8b 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/cdk-integ-lambda-python.assets.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/integ-lambda-python-pipenv.assets.json @@ -1,54 +1,54 @@ { "version": "21.0.0", "files": { - "377b8c7d7d74049daef959af1f7f0f0f2eaeb6ccb4c85fe80f8c00936183b6ff": { + "803e66cf17a8155efd491fa5e68f796bb74ae8337c455b23b5e52d0e5927b2a7": { "source": { - "path": "asset.377b8c7d7d74049daef959af1f7f0f0f2eaeb6ccb4c85fe80f8c00936183b6ff", + "path": "asset.803e66cf17a8155efd491fa5e68f796bb74ae8337c455b23b5e52d0e5927b2a7", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "377b8c7d7d74049daef959af1f7f0f0f2eaeb6ccb4c85fe80f8c00936183b6ff.zip", + "objectKey": "803e66cf17a8155efd491fa5e68f796bb74ae8337c455b23b5e52d0e5927b2a7.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "f27e50ce3e964bd188b2fad96e1819a8e68a7a7a17e1f701b6bdcc054e29503a": { + "2a6fcac567a26e1be604dec572e270fbd091180dccf23a209e21c5900ce24ff0": { "source": { - "path": "asset.f27e50ce3e964bd188b2fad96e1819a8e68a7a7a17e1f701b6bdcc054e29503a", + "path": "asset.2a6fcac567a26e1be604dec572e270fbd091180dccf23a209e21c5900ce24ff0", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "f27e50ce3e964bd188b2fad96e1819a8e68a7a7a17e1f701b6bdcc054e29503a.zip", + "objectKey": "2a6fcac567a26e1be604dec572e270fbd091180dccf23a209e21c5900ce24ff0.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "d165152de494c90bdd8c4aa643a5b1e99b2a5cbacb7f4594319b3b45d6845fd3": { + "e223ff54d4d46f8f1e5876b5697de59a81ba36113fa0bf2b46d29917fcbee403": { "source": { - "path": "asset.d165152de494c90bdd8c4aa643a5b1e99b2a5cbacb7f4594319b3b45d6845fd3", + "path": "asset.e223ff54d4d46f8f1e5876b5697de59a81ba36113fa0bf2b46d29917fcbee403", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "d165152de494c90bdd8c4aa643a5b1e99b2a5cbacb7f4594319b3b45d6845fd3.zip", + "objectKey": "e223ff54d4d46f8f1e5876b5697de59a81ba36113fa0bf2b46d29917fcbee403.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "5187de9a41f36d4b41ca1553d50265326d21791726e2a3dd0a3201910180fc0f": { + "0ed561f0d555914dbd2d0c6af29be68dd27eb65ee922d0f6eee6d50d3a0b5362": { "source": { - "path": "cdk-integ-lambda-python.template.json", + "path": "integ-lambda-python-pipenv.template.json", "packaging": "file" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "5187de9a41f36d4b41ca1553d50265326d21791726e2a3dd0a3201910180fc0f.json", + "objectKey": "0ed561f0d555914dbd2d0c6af29be68dd27eb65ee922d0f6eee6d50d3a0b5362.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/cdk-integ-lambda-python.template.json b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/integ-lambda-python-pipenv.template.json similarity index 83% rename from packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/cdk-integ-lambda-python.template.json rename to packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/integ-lambda-python-pipenv.template.json index 14440fd8aa966..3e664aeb17e51 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/cdk-integ-lambda-python.template.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/integ-lambda-python-pipenv.template.json @@ -38,7 +38,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "377b8c7d7d74049daef959af1f7f0f0f2eaeb6ccb4c85fe80f8c00936183b6ff.zip" + "S3Key": "803e66cf17a8155efd491fa5e68f796bb74ae8337c455b23b5e52d0e5927b2a7.zip" }, "Role": { "Fn::GetAtt": [ @@ -91,7 +91,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "f27e50ce3e964bd188b2fad96e1819a8e68a7a7a17e1f701b6bdcc054e29503a.zip" + "S3Key": "2a6fcac567a26e1be604dec572e270fbd091180dccf23a209e21c5900ce24ff0.zip" }, "Role": { "Fn::GetAtt": [ @@ -144,7 +144,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "d165152de494c90bdd8c4aa643a5b1e99b2a5cbacb7f4594319b3b45d6845fd3.zip" + "S3Key": "e223ff54d4d46f8f1e5876b5697de59a81ba36113fa0bf2b46d29917fcbee403.zip" }, "Role": { "Fn::GetAtt": [ @@ -161,14 +161,28 @@ } }, "Outputs": { - "InlineFunctionName": { + "ExportsOutputRefmyhandlerinline53D120C7B0898676": { "Value": { "Ref": "myhandlerinline53D120C7" + }, + "Export": { + "Name": "integ-lambda-python-pipenv:ExportsOutputRefmyhandlerinline53D120C7B0898676" } }, - "Python38FunctionName": { + "ExportsOutputRefmyhandlerpython384D62BBB58AA8B940": { "Value": { "Ref": "myhandlerpython384D62BBB5" + }, + "Export": { + "Name": "integ-lambda-python-pipenv:ExportsOutputRefmyhandlerpython384D62BBB58AA8B940" + } + }, + "ExportsOutputRefmyhandlerpython37C34039A7BB71D94D": { + "Value": { + "Ref": "myhandlerpython37C34039A7" + }, + "Export": { + "Name": "integ-lambda-python-pipenv:ExportsOutputRefmyhandlerpython37C34039A7BB71D94D" } } }, diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/integ.json b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/integ.json index d10304994cd71..37e33ee99af21 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/integ.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/integ.json @@ -1,14 +1,13 @@ { - "version": "20.0.0", + "version": "21.0.0", "testCases": { - "integ.function.pipenv": { + "pipenv/DefaultTest": { "stacks": [ - "cdk-integ-lambda-python" + "integ-lambda-python-pipenv" ], - "diffAssets": false, - "stackUpdateWorkflow": false + "stackUpdateWorkflow": false, + "assertionStack": "pipenv/DefaultTest/DeployAssert", + "assertionStackName": "pipenvDefaultTestDeployAssertF8231517" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/manifest.json index b031837c355b7..7758c7d1f91fe 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "21.0.0", "artifacts": { "Tree": { "type": "cdk:tree", @@ -7,27 +7,27 @@ "file": "tree.json" } }, - "cdk-integ-lambda-python.assets": { + "integ-lambda-python-pipenv.assets": { "type": "cdk:asset-manifest", "properties": { - "file": "cdk-integ-lambda-python.assets.json", + "file": "integ-lambda-python-pipenv.assets.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" } }, - "cdk-integ-lambda-python": { + "integ-lambda-python-pipenv": { "type": "aws:cloudformation:stack", "environment": "aws://unknown-account/unknown-region", "properties": { - "templateFile": "cdk-integ-lambda-python.template.json", + "templateFile": "integ-lambda-python-pipenv.template.json", "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/0a79cd3b6ac700ba99344c3dcf151ca901b64ee2635bb30d90e9f9cabd809612.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/0ed561f0d555914dbd2d0c6af29be68dd27eb65ee922d0f6eee6d50d3a0b5362.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ - "cdk-integ-lambda-python.assets" + "integ-lambda-python-pipenv.assets" ], "lookupRole": { "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", @@ -36,59 +36,209 @@ } }, "dependencies": [ - "cdk-integ-lambda-python.assets" + "integ-lambda-python-pipenv.assets" ], "metadata": { - "/cdk-integ-lambda-python/my_handler_inline/ServiceRole/Resource": [ + "/integ-lambda-python-pipenv/my_handler_inline/ServiceRole/Resource": [ { "type": "aws:cdk:logicalId", "data": "myhandlerinlineServiceRole10C681F6" } ], - "/cdk-integ-lambda-python/my_handler_inline/Resource": [ + "/integ-lambda-python-pipenv/my_handler_inline/Resource": [ { "type": "aws:cdk:logicalId", "data": "myhandlerinline53D120C7" } ], - "/cdk-integ-lambda-python/InlineFunctionName": [ + "/integ-lambda-python-pipenv/my_handler_python_38/ServiceRole/Resource": [ { "type": "aws:cdk:logicalId", - "data": "InlineFunctionName" + "data": "myhandlerpython38ServiceRole2049AFF7" } ], - "/cdk-integ-lambda-python/my_handler_python_38/ServiceRole/Resource": [ + "/integ-lambda-python-pipenv/my_handler_python_38/Resource": [ { "type": "aws:cdk:logicalId", - "data": "myhandlerpython38ServiceRole2049AFF7" + "data": "myhandlerpython384D62BBB5" } ], - "/cdk-integ-lambda-python/my_handler_python_38/Resource": [ + "/integ-lambda-python-pipenv/my_handler_python_37/ServiceRole/Resource": [ { "type": "aws:cdk:logicalId", - "data": "myhandlerpython384D62BBB5" + "data": "myhandlerpython37ServiceRole45CBD18D" + } + ], + "/integ-lambda-python-pipenv/my_handler_python_37/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "myhandlerpython37C34039A7" + } + ], + "/integ-lambda-python-pipenv/Exports/Output{\"Ref\":\"myhandlerinline53D120C7\"}": [ + { + "type": "aws:cdk:logicalId", + "data": "ExportsOutputRefmyhandlerinline53D120C7B0898676" + } + ], + "/integ-lambda-python-pipenv/Exports/Output{\"Ref\":\"myhandlerpython384D62BBB5\"}": [ + { + "type": "aws:cdk:logicalId", + "data": "ExportsOutputRefmyhandlerpython384D62BBB58AA8B940" + } + ], + "/integ-lambda-python-pipenv/Exports/Output{\"Ref\":\"myhandlerpython37C34039A7\"}": [ + { + "type": "aws:cdk:logicalId", + "data": "ExportsOutputRefmyhandlerpython37C34039A7BB71D94D" + } + ], + "/integ-lambda-python-pipenv/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-lambda-python-pipenv/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-lambda-python-pipenv" + }, + "pipenvDefaultTestDeployAssertF8231517.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "pipenvDefaultTestDeployAssertF8231517.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "pipenvDefaultTestDeployAssertF8231517": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "pipenvDefaultTestDeployAssertF8231517.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/60915425ae6d91c88b04adf7c9631b4ea5f48c4764bbff1edc0bc70d57705d3f.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "pipenvDefaultTestDeployAssertF8231517.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integ-lambda-python-pipenv", + "pipenvDefaultTestDeployAssertF8231517.assets" + ], + "metadata": { + "/pipenv/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke81c9998b1b428b309c8501e21b919d3d" + } + ], + "/pipenv/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/Invoke": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke81c9998b1b428b309c8501e21b919d3dInvokeEBA46CA4" + } + ], + "/pipenv/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/AssertEqualsLambdainvoke/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke81c9998b1b428b309c8501e21b919d3dAssertEqualsLambdainvoke0BDD9934" + } + ], + "/pipenv/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/AssertEqualsLambdainvoke/AssertionResults": [ + { + "type": "aws:cdk:logicalId", + "data": "AssertionResultsAssertEqualsLambdainvoke556559ea7575e3a52e6d6c32e2c07934" + } + ], + "/pipenv/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73" + } + ], + "/pipenv/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F" + } + ], + "/pipenv/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292" + } + ], + "/pipenv/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/Invoke": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292InvokeFD76DE7B" + } + ], + "/pipenv/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/AssertEqualsLambdainvoke/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292AssertEqualsLambdainvoke3F6858A2" + } + ], + "/pipenv/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/AssertEqualsLambdainvoke/AssertionResults": [ + { + "type": "aws:cdk:logicalId", + "data": "AssertionResultsAssertEqualsLambdainvoke921b66a1d8c9b23c2c2caef76d4b249b" + } + ], + "/pipenv/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75" + } + ], + "/pipenv/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/Invoke": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75Invoke11F9A252" + } + ], + "/pipenv/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/AssertEqualsLambdainvoke/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75AssertEqualsLambdainvoke2346EE1F" } ], - "/cdk-integ-lambda-python/Python38FunctionName": [ + "/pipenv/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/AssertEqualsLambdainvoke/AssertionResults": [ { "type": "aws:cdk:logicalId", - "data": "Python38FunctionName" + "data": "AssertionResultsAssertEqualsLambdainvoke98ea6f3253baf793823267fb4d86d1ed" } ], - "/cdk-integ-lambda-python/BootstrapVersion": [ + "/pipenv/DefaultTest/DeployAssert/BootstrapVersion": [ { "type": "aws:cdk:logicalId", "data": "BootstrapVersion" } ], - "/cdk-integ-lambda-python/CheckBootstrapVersion": [ + "/pipenv/DefaultTest/DeployAssert/CheckBootstrapVersion": [ { "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } ] }, - "displayName": "cdk-integ-lambda-python" + "displayName": "pipenv/DefaultTest/DeployAssert" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/pipenvDefaultTestDeployAssertF8231517.assets.json b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/pipenvDefaultTestDeployAssertF8231517.assets.json new file mode 100644 index 0000000000000..636ffaeafc5ce --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/pipenvDefaultTestDeployAssertF8231517.assets.json @@ -0,0 +1,32 @@ +{ + "version": "21.0.0", + "files": { + "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7": { + "source": { + "path": "asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "60915425ae6d91c88b04adf7c9631b4ea5f48c4764bbff1edc0bc70d57705d3f": { + "source": { + "path": "pipenvDefaultTestDeployAssertF8231517.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "60915425ae6d91c88b04adf7c9631b4ea5f48c4764bbff1edc0bc70d57705d3f.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/pipenvDefaultTestDeployAssertF8231517.template.json b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/pipenvDefaultTestDeployAssertF8231517.template.json new file mode 100644 index 0000000000000..4c9ade29468ec --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/pipenvDefaultTestDeployAssertF8231517.template.json @@ -0,0 +1,410 @@ +{ + "Resources": { + "LambdaInvoke81c9998b1b428b309c8501e21b919d3d": { + "Type": "Custom::DeployAssert@SdkCallLambdainvoke", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "service": "Lambda", + "api": "invoke", + "parameters": { + "FunctionName": { + "Fn::ImportValue": "integ-lambda-python-pipenv:ExportsOutputRefmyhandlerinline53D120C7B0898676" + } + }, + "flattenResponse": "false", + "salt": "1662643820432" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "LambdaInvoke81c9998b1b428b309c8501e21b919d3dInvokeEBA46CA4": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::ImportValue": "integ-lambda-python-pipenv:ExportsOutputRefmyhandlerinline53D120C7B0898676" + }, + "Principal": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + }, + "LambdaInvoke81c9998b1b428b309c8501e21b919d3dAssertEqualsLambdainvoke0BDD9934": { + "Type": "Custom::DeployAssert@AssertEquals", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "actual": { + "Fn::GetAtt": [ + "LambdaInvoke81c9998b1b428b309c8501e21b919d3d", + "apiCallResponse" + ] + }, + "expected": "{\"$ObjectLike\":{\"Payload\":\"200\"}}", + "salt": "1662643820433" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "lambda:Invoke" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":lambda:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":function:", + { + "Fn::ImportValue": "integ-lambda-python-pipenv:ExportsOutputRefmyhandlerinline53D120C7B0898676" + } + ] + ] + } + ] + }, + { + "Action": [ + "lambda:Invoke" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":lambda:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":function:", + { + "Fn::ImportValue": "integ-lambda-python-pipenv:ExportsOutputRefmyhandlerpython384D62BBB58AA8B940" + } + ] + ] + } + ] + }, + { + "Action": [ + "lambda:Invoke" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":lambda:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":function:", + { + "Fn::ImportValue": "integ-lambda-python-pipenv:ExportsOutputRefmyhandlerpython37C34039A7BB71D94D" + } + ] + ] + } + ] + } + ] + } + } + ] + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Runtime": "nodejs14.x", + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip" + }, + "Timeout": 120, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + }, + "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292": { + "Type": "Custom::DeployAssert@SdkCallLambdainvoke", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "service": "Lambda", + "api": "invoke", + "parameters": { + "FunctionName": { + "Fn::ImportValue": "integ-lambda-python-pipenv:ExportsOutputRefmyhandlerpython384D62BBB58AA8B940" + } + }, + "flattenResponse": "false", + "salt": "1662643820434" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292InvokeFD76DE7B": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::ImportValue": "integ-lambda-python-pipenv:ExportsOutputRefmyhandlerpython384D62BBB58AA8B940" + }, + "Principal": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + }, + "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292AssertEqualsLambdainvoke3F6858A2": { + "Type": "Custom::DeployAssert@AssertEquals", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "actual": { + "Fn::GetAtt": [ + "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292", + "apiCallResponse" + ] + }, + "expected": "{\"$ObjectLike\":{\"Payload\":\"200\"}}", + "salt": "1662643820434" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75": { + "Type": "Custom::DeployAssert@SdkCallLambdainvoke", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "service": "Lambda", + "api": "invoke", + "parameters": { + "FunctionName": { + "Fn::ImportValue": "integ-lambda-python-pipenv:ExportsOutputRefmyhandlerpython37C34039A7BB71D94D" + } + }, + "flattenResponse": "false", + "salt": "1662643820434" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75Invoke11F9A252": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::ImportValue": "integ-lambda-python-pipenv:ExportsOutputRefmyhandlerpython37C34039A7BB71D94D" + }, + "Principal": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + }, + "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75AssertEqualsLambdainvoke2346EE1F": { + "Type": "Custom::DeployAssert@AssertEquals", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "actual": { + "Fn::GetAtt": [ + "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75", + "apiCallResponse" + ] + }, + "expected": "{\"$ObjectLike\":{\"Payload\":\"200\"}}", + "salt": "1662643820434" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Outputs": { + "AssertionResultsAssertEqualsLambdainvoke556559ea7575e3a52e6d6c32e2c07934": { + "Value": { + "Fn::GetAtt": [ + "LambdaInvoke81c9998b1b428b309c8501e21b919d3dAssertEqualsLambdainvoke0BDD9934", + "data" + ] + } + }, + "AssertionResultsAssertEqualsLambdainvoke921b66a1d8c9b23c2c2caef76d4b249b": { + "Value": { + "Fn::GetAtt": [ + "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292AssertEqualsLambdainvoke3F6858A2", + "data" + ] + } + }, + "AssertionResultsAssertEqualsLambdainvoke98ea6f3253baf793823267fb4d86d1ed": { + "Value": { + "Fn::GetAtt": [ + "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75AssertEqualsLambdainvoke2346EE1F", + "data" + ] + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/tree.json b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/tree.json index 139a6e5e3ee19..c8fc3ed91b09b 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/tree.json @@ -9,24 +9,24 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } }, - "cdk-integ-lambda-python": { - "id": "cdk-integ-lambda-python", - "path": "cdk-integ-lambda-python", + "integ-lambda-python-pipenv": { + "id": "integ-lambda-python-pipenv", + "path": "integ-lambda-python-pipenv", "children": { "my_handler_inline": { "id": "my_handler_inline", - "path": "cdk-integ-lambda-python/my_handler_inline", + "path": "integ-lambda-python-pipenv/my_handler_inline", "children": { "ServiceRole": { "id": "ServiceRole", - "path": "cdk-integ-lambda-python/my_handler_inline/ServiceRole", + "path": "integ-lambda-python-pipenv/my_handler_inline/ServiceRole", "children": { "Resource": { "id": "Resource", - "path": "cdk-integ-lambda-python/my_handler_inline/ServiceRole/Resource", + "path": "integ-lambda-python-pipenv/my_handler_inline/ServiceRole/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::IAM::Role", "aws:cdk:cloudformation:props": { @@ -71,19 +71,19 @@ }, "Code": { "id": "Code", - "path": "cdk-integ-lambda-python/my_handler_inline/Code", + "path": "integ-lambda-python-pipenv/my_handler_inline/Code", "children": { "Stage": { "id": "Stage", - "path": "cdk-integ-lambda-python/my_handler_inline/Code/Stage", + "path": "integ-lambda-python-pipenv/my_handler_inline/Code/Stage", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "AssetBucket": { "id": "AssetBucket", - "path": "cdk-integ-lambda-python/my_handler_inline/Code/AssetBucket", + "path": "integ-lambda-python-pipenv/my_handler_inline/Code/AssetBucket", "constructInfo": { "fqn": "@aws-cdk/aws-s3.BucketBase", "version": "0.0.0" @@ -97,7 +97,7 @@ }, "Resource": { "id": "Resource", - "path": "cdk-integ-lambda-python/my_handler_inline/Resource", + "path": "integ-lambda-python-pipenv/my_handler_inline/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { @@ -105,7 +105,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "8d7289aede51c7665a9df0be604eabacb55f0dc5979ea64c70fe3686e60ae5ae.zip" + "s3Key": "803e66cf17a8155efd491fa5e68f796bb74ae8337c455b23b5e52d0e5927b2a7.zip" }, "role": { "Fn::GetAtt": [ @@ -128,25 +128,17 @@ "version": "0.0.0" } }, - "InlineFunctionName": { - "id": "InlineFunctionName", - "path": "cdk-integ-lambda-python/InlineFunctionName", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "my_handler_python_38": { "id": "my_handler_python_38", - "path": "cdk-integ-lambda-python/my_handler_python_38", + "path": "integ-lambda-python-pipenv/my_handler_python_38", "children": { "ServiceRole": { "id": "ServiceRole", - "path": "cdk-integ-lambda-python/my_handler_python_38/ServiceRole", + "path": "integ-lambda-python-pipenv/my_handler_python_38/ServiceRole", "children": { "Resource": { "id": "Resource", - "path": "cdk-integ-lambda-python/my_handler_python_38/ServiceRole/Resource", + "path": "integ-lambda-python-pipenv/my_handler_python_38/ServiceRole/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::IAM::Role", "aws:cdk:cloudformation:props": { @@ -191,19 +183,19 @@ }, "Code": { "id": "Code", - "path": "cdk-integ-lambda-python/my_handler_python_38/Code", + "path": "integ-lambda-python-pipenv/my_handler_python_38/Code", "children": { "Stage": { "id": "Stage", - "path": "cdk-integ-lambda-python/my_handler_python_38/Code/Stage", + "path": "integ-lambda-python-pipenv/my_handler_python_38/Code/Stage", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "AssetBucket": { "id": "AssetBucket", - "path": "cdk-integ-lambda-python/my_handler_python_38/Code/AssetBucket", + "path": "integ-lambda-python-pipenv/my_handler_python_38/Code/AssetBucket", "constructInfo": { "fqn": "@aws-cdk/aws-s3.BucketBase", "version": "0.0.0" @@ -217,7 +209,7 @@ }, "Resource": { "id": "Resource", - "path": "cdk-integ-lambda-python/my_handler_python_38/Resource", + "path": "integ-lambda-python-pipenv/my_handler_python_38/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { @@ -225,7 +217,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "48df79eafe4c27c7b40259916623d0b5a9722e315827d20e6f2dd91c5103352a.zip" + "s3Key": "2a6fcac567a26e1be604dec572e270fbd091180dccf23a209e21c5900ce24ff0.zip" }, "role": { "Fn::GetAtt": [ @@ -248,24 +240,558 @@ "version": "0.0.0" } }, - "Python38FunctionName": { - "id": "Python38FunctionName", - "path": "cdk-integ-lambda-python/Python38FunctionName", + "my_handler_python_37": { + "id": "my_handler_python_37", + "path": "integ-lambda-python-pipenv/my_handler_python_37", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "integ-lambda-python-pipenv/my_handler_python_37/ServiceRole", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-lambda-python-pipenv/my_handler_python_37/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Code": { + "id": "Code", + "path": "integ-lambda-python-pipenv/my_handler_python_37/Code", + "children": { + "Stage": { + "id": "Stage", + "path": "integ-lambda-python-pipenv/my_handler_python_37/Code/Stage", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "integ-lambda-python-pipenv/my_handler_python_37/Code/AssetBucket", + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3-assets.Asset", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-lambda-python-pipenv/my_handler_python_37/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "s3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "s3Key": "e223ff54d4d46f8f1e5876b5697de59a81ba36113fa0bf2b46d29917fcbee403.zip" + }, + "role": { + "Fn::GetAtt": [ + "myhandlerpython37ServiceRole45CBD18D", + "Arn" + ] + }, + "handler": "index.handler", + "runtime": "python3.7" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda-python.PythonFunction", + "version": "0.0.0" + } + }, + "Exports": { + "id": "Exports", + "path": "integ-lambda-python-pipenv/Exports", + "children": { + "Output{\"Ref\":\"myhandlerinline53D120C7\"}": { + "id": "Output{\"Ref\":\"myhandlerinline53D120C7\"}", + "path": "integ-lambda-python-pipenv/Exports/Output{\"Ref\":\"myhandlerinline53D120C7\"}", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "Output{\"Ref\":\"myhandlerpython384D62BBB5\"}": { + "id": "Output{\"Ref\":\"myhandlerpython384D62BBB5\"}", + "path": "integ-lambda-python-pipenv/Exports/Output{\"Ref\":\"myhandlerpython384D62BBB5\"}", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "Output{\"Ref\":\"myhandlerpython37C34039A7\"}": { + "id": "Output{\"Ref\":\"myhandlerpython37C34039A7\"}", + "path": "integ-lambda-python-pipenv/Exports/Output{\"Ref\":\"myhandlerpython37C34039A7\"}", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "pipenv": { + "id": "pipenv", + "path": "pipenv", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "pipenv/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "pipenv/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "pipenv/DefaultTest/DeployAssert", + "children": { + "LambdaInvoke81c9998b1b428b309c8501e21b919d3d": { + "id": "LambdaInvoke81c9998b1b428b309c8501e21b919d3d", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d", + "children": { + "SdkProvider": { + "id": "SdkProvider", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/SdkProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/SdkProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "Default": { + "id": "Default", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/Default", + "children": { + "Default": { + "id": "Default", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "Invoke": { + "id": "Invoke", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/Invoke", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "AssertEqualsLambdainvoke": { + "id": "AssertEqualsLambdainvoke", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/AssertEqualsLambdainvoke", + "children": { + "AssertionProvider": { + "id": "AssertionProvider", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/AssertEqualsLambdainvoke/AssertionProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/AssertEqualsLambdainvoke/AssertionProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "Default": { + "id": "Default", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/AssertEqualsLambdainvoke/Default", + "children": { + "Default": { + "id": "Default", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/AssertEqualsLambdainvoke/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "AssertionResults": { + "id": "AssertionResults", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/AssertEqualsLambdainvoke/AssertionResults", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81": { + "id": "SingletonFunction1488541a7b23466481b69b4408076b81", + "path": "pipenv/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81", + "children": { + "Staging": { + "id": "Staging", + "path": "pipenv/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Staging", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "pipenv/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "pipenv/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292": { + "id": "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292", + "children": { + "SdkProvider": { + "id": "SdkProvider", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/SdkProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/SdkProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "Default": { + "id": "Default", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/Default", + "children": { + "Default": { + "id": "Default", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "Invoke": { + "id": "Invoke", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/Invoke", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "AssertEqualsLambdainvoke": { + "id": "AssertEqualsLambdainvoke", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/AssertEqualsLambdainvoke", + "children": { + "AssertionProvider": { + "id": "AssertionProvider", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/AssertEqualsLambdainvoke/AssertionProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/AssertEqualsLambdainvoke/AssertionProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "Default": { + "id": "Default", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/AssertEqualsLambdainvoke/Default", + "children": { + "Default": { + "id": "Default", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/AssertEqualsLambdainvoke/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "AssertionResults": { + "id": "AssertionResults", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/AssertEqualsLambdainvoke/AssertionResults", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75": { + "id": "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75", + "children": { + "SdkProvider": { + "id": "SdkProvider", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/SdkProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/SdkProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "Default": { + "id": "Default", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/Default", + "children": { + "Default": { + "id": "Default", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "Invoke": { + "id": "Invoke", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/Invoke", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "AssertEqualsLambdainvoke": { + "id": "AssertEqualsLambdainvoke", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/AssertEqualsLambdainvoke", + "children": { + "AssertionProvider": { + "id": "AssertionProvider", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/AssertEqualsLambdainvoke/AssertionProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/AssertEqualsLambdainvoke/AssertionProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "Default": { + "id": "Default", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/AssertEqualsLambdainvoke/Default", + "children": { + "Default": { + "id": "Default", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/AssertEqualsLambdainvoke/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "AssertionResults": { + "id": "AssertionResults", + "path": "pipenv/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/AssertEqualsLambdainvoke/AssertionResults", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js b/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js new file mode 100644 index 0000000000000..ba956d47f51fe --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js @@ -0,0 +1,612 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// lib/assertions/providers/lambda-handler/index.ts +var lambda_handler_exports = {}; +__export(lambda_handler_exports, { + handler: () => handler +}); +module.exports = __toCommonJS(lambda_handler_exports); + +// ../assertions/lib/matcher.ts +var Matcher = class { + static isMatcher(x) { + return x && x instanceof Matcher; + } +}; +var MatchResult = class { + constructor(target) { + this.failures = []; + this.captures = /* @__PURE__ */ new Map(); + this.finalized = false; + this.target = target; + } + push(matcher, path, message) { + return this.recordFailure({ matcher, path, message }); + } + recordFailure(failure) { + this.failures.push(failure); + return this; + } + hasFailed() { + return this.failures.length !== 0; + } + get failCount() { + return this.failures.length; + } + compose(id, inner) { + const innerF = inner.failures; + this.failures.push(...innerF.map((f) => { + return { path: [id, ...f.path], message: f.message, matcher: f.matcher }; + })); + inner.captures.forEach((vals, capture) => { + vals.forEach((value) => this.recordCapture({ capture, value })); + }); + return this; + } + finished() { + if (this.finalized) { + return this; + } + if (this.failCount === 0) { + this.captures.forEach((vals, cap) => cap._captured.push(...vals)); + } + this.finalized = true; + return this; + } + toHumanStrings() { + return this.failures.map((r) => { + const loc = r.path.length === 0 ? "" : ` at ${r.path.join("")}`; + return "" + r.message + loc + ` (using ${r.matcher.name} matcher)`; + }); + } + recordCapture(options) { + let values = this.captures.get(options.capture); + if (values === void 0) { + values = []; + } + values.push(options.value); + this.captures.set(options.capture, values); + } +}; + +// ../assertions/lib/private/matchers/absent.ts +var AbsentMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual !== void 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Received ${actual}, but key should be absent` + }); + } + return result; + } +}; + +// ../assertions/lib/private/type.ts +function getType(obj) { + return Array.isArray(obj) ? "array" : typeof obj; +} + +// ../assertions/lib/match.ts +var Match = class { + static absent() { + return new AbsentMatch("absent"); + } + static arrayWith(pattern) { + return new ArrayMatch("arrayWith", pattern); + } + static arrayEquals(pattern) { + return new ArrayMatch("arrayEquals", pattern, { subsequence: false }); + } + static exact(pattern) { + return new LiteralMatch("exact", pattern, { partialObjects: false }); + } + static objectLike(pattern) { + return new ObjectMatch("objectLike", pattern); + } + static objectEquals(pattern) { + return new ObjectMatch("objectEquals", pattern, { partial: false }); + } + static not(pattern) { + return new NotMatch("not", pattern); + } + static serializedJson(pattern) { + return new SerializedJson("serializedJson", pattern); + } + static anyValue() { + return new AnyMatch("anyValue"); + } + static stringLikeRegexp(pattern) { + return new StringLikeRegexpMatch("stringLikeRegexp", pattern); + } +}; +var LiteralMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partialObjects = options.partialObjects ?? false; + if (Matcher.isMatcher(this.pattern)) { + throw new Error("LiteralMatch cannot directly contain another matcher. Remove the top-level matcher or nest it more deeply."); + } + } + test(actual) { + if (Array.isArray(this.pattern)) { + return new ArrayMatch(this.name, this.pattern, { subsequence: false, partialObjects: this.partialObjects }).test(actual); + } + if (typeof this.pattern === "object") { + return new ObjectMatch(this.name, this.pattern, { partial: this.partialObjects }).test(actual); + } + const result = new MatchResult(actual); + if (typeof this.pattern !== typeof actual) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected type ${typeof this.pattern} but received ${getType(actual)}` + }); + return result; + } + if (actual !== this.pattern) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected ${this.pattern} but received ${actual}` + }); + } + return result; + } +}; +var ArrayMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.subsequence = options.subsequence ?? true; + this.partialObjects = options.partialObjects ?? false; + } + test(actual) { + if (!Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type array but received ${getType(actual)}` + }); + } + if (!this.subsequence && this.pattern.length !== actual.length) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected array of length ${this.pattern.length} but received ${actual.length}` + }); + } + let patternIdx = 0; + let actualIdx = 0; + const result = new MatchResult(actual); + while (patternIdx < this.pattern.length && actualIdx < actual.length) { + const patternElement = this.pattern[patternIdx]; + const matcher = Matcher.isMatcher(patternElement) ? patternElement : new LiteralMatch(this.name, patternElement, { partialObjects: this.partialObjects }); + const matcherName = matcher.name; + if (this.subsequence && (matcherName == "absent" || matcherName == "anyValue")) { + throw new Error(`The Matcher ${matcherName}() cannot be nested within arrayWith()`); + } + const innerResult = matcher.test(actual[actualIdx]); + if (!this.subsequence || !innerResult.hasFailed()) { + result.compose(`[${actualIdx}]`, innerResult); + patternIdx++; + actualIdx++; + } else { + actualIdx++; + } + } + for (; patternIdx < this.pattern.length; patternIdx++) { + const pattern = this.pattern[patternIdx]; + const element = Matcher.isMatcher(pattern) || typeof pattern === "object" ? " " : ` [${pattern}] `; + result.recordFailure({ + matcher: this, + path: [], + message: `Missing element${element}at pattern index ${patternIdx}` + }); + } + return result; + } +}; +var ObjectMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partial = options.partial ?? true; + } + test(actual) { + if (typeof actual !== "object" || Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type object but received ${getType(actual)}` + }); + } + const result = new MatchResult(actual); + if (!this.partial) { + for (const a of Object.keys(actual)) { + if (!(a in this.pattern)) { + result.recordFailure({ + matcher: this, + path: [`/${a}`], + message: "Unexpected key" + }); + } + } + } + for (const [patternKey, patternVal] of Object.entries(this.pattern)) { + if (!(patternKey in actual) && !(patternVal instanceof AbsentMatch)) { + result.recordFailure({ + matcher: this, + path: [`/${patternKey}`], + message: `Missing key '${patternKey}' among {${Object.keys(actual).join(",")}}` + }); + continue; + } + const matcher = Matcher.isMatcher(patternVal) ? patternVal : new LiteralMatch(this.name, patternVal, { partialObjects: this.partial }); + const inner = matcher.test(actual[patternKey]); + result.compose(`/${patternKey}`, inner); + } + return result; + } +}; +var SerializedJson = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + if (getType(actual) !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected JSON as a string but found ${getType(actual)}` + }); + return result; + } + let parsed; + try { + parsed = JSON.parse(actual); + } catch (err) { + if (err instanceof SyntaxError) { + result.recordFailure({ + matcher: this, + path: [], + message: `Invalid JSON string: ${actual}` + }); + return result; + } else { + throw err; + } + } + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(parsed); + result.compose(`(${this.name})`, innerResult); + return result; + } +}; +var NotMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(actual); + const result = new MatchResult(actual); + if (innerResult.failCount === 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Found unexpected match: ${JSON.stringify(actual, void 0, 2)}` + }); + } + return result; + } +}; +var AnyMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual == null) { + result.recordFailure({ + matcher: this, + path: [], + message: "Expected a value but found none" + }); + } + return result; + } +}; +var StringLikeRegexpMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + const regex = new RegExp(this.pattern, "gm"); + if (typeof actual !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected a string, but got '${typeof actual}'` + }); + } + if (!regex.test(actual)) { + result.recordFailure({ + matcher: this, + path: [], + message: `String '${actual}' did not match pattern '${this.pattern}'` + }); + } + return result; + } +}; + +// lib/assertions/providers/lambda-handler/base.ts +var https = __toESM(require("https")); +var url = __toESM(require("url")); +var CustomResourceHandler = class { + constructor(event, context) { + this.event = event; + this.context = context; + this.timedOut = false; + this.timeout = setTimeout(async () => { + await this.respond({ + status: "FAILED", + reason: "Lambda Function Timeout", + data: this.context.logStreamName + }); + this.timedOut = true; + }, context.getRemainingTimeInMillis() - 1200); + this.event = event; + this.physicalResourceId = extractPhysicalResourceId(event); + } + async handle() { + try { + console.log(`Event: ${JSON.stringify({ ...this.event, ResponseURL: "..." })}`); + const response = await this.processEvent(this.event.ResourceProperties); + console.log(`Event output : ${JSON.stringify(response)}`); + await this.respond({ + status: "SUCCESS", + reason: "OK", + data: response + }); + } catch (e) { + console.log(e); + await this.respond({ + status: "FAILED", + reason: e.message ?? "Internal Error" + }); + } finally { + clearTimeout(this.timeout); + } + } + respond(response) { + if (this.timedOut) { + return; + } + const cfResponse = { + Status: response.status, + Reason: response.reason, + PhysicalResourceId: this.physicalResourceId, + StackId: this.event.StackId, + RequestId: this.event.RequestId, + LogicalResourceId: this.event.LogicalResourceId, + NoEcho: false, + Data: response.data + }; + const responseBody = JSON.stringify(cfResponse); + console.log("Responding to CloudFormation", responseBody); + const parsedUrl = url.parse(this.event.ResponseURL); + const requestOptions = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: "PUT", + headers: { "content-type": "", "content-length": responseBody.length } + }; + return new Promise((resolve, reject) => { + try { + const request2 = https.request(requestOptions, resolve); + request2.on("error", reject); + request2.write(responseBody); + request2.end(); + } catch (e) { + reject(e); + } + }); + } +}; +function extractPhysicalResourceId(event) { + switch (event.RequestType) { + case "Create": + return event.LogicalResourceId; + case "Update": + case "Delete": + return event.PhysicalResourceId; + } +} + +// lib/assertions/providers/lambda-handler/assertion.ts +var AssertionHandler = class extends CustomResourceHandler { + async processEvent(request2) { + let actual = decodeCall(request2.actual); + const expected = decodeCall(request2.expected); + let result; + const matcher = new MatchCreator(expected).getMatcher(); + console.log(`Testing equality between ${JSON.stringify(request2.actual)} and ${JSON.stringify(request2.expected)}`); + const matchResult = matcher.test(actual); + matchResult.finished(); + if (matchResult.hasFailed()) { + result = { + data: JSON.stringify({ + status: "fail", + message: [ + ...matchResult.toHumanStrings(), + JSON.stringify(matchResult.target, void 0, 2) + ].join("\n") + }) + }; + if (request2.failDeployment) { + throw new Error(result.data); + } + } else { + result = { + data: JSON.stringify({ + status: "success" + }) + }; + } + return result; + } +}; +var MatchCreator = class { + constructor(obj) { + this.parsedObj = { + matcher: obj + }; + } + getMatcher() { + try { + const final = JSON.parse(JSON.stringify(this.parsedObj), function(_k, v) { + const nested = Object.keys(v)[0]; + switch (nested) { + case "$ArrayWith": + return Match.arrayWith(v[nested]); + case "$ObjectLike": + return Match.objectLike(v[nested]); + case "$StringLike": + return Match.stringLikeRegexp(v[nested]); + default: + return v; + } + }); + if (Matcher.isMatcher(final.matcher)) { + return final.matcher; + } + return Match.exact(final.matcher); + } catch { + return Match.exact(this.parsedObj.matcher); + } + } +}; +function decodeCall(call) { + if (!call) { + return void 0; + } + try { + const parsed = JSON.parse(call); + return parsed; + } catch (e) { + return call; + } +} + +// lib/assertions/providers/lambda-handler/utils.ts +function decode(object) { + return JSON.parse(JSON.stringify(object), (_k, v) => { + switch (v) { + case "TRUE:BOOLEAN": + return true; + case "FALSE:BOOLEAN": + return false; + default: + return v; + } + }); +} + +// lib/assertions/providers/lambda-handler/sdk.ts +function flatten(object) { + return Object.assign( + {}, + ...function _flatten(child, path = []) { + return [].concat(...Object.keys(child).map((key) => { + const childKey = Buffer.isBuffer(child[key]) ? child[key].toString("utf8") : child[key]; + return typeof childKey === "object" && childKey !== null ? _flatten(childKey, path.concat([key])) : { [path.concat([key]).join(".")]: childKey }; + })); + }(object) + ); +} +var AwsApiCallHandler = class extends CustomResourceHandler { + async processEvent(request2) { + const AWS = require("aws-sdk"); + console.log(`AWS SDK VERSION: ${AWS.VERSION}`); + const service = new AWS[request2.service](); + const response = await service[request2.api](request2.parameters && decode(request2.parameters)).promise(); + console.log(`SDK response received ${JSON.stringify(response)}`); + delete response.ResponseMetadata; + const respond = { + apiCallResponse: response + }; + const flatData = { + ...flatten(respond) + }; + return request2.flattenResponse === "true" ? flatData : respond; + } +}; + +// lib/assertions/providers/lambda-handler/types.ts +var ASSERT_RESOURCE_TYPE = "Custom::DeployAssert@AssertEquals"; +var SDK_RESOURCE_TYPE_PREFIX = "Custom::DeployAssert@SdkCall"; + +// lib/assertions/providers/lambda-handler/index.ts +async function handler(event, context) { + const provider = createResourceHandler(event, context); + await provider.handle(); +} +function createResourceHandler(event, context) { + if (event.ResourceType.startsWith(SDK_RESOURCE_TYPE_PREFIX)) { + return new AwsApiCallHandler(event, context); + } + switch (event.ResourceType) { + case ASSERT_RESOURCE_TYPE: + return new AssertionHandler(event, context); + default: + throw new Error(`Unsupported resource type "${event.ResourceType}`); + } +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + handler +}); diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/integ-lambda-python-poetry.assets.json b/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/integ-lambda-python-poetry.assets.json new file mode 100644 index 0000000000000..1b2daf3089b55 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/integ-lambda-python-poetry.assets.json @@ -0,0 +1,58 @@ +{ + "version": "21.0.0", + "files": { + "c61e0f11a70b8ae390550b4477f611d7548cddc58c9a1808b8fa738c84e8849a": { + "source": { + "path": "asset.c61e0f11a70b8ae390550b4477f611d7548cddc58c9a1808b8fa738c84e8849a", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "c61e0f11a70b8ae390550b4477f611d7548cddc58c9a1808b8fa738c84e8849a.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "6d591f099499066675f839dee783892f055c6748cad3ec707031bfb839a7dcf6": { + "source": { + "path": "asset.6d591f099499066675f839dee783892f055c6748cad3ec707031bfb839a7dcf6", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "6d591f099499066675f839dee783892f055c6748cad3ec707031bfb839a7dcf6.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "bc90fc78bab5daff01b73ec5433b085e4324b6956f1c77d320a2d54fb8eb03f1": { + "source": { + "path": "asset.bc90fc78bab5daff01b73ec5433b085e4324b6956f1c77d320a2d54fb8eb03f1", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "bc90fc78bab5daff01b73ec5433b085e4324b6956f1c77d320a2d54fb8eb03f1.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "8112ad5508e2643bdc358860414feb34c0375b34b86dfdaec27fab32c38ea900": { + "source": { + "path": "integ-lambda-python-poetry.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "8112ad5508e2643bdc358860414feb34c0375b34b86dfdaec27fab32c38ea900.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/cdk-integ-lambda-python.template.json b/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/integ-lambda-python-poetry.template.json similarity index 61% rename from packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/cdk-integ-lambda-python.template.json rename to packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/integ-lambda-python-poetry.template.json index 417490cd7cb8e..c9954042be36b 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/cdk-integ-lambda-python.template.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/integ-lambda-python-poetry.template.json @@ -38,7 +38,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "8d7289aede51c7665a9df0be604eabacb55f0dc5979ea64c70fe3686e60ae5ae.zip" + "S3Key": "c61e0f11a70b8ae390550b4477f611d7548cddc58c9a1808b8fa738c84e8849a.zip" }, "Role": { "Fn::GetAtt": [ @@ -91,7 +91,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "48df79eafe4c27c7b40259916623d0b5a9722e315827d20e6f2dd91c5103352a.zip" + "S3Key": "6d591f099499066675f839dee783892f055c6748cad3ec707031bfb839a7dcf6.zip" }, "Role": { "Fn::GetAtt": [ @@ -105,17 +105,84 @@ "DependsOn": [ "myhandlerpython38ServiceRole2049AFF7" ] + }, + "myhandlerpython37ServiceRole45CBD18D": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "myhandlerpython37C34039A7": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "bc90fc78bab5daff01b73ec5433b085e4324b6956f1c77d320a2d54fb8eb03f1.zip" + }, + "Role": { + "Fn::GetAtt": [ + "myhandlerpython37ServiceRole45CBD18D", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "python3.7" + }, + "DependsOn": [ + "myhandlerpython37ServiceRole45CBD18D" + ] } }, "Outputs": { - "InlineFunctionName": { + "ExportsOutputRefmyhandlerinline53D120C7B0898676": { "Value": { "Ref": "myhandlerinline53D120C7" + }, + "Export": { + "Name": "integ-lambda-python-poetry:ExportsOutputRefmyhandlerinline53D120C7B0898676" } }, - "Python38FunctionName": { + "ExportsOutputRefmyhandlerpython384D62BBB58AA8B940": { "Value": { "Ref": "myhandlerpython384D62BBB5" + }, + "Export": { + "Name": "integ-lambda-python-poetry:ExportsOutputRefmyhandlerpython384D62BBB58AA8B940" + } + }, + "ExportsOutputRefmyhandlerpython37C34039A7BB71D94D": { + "Value": { + "Ref": "myhandlerpython37C34039A7" + }, + "Export": { + "Name": "integ-lambda-python-poetry:ExportsOutputRefmyhandlerpython37C34039A7BB71D94D" } } }, diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/integ.json b/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/integ.json index 9d43d6f6375d1..373db0c4530d7 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/integ.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/integ.json @@ -3,7 +3,7 @@ "testCases": { "poetry/DefaultTest": { "stacks": [ - "cdk-integ-lambda-python" + "integ-lambda-python-poetry" ], "stackUpdateWorkflow": false, "assertionStack": "poetry/DefaultTest/DeployAssert", diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/manifest.json index 87d4bef76061d..ca49d8411e8cf 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/manifest.json @@ -7,27 +7,27 @@ "file": "tree.json" } }, - "cdk-integ-lambda-python.assets": { + "integ-lambda-python-poetry.assets": { "type": "cdk:asset-manifest", "properties": { - "file": "cdk-integ-lambda-python.assets.json", + "file": "integ-lambda-python-poetry.assets.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" } }, - "cdk-integ-lambda-python": { + "integ-lambda-python-poetry": { "type": "aws:cloudformation:stack", "environment": "aws://unknown-account/unknown-region", "properties": { - "templateFile": "cdk-integ-lambda-python.template.json", + "templateFile": "integ-lambda-python-poetry.template.json", "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/5187de9a41f36d4b41ca1553d50265326d21791726e2a3dd0a3201910180fc0f.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/8112ad5508e2643bdc358860414feb34c0375b34b86dfdaec27fab32c38ea900.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ - "cdk-integ-lambda-python.assets" + "integ-lambda-python-poetry.assets" ], "lookupRole": { "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", @@ -36,71 +36,77 @@ } }, "dependencies": [ - "cdk-integ-lambda-python.assets" + "integ-lambda-python-poetry.assets" ], "metadata": { - "/cdk-integ-lambda-python/my_handler_inline/ServiceRole/Resource": [ + "/integ-lambda-python-poetry/my_handler_inline/ServiceRole/Resource": [ { "type": "aws:cdk:logicalId", "data": "myhandlerinlineServiceRole10C681F6" } ], - "/cdk-integ-lambda-python/my_handler_inline/Resource": [ + "/integ-lambda-python-poetry/my_handler_inline/Resource": [ { "type": "aws:cdk:logicalId", "data": "myhandlerinline53D120C7" } ], - "/cdk-integ-lambda-python/InlineFunctionName": [ + "/integ-lambda-python-poetry/my_handler_python_38/ServiceRole/Resource": [ { "type": "aws:cdk:logicalId", - "data": "InlineFunctionName" + "data": "myhandlerpython38ServiceRole2049AFF7" } ], - "/cdk-integ-lambda-python/my_handler_python_38/ServiceRole/Resource": [ + "/integ-lambda-python-poetry/my_handler_python_38/Resource": [ { "type": "aws:cdk:logicalId", - "data": "myhandlerpython38ServiceRole2049AFF7" + "data": "myhandlerpython384D62BBB5" } ], - "/cdk-integ-lambda-python/my_handler_python_38/Resource": [ + "/integ-lambda-python-poetry/my_handler_python_37/ServiceRole/Resource": [ { "type": "aws:cdk:logicalId", - "data": "myhandlerpython384D62BBB5" + "data": "myhandlerpython37ServiceRole45CBD18D" } ], - "/cdk-integ-lambda-python/Python38FunctionName": [ + "/integ-lambda-python-poetry/my_handler_python_37/Resource": [ { "type": "aws:cdk:logicalId", - "data": "Python38FunctionName" + "data": "myhandlerpython37C34039A7" } ], - "/cdk-integ-lambda-python/my_handler_python_37/ServiceRole/Resource": [ + "/integ-lambda-python-poetry/Exports/Output{\"Ref\":\"myhandlerinline53D120C7\"}": [ { "type": "aws:cdk:logicalId", - "data": "myhandlerpython37ServiceRole45CBD18D" + "data": "ExportsOutputRefmyhandlerinline53D120C7B0898676" } ], - "/cdk-integ-lambda-python/my_handler_python_37/Resource": [ + "/integ-lambda-python-poetry/Exports/Output{\"Ref\":\"myhandlerpython384D62BBB5\"}": [ { "type": "aws:cdk:logicalId", - "data": "myhandlerpython37C34039A7" + "data": "ExportsOutputRefmyhandlerpython384D62BBB58AA8B940" } ], - "/cdk-integ-lambda-python/BootstrapVersion": [ + "/integ-lambda-python-poetry/Exports/Output{\"Ref\":\"myhandlerpython37C34039A7\"}": [ + { + "type": "aws:cdk:logicalId", + "data": "ExportsOutputRefmyhandlerpython37C34039A7BB71D94D" + } + ], + "/integ-lambda-python-poetry/BootstrapVersion": [ { "type": "aws:cdk:logicalId", "data": "BootstrapVersion" } ], - "/cdk-integ-lambda-python/CheckBootstrapVersion": [ + "/integ-lambda-python-poetry/CheckBootstrapVersion": [ { "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } ] }, - "displayName": "cdk-integ-lambda-python" + "displayName": "integ-lambda-python-poetry" }, "poetryDefaultTestDeployAssertE9C9CB8F.assets": { "type": "cdk:asset-manifest", @@ -118,7 +124,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/6124f12c447c253e12d289b2cbb005676d5dd3f56d70cb3213d2c534caae16cc.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -131,9 +137,94 @@ } }, "dependencies": [ + "integ-lambda-python-poetry", "poetryDefaultTestDeployAssertE9C9CB8F.assets" ], "metadata": { + "/poetry/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke81c9998b1b428b309c8501e21b919d3d" + } + ], + "/poetry/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/Invoke": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke81c9998b1b428b309c8501e21b919d3dInvokeEBA46CA4" + } + ], + "/poetry/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/AssertEqualsLambdainvoke/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke81c9998b1b428b309c8501e21b919d3dAssertEqualsLambdainvoke0BDD9934" + } + ], + "/poetry/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/AssertEqualsLambdainvoke/AssertionResults": [ + { + "type": "aws:cdk:logicalId", + "data": "AssertionResultsAssertEqualsLambdainvoke7418f30d48b25a0240557aece0f9bcb3" + } + ], + "/poetry/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73" + } + ], + "/poetry/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F" + } + ], + "/poetry/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292" + } + ], + "/poetry/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/Invoke": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292InvokeFD76DE7B" + } + ], + "/poetry/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/AssertEqualsLambdainvoke/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292AssertEqualsLambdainvoke3F6858A2" + } + ], + "/poetry/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/AssertEqualsLambdainvoke/AssertionResults": [ + { + "type": "aws:cdk:logicalId", + "data": "AssertionResultsAssertEqualsLambdainvoke3a1682daaa67c2d3f1c57ad30bb121be" + } + ], + "/poetry/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75" + } + ], + "/poetry/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/Invoke": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75Invoke11F9A252" + } + ], + "/poetry/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/AssertEqualsLambdainvoke/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75AssertEqualsLambdainvoke2346EE1F" + } + ], + "/poetry/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/AssertEqualsLambdainvoke/AssertionResults": [ + { + "type": "aws:cdk:logicalId", + "data": "AssertionResultsAssertEqualsLambdainvoke71fd18c839842d08b4fd70cd8691cb1f" + } + ], "/poetry/DefaultTest/DeployAssert/BootstrapVersion": [ { "type": "aws:cdk:logicalId", diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/poetryDefaultTestDeployAssertE9C9CB8F.assets.json b/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/poetryDefaultTestDeployAssertE9C9CB8F.assets.json index d73b790ad18fa..1d5bf07a5344f 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/poetryDefaultTestDeployAssertE9C9CB8F.assets.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/poetryDefaultTestDeployAssertE9C9CB8F.assets.json @@ -1,7 +1,20 @@ { "version": "21.0.0", "files": { - "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7": { + "source": { + "path": "asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "6124f12c447c253e12d289b2cbb005676d5dd3f56d70cb3213d2c534caae16cc": { "source": { "path": "poetryDefaultTestDeployAssertE9C9CB8F.template.json", "packaging": "file" @@ -9,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "objectKey": "6124f12c447c253e12d289b2cbb005676d5dd3f56d70cb3213d2c534caae16cc.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/poetryDefaultTestDeployAssertE9C9CB8F.template.json b/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/poetryDefaultTestDeployAssertE9C9CB8F.template.json index ad9d0fb73d1dd..634e3f92ddaf6 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/poetryDefaultTestDeployAssertE9C9CB8F.template.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/poetryDefaultTestDeployAssertE9C9CB8F.template.json @@ -1,4 +1,378 @@ { + "Resources": { + "LambdaInvoke81c9998b1b428b309c8501e21b919d3d": { + "Type": "Custom::DeployAssert@SdkCallLambdainvoke", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "service": "Lambda", + "api": "invoke", + "parameters": { + "FunctionName": { + "Fn::ImportValue": "integ-lambda-python-poetry:ExportsOutputRefmyhandlerinline53D120C7B0898676" + } + }, + "flattenResponse": "false", + "salt": "1662643425337" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "LambdaInvoke81c9998b1b428b309c8501e21b919d3dInvokeEBA46CA4": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::ImportValue": "integ-lambda-python-poetry:ExportsOutputRefmyhandlerinline53D120C7B0898676" + }, + "Principal": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + }, + "LambdaInvoke81c9998b1b428b309c8501e21b919d3dAssertEqualsLambdainvoke0BDD9934": { + "Type": "Custom::DeployAssert@AssertEquals", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "actual": { + "Fn::GetAtt": [ + "LambdaInvoke81c9998b1b428b309c8501e21b919d3d", + "apiCallResponse" + ] + }, + "expected": "{\"$ObjectLike\":{\"Payload\":\"200\"}}", + "salt": "1662643425338" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "lambda:Invoke" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":lambda:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":function:", + { + "Fn::ImportValue": "integ-lambda-python-poetry:ExportsOutputRefmyhandlerinline53D120C7B0898676" + } + ] + ] + } + ] + }, + { + "Action": [ + "lambda:Invoke" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":lambda:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":function:", + { + "Fn::ImportValue": "integ-lambda-python-poetry:ExportsOutputRefmyhandlerpython384D62BBB58AA8B940" + } + ] + ] + } + ] + }, + { + "Action": [ + "lambda:Invoke" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":lambda:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":function:", + { + "Fn::ImportValue": "integ-lambda-python-poetry:ExportsOutputRefmyhandlerpython37C34039A7BB71D94D" + } + ] + ] + } + ] + } + ] + } + } + ] + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Runtime": "nodejs14.x", + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip" + }, + "Timeout": 120, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + }, + "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292": { + "Type": "Custom::DeployAssert@SdkCallLambdainvoke", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "service": "Lambda", + "api": "invoke", + "parameters": { + "FunctionName": { + "Fn::ImportValue": "integ-lambda-python-poetry:ExportsOutputRefmyhandlerpython384D62BBB58AA8B940" + } + }, + "flattenResponse": "false", + "salt": "1662643425339" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292InvokeFD76DE7B": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::ImportValue": "integ-lambda-python-poetry:ExportsOutputRefmyhandlerpython384D62BBB58AA8B940" + }, + "Principal": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + }, + "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292AssertEqualsLambdainvoke3F6858A2": { + "Type": "Custom::DeployAssert@AssertEquals", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "actual": { + "Fn::GetAtt": [ + "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292", + "apiCallResponse" + ] + }, + "expected": "{\"$ObjectLike\":{\"Payload\":\"200\"}}", + "salt": "1662643425339" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75": { + "Type": "Custom::DeployAssert@SdkCallLambdainvoke", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "service": "Lambda", + "api": "invoke", + "parameters": { + "FunctionName": { + "Fn::ImportValue": "integ-lambda-python-poetry:ExportsOutputRefmyhandlerpython37C34039A7BB71D94D" + } + }, + "flattenResponse": "false", + "salt": "1662643425339" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75Invoke11F9A252": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::ImportValue": "integ-lambda-python-poetry:ExportsOutputRefmyhandlerpython37C34039A7BB71D94D" + }, + "Principal": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + }, + "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75AssertEqualsLambdainvoke2346EE1F": { + "Type": "Custom::DeployAssert@AssertEquals", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "actual": { + "Fn::GetAtt": [ + "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75", + "apiCallResponse" + ] + }, + "expected": "{\"$ObjectLike\":{\"Payload\":\"200\"}}", + "salt": "1662643425339" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Outputs": { + "AssertionResultsAssertEqualsLambdainvoke7418f30d48b25a0240557aece0f9bcb3": { + "Value": { + "Fn::GetAtt": [ + "LambdaInvoke81c9998b1b428b309c8501e21b919d3dAssertEqualsLambdainvoke0BDD9934", + "data" + ] + } + }, + "AssertionResultsAssertEqualsLambdainvoke3a1682daaa67c2d3f1c57ad30bb121be": { + "Value": { + "Fn::GetAtt": [ + "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292AssertEqualsLambdainvoke3F6858A2", + "data" + ] + } + }, + "AssertionResultsAssertEqualsLambdainvoke71fd18c839842d08b4fd70cd8691cb1f": { + "Value": { + "Fn::GetAtt": [ + "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75AssertEqualsLambdainvoke2346EE1F", + "data" + ] + } + } + }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/tree.json b/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/tree.json index 9e9b09c2a9c47..79fdc9449e9f8 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.poetry.integ.snapshot/tree.json @@ -12,21 +12,21 @@ "version": "10.1.95" } }, - "cdk-integ-lambda-python": { - "id": "cdk-integ-lambda-python", - "path": "cdk-integ-lambda-python", + "integ-lambda-python-poetry": { + "id": "integ-lambda-python-poetry", + "path": "integ-lambda-python-poetry", "children": { "my_handler_inline": { "id": "my_handler_inline", - "path": "cdk-integ-lambda-python/my_handler_inline", + "path": "integ-lambda-python-poetry/my_handler_inline", "children": { "ServiceRole": { "id": "ServiceRole", - "path": "cdk-integ-lambda-python/my_handler_inline/ServiceRole", + "path": "integ-lambda-python-poetry/my_handler_inline/ServiceRole", "children": { "Resource": { "id": "Resource", - "path": "cdk-integ-lambda-python/my_handler_inline/ServiceRole/Resource", + "path": "integ-lambda-python-poetry/my_handler_inline/ServiceRole/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::IAM::Role", "aws:cdk:cloudformation:props": { @@ -71,11 +71,11 @@ }, "Code": { "id": "Code", - "path": "cdk-integ-lambda-python/my_handler_inline/Code", + "path": "integ-lambda-python-poetry/my_handler_inline/Code", "children": { "Stage": { "id": "Stage", - "path": "cdk-integ-lambda-python/my_handler_inline/Code/Stage", + "path": "integ-lambda-python-poetry/my_handler_inline/Code/Stage", "constructInfo": { "fqn": "@aws-cdk/core.AssetStaging", "version": "0.0.0" @@ -83,7 +83,7 @@ }, "AssetBucket": { "id": "AssetBucket", - "path": "cdk-integ-lambda-python/my_handler_inline/Code/AssetBucket", + "path": "integ-lambda-python-poetry/my_handler_inline/Code/AssetBucket", "constructInfo": { "fqn": "@aws-cdk/aws-s3.BucketBase", "version": "0.0.0" @@ -97,7 +97,7 @@ }, "Resource": { "id": "Resource", - "path": "cdk-integ-lambda-python/my_handler_inline/Resource", + "path": "integ-lambda-python-poetry/my_handler_inline/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { @@ -105,7 +105,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "377b8c7d7d74049daef959af1f7f0f0f2eaeb6ccb4c85fe80f8c00936183b6ff.zip" + "s3Key": "c61e0f11a70b8ae390550b4477f611d7548cddc58c9a1808b8fa738c84e8849a.zip" }, "role": { "Fn::GetAtt": [ @@ -128,25 +128,17 @@ "version": "0.0.0" } }, - "InlineFunctionName": { - "id": "InlineFunctionName", - "path": "cdk-integ-lambda-python/InlineFunctionName", - "constructInfo": { - "fqn": "@aws-cdk/core.CfnOutput", - "version": "0.0.0" - } - }, "my_handler_python_38": { "id": "my_handler_python_38", - "path": "cdk-integ-lambda-python/my_handler_python_38", + "path": "integ-lambda-python-poetry/my_handler_python_38", "children": { "ServiceRole": { "id": "ServiceRole", - "path": "cdk-integ-lambda-python/my_handler_python_38/ServiceRole", + "path": "integ-lambda-python-poetry/my_handler_python_38/ServiceRole", "children": { "Resource": { "id": "Resource", - "path": "cdk-integ-lambda-python/my_handler_python_38/ServiceRole/Resource", + "path": "integ-lambda-python-poetry/my_handler_python_38/ServiceRole/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::IAM::Role", "aws:cdk:cloudformation:props": { @@ -191,11 +183,11 @@ }, "Code": { "id": "Code", - "path": "cdk-integ-lambda-python/my_handler_python_38/Code", + "path": "integ-lambda-python-poetry/my_handler_python_38/Code", "children": { "Stage": { "id": "Stage", - "path": "cdk-integ-lambda-python/my_handler_python_38/Code/Stage", + "path": "integ-lambda-python-poetry/my_handler_python_38/Code/Stage", "constructInfo": { "fqn": "@aws-cdk/core.AssetStaging", "version": "0.0.0" @@ -203,7 +195,7 @@ }, "AssetBucket": { "id": "AssetBucket", - "path": "cdk-integ-lambda-python/my_handler_python_38/Code/AssetBucket", + "path": "integ-lambda-python-poetry/my_handler_python_38/Code/AssetBucket", "constructInfo": { "fqn": "@aws-cdk/aws-s3.BucketBase", "version": "0.0.0" @@ -217,7 +209,7 @@ }, "Resource": { "id": "Resource", - "path": "cdk-integ-lambda-python/my_handler_python_38/Resource", + "path": "integ-lambda-python-poetry/my_handler_python_38/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { @@ -225,7 +217,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "f27e50ce3e964bd188b2fad96e1819a8e68a7a7a17e1f701b6bdcc054e29503a.zip" + "s3Key": "6d591f099499066675f839dee783892f055c6748cad3ec707031bfb839a7dcf6.zip" }, "role": { "Fn::GetAtt": [ @@ -248,25 +240,17 @@ "version": "0.0.0" } }, - "Python38FunctionName": { - "id": "Python38FunctionName", - "path": "cdk-integ-lambda-python/Python38FunctionName", - "constructInfo": { - "fqn": "@aws-cdk/core.CfnOutput", - "version": "0.0.0" - } - }, "my_handler_python_37": { "id": "my_handler_python_37", - "path": "cdk-integ-lambda-python/my_handler_python_37", + "path": "integ-lambda-python-poetry/my_handler_python_37", "children": { "ServiceRole": { "id": "ServiceRole", - "path": "cdk-integ-lambda-python/my_handler_python_37/ServiceRole", + "path": "integ-lambda-python-poetry/my_handler_python_37/ServiceRole", "children": { "Resource": { "id": "Resource", - "path": "cdk-integ-lambda-python/my_handler_python_37/ServiceRole/Resource", + "path": "integ-lambda-python-poetry/my_handler_python_37/ServiceRole/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::IAM::Role", "aws:cdk:cloudformation:props": { @@ -311,11 +295,11 @@ }, "Code": { "id": "Code", - "path": "cdk-integ-lambda-python/my_handler_python_37/Code", + "path": "integ-lambda-python-poetry/my_handler_python_37/Code", "children": { "Stage": { "id": "Stage", - "path": "cdk-integ-lambda-python/my_handler_python_37/Code/Stage", + "path": "integ-lambda-python-poetry/my_handler_python_37/Code/Stage", "constructInfo": { "fqn": "@aws-cdk/core.AssetStaging", "version": "0.0.0" @@ -323,7 +307,7 @@ }, "AssetBucket": { "id": "AssetBucket", - "path": "cdk-integ-lambda-python/my_handler_python_37/Code/AssetBucket", + "path": "integ-lambda-python-poetry/my_handler_python_37/Code/AssetBucket", "constructInfo": { "fqn": "@aws-cdk/aws-s3.BucketBase", "version": "0.0.0" @@ -337,7 +321,7 @@ }, "Resource": { "id": "Resource", - "path": "cdk-integ-lambda-python/my_handler_python_37/Resource", + "path": "integ-lambda-python-poetry/my_handler_python_37/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { @@ -345,7 +329,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "d165152de494c90bdd8c4aa643a5b1e99b2a5cbacb7f4594319b3b45d6845fd3.zip" + "s3Key": "bc90fc78bab5daff01b73ec5433b085e4324b6956f1c77d320a2d54fb8eb03f1.zip" }, "role": { "Fn::GetAtt": [ @@ -367,6 +351,40 @@ "fqn": "@aws-cdk/aws-lambda-python.PythonFunction", "version": "0.0.0" } + }, + "Exports": { + "id": "Exports", + "path": "integ-lambda-python-poetry/Exports", + "children": { + "Output{\"Ref\":\"myhandlerinline53D120C7\"}": { + "id": "Output{\"Ref\":\"myhandlerinline53D120C7\"}", + "path": "integ-lambda-python-poetry/Exports/Output{\"Ref\":\"myhandlerinline53D120C7\"}", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "Output{\"Ref\":\"myhandlerpython384D62BBB5\"}": { + "id": "Output{\"Ref\":\"myhandlerpython384D62BBB5\"}", + "path": "integ-lambda-python-poetry/Exports/Output{\"Ref\":\"myhandlerpython384D62BBB5\"}", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "Output{\"Ref\":\"myhandlerpython37C34039A7\"}": { + "id": "Output{\"Ref\":\"myhandlerpython37C34039A7\"}", + "path": "integ-lambda-python-poetry/Exports/Output{\"Ref\":\"myhandlerpython37C34039A7\"}", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } } }, "constructInfo": { @@ -393,6 +411,366 @@ "DeployAssert": { "id": "DeployAssert", "path": "poetry/DefaultTest/DeployAssert", + "children": { + "LambdaInvoke81c9998b1b428b309c8501e21b919d3d": { + "id": "LambdaInvoke81c9998b1b428b309c8501e21b919d3d", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d", + "children": { + "SdkProvider": { + "id": "SdkProvider", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/SdkProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/SdkProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "Default": { + "id": "Default", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/Default", + "children": { + "Default": { + "id": "Default", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "Invoke": { + "id": "Invoke", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/Invoke", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "AssertEqualsLambdainvoke": { + "id": "AssertEqualsLambdainvoke", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/AssertEqualsLambdainvoke", + "children": { + "AssertionProvider": { + "id": "AssertionProvider", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/AssertEqualsLambdainvoke/AssertionProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/AssertEqualsLambdainvoke/AssertionProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "Default": { + "id": "Default", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/AssertEqualsLambdainvoke/Default", + "children": { + "Default": { + "id": "Default", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/AssertEqualsLambdainvoke/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "AssertionResults": { + "id": "AssertionResults", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke81c9998b1b428b309c8501e21b919d3d/AssertEqualsLambdainvoke/AssertionResults", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81": { + "id": "SingletonFunction1488541a7b23466481b69b4408076b81", + "path": "poetry/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81", + "children": { + "Staging": { + "id": "Staging", + "path": "poetry/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Staging", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "poetry/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "poetry/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292": { + "id": "LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292", + "children": { + "SdkProvider": { + "id": "SdkProvider", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/SdkProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/SdkProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "Default": { + "id": "Default", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/Default", + "children": { + "Default": { + "id": "Default", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "Invoke": { + "id": "Invoke", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/Invoke", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "AssertEqualsLambdainvoke": { + "id": "AssertEqualsLambdainvoke", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/AssertEqualsLambdainvoke", + "children": { + "AssertionProvider": { + "id": "AssertionProvider", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/AssertEqualsLambdainvoke/AssertionProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/AssertEqualsLambdainvoke/AssertionProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "Default": { + "id": "Default", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/AssertEqualsLambdainvoke/Default", + "children": { + "Default": { + "id": "Default", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/AssertEqualsLambdainvoke/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "AssertionResults": { + "id": "AssertionResults", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke9a0beb4ea6cc38db92e9ff664c085292/AssertEqualsLambdainvoke/AssertionResults", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75": { + "id": "LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75", + "children": { + "SdkProvider": { + "id": "SdkProvider", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/SdkProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/SdkProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "Default": { + "id": "Default", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/Default", + "children": { + "Default": { + "id": "Default", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "Invoke": { + "id": "Invoke", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/Invoke", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "AssertEqualsLambdainvoke": { + "id": "AssertEqualsLambdainvoke", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/AssertEqualsLambdainvoke", + "children": { + "AssertionProvider": { + "id": "AssertionProvider", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/AssertEqualsLambdainvoke/AssertionProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/AssertEqualsLambdainvoke/AssertionProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "Default": { + "id": "Default", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/AssertEqualsLambdainvoke/Default", + "children": { + "Default": { + "id": "Default", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/AssertEqualsLambdainvoke/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "AssertionResults": { + "id": "AssertionResults", + "path": "poetry/DefaultTest/DeployAssert/LambdaInvoke631dde0680edf7d2f0eea8d9b9c06c75/AssertEqualsLambdainvoke/AssertionResults", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, "constructInfo": { "fqn": "@aws-cdk/core.Stack", "version": "0.0.0" @@ -400,14 +778,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/integ-tests.IntegTestCase", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.95" } } }, "constructInfo": { - "fqn": "@aws-cdk/integ-tests.IntegTest", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.95" } } }, diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/asset.16976a5b4fcf4379b644e054aec3b6f87482e14284beff7337971995fa21e98c/index.py b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/asset.16976a5b4fcf4379b644e054aec3b6f87482e14284beff7337971995fa21e98c/index.py deleted file mode 100644 index fb1e8bb1ce0ab..0000000000000 --- a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/asset.16976a5b4fcf4379b644e054aec3b6f87482e14284beff7337971995fa21e98c/index.py +++ /dev/null @@ -1,9 +0,0 @@ -import requests -import shared - -def handler(event, context): - response = requests.get(shared.get_url(), stream=True) - - print(response.status_code) - - return response.status_code diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js new file mode 100644 index 0000000000000..ba956d47f51fe --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js @@ -0,0 +1,612 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// lib/assertions/providers/lambda-handler/index.ts +var lambda_handler_exports = {}; +__export(lambda_handler_exports, { + handler: () => handler +}); +module.exports = __toCommonJS(lambda_handler_exports); + +// ../assertions/lib/matcher.ts +var Matcher = class { + static isMatcher(x) { + return x && x instanceof Matcher; + } +}; +var MatchResult = class { + constructor(target) { + this.failures = []; + this.captures = /* @__PURE__ */ new Map(); + this.finalized = false; + this.target = target; + } + push(matcher, path, message) { + return this.recordFailure({ matcher, path, message }); + } + recordFailure(failure) { + this.failures.push(failure); + return this; + } + hasFailed() { + return this.failures.length !== 0; + } + get failCount() { + return this.failures.length; + } + compose(id, inner) { + const innerF = inner.failures; + this.failures.push(...innerF.map((f) => { + return { path: [id, ...f.path], message: f.message, matcher: f.matcher }; + })); + inner.captures.forEach((vals, capture) => { + vals.forEach((value) => this.recordCapture({ capture, value })); + }); + return this; + } + finished() { + if (this.finalized) { + return this; + } + if (this.failCount === 0) { + this.captures.forEach((vals, cap) => cap._captured.push(...vals)); + } + this.finalized = true; + return this; + } + toHumanStrings() { + return this.failures.map((r) => { + const loc = r.path.length === 0 ? "" : ` at ${r.path.join("")}`; + return "" + r.message + loc + ` (using ${r.matcher.name} matcher)`; + }); + } + recordCapture(options) { + let values = this.captures.get(options.capture); + if (values === void 0) { + values = []; + } + values.push(options.value); + this.captures.set(options.capture, values); + } +}; + +// ../assertions/lib/private/matchers/absent.ts +var AbsentMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual !== void 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Received ${actual}, but key should be absent` + }); + } + return result; + } +}; + +// ../assertions/lib/private/type.ts +function getType(obj) { + return Array.isArray(obj) ? "array" : typeof obj; +} + +// ../assertions/lib/match.ts +var Match = class { + static absent() { + return new AbsentMatch("absent"); + } + static arrayWith(pattern) { + return new ArrayMatch("arrayWith", pattern); + } + static arrayEquals(pattern) { + return new ArrayMatch("arrayEquals", pattern, { subsequence: false }); + } + static exact(pattern) { + return new LiteralMatch("exact", pattern, { partialObjects: false }); + } + static objectLike(pattern) { + return new ObjectMatch("objectLike", pattern); + } + static objectEquals(pattern) { + return new ObjectMatch("objectEquals", pattern, { partial: false }); + } + static not(pattern) { + return new NotMatch("not", pattern); + } + static serializedJson(pattern) { + return new SerializedJson("serializedJson", pattern); + } + static anyValue() { + return new AnyMatch("anyValue"); + } + static stringLikeRegexp(pattern) { + return new StringLikeRegexpMatch("stringLikeRegexp", pattern); + } +}; +var LiteralMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partialObjects = options.partialObjects ?? false; + if (Matcher.isMatcher(this.pattern)) { + throw new Error("LiteralMatch cannot directly contain another matcher. Remove the top-level matcher or nest it more deeply."); + } + } + test(actual) { + if (Array.isArray(this.pattern)) { + return new ArrayMatch(this.name, this.pattern, { subsequence: false, partialObjects: this.partialObjects }).test(actual); + } + if (typeof this.pattern === "object") { + return new ObjectMatch(this.name, this.pattern, { partial: this.partialObjects }).test(actual); + } + const result = new MatchResult(actual); + if (typeof this.pattern !== typeof actual) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected type ${typeof this.pattern} but received ${getType(actual)}` + }); + return result; + } + if (actual !== this.pattern) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected ${this.pattern} but received ${actual}` + }); + } + return result; + } +}; +var ArrayMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.subsequence = options.subsequence ?? true; + this.partialObjects = options.partialObjects ?? false; + } + test(actual) { + if (!Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type array but received ${getType(actual)}` + }); + } + if (!this.subsequence && this.pattern.length !== actual.length) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected array of length ${this.pattern.length} but received ${actual.length}` + }); + } + let patternIdx = 0; + let actualIdx = 0; + const result = new MatchResult(actual); + while (patternIdx < this.pattern.length && actualIdx < actual.length) { + const patternElement = this.pattern[patternIdx]; + const matcher = Matcher.isMatcher(patternElement) ? patternElement : new LiteralMatch(this.name, patternElement, { partialObjects: this.partialObjects }); + const matcherName = matcher.name; + if (this.subsequence && (matcherName == "absent" || matcherName == "anyValue")) { + throw new Error(`The Matcher ${matcherName}() cannot be nested within arrayWith()`); + } + const innerResult = matcher.test(actual[actualIdx]); + if (!this.subsequence || !innerResult.hasFailed()) { + result.compose(`[${actualIdx}]`, innerResult); + patternIdx++; + actualIdx++; + } else { + actualIdx++; + } + } + for (; patternIdx < this.pattern.length; patternIdx++) { + const pattern = this.pattern[patternIdx]; + const element = Matcher.isMatcher(pattern) || typeof pattern === "object" ? " " : ` [${pattern}] `; + result.recordFailure({ + matcher: this, + path: [], + message: `Missing element${element}at pattern index ${patternIdx}` + }); + } + return result; + } +}; +var ObjectMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partial = options.partial ?? true; + } + test(actual) { + if (typeof actual !== "object" || Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type object but received ${getType(actual)}` + }); + } + const result = new MatchResult(actual); + if (!this.partial) { + for (const a of Object.keys(actual)) { + if (!(a in this.pattern)) { + result.recordFailure({ + matcher: this, + path: [`/${a}`], + message: "Unexpected key" + }); + } + } + } + for (const [patternKey, patternVal] of Object.entries(this.pattern)) { + if (!(patternKey in actual) && !(patternVal instanceof AbsentMatch)) { + result.recordFailure({ + matcher: this, + path: [`/${patternKey}`], + message: `Missing key '${patternKey}' among {${Object.keys(actual).join(",")}}` + }); + continue; + } + const matcher = Matcher.isMatcher(patternVal) ? patternVal : new LiteralMatch(this.name, patternVal, { partialObjects: this.partial }); + const inner = matcher.test(actual[patternKey]); + result.compose(`/${patternKey}`, inner); + } + return result; + } +}; +var SerializedJson = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + if (getType(actual) !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected JSON as a string but found ${getType(actual)}` + }); + return result; + } + let parsed; + try { + parsed = JSON.parse(actual); + } catch (err) { + if (err instanceof SyntaxError) { + result.recordFailure({ + matcher: this, + path: [], + message: `Invalid JSON string: ${actual}` + }); + return result; + } else { + throw err; + } + } + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(parsed); + result.compose(`(${this.name})`, innerResult); + return result; + } +}; +var NotMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(actual); + const result = new MatchResult(actual); + if (innerResult.failCount === 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Found unexpected match: ${JSON.stringify(actual, void 0, 2)}` + }); + } + return result; + } +}; +var AnyMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual == null) { + result.recordFailure({ + matcher: this, + path: [], + message: "Expected a value but found none" + }); + } + return result; + } +}; +var StringLikeRegexpMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + const regex = new RegExp(this.pattern, "gm"); + if (typeof actual !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected a string, but got '${typeof actual}'` + }); + } + if (!regex.test(actual)) { + result.recordFailure({ + matcher: this, + path: [], + message: `String '${actual}' did not match pattern '${this.pattern}'` + }); + } + return result; + } +}; + +// lib/assertions/providers/lambda-handler/base.ts +var https = __toESM(require("https")); +var url = __toESM(require("url")); +var CustomResourceHandler = class { + constructor(event, context) { + this.event = event; + this.context = context; + this.timedOut = false; + this.timeout = setTimeout(async () => { + await this.respond({ + status: "FAILED", + reason: "Lambda Function Timeout", + data: this.context.logStreamName + }); + this.timedOut = true; + }, context.getRemainingTimeInMillis() - 1200); + this.event = event; + this.physicalResourceId = extractPhysicalResourceId(event); + } + async handle() { + try { + console.log(`Event: ${JSON.stringify({ ...this.event, ResponseURL: "..." })}`); + const response = await this.processEvent(this.event.ResourceProperties); + console.log(`Event output : ${JSON.stringify(response)}`); + await this.respond({ + status: "SUCCESS", + reason: "OK", + data: response + }); + } catch (e) { + console.log(e); + await this.respond({ + status: "FAILED", + reason: e.message ?? "Internal Error" + }); + } finally { + clearTimeout(this.timeout); + } + } + respond(response) { + if (this.timedOut) { + return; + } + const cfResponse = { + Status: response.status, + Reason: response.reason, + PhysicalResourceId: this.physicalResourceId, + StackId: this.event.StackId, + RequestId: this.event.RequestId, + LogicalResourceId: this.event.LogicalResourceId, + NoEcho: false, + Data: response.data + }; + const responseBody = JSON.stringify(cfResponse); + console.log("Responding to CloudFormation", responseBody); + const parsedUrl = url.parse(this.event.ResponseURL); + const requestOptions = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: "PUT", + headers: { "content-type": "", "content-length": responseBody.length } + }; + return new Promise((resolve, reject) => { + try { + const request2 = https.request(requestOptions, resolve); + request2.on("error", reject); + request2.write(responseBody); + request2.end(); + } catch (e) { + reject(e); + } + }); + } +}; +function extractPhysicalResourceId(event) { + switch (event.RequestType) { + case "Create": + return event.LogicalResourceId; + case "Update": + case "Delete": + return event.PhysicalResourceId; + } +} + +// lib/assertions/providers/lambda-handler/assertion.ts +var AssertionHandler = class extends CustomResourceHandler { + async processEvent(request2) { + let actual = decodeCall(request2.actual); + const expected = decodeCall(request2.expected); + let result; + const matcher = new MatchCreator(expected).getMatcher(); + console.log(`Testing equality between ${JSON.stringify(request2.actual)} and ${JSON.stringify(request2.expected)}`); + const matchResult = matcher.test(actual); + matchResult.finished(); + if (matchResult.hasFailed()) { + result = { + data: JSON.stringify({ + status: "fail", + message: [ + ...matchResult.toHumanStrings(), + JSON.stringify(matchResult.target, void 0, 2) + ].join("\n") + }) + }; + if (request2.failDeployment) { + throw new Error(result.data); + } + } else { + result = { + data: JSON.stringify({ + status: "success" + }) + }; + } + return result; + } +}; +var MatchCreator = class { + constructor(obj) { + this.parsedObj = { + matcher: obj + }; + } + getMatcher() { + try { + const final = JSON.parse(JSON.stringify(this.parsedObj), function(_k, v) { + const nested = Object.keys(v)[0]; + switch (nested) { + case "$ArrayWith": + return Match.arrayWith(v[nested]); + case "$ObjectLike": + return Match.objectLike(v[nested]); + case "$StringLike": + return Match.stringLikeRegexp(v[nested]); + default: + return v; + } + }); + if (Matcher.isMatcher(final.matcher)) { + return final.matcher; + } + return Match.exact(final.matcher); + } catch { + return Match.exact(this.parsedObj.matcher); + } + } +}; +function decodeCall(call) { + if (!call) { + return void 0; + } + try { + const parsed = JSON.parse(call); + return parsed; + } catch (e) { + return call; + } +} + +// lib/assertions/providers/lambda-handler/utils.ts +function decode(object) { + return JSON.parse(JSON.stringify(object), (_k, v) => { + switch (v) { + case "TRUE:BOOLEAN": + return true; + case "FALSE:BOOLEAN": + return false; + default: + return v; + } + }); +} + +// lib/assertions/providers/lambda-handler/sdk.ts +function flatten(object) { + return Object.assign( + {}, + ...function _flatten(child, path = []) { + return [].concat(...Object.keys(child).map((key) => { + const childKey = Buffer.isBuffer(child[key]) ? child[key].toString("utf8") : child[key]; + return typeof childKey === "object" && childKey !== null ? _flatten(childKey, path.concat([key])) : { [path.concat([key]).join(".")]: childKey }; + })); + }(object) + ); +} +var AwsApiCallHandler = class extends CustomResourceHandler { + async processEvent(request2) { + const AWS = require("aws-sdk"); + console.log(`AWS SDK VERSION: ${AWS.VERSION}`); + const service = new AWS[request2.service](); + const response = await service[request2.api](request2.parameters && decode(request2.parameters)).promise(); + console.log(`SDK response received ${JSON.stringify(response)}`); + delete response.ResponseMetadata; + const respond = { + apiCallResponse: response + }; + const flatData = { + ...flatten(respond) + }; + return request2.flattenResponse === "true" ? flatData : respond; + } +}; + +// lib/assertions/providers/lambda-handler/types.ts +var ASSERT_RESOURCE_TYPE = "Custom::DeployAssert@AssertEquals"; +var SDK_RESOURCE_TYPE_PREFIX = "Custom::DeployAssert@SdkCall"; + +// lib/assertions/providers/lambda-handler/index.ts +async function handler(event, context) { + const provider = createResourceHandler(event, context); + await provider.handle(); +} +function createResourceHandler(event, context) { + if (event.ResourceType.startsWith(SDK_RESOURCE_TYPE_PREFIX)) { + return new AwsApiCallHandler(event, context); + } + switch (event.ResourceType) { + case ASSERT_RESOURCE_TYPE: + return new AssertionHandler(event, context); + default: + throw new Error(`Unsupported resource type "${event.ResourceType}`); + } +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + handler +}); diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/asset.af982faba6f73b0b56c28d879814d9332c23cef5e285f6ed34a0c492b45bbae6/requirements.txt b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/asset.af982faba6f73b0b56c28d879814d9332c23cef5e285f6ed34a0c492b45bbae6/requirements.txt deleted file mode 100644 index eff24435fa632..0000000000000 --- a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/asset.af982faba6f73b0b56c28d879814d9332c23cef5e285f6ed34a0c492b45bbae6/requirements.txt +++ /dev/null @@ -1,6 +0,0 @@ -# Lock versions of pip packages -certifi==2020.6.20 -chardet==3.0.4 -idna==2.10 -urllib3==1.26.7 -# Requests used by this lambda diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/asset.af982faba6f73b0b56c28d879814d9332c23cef5e285f6ed34a0c492b45bbae6/shared.py b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/asset.af982faba6f73b0b56c28d879814d9332c23cef5e285f6ed34a0c492b45bbae6/shared.py deleted file mode 100644 index b17623b83b881..0000000000000 --- a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/asset.af982faba6f73b0b56c28d879814d9332c23cef5e285f6ed34a0c492b45bbae6/shared.py +++ /dev/null @@ -1,2 +0,0 @@ -def get_url() -> str: - return 'https://a0.awsstatic.com/main/images/logos/aws_smile-header-desktop-en-white_59x35.png' diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/cdk-integ-lambda-function-project.assets.json b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/cdk-integ-lambda-function-project.assets.json index 2a0e44bab5e84..17e695185c098 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/cdk-integ-lambda-function-project.assets.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/cdk-integ-lambda-function-project.assets.json @@ -1,33 +1,33 @@ { - "version": "20.0.0", + "version": "21.0.0", "files": { - "f1eb849ae54216b1a7785bca3aa8031a4671eac68c1997e3b6a500336fd6d8fa": { + "33674c5088a855fbd87f051a085794b3bd1bd41823d88091874d5f4f1b8ad884": { "source": { - "path": "asset.f1eb849ae54216b1a7785bca3aa8031a4671eac68c1997e3b6a500336fd6d8fa", + "path": "asset.33674c5088a855fbd87f051a085794b3bd1bd41823d88091874d5f4f1b8ad884", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "f1eb849ae54216b1a7785bca3aa8031a4671eac68c1997e3b6a500336fd6d8fa.zip", + "objectKey": "33674c5088a855fbd87f051a085794b3bd1bd41823d88091874d5f4f1b8ad884.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "55a6269bb8a00cf3b6d0b295a87c2fb8670afbeceb4427622bd38f248abfd3ed": { + "708ad240e424cc18dd8b85017f9e1173ac983ddd3b387b9f4df3577ea60e4a65": { "source": { - "path": "asset.55a6269bb8a00cf3b6d0b295a87c2fb8670afbeceb4427622bd38f248abfd3ed", + "path": "asset.708ad240e424cc18dd8b85017f9e1173ac983ddd3b387b9f4df3577ea60e4a65", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "55a6269bb8a00cf3b6d0b295a87c2fb8670afbeceb4427622bd38f248abfd3ed.zip", + "objectKey": "708ad240e424cc18dd8b85017f9e1173ac983ddd3b387b9f4df3577ea60e4a65.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "faed325694c61d70ce19c9e4425aaf59cd3478fd954936a51abe14daae853de3": { + "7444af4af0d237c9fc39ed1bcb1a601d3c2bf2fc1be3b14de2e94d38d8d1895a": { "source": { "path": "cdk-integ-lambda-function-project.template.json", "packaging": "file" @@ -35,7 +35,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "faed325694c61d70ce19c9e4425aaf59cd3478fd954936a51abe14daae853de3.json", + "objectKey": "7444af4af0d237c9fc39ed1bcb1a601d3c2bf2fc1be3b14de2e94d38d8d1895a.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/cdk-integ-lambda-function-project.template.json b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/cdk-integ-lambda-function-project.template.json index 4d33cd269a11c..0fe267774286a 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/cdk-integ-lambda-function-project.template.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/cdk-integ-lambda-function-project.template.json @@ -7,7 +7,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "f1eb849ae54216b1a7785bca3aa8031a4671eac68c1997e3b6a500336fd6d8fa.zip" + "S3Key": "33674c5088a855fbd87f051a085794b3bd1bd41823d88091874d5f4f1b8ad884.zip" }, "CompatibleRuntimes": [ "python3.9" @@ -52,7 +52,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "55a6269bb8a00cf3b6d0b295a87c2fb8670afbeceb4427622bd38f248abfd3ed.zip" + "S3Key": "708ad240e424cc18dd8b85017f9e1173ac983ddd3b387b9f4df3577ea60e4a65.zip" }, "Role": { "Fn::GetAtt": [ @@ -74,12 +74,12 @@ } }, "Outputs": { - "FunctionArn": { + "ExportsOutputRefmyhandlerD202FA8E369E8804": { "Value": { - "Fn::GetAtt": [ - "myhandlerD202FA8E", - "Arn" - ] + "Ref": "myhandlerD202FA8E" + }, + "Export": { + "Name": "cdk-integ-lambda-function-project:ExportsOutputRefmyhandlerD202FA8E369E8804" } } }, diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/cdk.out index 588d7b269d34f..8ecc185e9dbee 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/integ.json b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/integ.json index e554380361b1a..7c1dd35a87e06 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/integ.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/integ.json @@ -1,14 +1,13 @@ { - "version": "20.0.0", + "version": "21.0.0", "testCases": { - "integ.function.project": { + "lambda-python-project/DefaultTest": { "stacks": [ "cdk-integ-lambda-function-project" ], - "diffAssets": false, - "stackUpdateWorkflow": false + "stackUpdateWorkflow": false, + "assertionStack": "lambda-python-project/DefaultTest/DeployAssert", + "assertionStackName": "lambdapythonprojectDefaultTestDeployAssert35F9254C" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/lambdapythonprojectDefaultTestDeployAssert35F9254C.assets.json b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/lambdapythonprojectDefaultTestDeployAssert35F9254C.assets.json new file mode 100644 index 0000000000000..8ab3539edcbc7 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/lambdapythonprojectDefaultTestDeployAssert35F9254C.assets.json @@ -0,0 +1,32 @@ +{ + "version": "21.0.0", + "files": { + "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7": { + "source": { + "path": "asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "ea5d18a1dfe899a7d6663515813ddbaac0be15837184d8e091c140a5f9a3b5a7": { + "source": { + "path": "lambdapythonprojectDefaultTestDeployAssert35F9254C.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "ea5d18a1dfe899a7d6663515813ddbaac0be15837184d8e091c140a5f9a3b5a7.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/lambdapythonprojectDefaultTestDeployAssert35F9254C.template.json b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/lambdapythonprojectDefaultTestDeployAssert35F9254C.template.json new file mode 100644 index 0000000000000..02657b219f069 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/lambdapythonprojectDefaultTestDeployAssert35F9254C.template.json @@ -0,0 +1,198 @@ +{ + "Resources": { + "LambdaInvoke431773224924ebf10c8a31d363a6bf16": { + "Type": "Custom::DeployAssert@SdkCallLambdainvoke", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "service": "Lambda", + "api": "invoke", + "parameters": { + "FunctionName": { + "Fn::ImportValue": "cdk-integ-lambda-function-project:ExportsOutputRefmyhandlerD202FA8E369E8804" + } + }, + "flattenResponse": "false", + "salt": "1662650651537" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "LambdaInvoke431773224924ebf10c8a31d363a6bf16Invoke9BC0E67F": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::ImportValue": "cdk-integ-lambda-function-project:ExportsOutputRefmyhandlerD202FA8E369E8804" + }, + "Principal": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + }, + "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B": { + "Type": "Custom::DeployAssert@AssertEquals", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "actual": { + "Fn::GetAtt": [ + "LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "apiCallResponse" + ] + }, + "expected": "{\"$ObjectLike\":{\"Payload\":\"200\"}}", + "salt": "1662650651538" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "lambda:Invoke" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":lambda:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":function:", + { + "Fn::ImportValue": "cdk-integ-lambda-function-project:ExportsOutputRefmyhandlerD202FA8E369E8804" + } + ] + ] + } + ] + } + ] + } + } + ] + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Runtime": "nodejs14.x", + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip" + }, + "Timeout": 120, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + } + }, + "Outputs": { + "AssertionResultsAssertEqualsLambdainvokeb3d9316f0fb548427dcfcc9cb47a7866": { + "Value": { + "Fn::GetAtt": [ + "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B", + "data" + ] + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/manifest.json index 65ed3c511fa98..7498f14bf2395 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "21.0.0", "artifacts": { "Tree": { "type": "cdk:tree", @@ -23,7 +23,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/faed325694c61d70ce19c9e4425aaf59cd3478fd954936a51abe14daae853de3.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/7444af4af0d237c9fc39ed1bcb1a601d3c2bf2fc1be3b14de2e94d38d8d1895a.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -42,10 +42,7 @@ "/cdk-integ-lambda-function-project/Shared/Resource": [ { "type": "aws:cdk:logicalId", - "data": "SharedDACC02AA", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "SharedDACC02AA" } ], "/cdk-integ-lambda-function-project/my_handler/ServiceRole/Resource": [ @@ -60,10 +57,10 @@ "data": "myhandlerD202FA8E" } ], - "/cdk-integ-lambda-function-project/FunctionArn": [ + "/cdk-integ-lambda-function-project/Exports/Output{\"Ref\":\"myhandlerD202FA8E\"}": [ { "type": "aws:cdk:logicalId", - "data": "FunctionArn" + "data": "ExportsOutputRefmyhandlerD202FA8E369E8804" } ], "/cdk-integ-lambda-function-project/BootstrapVersion": [ @@ -80,6 +77,90 @@ ] }, "displayName": "cdk-integ-lambda-function-project" + }, + "lambdapythonprojectDefaultTestDeployAssert35F9254C.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "lambdapythonprojectDefaultTestDeployAssert35F9254C.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "lambdapythonprojectDefaultTestDeployAssert35F9254C": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "lambdapythonprojectDefaultTestDeployAssert35F9254C.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/ea5d18a1dfe899a7d6663515813ddbaac0be15837184d8e091c140a5f9a3b5a7.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "lambdapythonprojectDefaultTestDeployAssert35F9254C.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "cdk-integ-lambda-function-project", + "lambdapythonprojectDefaultTestDeployAssert35F9254C.assets" + ], + "metadata": { + "/lambda-python-project/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16" + } + ], + "/lambda-python-project/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Invoke": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16Invoke9BC0E67F" + } + ], + "/lambda-python-project/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B" + } + ], + "/lambda-python-project/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionResults": [ + { + "type": "aws:cdk:logicalId", + "data": "AssertionResultsAssertEqualsLambdainvokeb3d9316f0fb548427dcfcc9cb47a7866" + } + ], + "/lambda-python-project/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73" + } + ], + "/lambda-python-project/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F" + } + ], + "/lambda-python-project/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/lambda-python-project/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "lambda-python-project/DefaultTest/DeployAssert" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/tree.json b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/tree.json index 6574b1a011588..7bee60621ae5c 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.project.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } }, "cdk-integ-lambda-function-project": { @@ -28,8 +28,8 @@ "id": "Stage", "path": "cdk-integ-lambda-function-project/Shared/Code/Stage", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "AssetBucket": { @@ -56,7 +56,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "f1eb849ae54216b1a7785bca3aa8031a4671eac68c1997e3b6a500336fd6d8fa.zip" + "s3Key": "33674c5088a855fbd87f051a085794b3bd1bd41823d88091874d5f4f1b8ad884.zip" }, "compatibleRuntimes": [ "python3.9" @@ -135,8 +135,8 @@ "id": "Stage", "path": "cdk-integ-lambda-function-project/my_handler/Code/Stage", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "AssetBucket": { @@ -163,7 +163,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "55a6269bb8a00cf3b6d0b295a87c2fb8670afbeceb4427622bd38f248abfd3ed.zip" + "s3Key": "708ad240e424cc18dd8b85017f9e1173ac983ddd3b387b9f4df3577ea60e4a65.zip" }, "role": { "Fn::GetAtt": [ @@ -191,24 +191,214 @@ "version": "0.0.0" } }, - "FunctionArn": { - "id": "FunctionArn", - "path": "cdk-integ-lambda-function-project/FunctionArn", + "Exports": { + "id": "Exports", + "path": "cdk-integ-lambda-function-project/Exports", + "children": { + "Output{\"Ref\":\"myhandlerD202FA8E\"}": { + "id": "Output{\"Ref\":\"myhandlerD202FA8E\"}", + "path": "cdk-integ-lambda-function-project/Exports/Output{\"Ref\":\"myhandlerD202FA8E\"}", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "lambda-python-project": { + "id": "lambda-python-project", + "path": "lambda-python-project", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "lambda-python-project/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "lambda-python-project/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "lambda-python-project/DefaultTest/DeployAssert", + "children": { + "LambdaInvoke431773224924ebf10c8a31d363a6bf16": { + "id": "LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "path": "lambda-python-project/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "children": { + "SdkProvider": { + "id": "SdkProvider", + "path": "lambda-python-project/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/SdkProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "lambda-python-project/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/SdkProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.AssertionsProvider", + "version": "0.0.0" + } + }, + "Default": { + "id": "Default", + "path": "lambda-python-project/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default", + "children": { + "Default": { + "id": "Default", + "path": "lambda-python-project/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "Invoke": { + "id": "Invoke", + "path": "lambda-python-project/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Invoke", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "AssertEqualsLambdainvoke": { + "id": "AssertEqualsLambdainvoke", + "path": "lambda-python-project/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke", + "children": { + "AssertionProvider": { + "id": "AssertionProvider", + "path": "lambda-python-project/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "lambda-python-project/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.AssertionsProvider", + "version": "0.0.0" + } + }, + "Default": { + "id": "Default", + "path": "lambda-python-project/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default", + "children": { + "Default": { + "id": "Default", + "path": "lambda-python-project/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "AssertionResults": { + "id": "AssertionResults", + "path": "lambda-python-project/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionResults", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.EqualsAssertion", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.LambdaInvokeFunction", + "version": "0.0.0" + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81": { + "id": "SingletonFunction1488541a7b23466481b69b4408076b81", + "path": "lambda-python-project/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81", + "children": { + "Staging": { + "id": "Staging", + "path": "lambda-python-project/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Staging", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "lambda-python-project/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "lambda-python-project/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js new file mode 100644 index 0000000000000..ba956d47f51fe --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js @@ -0,0 +1,612 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// lib/assertions/providers/lambda-handler/index.ts +var lambda_handler_exports = {}; +__export(lambda_handler_exports, { + handler: () => handler +}); +module.exports = __toCommonJS(lambda_handler_exports); + +// ../assertions/lib/matcher.ts +var Matcher = class { + static isMatcher(x) { + return x && x instanceof Matcher; + } +}; +var MatchResult = class { + constructor(target) { + this.failures = []; + this.captures = /* @__PURE__ */ new Map(); + this.finalized = false; + this.target = target; + } + push(matcher, path, message) { + return this.recordFailure({ matcher, path, message }); + } + recordFailure(failure) { + this.failures.push(failure); + return this; + } + hasFailed() { + return this.failures.length !== 0; + } + get failCount() { + return this.failures.length; + } + compose(id, inner) { + const innerF = inner.failures; + this.failures.push(...innerF.map((f) => { + return { path: [id, ...f.path], message: f.message, matcher: f.matcher }; + })); + inner.captures.forEach((vals, capture) => { + vals.forEach((value) => this.recordCapture({ capture, value })); + }); + return this; + } + finished() { + if (this.finalized) { + return this; + } + if (this.failCount === 0) { + this.captures.forEach((vals, cap) => cap._captured.push(...vals)); + } + this.finalized = true; + return this; + } + toHumanStrings() { + return this.failures.map((r) => { + const loc = r.path.length === 0 ? "" : ` at ${r.path.join("")}`; + return "" + r.message + loc + ` (using ${r.matcher.name} matcher)`; + }); + } + recordCapture(options) { + let values = this.captures.get(options.capture); + if (values === void 0) { + values = []; + } + values.push(options.value); + this.captures.set(options.capture, values); + } +}; + +// ../assertions/lib/private/matchers/absent.ts +var AbsentMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual !== void 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Received ${actual}, but key should be absent` + }); + } + return result; + } +}; + +// ../assertions/lib/private/type.ts +function getType(obj) { + return Array.isArray(obj) ? "array" : typeof obj; +} + +// ../assertions/lib/match.ts +var Match = class { + static absent() { + return new AbsentMatch("absent"); + } + static arrayWith(pattern) { + return new ArrayMatch("arrayWith", pattern); + } + static arrayEquals(pattern) { + return new ArrayMatch("arrayEquals", pattern, { subsequence: false }); + } + static exact(pattern) { + return new LiteralMatch("exact", pattern, { partialObjects: false }); + } + static objectLike(pattern) { + return new ObjectMatch("objectLike", pattern); + } + static objectEquals(pattern) { + return new ObjectMatch("objectEquals", pattern, { partial: false }); + } + static not(pattern) { + return new NotMatch("not", pattern); + } + static serializedJson(pattern) { + return new SerializedJson("serializedJson", pattern); + } + static anyValue() { + return new AnyMatch("anyValue"); + } + static stringLikeRegexp(pattern) { + return new StringLikeRegexpMatch("stringLikeRegexp", pattern); + } +}; +var LiteralMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partialObjects = options.partialObjects ?? false; + if (Matcher.isMatcher(this.pattern)) { + throw new Error("LiteralMatch cannot directly contain another matcher. Remove the top-level matcher or nest it more deeply."); + } + } + test(actual) { + if (Array.isArray(this.pattern)) { + return new ArrayMatch(this.name, this.pattern, { subsequence: false, partialObjects: this.partialObjects }).test(actual); + } + if (typeof this.pattern === "object") { + return new ObjectMatch(this.name, this.pattern, { partial: this.partialObjects }).test(actual); + } + const result = new MatchResult(actual); + if (typeof this.pattern !== typeof actual) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected type ${typeof this.pattern} but received ${getType(actual)}` + }); + return result; + } + if (actual !== this.pattern) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected ${this.pattern} but received ${actual}` + }); + } + return result; + } +}; +var ArrayMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.subsequence = options.subsequence ?? true; + this.partialObjects = options.partialObjects ?? false; + } + test(actual) { + if (!Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type array but received ${getType(actual)}` + }); + } + if (!this.subsequence && this.pattern.length !== actual.length) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected array of length ${this.pattern.length} but received ${actual.length}` + }); + } + let patternIdx = 0; + let actualIdx = 0; + const result = new MatchResult(actual); + while (patternIdx < this.pattern.length && actualIdx < actual.length) { + const patternElement = this.pattern[patternIdx]; + const matcher = Matcher.isMatcher(patternElement) ? patternElement : new LiteralMatch(this.name, patternElement, { partialObjects: this.partialObjects }); + const matcherName = matcher.name; + if (this.subsequence && (matcherName == "absent" || matcherName == "anyValue")) { + throw new Error(`The Matcher ${matcherName}() cannot be nested within arrayWith()`); + } + const innerResult = matcher.test(actual[actualIdx]); + if (!this.subsequence || !innerResult.hasFailed()) { + result.compose(`[${actualIdx}]`, innerResult); + patternIdx++; + actualIdx++; + } else { + actualIdx++; + } + } + for (; patternIdx < this.pattern.length; patternIdx++) { + const pattern = this.pattern[patternIdx]; + const element = Matcher.isMatcher(pattern) || typeof pattern === "object" ? " " : ` [${pattern}] `; + result.recordFailure({ + matcher: this, + path: [], + message: `Missing element${element}at pattern index ${patternIdx}` + }); + } + return result; + } +}; +var ObjectMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partial = options.partial ?? true; + } + test(actual) { + if (typeof actual !== "object" || Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type object but received ${getType(actual)}` + }); + } + const result = new MatchResult(actual); + if (!this.partial) { + for (const a of Object.keys(actual)) { + if (!(a in this.pattern)) { + result.recordFailure({ + matcher: this, + path: [`/${a}`], + message: "Unexpected key" + }); + } + } + } + for (const [patternKey, patternVal] of Object.entries(this.pattern)) { + if (!(patternKey in actual) && !(patternVal instanceof AbsentMatch)) { + result.recordFailure({ + matcher: this, + path: [`/${patternKey}`], + message: `Missing key '${patternKey}' among {${Object.keys(actual).join(",")}}` + }); + continue; + } + const matcher = Matcher.isMatcher(patternVal) ? patternVal : new LiteralMatch(this.name, patternVal, { partialObjects: this.partial }); + const inner = matcher.test(actual[patternKey]); + result.compose(`/${patternKey}`, inner); + } + return result; + } +}; +var SerializedJson = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + if (getType(actual) !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected JSON as a string but found ${getType(actual)}` + }); + return result; + } + let parsed; + try { + parsed = JSON.parse(actual); + } catch (err) { + if (err instanceof SyntaxError) { + result.recordFailure({ + matcher: this, + path: [], + message: `Invalid JSON string: ${actual}` + }); + return result; + } else { + throw err; + } + } + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(parsed); + result.compose(`(${this.name})`, innerResult); + return result; + } +}; +var NotMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(actual); + const result = new MatchResult(actual); + if (innerResult.failCount === 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Found unexpected match: ${JSON.stringify(actual, void 0, 2)}` + }); + } + return result; + } +}; +var AnyMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual == null) { + result.recordFailure({ + matcher: this, + path: [], + message: "Expected a value but found none" + }); + } + return result; + } +}; +var StringLikeRegexpMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + const regex = new RegExp(this.pattern, "gm"); + if (typeof actual !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected a string, but got '${typeof actual}'` + }); + } + if (!regex.test(actual)) { + result.recordFailure({ + matcher: this, + path: [], + message: `String '${actual}' did not match pattern '${this.pattern}'` + }); + } + return result; + } +}; + +// lib/assertions/providers/lambda-handler/base.ts +var https = __toESM(require("https")); +var url = __toESM(require("url")); +var CustomResourceHandler = class { + constructor(event, context) { + this.event = event; + this.context = context; + this.timedOut = false; + this.timeout = setTimeout(async () => { + await this.respond({ + status: "FAILED", + reason: "Lambda Function Timeout", + data: this.context.logStreamName + }); + this.timedOut = true; + }, context.getRemainingTimeInMillis() - 1200); + this.event = event; + this.physicalResourceId = extractPhysicalResourceId(event); + } + async handle() { + try { + console.log(`Event: ${JSON.stringify({ ...this.event, ResponseURL: "..." })}`); + const response = await this.processEvent(this.event.ResourceProperties); + console.log(`Event output : ${JSON.stringify(response)}`); + await this.respond({ + status: "SUCCESS", + reason: "OK", + data: response + }); + } catch (e) { + console.log(e); + await this.respond({ + status: "FAILED", + reason: e.message ?? "Internal Error" + }); + } finally { + clearTimeout(this.timeout); + } + } + respond(response) { + if (this.timedOut) { + return; + } + const cfResponse = { + Status: response.status, + Reason: response.reason, + PhysicalResourceId: this.physicalResourceId, + StackId: this.event.StackId, + RequestId: this.event.RequestId, + LogicalResourceId: this.event.LogicalResourceId, + NoEcho: false, + Data: response.data + }; + const responseBody = JSON.stringify(cfResponse); + console.log("Responding to CloudFormation", responseBody); + const parsedUrl = url.parse(this.event.ResponseURL); + const requestOptions = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: "PUT", + headers: { "content-type": "", "content-length": responseBody.length } + }; + return new Promise((resolve, reject) => { + try { + const request2 = https.request(requestOptions, resolve); + request2.on("error", reject); + request2.write(responseBody); + request2.end(); + } catch (e) { + reject(e); + } + }); + } +}; +function extractPhysicalResourceId(event) { + switch (event.RequestType) { + case "Create": + return event.LogicalResourceId; + case "Update": + case "Delete": + return event.PhysicalResourceId; + } +} + +// lib/assertions/providers/lambda-handler/assertion.ts +var AssertionHandler = class extends CustomResourceHandler { + async processEvent(request2) { + let actual = decodeCall(request2.actual); + const expected = decodeCall(request2.expected); + let result; + const matcher = new MatchCreator(expected).getMatcher(); + console.log(`Testing equality between ${JSON.stringify(request2.actual)} and ${JSON.stringify(request2.expected)}`); + const matchResult = matcher.test(actual); + matchResult.finished(); + if (matchResult.hasFailed()) { + result = { + data: JSON.stringify({ + status: "fail", + message: [ + ...matchResult.toHumanStrings(), + JSON.stringify(matchResult.target, void 0, 2) + ].join("\n") + }) + }; + if (request2.failDeployment) { + throw new Error(result.data); + } + } else { + result = { + data: JSON.stringify({ + status: "success" + }) + }; + } + return result; + } +}; +var MatchCreator = class { + constructor(obj) { + this.parsedObj = { + matcher: obj + }; + } + getMatcher() { + try { + const final = JSON.parse(JSON.stringify(this.parsedObj), function(_k, v) { + const nested = Object.keys(v)[0]; + switch (nested) { + case "$ArrayWith": + return Match.arrayWith(v[nested]); + case "$ObjectLike": + return Match.objectLike(v[nested]); + case "$StringLike": + return Match.stringLikeRegexp(v[nested]); + default: + return v; + } + }); + if (Matcher.isMatcher(final.matcher)) { + return final.matcher; + } + return Match.exact(final.matcher); + } catch { + return Match.exact(this.parsedObj.matcher); + } + } +}; +function decodeCall(call) { + if (!call) { + return void 0; + } + try { + const parsed = JSON.parse(call); + return parsed; + } catch (e) { + return call; + } +} + +// lib/assertions/providers/lambda-handler/utils.ts +function decode(object) { + return JSON.parse(JSON.stringify(object), (_k, v) => { + switch (v) { + case "TRUE:BOOLEAN": + return true; + case "FALSE:BOOLEAN": + return false; + default: + return v; + } + }); +} + +// lib/assertions/providers/lambda-handler/sdk.ts +function flatten(object) { + return Object.assign( + {}, + ...function _flatten(child, path = []) { + return [].concat(...Object.keys(child).map((key) => { + const childKey = Buffer.isBuffer(child[key]) ? child[key].toString("utf8") : child[key]; + return typeof childKey === "object" && childKey !== null ? _flatten(childKey, path.concat([key])) : { [path.concat([key]).join(".")]: childKey }; + })); + }(object) + ); +} +var AwsApiCallHandler = class extends CustomResourceHandler { + async processEvent(request2) { + const AWS = require("aws-sdk"); + console.log(`AWS SDK VERSION: ${AWS.VERSION}`); + const service = new AWS[request2.service](); + const response = await service[request2.api](request2.parameters && decode(request2.parameters)).promise(); + console.log(`SDK response received ${JSON.stringify(response)}`); + delete response.ResponseMetadata; + const respond = { + apiCallResponse: response + }; + const flatData = { + ...flatten(respond) + }; + return request2.flattenResponse === "true" ? flatData : respond; + } +}; + +// lib/assertions/providers/lambda-handler/types.ts +var ASSERT_RESOURCE_TYPE = "Custom::DeployAssert@AssertEquals"; +var SDK_RESOURCE_TYPE_PREFIX = "Custom::DeployAssert@SdkCall"; + +// lib/assertions/providers/lambda-handler/index.ts +async function handler(event, context) { + const provider = createResourceHandler(event, context); + await provider.handle(); +} +function createResourceHandler(event, context) { + if (event.ResourceType.startsWith(SDK_RESOURCE_TYPE_PREFIX)) { + return new AwsApiCallHandler(event, context); + } + switch (event.ResourceType) { + case ASSERT_RESOURCE_TYPE: + return new AssertionHandler(event, context); + default: + throw new Error(`Unsupported resource type "${event.ResourceType}`); + } +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + handler +}); diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/asset.e3d888d855ebd2b6173af510e2eba9e1542084655559f4bb05adbb2e6ca63b73/index.py b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/asset.e3d888d855ebd2b6173af510e2eba9e1542084655559f4bb05adbb2e6ca63b73/index.py deleted file mode 100644 index 04f99eb108b30..0000000000000 --- a/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/asset.e3d888d855ebd2b6173af510e2eba9e1542084655559f4bb05adbb2e6ca63b73/index.py +++ /dev/null @@ -1,8 +0,0 @@ -import requests - -def handler(event, context): - response = requests.get('https://a0.awsstatic.com/main/images/logos/aws_smile-header-desktop-en-white_59x35.png', stream=True) - - print(response.status_code) - - return response.status_code diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/asset.e3d888d855ebd2b6173af510e2eba9e1542084655559f4bb05adbb2e6ca63b73/requirements.txt b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/asset.e3d888d855ebd2b6173af510e2eba9e1542084655559f4bb05adbb2e6ca63b73/requirements.txt deleted file mode 100644 index 4fcd85719fe3a..0000000000000 --- a/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/asset.e3d888d855ebd2b6173af510e2eba9e1542084655559f4bb05adbb2e6ca63b73/requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -# Lock versions of pip packages -certifi==2020.6.20 -chardet==3.0.4 -idna==2.10 -urllib3==1.26.7 -# Requests used by this lambda -requests==2.26.0 diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/cdk-integ-lambda-python-38.assets.json b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/cdk-integ-lambda-python-38.assets.json index c4286a0556e95..4b8d12c7c31ae 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/cdk-integ-lambda-python-38.assets.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/cdk-integ-lambda-python-38.assets.json @@ -1,20 +1,20 @@ { - "version": "20.0.0", + "version": "21.0.0", "files": { - "a4b6626caa13d8b9bdd848a73402d0d6359d26541692aa37347f2e8d3a11bee0": { + "bbaaba57f949375edc8d6f111608aacbd9aed02c8e33d0ad355375461590948b": { "source": { - "path": "asset.a4b6626caa13d8b9bdd848a73402d0d6359d26541692aa37347f2e8d3a11bee0", + "path": "asset.bbaaba57f949375edc8d6f111608aacbd9aed02c8e33d0ad355375461590948b", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "a4b6626caa13d8b9bdd848a73402d0d6359d26541692aa37347f2e8d3a11bee0.zip", + "objectKey": "bbaaba57f949375edc8d6f111608aacbd9aed02c8e33d0ad355375461590948b.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "d6ffbf3ee613bc8f0ca6cd812d528f166a0f706ff538a0eb33908bf02ef7dff3": { + "20b8f61550e4055a7b76b72e1f7d47451dff1959235b6b4425a74fc910cc2c4f": { "source": { "path": "cdk-integ-lambda-python-38.template.json", "packaging": "file" @@ -22,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "d6ffbf3ee613bc8f0ca6cd812d528f166a0f706ff538a0eb33908bf02ef7dff3.json", + "objectKey": "20b8f61550e4055a7b76b72e1f7d47451dff1959235b6b4425a74fc910cc2c4f.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/cdk-integ-lambda-python-38.template.json b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/cdk-integ-lambda-python-38.template.json index a3c934e9d0aea..15e04b05e373a 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/cdk-integ-lambda-python-38.template.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/cdk-integ-lambda-python-38.template.json @@ -38,7 +38,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "a4b6626caa13d8b9bdd848a73402d0d6359d26541692aa37347f2e8d3a11bee0.zip" + "S3Key": "bbaaba57f949375edc8d6f111608aacbd9aed02c8e33d0ad355375461590948b.zip" }, "Role": { "Fn::GetAtt": [ @@ -62,6 +62,14 @@ "Arn" ] } + }, + "ExportsOutputRefmyhandlerD202FA8E369E8804": { + "Value": { + "Ref": "myhandlerD202FA8E" + }, + "Export": { + "Name": "cdk-integ-lambda-python-38:ExportsOutputRefmyhandlerD202FA8E369E8804" + } } }, "Parameters": { diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/cdk.out index 588d7b269d34f..8ecc185e9dbee 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/integ.json b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/integ.json index 53257f01c1b6f..6d3655058dd24 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/integ.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/integ.json @@ -1,14 +1,13 @@ { - "version": "20.0.0", + "version": "21.0.0", "testCases": { - "integ.function.py38": { + "lambda-python-38/DefaultTest": { "stacks": [ "cdk-integ-lambda-python-38" ], - "diffAssets": false, - "stackUpdateWorkflow": false + "stackUpdateWorkflow": false, + "assertionStack": "lambda-python-38/DefaultTest/DeployAssert", + "assertionStackName": "lambdapython38DefaultTestDeployAssertDDBFEEAF" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/lambdapython38DefaultTestDeployAssertDDBFEEAF.assets.json b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/lambdapython38DefaultTestDeployAssertDDBFEEAF.assets.json new file mode 100644 index 0000000000000..8a194561ee133 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/lambdapython38DefaultTestDeployAssertDDBFEEAF.assets.json @@ -0,0 +1,32 @@ +{ + "version": "21.0.0", + "files": { + "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7": { + "source": { + "path": "asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "1e709498a8f74a83d4737886ebbfe372fdddc55f4aa1843685f587a6b594c6be": { + "source": { + "path": "lambdapython38DefaultTestDeployAssertDDBFEEAF.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "1e709498a8f74a83d4737886ebbfe372fdddc55f4aa1843685f587a6b594c6be.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/lambdapython38DefaultTestDeployAssertDDBFEEAF.template.json b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/lambdapython38DefaultTestDeployAssertDDBFEEAF.template.json new file mode 100644 index 0000000000000..79870b2d95ef9 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/lambdapython38DefaultTestDeployAssertDDBFEEAF.template.json @@ -0,0 +1,198 @@ +{ + "Resources": { + "LambdaInvoke431773224924ebf10c8a31d363a6bf16": { + "Type": "Custom::DeployAssert@SdkCallLambdainvoke", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "service": "Lambda", + "api": "invoke", + "parameters": { + "FunctionName": { + "Fn::ImportValue": "cdk-integ-lambda-python-38:ExportsOutputRefmyhandlerD202FA8E369E8804" + } + }, + "flattenResponse": "false", + "salt": "1662643640442" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "LambdaInvoke431773224924ebf10c8a31d363a6bf16Invoke9BC0E67F": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::ImportValue": "cdk-integ-lambda-python-38:ExportsOutputRefmyhandlerD202FA8E369E8804" + }, + "Principal": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + }, + "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B": { + "Type": "Custom::DeployAssert@AssertEquals", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "actual": { + "Fn::GetAtt": [ + "LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "apiCallResponse" + ] + }, + "expected": "{\"$ObjectLike\":{\"Payload\":\"200\"}}", + "salt": "1662643640443" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "lambda:Invoke" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":lambda:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":function:", + { + "Fn::ImportValue": "cdk-integ-lambda-python-38:ExportsOutputRefmyhandlerD202FA8E369E8804" + } + ] + ] + } + ] + } + ] + } + } + ] + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Runtime": "nodejs14.x", + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip" + }, + "Timeout": 120, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + } + }, + "Outputs": { + "AssertionResultsAssertEqualsLambdainvoke602537204bd4bab1eecafd00eb20f462": { + "Value": { + "Fn::GetAtt": [ + "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B", + "data" + ] + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/manifest.json index b2a5c34508ac8..2992875b68650 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "21.0.0", "artifacts": { "Tree": { "type": "cdk:tree", @@ -23,7 +23,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/d6ffbf3ee613bc8f0ca6cd812d528f166a0f706ff538a0eb33908bf02ef7dff3.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/20b8f61550e4055a7b76b72e1f7d47451dff1959235b6b4425a74fc910cc2c4f.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -57,6 +57,12 @@ "data": "FunctionArn" } ], + "/cdk-integ-lambda-python-38/Exports/Output{\"Ref\":\"myhandlerD202FA8E\"}": [ + { + "type": "aws:cdk:logicalId", + "data": "ExportsOutputRefmyhandlerD202FA8E369E8804" + } + ], "/cdk-integ-lambda-python-38/BootstrapVersion": [ { "type": "aws:cdk:logicalId", @@ -71,6 +77,90 @@ ] }, "displayName": "cdk-integ-lambda-python-38" + }, + "lambdapython38DefaultTestDeployAssertDDBFEEAF.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "lambdapython38DefaultTestDeployAssertDDBFEEAF.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "lambdapython38DefaultTestDeployAssertDDBFEEAF": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "lambdapython38DefaultTestDeployAssertDDBFEEAF.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/1e709498a8f74a83d4737886ebbfe372fdddc55f4aa1843685f587a6b594c6be.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "lambdapython38DefaultTestDeployAssertDDBFEEAF.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "cdk-integ-lambda-python-38", + "lambdapython38DefaultTestDeployAssertDDBFEEAF.assets" + ], + "metadata": { + "/lambda-python-38/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16" + } + ], + "/lambda-python-38/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Invoke": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16Invoke9BC0E67F" + } + ], + "/lambda-python-38/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B" + } + ], + "/lambda-python-38/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionResults": [ + { + "type": "aws:cdk:logicalId", + "data": "AssertionResultsAssertEqualsLambdainvoke602537204bd4bab1eecafd00eb20f462" + } + ], + "/lambda-python-38/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73" + } + ], + "/lambda-python-38/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F" + } + ], + "/lambda-python-38/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/lambda-python-38/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "lambda-python-38/DefaultTest/DeployAssert" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/tree.json b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/tree.json index ac0e0921c71e9..25223dbbbdcc9 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.py38.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } }, "cdk-integ-lambda-python-38": { @@ -77,8 +77,8 @@ "id": "Stage", "path": "cdk-integ-lambda-python-38/my_handler/Code/Stage", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "AssetBucket": { @@ -105,7 +105,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "a4b6626caa13d8b9bdd848a73402d0d6359d26541692aa37347f2e8d3a11bee0.zip" + "s3Key": "bbaaba57f949375edc8d6f111608aacbd9aed02c8e33d0ad355375461590948b.zip" }, "role": { "Fn::GetAtt": [ @@ -131,21 +131,219 @@ "FunctionArn": { "id": "FunctionArn", "path": "cdk-integ-lambda-python-38/FunctionArn", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "Exports": { + "id": "Exports", + "path": "cdk-integ-lambda-python-38/Exports", + "children": { + "Output{\"Ref\":\"myhandlerD202FA8E\"}": { + "id": "Output{\"Ref\":\"myhandlerD202FA8E\"}", + "path": "cdk-integ-lambda-python-38/Exports/Output{\"Ref\":\"myhandlerD202FA8E\"}", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "lambda-python-38": { + "id": "lambda-python-38", + "path": "lambda-python-38", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "lambda-python-38/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "lambda-python-38/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "lambda-python-38/DefaultTest/DeployAssert", + "children": { + "LambdaInvoke431773224924ebf10c8a31d363a6bf16": { + "id": "LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "path": "lambda-python-38/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "children": { + "SdkProvider": { + "id": "SdkProvider", + "path": "lambda-python-38/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/SdkProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "lambda-python-38/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/SdkProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "Default": { + "id": "Default", + "path": "lambda-python-38/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default", + "children": { + "Default": { + "id": "Default", + "path": "lambda-python-38/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "Invoke": { + "id": "Invoke", + "path": "lambda-python-38/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Invoke", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "AssertEqualsLambdainvoke": { + "id": "AssertEqualsLambdainvoke", + "path": "lambda-python-38/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke", + "children": { + "AssertionProvider": { + "id": "AssertionProvider", + "path": "lambda-python-38/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "lambda-python-38/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "Default": { + "id": "Default", + "path": "lambda-python-38/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default", + "children": { + "Default": { + "id": "Default", + "path": "lambda-python-38/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "AssertionResults": { + "id": "AssertionResults", + "path": "lambda-python-38/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionResults", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81": { + "id": "SingletonFunction1488541a7b23466481b69b4408076b81", + "path": "lambda-python-38/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81", + "children": { + "Staging": { + "id": "Staging", + "path": "lambda-python-38/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Staging", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "lambda-python-38/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "lambda-python-38/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/asset.35995f8d8e738c0883e84fd6711175c4c488f2f2bc854d464bbda64ce097e1ab/inner/custom_index.py b/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/asset.35995f8d8e738c0883e84fd6711175c4c488f2f2bc854d464bbda64ce097e1ab/inner/custom_index.py deleted file mode 100644 index d7b2ce8db00e9..0000000000000 --- a/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/asset.35995f8d8e738c0883e84fd6711175c4c488f2f2bc854d464bbda64ce097e1ab/inner/custom_index.py +++ /dev/null @@ -1,5 +0,0 @@ -from http import HTTPStatus - -def handler(event, context): - print('No dependencies') - return HTTPStatus.OK.value diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js b/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js new file mode 100644 index 0000000000000..ba956d47f51fe --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js @@ -0,0 +1,612 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// lib/assertions/providers/lambda-handler/index.ts +var lambda_handler_exports = {}; +__export(lambda_handler_exports, { + handler: () => handler +}); +module.exports = __toCommonJS(lambda_handler_exports); + +// ../assertions/lib/matcher.ts +var Matcher = class { + static isMatcher(x) { + return x && x instanceof Matcher; + } +}; +var MatchResult = class { + constructor(target) { + this.failures = []; + this.captures = /* @__PURE__ */ new Map(); + this.finalized = false; + this.target = target; + } + push(matcher, path, message) { + return this.recordFailure({ matcher, path, message }); + } + recordFailure(failure) { + this.failures.push(failure); + return this; + } + hasFailed() { + return this.failures.length !== 0; + } + get failCount() { + return this.failures.length; + } + compose(id, inner) { + const innerF = inner.failures; + this.failures.push(...innerF.map((f) => { + return { path: [id, ...f.path], message: f.message, matcher: f.matcher }; + })); + inner.captures.forEach((vals, capture) => { + vals.forEach((value) => this.recordCapture({ capture, value })); + }); + return this; + } + finished() { + if (this.finalized) { + return this; + } + if (this.failCount === 0) { + this.captures.forEach((vals, cap) => cap._captured.push(...vals)); + } + this.finalized = true; + return this; + } + toHumanStrings() { + return this.failures.map((r) => { + const loc = r.path.length === 0 ? "" : ` at ${r.path.join("")}`; + return "" + r.message + loc + ` (using ${r.matcher.name} matcher)`; + }); + } + recordCapture(options) { + let values = this.captures.get(options.capture); + if (values === void 0) { + values = []; + } + values.push(options.value); + this.captures.set(options.capture, values); + } +}; + +// ../assertions/lib/private/matchers/absent.ts +var AbsentMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual !== void 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Received ${actual}, but key should be absent` + }); + } + return result; + } +}; + +// ../assertions/lib/private/type.ts +function getType(obj) { + return Array.isArray(obj) ? "array" : typeof obj; +} + +// ../assertions/lib/match.ts +var Match = class { + static absent() { + return new AbsentMatch("absent"); + } + static arrayWith(pattern) { + return new ArrayMatch("arrayWith", pattern); + } + static arrayEquals(pattern) { + return new ArrayMatch("arrayEquals", pattern, { subsequence: false }); + } + static exact(pattern) { + return new LiteralMatch("exact", pattern, { partialObjects: false }); + } + static objectLike(pattern) { + return new ObjectMatch("objectLike", pattern); + } + static objectEquals(pattern) { + return new ObjectMatch("objectEquals", pattern, { partial: false }); + } + static not(pattern) { + return new NotMatch("not", pattern); + } + static serializedJson(pattern) { + return new SerializedJson("serializedJson", pattern); + } + static anyValue() { + return new AnyMatch("anyValue"); + } + static stringLikeRegexp(pattern) { + return new StringLikeRegexpMatch("stringLikeRegexp", pattern); + } +}; +var LiteralMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partialObjects = options.partialObjects ?? false; + if (Matcher.isMatcher(this.pattern)) { + throw new Error("LiteralMatch cannot directly contain another matcher. Remove the top-level matcher or nest it more deeply."); + } + } + test(actual) { + if (Array.isArray(this.pattern)) { + return new ArrayMatch(this.name, this.pattern, { subsequence: false, partialObjects: this.partialObjects }).test(actual); + } + if (typeof this.pattern === "object") { + return new ObjectMatch(this.name, this.pattern, { partial: this.partialObjects }).test(actual); + } + const result = new MatchResult(actual); + if (typeof this.pattern !== typeof actual) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected type ${typeof this.pattern} but received ${getType(actual)}` + }); + return result; + } + if (actual !== this.pattern) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected ${this.pattern} but received ${actual}` + }); + } + return result; + } +}; +var ArrayMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.subsequence = options.subsequence ?? true; + this.partialObjects = options.partialObjects ?? false; + } + test(actual) { + if (!Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type array but received ${getType(actual)}` + }); + } + if (!this.subsequence && this.pattern.length !== actual.length) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected array of length ${this.pattern.length} but received ${actual.length}` + }); + } + let patternIdx = 0; + let actualIdx = 0; + const result = new MatchResult(actual); + while (patternIdx < this.pattern.length && actualIdx < actual.length) { + const patternElement = this.pattern[patternIdx]; + const matcher = Matcher.isMatcher(patternElement) ? patternElement : new LiteralMatch(this.name, patternElement, { partialObjects: this.partialObjects }); + const matcherName = matcher.name; + if (this.subsequence && (matcherName == "absent" || matcherName == "anyValue")) { + throw new Error(`The Matcher ${matcherName}() cannot be nested within arrayWith()`); + } + const innerResult = matcher.test(actual[actualIdx]); + if (!this.subsequence || !innerResult.hasFailed()) { + result.compose(`[${actualIdx}]`, innerResult); + patternIdx++; + actualIdx++; + } else { + actualIdx++; + } + } + for (; patternIdx < this.pattern.length; patternIdx++) { + const pattern = this.pattern[patternIdx]; + const element = Matcher.isMatcher(pattern) || typeof pattern === "object" ? " " : ` [${pattern}] `; + result.recordFailure({ + matcher: this, + path: [], + message: `Missing element${element}at pattern index ${patternIdx}` + }); + } + return result; + } +}; +var ObjectMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partial = options.partial ?? true; + } + test(actual) { + if (typeof actual !== "object" || Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type object but received ${getType(actual)}` + }); + } + const result = new MatchResult(actual); + if (!this.partial) { + for (const a of Object.keys(actual)) { + if (!(a in this.pattern)) { + result.recordFailure({ + matcher: this, + path: [`/${a}`], + message: "Unexpected key" + }); + } + } + } + for (const [patternKey, patternVal] of Object.entries(this.pattern)) { + if (!(patternKey in actual) && !(patternVal instanceof AbsentMatch)) { + result.recordFailure({ + matcher: this, + path: [`/${patternKey}`], + message: `Missing key '${patternKey}' among {${Object.keys(actual).join(",")}}` + }); + continue; + } + const matcher = Matcher.isMatcher(patternVal) ? patternVal : new LiteralMatch(this.name, patternVal, { partialObjects: this.partial }); + const inner = matcher.test(actual[patternKey]); + result.compose(`/${patternKey}`, inner); + } + return result; + } +}; +var SerializedJson = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + if (getType(actual) !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected JSON as a string but found ${getType(actual)}` + }); + return result; + } + let parsed; + try { + parsed = JSON.parse(actual); + } catch (err) { + if (err instanceof SyntaxError) { + result.recordFailure({ + matcher: this, + path: [], + message: `Invalid JSON string: ${actual}` + }); + return result; + } else { + throw err; + } + } + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(parsed); + result.compose(`(${this.name})`, innerResult); + return result; + } +}; +var NotMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(actual); + const result = new MatchResult(actual); + if (innerResult.failCount === 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Found unexpected match: ${JSON.stringify(actual, void 0, 2)}` + }); + } + return result; + } +}; +var AnyMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual == null) { + result.recordFailure({ + matcher: this, + path: [], + message: "Expected a value but found none" + }); + } + return result; + } +}; +var StringLikeRegexpMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + const regex = new RegExp(this.pattern, "gm"); + if (typeof actual !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected a string, but got '${typeof actual}'` + }); + } + if (!regex.test(actual)) { + result.recordFailure({ + matcher: this, + path: [], + message: `String '${actual}' did not match pattern '${this.pattern}'` + }); + } + return result; + } +}; + +// lib/assertions/providers/lambda-handler/base.ts +var https = __toESM(require("https")); +var url = __toESM(require("url")); +var CustomResourceHandler = class { + constructor(event, context) { + this.event = event; + this.context = context; + this.timedOut = false; + this.timeout = setTimeout(async () => { + await this.respond({ + status: "FAILED", + reason: "Lambda Function Timeout", + data: this.context.logStreamName + }); + this.timedOut = true; + }, context.getRemainingTimeInMillis() - 1200); + this.event = event; + this.physicalResourceId = extractPhysicalResourceId(event); + } + async handle() { + try { + console.log(`Event: ${JSON.stringify({ ...this.event, ResponseURL: "..." })}`); + const response = await this.processEvent(this.event.ResourceProperties); + console.log(`Event output : ${JSON.stringify(response)}`); + await this.respond({ + status: "SUCCESS", + reason: "OK", + data: response + }); + } catch (e) { + console.log(e); + await this.respond({ + status: "FAILED", + reason: e.message ?? "Internal Error" + }); + } finally { + clearTimeout(this.timeout); + } + } + respond(response) { + if (this.timedOut) { + return; + } + const cfResponse = { + Status: response.status, + Reason: response.reason, + PhysicalResourceId: this.physicalResourceId, + StackId: this.event.StackId, + RequestId: this.event.RequestId, + LogicalResourceId: this.event.LogicalResourceId, + NoEcho: false, + Data: response.data + }; + const responseBody = JSON.stringify(cfResponse); + console.log("Responding to CloudFormation", responseBody); + const parsedUrl = url.parse(this.event.ResponseURL); + const requestOptions = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: "PUT", + headers: { "content-type": "", "content-length": responseBody.length } + }; + return new Promise((resolve, reject) => { + try { + const request2 = https.request(requestOptions, resolve); + request2.on("error", reject); + request2.write(responseBody); + request2.end(); + } catch (e) { + reject(e); + } + }); + } +}; +function extractPhysicalResourceId(event) { + switch (event.RequestType) { + case "Create": + return event.LogicalResourceId; + case "Update": + case "Delete": + return event.PhysicalResourceId; + } +} + +// lib/assertions/providers/lambda-handler/assertion.ts +var AssertionHandler = class extends CustomResourceHandler { + async processEvent(request2) { + let actual = decodeCall(request2.actual); + const expected = decodeCall(request2.expected); + let result; + const matcher = new MatchCreator(expected).getMatcher(); + console.log(`Testing equality between ${JSON.stringify(request2.actual)} and ${JSON.stringify(request2.expected)}`); + const matchResult = matcher.test(actual); + matchResult.finished(); + if (matchResult.hasFailed()) { + result = { + data: JSON.stringify({ + status: "fail", + message: [ + ...matchResult.toHumanStrings(), + JSON.stringify(matchResult.target, void 0, 2) + ].join("\n") + }) + }; + if (request2.failDeployment) { + throw new Error(result.data); + } + } else { + result = { + data: JSON.stringify({ + status: "success" + }) + }; + } + return result; + } +}; +var MatchCreator = class { + constructor(obj) { + this.parsedObj = { + matcher: obj + }; + } + getMatcher() { + try { + const final = JSON.parse(JSON.stringify(this.parsedObj), function(_k, v) { + const nested = Object.keys(v)[0]; + switch (nested) { + case "$ArrayWith": + return Match.arrayWith(v[nested]); + case "$ObjectLike": + return Match.objectLike(v[nested]); + case "$StringLike": + return Match.stringLikeRegexp(v[nested]); + default: + return v; + } + }); + if (Matcher.isMatcher(final.matcher)) { + return final.matcher; + } + return Match.exact(final.matcher); + } catch { + return Match.exact(this.parsedObj.matcher); + } + } +}; +function decodeCall(call) { + if (!call) { + return void 0; + } + try { + const parsed = JSON.parse(call); + return parsed; + } catch (e) { + return call; + } +} + +// lib/assertions/providers/lambda-handler/utils.ts +function decode(object) { + return JSON.parse(JSON.stringify(object), (_k, v) => { + switch (v) { + case "TRUE:BOOLEAN": + return true; + case "FALSE:BOOLEAN": + return false; + default: + return v; + } + }); +} + +// lib/assertions/providers/lambda-handler/sdk.ts +function flatten(object) { + return Object.assign( + {}, + ...function _flatten(child, path = []) { + return [].concat(...Object.keys(child).map((key) => { + const childKey = Buffer.isBuffer(child[key]) ? child[key].toString("utf8") : child[key]; + return typeof childKey === "object" && childKey !== null ? _flatten(childKey, path.concat([key])) : { [path.concat([key]).join(".")]: childKey }; + })); + }(object) + ); +} +var AwsApiCallHandler = class extends CustomResourceHandler { + async processEvent(request2) { + const AWS = require("aws-sdk"); + console.log(`AWS SDK VERSION: ${AWS.VERSION}`); + const service = new AWS[request2.service](); + const response = await service[request2.api](request2.parameters && decode(request2.parameters)).promise(); + console.log(`SDK response received ${JSON.stringify(response)}`); + delete response.ResponseMetadata; + const respond = { + apiCallResponse: response + }; + const flatData = { + ...flatten(respond) + }; + return request2.flattenResponse === "true" ? flatData : respond; + } +}; + +// lib/assertions/providers/lambda-handler/types.ts +var ASSERT_RESOURCE_TYPE = "Custom::DeployAssert@AssertEquals"; +var SDK_RESOURCE_TYPE_PREFIX = "Custom::DeployAssert@SdkCall"; + +// lib/assertions/providers/lambda-handler/index.ts +async function handler(event, context) { + const provider = createResourceHandler(event, context); + await provider.handle(); +} +function createResourceHandler(event, context) { + if (event.ResourceType.startsWith(SDK_RESOURCE_TYPE_PREFIX)) { + return new AwsApiCallHandler(event, context); + } + switch (event.ResourceType) { + case ASSERT_RESOURCE_TYPE: + return new AssertionHandler(event, context); + default: + throw new Error(`Unsupported resource type "${event.ResourceType}`); + } +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + handler +}); diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/cdk.out index 588d7b269d34f..8ecc185e9dbee 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/functionsubDefaultTestDeployAssert6BC1DDE4.assets.json b/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/functionsubDefaultTestDeployAssert6BC1DDE4.assets.json new file mode 100644 index 0000000000000..a97c153918d5a --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/functionsubDefaultTestDeployAssert6BC1DDE4.assets.json @@ -0,0 +1,32 @@ +{ + "version": "21.0.0", + "files": { + "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7": { + "source": { + "path": "asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "4439d15cb8dd748604834c9a98792e2ea21368368df94b230582c349afbde616": { + "source": { + "path": "functionsubDefaultTestDeployAssert6BC1DDE4.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "4439d15cb8dd748604834c9a98792e2ea21368368df94b230582c349afbde616.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/functionsubDefaultTestDeployAssert6BC1DDE4.template.json b/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/functionsubDefaultTestDeployAssert6BC1DDE4.template.json new file mode 100644 index 0000000000000..d74992c0a1d41 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/functionsubDefaultTestDeployAssert6BC1DDE4.template.json @@ -0,0 +1,198 @@ +{ + "Resources": { + "LambdaInvoke431773224924ebf10c8a31d363a6bf16": { + "Type": "Custom::DeployAssert@SdkCallLambdainvoke", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "service": "Lambda", + "api": "invoke", + "parameters": { + "FunctionName": { + "Fn::ImportValue": "integ-lambda-python-function-sub:ExportsOutputRefmyhandlerD202FA8E369E8804" + } + }, + "flattenResponse": "false", + "salt": "1662646331047" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "LambdaInvoke431773224924ebf10c8a31d363a6bf16Invoke9BC0E67F": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::ImportValue": "integ-lambda-python-function-sub:ExportsOutputRefmyhandlerD202FA8E369E8804" + }, + "Principal": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + }, + "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B": { + "Type": "Custom::DeployAssert@AssertEquals", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "actual": { + "Fn::GetAtt": [ + "LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "apiCallResponse" + ] + }, + "expected": "{\"$ObjectLike\":{\"Payload\":\"200\"}}", + "salt": "1662646331047" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "lambda:Invoke" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":lambda:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":function:", + { + "Fn::ImportValue": "integ-lambda-python-function-sub:ExportsOutputRefmyhandlerD202FA8E369E8804" + } + ] + ] + } + ] + } + ] + } + } + ] + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Runtime": "nodejs14.x", + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip" + }, + "Timeout": 120, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + } + }, + "Outputs": { + "AssertionResultsAssertEqualsLambdainvoke355665d3c1afb350a666dab592942021": { + "Value": { + "Fn::GetAtt": [ + "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B", + "data" + ] + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/integ-lambda-python-function-sub.assets.json b/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/integ-lambda-python-function-sub.assets.json new file mode 100644 index 0000000000000..738e106f892e9 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/integ-lambda-python-function-sub.assets.json @@ -0,0 +1,32 @@ +{ + "version": "21.0.0", + "files": { + "eef2fb23b619f037f697f4a27f8222232f65cb2bcc1e46ee560f3cdbdc685b1f": { + "source": { + "path": "asset.eef2fb23b619f037f697f4a27f8222232f65cb2bcc1e46ee560f3cdbdc685b1f", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "eef2fb23b619f037f697f4a27f8222232f65cb2bcc1e46ee560f3cdbdc685b1f.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "88108bc4d7ce82d1dde591e2faeeb55741b5f7dc1dafeb9ee143582c7ff74da0": { + "source": { + "path": "integ-lambda-python-function-sub.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "88108bc4d7ce82d1dde591e2faeeb55741b5f7dc1dafeb9ee143582c7ff74da0.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/cdk-integ-lambda-python.template.json b/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/integ-lambda-python-function-sub.template.json similarity index 86% rename from packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/cdk-integ-lambda-python.template.json rename to packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/integ-lambda-python-function-sub.template.json index df906236291f3..4a623c42d3144 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/cdk-integ-lambda-python.template.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/integ-lambda-python-function-sub.template.json @@ -38,7 +38,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "15c6226da35cc14f12fdaece3b3d66dde7401588e7d26238ecd92d6200f19231.zip" + "S3Key": "eef2fb23b619f037f697f4a27f8222232f65cb2bcc1e46ee560f3cdbdc685b1f.zip" }, "Role": { "Fn::GetAtt": [ @@ -62,6 +62,14 @@ "Arn" ] } + }, + "ExportsOutputRefmyhandlerD202FA8E369E8804": { + "Value": { + "Ref": "myhandlerD202FA8E" + }, + "Export": { + "Name": "integ-lambda-python-function-sub:ExportsOutputRefmyhandlerD202FA8E369E8804" + } } }, "Parameters": { diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/integ.json b/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/integ.json index 8ca519a667e48..4ef83b65d513b 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/integ.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/integ.json @@ -1,14 +1,13 @@ { - "version": "20.0.0", + "version": "21.0.0", "testCases": { - "integ.function.sub": { + "function-sub/DefaultTest": { "stacks": [ - "cdk-integ-lambda-python" + "integ-lambda-python-function-sub" ], - "diffAssets": false, - "stackUpdateWorkflow": false + "stackUpdateWorkflow": false, + "assertionStack": "function-sub/DefaultTest/DeployAssert", + "assertionStackName": "functionsubDefaultTestDeployAssert6BC1DDE4" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/manifest.json index 206688a3b8e61..55dfb9d0c5c16 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "21.0.0", "artifacts": { "Tree": { "type": "cdk:tree", @@ -7,27 +7,27 @@ "file": "tree.json" } }, - "cdk-integ-lambda-python.assets": { + "integ-lambda-python-function-sub.assets": { "type": "cdk:asset-manifest", "properties": { - "file": "cdk-integ-lambda-python.assets.json", + "file": "integ-lambda-python-function-sub.assets.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" } }, - "cdk-integ-lambda-python": { + "integ-lambda-python-function-sub": { "type": "aws:cloudformation:stack", "environment": "aws://unknown-account/unknown-region", "properties": { - "templateFile": "cdk-integ-lambda-python.template.json", + "templateFile": "integ-lambda-python-function-sub.template.json", "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/3ac51f034af66ed4cf5ec29e168dc5079869d2f535647dc8ce28de4fe50c9dfe.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/88108bc4d7ce82d1dde591e2faeeb55741b5f7dc1dafeb9ee143582c7ff74da0.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ - "cdk-integ-lambda-python.assets" + "integ-lambda-python-function-sub.assets" ], "lookupRole": { "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", @@ -36,41 +36,131 @@ } }, "dependencies": [ - "cdk-integ-lambda-python.assets" + "integ-lambda-python-function-sub.assets" ], "metadata": { - "/cdk-integ-lambda-python/my_handler/ServiceRole/Resource": [ + "/integ-lambda-python-function-sub/my_handler/ServiceRole/Resource": [ { "type": "aws:cdk:logicalId", "data": "myhandlerServiceRole77891068" } ], - "/cdk-integ-lambda-python/my_handler/Resource": [ + "/integ-lambda-python-function-sub/my_handler/Resource": [ { "type": "aws:cdk:logicalId", "data": "myhandlerD202FA8E" } ], - "/cdk-integ-lambda-python/FunctionArn": [ + "/integ-lambda-python-function-sub/FunctionArn": [ { "type": "aws:cdk:logicalId", "data": "FunctionArn" } ], - "/cdk-integ-lambda-python/BootstrapVersion": [ + "/integ-lambda-python-function-sub/Exports/Output{\"Ref\":\"myhandlerD202FA8E\"}": [ + { + "type": "aws:cdk:logicalId", + "data": "ExportsOutputRefmyhandlerD202FA8E369E8804" + } + ], + "/integ-lambda-python-function-sub/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-lambda-python-function-sub/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-lambda-python-function-sub" + }, + "functionsubDefaultTestDeployAssert6BC1DDE4.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "functionsubDefaultTestDeployAssert6BC1DDE4.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "functionsubDefaultTestDeployAssert6BC1DDE4": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "functionsubDefaultTestDeployAssert6BC1DDE4.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/4439d15cb8dd748604834c9a98792e2ea21368368df94b230582c349afbde616.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "functionsubDefaultTestDeployAssert6BC1DDE4.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integ-lambda-python-function-sub", + "functionsubDefaultTestDeployAssert6BC1DDE4.assets" + ], + "metadata": { + "/function-sub/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16" + } + ], + "/function-sub/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Invoke": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16Invoke9BC0E67F" + } + ], + "/function-sub/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B" + } + ], + "/function-sub/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionResults": [ + { + "type": "aws:cdk:logicalId", + "data": "AssertionResultsAssertEqualsLambdainvoke355665d3c1afb350a666dab592942021" + } + ], + "/function-sub/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73" + } + ], + "/function-sub/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F" + } + ], + "/function-sub/DefaultTest/DeployAssert/BootstrapVersion": [ { "type": "aws:cdk:logicalId", "data": "BootstrapVersion" } ], - "/cdk-integ-lambda-python/CheckBootstrapVersion": [ + "/function-sub/DefaultTest/DeployAssert/CheckBootstrapVersion": [ { "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } ] }, - "displayName": "cdk-integ-lambda-python" + "displayName": "function-sub/DefaultTest/DeployAssert" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/tree.json b/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/tree.json index ebeece5c20395..4585432982d5a 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.sub.integ.snapshot/tree.json @@ -9,24 +9,24 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } }, - "cdk-integ-lambda-python": { - "id": "cdk-integ-lambda-python", - "path": "cdk-integ-lambda-python", + "integ-lambda-python-function-sub": { + "id": "integ-lambda-python-function-sub", + "path": "integ-lambda-python-function-sub", "children": { "my_handler": { "id": "my_handler", - "path": "cdk-integ-lambda-python/my_handler", + "path": "integ-lambda-python-function-sub/my_handler", "children": { "ServiceRole": { "id": "ServiceRole", - "path": "cdk-integ-lambda-python/my_handler/ServiceRole", + "path": "integ-lambda-python-function-sub/my_handler/ServiceRole", "children": { "Resource": { "id": "Resource", - "path": "cdk-integ-lambda-python/my_handler/ServiceRole/Resource", + "path": "integ-lambda-python-function-sub/my_handler/ServiceRole/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::IAM::Role", "aws:cdk:cloudformation:props": { @@ -71,19 +71,19 @@ }, "Code": { "id": "Code", - "path": "cdk-integ-lambda-python/my_handler/Code", + "path": "integ-lambda-python-function-sub/my_handler/Code", "children": { "Stage": { "id": "Stage", - "path": "cdk-integ-lambda-python/my_handler/Code/Stage", + "path": "integ-lambda-python-function-sub/my_handler/Code/Stage", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "AssetBucket": { "id": "AssetBucket", - "path": "cdk-integ-lambda-python/my_handler/Code/AssetBucket", + "path": "integ-lambda-python-function-sub/my_handler/Code/AssetBucket", "constructInfo": { "fqn": "@aws-cdk/aws-s3.BucketBase", "version": "0.0.0" @@ -97,7 +97,7 @@ }, "Resource": { "id": "Resource", - "path": "cdk-integ-lambda-python/my_handler/Resource", + "path": "integ-lambda-python-function-sub/my_handler/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { @@ -105,7 +105,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "15c6226da35cc14f12fdaece3b3d66dde7401588e7d26238ecd92d6200f19231.zip" + "s3Key": "eef2fb23b619f037f697f4a27f8222232f65cb2bcc1e46ee560f3cdbdc685b1f.zip" }, "role": { "Fn::GetAtt": [ @@ -130,22 +130,220 @@ }, "FunctionArn": { "id": "FunctionArn", - "path": "cdk-integ-lambda-python/FunctionArn", + "path": "integ-lambda-python-function-sub/FunctionArn", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "Exports": { + "id": "Exports", + "path": "integ-lambda-python-function-sub/Exports", + "children": { + "Output{\"Ref\":\"myhandlerD202FA8E\"}": { + "id": "Output{\"Ref\":\"myhandlerD202FA8E\"}", + "path": "integ-lambda-python-function-sub/Exports/Output{\"Ref\":\"myhandlerD202FA8E\"}", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "function-sub": { + "id": "function-sub", + "path": "function-sub", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "function-sub/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "function-sub/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "function-sub/DefaultTest/DeployAssert", + "children": { + "LambdaInvoke431773224924ebf10c8a31d363a6bf16": { + "id": "LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "path": "function-sub/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "children": { + "SdkProvider": { + "id": "SdkProvider", + "path": "function-sub/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/SdkProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "function-sub/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/SdkProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.AssertionsProvider", + "version": "0.0.0" + } + }, + "Default": { + "id": "Default", + "path": "function-sub/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default", + "children": { + "Default": { + "id": "Default", + "path": "function-sub/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "Invoke": { + "id": "Invoke", + "path": "function-sub/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Invoke", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "AssertEqualsLambdainvoke": { + "id": "AssertEqualsLambdainvoke", + "path": "function-sub/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke", + "children": { + "AssertionProvider": { + "id": "AssertionProvider", + "path": "function-sub/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "function-sub/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.AssertionsProvider", + "version": "0.0.0" + } + }, + "Default": { + "id": "Default", + "path": "function-sub/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default", + "children": { + "Default": { + "id": "Default", + "path": "function-sub/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "AssertionResults": { + "id": "AssertionResults", + "path": "function-sub/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionResults", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.EqualsAssertion", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.LambdaInvokeFunction", + "version": "0.0.0" + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81": { + "id": "SingletonFunction1488541a7b23466481b69b4408076b81", + "path": "function-sub/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81", + "children": { + "Staging": { + "id": "Staging", + "path": "function-sub/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Staging", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "function-sub/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "function-sub/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js new file mode 100644 index 0000000000000..ba956d47f51fe --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js @@ -0,0 +1,612 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// lib/assertions/providers/lambda-handler/index.ts +var lambda_handler_exports = {}; +__export(lambda_handler_exports, { + handler: () => handler +}); +module.exports = __toCommonJS(lambda_handler_exports); + +// ../assertions/lib/matcher.ts +var Matcher = class { + static isMatcher(x) { + return x && x instanceof Matcher; + } +}; +var MatchResult = class { + constructor(target) { + this.failures = []; + this.captures = /* @__PURE__ */ new Map(); + this.finalized = false; + this.target = target; + } + push(matcher, path, message) { + return this.recordFailure({ matcher, path, message }); + } + recordFailure(failure) { + this.failures.push(failure); + return this; + } + hasFailed() { + return this.failures.length !== 0; + } + get failCount() { + return this.failures.length; + } + compose(id, inner) { + const innerF = inner.failures; + this.failures.push(...innerF.map((f) => { + return { path: [id, ...f.path], message: f.message, matcher: f.matcher }; + })); + inner.captures.forEach((vals, capture) => { + vals.forEach((value) => this.recordCapture({ capture, value })); + }); + return this; + } + finished() { + if (this.finalized) { + return this; + } + if (this.failCount === 0) { + this.captures.forEach((vals, cap) => cap._captured.push(...vals)); + } + this.finalized = true; + return this; + } + toHumanStrings() { + return this.failures.map((r) => { + const loc = r.path.length === 0 ? "" : ` at ${r.path.join("")}`; + return "" + r.message + loc + ` (using ${r.matcher.name} matcher)`; + }); + } + recordCapture(options) { + let values = this.captures.get(options.capture); + if (values === void 0) { + values = []; + } + values.push(options.value); + this.captures.set(options.capture, values); + } +}; + +// ../assertions/lib/private/matchers/absent.ts +var AbsentMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual !== void 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Received ${actual}, but key should be absent` + }); + } + return result; + } +}; + +// ../assertions/lib/private/type.ts +function getType(obj) { + return Array.isArray(obj) ? "array" : typeof obj; +} + +// ../assertions/lib/match.ts +var Match = class { + static absent() { + return new AbsentMatch("absent"); + } + static arrayWith(pattern) { + return new ArrayMatch("arrayWith", pattern); + } + static arrayEquals(pattern) { + return new ArrayMatch("arrayEquals", pattern, { subsequence: false }); + } + static exact(pattern) { + return new LiteralMatch("exact", pattern, { partialObjects: false }); + } + static objectLike(pattern) { + return new ObjectMatch("objectLike", pattern); + } + static objectEquals(pattern) { + return new ObjectMatch("objectEquals", pattern, { partial: false }); + } + static not(pattern) { + return new NotMatch("not", pattern); + } + static serializedJson(pattern) { + return new SerializedJson("serializedJson", pattern); + } + static anyValue() { + return new AnyMatch("anyValue"); + } + static stringLikeRegexp(pattern) { + return new StringLikeRegexpMatch("stringLikeRegexp", pattern); + } +}; +var LiteralMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partialObjects = options.partialObjects ?? false; + if (Matcher.isMatcher(this.pattern)) { + throw new Error("LiteralMatch cannot directly contain another matcher. Remove the top-level matcher or nest it more deeply."); + } + } + test(actual) { + if (Array.isArray(this.pattern)) { + return new ArrayMatch(this.name, this.pattern, { subsequence: false, partialObjects: this.partialObjects }).test(actual); + } + if (typeof this.pattern === "object") { + return new ObjectMatch(this.name, this.pattern, { partial: this.partialObjects }).test(actual); + } + const result = new MatchResult(actual); + if (typeof this.pattern !== typeof actual) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected type ${typeof this.pattern} but received ${getType(actual)}` + }); + return result; + } + if (actual !== this.pattern) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected ${this.pattern} but received ${actual}` + }); + } + return result; + } +}; +var ArrayMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.subsequence = options.subsequence ?? true; + this.partialObjects = options.partialObjects ?? false; + } + test(actual) { + if (!Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type array but received ${getType(actual)}` + }); + } + if (!this.subsequence && this.pattern.length !== actual.length) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected array of length ${this.pattern.length} but received ${actual.length}` + }); + } + let patternIdx = 0; + let actualIdx = 0; + const result = new MatchResult(actual); + while (patternIdx < this.pattern.length && actualIdx < actual.length) { + const patternElement = this.pattern[patternIdx]; + const matcher = Matcher.isMatcher(patternElement) ? patternElement : new LiteralMatch(this.name, patternElement, { partialObjects: this.partialObjects }); + const matcherName = matcher.name; + if (this.subsequence && (matcherName == "absent" || matcherName == "anyValue")) { + throw new Error(`The Matcher ${matcherName}() cannot be nested within arrayWith()`); + } + const innerResult = matcher.test(actual[actualIdx]); + if (!this.subsequence || !innerResult.hasFailed()) { + result.compose(`[${actualIdx}]`, innerResult); + patternIdx++; + actualIdx++; + } else { + actualIdx++; + } + } + for (; patternIdx < this.pattern.length; patternIdx++) { + const pattern = this.pattern[patternIdx]; + const element = Matcher.isMatcher(pattern) || typeof pattern === "object" ? " " : ` [${pattern}] `; + result.recordFailure({ + matcher: this, + path: [], + message: `Missing element${element}at pattern index ${patternIdx}` + }); + } + return result; + } +}; +var ObjectMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partial = options.partial ?? true; + } + test(actual) { + if (typeof actual !== "object" || Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type object but received ${getType(actual)}` + }); + } + const result = new MatchResult(actual); + if (!this.partial) { + for (const a of Object.keys(actual)) { + if (!(a in this.pattern)) { + result.recordFailure({ + matcher: this, + path: [`/${a}`], + message: "Unexpected key" + }); + } + } + } + for (const [patternKey, patternVal] of Object.entries(this.pattern)) { + if (!(patternKey in actual) && !(patternVal instanceof AbsentMatch)) { + result.recordFailure({ + matcher: this, + path: [`/${patternKey}`], + message: `Missing key '${patternKey}' among {${Object.keys(actual).join(",")}}` + }); + continue; + } + const matcher = Matcher.isMatcher(patternVal) ? patternVal : new LiteralMatch(this.name, patternVal, { partialObjects: this.partial }); + const inner = matcher.test(actual[patternKey]); + result.compose(`/${patternKey}`, inner); + } + return result; + } +}; +var SerializedJson = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + if (getType(actual) !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected JSON as a string but found ${getType(actual)}` + }); + return result; + } + let parsed; + try { + parsed = JSON.parse(actual); + } catch (err) { + if (err instanceof SyntaxError) { + result.recordFailure({ + matcher: this, + path: [], + message: `Invalid JSON string: ${actual}` + }); + return result; + } else { + throw err; + } + } + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(parsed); + result.compose(`(${this.name})`, innerResult); + return result; + } +}; +var NotMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(actual); + const result = new MatchResult(actual); + if (innerResult.failCount === 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Found unexpected match: ${JSON.stringify(actual, void 0, 2)}` + }); + } + return result; + } +}; +var AnyMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual == null) { + result.recordFailure({ + matcher: this, + path: [], + message: "Expected a value but found none" + }); + } + return result; + } +}; +var StringLikeRegexpMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + const regex = new RegExp(this.pattern, "gm"); + if (typeof actual !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected a string, but got '${typeof actual}'` + }); + } + if (!regex.test(actual)) { + result.recordFailure({ + matcher: this, + path: [], + message: `String '${actual}' did not match pattern '${this.pattern}'` + }); + } + return result; + } +}; + +// lib/assertions/providers/lambda-handler/base.ts +var https = __toESM(require("https")); +var url = __toESM(require("url")); +var CustomResourceHandler = class { + constructor(event, context) { + this.event = event; + this.context = context; + this.timedOut = false; + this.timeout = setTimeout(async () => { + await this.respond({ + status: "FAILED", + reason: "Lambda Function Timeout", + data: this.context.logStreamName + }); + this.timedOut = true; + }, context.getRemainingTimeInMillis() - 1200); + this.event = event; + this.physicalResourceId = extractPhysicalResourceId(event); + } + async handle() { + try { + console.log(`Event: ${JSON.stringify({ ...this.event, ResponseURL: "..." })}`); + const response = await this.processEvent(this.event.ResourceProperties); + console.log(`Event output : ${JSON.stringify(response)}`); + await this.respond({ + status: "SUCCESS", + reason: "OK", + data: response + }); + } catch (e) { + console.log(e); + await this.respond({ + status: "FAILED", + reason: e.message ?? "Internal Error" + }); + } finally { + clearTimeout(this.timeout); + } + } + respond(response) { + if (this.timedOut) { + return; + } + const cfResponse = { + Status: response.status, + Reason: response.reason, + PhysicalResourceId: this.physicalResourceId, + StackId: this.event.StackId, + RequestId: this.event.RequestId, + LogicalResourceId: this.event.LogicalResourceId, + NoEcho: false, + Data: response.data + }; + const responseBody = JSON.stringify(cfResponse); + console.log("Responding to CloudFormation", responseBody); + const parsedUrl = url.parse(this.event.ResponseURL); + const requestOptions = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: "PUT", + headers: { "content-type": "", "content-length": responseBody.length } + }; + return new Promise((resolve, reject) => { + try { + const request2 = https.request(requestOptions, resolve); + request2.on("error", reject); + request2.write(responseBody); + request2.end(); + } catch (e) { + reject(e); + } + }); + } +}; +function extractPhysicalResourceId(event) { + switch (event.RequestType) { + case "Create": + return event.LogicalResourceId; + case "Update": + case "Delete": + return event.PhysicalResourceId; + } +} + +// lib/assertions/providers/lambda-handler/assertion.ts +var AssertionHandler = class extends CustomResourceHandler { + async processEvent(request2) { + let actual = decodeCall(request2.actual); + const expected = decodeCall(request2.expected); + let result; + const matcher = new MatchCreator(expected).getMatcher(); + console.log(`Testing equality between ${JSON.stringify(request2.actual)} and ${JSON.stringify(request2.expected)}`); + const matchResult = matcher.test(actual); + matchResult.finished(); + if (matchResult.hasFailed()) { + result = { + data: JSON.stringify({ + status: "fail", + message: [ + ...matchResult.toHumanStrings(), + JSON.stringify(matchResult.target, void 0, 2) + ].join("\n") + }) + }; + if (request2.failDeployment) { + throw new Error(result.data); + } + } else { + result = { + data: JSON.stringify({ + status: "success" + }) + }; + } + return result; + } +}; +var MatchCreator = class { + constructor(obj) { + this.parsedObj = { + matcher: obj + }; + } + getMatcher() { + try { + const final = JSON.parse(JSON.stringify(this.parsedObj), function(_k, v) { + const nested = Object.keys(v)[0]; + switch (nested) { + case "$ArrayWith": + return Match.arrayWith(v[nested]); + case "$ObjectLike": + return Match.objectLike(v[nested]); + case "$StringLike": + return Match.stringLikeRegexp(v[nested]); + default: + return v; + } + }); + if (Matcher.isMatcher(final.matcher)) { + return final.matcher; + } + return Match.exact(final.matcher); + } catch { + return Match.exact(this.parsedObj.matcher); + } + } +}; +function decodeCall(call) { + if (!call) { + return void 0; + } + try { + const parsed = JSON.parse(call); + return parsed; + } catch (e) { + return call; + } +} + +// lib/assertions/providers/lambda-handler/utils.ts +function decode(object) { + return JSON.parse(JSON.stringify(object), (_k, v) => { + switch (v) { + case "TRUE:BOOLEAN": + return true; + case "FALSE:BOOLEAN": + return false; + default: + return v; + } + }); +} + +// lib/assertions/providers/lambda-handler/sdk.ts +function flatten(object) { + return Object.assign( + {}, + ...function _flatten(child, path = []) { + return [].concat(...Object.keys(child).map((key) => { + const childKey = Buffer.isBuffer(child[key]) ? child[key].toString("utf8") : child[key]; + return typeof childKey === "object" && childKey !== null ? _flatten(childKey, path.concat([key])) : { [path.concat([key]).join(".")]: childKey }; + })); + }(object) + ); +} +var AwsApiCallHandler = class extends CustomResourceHandler { + async processEvent(request2) { + const AWS = require("aws-sdk"); + console.log(`AWS SDK VERSION: ${AWS.VERSION}`); + const service = new AWS[request2.service](); + const response = await service[request2.api](request2.parameters && decode(request2.parameters)).promise(); + console.log(`SDK response received ${JSON.stringify(response)}`); + delete response.ResponseMetadata; + const respond = { + apiCallResponse: response + }; + const flatData = { + ...flatten(respond) + }; + return request2.flattenResponse === "true" ? flatData : respond; + } +}; + +// lib/assertions/providers/lambda-handler/types.ts +var ASSERT_RESOURCE_TYPE = "Custom::DeployAssert@AssertEquals"; +var SDK_RESOURCE_TYPE_PREFIX = "Custom::DeployAssert@SdkCall"; + +// lib/assertions/providers/lambda-handler/index.ts +async function handler(event, context) { + const provider = createResourceHandler(event, context); + await provider.handle(); +} +function createResourceHandler(event, context) { + if (event.ResourceType.startsWith(SDK_RESOURCE_TYPE_PREFIX)) { + return new AwsApiCallHandler(event, context); + } + switch (event.ResourceType) { + case ASSERT_RESOURCE_TYPE: + return new AssertionHandler(event, context); + default: + throw new Error(`Unsupported resource type "${event.ResourceType}`); + } +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + handler +}); diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/asset.e3d888d855ebd2b6173af510e2eba9e1542084655559f4bb05adbb2e6ca63b73/index.py b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/asset.e3d888d855ebd2b6173af510e2eba9e1542084655559f4bb05adbb2e6ca63b73/index.py deleted file mode 100644 index 04f99eb108b30..0000000000000 --- a/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/asset.e3d888d855ebd2b6173af510e2eba9e1542084655559f4bb05adbb2e6ca63b73/index.py +++ /dev/null @@ -1,8 +0,0 @@ -import requests - -def handler(event, context): - response = requests.get('https://a0.awsstatic.com/main/images/logos/aws_smile-header-desktop-en-white_59x35.png', stream=True) - - print(response.status_code) - - return response.status_code diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/asset.e3d888d855ebd2b6173af510e2eba9e1542084655559f4bb05adbb2e6ca63b73/requirements.txt b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/asset.e3d888d855ebd2b6173af510e2eba9e1542084655559f4bb05adbb2e6ca63b73/requirements.txt deleted file mode 100644 index 4fcd85719fe3a..0000000000000 --- a/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/asset.e3d888d855ebd2b6173af510e2eba9e1542084655559f4bb05adbb2e6ca63b73/requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -# Lock versions of pip packages -certifi==2020.6.20 -chardet==3.0.4 -idna==2.10 -urllib3==1.26.7 -# Requests used by this lambda -requests==2.26.0 diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/cdk-integ-lambda-python-vpc.assets.json b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/cdk-integ-lambda-python-vpc.assets.json index 8073e5cfdc435..ec304783a2880 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/cdk-integ-lambda-python-vpc.assets.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/cdk-integ-lambda-python-vpc.assets.json @@ -1,20 +1,20 @@ { - "version": "20.0.0", + "version": "21.0.0", "files": { - "7641c95c909cbd220aa45f8b7dca8606bd48b9a84f0c5d28fa697c90c810983b": { + "3b4e770c8242272e96f6faafd45d2446549a060a25dcce2d246445447e356ca9": { "source": { - "path": "asset.7641c95c909cbd220aa45f8b7dca8606bd48b9a84f0c5d28fa697c90c810983b", + "path": "asset.3b4e770c8242272e96f6faafd45d2446549a060a25dcce2d246445447e356ca9", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "7641c95c909cbd220aa45f8b7dca8606bd48b9a84f0c5d28fa697c90c810983b.zip", + "objectKey": "3b4e770c8242272e96f6faafd45d2446549a060a25dcce2d246445447e356ca9.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "9f8f235bc0574a06fafca37baeeb5e4f4e0307e4bb952f68d7bd493ab6c2ff78": { + "6ce6ccc522282d726af7d10e96bac782bf7551895e5a1ec08cdac3512dccd530": { "source": { "path": "cdk-integ-lambda-python-vpc.template.json", "packaging": "file" @@ -22,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "9f8f235bc0574a06fafca37baeeb5e4f4e0307e4bb952f68d7bd493ab6c2ff78.json", + "objectKey": "6ce6ccc522282d726af7d10e96bac782bf7551895e5a1ec08cdac3512dccd530.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/cdk-integ-lambda-python-vpc.template.json b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/cdk-integ-lambda-python-vpc.template.json index 23a2370687805..25363a20c9ad4 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/cdk-integ-lambda-python-vpc.template.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/cdk-integ-lambda-python-vpc.template.json @@ -15,7 +15,7 @@ ] } }, - "myvpcingressSubnet1Subnet82F0259C": { + "myvpcPublicSubnet1Subnet6BD75C12": { "Type": "AWS::EC2::Subnet", "Properties": { "VpcId": { @@ -29,12 +29,12 @@ } ] }, - "CidrBlock": "10.0.0.0/24", + "CidrBlock": "10.0.0.0/18", "MapPublicIpOnLaunch": true, "Tags": [ { "Key": "aws-cdk:subnet-name", - "Value": "ingress" + "Value": "Public" }, { "Key": "aws-cdk:subnet-type", @@ -42,12 +42,12 @@ }, { "Key": "Name", - "Value": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet1" + "Value": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1" } ] } }, - "myvpcingressSubnet1RouteTableD6322DD5": { + "myvpcPublicSubnet1RouteTableF7E8D7F1": { "Type": "AWS::EC2::RouteTable", "Properties": { "VpcId": { @@ -56,27 +56,27 @@ "Tags": [ { "Key": "Name", - "Value": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet1" + "Value": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1" } ] } }, - "myvpcingressSubnet1RouteTableAssociation12FE9C06": { + "myvpcPublicSubnet1RouteTableAssociationC697FA56": { "Type": "AWS::EC2::SubnetRouteTableAssociation", "Properties": { "RouteTableId": { - "Ref": "myvpcingressSubnet1RouteTableD6322DD5" + "Ref": "myvpcPublicSubnet1RouteTableF7E8D7F1" }, "SubnetId": { - "Ref": "myvpcingressSubnet1Subnet82F0259C" + "Ref": "myvpcPublicSubnet1Subnet6BD75C12" } } }, - "myvpcingressSubnet1DefaultRoute6FCDFDDF": { + "myvpcPublicSubnet1DefaultRouteBE259807": { "Type": "AWS::EC2::Route", "Properties": { "RouteTableId": { - "Ref": "myvpcingressSubnet1RouteTableD6322DD5" + "Ref": "myvpcPublicSubnet1RouteTableF7E8D7F1" }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { @@ -87,7 +87,43 @@ "myvpcVPCGWD483DB64" ] }, - "myvpcingressSubnet2Subnet56945106": { + "myvpcPublicSubnet1EIP88D18203": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1" + } + ] + } + }, + "myvpcPublicSubnet1NATGatewayD3DC5B8D": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "SubnetId": { + "Ref": "myvpcPublicSubnet1Subnet6BD75C12" + }, + "AllocationId": { + "Fn::GetAtt": [ + "myvpcPublicSubnet1EIP88D18203", + "AllocationId" + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1" + } + ] + }, + "DependsOn": [ + "myvpcPublicSubnet1DefaultRouteBE259807", + "myvpcPublicSubnet1RouteTableAssociationC697FA56" + ] + }, + "myvpcPublicSubnet2Subnet844B7F05": { "Type": "AWS::EC2::Subnet", "Properties": { "VpcId": { @@ -101,12 +137,12 @@ } ] }, - "CidrBlock": "10.0.1.0/24", + "CidrBlock": "10.0.64.0/18", "MapPublicIpOnLaunch": true, "Tags": [ { "Key": "aws-cdk:subnet-name", - "Value": "ingress" + "Value": "Public" }, { "Key": "aws-cdk:subnet-type", @@ -114,12 +150,12 @@ }, { "Key": "Name", - "Value": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet2" + "Value": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2" } ] } }, - "myvpcingressSubnet2RouteTable2112B53A": { + "myvpcPublicSubnet2RouteTable9A4CA50C": { "Type": "AWS::EC2::RouteTable", "Properties": { "VpcId": { @@ -128,27 +164,27 @@ "Tags": [ { "Key": "Name", - "Value": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet2" + "Value": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2" } ] } }, - "myvpcingressSubnet2RouteTableAssociation08B3BE06": { + "myvpcPublicSubnet2RouteTableAssociation28F6DD6F": { "Type": "AWS::EC2::SubnetRouteTableAssociation", "Properties": { "RouteTableId": { - "Ref": "myvpcingressSubnet2RouteTable2112B53A" + "Ref": "myvpcPublicSubnet2RouteTable9A4CA50C" }, "SubnetId": { - "Ref": "myvpcingressSubnet2Subnet56945106" + "Ref": "myvpcPublicSubnet2Subnet844B7F05" } } }, - "myvpcingressSubnet2DefaultRouteBF3C1EC8": { + "myvpcPublicSubnet2DefaultRoute22D543BA": { "Type": "AWS::EC2::Route", "Properties": { "RouteTableId": { - "Ref": "myvpcingressSubnet2RouteTable2112B53A" + "Ref": "myvpcPublicSubnet2RouteTable9A4CA50C" }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { @@ -159,6 +195,180 @@ "myvpcVPCGWD483DB64" ] }, + "myvpcPublicSubnet2EIPA3AF827D": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2" + } + ] + } + }, + "myvpcPublicSubnet2NATGateway45472CCD": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "SubnetId": { + "Ref": "myvpcPublicSubnet2Subnet844B7F05" + }, + "AllocationId": { + "Fn::GetAtt": [ + "myvpcPublicSubnet2EIPA3AF827D", + "AllocationId" + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2" + } + ] + }, + "DependsOn": [ + "myvpcPublicSubnet2DefaultRoute22D543BA", + "myvpcPublicSubnet2RouteTableAssociation28F6DD6F" + ] + }, + "myvpcPrivateSubnet1SubnetAE3DECEE": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "myvpc9455A260" + }, + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.128.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet1" + } + ] + } + }, + "myvpcPrivateSubnet1RouteTable991B69A9": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "myvpc9455A260" + }, + "Tags": [ + { + "Key": "Name", + "Value": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet1" + } + ] + } + }, + "myvpcPrivateSubnet1RouteTableAssociation91351DDE": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "myvpcPrivateSubnet1RouteTable991B69A9" + }, + "SubnetId": { + "Ref": "myvpcPrivateSubnet1SubnetAE3DECEE" + } + } + }, + "myvpcPrivateSubnet1DefaultRouteA1815BF3": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "myvpcPrivateSubnet1RouteTable991B69A9" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "myvpcPublicSubnet1NATGatewayD3DC5B8D" + } + } + }, + "myvpcPrivateSubnet2SubnetE09939FB": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "myvpc9455A260" + }, + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.192.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet2" + } + ] + } + }, + "myvpcPrivateSubnet2RouteTableF2B44BF5": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "myvpc9455A260" + }, + "Tags": [ + { + "Key": "Name", + "Value": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet2" + } + ] + } + }, + "myvpcPrivateSubnet2RouteTableAssociation071745F0": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "myvpcPrivateSubnet2RouteTableF2B44BF5" + }, + "SubnetId": { + "Ref": "myvpcPrivateSubnet2SubnetE09939FB" + } + } + }, + "myvpcPrivateSubnet2DefaultRouteB54E314A": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "myvpcPrivateSubnet2RouteTableF2B44BF5" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "myvpcPublicSubnet2NATGateway45472CCD" + } + } + }, "myvpcIGW24C0BBAE": { "Type": "AWS::EC2::InternetGateway", "Properties": { @@ -224,10 +434,10 @@ ] }, "DependsOn": [ - "myvpcingressSubnet1DefaultRoute6FCDFDDF", - "myvpcingressSubnet1RouteTableAssociation12FE9C06", - "myvpcingressSubnet2DefaultRouteBF3C1EC8", - "myvpcingressSubnet2RouteTableAssociation08B3BE06" + "myvpcPrivateSubnet1DefaultRouteA1815BF3", + "myvpcPrivateSubnet1RouteTableAssociation91351DDE", + "myvpcPrivateSubnet2DefaultRouteB54E314A", + "myvpcPrivateSubnet2RouteTableAssociation071745F0" ] }, "myhandlerSecurityGroupF566A239": { @@ -246,10 +456,10 @@ } }, "DependsOn": [ - "myvpcingressSubnet1DefaultRoute6FCDFDDF", - "myvpcingressSubnet1RouteTableAssociation12FE9C06", - "myvpcingressSubnet2DefaultRouteBF3C1EC8", - "myvpcingressSubnet2RouteTableAssociation08B3BE06" + "myvpcPrivateSubnet1DefaultRouteA1815BF3", + "myvpcPrivateSubnet1RouteTableAssociation91351DDE", + "myvpcPrivateSubnet2DefaultRouteB54E314A", + "myvpcPrivateSubnet2RouteTableAssociation071745F0" ] }, "myhandlerD202FA8E": { @@ -259,7 +469,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7641c95c909cbd220aa45f8b7dca8606bd48b9a84f0c5d28fa697c90c810983b.zip" + "S3Key": "3b4e770c8242272e96f6faafd45d2446549a060a25dcce2d246445447e356ca9.zip" }, "Role": { "Fn::GetAtt": [ @@ -280,30 +490,30 @@ ], "SubnetIds": [ { - "Ref": "myvpcingressSubnet1Subnet82F0259C" + "Ref": "myvpcPrivateSubnet1SubnetAE3DECEE" }, { - "Ref": "myvpcingressSubnet2Subnet56945106" + "Ref": "myvpcPrivateSubnet2SubnetE09939FB" } ] } }, "DependsOn": [ "myhandlerServiceRole77891068", - "myvpcingressSubnet1DefaultRoute6FCDFDDF", - "myvpcingressSubnet1RouteTableAssociation12FE9C06", - "myvpcingressSubnet2DefaultRouteBF3C1EC8", - "myvpcingressSubnet2RouteTableAssociation08B3BE06" + "myvpcPrivateSubnet1DefaultRouteA1815BF3", + "myvpcPrivateSubnet1RouteTableAssociation91351DDE", + "myvpcPrivateSubnet2DefaultRouteB54E314A", + "myvpcPrivateSubnet2RouteTableAssociation071745F0" ] } }, "Outputs": { - "FunctionArn": { + "ExportsOutputRefmyhandlerD202FA8E369E8804": { "Value": { - "Fn::GetAtt": [ - "myhandlerD202FA8E", - "Arn" - ] + "Ref": "myhandlerD202FA8E" + }, + "Export": { + "Name": "cdk-integ-lambda-python-vpc:ExportsOutputRefmyhandlerD202FA8E369E8804" } } }, diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/cdk.out index 588d7b269d34f..8ecc185e9dbee 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/integ.json b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/integ.json index de22ed99acbac..8461763dfe874 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/integ.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/integ.json @@ -1,14 +1,13 @@ { - "version": "20.0.0", + "version": "21.0.0", "testCases": { - "integ.function.vpc": { + "lambda-python-vpc/DefaultTest": { "stacks": [ "cdk-integ-lambda-python-vpc" ], - "diffAssets": false, - "stackUpdateWorkflow": false + "stackUpdateWorkflow": false, + "assertionStack": "lambda-python-vpc/DefaultTest/DeployAssert", + "assertionStackName": "lambdapythonvpcDefaultTestDeployAssert54E0DCFB" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/lambdapythonvpcDefaultTestDeployAssert54E0DCFB.assets.json b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/lambdapythonvpcDefaultTestDeployAssert54E0DCFB.assets.json new file mode 100644 index 0000000000000..3e5328c622b49 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/lambdapythonvpcDefaultTestDeployAssert54E0DCFB.assets.json @@ -0,0 +1,32 @@ +{ + "version": "21.0.0", + "files": { + "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7": { + "source": { + "path": "asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "a0651ad741f16b986ca00083720eb4e40348df935c5cfef88d6f8b4bff635617": { + "source": { + "path": "lambdapythonvpcDefaultTestDeployAssert54E0DCFB.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "a0651ad741f16b986ca00083720eb4e40348df935c5cfef88d6f8b4bff635617.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/lambdapythonvpcDefaultTestDeployAssert54E0DCFB.template.json b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/lambdapythonvpcDefaultTestDeployAssert54E0DCFB.template.json new file mode 100644 index 0000000000000..47cc77c11984e --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/lambdapythonvpcDefaultTestDeployAssert54E0DCFB.template.json @@ -0,0 +1,198 @@ +{ + "Resources": { + "LambdaInvoke431773224924ebf10c8a31d363a6bf16": { + "Type": "Custom::DeployAssert@SdkCallLambdainvoke", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "service": "Lambda", + "api": "invoke", + "parameters": { + "FunctionName": { + "Fn::ImportValue": "cdk-integ-lambda-python-vpc:ExportsOutputRefmyhandlerD202FA8E369E8804" + } + }, + "flattenResponse": "false", + "salt": "1662649883464" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "LambdaInvoke431773224924ebf10c8a31d363a6bf16Invoke9BC0E67F": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::ImportValue": "cdk-integ-lambda-python-vpc:ExportsOutputRefmyhandlerD202FA8E369E8804" + }, + "Principal": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + }, + "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B": { + "Type": "Custom::DeployAssert@AssertEquals", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "actual": { + "Fn::GetAtt": [ + "LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "apiCallResponse" + ] + }, + "expected": "{\"$ObjectLike\":{\"Payload\":\"200\"}}", + "salt": "1662649883465" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "lambda:Invoke" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":lambda:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":function:", + { + "Fn::ImportValue": "cdk-integ-lambda-python-vpc:ExportsOutputRefmyhandlerD202FA8E369E8804" + } + ] + ] + } + ] + } + ] + } + } + ] + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Runtime": "nodejs14.x", + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip" + }, + "Timeout": 120, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + } + }, + "Outputs": { + "AssertionResultsAssertEqualsLambdainvoke29290e026919ecb85e75d0aca122fdc1": { + "Value": { + "Fn::GetAtt": [ + "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B", + "data" + ] + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/manifest.json index 0cec9544ad689..b07900e26e901 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "21.0.0", "artifacts": { "Tree": { "type": "cdk:tree", @@ -23,7 +23,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/9f8f235bc0574a06fafca37baeeb5e4f4e0307e4bb952f68d7bd493ab6c2ff78.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/6ce6ccc522282d726af7d10e96bac782bf7551895e5a1ec08cdac3512dccd530.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -45,52 +45,124 @@ "data": "myvpc9455A260" } ], - "/cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet1/Subnet": [ + "/cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1/Subnet": [ { "type": "aws:cdk:logicalId", - "data": "myvpcingressSubnet1Subnet82F0259C" + "data": "myvpcPublicSubnet1Subnet6BD75C12" } ], - "/cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet1/RouteTable": [ + "/cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1/RouteTable": [ { "type": "aws:cdk:logicalId", - "data": "myvpcingressSubnet1RouteTableD6322DD5" + "data": "myvpcPublicSubnet1RouteTableF7E8D7F1" } ], - "/cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet1/RouteTableAssociation": [ + "/cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1/RouteTableAssociation": [ { "type": "aws:cdk:logicalId", - "data": "myvpcingressSubnet1RouteTableAssociation12FE9C06" + "data": "myvpcPublicSubnet1RouteTableAssociationC697FA56" } ], - "/cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet1/DefaultRoute": [ + "/cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1/DefaultRoute": [ { "type": "aws:cdk:logicalId", - "data": "myvpcingressSubnet1DefaultRoute6FCDFDDF" + "data": "myvpcPublicSubnet1DefaultRouteBE259807" } ], - "/cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet2/Subnet": [ + "/cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1/EIP": [ { "type": "aws:cdk:logicalId", - "data": "myvpcingressSubnet2Subnet56945106" + "data": "myvpcPublicSubnet1EIP88D18203" } ], - "/cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet2/RouteTable": [ + "/cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1/NATGateway": [ { "type": "aws:cdk:logicalId", - "data": "myvpcingressSubnet2RouteTable2112B53A" + "data": "myvpcPublicSubnet1NATGatewayD3DC5B8D" } ], - "/cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet2/RouteTableAssociation": [ + "/cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2/Subnet": [ { "type": "aws:cdk:logicalId", - "data": "myvpcingressSubnet2RouteTableAssociation08B3BE06" + "data": "myvpcPublicSubnet2Subnet844B7F05" } ], - "/cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet2/DefaultRoute": [ + "/cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2/RouteTable": [ { "type": "aws:cdk:logicalId", - "data": "myvpcingressSubnet2DefaultRouteBF3C1EC8" + "data": "myvpcPublicSubnet2RouteTable9A4CA50C" + } + ], + "/cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcPublicSubnet2RouteTableAssociation28F6DD6F" + } + ], + "/cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcPublicSubnet2DefaultRoute22D543BA" + } + ], + "/cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcPublicSubnet2EIPA3AF827D" + } + ], + "/cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcPublicSubnet2NATGateway45472CCD" + } + ], + "/cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcPrivateSubnet1SubnetAE3DECEE" + } + ], + "/cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcPrivateSubnet1RouteTable991B69A9" + } + ], + "/cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcPrivateSubnet1RouteTableAssociation91351DDE" + } + ], + "/cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcPrivateSubnet1DefaultRouteA1815BF3" + } + ], + "/cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcPrivateSubnet2SubnetE09939FB" + } + ], + "/cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcPrivateSubnet2RouteTableF2B44BF5" + } + ], + "/cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcPrivateSubnet2RouteTableAssociation071745F0" + } + ], + "/cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcPrivateSubnet2DefaultRouteB54E314A" } ], "/cdk-integ-lambda-python-vpc/my_vpc/IGW": [ @@ -123,10 +195,10 @@ "data": "myhandlerD202FA8E" } ], - "/cdk-integ-lambda-python-vpc/FunctionArn": [ + "/cdk-integ-lambda-python-vpc/Exports/Output{\"Ref\":\"myhandlerD202FA8E\"}": [ { "type": "aws:cdk:logicalId", - "data": "FunctionArn" + "data": "ExportsOutputRefmyhandlerD202FA8E369E8804" } ], "/cdk-integ-lambda-python-vpc/BootstrapVersion": [ @@ -140,9 +212,165 @@ "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } + ], + "myvpcingressSubnet1Subnet82F0259C": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcingressSubnet1Subnet82F0259C", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ], + "myvpcingressSubnet1RouteTableD6322DD5": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcingressSubnet1RouteTableD6322DD5", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ], + "myvpcingressSubnet1RouteTableAssociation12FE9C06": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcingressSubnet1RouteTableAssociation12FE9C06", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ], + "myvpcingressSubnet1DefaultRoute6FCDFDDF": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcingressSubnet1DefaultRoute6FCDFDDF", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ], + "myvpcingressSubnet2Subnet56945106": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcingressSubnet2Subnet56945106", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ], + "myvpcingressSubnet2RouteTable2112B53A": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcingressSubnet2RouteTable2112B53A", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ], + "myvpcingressSubnet2RouteTableAssociation08B3BE06": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcingressSubnet2RouteTableAssociation08B3BE06", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ], + "myvpcingressSubnet2DefaultRouteBF3C1EC8": [ + { + "type": "aws:cdk:logicalId", + "data": "myvpcingressSubnet2DefaultRouteBF3C1EC8", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } ] }, "displayName": "cdk-integ-lambda-python-vpc" + }, + "lambdapythonvpcDefaultTestDeployAssert54E0DCFB.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "lambdapythonvpcDefaultTestDeployAssert54E0DCFB.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "lambdapythonvpcDefaultTestDeployAssert54E0DCFB": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "lambdapythonvpcDefaultTestDeployAssert54E0DCFB.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/a0651ad741f16b986ca00083720eb4e40348df935c5cfef88d6f8b4bff635617.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "lambdapythonvpcDefaultTestDeployAssert54E0DCFB.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "cdk-integ-lambda-python-vpc", + "lambdapythonvpcDefaultTestDeployAssert54E0DCFB.assets" + ], + "metadata": { + "/lambda-python-vpc/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16" + } + ], + "/lambda-python-vpc/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Invoke": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16Invoke9BC0E67F" + } + ], + "/lambda-python-vpc/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaInvoke431773224924ebf10c8a31d363a6bf16AssertEqualsLambdainvokeF6179C6B" + } + ], + "/lambda-python-vpc/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionResults": [ + { + "type": "aws:cdk:logicalId", + "data": "AssertionResultsAssertEqualsLambdainvoke29290e026919ecb85e75d0aca122fdc1" + } + ], + "/lambda-python-vpc/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73" + } + ], + "/lambda-python-vpc/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F" + } + ], + "/lambda-python-vpc/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/lambda-python-vpc/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "lambda-python-vpc/DefaultTest/DeployAssert" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/tree.json b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/tree.json index d2df9d322e68b..129f8a922c050 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-lambda-python/test/function.vpc.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } }, "cdk-integ-lambda-python-vpc": { @@ -43,13 +43,13 @@ "version": "0.0.0" } }, - "ingressSubnet1": { - "id": "ingressSubnet1", - "path": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet1", + "PublicSubnet1": { + "id": "PublicSubnet1", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1", "children": { "Subnet": { "id": "Subnet", - "path": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet1/Subnet", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1/Subnet", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", "aws:cdk:cloudformation:props": { @@ -64,12 +64,12 @@ } ] }, - "cidrBlock": "10.0.0.0/24", + "cidrBlock": "10.0.0.0/18", "mapPublicIpOnLaunch": true, "tags": [ { "key": "aws-cdk:subnet-name", - "value": "ingress" + "value": "Public" }, { "key": "aws-cdk:subnet-type", @@ -77,7 +77,7 @@ }, { "key": "Name", - "value": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet1" + "value": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1" } ] } @@ -89,15 +89,15 @@ }, "Acl": { "id": "Acl", - "path": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet1/Acl", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { "id": "RouteTable", - "path": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet1/RouteTable", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1/RouteTable", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", "aws:cdk:cloudformation:props": { @@ -107,7 +107,7 @@ "tags": [ { "key": "Name", - "value": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet1" + "value": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1" } ] } @@ -119,15 +119,15 @@ }, "RouteTableAssociation": { "id": "RouteTableAssociation", - "path": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet1/RouteTableAssociation", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1/RouteTableAssociation", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", "aws:cdk:cloudformation:props": { "routeTableId": { - "Ref": "myvpcingressSubnet1RouteTableD6322DD5" + "Ref": "myvpcPublicSubnet1RouteTableF7E8D7F1" }, "subnetId": { - "Ref": "myvpcingressSubnet1Subnet82F0259C" + "Ref": "myvpcPublicSubnet1Subnet6BD75C12" } } }, @@ -138,12 +138,12 @@ }, "DefaultRoute": { "id": "DefaultRoute", - "path": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet1/DefaultRoute", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1/DefaultRoute", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Route", "aws:cdk:cloudformation:props": { "routeTableId": { - "Ref": "myvpcingressSubnet1RouteTableD6322DD5" + "Ref": "myvpcPublicSubnet1RouteTableF7E8D7F1" }, "destinationCidrBlock": "0.0.0.0/0", "gatewayId": { @@ -155,6 +155,54 @@ "fqn": "@aws-cdk/aws-ec2.CfnRoute", "version": "0.0.0" } + }, + "EIP": { + "id": "EIP", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1/NATGateway", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", + "aws:cdk:cloudformation:props": { + "subnetId": { + "Ref": "myvpcPublicSubnet1Subnet6BD75C12" + }, + "allocationId": { + "Fn::GetAtt": [ + "myvpcPublicSubnet1EIP88D18203", + "AllocationId" + ] + }, + "tags": [ + { + "key": "Name", + "value": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnNatGateway", + "version": "0.0.0" + } } }, "constructInfo": { @@ -162,13 +210,13 @@ "version": "0.0.0" } }, - "ingressSubnet2": { - "id": "ingressSubnet2", - "path": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet2", + "PublicSubnet2": { + "id": "PublicSubnet2", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2", "children": { "Subnet": { "id": "Subnet", - "path": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet2/Subnet", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2/Subnet", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", "aws:cdk:cloudformation:props": { @@ -183,12 +231,12 @@ } ] }, - "cidrBlock": "10.0.1.0/24", + "cidrBlock": "10.0.64.0/18", "mapPublicIpOnLaunch": true, "tags": [ { "key": "aws-cdk:subnet-name", - "value": "ingress" + "value": "Public" }, { "key": "aws-cdk:subnet-type", @@ -196,7 +244,7 @@ }, { "key": "Name", - "value": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet2" + "value": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2" } ] } @@ -208,15 +256,15 @@ }, "Acl": { "id": "Acl", - "path": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet2/Acl", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { "id": "RouteTable", - "path": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet2/RouteTable", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2/RouteTable", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", "aws:cdk:cloudformation:props": { @@ -226,7 +274,7 @@ "tags": [ { "key": "Name", - "value": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet2" + "value": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2" } ] } @@ -238,15 +286,15 @@ }, "RouteTableAssociation": { "id": "RouteTableAssociation", - "path": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet2/RouteTableAssociation", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2/RouteTableAssociation", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", "aws:cdk:cloudformation:props": { "routeTableId": { - "Ref": "myvpcingressSubnet2RouteTable2112B53A" + "Ref": "myvpcPublicSubnet2RouteTable9A4CA50C" }, "subnetId": { - "Ref": "myvpcingressSubnet2Subnet56945106" + "Ref": "myvpcPublicSubnet2Subnet844B7F05" } } }, @@ -257,12 +305,12 @@ }, "DefaultRoute": { "id": "DefaultRoute", - "path": "cdk-integ-lambda-python-vpc/my_vpc/ingressSubnet2/DefaultRoute", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2/DefaultRoute", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Route", "aws:cdk:cloudformation:props": { "routeTableId": { - "Ref": "myvpcingressSubnet2RouteTable2112B53A" + "Ref": "myvpcPublicSubnet2RouteTable9A4CA50C" }, "destinationCidrBlock": "0.0.0.0/0", "gatewayId": { @@ -274,6 +322,54 @@ "fqn": "@aws-cdk/aws-ec2.CfnRoute", "version": "0.0.0" } + }, + "EIP": { + "id": "EIP", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2/NATGateway", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", + "aws:cdk:cloudformation:props": { + "subnetId": { + "Ref": "myvpcPublicSubnet2Subnet844B7F05" + }, + "allocationId": { + "Fn::GetAtt": [ + "myvpcPublicSubnet2EIPA3AF827D", + "AllocationId" + ] + }, + "tags": [ + { + "key": "Name", + "value": "cdk-integ-lambda-python-vpc/my_vpc/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnNatGateway", + "version": "0.0.0" + } } }, "constructInfo": { @@ -281,6 +377,244 @@ "version": "0.0.0" } }, + "PrivateSubnet1": { + "id": "PrivateSubnet1", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "myvpc9455A260" + }, + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.128.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet1/Acl", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "myvpc9455A260" + }, + "tags": [ + { + "key": "Name", + "value": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "myvpcPrivateSubnet1RouteTable991B69A9" + }, + "subnetId": { + "Ref": "myvpcPrivateSubnet1SubnetAE3DECEE" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "myvpcPrivateSubnet1RouteTable991B69A9" + }, + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "myvpcPublicSubnet1NATGatewayD3DC5B8D" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet2": { + "id": "PrivateSubnet2", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "myvpc9455A260" + }, + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.192.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet2/Acl", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "myvpc9455A260" + }, + "tags": [ + { + "key": "Name", + "value": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "myvpcPrivateSubnet2RouteTableF2B44BF5" + }, + "subnetId": { + "Ref": "myvpcPrivateSubnet2SubnetE09939FB" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "cdk-integ-lambda-python-vpc/my_vpc/PrivateSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "myvpcPrivateSubnet2RouteTableF2B44BF5" + }, + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "myvpcPublicSubnet2NATGateway45472CCD" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.PrivateSubnet", + "version": "0.0.0" + } + }, "IGW": { "id": "IGW", "path": "cdk-integ-lambda-python-vpc/my_vpc/IGW", @@ -398,8 +732,8 @@ "id": "Stage", "path": "cdk-integ-lambda-python-vpc/my_handler/Code/Stage", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "AssetBucket": { @@ -460,7 +794,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7641c95c909cbd220aa45f8b7dca8606bd48b9a84f0c5d28fa697c90c810983b.zip" + "s3Key": "3b4e770c8242272e96f6faafd45d2446549a060a25dcce2d246445447e356ca9.zip" }, "role": { "Fn::GetAtt": [ @@ -473,10 +807,10 @@ "vpcConfig": { "subnetIds": [ { - "Ref": "myvpcingressSubnet1Subnet82F0259C" + "Ref": "myvpcPrivateSubnet1SubnetAE3DECEE" }, { - "Ref": "myvpcingressSubnet2Subnet56945106" + "Ref": "myvpcPrivateSubnet2SubnetE09939FB" } ], "securityGroupIds": [ @@ -501,24 +835,214 @@ "version": "0.0.0" } }, - "FunctionArn": { - "id": "FunctionArn", - "path": "cdk-integ-lambda-python-vpc/FunctionArn", + "Exports": { + "id": "Exports", + "path": "cdk-integ-lambda-python-vpc/Exports", + "children": { + "Output{\"Ref\":\"myhandlerD202FA8E\"}": { + "id": "Output{\"Ref\":\"myhandlerD202FA8E\"}", + "path": "cdk-integ-lambda-python-vpc/Exports/Output{\"Ref\":\"myhandlerD202FA8E\"}", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.95" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "lambda-python-vpc": { + "id": "lambda-python-vpc", + "path": "lambda-python-vpc", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "lambda-python-vpc/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "lambda-python-vpc/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "lambda-python-vpc/DefaultTest/DeployAssert", + "children": { + "LambdaInvoke431773224924ebf10c8a31d363a6bf16": { + "id": "LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "path": "lambda-python-vpc/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16", + "children": { + "SdkProvider": { + "id": "SdkProvider", + "path": "lambda-python-vpc/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/SdkProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "lambda-python-vpc/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/SdkProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.AssertionsProvider", + "version": "0.0.0" + } + }, + "Default": { + "id": "Default", + "path": "lambda-python-vpc/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default", + "children": { + "Default": { + "id": "Default", + "path": "lambda-python-vpc/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "Invoke": { + "id": "Invoke", + "path": "lambda-python-vpc/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/Invoke", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "AssertEqualsLambdainvoke": { + "id": "AssertEqualsLambdainvoke", + "path": "lambda-python-vpc/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke", + "children": { + "AssertionProvider": { + "id": "AssertionProvider", + "path": "lambda-python-vpc/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "lambda-python-vpc/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.AssertionsProvider", + "version": "0.0.0" + } + }, + "Default": { + "id": "Default", + "path": "lambda-python-vpc/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default", + "children": { + "Default": { + "id": "Default", + "path": "lambda-python-vpc/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "AssertionResults": { + "id": "AssertionResults", + "path": "lambda-python-vpc/DefaultTest/DeployAssert/LambdaInvoke431773224924ebf10c8a31d363a6bf16/AssertEqualsLambdainvoke/AssertionResults", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.EqualsAssertion", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.LambdaInvokeFunction", + "version": "0.0.0" + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81": { + "id": "SingletonFunction1488541a7b23466481b69b4408076b81", + "path": "lambda-python-vpc/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81", + "children": { + "Staging": { + "id": "Staging", + "path": "lambda-python-vpc/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Staging", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "lambda-python-vpc/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "lambda-python-vpc/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/integ.function.custom-build.ts b/packages/@aws-cdk/aws-lambda-python/test/integ.function.custom-build.ts index 4b584062317bf..f2b24641287e7 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/integ.function.custom-build.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/integ.function.custom-build.ts @@ -1,9 +1,7 @@ -// disabling update workflow because we don't want to include the assets in the snapshot -// python bundling changes the asset hash pretty frequently -/// !cdk-integ pragma:disable-update-workflow import * as path from 'path'; import { Runtime } from '@aws-cdk/aws-lambda'; -import { App, CfnOutput, DockerImage, Stack, StackProps } from '@aws-cdk/core'; +import { App, DockerImage, Stack, StackProps } from '@aws-cdk/core'; +import { IntegTest, ExpectedResult } from '@aws-cdk/integ-tests'; import { Construct } from 'constructs'; import * as lambda from '../lib'; @@ -13,6 +11,7 @@ import * as lambda from '../lib'; */ class TestStack extends Stack { + public readonly functionName: string; constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); @@ -22,13 +21,22 @@ class TestStack extends Stack { bundling: { image: DockerImage.fromBuild(path.join(entry)) }, runtime: Runtime.PYTHON_3_8, }); - - new CfnOutput(this, 'FunctionArn', { - value: fn.functionArn, - }); + this.functionName = fn.functionName; } } const app = new App(); -new TestStack(app, 'cdk-integ-lambda-custom-build'); +const testCase = new TestStack(app, 'cdk-integ-lambda-custom-build'); +const integ = new IntegTest(app, 'lambda-python-custom-build', { + testCases: [testCase], + stackUpdateWorkflow: false, +}); + +const invoke = integ.assertions.invokeFunction({ + functionName: testCase.functionName, +}); + +invoke.expect(ExpectedResult.objectLike({ + Payload: '200', +})); app.synth(); diff --git a/packages/@aws-cdk/aws-lambda-python/test/integ.function.nodeps.ts b/packages/@aws-cdk/aws-lambda-python/test/integ.function.nodeps.ts index 54d7eadd516c1..5dcf7bb572e11 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/integ.function.nodeps.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/integ.function.nodeps.ts @@ -1,6 +1,7 @@ import * as path from 'path'; import { Runtime } from '@aws-cdk/aws-lambda'; import { App, CfnOutput, Stack, StackProps } from '@aws-cdk/core'; +import { IntegTest, ExpectedResult } from '@aws-cdk/integ-tests'; import { Construct } from 'constructs'; import * as lambda from '../lib'; @@ -10,6 +11,7 @@ import * as lambda from '../lib'; */ class TestStack extends Stack { + public readonly functionName: string; constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); @@ -17,6 +19,7 @@ class TestStack extends Stack { entry: path.join(__dirname, 'lambda-handler-nodeps'), runtime: Runtime.PYTHON_3_8, }); + this.functionName = fn.functionName; new CfnOutput(this, 'FunctionArn', { value: fn.functionArn, @@ -25,5 +28,17 @@ class TestStack extends Stack { } const app = new App(); -new TestStack(app, 'cdk-integ-lambda-python'); +const testCase = new TestStack(app, 'integ-lambda-python-nodeps'); +const integ = new IntegTest(app, 'lambda-python-nodeps', { + testCases: [testCase], + stackUpdateWorkflow: false, +}); + +const invoke = integ.assertions.invokeFunction({ + functionName: testCase.functionName, +}); + +invoke.expect(ExpectedResult.objectLike({ + Payload: '200', +})); app.synth(); diff --git a/packages/@aws-cdk/aws-lambda-python/test/integ.function.pipenv.ts b/packages/@aws-cdk/aws-lambda-python/test/integ.function.pipenv.ts index 49f3fb0d8e23f..3d5a31dac63f9 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/integ.function.pipenv.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/integ.function.pipenv.ts @@ -3,7 +3,8 @@ /// !cdk-integ pragma:disable-update-workflow import * as path from 'path'; import { Runtime } from '@aws-cdk/aws-lambda'; -import { App, CfnOutput, Stack, StackProps } from '@aws-cdk/core'; +import { App, Stack, StackProps } from '@aws-cdk/core'; +import { IntegTest, ExpectedResult } from '@aws-cdk/integ-tests'; import { Construct } from 'constructs'; import * as lambda from '../lib'; @@ -13,27 +14,46 @@ import * as lambda from '../lib'; */ class TestStack extends Stack { + public readonly functionNames: string[] = []; constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); - const pythonFunctionInline = new lambda.PythonFunction(this, 'my_handler_inline', { + const pythonFunction39 = new lambda.PythonFunction(this, 'my_handler_inline', { entry: path.join(__dirname, 'lambda-handler-pipenv'), runtime: Runtime.PYTHON_3_9, }); - new CfnOutput(this, 'InlineFunctionName', { - value: pythonFunctionInline.functionName, - }); + this.functionNames.push(pythonFunction39.functionName); const pythonFunction38 = new lambda.PythonFunction(this, 'my_handler_python_38', { entry: path.join(__dirname, 'lambda-handler-pipenv'), runtime: Runtime.PYTHON_3_8, }); - new CfnOutput(this, 'Python38FunctionName', { - value: pythonFunction38.functionName, + this.functionNames.push(pythonFunction38.functionName); + + const pythonFunction37 = new lambda.PythonFunction(this, 'my_handler_python_37', { + entry: path.join(__dirname, 'lambda-handler-pipenv'), + runtime: Runtime.PYTHON_3_7, }); + this.functionNames.push(pythonFunction37.functionName); } } const app = new App(); -new TestStack(app, 'cdk-integ-lambda-python'); +const testCase = new TestStack(app, 'integ-lambda-python-pipenv'); +const integ = new IntegTest(app, 'pipenv', { + testCases: [testCase], + // disabling update workflow because we don't want to include the assets in the snapshot + // python bundling changes the asset hash pretty frequently + stackUpdateWorkflow: false, +}); + +testCase.functionNames.forEach(functionName => { + const invoke = integ.assertions.invokeFunction({ + functionName: functionName, + }); + + invoke.expect(ExpectedResult.objectLike({ + Payload: '200', + })); +}); app.synth(); diff --git a/packages/@aws-cdk/aws-lambda-python/test/integ.function.poetry.ts b/packages/@aws-cdk/aws-lambda-python/test/integ.function.poetry.ts index 3fecb2206eb73..162edff2db14c 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/integ.function.poetry.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/integ.function.poetry.ts @@ -1,7 +1,7 @@ import * as path from 'path'; import { Runtime } from '@aws-cdk/aws-lambda'; -import { App, CfnOutput, Stack, StackProps } from '@aws-cdk/core'; -import { IntegTest } from '@aws-cdk/integ-tests'; +import { App, Stack, StackProps } from '@aws-cdk/core'; +import { IntegTest, ExpectedResult } from '@aws-cdk/integ-tests'; import { Construct } from 'constructs'; import * as lambda from '../lib'; @@ -11,41 +11,49 @@ import * as lambda from '../lib'; */ class TestStack extends Stack { + public readonly functionNames: string[] = []; constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); - const pythonFunctionInline = new lambda.PythonFunction(this, 'my_handler_inline', { + const pythonFunction39 = new lambda.PythonFunction(this, 'my_handler_inline', { entry: path.join(__dirname, 'lambda-handler-poetry'), runtime: Runtime.PYTHON_3_9, }); - new CfnOutput(this, 'InlineFunctionName', { - value: pythonFunctionInline.functionName, - }); + this.functionNames.push(pythonFunction39.functionName); const pythonFunction38 = new lambda.PythonFunction(this, 'my_handler_python_38', { entry: path.join(__dirname, 'lambda-handler-poetry'), runtime: Runtime.PYTHON_3_8, }); - new CfnOutput(this, 'Python38FunctionName', { - value: pythonFunction38.functionName, - }); + this.functionNames.push(pythonFunction38.functionName); - new lambda.PythonFunction(this, 'my_handler_python_37', { + const pythonFunction37 = new lambda.PythonFunction(this, 'my_handler_python_37', { entry: path.join(__dirname, 'lambda-handler-poetry'), runtime: Runtime.PYTHON_3_7, }); + this.functionNames.push(pythonFunction37.functionName); } } const app = new App(); -const testCase = new TestStack(app, 'cdk-integ-lambda-python'); +const testCase = new TestStack(app, 'integ-lambda-python-poetry'); -new IntegTest(app, 'poetry', { +const integ = new IntegTest(app, 'poetry', { testCases: [testCase], // disabling update workflow because we don't want to include the assets in the snapshot // python bundling changes the asset hash pretty frequently stackUpdateWorkflow: false, }); +testCase.functionNames.forEach(functionName => { + const invoke = integ.assertions.invokeFunction({ + functionName: functionName, + }); + + invoke.expect(ExpectedResult.objectLike({ + Payload: '200', + })); +}); + app.synth(); diff --git a/packages/@aws-cdk/aws-lambda-python/test/integ.function.project.ts b/packages/@aws-cdk/aws-lambda-python/test/integ.function.project.ts index 535a684e67470..ee83939d11a5f 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/integ.function.project.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/integ.function.project.ts @@ -3,7 +3,8 @@ /// !cdk-integ pragma:disable-update-workflow import * as path from 'path'; import { Runtime } from '@aws-cdk/aws-lambda'; -import { App, CfnOutput, Stack, StackProps } from '@aws-cdk/core'; +import { App, Stack, StackProps } from '@aws-cdk/core'; +import { IntegTest, ExpectedResult } from '@aws-cdk/integ-tests'; import { Construct } from 'constructs'; import * as lambda from '../lib'; @@ -13,6 +14,7 @@ import * as lambda from '../lib'; */ class TestStack extends Stack { + public readonly functionName: string; constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); @@ -27,13 +29,22 @@ class TestStack extends Stack { }), ], }); - - new CfnOutput(this, 'FunctionArn', { - value: fn.functionArn, - }); + this.functionName = fn.functionName; } } const app = new App(); -new TestStack(app, 'cdk-integ-lambda-function-project'); +const testCase = new TestStack(app, 'cdk-integ-lambda-function-project'); +const integ = new IntegTest(app, 'lambda-python-project', { + testCases: [testCase], + stackUpdateWorkflow: false, +}); + +const invoke = integ.assertions.invokeFunction({ + functionName: testCase.functionName, +}); + +invoke.expect(ExpectedResult.objectLike({ + Payload: '200', +})); app.synth(); diff --git a/packages/@aws-cdk/aws-lambda-python/test/integ.function.py38.ts b/packages/@aws-cdk/aws-lambda-python/test/integ.function.py38.ts index 3acfba5cfab7c..e228ba5e38035 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/integ.function.py38.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/integ.function.py38.ts @@ -4,6 +4,7 @@ import * as path from 'path'; import { Runtime } from '@aws-cdk/aws-lambda'; import { App, CfnOutput, Stack, StackProps } from '@aws-cdk/core'; +import { IntegTest, ExpectedResult } from '@aws-cdk/integ-tests'; import { Construct } from 'constructs'; import * as lambda from '../lib'; @@ -13,6 +14,7 @@ import * as lambda from '../lib'; */ class TestStack extends Stack { + public readonly functionName: string; constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); @@ -20,6 +22,7 @@ class TestStack extends Stack { entry: path.join(__dirname, 'lambda-handler'), runtime: Runtime.PYTHON_3_8, }); + this.functionName = fn.functionName; new CfnOutput(this, 'FunctionArn', { value: fn.functionArn, @@ -28,5 +31,17 @@ class TestStack extends Stack { } const app = new App(); -new TestStack(app, 'cdk-integ-lambda-python-38'); +const testCase = new TestStack(app, 'cdk-integ-lambda-python-38'); +const integ = new IntegTest(app, 'lambda-python-38', { + testCases: [testCase], + stackUpdateWorkflow: false, +}); + +const invoke = integ.assertions.invokeFunction({ + functionName: testCase.functionName, +}); + +invoke.expect(ExpectedResult.objectLike({ + Payload: '200', +})); app.synth(); diff --git a/packages/@aws-cdk/aws-lambda-python/test/integ.function.sub.ts b/packages/@aws-cdk/aws-lambda-python/test/integ.function.sub.ts index 73ef4efe13228..59a637a16417d 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/integ.function.sub.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/integ.function.sub.ts @@ -1,9 +1,7 @@ -// disabling update workflow because we don't want to include the assets in the snapshot -// python bundling changes the asset hash pretty frequently -/// !cdk-integ pragma:disable-update-workflow import * as path from 'path'; import { Runtime } from '@aws-cdk/aws-lambda'; import { App, CfnOutput, Stack, StackProps } from '@aws-cdk/core'; +import { IntegTest, ExpectedResult } from '@aws-cdk/integ-tests'; import { Construct } from 'constructs'; import * as lambda from '../lib'; @@ -13,6 +11,7 @@ import * as lambda from '../lib'; */ class TestStack extends Stack { + public readonly functionName: string; constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); @@ -22,6 +21,7 @@ class TestStack extends Stack { handler: 'custom_handler', runtime: Runtime.PYTHON_3_8, }); + this.functionName = fn.functionName; new CfnOutput(this, 'FunctionArn', { value: fn.functionArn, @@ -30,5 +30,17 @@ class TestStack extends Stack { } const app = new App(); -new TestStack(app, 'cdk-integ-lambda-python'); +const testCase = new TestStack(app, 'integ-lambda-python-function-sub'); +const integ = new IntegTest(app, 'function-sub', { + testCases: [testCase], + stackUpdateWorkflow: false, +}); + +const invoke = integ.assertions.invokeFunction({ + functionName: testCase.functionName, +}); + +invoke.expect(ExpectedResult.objectLike({ + Payload: '200', +})); app.synth(); diff --git a/packages/@aws-cdk/aws-lambda-python/test/integ.function.ts b/packages/@aws-cdk/aws-lambda-python/test/integ.function.ts index c2d88d7ebf99a..e794c7afbb7a8 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/integ.function.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/integ.function.ts @@ -4,6 +4,7 @@ import * as path from 'path'; import { Runtime } from '@aws-cdk/aws-lambda'; import { App, CfnOutput, Stack, StackProps } from '@aws-cdk/core'; +import { IntegTest, ExpectedResult } from '@aws-cdk/integ-tests'; import { Construct } from 'constructs'; import * as lambda from '../lib'; @@ -13,6 +14,7 @@ import * as lambda from '../lib'; */ class TestStack extends Stack { + public readonly functionName: string; constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); @@ -20,6 +22,7 @@ class TestStack extends Stack { entry: path.join(__dirname, 'lambda-handler'), runtime: Runtime.PYTHON_3_9, }); + this.functionName = fn.functionName; new CfnOutput(this, 'FunctionArn', { value: fn.functionArn, @@ -28,5 +31,18 @@ class TestStack extends Stack { } const app = new App(); -new TestStack(app, 'cdk-integ-lambda-python'); +const testCase = new TestStack(app, 'integ-lambda-python-function'); +const integ = new IntegTest(app, 'lambda-python-function', { + testCases: [testCase], + stackUpdateWorkflow: false, +}); + +const invoke = integ.assertions.invokeFunction({ + functionName: testCase.functionName, +}); + +invoke.expect(ExpectedResult.objectLike({ + Payload: '200', +})); + app.synth(); diff --git a/packages/@aws-cdk/aws-lambda-python/test/integ.function.vpc.ts b/packages/@aws-cdk/aws-lambda-python/test/integ.function.vpc.ts index fe3defdc185f5..b1b25d021b3eb 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/integ.function.vpc.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/integ.function.vpc.ts @@ -2,9 +2,10 @@ // python bundling changes the asset hash pretty frequently /// !cdk-integ pragma:disable-update-workflow import * as path from 'path'; -import { Vpc, SubnetType } from '@aws-cdk/aws-ec2'; +import { Vpc } from '@aws-cdk/aws-ec2'; import { Runtime } from '@aws-cdk/aws-lambda'; -import { App, CfnOutput, Stack, StackProps } from '@aws-cdk/core'; +import { App, Stack, StackProps } from '@aws-cdk/core'; +import { IntegTest, ExpectedResult } from '@aws-cdk/integ-tests'; import { Construct } from 'constructs'; import * as lambda from '../lib'; @@ -14,29 +15,34 @@ import * as lambda from '../lib'; */ class TestStack extends Stack { + public readonly functionName: string; constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); - const vpc = new Vpc(this, 'my_vpc', { - natGateways: 0, - subnetConfiguration: [ - { cidrMask: 24, name: 'ingress', subnetType: SubnetType.PUBLIC }, - ], - }); + const vpc = new Vpc(this, 'my_vpc'); const fn = new lambda.PythonFunction(this, 'my_handler', { entry: path.join(__dirname, 'lambda-handler'), runtime: Runtime.PYTHON_3_9, vpc, - allowPublicSubnet: true, - }); - - new CfnOutput(this, 'FunctionArn', { - value: fn.functionArn, }); + this.functionName = fn.functionName; } } const app = new App(); -new TestStack(app, 'cdk-integ-lambda-python-vpc'); +const testCase = new TestStack(app, 'cdk-integ-lambda-python-vpc'); + +const integ = new IntegTest(app, 'lambda-python-vpc', { + testCases: [testCase], + stackUpdateWorkflow: false, +}); + +const invoke = integ.assertions.invokeFunction({ + functionName: testCase.functionName, +}); + +invoke.expect(ExpectedResult.objectLike({ + Payload: '200', +})); app.synth(); diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/asset.ab9c2b6025059cecbb1d54da74eb950315bc9fee8233e18822cefc8cff5806a0/requirements.txt b/packages/@aws-cdk/aws-lambda-python/test/lambda-handler-project/lambda/requirements.txt similarity index 100% rename from packages/@aws-cdk/aws-lambda-python/test/function.custom-build.integ.snapshot/asset.ab9c2b6025059cecbb1d54da74eb950315bc9fee8233e18822cefc8cff5806a0/requirements.txt rename to packages/@aws-cdk/aws-lambda-python/test/lambda-handler-project/lambda/requirements.txt diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/asset.c1175cf2b10c78c2687560b17053e3d51a3636b7aac017e713e5a586470606ff/.ignorefile b/packages/@aws-cdk/aws-lambda-python/test/lambda-handler-sub/inner/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-lambda-python/test/function.pipenv.integ.snapshot/asset.c1175cf2b10c78c2687560b17053e3d51a3636b7aac017e713e5a586470606ff/.ignorefile rename to packages/@aws-cdk/aws-lambda-python/test/lambda-handler-sub/inner/__init__.py diff --git a/packages/@aws-cdk/aws-lambda-python/test/lambda-handler-sub/inner/custom_index.py b/packages/@aws-cdk/aws-lambda-python/test/lambda-handler-sub/inner/custom_index.py index d7b2ce8db00e9..8ea5f42d80637 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/lambda-handler-sub/inner/custom_index.py +++ b/packages/@aws-cdk/aws-lambda-python/test/lambda-handler-sub/inner/custom_index.py @@ -1,5 +1,5 @@ from http import HTTPStatus -def handler(event, context): +def custom_handler(event, context): print('No dependencies') return HTTPStatus.OK.value diff --git a/packages/@aws-cdk/aws-lambda/README.md b/packages/@aws-cdk/aws-lambda/README.md index f12afc0c3d809..d5644331cec0d 100644 --- a/packages/@aws-cdk/aws-lambda/README.md +++ b/packages/@aws-cdk/aws-lambda/README.md @@ -632,6 +632,26 @@ fn.addEventSource(new eventsources.S3EventSource(bucket, { })); ``` +The following code adds an DynamoDB notification as an event source filtering insert events: + +```ts +import * as eventsources from '@aws-cdk/aws-lambda-event-sources'; +import * as dynamodb from '@aws-cdk/aws-dynamodb'; + +declare const fn: lambda.Function; +const table = new dynamodb.Table(this, 'Table', { + partitionKey: { + name: 'id', + type: dynamodb.AttributeType.STRING, + }, + stream: dynamodb.StreamViewType.NEW_IMAGE, +}); +fn.addEventSource(new eventsources.DynamoEventSource(table, { + startingPosition: lambda.StartingPosition.LATEST, + filters: [{ eventName: lambda.FilterRule.isEqual('INSERT') }], +})); +``` + See the documentation for the __@aws-cdk/aws-lambda-event-sources__ module for more details. ## Imported Lambdas diff --git a/packages/@aws-cdk/aws-lambda/lib/event-source-filter.ts b/packages/@aws-cdk/aws-lambda/lib/event-source-filter.ts new file mode 100644 index 0000000000000..50bce839123ba --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/lib/event-source-filter.ts @@ -0,0 +1,82 @@ +/** + * Filter rules for Lambda event filtering + */ +export class FilterRule { + /** + * Null comparison operator + */ + public static null(): string[] { + return []; + } + + /** + * Empty comparison operator + */ + public static empty(): string[] { + return ['']; + } + + /** + * Equals comparison operator + */ + public static isEqual(item: string | number): any { + if (typeof item === 'number') { + return [{ numeric: ['=', item] }]; + } + return [item]; + } + + /** + * Or comparison operator + */ + public static or(...elem: string[]): string[] { + return elem; + } + + /** + * Not equals comparison operator + */ + public static notEquals(elem: string): {[key:string]: string[]}[] { + return [{ 'anything-but': [elem] }]; + } + + /** + * Numeric range comparison operator + */ + public static between(first: number, second: number): {[key:string]: any[]}[] { + return [{ numeric: ['>', first, '<=', second] }]; + } + + /** + * Exists comparison operator + */ + public static exists(): {[key:string]: boolean}[] { + return [{ exists: true }]; + } + + /** + * Not exists comparison operator + */ + public static notExists(): {[key:string]: boolean}[] { + return [{ exists: false }]; + } + + /** + * Begins with comparison operator + */ + public static beginsWith(elem: string): {[key:string]: string}[] { + return [{ prefix: elem }]; + } +} + +/** + * Filter criteria for Lambda event filtering + */ +export class FilterCriteria { + /** + * Filter for event source + */ + public static filter(filter: {[key:string]: any}): {[key:string]: any} { + return { pattern: JSON.stringify(filter) }; + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/lib/event-source-mapping.ts b/packages/@aws-cdk/aws-lambda/lib/event-source-mapping.ts index 08e43ca31e310..9798a31c313f0 100644 --- a/packages/@aws-cdk/aws-lambda/lib/event-source-mapping.ts +++ b/packages/@aws-cdk/aws-lambda/lib/event-source-mapping.ts @@ -232,6 +232,14 @@ export interface EventSourceMappingOptions { * @default - none */ readonly sourceAccessConfigurations?: SourceAccessConfiguration[] + + /** + * Add filter criteria to Event Source + * @see https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventfiltering.html + * + * @default - none + */ + readonly filters?: Array<{[key: string]: any}> } /** @@ -366,6 +374,7 @@ export class EventSourceMapping extends cdk.Resource implements IEventSourceMapp tumblingWindowInSeconds: props.tumblingWindow?.toSeconds(), sourceAccessConfigurations: props.sourceAccessConfigurations?.map((o) => {return { type: o.type.type, uri: o.uri };}), selfManagedEventSource, + filterCriteria: props.filters ? { filters: props.filters }: undefined, selfManagedKafkaEventSourceConfig: props.kafkaBootstrapServers ? consumerGroupConfig : undefined, amazonManagedKafkaEventSourceConfig: props.eventSourceArn ? consumerGroupConfig : undefined, }); diff --git a/packages/@aws-cdk/aws-lambda/lib/index.ts b/packages/@aws-cdk/aws-lambda/lib/index.ts index a56224d5fba12..104afa76627a0 100644 --- a/packages/@aws-cdk/aws-lambda/lib/index.ts +++ b/packages/@aws-cdk/aws-lambda/lib/index.ts @@ -13,6 +13,7 @@ export * from './lambda-version'; export * from './singleton-lambda'; export * from './event-source'; export * from './event-source-mapping'; +export * from './event-source-filter'; export * from './destination'; export * from './event-invoke-config'; export * from './scalable-attribute-api'; diff --git a/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/cdk.out b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/cdk-integ-lambda-python.assets.json b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/lambda-test-assets.assets.json similarity index 60% rename from packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/cdk-integ-lambda-python.assets.json rename to packages/@aws-cdk/aws-lambda/test/cdk-integ.out/lambda-test-assets.assets.json index 4f05821bf51db..981e7b2f4cbc4 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.nodeps.integ.snapshot/cdk-integ-lambda-python.assets.json +++ b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/lambda-test-assets.assets.json @@ -1,28 +1,28 @@ { - "version": "20.0.0", + "version": "21.0.0", "files": { - "8c24af4ca0853fa9cd2372aa99864ccd1554740ac76e69773c82ba334df77f04": { + "9678c34eca93259d11f2d714177347afd66c50116e1e08996eff893d3ca81232": { "source": { - "path": "asset.8c24af4ca0853fa9cd2372aa99864ccd1554740ac76e69773c82ba334df77f04", + "path": "/home/marcio/marcio/aws-cdk/packages/@aws-cdk/aws-lambda/test/my-lambda-handler", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "8c24af4ca0853fa9cd2372aa99864ccd1554740ac76e69773c82ba334df77f04.zip", + "objectKey": "9678c34eca93259d11f2d714177347afd66c50116e1e08996eff893d3ca81232.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "281037e987baf7d3abbb443b0ceb1c7e3a6eaaade8bb12ca2c25c236a3c065d7": { + "b7318e1b9cb46d3116b3092ae8d67eeb76f991783ed974f75c3199bbcccc1847": { "source": { - "path": "cdk-integ-lambda-python.template.json", + "path": "lambda-test-assets.template.json", "packaging": "file" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "281037e987baf7d3abbb443b0ceb1c7e3a6eaaade8bb12ca2c25c236a3c065d7.json", + "objectKey": "b7318e1b9cb46d3116b3092ae8d67eeb76f991783ed974f75c3199bbcccc1847.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/lambda-test-assets.template.json b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/lambda-test-assets.template.json new file mode 100644 index 0000000000000..4bf977885b091 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/lambda-test-assets.template.json @@ -0,0 +1,91 @@ +{ + "Resources": { + "MyLambdaServiceRole4539ECB6": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "MyLambdaCCE802FB": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "9678c34eca93259d11f2d714177347afd66c50116e1e08996eff893d3ca81232.zip" + }, + "Role": { + "Fn::GetAtt": [ + "MyLambdaServiceRole4539ECB6", + "Arn" + ] + }, + "Handler": "index.main", + "Runtime": "python3.9" + }, + "DependsOn": [ + "MyLambdaServiceRole4539ECB6" + ] + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/manifest.json b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/manifest.json new file mode 100644 index 0000000000000..d517f7fd89f45 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/manifest.json @@ -0,0 +1,70 @@ +{ + "version": "21.0.0", + "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "lambda-test-assets.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "lambda-test-assets.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "lambda-test-assets": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "lambda-test-assets.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/b7318e1b9cb46d3116b3092ae8d67eeb76f991783ed974f75c3199bbcccc1847.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "lambda-test-assets.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "lambda-test-assets.assets" + ], + "metadata": { + "/lambda-test-assets/MyLambda/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyLambdaServiceRole4539ECB6" + } + ], + "/lambda-test-assets/MyLambda/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyLambdaCCE802FB" + } + ], + "/lambda-test-assets/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/lambda-test-assets/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "lambda-test-assets" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/tree.json b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/tree.json new file mode 100644 index 0000000000000..b16b292afcec8 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/tree.json @@ -0,0 +1,143 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.92" + } + }, + "lambda-test-assets": { + "id": "lambda-test-assets", + "path": "lambda-test-assets", + "children": { + "MyLambda": { + "id": "MyLambda", + "path": "lambda-test-assets/MyLambda", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "lambda-test-assets/MyLambda/ServiceRole", + "children": { + "Resource": { + "id": "Resource", + "path": "lambda-test-assets/MyLambda/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Code": { + "id": "Code", + "path": "lambda-test-assets/MyLambda/Code", + "children": { + "Stage": { + "id": "Stage", + "path": "lambda-test-assets/MyLambda/Code/Stage", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "lambda-test-assets/MyLambda/Code/AssetBucket", + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3-assets.Asset", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "lambda-test-assets/MyLambda/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "s3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "s3Key": "9678c34eca93259d11f2d714177347afd66c50116e1e08996eff893d3ca81232.zip" + }, + "role": { + "Fn::GetAtt": [ + "MyLambdaServiceRole4539ECB6", + "Arn" + ] + }, + "handler": "index.main", + "runtime": "python3.9" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/event-source-mapping.test.ts b/packages/@aws-cdk/aws-lambda/test/event-source-mapping.test.ts index d283c63f09c09..728cfd5d161ee 100644 --- a/packages/@aws-cdk/aws-lambda/test/event-source-mapping.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/event-source-mapping.test.ts @@ -1,6 +1,6 @@ import { Match, Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; -import { Code, EventSourceMapping, Function, Runtime, Alias, StartingPosition } from '../lib'; +import { Code, EventSourceMapping, Function, Runtime, Alias, StartingPosition, FilterRule, FilterCriteria } from '../lib'; let stack: cdk.Stack; let fn: Function; @@ -212,6 +212,71 @@ describe('event source mapping', () => { }); }); + test('filter with one pattern', () => { + const topicNameParam = new cdk.CfnParameter(stack, 'TopicNameParam', { + type: 'String', + }); + + let eventSourceArn = 'some-arn'; + + new EventSourceMapping(stack, 'test', { + target: fn, + eventSourceArn: eventSourceArn, + kafkaTopic: topicNameParam.valueAsString, + filters: [ + FilterCriteria.filter({ + numericEquals: FilterRule.isEqual(1), + }), + ], + }); + + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::EventSourceMapping', { + FilterCriteria: { + Filters: [ + { + Pattern: '{"numericEquals":[{"numeric":["=",1]}]}', + }, + ], + }, + }); + }); + + test('filter with more than one pattern', () => { + const topicNameParam = new cdk.CfnParameter(stack, 'TopicNameParam', { + type: 'String', + }); + + let eventSourceArn = 'some-arn'; + + new EventSourceMapping(stack, 'test', { + target: fn, + eventSourceArn: eventSourceArn, + kafkaTopic: topicNameParam.valueAsString, + filters: [ + FilterCriteria.filter({ + orFilter: FilterRule.or('one', 'two'), + stringEquals: FilterRule.isEqual('test'), + }), + FilterCriteria.filter({ + numericEquals: FilterRule.isEqual(1), + }), + ], + }); + + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::EventSourceMapping', { + FilterCriteria: { + Filters: [ + { + Pattern: '{"orFilter":["one","two"],"stringEquals":["test"]}', + }, + { + Pattern: '{"numericEquals":[{"numeric":["=",1]}]}', + }, + ], + }, + }); + }); + test('kafkaBootstrapServers appears in stack', () => { const topicNameParam = new cdk.CfnParameter(stack, 'TopicNameParam', { type: 'String', diff --git a/packages/@aws-cdk/aws-redshift/README.md b/packages/@aws-cdk/aws-redshift/README.md index 9c7897fb28e39..66af962185f72 100644 --- a/packages/@aws-cdk/aws-redshift/README.md +++ b/packages/@aws-cdk/aws-redshift/README.md @@ -300,6 +300,37 @@ cluster.addRotationMultiUser('MultiUserRotation', { }); ``` +## Adding Parameters + +You can add a parameter to a parameter group with`ClusterParameterGroup.addParameter()`. + +```ts +const params = new ClusterParameterGroup(stack, 'Params', { + description: 'desc', + parameters: { + require_ssl: 'true', + }, +}); + +params.addParameter('enable_user_activity_logging', 'true'); +``` + +Additionally, you can add a parameter to the cluster's associated parameter group with `Cluster.addToParameterGroup()`. If the cluster does not have an associated parameter group, a new parameter group is created. + +```ts +declare const vpc: ec2.Vpc; + +const cluster = new Cluster(this, 'Cluster', { + masterUser: { + masterUsername: 'admin', + masterPassword: cdk.SecretValue.unsafePlainText('tooshort'), + }, + vpc, +}); + +cluster.addToParameterGroup('enable_user_activity_logging', 'true'); +``` + ## Elastic IP If you configure your cluster to be publicly accessible, you can optionally select an *elastic IP address* to use for the external IP address. An elastic IP address is a static IP address that is associated with your AWS account. You can use an elastic IP address to connect to your cluster from outside the VPC. An elastic IP address gives you the ability to change your underlying configuration without affecting the IP address that clients use to connect to your cluster. This approach can be helpful for situations such as recovery after a failure. diff --git a/packages/@aws-cdk/aws-redshift/lib/cluster.ts b/packages/@aws-cdk/aws-redshift/lib/cluster.ts index f1d1a05c4903a..f888bc8cf309c 100644 --- a/packages/@aws-cdk/aws-redshift/lib/cluster.ts +++ b/packages/@aws-cdk/aws-redshift/lib/cluster.ts @@ -7,7 +7,7 @@ import { Duration, IResource, RemovalPolicy, Resource, SecretValue, Token } from import { Construct } from 'constructs'; import { DatabaseSecret } from './database-secret'; import { Endpoint } from './endpoint'; -import { IClusterParameterGroup } from './parameter-group'; +import { ClusterParameterGroup, IClusterParameterGroup } from './parameter-group'; import { CfnCluster } from './redshift.generated'; import { ClusterSubnetGroup, IClusterSubnetGroup } from './subnet-group'; @@ -360,6 +360,7 @@ export interface ClusterProps { * A new or imported clustered database. */ abstract class ClusterBase extends Resource implements ICluster { + /** * Name of the cluster */ @@ -405,7 +406,6 @@ export class Cluster extends ClusterBase { public readonly instanceIdentifiers: string[] = []; public readonly clusterEndpoint = new Endpoint(attrs.clusterEndpointAddress, attrs.clusterEndpointPort); } - return new Import(scope, id); } @@ -442,6 +442,16 @@ export class Cluster extends ClusterBase { */ private readonly vpcSubnets?: ec2.SubnetSelection; + /** + * The underlying CfnCluster + */ + private readonly cluster: CfnCluster; + + /** + * The cluster's parameter group + */ + protected parameterGroup?: IClusterParameterGroup; + constructor(scope: Construct, id: string, props: ClusterProps) { super(scope, id); @@ -449,6 +459,7 @@ export class Cluster extends ClusterBase { this.vpcSubnets = props.vpcSubnets ?? { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, }; + this.parameterGroup = props.parameterGroup; const removalPolicy = props.removalPolicy ?? RemovalPolicy.RETAIN; @@ -509,7 +520,7 @@ export class Cluster extends ClusterBase { ); } - const cluster = new CfnCluster(this, 'Resource', { + this.cluster = new CfnCluster(this, 'Resource', { // Basic allowVersionUpgrade: true, automatedSnapshotRetentionPeriod: 1, @@ -538,15 +549,15 @@ export class Cluster extends ClusterBase { elasticIp: props.elasticIp, }); - cluster.applyRemovalPolicy(removalPolicy, { + this.cluster.applyRemovalPolicy(removalPolicy, { applyToUpdateReplacePolicy: true, }); - this.clusterName = cluster.ref; + this.clusterName = this.cluster.ref; // create a number token that represents the port of the cluster - const portAttribute = Token.asNumber(cluster.attrEndpointPort); - this.clusterEndpoint = new Endpoint(cluster.attrEndpointAddress, portAttribute); + const portAttribute = Token.asNumber(this.cluster.attrEndpointPort); + this.clusterEndpoint = new Endpoint(this.cluster.attrEndpointAddress, portAttribute); if (secret) { this.secret = secret.attach(this); @@ -619,4 +630,26 @@ export class Cluster extends ClusterBase { return nodeCount; } } + + /** + * Adds a parameter to the Clusters' parameter group + * + * @param name the parameter name + * @param value the parameter name + */ + public addToParameterGroup(name: string, value: string): void { + if (!this.parameterGroup) { + const param: { [name: string]: string } = {}; + param[name] = value; + this.parameterGroup = new ClusterParameterGroup(this, 'ParameterGroup', { + description: this.cluster.clusterIdentifier ? `Parameter Group for the ${this.cluster.clusterIdentifier} Redshift cluster` : 'Cluster parameter group for family redshift-1.0', + parameters: param, + }); + this.cluster.clusterParameterGroupName = this.parameterGroup.clusterParameterGroupName; + } else if (this.parameterGroup instanceof ClusterParameterGroup) { + this.parameterGroup.addParameter(name, value); + } else { + throw new Error('Cannot add a parameter to an imported parameter group.'); + } + } } diff --git a/packages/@aws-cdk/aws-redshift/lib/parameter-group.ts b/packages/@aws-cdk/aws-redshift/lib/parameter-group.ts index 7fb570bc23ce6..831b79d42dc46 100644 --- a/packages/@aws-cdk/aws-redshift/lib/parameter-group.ts +++ b/packages/@aws-cdk/aws-redshift/lib/parameter-group.ts @@ -18,6 +18,7 @@ export interface IClusterParameterGroup extends IResource { * A new cluster or instance parameter group */ abstract class ClusterParameterGroupBase extends Resource implements IClusterParameterGroup { + /** * The name of the parameter group */ @@ -62,17 +63,46 @@ export class ClusterParameterGroup extends ClusterParameterGroupBase { */ public readonly clusterParameterGroupName: string; + /** + * The parameters in the parameter group + */ + readonly parameters: { [name: string]: string }; + + /** + * The underlying CfnClusterParameterGroup + */ + private readonly resource: CfnClusterParameterGroup; + constructor(scope: Construct, id: string, props: ClusterParameterGroupProps) { super(scope, id); - - const resource = new CfnClusterParameterGroup(this, 'Resource', { + this.parameters = props.parameters; + this.resource = new CfnClusterParameterGroup(this, 'Resource', { description: props.description || 'Cluster parameter group for family redshift-1.0', parameterGroupFamily: 'redshift-1.0', - parameters: Object.entries(props.parameters).map(([name, value]) => { - return { parameterName: name, parameterValue: value }; - }), + parameters: this.parseParameters(), }); - this.clusterParameterGroupName = resource.ref; + this.clusterParameterGroupName = this.resource.ref; + } + private parseParameters(): any { + return Object.entries(this.parameters).map(([name, value]) => { + return { parameterName: name, parameterValue: value }; + }); + } + + /** + * Adds a parameter to the parameter group + * + * @param name the parameter name + * @param value the parameter name + */ + public addParameter(name: string, value: string): void { + const existingValue = Object.entries(this.parameters).find(([key, _]) => key === name)?.[1]; + if (existingValue === undefined) { + this.parameters[name] = value; + this.resource.parameters = this.parseParameters(); + } else if (existingValue !== value) { + throw new Error(`The parameter group already contains the parameter "${name}", but with a different value (Given: ${value}, Existing: ${existingValue}).`); + } } } diff --git a/packages/@aws-cdk/aws-redshift/test/cluster.test.ts b/packages/@aws-cdk/aws-redshift/test/cluster.test.ts index 703abd29e1e84..49f52e91dadb3 100644 --- a/packages/@aws-cdk/aws-redshift/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-redshift/test/cluster.test.ts @@ -253,27 +253,116 @@ test('create an encrypted cluster with custom KMS key', () => { }, }); }); +describe('parameter group', () => { + test('cluster instantiated with parameter group', () => { + // WHEN + const group = new ClusterParameterGroup(stack, 'Params', { + description: 'bye', + parameters: { + param: 'value', + }, + }); + + new Cluster(stack, 'Redshift', { + masterUser: { + masterUsername: 'admin', + }, + vpc, + parameterGroup: group, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Redshift::Cluster', { + ClusterParameterGroupName: { Ref: 'ParamsA8366201' }, + }); -test('cluster with parameter group', () => { - // WHEN - const group = new ClusterParameterGroup(stack, 'Params', { - description: 'bye', - parameters: { - param: 'value', - }, }); - new Cluster(stack, 'Redshift', { - masterUser: { - masterUsername: 'admin', - }, - vpc, - parameterGroup: group, + test('Adding to the cluster parameter group on a cluster not instantiated with a parameter group', () => { + + // WHEN + const cluster = new Cluster(stack, 'Redshift', { + clusterName: 'foobar', + masterUser: { + masterUsername: 'admin', + }, + vpc, + }); + + cluster.addToParameterGroup('foo', 'bar'); + + const template = Template.fromStack(stack); + template.hasResourceProperties('AWS::Redshift::Cluster', { + ClusterParameterGroupName: { Ref: Match.anyValue() }, + }); + + template.hasResourceProperties('AWS::Redshift::ClusterParameterGroup', { + Description: 'Parameter Group for the foobar Redshift cluster', + ParameterGroupFamily: 'redshift-1.0', + Parameters: [ + { + ParameterName: 'foo', + ParameterValue: 'bar', + }, + ], + }); }); - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::Redshift::Cluster', { - ClusterParameterGroupName: { Ref: 'ParamsA8366201' }, + test('Adding to the cluster parameter group on a cluster instantiated with a parameter group', () => { + + // WHEN + const group = new ClusterParameterGroup(stack, 'Params', { + description: 'lorem ipsum', + parameters: { + param: 'value', + }, + }); + + const cluster = new Cluster(stack, 'Redshift', { + masterUser: { + masterUsername: 'admin', + }, + vpc, + parameterGroup: group, + }); + cluster.addToParameterGroup('foo', 'bar'); + + const template = Template.fromStack(stack); + template.hasResourceProperties('AWS::Redshift::Cluster', { + ClusterParameterGroupName: { Ref: Match.anyValue() }, + }); + + template.hasResourceProperties('AWS::Redshift::ClusterParameterGroup', { + Description: 'lorem ipsum', + ParameterGroupFamily: 'redshift-1.0', + Parameters: [ + { + ParameterName: 'param', + ParameterValue: 'value', + }, + { + ParameterName: 'foo', + ParameterValue: 'bar', + }, + ], + }); + }); + + test('Adding a parameter to an IClusterParameterGroup', () => { + // GIVEN + const cluster = new Cluster(stack, 'Redshift', { + clusterName: 'foobar', + parameterGroup: ClusterParameterGroup.fromClusterParameterGroupName(stack, 'Params', 'foo'), + masterUser: { + masterUsername: 'admin', + }, + vpc, + }); + + // WHEN + expect(() => cluster.addToParameterGroup('param', 'value2')) + // THEN + .toThrowError('Cannot add a parameter to an imported parameter group'); }); }); @@ -374,7 +463,7 @@ test('throws validation error when trying to set encryptionKey without enabling // THEN expect(() => { - new Cluster(stack, 'Redshift', props ); + new Cluster(stack, 'Redshift', props); }).toThrowError(); }); diff --git a/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/aws-cdk-redshift-cluster-database.assets.json b/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/aws-cdk-redshift-cluster-database.assets.json index 8345a0b1525bc..f92a39bfbbcef 100644 --- a/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/aws-cdk-redshift-cluster-database.assets.json +++ b/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/aws-cdk-redshift-cluster-database.assets.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "21.0.0", "files": { "fb53353ae3322d38cf92fc2d8a73910a88c06a725900f0815aeaab985e6a19e3": { "source": { @@ -27,7 +27,7 @@ } } }, - "824f9ae87e8bb069d7316bd7955079be850bbe42b32fc16c6c57738078b57296": { + "784177efbde5b0ae9662ffc9f5f85895be269347870d0564efaa1281f8a1c38e": { "source": { "path": "aws-cdk-redshift-cluster-database.template.json", "packaging": "file" @@ -35,7 +35,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "824f9ae87e8bb069d7316bd7955079be850bbe42b32fc16c6c57738078b57296.json", + "objectKey": "784177efbde5b0ae9662ffc9f5f85895be269347870d0564efaa1281f8a1c38e.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/aws-cdk-redshift-cluster-database.template.json b/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/aws-cdk-redshift-cluster-database.template.json index b4677ceaf31b1..2d14182a7f2ad 100644 --- a/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/aws-cdk-redshift-cluster-database.template.json +++ b/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/aws-cdk-redshift-cluster-database.template.json @@ -565,6 +565,9 @@ "NodeType": "dc2.large", "AllowVersionUpgrade": true, "AutomatedSnapshotRetentionPeriod": 1, + "ClusterParameterGroupName": { + "Ref": "ClusterParameterGroup879806FD" + }, "ClusterSubnetGroupName": { "Ref": "ClusterSubnetsDCFA5CB7" }, @@ -586,6 +589,21 @@ "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" }, + "ClusterParameterGroup879806FD": { + "Type": "AWS::Redshift::ClusterParameterGroup", + "Properties": { + "Description": "Cluster parameter group for family redshift-1.0", + "ParameterGroupFamily": "redshift-1.0", + "Parameters": [ + { + "ParameterName": "enable_user_activity_logging", + "ParameterValue": "true" + } + ] + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, "UserSecretE2C04A69": { "Type": "AWS::SecretsManager::Secret", "Properties": { diff --git a/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/cdk.out index 588d7b269d34f..8ecc185e9dbee 100644 --- a/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/integ.json b/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/integ.json index a0f6a09b6ba58..0920057138199 100644 --- a/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/integ.json +++ b/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "21.0.0", "testCases": { "integ.database": { "stacks": [ diff --git a/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/manifest.json index 65efefc2bab16..fe9068d22e8a7 100644 --- a/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "21.0.0", "artifacts": { "Tree": { "type": "cdk:tree", @@ -23,7 +23,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/824f9ae87e8bb069d7316bd7955079be850bbe42b32fc16c6c57738078b57296.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/784177efbde5b0ae9662ffc9f5f85895be269347870d0564efaa1281f8a1c38e.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -213,6 +213,15 @@ "data": "ClusterEB0386A7" } ], + "/aws-cdk-redshift-cluster-database/Cluster/ParameterGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ClusterParameterGroup879806FD", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" + ] + } + ], "/aws-cdk-redshift-cluster-database/User/Secret/Resource": [ { "type": "aws:cdk:logicalId", diff --git a/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/tree.json b/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/tree.json index c10837094826a..1f4c6c4140f6b 100644 --- a/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-redshift/test/database.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.92" } }, "aws-cdk-redshift-cluster-database": { @@ -91,8 +91,8 @@ "id": "Acl", "path": "aws-cdk-redshift-cluster-database/Vpc/PublicSubnet1/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -258,8 +258,8 @@ "id": "Acl", "path": "aws-cdk-redshift-cluster-database/Vpc/PublicSubnet2/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -425,8 +425,8 @@ "id": "Acl", "path": "aws-cdk-redshift-cluster-database/Vpc/PrivateSubnet1/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -544,8 +544,8 @@ "id": "Acl", "path": "aws-cdk-redshift-cluster-database/Vpc/PrivateSubnet2/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -874,6 +874,9 @@ "nodeType": "dc2.large", "allowVersionUpgrade": true, "automatedSnapshotRetentionPeriod": 1, + "clusterParameterGroupName": { + "Ref": "ClusterParameterGroup879806FD" + }, "clusterSubnetGroupName": { "Ref": "ClusterSubnetsDCFA5CB7" }, @@ -897,6 +900,37 @@ "fqn": "@aws-cdk/aws-redshift.CfnCluster", "version": "0.0.0" } + }, + "ParameterGroup": { + "id": "ParameterGroup", + "path": "aws-cdk-redshift-cluster-database/Cluster/ParameterGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-redshift-cluster-database/Cluster/ParameterGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Redshift::ClusterParameterGroup", + "aws:cdk:cloudformation:props": { + "description": "Cluster parameter group for family redshift-1.0", + "parameterGroupFamily": "redshift-1.0", + "parameters": [ + { + "parameterName": "enable_user_activity_logging", + "parameterValue": "true" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-redshift.CfnClusterParameterGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-redshift.ClusterParameterGroup", + "version": "0.0.0" + } } }, "constructInfo": { @@ -1104,8 +1138,8 @@ "id": "Stage", "path": "aws-cdk-redshift-cluster-database/User/Resource/Provider/framework-onEvent/Code/Stage", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "AssetBucket": { @@ -1181,20 +1215,20 @@ "id": "Default", "path": "aws-cdk-redshift-cluster-database/User/Resource/Resource/Default", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.92" } }, "TablePrivileges": { @@ -1338,8 +1372,8 @@ "id": "Stage", "path": "aws-cdk-redshift-cluster-database/User/TablePrivileges/Resource/Provider/framework-onEvent/Code/Stage", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "AssetBucket": { @@ -1415,26 +1449,26 @@ "id": "Default", "path": "aws-cdk-redshift-cluster-database/User/TablePrivileges/Resource/Resource/Default", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.92" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.92" } } }, @@ -1561,8 +1595,8 @@ "id": "Stage", "path": "aws-cdk-redshift-cluster-database/Query Redshift Database3de5bea727da479686625efb56431b5f/Code/Stage", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "AssetBucket": { @@ -1754,8 +1788,8 @@ "id": "Stage", "path": "aws-cdk-redshift-cluster-database/Table/Resource/Provider/framework-onEvent/Code/Stage", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "AssetBucket": { @@ -1831,20 +1865,20 @@ "id": "Default", "path": "aws-cdk-redshift-cluster-database/Table/Resource/Resource/Default", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.92" } } }, @@ -1855,14 +1889,14 @@ } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-redshift/test/integ.database.ts b/packages/@aws-cdk/aws-redshift/test/integ.database.ts index c2a362310cf5c..45a67f26f499e 100644 --- a/packages/@aws-cdk/aws-redshift/test/integ.database.ts +++ b/packages/@aws-cdk/aws-redshift/test/integ.database.ts @@ -31,6 +31,8 @@ const cluster = new redshift.Cluster(stack, 'Cluster', { encryptionKey: new kms.Key(stack, 'custom-kms-key'), }); +cluster.addToParameterGroup('enable_user_activity_logging', 'true'); + const databaseOptions = { cluster: cluster, databaseName: databaseName, @@ -47,5 +49,4 @@ const table = new redshift.Table(stack, 'Table', { sortStyle: redshift.TableSortStyle.INTERLEAVED, }); table.grant(user, redshift.TableAction.INSERT, redshift.TableAction.DELETE); - app.synth(); diff --git a/packages/@aws-cdk/aws-redshift/test/parameter-group.test.ts b/packages/@aws-cdk/aws-redshift/test/parameter-group.test.ts index 1853fc0f5baf5..115c19cc603a8 100644 --- a/packages/@aws-cdk/aws-redshift/test/parameter-group.test.ts +++ b/packages/@aws-cdk/aws-redshift/test/parameter-group.test.ts @@ -26,4 +26,78 @@ test('create a cluster parameter group', () => { ], }); +}); + +describe('Adding parameters to an existing group', () => { + test('Adding a new parameter', () => { + // GIVEN + const stack = new cdk.Stack(); + const params = new ClusterParameterGroup(stack, 'Params', { + description: 'desc', + parameters: { + param: 'value', + }, + }); + + // WHEN + params.addParameter('param2', 'value2'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Redshift::ClusterParameterGroup', { + Description: 'desc', + ParameterGroupFamily: 'redshift-1.0', + Parameters: [ + { + ParameterName: 'param', + ParameterValue: 'value', + }, + { + ParameterName: 'param2', + ParameterValue: 'value2', + }, + ], + }); + }); + + test('Adding an existing named parameter with the same value', () => { + // GIVEN + const stack = new cdk.Stack(); + const params = new ClusterParameterGroup(stack, 'Params', { + description: 'desc', + parameters: { + param: 'value', + }, + }); + + // WHEN + params.addParameter('param', 'value'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Redshift::ClusterParameterGroup', { + Description: 'desc', + ParameterGroupFamily: 'redshift-1.0', + Parameters: [ + { + ParameterName: 'param', + ParameterValue: 'value', + }, + ], + }); + }); + + test('Adding an existing named parameter with a different value', () => { + // GIVEN + const stack = new cdk.Stack(); + const params = new ClusterParameterGroup(stack, 'Params', { + description: 'desc', + parameters: { + param: 'value', + }, + }); + + // WHEN + expect(() => params.addParameter('param', 'value2')) + // THEN + .toThrowError('The parameter group already contains the parameter'); + }); }); \ No newline at end of file diff --git a/packages/@aws-cdk/integ-runner/test/test-data/test-with-snapshot-assets-diff.integ.snapshot/manifest.json b/packages/@aws-cdk/integ-runner/test/test-data/test-with-snapshot-assets-diff.integ.snapshot/manifest.json index d5518ce4bd0e1..0d7e598bc5bd2 100644 --- a/packages/@aws-cdk/integ-runner/test/test-data/test-with-snapshot-assets-diff.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/integ-runner/test/test-data/test-with-snapshot-assets-diff.integ.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "21.0.0", "artifacts": { "Tree": { "type": "cdk:tree", diff --git a/packages/@aws-cdk/integ-runner/test/test-data/test-with-snapshot-assets.integ.snapshot/manifest.json b/packages/@aws-cdk/integ-runner/test/test-data/test-with-snapshot-assets.integ.snapshot/manifest.json index 7c2c6d4d8cdce..606c37571a711 100644 --- a/packages/@aws-cdk/integ-runner/test/test-data/test-with-snapshot-assets.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/integ-runner/test/test-data/test-with-snapshot-assets.integ.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "21.0.0", "artifacts": { "Tree": { "type": "cdk:tree", diff --git a/packages/@aws-cdk/integ-runner/test/test-data/test-with-snapshot.integ.snapshot/manifest.json b/packages/@aws-cdk/integ-runner/test/test-data/test-with-snapshot.integ.snapshot/manifest.json index 7b8ed0311e8f0..5c9fd61ecec9f 100644 --- a/packages/@aws-cdk/integ-runner/test/test-data/test-with-snapshot.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/integ-runner/test/test-data/test-with-snapshot.integ.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "21.0.0", "artifacts": { "Tree": { "type": "cdk:tree", diff --git a/packages/@aws-cdk/integ-tests/lib/assertions/assertions.ts b/packages/@aws-cdk/integ-tests/lib/assertions/assertions.ts index 507d6c1d158cc..6442c07318aee 100644 --- a/packages/@aws-cdk/integ-tests/lib/assertions/assertions.ts +++ b/packages/@aws-cdk/integ-tests/lib/assertions/assertions.ts @@ -1,6 +1,7 @@ import { CustomResource, CfnOutput } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { ExpectedResult, ActualResult } from './common'; +import { md5hash } from './private/hash'; import { AssertionRequest, AssertionsProvider, ASSERT_RESOURCE_TYPE } from './providers'; /** @@ -60,6 +61,6 @@ export class EqualsAssertion extends Construct { new CfnOutput(this, 'AssertionResults', { value: this.result, - }).overrideLogicalId(`AssertionResults${id}`); + }).overrideLogicalId(`AssertionResults${id}${md5hash({ actual: props.actual.result, expected: props.expected.result })}`); } } diff --git a/packages/aws-cdk/lib/init-templates/app/csharp/add-project.hook.ts b/packages/aws-cdk/lib/init-templates/app/csharp/add-project.hook.ts index c839c1e01db08..ad074041fab32 100644 --- a/packages/aws-cdk/lib/init-templates/app/csharp/add-project.hook.ts +++ b/packages/aws-cdk/lib/init-templates/app/csharp/add-project.hook.ts @@ -1,33 +1,13 @@ -import * as child_process from 'child_process'; import * as path from 'path'; import { InvokeHook } from '../../../init'; +import { shell } from '../../../os'; export const invoke: InvokeHook = async (targetDirectory: string) => { const slnPath = path.join(targetDirectory, 'src', '%name.PascalCased%.sln'); const csprojPath = path.join(targetDirectory, 'src', '%name.PascalCased%', '%name.PascalCased%.csproj'); - - const child = child_process.spawn('dotnet', ['sln', slnPath, 'add', csprojPath], { - // Need this for Windows where we want .cmd and .bat to be found as well. - shell: true, - stdio: ['ignore', 'pipe', 'inherit'], - }); - - await new Promise((resolve, reject) => { - const stdout = new Array(); - - child.stdout.on('data', chunk => { - process.stdout.write(chunk); - stdout.push(chunk); - }); - - child.once('error', reject); - - child.once('exit', code => { - if (code === 0) { - resolve(Buffer.concat(stdout).toString('utf-8')); - } else { - reject(new Error(`Could not add project %name.PascalCased%.csproj to solution %name.PascalCased%.sln. Error code: ${code}`)); - } - }); - }); + try { + await shell(['dotnet', 'sln', slnPath, 'add', csprojPath]); + } catch (e) { + throw new Error(`Could not add project %name.PascalCased%.csproj to solution %name.PascalCased%.sln. ${e.message}`); + } }; diff --git a/packages/aws-cdk/lib/init-templates/app/fsharp/add-project.hook.ts b/packages/aws-cdk/lib/init-templates/app/fsharp/add-project.hook.ts index efeed98d57ee2..e3cae76dba992 100644 --- a/packages/aws-cdk/lib/init-templates/app/fsharp/add-project.hook.ts +++ b/packages/aws-cdk/lib/init-templates/app/fsharp/add-project.hook.ts @@ -1,33 +1,13 @@ -import * as child_process from 'child_process'; import * as path from 'path'; import { InvokeHook } from '../../../init'; +import { shell } from '../../../os'; export const invoke: InvokeHook = async (targetDirectory: string) => { const slnPath = path.join(targetDirectory, 'src', '%name.PascalCased%.sln'); const fsprojPath = path.join(targetDirectory, 'src', '%name.PascalCased%', '%name.PascalCased%.fsproj'); - - const child = child_process.spawn('dotnet', ['sln', slnPath, 'add', fsprojPath], { - // Need this for Windows where we want .cmd and .bat to be found as well. - shell: true, - stdio: ['ignore', 'pipe', 'inherit'], - }); - - await new Promise((resolve, reject) => { - const stdout = new Array(); - - child.stdout.on('data', chunk => { - process.stdout.write(chunk); - stdout.push(chunk); - }); - - child.once('error', reject); - - child.once('exit', code => { - if (code === 0) { - resolve(Buffer.concat(stdout).toString('utf-8')); - } else { - reject(new Error(`Could not add project %name.PascalCased%.fsproj to solution %name.PascalCased%.sln. Error code: ${code}`)); - } - }); - }); + try { + await shell(['dotnet', 'sln', slnPath, 'add', fsprojPath]); + } catch (e) { + throw new Error(`Could not add project %name.PascalCased%.fsproj to solution %name.PascalCased%.sln. ${e.message}`); + } }; diff --git a/packages/aws-cdk/lib/init-templates/sample-app/csharp/add-project.hook.ts b/packages/aws-cdk/lib/init-templates/sample-app/csharp/add-project.hook.ts index c839c1e01db08..ad074041fab32 100644 --- a/packages/aws-cdk/lib/init-templates/sample-app/csharp/add-project.hook.ts +++ b/packages/aws-cdk/lib/init-templates/sample-app/csharp/add-project.hook.ts @@ -1,33 +1,13 @@ -import * as child_process from 'child_process'; import * as path from 'path'; import { InvokeHook } from '../../../init'; +import { shell } from '../../../os'; export const invoke: InvokeHook = async (targetDirectory: string) => { const slnPath = path.join(targetDirectory, 'src', '%name.PascalCased%.sln'); const csprojPath = path.join(targetDirectory, 'src', '%name.PascalCased%', '%name.PascalCased%.csproj'); - - const child = child_process.spawn('dotnet', ['sln', slnPath, 'add', csprojPath], { - // Need this for Windows where we want .cmd and .bat to be found as well. - shell: true, - stdio: ['ignore', 'pipe', 'inherit'], - }); - - await new Promise((resolve, reject) => { - const stdout = new Array(); - - child.stdout.on('data', chunk => { - process.stdout.write(chunk); - stdout.push(chunk); - }); - - child.once('error', reject); - - child.once('exit', code => { - if (code === 0) { - resolve(Buffer.concat(stdout).toString('utf-8')); - } else { - reject(new Error(`Could not add project %name.PascalCased%.csproj to solution %name.PascalCased%.sln. Error code: ${code}`)); - } - }); - }); + try { + await shell(['dotnet', 'sln', slnPath, 'add', csprojPath]); + } catch (e) { + throw new Error(`Could not add project %name.PascalCased%.csproj to solution %name.PascalCased%.sln. ${e.message}`); + } }; diff --git a/packages/aws-cdk/lib/init-templates/sample-app/fsharp/add-project.hook.ts b/packages/aws-cdk/lib/init-templates/sample-app/fsharp/add-project.hook.ts index efeed98d57ee2..e3cae76dba992 100644 --- a/packages/aws-cdk/lib/init-templates/sample-app/fsharp/add-project.hook.ts +++ b/packages/aws-cdk/lib/init-templates/sample-app/fsharp/add-project.hook.ts @@ -1,33 +1,13 @@ -import * as child_process from 'child_process'; import * as path from 'path'; import { InvokeHook } from '../../../init'; +import { shell } from '../../../os'; export const invoke: InvokeHook = async (targetDirectory: string) => { const slnPath = path.join(targetDirectory, 'src', '%name.PascalCased%.sln'); const fsprojPath = path.join(targetDirectory, 'src', '%name.PascalCased%', '%name.PascalCased%.fsproj'); - - const child = child_process.spawn('dotnet', ['sln', slnPath, 'add', fsprojPath], { - // Need this for Windows where we want .cmd and .bat to be found as well. - shell: true, - stdio: ['ignore', 'pipe', 'inherit'], - }); - - await new Promise((resolve, reject) => { - const stdout = new Array(); - - child.stdout.on('data', chunk => { - process.stdout.write(chunk); - stdout.push(chunk); - }); - - child.once('error', reject); - - child.once('exit', code => { - if (code === 0) { - resolve(Buffer.concat(stdout).toString('utf-8')); - } else { - reject(new Error(`Could not add project %name.PascalCased%.fsproj to solution %name.PascalCased%.sln. Error code: ${code}`)); - } - }); - }); + try { + await shell(['dotnet', 'sln', slnPath, 'add', fsprojPath]); + } catch (e) { + throw new Error(`Could not add project %name.PascalCased%.fsproj to solution %name.PascalCased%.sln. ${e.message}`); + } }; diff --git a/packages/aws-cdk/lib/init.ts b/packages/aws-cdk/lib/init.ts index 0a6d1dc0cf458..e5ecef421cde4 100644 --- a/packages/aws-cdk/lib/init.ts +++ b/packages/aws-cdk/lib/init.ts @@ -69,11 +69,12 @@ function pythonExecutable() { return python; } const INFO_DOT_JSON = 'info.json'; +const HOOK_DIR_PREFIX = 'tmp'; export class InitTemplate { public static async fromName(templatesDir: string, name: string) { const basePath = path.join(templatesDir, name); - const languages = (await listDirectory(basePath)).filter(f => f !== INFO_DOT_JSON); + const languages = (await listDirectory(basePath)); const info = await fs.readJson(path.join(basePath, INFO_DOT_JSON)); return new InitTemplate(basePath, name, languages, info); } @@ -117,6 +118,9 @@ export class InitTemplate { name: decamelize(path.basename(path.resolve(targetDirectory))), }; + const sourceDirectory = path.join(this.basePath, language); + const hookTempDirectory = path.join(this.basePath, `${HOOK_DIR_PREFIX}-${projectInfo.name}`); + const hookContext: HookContext = { substitutePlaceholdersIn: async (...fileNames: string[]) => { for (const fileName of fileNames) { @@ -127,28 +131,31 @@ export class InitTemplate { }, }; - const sourceDirectory = path.join(this.basePath, language); - const hookTempDirectory = path.join(targetDirectory, 'tmp'); - await fs.mkdir(hookTempDirectory); - await this.installFiles(sourceDirectory, targetDirectory, language, projectInfo); - await this.applyFutureFlags(targetDirectory); - await this.invokeHooks(hookTempDirectory, targetDirectory, hookContext); - await fs.remove(hookTempDirectory); + try { + await fs.mkdir(hookTempDirectory); + await this.installFiles(sourceDirectory, targetDirectory, hookTempDirectory, language, projectInfo); + await this.applyFutureFlags(targetDirectory); + await this.invokeHooks(hookTempDirectory, targetDirectory, hookContext); + } catch (e) { + warning(`Unable to create ${projectInfo.name}: ${e.message}`); + } finally { + await fs.remove(hookTempDirectory); + } } - private async installFiles(sourceDirectory: string, targetDirectory: string, language:string, project: ProjectInfo) { + private async installFiles(sourceDirectory: string, targetDirectory: string, hookTempDirectory: string, language:string, project: ProjectInfo) { for (const file of await fs.readdir(sourceDirectory)) { const fromFile = path.join(sourceDirectory, file); const toFile = path.join(targetDirectory, this.expand(file, language, project)); if ((await fs.stat(fromFile)).isDirectory()) { await fs.mkdir(toFile); - await this.installFiles(fromFile, toFile, language, project); + await this.installFiles(fromFile, toFile, hookTempDirectory, language, project); continue; } else if (file.match(/^.*\.template\.[^.]+$/)) { await this.installProcessed(fromFile, toFile.replace(/\.template(\.[^.]+)$/, '$1'), language, project); continue; } else if (file.match(/^.*\.hook\.(d.)?[^.]+$/)) { - await this.installProcessed(fromFile, path.join(targetDirectory, 'tmp', file), language, project); + await this.installProcessed(fromFile, path.join(hookTempDirectory, file), language, project); continue; } else { await fs.copy(fromFile, toFile); @@ -272,6 +279,9 @@ async function listDirectory(dirPath: string) { return (await fs.readdir(dirPath)) .filter(p => !p.startsWith('.')) .filter(p => !(p === 'LICENSE')) + // if, for some reason, the temp folder for the hook doesn't get deleted we don't want to display it in this list + .filter(p => !p.startsWith(HOOK_DIR_PREFIX)) + .filter(p => !(p === INFO_DOT_JSON)) .sort(); } diff --git a/packages/aws-cdk/lib/os.ts b/packages/aws-cdk/lib/os.ts index 95d459a266145..0ae21508e7e0c 100644 --- a/packages/aws-cdk/lib/os.ts +++ b/packages/aws-cdk/lib/os.ts @@ -2,20 +2,18 @@ import * as child_process from 'child_process'; import * as chalk from 'chalk'; import { debug } from './logging'; -export interface ShellOptions extends child_process.SpawnOptions { - quiet?: boolean; -} - /** * OS helpers * * Shell function which both prints to stdout and collects the output into a * string. */ -export async function shell(command: string[], options: ShellOptions = {}): Promise { - debug(`Executing ${chalk.blue(renderCommandLine(command))}`); - const child = child_process.spawn(command[0], command.slice(1), { - ...options, +export async function shell(command: string[]): Promise { + const commandLine = renderCommandLine(command); + debug(`Executing ${chalk.blue(commandLine)}`); + const child = child_process.spawn(command[0], renderArguments(command.slice(1)), { + // Need this for Windows where we want .cmd and .bat to be found as well. + shell: true, stdio: ['ignore', 'pipe', 'inherit'], }); @@ -24,9 +22,7 @@ export async function shell(command: string[], options: ShellOptions = {}): Prom // Both write to stdout and collect child.stdout.on('data', chunk => { - if (!options.quiet) { - process.stdout.write(chunk); - } + process.stdout.write(chunk); stdout.push(chunk); }); @@ -34,20 +30,22 @@ export async function shell(command: string[], options: ShellOptions = {}): Prom child.once('exit', code => { if (code === 0) { - resolve(Buffer.concat(stdout).toString('utf-8')); + resolve(Buffer.from(stdout).toString('utf-8')); } else { - reject(new Error(`${renderCommandLine(command)} exited with error code ${code}`)); + reject(new Error(`${commandLine} exited with error code ${code}`)); } }); }); } +function renderCommandLine(cmd: string[]) { + return renderArguments(cmd).join(' '); +} + /** - * Render the given command line as a string - * - * Probably missing some cases but giving it a good effort. + * Render the arguments to include escape characters for each platform. */ -function renderCommandLine(cmd: string[]) { +function renderArguments(cmd: string[]) { if (process.platform !== 'win32') { return doRender(cmd, hasAnyChars(' ', '\\', '!', '"', "'", '&', '$'), posixEscape); } else { @@ -58,8 +56,8 @@ function renderCommandLine(cmd: string[]) { /** * Render a UNIX command line */ -function doRender(cmd: string[], needsEscaping: (x: string) => boolean, doEscape: (x: string) => string): string { - return cmd.map(x => needsEscaping(x) ? doEscape(x) : x).join(' '); +function doRender(cmd: string[], needsEscaping: (x: string) => boolean, doEscape: (x: string) => string): string[] { + return cmd.map(x => needsEscaping(x) ? doEscape(x) : x); } /** @@ -78,7 +76,7 @@ function hasAnyChars(...chars: string[]): (x: string) => boolean { */ function posixEscape(x: string) { // Turn ' -> '"'"' - x = x.replace("'", "'\"'\"'"); + x = x.replace(/'/g, "'\"'\"'"); return `'${x}'`; } @@ -95,4 +93,4 @@ function windowsEscape(x: string): string { // Now escape all special characters const shellMeta = new Set(['"', '&', '^', '%']); return x.split('').map(c => shellMeta.has(x) ? '^' + c : c).join(''); -} +} \ No newline at end of file diff --git a/packages/aws-cdk/test/init.test.ts b/packages/aws-cdk/test/init.test.ts index fc4750beef69f..0e674ff8ab963 100644 --- a/packages/aws-cdk/test/init.test.ts +++ b/packages/aws-cdk/test/init.test.ts @@ -76,6 +76,28 @@ describe('constructs version', () => { expect(sln).toContainEqual(expect.stringMatching(/\"AwsCdkTest[a-zA-Z0-9]{6}\\AwsCdkTest[a-zA-Z0-9]{6}.fsproj\"/)); }); + cliTestWithDirSpaces('csharp app with spaces', async (workDir) => { + await cliInit('app', 'csharp', false, true, workDir); + + const csprojFile = (await recursiveListFiles(workDir)).filter(f => f.endsWith('.csproj'))[0]; + expect(csprojFile).toBeDefined(); + + const csproj = (await fs.readFile(csprojFile, 'utf8')).split(/\r?\n/); + + expect(csproj).toContainEqual(expect.stringMatching(/\ { + await cliInit('app', 'fsharp', false, true, workDir); + + const fsprojFile = (await recursiveListFiles(workDir)).filter(f => f.endsWith('.fsproj'))[0]; + expect(fsprojFile).toBeDefined(); + + const fsproj = (await fs.readFile(fsprojFile, 'utf8')).split(/\r?\n/); + + expect(fsproj).toContainEqual(expect.stringMatching(/\ { await cliInit('app', 'python', false, true, workDir); @@ -147,7 +169,6 @@ describe('constructs version', () => { }); test('when no version number is present (e.g., local development), the v2 templates are chosen by default', async () => { - expect((await availableInitTemplates()).length).toBeGreaterThan(0); }); @@ -164,6 +185,19 @@ async function withTempDir(cb: (dir: string) => void | Promise) { } } +function cliTestWithDirSpaces(name: string, handler: (dir: string) => void | Promise): void { + test(name, () => withTempDirWithSpaces(handler)); +} + +async function withTempDirWithSpaces(cb: (dir: string) => void | Promise) { + const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'aws-cdk-test with-space')); + try { + await cb(tmpDir); + } finally { + await fs.remove(tmpDir); + } +} + /** * List all files underneath dir */