-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
feat(lambda): introduce a new kind of Code
, CfnParametersCode
.
#2027
Conversation
6ab070f
to
f825d39
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I understand the use case here. Where is the Lambda code actually coming from? The example seems to imply that there's some lambdaBuildAction
that has the artifacts of your lambda function, but I am not sure how this interplays with your infrastructure code...
What happens if this stack is deployed through cdk deploy
? What does it mean for the Lambda to use a CodePipelineCode
in that case?
The use case is deploying your Lambda through a CodePipeline. The This was the experience we discussed in the doc review for Lambda in CodePipeline.
That wouldn't work really - you would need to provide the values for the 2 CFN Parameters, and we don't support that from the toolkit I believe. This Stack is meant to be deployed only through a CloudFormation Action. |
Is this PR superseded by your other one about exposing the parameter names? |
In my opinion, no. |
But isn't the other PR also about overriding an asset's source when deployed through a pipeline? |
There is still a usecase that is not handled well, even if that PR is merged, and that is a situation where you don't have any Assets to point to when creating your Lambda construct (example when this comes up: when the CDK code and the Lambda code are mastered in separate codebases). In that situation, you currently have to do something like this: const bucketNameParam = new cdk.CfnParameter(lambdaStack, 'BucketNameLambdaSourceParam', {
type: 'String',
});
const objectKeyParam = new cdk.CfnParameter(lambdaStack, 'ObjectKeyLambdaSourceParam', {
type: 'String',
});
const bucket = s3.Bucket.import(lambdaStack, 'LambdaBucket', {
bucketName: bucketNameParam.stringValue,
});
const lambdaCode = lambda.Code.bucket(bucket, objectKeyParam.stringValue);
// later, in the Pipeline Stack:
const parameterOverrides: { [name: string]: any } = {};
parameterOverrides[bucketNameParam.logicalId] = lambdaBuildAction.outputArtifact.bucketName;
parameterOverrides[objectKeyParam.logicalId] = lambdaBuildAction.outputArtifact.objectKey;
const cfnDeployAction = new cloudformation.PipelineCreateUpdateStackAction({
// bunch of stuff here...
parameterOverrides,
additionalInputArtifacts: [lambdaBuildAction.outputArtifact],
}); This is far from ideal. What I want to have is: const lambdaCode = lambda.Code.codePipeline(); // name TBD
// later, in the Pipeline Stack:
const cfnDeployAction = new cloudformation.PipelineCreateUpdateStackAction({
// bunch of stuff here...
parameterOverrides: lambdaCode.overrideWith(lambdaBuildAction.outputArtifact),
additionalInputArtifacts: [lambdaBuildAction.outputArtifact],
}); |
I see, thanks for explaining. I would like to see the use case for this type of asset documented very clearly on the class then. Think of our poor users who won't understand! (i.e., me in 3 months ;)) |
@@ -120,6 +120,68 @@ lambdaAction.outputArtifact('Out2'); // returns the named output Artifact, or th | |||
See [the AWS documentation](https://docs.aws.amazon.com/codepipeline/latest/userguide/actions-invoke-lambda-function.html) | |||
on how to write a Lambda function invoked from CodePipeline. | |||
|
|||
### Lambda deployed through CodePipeline | |||
|
|||
If you want to deploy your Lambda through CodePipeline, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lambda deployed exclusively through CodePipeline, right? Might be worth a note that if you're using assets, you can override them anyway so no need to change your code then. I'm saying this because I want this to be the 99% case:
- Use an asset, use "cdk deploy" for "personal dev stack"
- That same asset is reused for CI/CD deployments.
I don't want the docs to send people down paths where they're going to be writing complicated conditionals because they think this is what they have to do to deploy via a Pipeline. Or worse, get confused and come ask us.
Maybe it's worth combining those 2 PRs so we can get the messaging and the examples right in one place?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the other PR with overriding Assets has been closed without merging, I kept this title as-is. Let me know if that's fine, or if you still want to change it.
f825d39
to
5ab21c3
Compare
Code
, CodePipelineCode
Code
, CfnParametersCode
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good. Artifact.fillParameters is a bit off. It’s very specific to lambda code which doesn’t feel right. I am wondering if there’s room for a more abstract concept for an “s3 path” (basically the tuple bucket+key[+version]) and then lambda.CfnParametersCode can implement this interface or have a property that returns this tuple.
I thought about this for some time, and I didn't really get anywhere. The only thing that came to me was something like this: // in the S3 module
export interface S3Coordinates {
readonly bucketName: string;
readonly objectKey: string;
readonly version?: string; // not really needed at this point, but why not
} , then have I'm not in love with this solution. How about we invert the control a little bit? // in the S3 module
export interface S3CoordinatesProvider {
readonly bucketName: string;
readonly objectKey: string;
}
// in the CodePipeline module
export class Artifact implements s3.S3CoordinatesProvider {
// ...
}
// in the Lambda module
export class CfnParametersCode extends /* ... */ {
// ...
public fillParameters(provider: s3.S3CoordinatesProvider): { [name: string]: any } {
const ret: { [name: string]: any } = {};
ret[this.bucketNameParam.logicalId] = provider.bucketName;
ret[this.objectKeyParam.logicalId] = provider.objectKey;
return ret;
}
} And its usage looks like this in the CloudFormation Action: new codepipeline_actions.CloudFormationCreateUpdateStackAction({
parameterOverrides: {
...lambdaCode.fillParameters(lambdaBuildAction.outputArtifact),
},
additionalInputArtifacts: [
lambdaBuildAction.outputArtifact,
],
// ...
}); Thoughts on this? |
You are right that it doesn't make sense for CfnParametersCode to expose the coordinates, because those are not the coordinates but rather the parameters... But How about: parameterOverrides: cfnParametersCode.assign({
bucketName: outputArtifact.bucketName,
objectKey: outputArtifact.objectKey
}), Or if we really want to model coordinates, then: parameterOverrides: cfnParametersCode.assign(outputArtifact.s3Coordinates) |
5ab21c3
to
fd3b26c
Compare
I went with this option, let me know if that works. |
This Code type is helpful when there is no local file/directory to use Assets with, and the Lambda is supposed to be deployed in a CodePipeline.
fd3b26c
to
4c5d89e
Compare
Renamed |
…2027) This Code type is helpful when there is no local file/directory to use Assets with, and the Lambda is supposed to be deployed in a CodePipeline.
This Code type is helpful when there is no local file/directory to use Assets with,
and the Lambda is supposed to be deployed in a CodePipeline.
Pull Request Checklist
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license.