From 178ddb92c0f11fadfd3cfd60ade5845402b122a1 Mon Sep 17 00:00:00 2001 From: i18n-tribe <62100288+i18n-tribe@users.noreply.github.com> Date: Tue, 11 Oct 2022 19:15:39 +0100 Subject: [PATCH] Add tests to ensure SAM supports CDK apps where Docker image asset `file` is a path to a docker file via subdirectories. --- .../cdk/test_sam_cdk_integration.py | 10 ++++++ .../src/main/java/com/myorg/JavaStack.java | 21 ++++++++++++ .../cdk_v1/python/python/python_stack.py | 34 +++++++++++++++++-- .../cdk_v1/typescript/lib/test-stack.ts | 25 ++++++++++++++ .../src/main/java/com/myorg/JavaStack.java | 22 ++++++++++++ .../cdk_v2/python/python/python_stack.py | 34 +++++++++++++++++-- .../cdk_v2/typescript/lib/test-stack.ts | 25 ++++++++++++++ .../Dockerfile | 16 +++++++++ .../DockerImageFunctionWithSharedCode/app.js | 24 +++++++++++++ .../Dockerfile | 16 +++++++++ .../FunctionImageAssetWithSharedCode/app.js | 24 +++++++++++++ .../ImagesWithSharedCode/SharedCode/shared.js | 4 +++ .../docker/ImagesWithSharedCode/package.json | 16 +++++++++ 13 files changed, 267 insertions(+), 4 deletions(-) create mode 100644 tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/DockerImageFunctionWithSharedCode/Dockerfile create mode 100644 tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/DockerImageFunctionWithSharedCode/app.js create mode 100644 tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/FunctionImageAssetWithSharedCode/Dockerfile create mode 100644 tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/FunctionImageAssetWithSharedCode/app.js create mode 100644 tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/SharedCode/shared.js create mode 100644 tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/package.json diff --git a/tests/iac_integration/cdk/test_sam_cdk_integration.py b/tests/iac_integration/cdk/test_sam_cdk_integration.py index 430fda764c..946dc1287e 100644 --- a/tests/iac_integration/cdk/test_sam_cdk_integration.py +++ b/tests/iac_integration/cdk/test_sam_cdk_integration.py @@ -111,6 +111,16 @@ def random_port(): ("/restapis/normal/functionGoRuntime", "Hello World from function construct with go runtime"), ("/restapis/normal/dockerImageFunction", "Hello World from docker image function construct"), ("/restapis/normal/functionImageAsset", "Hello World from function construct with image asset"), + ( + "/restapis/normal/dockerImageFunctionWithSharedCode", + "Hello World from docker image function construct " + "with a Dockerfile that shares code with another Dockerfile", + ), + ( + "/restapis/normal/functionImageAssetWithSharedCode", + "Hello World from function construct with image asset " + "with a Dockerfile that shares code with another Dockerfile", + ), ] ) @pytest.mark.flaky(reruns=3) diff --git a/tests/iac_integration/cdk/testdata/cdk_v1/java/src/main/java/com/myorg/JavaStack.java b/tests/iac_integration/cdk/testdata/cdk_v1/java/src/main/java/com/myorg/JavaStack.java index 86889b8d15..62b6f40764 100644 --- a/tests/iac_integration/cdk/testdata/cdk_v1/java/src/main/java/com/myorg/JavaStack.java +++ b/tests/iac_integration/cdk/testdata/cdk_v1/java/src/main/java/com/myorg/JavaStack.java @@ -192,6 +192,23 @@ public JavaStack(final Construct scope, final String id, final StackProps props) .tracing(Tracing.ACTIVE) .build(); + // both ways work when 'file' is a path via subfolders to the Dockerfile + // this is useful when multiple docker images share some common code + DockerImageFunction dockerImageFunctionWithSharedCode = DockerImageFunction.Builder.create(this, "DockerImageFunctionWithSharedCode") + .code(DockerImageCode.fromImageAsset("../../src/docker/ImagesWithSharedCode", + AssetImageCodeProps.builder().file("DockerImageFunctionWithSharedCode/Dockerfile").build() + ) + ).tracing(Tracing.ACTIVE) + .build(); + + Function functionImageAssetWithSharedCode = Function.Builder.create(this, "FunctionImageAssetWithSharedCode") + .code(Code.fromAssetImage("../../src/docker/ImagesWithSharedCode", + AssetImageCodeProps.builder().file("FunctionImageAssetWithSharedCode/Dockerfile").build())) + .handler(Handler.FROM_IMAGE) + .runtime(Runtime.FROM_IMAGE) + .tracing(Tracing.ACTIVE) + .build(); + //Rest APIs // Spec Rest Api @@ -239,6 +256,10 @@ public JavaStack(final Construct scope, final String id, final StackProps props) .addMethod("GET", new LambdaIntegration(dockerImageFunction)); normalRootResource.addResource("functionImageAsset") .addMethod("GET", new LambdaIntegration(functionImageAsset)); + normalRootResource.addResource("dockerImageFunctionWithSharedCode") + .addMethod("GET", new LambdaIntegration(dockerImageFunctionWithSharedCode)); + normalRootResource.addResource("functionImageAssetWithSharedCode") + .addMethod("GET", new LambdaIntegration(functionImageAssetWithSharedCode)); // Nested Stack new NestedStack1(this, "NestedStack"); diff --git a/tests/iac_integration/cdk/testdata/cdk_v1/python/python/python_stack.py b/tests/iac_integration/cdk/testdata/cdk_v1/python/python/python_stack.py index 643313486a..c453a4eb79 100644 --- a/tests/iac_integration/cdk/testdata/cdk_v1/python/python/python_stack.py +++ b/tests/iac_integration/cdk/testdata/cdk_v1/python/python/python_stack.py @@ -217,7 +217,7 @@ def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None: self, "DockerImageFunction", code=lambda1.DockerImageCode.from_image_asset( - "../../src/docker/DockerImageFunctionConstruct", + directory="../../src/docker/DockerImageFunctionConstruct", file="Dockerfile", ), tracing=lambda1.Tracing.ACTIVE, @@ -228,7 +228,7 @@ def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None: self, "FunctionImageAsset", code=lambda1.Code.from_asset_image( - "../../src/docker/FunctionConstructWithImageAssetCode", + directory="../../src/docker/FunctionConstructWithImageAssetCode", file="Dockerfile", ), handler=lambda1.Handler.FROM_IMAGE, @@ -236,6 +236,30 @@ def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None: tracing=lambda1.Tracing.ACTIVE, ) + # both ways work when 'file' is a path via subfolders to the Dockerfile + # this is useful when multiple docker images share some common code + docker_image_function_with_shared_code = lambda1.DockerImageFunction( + self, + "DockerImageFunctionWithSharedCode", + code=lambda1.DockerImageCode.from_image_asset( + directory="../../src/docker/ImagesWithSharedCode", + file="DockerImageFunctionWithSharedCode/Dockerfile", + ), + tracing=lambda1.Tracing.ACTIVE, + ) + + function_image_asset_with_shared_code = lambda1.Function( + self, + "FunctionImageAssetWithSharedCode", + code=lambda1.Code.from_asset_image( + directory="../../src/docker/ImagesWithSharedCode", + file="FunctionImageAssetWithSharedCode/Dockerfile", + ), + handler=lambda1.Handler.FROM_IMAGE, + runtime=lambda1.Runtime.FROM_IMAGE, + tracing=lambda1.Tracing.ACTIVE, + ) + # Rest APIs # Spec Rest Api @@ -287,6 +311,12 @@ def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None: normal_root_resource.add_resource("functionImageAsset").add_method( "GET", LambdaIntegration(function_image_asset) ) + normal_root_resource.add_resource("dockerImageFunctionWithSharedCode").add_method( + "GET", LambdaIntegration(docker_image_function_with_shared_code) + ) + normal_root_resource.add_resource("functionImageAssetWithSharedCode").add_method( + "GET", LambdaIntegration(function_image_asset_with_shared_code) + ) # Nested Stack NestedStack1(self, "NestedStack") diff --git a/tests/iac_integration/cdk/testdata/cdk_v1/typescript/lib/test-stack.ts b/tests/iac_integration/cdk/testdata/cdk_v1/typescript/lib/test-stack.ts index 3850e0196b..fa500f5929 100644 --- a/tests/iac_integration/cdk/testdata/cdk_v1/typescript/lib/test-stack.ts +++ b/tests/iac_integration/cdk/testdata/cdk_v1/typescript/lib/test-stack.ts @@ -191,6 +191,25 @@ export class CDKSupportDemoRootStack extends cdk.Stack { tracing: lambda.Tracing.ACTIVE, }); + // both ways work when 'file' is a path via subfolders to the Dockerfile + // this is useful when multiple docker images share some common code + const dockerImageFunctionWithSharedCode = new lambda.DockerImageFunction(this, "DockerImageFunctionWithSharedCode", { + code: lambda.DockerImageCode.fromImageAsset("../../src/docker/ImagesWithSharedCode", { + file: "DockerImageFunctionWithSharedCode/Dockerfile", + }), + tracing: lambda.Tracing.ACTIVE, + }); + + // another way + const functionImageAssetWithSharedCode = new lambda.Function(this, "FunctionImageAssetWithSharedCode", { + code: lambda.Code.fromAssetImage("../../src/docker/ImagesWithSharedCode", { + file: "FunctionImageAssetWithSharedCode/Dockerfile", + }), + handler: lambda.Handler.FROM_IMAGE, + runtime: lambda.Runtime.FROM_IMAGE, + tracing: lambda.Tracing.ACTIVE, + }); + //Rest APIs @@ -246,6 +265,12 @@ export class CDKSupportDemoRootStack extends cdk.Stack { normalRootResource.addResource('functionImageAsset') .addMethod('GET', new LambdaIntegration(functionImageAsset)); + + normalRootResource.addResource('dockerImageFunctionWithSharedCode') + .addMethod('GET', new LambdaIntegration(dockerImageFunctionWithSharedCode)); + + normalRootResource.addResource('functionImageAssetWithSharedCode') + .addMethod('GET', new LambdaIntegration(functionImageAssetWithSharedCode)); // Nested Stack new NestedStack1(this, 'NestedStack' ,{}); diff --git a/tests/iac_integration/cdk/testdata/cdk_v2/java/src/main/java/com/myorg/JavaStack.java b/tests/iac_integration/cdk/testdata/cdk_v2/java/src/main/java/com/myorg/JavaStack.java index cd7252823a..38fd03a99a 100644 --- a/tests/iac_integration/cdk/testdata/cdk_v2/java/src/main/java/com/myorg/JavaStack.java +++ b/tests/iac_integration/cdk/testdata/cdk_v2/java/src/main/java/com/myorg/JavaStack.java @@ -193,6 +193,23 @@ public JavaStack(final Construct scope, final String id, final StackProps props) .tracing(Tracing.ACTIVE) .build(); + // both ways work when 'file' is a path via subfolders to the Dockerfile + // this is useful when multiple docker images share some common code + DockerImageFunction dockerImageFunctionWithSharedCode = DockerImageFunction.Builder.create(this, "DockerImageFunctionWithSharedCode") + .code(DockerImageCode.fromImageAsset("../../src/docker/ImagesWithSharedCode", + AssetImageCodeProps.builder().file("DockerImageFunctionWithSharedCode/Dockerfile").build() + ) + ).tracing(Tracing.ACTIVE) + .build(); + + Function functionImageAssetWithSharedCode = Function.Builder.create(this, "FunctionImageAssetWithSharedCode") + .code(Code.fromAssetImage("../../src/docker/ImagesWithSharedCode", + AssetImageCodeProps.builder().file("FunctionImageAssetWithSharedCode/Dockerfile").build())) + .handler(Handler.FROM_IMAGE) + .runtime(Runtime.FROM_IMAGE) + .tracing(Tracing.ACTIVE) + .build(); + //Rest APIs // Spec Rest Api @@ -240,6 +257,11 @@ public JavaStack(final Construct scope, final String id, final StackProps props) .addMethod("GET", new LambdaIntegration(dockerImageFunction)); normalRootResource.addResource("functionImageAsset") .addMethod("GET", new LambdaIntegration(functionImageAsset)); + normalRootResource.addResource("dockerImageFunctionWithSharedCode") + .addMethod("GET", new LambdaIntegration(dockerImageFunctionWithSharedCode)); + normalRootResource.addResource("functionImageAssetWithSharedCode") + .addMethod("GET", new LambdaIntegration(functionImageAssetWithSharedCode)); + // Nested Stack new NestedStack1(this, "NestedStack"); diff --git a/tests/iac_integration/cdk/testdata/cdk_v2/python/python/python_stack.py b/tests/iac_integration/cdk/testdata/cdk_v2/python/python/python_stack.py index 6bd63a6eb8..730613ca41 100644 --- a/tests/iac_integration/cdk/testdata/cdk_v2/python/python/python_stack.py +++ b/tests/iac_integration/cdk/testdata/cdk_v2/python/python/python_stack.py @@ -217,7 +217,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: self, "DockerImageFunction", code=lambda1.DockerImageCode.from_image_asset( - "../../src/docker/DockerImageFunctionConstruct", + directory="../../src/docker/DockerImageFunctionConstruct", file="Dockerfile", ), tracing=lambda1.Tracing.ACTIVE, @@ -228,7 +228,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: self, "FunctionImageAsset", code=lambda1.Code.from_asset_image( - "../../src/docker/FunctionConstructWithImageAssetCode", + directory="../../src/docker/FunctionConstructWithImageAssetCode", file="Dockerfile", ), handler=lambda1.Handler.FROM_IMAGE, @@ -236,6 +236,30 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: tracing=lambda1.Tracing.ACTIVE, ) + # both ways work when 'file' is a path via subfolders to the Dockerfile + # this is useful when multiple docker images share some common code + docker_image_function_with_shared_code = lambda1.DockerImageFunction( + self, + "DockerImageFunctionWithSharedCode", + code=lambda1.DockerImageCode.from_image_asset( + directory="../../src/docker/ImagesWithSharedCode", + file="DockerImageFunctionWithSharedCode/Dockerfile", + ), + tracing=lambda1.Tracing.ACTIVE, + ) + + function_image_asset_with_shared_code = lambda1.Function( + self, + "FunctionImageAssetWithSharedCode", + code=lambda1.Code.from_asset_image( + directory="../../src/docker/ImagesWithSharedCode", + file="FunctionImageAssetWithSharedCode/Dockerfile", + ), + handler=lambda1.Handler.FROM_IMAGE, + runtime=lambda1.Runtime.FROM_IMAGE, + tracing=lambda1.Tracing.ACTIVE, + ) + # Rest APIs # Spec Rest Api @@ -287,6 +311,12 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: normal_root_resource.add_resource("functionImageAsset").add_method( "GET", LambdaIntegration(function_image_asset) ) + normal_root_resource.add_resource("dockerImageFunctionWithSharedCode").add_method( + "GET", LambdaIntegration(docker_image_function_with_shared_code) + ) + normal_root_resource.add_resource("functionImageAssetWithSharedCode").add_method( + "GET", LambdaIntegration(function_image_asset_with_shared_code) + ) # Nested Stack NestedStack1(self, "NestedStack") diff --git a/tests/iac_integration/cdk/testdata/cdk_v2/typescript/lib/test-stack.ts b/tests/iac_integration/cdk/testdata/cdk_v2/typescript/lib/test-stack.ts index eabd9ede5d..2d88a8ad26 100644 --- a/tests/iac_integration/cdk/testdata/cdk_v2/typescript/lib/test-stack.ts +++ b/tests/iac_integration/cdk/testdata/cdk_v2/typescript/lib/test-stack.ts @@ -190,6 +190,25 @@ export class CDKSupportDemoRootStack extends cdk.Stack { tracing: lambda.Tracing.ACTIVE, }); + // both ways work when 'file' is a path via subfolders to the Dockerfile + // this is useful when multiple docker images share some common code + const dockerImageFunctionWithSharedCode = new lambda.DockerImageFunction(this, "DockerImageFunctionWithSharedCode", { + code: lambda.DockerImageCode.fromImageAsset("../../src/docker/ImagesWithSharedCode", { + file: "DockerImageFunctionWithSharedCode/Dockerfile", + }), + tracing: lambda.Tracing.ACTIVE, + }); + + // another way + const functionImageAssetWithSharedCode = new lambda.Function(this, "FunctionImageAssetWithSharedCode", { + code: lambda.Code.fromAssetImage("../../src/docker/ImagesWithSharedCode", { + file: "FunctionImageAssetWithSharedCode/Dockerfile", + }), + handler: lambda.Handler.FROM_IMAGE, + runtime: lambda.Runtime.FROM_IMAGE, + tracing: lambda.Tracing.ACTIVE, + }); + //Rest APIs @@ -246,6 +265,12 @@ export class CDKSupportDemoRootStack extends cdk.Stack { normalRootResource.addResource('functionImageAsset') .addMethod('GET', new LambdaIntegration(functionImageAsset)); + normalRootResource.addResource('dockerImageFunctionWithSharedCode') + .addMethod('GET', new LambdaIntegration(dockerImageFunctionWithSharedCode)); + + normalRootResource.addResource('functionImageAssetWithSharedCode') + .addMethod('GET', new LambdaIntegration(functionImageAssetWithSharedCode)); + // Nested Stack new NestedStack1(this, 'NestedStack' ,{}); } diff --git a/tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/DockerImageFunctionWithSharedCode/Dockerfile b/tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/DockerImageFunctionWithSharedCode/Dockerfile new file mode 100644 index 0000000000..a2c99c17fd --- /dev/null +++ b/tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/DockerImageFunctionWithSharedCode/Dockerfile @@ -0,0 +1,16 @@ +FROM public.ecr.aws/lambda/nodejs:14 + +# Add the lambda handler for this feature +COPY DockerImageFunctionWithSharedCode/app.js ./ + +# Add the shared code +COPY SharedCode/ ./SharedCode + +# Add the shared dependencies +COPY package.json ./ + +# Install the dependencies +RUN npm install + +# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile) +CMD [ "app.lambdaHandler" ] \ No newline at end of file diff --git a/tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/DockerImageFunctionWithSharedCode/app.js b/tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/DockerImageFunctionWithSharedCode/app.js new file mode 100644 index 0000000000..239c7bafad --- /dev/null +++ b/tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/DockerImageFunctionWithSharedCode/app.js @@ -0,0 +1,24 @@ +var gen = require('unique-names-generator'); +const {sayHelloWorld} = require("./SharedCode/shared"); + +const colorName = gen.uniqueNamesGenerator({ + dictionaries: [gen.colors] +}); + + +exports.lambdaHandler = async(event, context) => { + let response; + + try { + response = { + 'statusCode': 200, + 'body': JSON.stringify({ + message: sayHelloWorld("docker image function construct"), + }), + }; + } catch (err) { + console.log(err); + return err; + } + return response; +}; diff --git a/tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/FunctionImageAssetWithSharedCode/Dockerfile b/tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/FunctionImageAssetWithSharedCode/Dockerfile new file mode 100644 index 0000000000..a68a4f5978 --- /dev/null +++ b/tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/FunctionImageAssetWithSharedCode/Dockerfile @@ -0,0 +1,16 @@ +FROM public.ecr.aws/lambda/nodejs:14 + +# Add the lambda handler for this feature +COPY FunctionImageAssetWithSharedCode/app.js ./ + +# Add the shared code +COPY SharedCode/ ./SharedCode + +# Add the shared dependencies +COPY package.json ./ + +# Install the dependencies +RUN npm install + +# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile) +CMD [ "app.lambdaHandler" ] \ No newline at end of file diff --git a/tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/FunctionImageAssetWithSharedCode/app.js b/tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/FunctionImageAssetWithSharedCode/app.js new file mode 100644 index 0000000000..f1dca39268 --- /dev/null +++ b/tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/FunctionImageAssetWithSharedCode/app.js @@ -0,0 +1,24 @@ +var gen = require('unique-names-generator'); +const {sayHelloWorld} = require("./SharedCode/shared"); + +const colorName = gen.uniqueNamesGenerator({ + dictionaries: [gen.colors] +}); + + +exports.lambdaHandler = async(event, context) => { + let response; + + try { + response = { + 'statusCode': 200, + 'body': JSON.stringify({ + message: sayHelloWorld("function construct with image asset"), + }), + }; + } catch (err) { + console.log(err); + return err; + } + return response; +}; diff --git a/tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/SharedCode/shared.js b/tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/SharedCode/shared.js new file mode 100644 index 0000000000..334a8051fe --- /dev/null +++ b/tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/SharedCode/shared.js @@ -0,0 +1,4 @@ + +exports.sayHelloWorld = (from) => { + return `Hello World from ${from} with a Dockerfile that shares code with another Dockerfile`; +} diff --git a/tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/package.json b/tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/package.json new file mode 100644 index 0000000000..7b15f7c978 --- /dev/null +++ b/tests/iac_integration/cdk/testdata/src/docker/ImagesWithSharedCode/package.json @@ -0,0 +1,16 @@ +{ + "name": "randomColors", + "version": "0.1.0", + "bin": { + "randomColors": "bin/app.js" + }, + "scripts": { + "build": "tsc", + "watch": "tsc -w", + "test": "jest", + "cdk": "cdk" + }, + "dependencies": { + "unique-names-generator": "^4.6.0" + } +}