Skip to content
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

Lambda SnapStart #28097

Merged
merged 4 commits into from
Nov 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/28097.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_lambda_function: Add `snap_start` attribute
```
56 changes: 56 additions & 0 deletions internal/service/lambda/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,24 @@ func ResourceFunction() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"snap_start": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"apply_on": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice(lambda.SnapStartApplyOn_Values(), true),
},
"optimization_status": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"source_code_hash": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -400,6 +418,7 @@ func hasConfigChanges(d verify.ResourceDiffer) bool {
d.HasChange("kms_key_arn") ||
d.HasChange("layers") ||
d.HasChange("dead_letter_config") ||
d.HasChange("snap_start") ||
d.HasChange("tracing_config") ||
d.HasChange("vpc_config.0.security_group_ids") ||
d.HasChange("vpc_config.0.subnet_ids") ||
Expand Down Expand Up @@ -530,6 +549,10 @@ func resourceFunctionCreate(d *schema.ResourceData, meta interface{}) error {
}
}

if v, ok := d.GetOk("snap_start"); ok {
params.SnapStart = expandSnapStart(v.([]interface{}))
}

if v, ok := d.GetOk("tracing_config"); ok {
tracingConfig := v.([]interface{})
tracing := tracingConfig[0].(map[string]interface{})
Expand Down Expand Up @@ -844,6 +867,11 @@ func resourceFunctionRead(d *schema.ResourceData, meta interface{}) error {
d.Set("dead_letter_config", []interface{}{})
}

snapStart := flattenSnapStart(function.SnapStart)
if err := d.Set("snap_start", snapStart); err != nil {
return fmt.Errorf("error setting snap_start for Lambda Function (%s): %w", d.Id(), err)
}

// Assume `PassThrough` on partitions that don't support tracing config
tracingConfigMode := "PassThrough"
if function.TracingConfig != nil {
Expand Down Expand Up @@ -1058,6 +1086,10 @@ func resourceFunctionUpdate(d *schema.ResourceData, meta interface{}) error {
configReq.DeadLetterConfig.TargetArn = aws.String(dlcMap["target_arn"].(string))
}
}
if d.HasChange("snap_start") {
snapStart := d.Get("snap_start").([]interface{})
configReq.SnapStart = expandSnapStart(snapStart)
}
if d.HasChange("tracing_config") {
tracingConfig := d.Get("tracing_config").([]interface{})
if len(tracingConfig) == 1 { // Schema guarantees either 0 or 1
Expand Down Expand Up @@ -1553,3 +1585,27 @@ func flattenEphemeralStorage(response *lambda.EphemeralStorage) []map[string]int

return []map[string]interface{}{m}
}

func expandSnapStart(tfList []interface{}) *lambda.SnapStart {
snapStart := &lambda.SnapStart{ApplyOn: aws.String(lambda.SnapStartApplyOnNone)}
if len(tfList) == 1 && tfList[0] != nil {
item := tfList[0].(map[string]interface{})
snapStart.ApplyOn = aws.String(item["apply_on"].(string))
}
return snapStart
}

func flattenSnapStart(apiObject *lambda.SnapStartResponse) []interface{} {
if apiObject == nil || apiObject.ApplyOn == nil {
return nil
}
if aws.StringValue(apiObject.ApplyOn) == lambda.SnapStartApplyOnNone {
return nil
}
m := map[string]interface{}{
"apply_on": aws.StringValue(apiObject.ApplyOn),
"optimization_status": aws.StringValue(apiObject.OptimizationStatus),
}

return []interface{}{m}
}
68 changes: 68 additions & 0 deletions internal/service/lambda/function_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1865,6 +1865,42 @@ func TestAccLambdaFunction_S3Update_unversioned(t *testing.T) {
})
}

func TestAccLambdaFunction_snapStart(t *testing.T) {
var conf lambda.GetFunctionOutput
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_lambda_function.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, lambda.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckFunctionDestroy,
Steps: []resource.TestStep{
{
Config: testAccFunctionConfig_snapStartEnabled(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckFunctionExists(resourceName, &conf),
resource.TestCheckResourceAttr(resourceName, "snap_start.#", "1"),
resource.TestCheckResourceAttr(resourceName, "snap_start.0.apply_on", "PublishedVersions"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"filename", "publish"},
},
{
Config: testAccFunctionConfig_snapStartDisabled(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckFunctionExists(resourceName, &conf),
resource.TestCheckResourceAttr(resourceName, "snap_start.#", "0"),
),
},
},
})
}

func TestAccLambdaFunction_runtimes(t *testing.T) {
if testing.Short() {
t.Skip("skipping long-running test in short mode")
Expand Down Expand Up @@ -2150,6 +2186,38 @@ resource "aws_lambda_function" "test" {
`, funcName)
}

