[go: up one dir, main page]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Remove build golang lambda #535

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
f3f6aa2
chore: try crane
wchaws Feb 20, 2024
f13bbcf
chore: try crane wip
wchaws Feb 20, 2024
0eff792
chore: try crane wip
wchaws Feb 20, 2024
96c307b
chore: projen update
wchaws Feb 20, 2024
8fd1025
chore: crane support read creds from secrets manager
wchaws Feb 20, 2024
7b43ef5
chore: self mutation
invalid-email-address Feb 20, 2024
a0f0d52
chore: remove golang build
wchaws Feb 21, 2024
43efd4f
Merge branch 'dev' of https://github.com/cdklabs/cdk-ecr-deployment i…
wchaws Feb 21, 2024
02d7f83
fxi: build error
wchaws Feb 21, 2024
c4531a1
fix: build error
wchaws Feb 21, 2024
f90e103
Merge branch 'main' into dev
wchaws Feb 21, 2024
7c11e1b
chore: remove build lambda
wchaws Feb 21, 2024
af1c525
chore: add unit test for python
wchaws Feb 21, 2024
c8e6192
chore: enable lambda test
wchaws Feb 21, 2024
bf66e8e
chore: self mutation
invalid-email-address Feb 21, 2024
d8438ae
chore: add python unit test
wchaws Feb 21, 2024
5c63612
Merge branch 'dev' of https://github.com/cdklabs/cdk-ecr-deployment i…
wchaws Feb 21, 2024
13462b1
chore: move pyproject.toml -> lambda2/pyproject.toml
wchaws Feb 21, 2024
1939c90
Merge branch 'main' into dev
wchaws Mar 3, 2024
b1b8fc5
chore: add more python ut
wchaws Mar 3, 2024
8013833
Merge branch 'dev' of https://github.com/cdklabs/cdk-ecr-deployment i…
wchaws Mar 3, 2024
620fb87
chore: remove golang lambda
wchaws Mar 3, 2024
20386dc
chore: add comments
wchaws Mar 3, 2024
58a4878
chore: update README.md
wchaws Mar 3, 2024
963dedf
chore: update REAMDE.md
wchaws Mar 3, 2024
1614181
chore: update README
wchaws Mar 3, 2024
8e62c49
chore: update README
wchaws Mar 3, 2024
7b80c20
Merge branch 'main' into dev
wchaws Mar 11, 2024
24865dd
Merge branch 'main' into dev
wchaws Mar 16, 2024
e58665a
Merge branch 'main' into dev
wchaws Mar 19, 2024
aee18b7
Merge branch 'main' into dev
wchaws Apr 5, 2024
b6d829c
Merge branch 'main' into dev
wchaws Jun 13, 2024
5d7249c
Merge branch 'main' into dev
wchaws Jun 14, 2024
0f0ff9e
chore: set major version to 4
wchaws Jun 14, 2024
41431b3
Merge branch 'main' of github.com:cdklabs/cdk-ecr-deployment into dev
wchaws Jun 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
chore: try crane
  • Loading branch information
wchaws committed Feb 20, 2024
commit f3f6aa2c4b3b7c43aa08891fcc3bb8f888055e9d
40 changes: 40 additions & 0 deletions lambda2/index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import subprocess


def proc_run(command):
return subprocess.check_output(command, text=True, stderr=subprocess.STDOUT)


def on_event(event, _):
request_type = event["RequestType"]
props = event["ResourceProperties"]

if request_type == "Delete":
print("We don't support delete remote image repo!")
elif request_type == "Create" or request_type == "Update":
print(props)
print(proc_run(["/opt/crane/crane", "help"]))


def lambda_handler(event, context):
# Command to execute using Crane
command = ["crane", "help"]

try:
# Execute the command and capture the output
result = subprocess.check_output(command, text=True, stderr=subprocess.STDOUT)

