Closed eladb closed 4 years ago
Copy @jfuss
Additional context:
pip install
might not be enough. On most systems, pip defaults to the system python which still tends to be Python2.7 (which makes me super sad). Once Py2.7 support is dropped, customers may not be able to install and would require them to download/install Python3.6 or greater. The moral of this is, aws-lambda-builders might need an installer that is easy to run which will setup the library correctly and lowering the bar for entry on installing. This could open the door for an easier installation with CDK as well.Working with aws-lambda-builders to extract the logic within SAM that maps a function runtime to a build workflow, e.g. taking a java8 function and determining if it's a maven or gradle project by looking for a pom.xml
or build.gradle
file. This wil enable us to provide the following experience:
const myFunction = new lambda.JavaFunction(stack, 'MyJavaFunction', {
projectPath: './lambda'
});
I am currently using the asset's bind
function as a hook to inspect the runtime
property of Function
to determine which lambda-builder workflow to run. It enables a familiar experience, only requiring you to use lambda.Code.build
instead of asset
or file
:
const gradle = new lambda.Function(stack, 'Gradle', {
code: lambda.Code.build('./gradle-project'),
runtime: lambda.Runtime.Java8,
handler: 'com.example.Main:handle'
});
It's simple, but lambda.Code.bind
takes a Construct
instead of a Function
, so I'm not sure if I can safely assume I'll always have access to the function's runtime . Is there a use-case here to pass anything other than a Function
to bind
?
I like the idea of a type-safe JvmFunction
because it enables the injection of hooks specific to an ecosystem, but I'm wondering how we should draw the lines between the CDK's responsibility and that of tools like aws-lambda-builders
. I have a prototype integrating lambda-builders
as an Asset
, where I have duplicated logic from SAM to detects things like gradle vs maven for java. The following PR proposes centralizing that logic in a common tool for both CDK and SAM, but we could also solve it with an explicit parameter:
const myFunction = new lambda.JvmFunction(stack, 'MyJavaFunction', {
projectPath: './lambda',
dependencyManager: 'maven'
});
Which begs the question: what information should be injectable as props and what information should be inferred by the tool?
Is there a use-case here to pass anything other than a
Function
tobind
?
Yes, for example, Layers also use the same Code mechanism. Maybe we should define an interface :-)
Which begs the question: what information should be injectable as props and what information should be inferred by the tool?
I think the default behavior should be to infer as much as possible, but I really like the option of letting users specify many of the project settings here (like dependencies etc) if they wish.
Layers changes things up a bit because they aren't specific to a single runtime: compatibleRuntimes?: Runtime[]
with default All
.
I see the following options for proceeding:
lambda.Code.build
so it doesn't need to inspect the Layer/Function
. This would mean we are redundantly passing runtime information to both the Layer/Function
and the Code
asset.
const fn = new lambda.Function(this, 'F', {
runtime: lambda.Runtime.Java8,
code: lambda.Code.build({
path: './path',
language: lambda.Runtime.Java8,
// maybe we only need to pass the family, not the specific language and infer the rest?
// language: lambda.RuntimeFamily.Java,
})
});
const fn = new lambda.Layer(this, 'F', {
code: lambda.Code.build({
path: './path',
language: lambda.Runtime.Java8
})
});
PythonFunction
or JvmLayer
.
const fn = new lambda.PythonFunction(this, 'F', {
path: './path',
version: '3.7'
});
const layer = new lambda.NodeLayer(this, 'L', {
path: './path',
});
lambda.Code.build
and instead have various options such as JvmCode
, NodeCode
:const fn = new lambda.Function(this, 'F', {
runtime: lambda.Runtime.Java8,
code: new JvmCode('./path')
});
const layer = new lambda.Layer(this, 'L', {
code: new NodeCode('./path'),
compatibleRuntimes: [
lambda.Runtime.NodeJs,
lambda.Runtime.NodeJs810,
// etc.
]
});
// the static method could still be useful for discoverability and consistency.
// again, requires redundant 'runtime' information to be passed
const fn = new lambda.Function(this, 'F', {
runtime: lambda.Runtime.Java8,
code: lambda.Code.java('./path')
});
I'm leaning towards a layered approach incorporating option 2. and 3. - provide high-level Function
constructs for each target we support, built on top of a set of Code
classes so developers can drop down and customize where they see fit.
Hey guys, is there any progress on the issue for typescript version?
Hi there, is there any news on this feature? I wrote all my provisioning code with Typescript, and just found out that the packaging of the lambdas must be done manually - I thought that there would be some equivalent of "sam build". Is there any way to actually invoke "sam build" on the synthesized cloudformation template, so that sam cli takes over the packaging?
Thank you
Unfortunately, we don't yet have a plan or update on this feature at this time.
@andreimcristof - this issue is only focusing on using the lambda builders tooling, i.e., equivalent of sam build
. Packaging and deployment would still be handled by the CDK.
If you're only looking to invoke sam build
on the synthesized template (found in cdk.out/
folder), this should be possible by passing in the right values to the --base-dir
and --template
parameters of the sam build
command.
At this point, it should be possible to run sam package
followed by sam deploy
on the output. However, it would not be possible to bring the generated template and build directory to work with cdk deploy
.
I think at a minimum we should provide guidance on how to use the SAM build capabilities as a pre synthesis step in order to produce lambda bundle zip files that can later be referenced as file assets for Lambda code.
...At this point, it should be possible to run
sam package
followed bysam deploy
on the output. However, it would not be possible to bring the generated template and build directory to work withcdk deploy
.
@nija-at but can sam build and the cdk not play nice with eachother? Meaning: before initializing the cdk infra, I trigger a sam build, and customise the path of the cdk lambdas to read from the sam build output? Can that not work? because, if I understood correctly, all that the cdk needs for the functions, is a path where to read the zips from:
return new lambda.Function(scope, `${funcHandler}_lambda`, {
runtime: lambda.Runtime.NODEJS_10_X,
handler: funcHandler,
code: lambda.Code.fromAsset(path.join(__dirname, 'crud')),
} as lambda.FunctionProps);
... so then, I just configure the .fromAsset to read from the sam build output? ah, exactly what @eladb suggested. No, wait. I'm missing something. @eladb - the sam build cannot be pre-synthesis, as it needs the template. the synth generates the template. The way I underrstand it, this would happen like this:
I had the same problem and solved it by having a separate stack for storing the lambda archives on S3, and before the stack is deployed building and uploading the lambdas so they can be referenced in CDK from the bucket: https://coderbyheart.com/how-i-package-typescript-lambdas-for-aws/
Addressed by #5532 and #9182
@eladb are there plans to make a aws-lambda-go
or aws-lambda-golang
package? Maybe I'm supposed to use Bundling Asset Code and its easy enough for Go?
@eladb are there plans to make a
aws-lambda-go
oraws-lambda-golang
package? Maybe I'm supposed to use Bundling Asset Code and its easy enough for Go?
No concrete plans but more than happy to take contributions! Bundling is the right way.
Thanks for the reply! I might just do that, though it'll be a while before I have time :)
We would like to leverage the aws-lambda-builders project (part of SAM CLI) in order to allow CDK users to build AWS Lambda bundles.
Requirement (API sketch):
Ideally, this is all the user should need to specify. The
lambda.Code.build
class should be able to deduce most of the information needed in order to tell the toolkit to invoke aws-lambda-builders via it's JSON RPC protocol when assets are prepared (similar to any other asset).Notes:
pip install
. We should consider if the toolkit can do this automatically upon first use?