From 1eebc0c4695eff3e95e62fbca84519ed2aaf8a60 Mon Sep 17 00:00:00 2001 From: Juho Saarinen Date: Mon, 12 Sep 2022 21:03:44 +0300 Subject: [PATCH] feat: allow inclusion of image copy to pipeline Support both codepipeline and pipelines --- API.md | 68 +- src/index.ts | 209 +-- src/lambdaInvokeStep.ts | 48 + src/types.ts | 172 ++ src/utils.ts | 9 + test/__snapshots__/index.test.ts.snap | 2306 ++++++++++++++++++++++++- test/index.test.ts | 85 +- 7 files changed, 2649 insertions(+), 248 deletions(-) create mode 100644 src/lambdaInvokeStep.ts create mode 100644 src/types.ts create mode 100644 src/utils.ts diff --git a/API.md b/API.md index d4474989..7c65d08c 100644 --- a/API.md +++ b/API.md @@ -4,9 +4,7 @@ Name|Description ----|----------- -[DockerImageName](#cdk-ecr-deployment-dockerimagename)|*No description* [ECRDeployment](#cdk-ecr-deployment-ecrdeployment)|*No description* -[S3ArchiveName](#cdk-ecr-deployment-s3archivename)|*No description* **Structs** @@ -27,36 +25,6 @@ Name|Description -## class DockerImageName - - - -__Implements__: [IImageName](#cdk-ecr-deployment-iimagename) - -### Initializer - - - - -```ts -new DockerImageName(name: string, creds?: ICredentials) -``` - -* **name** (string) *No description* -* **creds** ([ICredentials](#cdk-ecr-deployment-icredentials)) *No description* - - - -### Properties - - -Name | Type | Description ------|------|------------- -**uri** | string | The uri of the docker image. -**creds**? | [ICredentials](#cdk-ecr-deployment-icredentials) | __*Optional*__ - - - ## class ECRDeployment @@ -82,8 +50,10 @@ new ECRDeployment(scope: Construct, id: string, props: ECRDeploymentProps) * **environment** (Map) The environment variable to set. __*Optional*__ * **memoryLimit** (number) The amount of memory (in MiB) to allocate to the AWS Lambda function which replicates the files from the CDK bucket to the destination bucket. __*Default*__: 512 * **role** ([aws_iam.IRole](#aws-cdk-lib-aws-iam-irole)) Execution role associated with this function. __*Default*__: A role is automatically created + * **stage** ([aws_codepipeline.IStage](#aws-cdk-lib-aws-codepipeline-istage)) CodePipeline Stage to include lambda to. __*Optional*__ * **vpc** ([aws_ec2.IVpc](#aws-cdk-lib-aws-ec2-ivpc)) The VPC network to place the deployment lambda handler in. __*Default*__: None * **vpcSubnets** ([aws_ec2.SubnetSelection](#aws-cdk-lib-aws-ec2-subnetselection)) Where in the VPC to place the deployment lambda handler. __*Default*__: the Vpc default strategy if not specified + * **wave** ([pipelines.Wave](#aws-cdk-lib-pipelines-wave)) Pipelines Wave to include lambda to. __*Optional*__ ### Methods @@ -104,37 +74,6 @@ __Returns__: -## class S3ArchiveName - - - -__Implements__: [IImageName](#cdk-ecr-deployment-iimagename) - -### Initializer - - - - -```ts -new S3ArchiveName(p: string, ref?: string, creds?: ICredentials) -``` - -* **p** (string) *No description* -* **ref** (string) *No description* -* **creds** ([ICredentials](#cdk-ecr-deployment-icredentials)) *No description* - - - -### Properties - - -Name | Type | Description ------|------|------------- -**uri** | string | The uri of the docker image. -**creds**? | [ICredentials](#cdk-ecr-deployment-icredentials) | __*Optional*__ - - - ## struct ECRDeploymentProps @@ -150,8 +89,10 @@ Name | Type | Description **environment**? | Map | The environment variable to set.
__*Optional*__ **memoryLimit**? | number | The amount of memory (in MiB) to allocate to the AWS Lambda function which replicates the files from the CDK bucket to the destination bucket.
__*Default*__: 512 **role**? | [aws_iam.IRole](#aws-cdk-lib-aws-iam-irole) | Execution role associated with this function.
__*Default*__: A role is automatically created +**stage**? | [aws_codepipeline.IStage](#aws-cdk-lib-aws-codepipeline-istage) | CodePipeline Stage to include lambda to.
__*Optional*__ **vpc**? | [aws_ec2.IVpc](#aws-cdk-lib-aws-ec2-ivpc) | The VPC network to place the deployment lambda handler in.
__*Default*__: None **vpcSubnets**? | [aws_ec2.SubnetSelection](#aws-cdk-lib-aws-ec2-subnetselection) | Where in the VPC to place the deployment lambda handler.
__*Default*__: the Vpc default strategy if not specified +**wave**? | [pipelines.Wave](#aws-cdk-lib-pipelines-wave) | Pipelines Wave to include lambda to.
__*Optional*__ @@ -172,7 +113,6 @@ Name | Type | Description ## interface IImageName -__Implemented by__: [DockerImageName](#cdk-ecr-deployment-dockerimagename), [S3ArchiveName](#cdk-ecr-deployment-s3archivename) diff --git a/src/index.ts b/src/index.ts index cea7a7f4..2cab3443 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,156 +5,18 @@ import * as child_process from 'child_process'; import * as path from 'path'; import { - aws_ec2 as ec2, aws_iam as iam, aws_lambda as lambda, - aws_secretsmanager as sm, Duration, CustomResource, Token, DockerImage, } from 'aws-cdk-lib'; -import { PolicyStatement, AddToPrincipalPolicyResult } from 'aws-cdk-lib/aws-iam'; import { Construct } from 'constructs'; import { shouldUsePrebuiltLambda } from './config'; - -export interface ECRDeploymentProps { - - /** - * Image to use to build Golang lambda for custom resource, if download fails or is not wanted. - * - * Might be needed for local build if all images need to come from own registry. - * - * Note that image should use yum as a package manager and have golang available. - * - * @default public.ecr.aws/sam/build-go1.x:latest - */ - readonly buildImage?: string; - /** - * The source of the docker image. - */ - readonly src: IImageName; - - /** - * The destination of the docker image. - */ - readonly dest: IImageName; - - /** - * The amount of memory (in MiB) to allocate to the AWS Lambda function which - * replicates the files from the CDK bucket to the destination bucket. - * - * If you are deploying large files, you will need to increase this number - * accordingly. - * - * @default 512 - */ - readonly memoryLimit?: number; - - /** - * Execution role associated with this function - * - * @default - A role is automatically created - */ - readonly role?: iam.IRole; - - /** - * The VPC network to place the deployment lambda handler in. - * - * @default None - */ - readonly vpc?: ec2.IVpc; - - /** - * Where in the VPC to place the deployment lambda handler. - * Only used if 'vpc' is supplied. - * - * @default - the Vpc default strategy if not specified - */ - readonly vpcSubnets?: ec2.SubnetSelection; - - /** - * The environment variable to set - */ - readonly environment?: { [key: string]: string }; -} - -export interface IImageName { - /** - * The uri of the docker image. - * - * The uri spec follows https://github.com/containers/skopeo - */ - readonly uri: string; - - /** - * The credentials of the docker image. Format `user:password` or `AWS Secrets Manager secret arn` or `AWS Secrets Manager secret name` - */ - creds?: ICredentials; -} - -/** - * Credentials to autenticate to used container registry - */ -export interface ICredentials { - /** - * Plain text authentication - * - * Not recommended, as credentials are left in code, stack template and lambda logs. - */ - plainText?: IPlainText; - - /** - * Secrets Manager stored authentication - */ - secretManager?: ISecret; -} - -/** - * Secrets Manager provided credentials - */ -export interface ISecret { - /** - * Reference to secret where credentials are stored - * - * By default handled to include only authentication token. - * - * If using key-value secret, please define also `usernameKey` and `passwordKey`. - */ - secret: sm.ISecret; - /** - * Key containing username - */ - usenameKey?: string; - /** - * Key containing password - */ - passwordKey?: string; -} - -/** - * Plain text credentials - */ -export interface IPlainText { - /** Username to registry */ - userName: string; - /** Password to registry */ - password: string; -}; - -/** - * Simplified credentials delivery to Lambda - */ -interface LambdaCredentials { - /** Plain text credentials in form of username: password */ - plainText?: string; - /** ARN of secret containing credentials. If only this is provided, secret's whole content is used */ - secretArn?: string; - /** Key containing username */ - usernameKey?: string; - /** Key containing password */ - passwordKey?: string; -} +import { LambdaInvokeStep } from './lambdaInvokeStep'; +import { ECRDeploymentProps } from './types'; +import { formatCredentials } from './utils'; function getPrebuiltLambda(outputDir: string): boolean { try { @@ -169,38 +31,16 @@ function getPrebuiltLambda(outputDir: string): boolean { } } -export class DockerImageName implements IImageName { - public constructor(private name: string, public creds?: ICredentials) { } - public get uri(): string { return `docker://${this.name}`; } -} - -export class S3ArchiveName implements IImageName { - private name: string; - public constructor(p: string, ref?: string, public creds?: ICredentials) { - this.name = p; - if (ref) { - this.name += ':' + ref; - } - } - public get uri(): string { return `s3://${this.name}`; } -} - -/** Format credentials for Lambda call */ -const formatCredentials = (creds?: ICredentials): LambdaCredentials => ({ - plainText: creds?.plainText ? `${creds?.plainText?.userName}:${creds?.plainText?.password}` : undefined, - secretArn: creds?.secretManager?.secret.secretArn, - usernameKey: creds?.secretManager?.usenameKey, - passwordKey: creds?.secretManager?.passwordKey, -}); - - export class ECRDeployment extends Construct { private handler: lambda.SingletonFunction; constructor(scope: Construct, id: string, props: ECRDeploymentProps) { super(scope, id); + const partOfPipeline = props.stage || props.wave; const memoryLimit = props.memoryLimit ?? 512; - this.handler = new lambda.SingletonFunction(this, 'CustomResourceHandler', { + const lambdaId = partOfPipeline ? 'ImageCopyHandler' : 'CustomResourceHandler'; + const lambdaPurpose = partOfPipeline ? 'ImageCopy' : 'Custom::CDKECRDeployment'; + this.handler = new lambda.SingletonFunction(this, lambdaId, { uuid: this.renderSingletonUuid(memoryLimit), code: lambda.Code.fromAsset(path.join(__dirname, '../lambda'), { bundling: { @@ -254,7 +94,7 @@ export class ECRDeployment extends Construct { runtime: lambda.Runtime.GO_1_X, handler: 'main', environment: props.environment, - lambdaPurpose: 'Custom::CDKECRDeployment', + lambdaPurpose, timeout: Duration.minutes(15), role: props.role, memorySize: memoryLimit, @@ -298,19 +138,26 @@ export class ECRDeployment extends Construct { props.src.creds?.secretManager?.secret.grantRead(handlerRole); props.dest.creds?.secretManager?.secret.grantRead(handlerRole); - new CustomResource(this, 'CustomResource', { - serviceToken: this.handler.functionArn, - resourceType: 'Custom::CDKBucketDeployment', - properties: { - SrcImage: props.src.uri, - SrcCreds: formatCredentials(props.src.creds), - DestImage: props.dest.uri, - DestCreds: formatCredentials(props.dest.creds), - }, - }); + if (partOfPipeline) { + const factory = new LambdaInvokeStep(this.handler, props, lambdaPurpose); + + props.stage?.addAction(factory.getAction()); + props.wave?.addPost(factory); + } else { + new CustomResource(this, 'CustomResource', { + serviceToken: this.handler.functionArn, + resourceType: lambdaPurpose, + properties: { + SrcImage: props.src.uri, + SrcCreds: formatCredentials(props.src.creds), + DestImage: props.dest.uri, + DestCreds: formatCredentials(props.dest.creds), + }, + }); + } } - public addToPrincipalPolicy(statement: PolicyStatement): AddToPrincipalPolicyResult { + public addToPrincipalPolicy(statement: iam.PolicyStatement): iam.AddToPrincipalPolicyResult { const handlerRole = this.handler.role; if (!handlerRole) { throw new Error('lambda.SingletonFunction should have created a Role'); } @@ -334,3 +181,7 @@ export class ECRDeployment extends Construct { return uuid; } } + +// Exports for JSII +// see https://github.com/aws/jsii/issues/1818 +export { ECRDeploymentProps, IImageName, ICredentials, IPlainText, ISecret } from './types'; diff --git a/src/lambdaInvokeStep.ts b/src/lambdaInvokeStep.ts new file mode 100644 index 00000000..2fb6d9b4 --- /dev/null +++ b/src/lambdaInvokeStep.ts @@ -0,0 +1,48 @@ +import { + aws_codepipeline as codepipeline, + aws_codepipeline_actions as codepipeline_actions, + aws_lambda as lambda, + pipelines, +} from 'aws-cdk-lib'; +import { ECRDeploymentProps } from './types'; +import { formatCredentials } from './utils'; + +export class LambdaInvokeStep extends pipelines.Step implements pipelines.ICodePipelineActionFactory { + constructor( + private readonly handler: lambda.IFunction, + private readonly props: ECRDeploymentProps, + private readonly lambdaPurpose: string, + ) { + super('LambdaInvokeStep'); + + // This is necessary if your step accepts parametres, like environment variables, + // that may contain outputs from other steps. It doesn't matter what the + // structure is, as long as it contains the values that may contain outputs. + this.discoverReferencedOutputs({ + env: { /* ... */ }, + }); + } + + public produceAction(stage: codepipeline.IStage, _options: pipelines.ProduceActionOptions): pipelines.CodePipelineActionFactoryResult { + + + // This is where you control what type of Action gets added to the + // CodePipeline + stage.addAction(this.getAction()); + + return { runOrdersConsumed: 1 }; + } + + public getAction() { + return new codepipeline_actions.LambdaInvokeAction({ + lambda: this.handler, + actionName: this.lambdaPurpose, + userParameters: { + SrcImage: this.props.src.uri, + SrcCreds: formatCredentials(this.props.src.creds), + DestImage: this.props.dest.uri, + DestCreds: formatCredentials(this.props.dest.creds), + }, + }); + } +} diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 00000000..c6fba627 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,172 @@ + +import { + aws_codepipeline as codepipeline, + aws_ec2 as ec2, + aws_iam as iam, + aws_secretsmanager as sm, + pipelines, +} from 'aws-cdk-lib'; + +export interface ECRDeploymentProps { + + /** + * Image to use to build Golang lambda for custom resource, if download fails or is not wanted. + * + * Might be needed for local build if all images need to come from own registry. + * + * Note that image should use yum as a package manager and have golang available. + * + * @default public.ecr.aws/sam/build-go1.x:latest + */ + readonly buildImage?: string; + /** + * The source of the docker image. + */ + readonly src: IImageName; + + /** + * The destination of the docker image. + */ + readonly dest: IImageName; + + /** + * The amount of memory (in MiB) to allocate to the AWS Lambda function which + * replicates the files from the CDK bucket to the destination bucket. + * + * If you are deploying large files, you will need to increase this number + * accordingly. + * + * @default 512 + */ + readonly memoryLimit?: number; + + /** + * Execution role associated with this function + * + * @default - A role is automatically created + */ + readonly role?: iam.IRole; + + /** + * The VPC network to place the deployment lambda handler in. + * + * @default None + */ + readonly vpc?: ec2.IVpc; + + /** + * Where in the VPC to place the deployment lambda handler. + * Only used if 'vpc' is supplied. + * + * @default - the Vpc default strategy if not specified + */ + readonly vpcSubnets?: ec2.SubnetSelection; + + /** + * The environment variable to set + */ + readonly environment?: { [key: string]: string }; + + /** + * CodePipeline Stage to include lambda to. If this is set, lambda is invoked in pipeline instead of custom resource. + */ + readonly stage?: codepipeline.IStage; + + /** + * Pipelines Wave to include lambda to. If this is set, lambda is invoked in pipeline instead of custom resource. + */ + readonly wave?: pipelines.Wave; +} + +export interface IImageName { + /** + * The uri of the docker image. + * + * The uri spec follows https://github.com/containers/skopeo + */ + readonly uri: string; + + /** + * The credentials of the docker image. Format `user:password` or `AWS Secrets Manager secret arn` or `AWS Secrets Manager secret name` + */ + creds?: ICredentials; +} + +/** + * Credentials to autenticate to used container registry + */ +export interface ICredentials { + /** + * Plain text authentication + * + * Not recommended, as credentials are left in code, stack template and lambda logs. + */ + plainText?: IPlainText; + + /** + * Secrets Manager stored authentication + */ + secretManager?: ISecret; +} + +/** + * Secrets Manager provided credentials + */ +export interface ISecret { + /** + * Reference to secret where credentials are stored + * + * By default handled to include only authentication token. + * + * If using key-value secret, please define also `usernameKey` and `passwordKey`. + */ + secret: sm.ISecret; + /** + * Key containing username + */ + usenameKey?: string; + /** + * Key containing password + */ + passwordKey?: string; +} + +/** + * Plain text credentials + */ +export interface IPlainText { + /** Username to registry */ + userName: string; + /** Password to registry */ + password: string; +}; + +/** + * Simplified credentials delivery to Lambda + */ +export interface LambdaCredentials { + /** Plain text credentials in form of username: password */ + plainText?: string; + /** ARN of secret containing credentials. If only this is provided, secret's whole content is used */ + secretArn?: string; + /** Key containing username */ + usernameKey?: string; + /** Key containing password */ + passwordKey?: string; +} + +export class DockerImageName implements IImageName { + public constructor(private name: string, public creds?: ICredentials) { } + public get uri(): string { return `docker://${this.name}`; } +} + +export class S3ArchiveName implements IImageName { + private name: string; + public constructor(p: string, ref?: string, public creds?: ICredentials) { + this.name = p; + if (ref) { + this.name += ':' + ref; + } + } + public get uri(): string { return `s3://${this.name}`; } +} diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 00000000..667b4a2e --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,9 @@ +import { ICredentials, LambdaCredentials } from './types'; + +/** Format credentials for Lambda call */ +export const formatCredentials = (creds?: ICredentials): LambdaCredentials => ({ + plainText: creds?.plainText ? `${creds?.plainText?.userName}:${creds?.plainText?.password}` : undefined, + secretArn: creds?.secretManager?.secret.secretArn, + usernameKey: creds?.secretManager?.usenameKey, + passwordKey: creds?.secretManager?.passwordKey, +}); \ No newline at end of file diff --git a/test/__snapshots__/index.test.ts.snap b/test/__snapshots__/index.test.ts.snap index c1fb383a..c45ad086 100644 --- a/test/__snapshots__/index.test.ts.snap +++ b/test/__snapshots__/index.test.ts.snap @@ -1,5 +1,2307 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`lambda in codepipeline matches snapshot 1`] = ` +Object { + "Parameters": Object { + "BootstrapVersion": Object { + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]", + "Type": "AWS::SSM::Parameter::Value", + }, + }, + "Resources": Object { + "ImageCopybd07c930edb94112a20f03f096f53666512MiB0D4216F5": Object { + "DependsOn": Array [ + "ImageCopybd07c930edb94112a20f03f096f53666512MiBServiceRoleDefaultPolicyE7CC7658", + "ImageCopybd07c930edb94112a20f03f096f53666512MiBServiceRole20F78B19", + ], + "Properties": Object { + "Code": Object { + "S3Bucket": Object { + "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", + }, + "S3Key": "e5a8f1ac5b5eb16344c81e4f5f8c86d9e86b8b0a6ff7a4ec6db671c05d3401cc.zip", + }, + "Handler": "main", + "MemorySize": 512, + "Role": Object { + "Fn::GetAtt": Array [ + "ImageCopybd07c930edb94112a20f03f096f53666512MiBServiceRole20F78B19", + "Arn", + ], + }, + "Runtime": "go1.x", + "Timeout": 900, + }, + "Type": "AWS::Lambda::Function", + }, + "ImageCopybd07c930edb94112a20f03f096f53666512MiBServiceRole20F78B19": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": Array [ + Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "ImageCopybd07c930edb94112a20f03f096f53666512MiBServiceRoleDefaultPolicyE7CC7658": Object { + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "ecr:GetAuthorizationToken", + "ecr:BatchCheckLayerAvailability", + "ecr:GetDownloadUrlForLayer", + "ecr:GetRepositoryPolicy", + "ecr:DescribeRepositories", + "ecr:ListImages", + "ecr:DescribeImages", + "ecr:BatchGetImage", + "ecr:ListTagsForResource", + "ecr:DescribeImageScanFindings", + "ecr:InitiateLayerUpload", + "ecr:UploadLayerPart", + "ecr:CompleteLayerUpload", + "ecr:PutImage", + ], + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": "s3:GetObject", + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": Array [ + "codepipeline:PutJobSuccessResult", + "codepipeline:PutJobFailureResult", + ], + "Effect": "Allow", + "Resource": "*", + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "ImageCopybd07c930edb94112a20f03f096f53666512MiBServiceRoleDefaultPolicyE7CC7658", + "Roles": Array [ + Object { + "Ref": "ImageCopybd07c930edb94112a20f03f096f53666512MiBServiceRole20F78B19", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "NginxRepo42B51311": Object { + "DeletionPolicy": "Delete", + "Properties": Object { + "RepositoryName": "nginx", + }, + "Type": "AWS::ECR::Repository", + "UpdateReplacePolicy": "Delete", + }, + "PipelineWithLambdaArtifactsBucket47E296C2": Object { + "DeletionPolicy": "Retain", + "Properties": Object { + "BucketEncryption": Object { + "ServerSideEncryptionConfiguration": Array [ + Object { + "ServerSideEncryptionByDefault": Object { + "KMSMasterKeyID": Object { + "Fn::GetAtt": Array [ + "PipelineWithLambdaArtifactsBucketEncryptionKey18F9C71E", + "Arn", + ], + }, + "SSEAlgorithm": "aws:kms", + }, + }, + ], + }, + "PublicAccessBlockConfiguration": Object { + "BlockPublicAcls": true, + "BlockPublicPolicy": true, + "IgnorePublicAcls": true, + "RestrictPublicBuckets": true, + }, + }, + "Type": "AWS::S3::Bucket", + "UpdateReplacePolicy": "Retain", + }, + "PipelineWithLambdaArtifactsBucketEncryptionKey18F9C71E": Object { + "DeletionPolicy": "Delete", + "Properties": Object { + "KeyPolicy": Object { + "Statement": Array [ + Object { + "Action": "kms:*", + "Effect": "Allow", + "Principal": Object { + "AWS": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":iam::", + Object { + "Ref": "AWS::AccountId", + }, + ":root", + ], + ], + }, + }, + "Resource": "*", + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::KMS::Key", + "UpdateReplacePolicy": "Delete", + }, + "PipelineWithLambdaArtifactsBucketEncryptionKeyAliasD027891B": Object { + "DeletionPolicy": "Delete", + "Properties": Object { + "AliasName": "alias/codepipeline-pipelinewithlambda", + "TargetKeyId": Object { + "Fn::GetAtt": Array [ + "PipelineWithLambdaArtifactsBucketEncryptionKey18F9C71E", + "Arn", + ], + }, + }, + "Type": "AWS::KMS::Alias", + "UpdateReplacePolicy": "Delete", + }, + "PipelineWithLambdaArtifactsBucketPolicy8219A052": Object { + "Properties": Object { + "Bucket": Object { + "Ref": "PipelineWithLambdaArtifactsBucket47E296C2", + }, + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "s3:*", + "Condition": Object { + "Bool": Object { + "aws:SecureTransport": "false", + }, + }, + "Effect": "Deny", + "Principal": Object { + "AWS": "*", + }, + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "PipelineWithLambdaArtifactsBucket47E296C2", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "PipelineWithLambdaArtifactsBucket47E296C2", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::S3::BucketPolicy", + }, + "PipelineWithLambdaCopyImageImageCopyCodePipelineActionRoleB102070F": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "AWS": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":iam::", + Object { + "Ref": "AWS::AccountId", + }, + ":root", + ], + ], + }, + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "PipelineWithLambdaCopyImageImageCopyCodePipelineActionRoleDefaultPolicy27B08A0A": Object { + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "lambda:ListFunctions", + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": "lambda:InvokeFunction", + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "ImageCopybd07c930edb94112a20f03f096f53666512MiB0D4216F5", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "ImageCopybd07c930edb94112a20f03f096f53666512MiB0D4216F5", + "Arn", + ], + }, + ":*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "PipelineWithLambdaCopyImageImageCopyCodePipelineActionRoleDefaultPolicy27B08A0A", + "Roles": Array [ + Object { + "Ref": "PipelineWithLambdaCopyImageImageCopyCodePipelineActionRoleB102070F", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "PipelineWithLambdaEventsRole9045137E": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "events.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "PipelineWithLambdaEventsRoleDefaultPolicyDFA38DEA": Object { + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "codepipeline:StartPipelineExecution", + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":codepipeline:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "PipelineWithLambdaF3D188C7", + }, + ], + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "PipelineWithLambdaEventsRoleDefaultPolicyDFA38DEA", + "Roles": Array [ + Object { + "Ref": "PipelineWithLambdaEventsRole9045137E", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "PipelineWithLambdaF3D188C7": Object { + "DependsOn": Array [ + "PipelineWithLambdaRoleDefaultPolicy93F71456", + "PipelineWithLambdaRole23C1246E", + ], + "Properties": Object { + "ArtifactStore": Object { + "EncryptionKey": Object { + "Id": Object { + "Fn::GetAtt": Array [ + "PipelineWithLambdaArtifactsBucketEncryptionKey18F9C71E", + "Arn", + ], + }, + "Type": "KMS", + }, + "Location": Object { + "Ref": "PipelineWithLambdaArtifactsBucket47E296C2", + }, + "Type": "S3", + }, + "RoleArn": Object { + "Fn::GetAtt": Array [ + "PipelineWithLambdaRole23C1246E", + "Arn", + ], + }, + "Stages": Array [ + Object { + "Actions": Array [ + Object { + "ActionTypeId": Object { + "Category": "Source", + "Owner": "AWS", + "Provider": "CodeCommit", + "Version": "1", + }, + "Configuration": Object { + "BranchName": "master", + "PollForSourceChanges": false, + "RepositoryName": Object { + "Fn::GetAtt": Array [ + "Repo02AC86CF", + "Name", + ], + }, + }, + "Name": "Source", + "OutputArtifacts": Array [ + Object { + "Name": "Artifact_Source_Source", + }, + ], + "RoleArn": Object { + "Fn::GetAtt": Array [ + "PipelineWithLambdaSourceCodePipelineActionRole8A892282", + "Arn", + ], + }, + "RunOrder": 1, + }, + ], + "Name": "Source", + }, + Object { + "Actions": Array [ + Object { + "ActionTypeId": Object { + "Category": "Invoke", + "Owner": "AWS", + "Provider": "Lambda", + "Version": "1", + }, + "Configuration": Object { + "FunctionName": Object { + "Ref": "ImageCopybd07c930edb94112a20f03f096f53666512MiB0D4216F5", + }, + "UserParameters": Object { + "Fn::Join": Array [ + "", + Array [ + "{\\"SrcImage\\":\\"docker://", + Object { + "Fn::Select": Array [ + 4, + Object { + "Fn::Split": Array [ + ":", + Object { + "Fn::GetAtt": Array [ + "NginxRepo42B51311", + "Arn", + ], + }, + ], + }, + ], + }, + ".dkr.ecr.", + Object { + "Fn::Select": Array [ + 3, + Object { + "Fn::Split": Array [ + ":", + Object { + "Fn::GetAtt": Array [ + "NginxRepo42B51311", + "Arn", + ], + }, + ], + }, + ], + }, + ".", + Object { + "Ref": "AWS::URLSuffix", + }, + "/", + Object { + "Ref": "NginxRepo42B51311", + }, + ":stable\\",\\"SrcCreds\\":{},\\"DestImage\\":\\"docker://", + Object { + "Fn::Select": Array [ + 4, + Object { + "Fn::Split": Array [ + ":", + Object { + "Fn::GetAtt": Array [ + "NginxRepo42B51311", + "Arn", + ], + }, + ], + }, + ], + }, + ".dkr.ecr.", + Object { + "Fn::Select": Array [ + 3, + Object { + "Fn::Split": Array [ + ":", + Object { + "Fn::GetAtt": Array [ + "NginxRepo42B51311", + "Arn", + ], + }, + ], + }, + ], + }, + ".", + Object { + "Ref": "AWS::URLSuffix", + }, + "/", + Object { + "Ref": "NginxRepo42B51311", + }, + ":latest\\",\\"DestCreds\\":{}}", + ], + ], + }, + }, + "Name": "ImageCopy", + "RoleArn": Object { + "Fn::GetAtt": Array [ + "PipelineWithLambdaCopyImageImageCopyCodePipelineActionRoleB102070F", + "Arn", + ], + }, + "RunOrder": 1, + }, + ], + "Name": "CopyImage", + }, + ], + }, + "Type": "AWS::CodePipeline::Pipeline", + }, + "PipelineWithLambdaRole23C1246E": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "codepipeline.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "PipelineWithLambdaRoleDefaultPolicy93F71456": Object { + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + "s3:DeleteObject*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging", + "s3:Abort*", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "PipelineWithLambdaArtifactsBucket47E296C2", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "PipelineWithLambdaArtifactsBucket47E296C2", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + Object { + "Action": Array [ + "kms:Decrypt", + "kms:DescribeKey", + "kms:Encrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::GetAtt": Array [ + "PipelineWithLambdaArtifactsBucketEncryptionKey18F9C71E", + "Arn", + ], + }, + }, + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": Object { + "Fn::GetAtt": Array [ + "PipelineWithLambdaSourceCodePipelineActionRole8A892282", + "Arn", + ], + }, + }, + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": Object { + "Fn::GetAtt": Array [ + "PipelineWithLambdaCopyImageImageCopyCodePipelineActionRoleB102070F", + "Arn", + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "PipelineWithLambdaRoleDefaultPolicy93F71456", + "Roles": Array [ + Object { + "Ref": "PipelineWithLambdaRole23C1246E", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "PipelineWithLambdaSourceCodePipelineActionRole8A892282": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "AWS": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":iam::", + Object { + "Ref": "AWS::AccountId", + }, + ":root", + ], + ], + }, + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "PipelineWithLambdaSourceCodePipelineActionRoleDefaultPolicy66644772": Object { + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + "s3:DeleteObject*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging", + "s3:Abort*", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "PipelineWithLambdaArtifactsBucket47E296C2", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "PipelineWithLambdaArtifactsBucket47E296C2", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + Object { + "Action": Array [ + "kms:Decrypt", + "kms:DescribeKey", + "kms:Encrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::GetAtt": Array [ + "PipelineWithLambdaArtifactsBucketEncryptionKey18F9C71E", + "Arn", + ], + }, + }, + Object { + "Action": Array [ + "codecommit:GetBranch", + "codecommit:GetCommit", + "codecommit:UploadArchive", + "codecommit:GetUploadArchiveStatus", + "codecommit:CancelUploadArchive", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::GetAtt": Array [ + "Repo02AC86CF", + "Arn", + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "PipelineWithLambdaSourceCodePipelineActionRoleDefaultPolicy66644772", + "Roles": Array [ + Object { + "Ref": "PipelineWithLambdaSourceCodePipelineActionRole8A892282", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "Repo02AC86CF": Object { + "Properties": Object { + "RepositoryName": "test-repo", + }, + "Type": "AWS::CodeCommit::Repository", + }, + "RepoPipelineWithLambdaEventRuleDE3CEAA4": Object { + "Properties": Object { + "EventPattern": Object { + "detail": Object { + "event": Array [ + "referenceCreated", + "referenceUpdated", + ], + "referenceName": Array [ + "master", + ], + }, + "detail-type": Array [ + "CodeCommit Repository State Change", + ], + "resources": Array [ + Object { + "Fn::GetAtt": Array [ + "Repo02AC86CF", + "Arn", + ], + }, + ], + "source": Array [ + "aws.codecommit", + ], + }, + "State": "ENABLED", + "Targets": Array [ + Object { + "Arn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":codepipeline:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "PipelineWithLambdaF3D188C7", + }, + ], + ], + }, + "Id": "Target0", + "RoleArn": Object { + "Fn::GetAtt": Array [ + "PipelineWithLambdaEventsRole9045137E", + "Arn", + ], + }, + }, + ], + }, + "Type": "AWS::Events::Rule", + }, + }, + "Rules": Object { + "CheckBootstrapVersion": Object { + "Assertions": Array [ + Object { + "Assert": Object { + "Fn::Not": Array [ + Object { + "Fn::Contains": Array [ + Array [ + "1", + "2", + "3", + "4", + "5", + ], + Object { + "Ref": "BootstrapVersion", + }, + ], + }, + ], + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.", + }, + ], + }, + }, +} +`; + +exports[`lambda in pipelines pipeline matches snapshot 1`] = ` +Object { + "Parameters": Object { + "BootstrapVersion": Object { + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]", + "Type": "AWS::SSM::Parameter::Value", + }, + }, + "Resources": Object { + "ImageCopybd07c930edb94112a20f03f096f53666512MiB0D4216F5": Object { + "DependsOn": Array [ + "ImageCopybd07c930edb94112a20f03f096f53666512MiBServiceRoleDefaultPolicyE7CC7658", + "ImageCopybd07c930edb94112a20f03f096f53666512MiBServiceRole20F78B19", + ], + "Properties": Object { + "Code": Object { + "S3Bucket": Object { + "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", + }, + "S3Key": "e5a8f1ac5b5eb16344c81e4f5f8c86d9e86b8b0a6ff7a4ec6db671c05d3401cc.zip", + }, + "Handler": "main", + "MemorySize": 512, + "Role": Object { + "Fn::GetAtt": Array [ + "ImageCopybd07c930edb94112a20f03f096f53666512MiBServiceRole20F78B19", + "Arn", + ], + }, + "Runtime": "go1.x", + "Timeout": 900, + }, + "Type": "AWS::Lambda::Function", + }, + "ImageCopybd07c930edb94112a20f03f096f53666512MiBServiceRole20F78B19": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": Array [ + Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "ImageCopybd07c930edb94112a20f03f096f53666512MiBServiceRoleDefaultPolicyE7CC7658": Object { + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "ecr:GetAuthorizationToken", + "ecr:BatchCheckLayerAvailability", + "ecr:GetDownloadUrlForLayer", + "ecr:GetRepositoryPolicy", + "ecr:DescribeRepositories", + "ecr:ListImages", + "ecr:DescribeImages", + "ecr:BatchGetImage", + "ecr:ListTagsForResource", + "ecr:DescribeImageScanFindings", + "ecr:InitiateLayerUpload", + "ecr:UploadLayerPart", + "ecr:CompleteLayerUpload", + "ecr:PutImage", + ], + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": "s3:GetObject", + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": Array [ + "codepipeline:PutJobSuccessResult", + "codepipeline:PutJobFailureResult", + ], + "Effect": "Allow", + "Resource": "*", + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "ImageCopybd07c930edb94112a20f03f096f53666512MiBServiceRoleDefaultPolicyE7CC7658", + "Roles": Array [ + Object { + "Ref": "ImageCopybd07c930edb94112a20f03f096f53666512MiBServiceRole20F78B19", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "NginxRepo42B51311": Object { + "DeletionPolicy": "Delete", + "Properties": Object { + "RepositoryName": "nginx", + }, + "Type": "AWS::ECR::Repository", + "UpdateReplacePolicy": "Delete", + }, + "Repo02AC86CF": Object { + "Properties": Object { + "RepositoryName": "test-repo", + }, + "Type": "AWS::CodeCommit::Repository", + }, + "RepopipelinesPipeline19AAB9B8EventRule6357EE85": Object { + "Properties": Object { + "EventPattern": Object { + "detail": Object { + "event": Array [ + "referenceCreated", + "referenceUpdated", + ], + "referenceName": Array [ + "master", + ], + }, + "detail-type": Array [ + "CodeCommit Repository State Change", + ], + "resources": Array [ + Object { + "Fn::GetAtt": Array [ + "Repo02AC86CF", + "Arn", + ], + }, + ], + "source": Array [ + "aws.codecommit", + ], + }, + "State": "ENABLED", + "Targets": Array [ + Object { + "Arn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":codepipeline:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "pipelinesPipelineEAE3F1AF", + }, + ], + ], + }, + "Id": "Target0", + "RoleArn": Object { + "Fn::GetAtt": Array [ + "pipelinesPipelineEventsRoleF14AE9B6", + "Arn", + ], + }, + }, + ], + }, + "Type": "AWS::Events::Rule", + }, + "pipelinesCodeBuildActionRole0A34FFD8": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Condition": Object { + "Bool": Object { + "aws:ViaAWSService": "codepipeline.amazonaws.com", + }, + }, + "Effect": "Allow", + "Principal": Object { + "AWS": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":iam::", + Object { + "Ref": "AWS::AccountId", + }, + ":root", + ], + ], + }, + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "pipelinesCodeBuildActionRoleDefaultPolicy1075D2D6": Object { + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild", + "codebuild:StopBuild", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::GetAtt": Array [ + "pipelinesPipelineBuildsynthCdkBuildProjectC3D1D808", + "Arn", + ], + }, + }, + Object { + "Action": Array [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild", + "codebuild:StopBuild", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::GetAtt": Array [ + "pipelinesUpdatePipelineSelfMutationFA94E664", + "Arn", + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "pipelinesCodeBuildActionRoleDefaultPolicy1075D2D6", + "Roles": Array [ + Object { + "Ref": "pipelinesCodeBuildActionRole0A34FFD8", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "pipelinesPipelineArtifactsBucket27498DB8": Object { + "DeletionPolicy": "Retain", + "Properties": Object { + "BucketEncryption": Object { + "ServerSideEncryptionConfiguration": Array [ + Object { + "ServerSideEncryptionByDefault": Object { + "SSEAlgorithm": "aws:kms", + }, + }, + ], + }, + "PublicAccessBlockConfiguration": Object { + "BlockPublicAcls": true, + "BlockPublicPolicy": true, + "IgnorePublicAcls": true, + "RestrictPublicBuckets": true, + }, + }, + "Type": "AWS::S3::Bucket", + "UpdateReplacePolicy": "Retain", + }, + "pipelinesPipelineArtifactsBucketPolicy2E6820BE": Object { + "Properties": Object { + "Bucket": Object { + "Ref": "pipelinesPipelineArtifactsBucket27498DB8", + }, + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "s3:*", + "Condition": Object { + "Bool": Object { + "aws:SecureTransport": "false", + }, + }, + "Effect": "Deny", + "Principal": Object { + "AWS": "*", + }, + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "pipelinesPipelineArtifactsBucket27498DB8", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "pipelinesPipelineArtifactsBucket27498DB8", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::S3::BucketPolicy", + }, + "pipelinesPipelineBuildsynthCdkBuildProjectC3D1D808": Object { + "Properties": Object { + "Artifacts": Object { + "Type": "CODEPIPELINE", + }, + "Cache": Object { + "Type": "NO_CACHE", + }, + "Description": "Pipeline step Default/Pipeline/Build/synth", + "EncryptionKey": "alias/aws/s3", + "Environment": Object { + "ComputeType": "BUILD_GENERAL1_SMALL", + "Image": "aws/codebuild/standard:5.0", + "ImagePullCredentialsType": "CODEBUILD", + "PrivilegedMode": false, + "Type": "LINUX_CONTAINER", + }, + "ServiceRole": Object { + "Fn::GetAtt": Array [ + "pipelinesPipelineBuildsynthCdkBuildProjectRole501C3E99", + "Arn", + ], + }, + "Source": Object { + "BuildSpec": "{ + \\"version\\": \\"0.2\\", + \\"phases\\": { + \\"build\\": { + \\"commands\\": [ + \\"mkdir cdk.out\\", + \\"touch cdk.out/test\\" + ] + } + }, + \\"artifacts\\": { + \\"base-directory\\": \\"cdk.out\\", + \\"files\\": \\"**/*\\" + } +}", + "Type": "CODEPIPELINE", + }, + }, + "Type": "AWS::CodeBuild::Project", + }, + "pipelinesPipelineBuildsynthCdkBuildProjectRole501C3E99": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "codebuild.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "pipelinesPipelineBuildsynthCdkBuildProjectRoleDefaultPolicy0CFABA24": Object { + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":log-group:/aws/codebuild/", + Object { + "Ref": "pipelinesPipelineBuildsynthCdkBuildProjectC3D1D808", + }, + ], + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":log-group:/aws/codebuild/", + Object { + "Ref": "pipelinesPipelineBuildsynthCdkBuildProjectC3D1D808", + }, + ":*", + ], + ], + }, + ], + }, + Object { + "Action": Array [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":codebuild:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":report-group/", + Object { + "Ref": "pipelinesPipelineBuildsynthCdkBuildProjectC3D1D808", + }, + "-*", + ], + ], + }, + }, + Object { + "Action": Array [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + "s3:DeleteObject*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging", + "s3:Abort*", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "pipelinesPipelineArtifactsBucket27498DB8", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "pipelinesPipelineArtifactsBucket27498DB8", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "pipelinesPipelineBuildsynthCdkBuildProjectRoleDefaultPolicy0CFABA24", + "Roles": Array [ + Object { + "Ref": "pipelinesPipelineBuildsynthCdkBuildProjectRole501C3E99", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "pipelinesPipelineCopyImageImageCopyCodePipelineActionRoleBCA09BEC": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "AWS": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":iam::", + Object { + "Ref": "AWS::AccountId", + }, + ":root", + ], + ], + }, + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "pipelinesPipelineCopyImageImageCopyCodePipelineActionRoleDefaultPolicyF21FF0CC": Object { + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "lambda:ListFunctions", + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": "lambda:InvokeFunction", + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "ImageCopybd07c930edb94112a20f03f096f53666512MiB0D4216F5", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "ImageCopybd07c930edb94112a20f03f096f53666512MiB0D4216F5", + "Arn", + ], + }, + ":*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "pipelinesPipelineCopyImageImageCopyCodePipelineActionRoleDefaultPolicyF21FF0CC", + "Roles": Array [ + Object { + "Ref": "pipelinesPipelineCopyImageImageCopyCodePipelineActionRoleBCA09BEC", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "pipelinesPipelineEAE3F1AF": Object { + "DependsOn": Array [ + "pipelinesPipelineRoleDefaultPolicy8A18F220", + "pipelinesPipelineRole3396D699", + ], + "Properties": Object { + "ArtifactStore": Object { + "Location": Object { + "Ref": "pipelinesPipelineArtifactsBucket27498DB8", + }, + "Type": "S3", + }, + "RestartExecutionOnUpdate": true, + "RoleArn": Object { + "Fn::GetAtt": Array [ + "pipelinesPipelineRole3396D699", + "Arn", + ], + }, + "Stages": Array [ + Object { + "Actions": Array [ + Object { + "ActionTypeId": Object { + "Category": "Source", + "Owner": "AWS", + "Provider": "CodeCommit", + "Version": "1", + }, + "Configuration": Object { + "BranchName": "master", + "PollForSourceChanges": false, + "RepositoryName": Object { + "Fn::GetAtt": Array [ + "Repo02AC86CF", + "Name", + ], + }, + }, + "Name": Object { + "Fn::GetAtt": Array [ + "Repo02AC86CF", + "Name", + ], + }, + "OutputArtifacts": Array [ + Object { + "Name": "c8d064061d1c8680a574cd5a9f9c9c69b475d41907_Source", + }, + ], + "RoleArn": Object { + "Fn::GetAtt": Array [ + "pipelinesPipelineSourceCodeCommitCodePipelineActionRoleF943FC72", + "Arn", + ], + }, + "RunOrder": 1, + }, + ], + "Name": "Source", + }, + Object { + "Actions": Array [ + Object { + "ActionTypeId": Object { + "Category": "Build", + "Owner": "AWS", + "Provider": "CodeBuild", + "Version": "1", + }, + "Configuration": Object { + "EnvironmentVariables": "[{\\"name\\":\\"_PROJECT_CONFIG_HASH\\",\\"type\\":\\"PLAINTEXT\\",\\"value\\":\\"a90a19c9b1184e4a3d3cc11d28a23298fdf673655d0837d888091b17460eb6d6\\"}]", + "ProjectName": Object { + "Ref": "pipelinesPipelineBuildsynthCdkBuildProjectC3D1D808", + }, + }, + "InputArtifacts": Array [ + Object { + "Name": "c8d064061d1c8680a574cd5a9f9c9c69b475d41907_Source", + }, + ], + "Name": "synth", + "OutputArtifacts": Array [ + Object { + "Name": "synth_Output", + }, + ], + "RoleArn": Object { + "Fn::GetAtt": Array [ + "pipelinesCodeBuildActionRole0A34FFD8", + "Arn", + ], + }, + "RunOrder": 1, + }, + ], + "Name": "Build", + }, + Object { + "Actions": Array [ + Object { + "ActionTypeId": Object { + "Category": "Build", + "Owner": "AWS", + "Provider": "CodeBuild", + "Version": "1", + }, + "Configuration": Object { + "EnvironmentVariables": "[{\\"name\\":\\"_PROJECT_CONFIG_HASH\\",\\"type\\":\\"PLAINTEXT\\",\\"value\\":\\"de1738b881d2f46e53ab02de31ca684f8741d030cff96e621e2ce465b5d9c6a7\\"}]", + "ProjectName": Object { + "Ref": "pipelinesUpdatePipelineSelfMutationFA94E664", + }, + }, + "InputArtifacts": Array [ + Object { + "Name": "synth_Output", + }, + ], + "Name": "SelfMutate", + "RoleArn": Object { + "Fn::GetAtt": Array [ + "pipelinesCodeBuildActionRole0A34FFD8", + "Arn", + ], + }, + "RunOrder": 1, + }, + ], + "Name": "UpdatePipeline", + }, + Object { + "Actions": Array [ + Object { + "ActionTypeId": Object { + "Category": "Invoke", + "Owner": "AWS", + "Provider": "Lambda", + "Version": "1", + }, + "Configuration": Object { + "FunctionName": Object { + "Ref": "ImageCopybd07c930edb94112a20f03f096f53666512MiB0D4216F5", + }, + "UserParameters": Object { + "Fn::Join": Array [ + "", + Array [ + "{\\"SrcImage\\":\\"docker://", + Object { + "Fn::Select": Array [ + 4, + Object { + "Fn::Split": Array [ + ":", + Object { + "Fn::GetAtt": Array [ + "NginxRepo42B51311", + "Arn", + ], + }, + ], + }, + ], + }, + ".dkr.ecr.", + Object { + "Fn::Select": Array [ + 3, + Object { + "Fn::Split": Array [ + ":", + Object { + "Fn::GetAtt": Array [ + "NginxRepo42B51311", + "Arn", + ], + }, + ], + }, + ], + }, + ".", + Object { + "Ref": "AWS::URLSuffix", + }, + "/", + Object { + "Ref": "NginxRepo42B51311", + }, + ":stable\\",\\"SrcCreds\\":{},\\"DestImage\\":\\"docker://", + Object { + "Fn::Select": Array [ + 4, + Object { + "Fn::Split": Array [ + ":", + Object { + "Fn::GetAtt": Array [ + "NginxRepo42B51311", + "Arn", + ], + }, + ], + }, + ], + }, + ".dkr.ecr.", + Object { + "Fn::Select": Array [ + 3, + Object { + "Fn::Split": Array [ + ":", + Object { + "Fn::GetAtt": Array [ + "NginxRepo42B51311", + "Arn", + ], + }, + ], + }, + ], + }, + ".", + Object { + "Ref": "AWS::URLSuffix", + }, + "/", + Object { + "Ref": "NginxRepo42B51311", + }, + ":latest\\",\\"DestCreds\\":{}}", + ], + ], + }, + }, + "Name": "ImageCopy", + "RoleArn": Object { + "Fn::GetAtt": Array [ + "pipelinesPipelineCopyImageImageCopyCodePipelineActionRoleBCA09BEC", + "Arn", + ], + }, + "RunOrder": 1, + }, + ], + "Name": "CopyImage", + }, + ], + }, + "Type": "AWS::CodePipeline::Pipeline", + }, + "pipelinesPipelineEventsRoleDefaultPolicy9E5668AB": Object { + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "codepipeline:StartPipelineExecution", + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":codepipeline:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "pipelinesPipelineEAE3F1AF", + }, + ], + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "pipelinesPipelineEventsRoleDefaultPolicy9E5668AB", + "Roles": Array [ + Object { + "Ref": "pipelinesPipelineEventsRoleF14AE9B6", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "pipelinesPipelineEventsRoleF14AE9B6": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "events.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "pipelinesPipelineRole3396D699": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "codepipeline.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "pipelinesPipelineRoleDefaultPolicy8A18F220": Object { + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + "s3:DeleteObject*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging", + "s3:Abort*", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "pipelinesPipelineArtifactsBucket27498DB8", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "pipelinesPipelineArtifactsBucket27498DB8", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": Object { + "Fn::GetAtt": Array [ + "pipelinesPipelineSourceCodeCommitCodePipelineActionRoleF943FC72", + "Arn", + ], + }, + }, + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": Object { + "Fn::GetAtt": Array [ + "pipelinesCodeBuildActionRole0A34FFD8", + "Arn", + ], + }, + }, + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": Object { + "Fn::GetAtt": Array [ + "pipelinesPipelineCopyImageImageCopyCodePipelineActionRoleBCA09BEC", + "Arn", + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "pipelinesPipelineRoleDefaultPolicy8A18F220", + "Roles": Array [ + Object { + "Ref": "pipelinesPipelineRole3396D699", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "pipelinesPipelineSourceCodeCommitCodePipelineActionRoleDefaultPolicy3A67ACE9": Object { + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + "s3:DeleteObject*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging", + "s3:Abort*", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "pipelinesPipelineArtifactsBucket27498DB8", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "pipelinesPipelineArtifactsBucket27498DB8", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + Object { + "Action": Array [ + "codecommit:GetBranch", + "codecommit:GetCommit", + "codecommit:UploadArchive", + "codecommit:GetUploadArchiveStatus", + "codecommit:CancelUploadArchive", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::GetAtt": Array [ + "Repo02AC86CF", + "Arn", + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "pipelinesPipelineSourceCodeCommitCodePipelineActionRoleDefaultPolicy3A67ACE9", + "Roles": Array [ + Object { + "Ref": "pipelinesPipelineSourceCodeCommitCodePipelineActionRoleF943FC72", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "pipelinesPipelineSourceCodeCommitCodePipelineActionRoleF943FC72": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "AWS": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":iam::", + Object { + "Ref": "AWS::AccountId", + }, + ":root", + ], + ], + }, + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "pipelinesUpdatePipelineSelfMutationFA94E664": Object { + "Properties": Object { + "Artifacts": Object { + "Type": "CODEPIPELINE", + }, + "Cache": Object { + "Type": "NO_CACHE", + }, + "Description": "Pipeline step Default/Pipeline/UpdatePipeline/SelfMutate", + "EncryptionKey": "alias/aws/s3", + "Environment": Object { + "ComputeType": "BUILD_GENERAL1_SMALL", + "Image": "aws/codebuild/standard:5.0", + "ImagePullCredentialsType": "CODEBUILD", + "PrivilegedMode": false, + "Type": "LINUX_CONTAINER", + }, + "ServiceRole": Object { + "Fn::GetAtt": Array [ + "pipelinesUpdatePipelineSelfMutationRole6B594EB5", + "Arn", + ], + }, + "Source": Object { + "BuildSpec": "{ + \\"version\\": \\"0.2\\", + \\"phases\\": { + \\"install\\": { + \\"commands\\": [ + \\"npm install -g aws-cdk@2\\" + ] + }, + \\"build\\": { + \\"commands\\": [ + \\"cdk -a . deploy Default --require-approval=never --verbose\\" + ] + } + } +}", + "Type": "CODEPIPELINE", + }, + }, + "Type": "AWS::CodeBuild::Project", + }, + "pipelinesUpdatePipelineSelfMutationRole6B594EB5": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "codebuild.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "pipelinesUpdatePipelineSelfMutationRoleDefaultPolicyD785AFC1": Object { + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":log-group:/aws/codebuild/", + Object { + "Ref": "pipelinesUpdatePipelineSelfMutationFA94E664", + }, + ], + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":log-group:/aws/codebuild/", + Object { + "Ref": "pipelinesUpdatePipelineSelfMutationFA94E664", + }, + ":*", + ], + ], + }, + ], + }, + Object { + "Action": Array [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":codebuild:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":report-group/", + Object { + "Ref": "pipelinesUpdatePipelineSelfMutationFA94E664", + }, + "-*", + ], + ], + }, + }, + Object { + "Action": "sts:AssumeRole", + "Condition": Object { + "ForAnyValue:StringEquals": Object { + "iam:ResourceTag/aws-cdk:bootstrap-role": Array [ + "image-publishing", + "file-publishing", + "deploy", + ], + }, + }, + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:*:iam::", + Object { + "Ref": "AWS::AccountId", + }, + ":role/*", + ], + ], + }, + }, + Object { + "Action": "cloudformation:DescribeStacks", + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": "s3:ListBucket", + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": Array [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "pipelinesPipelineArtifactsBucket27498DB8", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "pipelinesPipelineArtifactsBucket27498DB8", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "pipelinesUpdatePipelineSelfMutationRoleDefaultPolicyD785AFC1", + "Roles": Array [ + Object { + "Ref": "pipelinesUpdatePipelineSelfMutationRole6B594EB5", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + }, + "Rules": Object { + "CheckBootstrapVersion": Object { + "Assertions": Array [ + Object { + "Assert": Object { + "Fn::Not": Array [ + Object { + "Fn::Contains": Array [ + Array [ + "1", + "2", + "3", + "4", + "5", + ], + Object { + "Ref": "BootstrapVersion", + }, + ], + }, + ], + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.", + }, + ], + }, + }, +} +`; + exports[`stack with key-value secret matches snapshot 1`] = ` Object { "Parameters": Object { @@ -220,7 +2522,7 @@ Object { }, "SrcImage": "docker://javacs3/javacs3:latest", }, - "Type": "Custom::CDKBucketDeployment", + "Type": "Custom::CDKECRDeployment", "UpdateReplacePolicy": "Delete", }, "NginxRepo42B51311": Object { @@ -480,7 +2782,7 @@ Object { }, "SrcImage": "docker://javacs3/javacs3:latest", }, - "Type": "Custom::CDKBucketDeployment", + "Type": "Custom::CDKECRDeployment", "UpdateReplacePolicy": "Delete", }, "NginxRepo42B51311": Object { diff --git a/test/index.test.ts b/test/index.test.ts index 1249584d..4db58e60 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -3,13 +3,18 @@ import { + aws_codecommit as codecommit, + aws_codepipeline as codepipeline, + aws_codepipeline_actions as codepipeline_actions, aws_ecr as ecr, aws_secretsmanager as sm, + pipelines, RemovalPolicy, Stack, } from 'aws-cdk-lib'; import { Match, Template } from 'aws-cdk-lib/assertions'; -import { DockerImageName, ECRDeployment, S3ArchiveName } from '../src'; +import { ECRDeployment } from '../src'; +import { DockerImageName, S3ArchiveName } from '../src/types'; test(`${DockerImageName.name}`, () => { @@ -63,7 +68,7 @@ describe('stack with secret', () => { }); test('calls Lambda with secret info', () => { - template.hasResourceProperties('Custom::CDKBucketDeployment', { + template.hasResourceProperties('Custom::CDKECRDeployment', { SrcCreds: { secretArn: { 'Fn::Join': Match.arrayWith([ @@ -120,7 +125,7 @@ describe('stack with key-value secret', () => { }); test('calls Lambda with secret info', () => { - template.hasResourceProperties('Custom::CDKBucketDeployment', { + template.hasResourceProperties('Custom::CDKECRDeployment', { SrcCreds: Match.objectLike({ passwordKey: 'password', secretArn: { @@ -133,6 +138,80 @@ describe('stack with key-value secret', () => { }); }); + test('matches snapshot', () => { + expect(template).toMatchSnapshot(); + }); +}); + +describe('lambda in codepipeline', () => { + const stack = new Stack(); + const pipeline = new codepipeline.Pipeline(stack, 'PipelineWithLambda', {}); + + const output = new codepipeline.Artifact(); + const repository = new codecommit.Repository(stack, 'Repo', { + repositoryName: 'test-repo', + }); + pipeline.addStage({ + stageName: 'Source', + actions: [ + new codepipeline_actions.CodeCommitSourceAction({ + actionName: 'Source', + output, + repository, + }), + ], + }); + const stage = pipeline.addStage({ + stageName: 'CopyImage', + }); + + const repo = new ecr.Repository(stack, 'NginxRepo', { + repositoryName: 'nginx', + removalPolicy: RemovalPolicy.DESTROY, + }); + + new ECRDeployment(stack, 'ImageCopy', { + dest: new DockerImageName(`${repo.repositoryUri}:latest`), + src: new DockerImageName(`${repo.repositoryUri}:stable`), + stage, + }); + const template = Template.fromStack(stack); + + test('matches snapshot', () => { + expect(template).toMatchSnapshot(); + }); +}); + +describe('lambda in pipelines pipeline', () => { + const stack = new Stack(); + const repository = new codecommit.Repository(stack, 'Repo', { + repositoryName: 'test-repo', + }); + + const pipeline = new pipelines.CodePipeline(stack, 'pipelines', { + synth: new pipelines.ShellStep('synth', { + input: pipelines.CodePipelineSource.codeCommit(repository, 'master'), + commands: [ + 'mkdir cdk.out', + 'touch cdk.out/test', + ], + }), + }); + + const wave = pipeline.addWave('CopyImage'); + + const repo = new ecr.Repository(stack, 'NginxRepo', { + repositoryName: 'nginx', + removalPolicy: RemovalPolicy.DESTROY, + }); + + new ECRDeployment(stack, 'ImageCopy', { + dest: new DockerImageName(`${repo.repositoryUri}:latest`), + src: new DockerImageName(`${repo.repositoryUri}:stable`), + wave, + }); + const template = Template.fromStack(stack); + test('matches snapshot', () => { expect(template).toMatchSnapshot(); });