11import * as fs from 'fs' ;
22import * as path from 'path' ;
33import * as ecr from '@aws-cdk/aws-ecr' ;
4- import { Annotations , AssetStaging , FeatureFlags , FileFingerprintOptions , IgnoreMode , Stack , SymlinkFollowMode , Token , Stage } from '@aws-cdk/core' ;
4+ import { Annotations , AssetStaging , FeatureFlags , FileFingerprintOptions , IgnoreMode , Stack , SymlinkFollowMode , Token , Stage , CfnResource } from '@aws-cdk/core' ;
55import * as cxapi from '@aws-cdk/cx-api' ;
66import { Construct } from 'constructs' ;
77
@@ -147,6 +147,30 @@ export class DockerImageAsset extends CoreConstruct implements IAsset {
147147 */
148148 public readonly assetHash : string ;
149149
150+ /**
151+ * The path to the asset, relative to the current Cloud Assembly
152+ *
153+ * If asset staging is disabled, this will just be the original path.
154+ *
155+ * If asset staging is enabled it will be the staged path.
156+ */
157+ private readonly assetPath : string ;
158+
159+ /**
160+ * The path to the Dockerfile, relative to the assetPath
161+ */
162+ private readonly dockerfilePath ?: string ;
163+
164+ /**
165+ * Build args to pass to the `docker build` command.
166+ */
167+ private readonly dockerBuildArgs ?: { [ key : string ] : string } ;
168+
169+ /**
170+ * Docker target to build to
171+ */
172+ private readonly dockerBuildTarget ?: string ;
173+
150174 constructor ( scope : Construct , id : string , props : DockerImageAssetProps ) {
151175 super ( scope , id ) ;
152176
@@ -160,7 +184,8 @@ export class DockerImageAsset extends CoreConstruct implements IAsset {
160184 }
161185
162186 // validate the docker file exists
163- const file = path . join ( dir , props . file || 'Dockerfile' ) ;
187+ this . dockerfilePath = props . file || 'Dockerfile' ;
188+ const file = path . join ( dir , this . dockerfilePath ) ;
164189 if ( ! fs . existsSync ( file ) ) {
165190 throw new Error ( `Cannot find file at ${ file } ` ) ;
166191 }
@@ -223,17 +248,53 @@ export class DockerImageAsset extends CoreConstruct implements IAsset {
223248 this . assetHash = staging . assetHash ;
224249
225250 const stack = Stack . of ( this ) ;
251+ this . assetPath = staging . relativeStagedPath ( stack ) ;
252+ this . dockerBuildArgs = props . buildArgs ;
253+ this . dockerBuildTarget = props . target ;
254+
226255 const location = stack . synthesizer . addDockerImageAsset ( {
227- directoryName : staging . relativeStagedPath ( stack ) ,
228- dockerBuildArgs : props . buildArgs ,
229- dockerBuildTarget : props . target ,
256+ directoryName : this . assetPath ,
257+ dockerBuildArgs : this . dockerBuildArgs ,
258+ dockerBuildTarget : this . dockerBuildTarget ,
230259 dockerFile : props . file ,
231260 sourceHash : staging . assetHash ,
232261 } ) ;
233262
234263 this . repository = ecr . Repository . fromRepositoryName ( this , 'Repository' , location . repositoryName ) ;
235264 this . imageUri = location . imageUri ;
236265 }
266+
267+ /**
268+ * Adds CloudFormation template metadata to the specified resource with
269+ * information that indicates which resource property is mapped to this local
270+ * asset. This can be used by tools such as SAM CLI to provide local
271+ * experience such as local invocation and debugging of Lambda functions.
272+ *
273+ * Asset metadata will only be included if the stack is synthesized with the
274+ * "aws:cdk:enable-asset-metadata" context key defined, which is the default
275+ * behavior when synthesizing via the CDK Toolkit.
276+ *
277+ * @see https://github.com/aws/aws-cdk/issues/1432
278+ *
279+ * @param resource The CloudFormation resource which is using this asset [disable-awslint:ref-via-interface]
280+ * @param resourceProperty The property name where this asset is referenced
281+ */
282+ public addResourceMetadata ( resource : CfnResource , resourceProperty : string ) {
283+ if ( ! this . node . tryGetContext ( cxapi . ASSET_RESOURCE_METADATA_ENABLED_CONTEXT ) ) {
284+ return ; // not enabled
285+ }
286+
287+ // tell tools such as SAM CLI that the resourceProperty of this resource
288+ // points to a local path and include the path to de dockerfile, docker build args, and target,
289+ // in order to enable local invocation of this function.
290+ resource . cfnOptions . metadata = resource . cfnOptions . metadata || { } ;
291+ resource . cfnOptions . metadata [ cxapi . ASSET_RESOURCE_METADATA_PATH_KEY ] = this . assetPath ;
292+ resource . cfnOptions . metadata [ cxapi . ASSET_RESOURCE_METADATA_DOCKERFILE_PATH_KEY ] = this . dockerfilePath ;
293+ resource . cfnOptions . metadata [ cxapi . ASSET_RESOURCE_METADATA_DOCKER_BUILD_ARGS_KEY ] = this . dockerBuildArgs ;
294+ resource . cfnOptions . metadata [ cxapi . ASSET_RESOURCE_METADATA_DOCKER_BUILD_TARGET_KEY ] = this . dockerBuildTarget ;
295+ resource . cfnOptions . metadata [ cxapi . ASSET_RESOURCE_METADATA_PROPERTY_KEY ] = resourceProperty ;
296+ }
297+
237298}
238299
239300function validateProps ( props : DockerImageAssetProps ) {
0 commit comments