# Output the result to stdout
print("Command output:")
print(result)
return {"statusCode": 200, "body": "Command executed successfully."}
except subprocess.CalledProcessError as e:
# Output error message to stdout
print("Command execution failed. Error:")
print(e.output)
return {"statusCode": 500, "body": "Command execution failed."}
except Exception as e:
# Output exception to stdout
print("Exception occurred:")
print(str(e))
return {"statusCode": 500, "body": "An error occurred."}
150 changes: 62 additions & 88 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@
// SPDX-License-Identifier: Apache-2.0


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, Duration, CustomResource, Token } from 'aws-cdk-lib';
import { PolicyStatement, AddToPrincipalPolicyResult } from 'aws-cdk-lib/aws-iam';
import { custom_resources as cr, aws_ec2 as ec2, aws_iam as iam, aws_lambda as lambda, Duration, CustomResource, Token } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { shouldUsePrebuiltLambda } from './config';

export interface ECRDeploymentProps {

Expand Down Expand Up @@ -90,102 +87,86 @@ export interface IImageName {
readonly uri: string;

/**
* The credentials of the docker image. Format `user:password` or `AWS Secrets Manager secret arn` or `AWS Secrets Manager secret name`
* The credentials of the docker image. Format `user:password` or `AWS Secrets Manager secret arn` or `AWS Secrets Manager secret name`
*/
creds?: string;
}

function getCode(buildImage: string): lambda.AssetCode {
if (shouldUsePrebuiltLambda()) {
try {
const installScript = path.join(__dirname, '../lambda/install.js');
const prebuiltPath = path.join(__dirname, '../lambda/out');
child_process.execFileSync(process.argv0, [installScript, prebuiltPath]);

return lambda.Code.fromAsset(prebuiltPath);
} catch (err) {
console.warn(`Can not get prebuilt lambda: ${err}`);
}
}

return lambda.Code.fromDockerBuild(path.join(__dirname, '../lambda'), {
buildArgs: {
buildImage,
},
});
}

export class DockerImageName implements IImageName {
public constructor(private name: string, public creds?: string) { }
public get uri(): string { return `docker://${this.name}`; }
public get uri(): string { return this.name; }
}

export class S3ArchiveName implements IImageName {
private name: string;
public constructor(p: string, ref?: string, public creds?: string) {
this.name = p;
if (ref) {
this.name += ':' + ref;
}

class CraneLayer extends lambda.LayerVersion {
constructor(scope: Construct, id: string) {
super(scope, id, {
code: lambda.Code.fromAsset(path.join(__dirname, '../layer/layer.zip'), {}),
description: '/opt/crane/crane',
license: 'Apache-2.0',
});
}
public get uri(): string { return `s3://${this.name}`; }
}

export class ECRDeployment extends Construct {
private handler: lambda.SingletonFunction;

constructor(scope: Construct, id: string, props: ECRDeploymentProps) {
super(scope, id);
const memoryLimit = props.memoryLimit ?? 512;
this.handler = new lambda.SingletonFunction(this, 'CustomResourceHandler', {
uuid: this.renderSingletonUuid(memoryLimit),
code: getCode(props.buildImage ?? 'golang:1'),
runtime: lambda.Runtime.PROVIDED_AL2023,
handler: 'bootstrap',
environment: props.environment,
lambdaPurpose: 'Custom::CDKECRDeployment',
timeout: Duration.minutes(15),
role: props.role,
memorySize: memoryLimit,
vpc: props.vpc,
vpcSubnets: props.vpcSubnets,
securityGroups: props.securityGroups,
});

const handlerRole = this.handler.role;
if (!handlerRole) { throw new Error('lambda.SingletonFunction should have created a Role'); }

handlerRole.addToPrincipalPolicy(
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: [
'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',
const memoryLimit = props.memoryLimit ?? 512;
const provider = new cr.Provider(this, 'Provider', {
onEventHandler: new lambda.SingletonFunction(this, 'CustomResourceHandler', {
uuid: this.renderSingletonUuid(memoryLimit),
code: lambda.Code.fromAsset(path.join(__dirname, '../lambda2')),
runtime: lambda.Runtime.PYTHON_3_11,
handler: 'index.on_event',
environment: Object.assign({
DOCKER_CONFIG: '/tmp/.docker',
}, props.environment),
lambdaPurpose: 'Custom::CDKECRDeployment',
timeout: Duration.minutes(15),
role: props.role,
vpc: props.vpc,
memorySize: memoryLimit,
vpcSubnets: props.vpcSubnets,
securityGroups: props.securityGroups,
initialPolicy: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: [
'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',
],
resources: ['*'],
}),
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: [
's3:GetObject',
],
resources: ['*'],
}),
],
layers: [
new CraneLayer(scope, 'CraneLayer'),
],
resources: ['*'],
}));
handlerRole.addToPrincipalPolicy(new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: [
's3:GetObject',
],
resources: ['*'],
}));
}),
});