func testAccFunctionConfig_snapStartEnabled(rName string) string {
return acctest.ConfigCompose(
acctest.ConfigLambdaBase(rName, rName, rName),
fmt.Sprintf(`
resource "aws_lambda_function" "test" {
filename = "test-fixtures/lambda_java11.zip"
function_name = %[1]q
role = aws_iam_role.iam_for_lambda.arn
handler = "example.Hello::handleRequest"
runtime = "java11"

snap_start {
apply_on = "PublishedVersions"
}
}
`, rName))
}

func testAccFunctionConfig_snapStartDisabled(rName string) string {
return acctest.ConfigCompose(
acctest.ConfigLambdaBase(rName, rName, rName),
fmt.Sprintf(`
resource "aws_lambda_function" "test" {
filename = "test-fixtures/lambda_java11.zip"
function_name = %[1]q
role = aws_iam_role.iam_for_lambda.arn
handler = "example.Hello::handleRequest"
runtime = "java11"
}
`, rName))
}

func testAccFunctionConfig_tags1(rName, tagKey1, tagValue1 string) string {
return acctest.ConfigCompose(
acctest.ConfigLambdaBase(rName, rName, rName),
Expand Down
Binary file not shown.
8 changes: 8 additions & 0 deletions website/docs/r/lambda_function.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ The following arguments are optional:
* `s3_key` - (Optional) S3 key of an object containing the function's deployment package. Conflicts with `filename` and `image_uri`.
* `s3_object_version` - (Optional) Object version containing the function's deployment package. Conflicts with `filename` and `image_uri`.
* `source_code_hash` - (Optional) Used to trigger updates. Must be set to a base64-encoded SHA256 hash of the package file specified with either `filename` or `s3_key`. The usual way to set this is `filebase64sha256("file.zip")` (Terraform 0.11.12 and later) or `base64sha256(file("file.zip"))` (Terraform 0.11.11 and earlier), where "file.zip" is the local filename of the lambda function source archive.
* `snap_start` - (Optional) Snap start settings block. Detailed below.
* `tags` - (Optional) Map of tags to assign to the object. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level.
* `timeout` - (Optional) Amount of time your Lambda Function has to run in seconds. Defaults to `3`. See [Limits][5].
* `tracing_config` - (Optional) Configuration block. Detailed below.
Expand Down Expand Up @@ -314,6 +315,12 @@ Container image configuration values that override the values in the container i
* `entry_point` - (Optional) Entry point to your application, which is typically the location of the runtime executable.
* `working_directory` - (Optional) Working directory.

### snap_start

Snap start settings for low-latency startups. This feature is currently only supported for `java11` runtimes. Remove this block to delete the associated settings (rather than setting `apply_on = "None"`).

* `apply_on` - (Required) Conditions where snap start is enabled. Valid values are `PublishedVersions`.

### tracing_config

* `mode` - (Required) Whether to to sample and trace a subset of incoming requests with AWS X-Ray. Valid values are `PassThrough` and `Active`. If `PassThrough`, Lambda will only trace the request from an upstream service if it contains a tracing header with "sampled=1". If `Active`, Lambda will respect any tracing header it receives from an upstream service. If no tracing header is received, Lambda will call X-Ray for a tracing decision.
Expand All @@ -338,6 +345,7 @@ In addition to all arguments above, the following attributes are exported:
* `qualified_invoke_arn` - Qualified ARN (ARN with lambda version number) to be used for invoking Lambda Function from API Gateway - to be used in [`aws_api_gateway_integration`](/docs/providers/aws/r/api_gateway_integration.html)'s `uri`.
* `signing_job_arn` - ARN of the signing job.
* `signing_profile_version_arn` - ARN of the signing profile version.
* `snap_start.optimization_status` - Optimization status of the snap start configuration. Valid values are `On` and `Off`.
* `source_code_size` - Size in bytes of the function .zip file.
* `tags_all` - A map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block).
* `version` - Latest published version of your Lambda Function.
Expand Down