-
Notifications
You must be signed in to change notification settings - Fork 9.6k
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
Version Publishing for AWS Lambda #6067
Comments
Hi @brian-polly! Thanks for this feature request. Terraform's model tends to be a bit weird for externally-versioned stuff since Terraform resources are built around a "Create, Read, Update, Delete" model, but I think one way we could support what you're after here is with a new resource like this:
I'm imagining its lifecycle as follows:
However, I think there might be some tricky interaction here because the |
It's not super clear to me how the source_code_hash works, but is there any reason that we couldn't feed it the same input that we feed the AWS Lambda Function resource: "${base64sha256(file("lambda_function_payload.zip"))}"? I don't know if there's some reason that it only works in the context of the lambda resource, but if not, it seems like there shouldn't be any problem using that for both resources. As far as I can tell, I have to have access to the zipped payload in order to version the lambda function in the first place, no? |
This feature was recently discussed somewhere in a different thread about Lambda and I agree it would be nice to support it, but the lack of it is not burning me personally. The good news is that there seems to be quite a simple solution - the https://github.com/aws/aws-sdk-go/blob/master/service/lambda/api.go#L1139-L1141 I personally don't plan to send a PR, but I'd be happy to review (and eventually merge) one, as long as it also has a test. 😉 |
@brian-polly, @radeksimko's solution seems much simpler than what I proposed, and so I think better to implement that way, but to answer your question: Providing the same expression in both places should work fine, but I usually try to avoid duplicating expressions in multiple places in my config, instead preferring to write them out at the "top" of the dependency tree and then refer up the tree. This means if I change the original expression I only need to change it in one place, and it also implicitly creates a dependency between the two resources (in this case the This is more a matter of style than anything else. Either way would work, though you'd need to make sure that Terraform is able to know the dependency between these somehow, or else it might try to create the version before it's updated the function. |
@apparentlymart That makes a lot of sense -- I'm definitely still acclimating myself to what "good style" means here. |
I was thinking about this again when I noticed couple days ago that AWS introduced I think Terraform could have a similar resource (
and (as opposed to CloudFormation) possibly these too
It would be up to the user to decide about the workflow for deployments:
In terms of CRUD operations on such resource I could imagine it to work like this:
Overall I'm not sure how far are versions and aliases interchangeable though. More likely |
@radeksimko, I don't really understand why we'd need to duplicate all the code-location-specification attributes from Looks like your workflow 1 is basically my original proposal, which also happens to (by lucky coincidence) exactly match the CloudFormation model: resource "aws_lambda_function" "foo" {
// ...
}
resource "aws_lambda_function_version" "foo" {
function_name = "${aws_lambda_function.foo.function_name}"
source_code_hash = "${aws_lambda_function.foo.source_code_hash}"
} It seems like workflow two could be written as you originally suggested, without involving and complicating the
Seems like the decider between these two approaches is that workflow 1 allows you to potentially create versions for only selected updates, though it'd definitely require some Terraform acrobatics to do that. For example, you could create the function and the version in two separate Terraform modules where the latter uses Given how rare that is, I expect the second workflow would be used in 99% of cases and so my instinct is to start with supporting only workflow 2 as you originally proposed, and wait for real use-cases to emerge for workflow 1 before supporting it in Terraform. |
I'm thinking about how to make this compatible with the "Otto-like" deployment model (
You could say that the whole
I think that changing IAM per version should be avoidable. AWS API key for common deployment should not need any I know of organisations using Terraform that have separate contexts/directories for all IAM resources (for good reasons) and I'm probably going to do that too very soon. Yes, IAM permissions based on on Lambda versions still don't fit into this theory well, but I think it's ok to scope permissions per functions, not versions.
I would personally want to use the 2nd workflow most of the time, because of the risks & reasons mentioned above. I'm aware that not many people may be using Terraform for real-life app deployments yet (as opposed to single-context infra deployments), but I'd say it can be more common in the future if we make it possible. |
Of course where exactly to draw the line between "infrastructure" and "app" will always be very subjective 😀 but thinking specifically about your IAM example it seems like this is already solved by having However, I'd agree that the permissions present a particular problem: the function must be created before the permissions can be assigned. This seems to be a limitation of Lambda's design where the permissions refer to their function, rather than the other way around as with IAM roles/policies. I certainly agree that being able to do what you describe would be ideal, but I worry about adding too much extra Terraform-specific behavior/workflow on top of the basic Lambda API operations. Like you said, having One answer would be to remove the possibility of uploading code from the main resource "aws_lambda_function" "example" {
function_name = "example"
role = "${aws_iam_role.iam_for_lambda.arn}"
// filename, handler, source_code_hash, s3_bucket, etc are not supported on this resource at all,
// and this function just creates a function with an empty placeholder implementation, ignoring
// the implementation on all future Refresh/Diff.
}
resource "aws_lambda_function_permission" "example" {
function_name = "${aws_lambda_function.example.function_name}"
// ...
}
resource "aws_lambda_function_version" "example" {
function_name = "${aws_lambda_function.example.function_name}"
filename = "lambda_function_payload.zip"
handler = "doSomething"
source_code_hash = "${base64sha256(file("lambda_function_payload.zip"))}"
} In this model "infrastructure-ish" things would depend on the This would of course be a breaking change at this point. Perhaps Lambda support in Terraform and Lambda usage in the real world are early enough that we could tolerate such a thing? I'm not sure... and I still feel a little weird making Terraform subvert the workflow intended by the Lambda product team. |
Is anyone here pinning their lambda function versions to version aliases? http://docs.aws.amazon.com/lambda/latest/dg/versioning-aliases.html Perhaps we could use a new resources |
I have been experimenting with both CloudFormation and Terraform to setup an decent automatic CI deploy process to aws. Ideally the CI process would build/zip/upload the ${commit}-build.zip to a bucket and configure a new version of lambda function(s) with that code (keeping old versions and their config immutable). TLDR: From what I've learned, I would vote in favor of In fact AWS docs argue the same on http://docs.aws.amazon.com/lambda/latest/dg/versioning-intro.html
Currently, CloudFormation does not support versioning of Lambda function well. Spend half a day banging my head. AWS::Lambda::Function resource does not have "Publish" property yet (but the latest API docs do http://docs.aws.amazon.com/lambda/latest/dg/API_CreateFunction.html). I believe CF is just behind in the release cycle and eventually "Publish" will be supported. CF AWS::Lambda::Version resource is useless in it's current form. Function's version is created on create-stack operation, but update-stack either errors out (Updates are not supported) when updating sha/description or has no effect (as version resource already exists). All other lambda resources support versioned Arn or qualified/versioned function name: AddPermission, CreateEventSourceMapping, CreateAlias. I think Terraform would need to adopt semantic to always create Permission/EventSourceMapping for the newly published version and update Alias to point to the version. To clarify here is my take on the desired terraform resources:
|
Here is my basic support: #6233 |
Any updates on this? I'd love to see version support added in. |
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further. |
New user here, totally in love with Terraform. I'm trying to use it in a few API Gateway/Lambda projects, and it's lifechanging.
With that said, one of the cooler new features of Lambda is the ability to publish versions: it gives us a clear, easy, guaranteed rollback. While I'm totally willing to give that up in order to use Terraform, it feels funny that it's missing.
The AWS API documentation for the feature I'm after is here:
Ideally, we'd be able to publish only when the lambda function is updated, but honestly, publishing every time i applied a configuration would also be an improvement over the status quo.
Thanks, everybody.
The text was updated successfully, but these errors were encountered: