From f0ea57f973a8b8fe0d48dbe7eca89d0291509f87 Mon Sep 17 00:00:00 2001 From: Mohamed Elasmar <71043312+moelasmar@users.noreply.github.com> Date: Fri, 19 Nov 2021 12:42:39 -0800 Subject: [PATCH] fix(assets): add missing SAM asset metadata information (#17591) Following up on issue #14593 The integration with SAM tool requires to have some more info about the Assets. SAM needs to know if the Asset was already bundled or not, and what is the original asset path before staging. This change is to add the following assets metadata: - aws:asset:is-bundled - aws:asset:original-path ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../@aws-cdk/aws-lambda/test/code.test.ts | 7 ++++++- .../@aws-cdk/aws-lambda/test/layers.test.ts | 5 ++++- .../aws-logs/test/log-retention.test.ts | 2 ++ packages/@aws-cdk/aws-s3-assets/lib/asset.ts | 20 ++++++++++++++++++- .../@aws-cdk/aws-s3-assets/test/asset.test.ts | 8 ++++++++ packages/@aws-cdk/cx-api/lib/assets.ts | 2 ++ 6 files changed, 41 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/test/code.test.ts b/packages/@aws-cdk/aws-lambda/test/code.test.ts index 40db469cc12d4..be6172c2454fc 100644 --- a/packages/@aws-cdk/aws-lambda/test/code.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/code.test.ts @@ -74,6 +74,8 @@ describe('code', () => { expect(stack).toHaveResource('AWS::Lambda::Function', { Metadata: { [cxapi.ASSET_RESOURCE_METADATA_PATH_KEY]: 'asset.9678c34eca93259d11f2d714177347afd66c50116e1e08996eff893d3ca81232', + [cxapi.ASSET_RESOURCE_METADATA_ORIGINAL_PATH_KEY]: location, + [cxapi.ASSET_RESOURCE_METADATA_IS_BUNDLED_KEY]: false, [cxapi.ASSET_RESOURCE_METADATA_PROPERTY_KEY]: 'Code', }, }, ResourcePart.CompleteDefinition); @@ -462,8 +464,9 @@ describe('code', () => { stack.node.setContext(cxapi.ASSET_RESOURCE_METADATA_ENABLED_CONTEXT, true); // when + const FunctionCodepath = path.join(__dirname, 'docker-build-lambda'); new lambda.Function(stack, 'Fn', { - code: lambda.Code.fromDockerBuild(path.join(__dirname, 'docker-build-lambda')), + code: lambda.Code.fromDockerBuild(FunctionCodepath), handler: 'index.handler', runtime: lambda.Runtime.NODEJS_12_X, }); @@ -472,6 +475,8 @@ describe('code', () => { expect(stack).toHaveResource('AWS::Lambda::Function', { Metadata: { [cxapi.ASSET_RESOURCE_METADATA_PATH_KEY]: 'asset.fbafdbb9ae8d1bae0def415b791a93c486d18ebc63270c748abecc3ac0ab9533', + [cxapi.ASSET_RESOURCE_METADATA_ORIGINAL_PATH_KEY]: FunctionCodepath, + [cxapi.ASSET_RESOURCE_METADATA_IS_BUNDLED_KEY]: false, [cxapi.ASSET_RESOURCE_METADATA_PROPERTY_KEY]: 'Code', }, }, ResourcePart.CompleteDefinition); diff --git a/packages/@aws-cdk/aws-lambda/test/layers.test.ts b/packages/@aws-cdk/aws-lambda/test/layers.test.ts index 1c416236c0980..6ec497848cfdf 100644 --- a/packages/@aws-cdk/aws-lambda/test/layers.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/layers.test.ts @@ -74,14 +74,17 @@ describe('layers', () => { stack.node.setContext(cxapi.ASSET_RESOURCE_METADATA_ENABLED_CONTEXT, true); // WHEN + let layerCodePath = path.join(__dirname, 'layer-code'); new lambda.LayerVersion(stack, 'layer', { - code: lambda.Code.fromAsset(path.join(__dirname, 'layer-code')), + code: lambda.Code.fromAsset(layerCodePath), }); // THEN expect(canonicalizeTemplate(SynthUtils.toCloudFormation(stack))).toHaveResource('AWS::Lambda::LayerVersion', { Metadata: { 'aws:asset:path': 'asset.Asset1Hash', + 'aws:asset:original-path': layerCodePath, + 'aws:asset:is-bundled': false, 'aws:asset:property': 'Content', }, }, ResourcePart.CompleteDefinition); diff --git a/packages/@aws-cdk/aws-logs/test/log-retention.test.ts b/packages/@aws-cdk/aws-logs/test/log-retention.test.ts index af746f956e675..8a5d1241c2f20 100644 --- a/packages/@aws-cdk/aws-logs/test/log-retention.test.ts +++ b/packages/@aws-cdk/aws-logs/test/log-retention.test.ts @@ -196,6 +196,8 @@ describe('log retention', () => { expect(stack).toHaveResource('AWS::Lambda::Function', { Metadata: { 'aws:asset:path': assetLocation, + 'aws:asset:original-path': assetLocation, + 'aws:asset:is-bundled': false, 'aws:asset:property': 'Code', }, }, ResourcePart.CompleteDefinition); diff --git a/packages/@aws-cdk/aws-s3-assets/lib/asset.ts b/packages/@aws-cdk/aws-s3-assets/lib/asset.ts index 0777602e788f6..46f8cb2901e8e 100644 --- a/packages/@aws-cdk/aws-s3-assets/lib/asset.ts +++ b/packages/@aws-cdk/aws-s3-assets/lib/asset.ts @@ -120,13 +120,29 @@ export class Asset extends CoreConstruct implements cdk.IAsset { public readonly assetHash: string; + /** + * The original Asset Path before it got staged. + * + * If asset staging is disabled, this will be same value as assetPath. + * If asset staging is enabled, it will be the Asset original path before staging. + */ + private readonly originalAssetPath: string; + + /** + * Indicates if this asset got bundled before staged, or not. + */ + private readonly isBundled: boolean; + constructor(scope: Construct, id: string, props: AssetProps) { super(scope, id); + this.originalAssetPath = path.resolve(props.path); + this.isBundled = props.bundling != null; + // stage the asset source (conditionally). const staging = new cdk.AssetStaging(this, 'Stage', { ...props, - sourcePath: path.resolve(props.path), + sourcePath: this.originalAssetPath, follow: props.followSymlinks ?? toSymlinkFollow(props.follow), assetHash: props.assetHash ?? props.sourceHash, }); @@ -191,6 +207,8 @@ export class Asset extends CoreConstruct implements cdk.IAsset { // points to a local path in order to enable local invocation of this function. resource.cfnOptions.metadata = resource.cfnOptions.metadata || { }; resource.cfnOptions.metadata[cxapi.ASSET_RESOURCE_METADATA_PATH_KEY] = this.assetPath; + resource.cfnOptions.metadata[cxapi.ASSET_RESOURCE_METADATA_ORIGINAL_PATH_KEY] = this.originalAssetPath; + resource.cfnOptions.metadata[cxapi.ASSET_RESOURCE_METADATA_IS_BUNDLED_KEY] = this.isBundled; resource.cfnOptions.metadata[cxapi.ASSET_RESOURCE_METADATA_PROPERTY_KEY] = resourceProperty; } diff --git a/packages/@aws-cdk/aws-s3-assets/test/asset.test.ts b/packages/@aws-cdk/aws-s3-assets/test/asset.test.ts index cf0a5c7bc03af..4ea59bff3c7ef 100644 --- a/packages/@aws-cdk/aws-s3-assets/test/asset.test.ts +++ b/packages/@aws-cdk/aws-s3-assets/test/asset.test.ts @@ -203,6 +203,8 @@ test('addResourceMetadata can be used to add CFN metadata to resources', () => { expect(stack).toHaveResource('My::Resource::Type', { Metadata: { 'aws:asset:path': 'asset.6b84b87243a4a01c592d78e1fd3855c4bfef39328cd0a450cc97e81717fea2a2', + 'aws:asset:original-path': location, + 'aws:asset:is-bundled': false, 'aws:asset:property': 'PropName', }, }, ResourcePart.CompleteDefinition); @@ -222,6 +224,8 @@ test('asset metadata is only emitted if ASSET_RESOURCE_METADATA_ENABLED_CONTEXT expect(stack).not.toHaveResource('My::Resource::Type', { Metadata: { 'aws:asset:path': SAMPLE_ASSET_DIR, + 'aws:asset:original-path': SAMPLE_ASSET_DIR, + 'aws:asset:is-bundled': false, 'aws:asset:property': 'PropName', }, }, ResourcePart.CompleteDefinition); @@ -351,6 +355,8 @@ describe('staging', () => { const template = SynthUtils.synthesize(stack).template; expect(template.Resources.MyResource.Metadata).toEqual({ 'aws:asset:path': 'asset.6b84b87243a4a01c592d78e1fd3855c4bfef39328cd0a450cc97e81717fea2a2', + 'aws:asset:original-path': SAMPLE_ASSET_DIR, + 'aws:asset:is-bundled': false, 'aws:asset:property': 'PropName', }); }); @@ -377,6 +383,8 @@ describe('staging', () => { const template = SynthUtils.synthesize(stack).template; expect(template.Resources.MyResource.Metadata).toEqual({ 'aws:asset:path': SAMPLE_ASSET_DIR, + 'aws:asset:original-path': SAMPLE_ASSET_DIR, + 'aws:asset:is-bundled': false, 'aws:asset:property': 'PropName', }); }); diff --git a/packages/@aws-cdk/cx-api/lib/assets.ts b/packages/@aws-cdk/cx-api/lib/assets.ts index 0b3eaa52cefb5..010bafc80c3a5 100644 --- a/packages/@aws-cdk/cx-api/lib/assets.ts +++ b/packages/@aws-cdk/cx-api/lib/assets.ts @@ -14,6 +14,8 @@ export const ASSET_RESOURCE_METADATA_DOCKERFILE_PATH_KEY = 'aws:asset:dockerfile export const ASSET_RESOURCE_METADATA_DOCKER_BUILD_ARGS_KEY = 'aws:asset:docker-build-args'; export const ASSET_RESOURCE_METADATA_DOCKER_BUILD_TARGET_KEY = 'aws:asset:docker-build-target'; export const ASSET_RESOURCE_METADATA_PROPERTY_KEY = 'aws:asset:property'; +export const ASSET_RESOURCE_METADATA_IS_BUNDLED_KEY = 'aws:asset:is-bundled'; +export const ASSET_RESOURCE_METADATA_ORIGINAL_PATH_KEY = 'aws:asset:original-path'; /** * Separator string that separates the prefix separator from the object key separator.