new CustomResource(this, 'CustomResource', {
serviceToken: this.handler.functionArn,
serviceToken: provider.serviceToken,
resourceType: 'Custom::CDKBucketDeployment',
properties: {
SrcImage: props.src.uri,
Expand All @@ -196,13 +177,6 @@ export class ECRDeployment extends Construct {
});
}

public addToPrincipalPolicy(statement: PolicyStatement): AddToPrincipalPolicyResult {
const handlerRole = this.handler.role;
if (!handlerRole) { throw new Error('lambda.SingletonFunction should have created a Role'); }

return handlerRole.addToPrincipalPolicy(statement);
}

private renderSingletonUuid(memoryLimit?: number) {
let uuid = 'bd07c930-edb9-4112-a20f-03f096f53666';

Expand Down
30 changes: 15 additions & 15 deletions test/example.ecr-deployment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import * as path from 'path';
import {
aws_iam as iam,
// aws_iam as iam,
aws_ecr as ecr,
aws_ecr_assets as assets,
Stack,
Expand All @@ -19,8 +19,8 @@ class TestECRDeployment extends Stack {
super(scope, id, props);

const repo = new ecr.Repository(this, 'NginxRepo', {
repositoryName: 'nginx',
removalPolicy: RemovalPolicy.DESTROY,
repositoryName: 'nginx3',
removalPolicy: RemovalPolicy.RETAIN,
});

// const repo = ecr.Repository.fromRepositoryName(this, 'Repo', 'test');
Expand All @@ -34,16 +34,16 @@ class TestECRDeployment extends Stack {
dest: new ecrDeploy.DockerImageName(`${repo.repositoryUri}:latest`),
});

new ecrDeploy.ECRDeployment(this, 'DeployDockerImage', {
src: new ecrDeploy.DockerImageName('javacs3/javacs3:latest', 'dockerhub'),
dest: new ecrDeploy.DockerImageName(`${repo.repositoryUri}:dockerhub`),
}).addToPrincipalPolicy(new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: [
'secretsmanager:GetSecretValue',
],
resources: ['*'],
}));
// new ecrDeploy.ECRDeployment(this, 'DeployDockerImage', {
// src: new ecrDeploy.DockerImageName('javacs3/javacs3:latest', 'dockerhub'),
// dest: new ecrDeploy.DockerImageName(`${repo.repositoryUri}:dockerhub`),
// }).addToPrincipalPolicy(new iam.PolicyStatement({
// effect: iam.Effect.ALLOW,
// actions: [
// 'secretsmanager:GetSecretValue',
// ],
// resources: ['*'],
// }));

// Your can also copy a docker archive image tarball from s3
// new ecrDeploy.ECRDeployment(this, 'DeployDockerImage', {
Expand All @@ -55,8 +55,8 @@ class TestECRDeployment extends Stack {

const app = new App();

new TestECRDeployment(app, 'test-ecr-deployments', {
env: { region: 'ap-northeast-1' },
new TestECRDeployment(app, 'test-ecr-deployments3', {
env: { region: 'us-west-2' },
});

app.synth();