Skip to content

Commit

Permalink
Merge pull request #23873 from vara-bonthu/f-lambda-function-ephemera…
Browse files Browse the repository at this point in the history
…lstorage

[Feature] Lambda Support for Ephemeral Storage upto 10GB
  • Loading branch information
ewbankkit authored Mar 25, 2022
2 parents 9ed478f + 5370bd5 commit 9684760
Show file tree
Hide file tree
Showing 7 changed files with 272 additions and 33 deletions.
7 changes: 7 additions & 0 deletions .changelog/23873.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:enhancement
resource/aws_lambda_function: Add `ephemeral_storage` argument
```

```release-note:enhancement
data-source/aws_lambda_function: Add `ephemeral_storage` attribute
```
54 changes: 52 additions & 2 deletions internal/service/lambda/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,22 @@ func ResourceFunction() *schema.Resource {
},
},
},
"ephemeral_storage": {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"size": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
ValidateFunc: validation.IntBetween(512, 10240),
},
},
},
},
"file_system_config": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -381,7 +397,8 @@ func hasConfigChanges(d verify.ResourceDiffer) bool {
d.HasChange("vpc_config.0.security_group_ids") ||
d.HasChange("vpc_config.0.subnet_ids") ||
d.HasChange("runtime") ||
d.HasChange("environment")
d.HasChange("environment") ||
d.HasChange("ephemeral_storage")
}

// resourceAwsLambdaFunction maps to:
Expand Down Expand Up @@ -481,6 +498,14 @@ func resourceFunctionCreate(d *schema.ResourceData, meta interface{}) error {
}
}

if v, ok := d.GetOk("ephemeral_storage"); ok && len(v.([]interface{})) > 0 {
ephemeralStorage := v.([]interface{})
configMap := ephemeralStorage[0].(map[string]interface{})
params.EphemeralStorage = &lambda.EphemeralStorage{
Size: aws.Int64(int64(configMap["size"].(int))),
}
}

if v, ok := d.GetOk("file_system_config"); ok && len(v.([]interface{})) > 0 {
params.FileSystemConfigs = expandFileSystemConfigs(v.([]interface{}))
}
Expand Down Expand Up @@ -792,6 +817,12 @@ func resourceFunctionRead(d *schema.ResourceData, meta interface{}) error {
log.Printf("[ERR] Error setting environment for Lambda Function (%s): %s", d.Id(), err)
}

ephemeralStorage := flattenEphemeralStorage(function.EphemeralStorage)
log.Printf("[INFO] Setting Lambda %s ephemeralStorage %#v from API", d.Id(), ephemeralStorage)
if err := d.Set("ephemeral_storage", ephemeralStorage); err != nil {
return fmt.Errorf("error setting ephemeral_storage for Lambda Function (%s): %w", d.Id(), err)
}

if function.DeadLetterConfig != nil && function.DeadLetterConfig.TargetArn != nil {
d.Set("dead_letter_config", []interface{}{
map[string]interface{}{
Expand Down Expand Up @@ -983,7 +1014,15 @@ func resourceFunctionUpdate(d *schema.ResourceData, meta interface{}) error {
if d.HasChange("description") {
configReq.Description = aws.String(d.Get("description").(string))
}

if d.HasChange("ephemeral_storage") {
ephemeralStorage := d.Get("ephemeral_storage").([]interface{})
if len(ephemeralStorage) == 1 {
configMap := ephemeralStorage[0].(map[string]interface{})
configReq.EphemeralStorage = &lambda.EphemeralStorage{
Size: aws.Int64(int64(configMap["size"].(int))),
}
}
}
if d.HasChange("handler") {
configReq.Handler = aws.String(d.Get("handler").(string))
}
Expand Down Expand Up @@ -1444,3 +1483,14 @@ func expandImageConfigs(imageConfigMaps []interface{}) *lambda.ImageConfig {
}
return imageConfig
}

func flattenEphemeralStorage(response *lambda.EphemeralStorage) []map[string]interface{} {
if response == nil {
return nil
}

m := make(map[string]interface{})
m["size"] = aws.Int64Value(response.Size)

return []map[string]interface{}{m}
}
16 changes: 16 additions & 0 deletions internal/service/lambda/function_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,18 @@ func DataSourceFunction() *schema.Resource {
},
},
},
"ephemeral_storage": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"size": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
"file_system_config": {
Type: schema.TypeList,
Computed: true,
Expand Down Expand Up @@ -356,5 +368,9 @@ func dataSourceFunctionRead(d *schema.ResourceData, meta interface{}) error {
return fmt.Errorf("Error setting architectures for Lambda Function (%s): %w", d.Id(), err)
}

if err := d.Set("ephemeral_storage", flattenEphemeralStorage(function.EphemeralStorage)); err != nil {
return fmt.Errorf("error setting ephemeral_storage: (%s): %w", d.Id(), err)
}

return nil
}
94 changes: 68 additions & 26 deletions internal/service/lambda/function_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ func TestAccLambdaFunctionDataSource_basic(t *testing.T) {
Config: testAccFunctionBasicDataSourceConfig(rName),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "code_signing_config_arn", resourceName, "code_signing_config_arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "dead_letter_config.#", resourceName, "dead_letter_config.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "description", resourceName, "description"),
resource.TestCheckResourceAttrPair(dataSourceName, "ephemeral_storage.#", resourceName, "ephemeral_storage.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "ephemeral_storage.0.size", resourceName, "ephemeral_storage.0.size"),
resource.TestCheckResourceAttrPair(dataSourceName, "function_name", resourceName, "function_name"),
resource.TestCheckResourceAttrPair(dataSourceName, "handler", resourceName, "handler"),
resource.TestCheckResourceAttrPair(dataSourceName, "invoke_arn", resourceName, "invoke_arn"),
Expand All @@ -40,16 +43,15 @@ func TestAccLambdaFunctionDataSource_basic(t *testing.T) {
resource.TestCheckResourceAttrPair(dataSourceName, "reserved_concurrent_executions", resourceName, "reserved_concurrent_executions"),
resource.TestCheckResourceAttrPair(dataSourceName, "role", resourceName, "role"),
resource.TestCheckResourceAttrPair(dataSourceName, "runtime", resourceName, "runtime"),
resource.TestCheckResourceAttrPair(dataSourceName, "signing_job_arn", resourceName, "signing_job_arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "signing_profile_version_arn", resourceName, "signing_profile_version_arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "source_code_hash", resourceName, "source_code_hash"),
resource.TestCheckResourceAttrPair(dataSourceName, "source_code_size", resourceName, "source_code_size"),
resource.TestCheckResourceAttrPair(dataSourceName, "tags.%", resourceName, "tags.%"),
resource.TestCheckResourceAttrPair(dataSourceName, "timeout", resourceName, "timeout"),
resource.TestCheckResourceAttrPair(dataSourceName, "tracing_config.#", resourceName, "tracing_config.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "tracing_config.0.mode", resourceName, "tracing_config.0.mode"),
resource.TestCheckResourceAttrPair(dataSourceName, "version", resourceName, "version"),
resource.TestCheckResourceAttrPair(dataSourceName, "signing_profile_version_arn", resourceName, "signing_profile_version_arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "signing_job_arn", resourceName, "signing_job_arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "code_signing_config_arn", resourceName, "code_signing_config_arn"),
),
},
},
Expand Down Expand Up @@ -245,6 +247,34 @@ func TestAccLambdaFunctionDataSource_architectures(t *testing.T) {
})
}

func TestAccLambdaFunctionDataSource_ephemeralStorage(t *testing.T) {
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
dataSourceName := "data.aws_lambda_function.test"
resourceName := "aws_lambda_function.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, lambda.EndpointsID),
Providers: acctest.Providers,
Steps: []resource.TestStep{
{
Config: testAccFunctionEphemeralStorageDataSourceConfig(rName),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "ephemeral_storage.#", resourceName, "ephemeral_storage.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "ephemeral_storage.0.size", resourceName, "ephemeral_storage.0.size"),
),
},
},
})
}

func testAccImagePreCheck(t *testing.T) {
if os.Getenv("AWS_LAMBDA_IMAGE_LATEST_ID") == "" {
t.Skip("AWS_LAMBDA_IMAGE_LATEST_ID env var must be set for Lambda Function Data Source Image Support acceptance tests.")
}
}

func testAccFunctionBaseDataSourceConfig(rName string) string {
return fmt.Sprintf(`
resource "aws_iam_role" "lambda" {
Expand Down Expand Up @@ -305,7 +335,7 @@ EOF
}

func testAccFunctionBasicDataSourceConfig(rName string) string {
return testAccFunctionBaseDataSourceConfig(rName) + fmt.Sprintf(`
return acctest.ConfigCompose(testAccFunctionBaseDataSourceConfig(rName), fmt.Sprintf(`
resource "aws_lambda_function" "test" {
filename = "test-fixtures/lambdatest.zip"
function_name = %[1]q
Expand All @@ -317,11 +347,11 @@ resource "aws_lambda_function" "test" {
data "aws_lambda_function" "test" {
function_name = aws_lambda_function.test.function_name
}
`, rName)
`, rName))
}

func testAccFunctionVersionDataSourceConfig(rName string) string {
return testAccFunctionBaseDataSourceConfig(rName) + fmt.Sprintf(`
return acctest.ConfigCompose(testAccFunctionBaseDataSourceConfig(rName), fmt.Sprintf(`
resource "aws_lambda_function" "test" {
filename = "test-fixtures/lambdatest.zip"
function_name = %[1]q
Expand All @@ -335,11 +365,11 @@ data "aws_lambda_function" "test" {
function_name = aws_lambda_function.test.function_name
qualifier = 1
}
`, rName)
`, rName))
}

func testAccFunctionAliasDataSourceConfig(rName string) string {
return testAccFunctionBaseDataSourceConfig(rName) + fmt.Sprintf(`
return acctest.ConfigCompose(testAccFunctionBaseDataSourceConfig(rName), fmt.Sprintf(`
resource "aws_lambda_function" "test" {
filename = "test-fixtures/lambdatest.zip"
function_name = %[1]q
Expand All @@ -359,11 +389,11 @@ data "aws_lambda_function" "test" {
function_name = aws_lambda_function.test.function_name
qualifier = aws_lambda_alias.test.name
}
`, rName)
`, rName))
}

func testAccFunctionLayersDataSourceConfig(rName string) string {
return testAccFunctionBaseDataSourceConfig(rName) + fmt.Sprintf(`
return acctest.ConfigCompose(testAccFunctionBaseDataSourceConfig(rName), fmt.Sprintf(`
resource "aws_lambda_layer_version" "test" {
filename = "test-fixtures/lambdatest.zip"
layer_name = %[1]q
Expand All @@ -382,11 +412,11 @@ resource "aws_lambda_function" "test" {
data "aws_lambda_function" "test" {
function_name = aws_lambda_function.test.function_name
}
`, rName)
`, rName))
}

func testAccFunctionVPCDataSourceConfig(rName string) string {
return testAccFunctionBaseDataSourceConfig(rName) + fmt.Sprintf(`
return acctest.ConfigCompose(testAccFunctionBaseDataSourceConfig(rName), fmt.Sprintf(`
resource "aws_vpc" "test" {
cidr_block = "10.0.0.0/16"
Expand Down Expand Up @@ -440,11 +470,11 @@ resource "aws_lambda_function" "test" {
data "aws_lambda_function" "test" {
function_name = aws_lambda_function.test.function_name
}
`, rName)
`, rName))
}

func testAccFunctionEnvironmentDataSourceConfig(rName string) string {
return testAccFunctionBaseDataSourceConfig(rName) + fmt.Sprintf(`
return acctest.ConfigCompose(testAccFunctionBaseDataSourceConfig(rName), fmt.Sprintf(`
resource "aws_lambda_function" "test" {
filename = "test-fixtures/lambdatest.zip"
function_name = %[1]q
Expand All @@ -463,11 +493,11 @@ resource "aws_lambda_function" "test" {
data "aws_lambda_function" "test" {
function_name = aws_lambda_function.test.function_name
}
`, rName)
`, rName))
}

func testAccFunctionFileSystemsDataSourceConfig(rName string) string {
return testAccFunctionBaseDataSourceConfig(rName) + fmt.Sprintf(`
return acctest.ConfigCompose(testAccFunctionBaseDataSourceConfig(rName), fmt.Sprintf(`
resource "aws_vpc" "test" {
cidr_block = "10.0.0.0/16"
Expand Down Expand Up @@ -558,13 +588,11 @@ resource "aws_lambda_function" "test" {
data "aws_lambda_function" "test" {
function_name = aws_lambda_function.test.function_name
}
`, rName)
`, rName))
}

func testAccFunctionImageDataSourceConfig(rName, imageID string) string {
return acctest.ConfigCompose(
testAccFunctionBaseDataSourceConfig(rName),
fmt.Sprintf(`
return acctest.ConfigCompose(testAccFunctionBaseDataSourceConfig(rName), fmt.Sprintf(`
resource "aws_lambda_function" "test" {
image_uri = %q
function_name = %q
Expand All @@ -584,7 +612,7 @@ data "aws_lambda_function" "test" {
}

func testAccFunctionArchitecturesDataSourceConfig(rName string) string {
return testAccFunctionBaseDataSourceConfig(rName) + fmt.Sprintf(`
return acctest.ConfigCompose(testAccFunctionBaseDataSourceConfig(rName), fmt.Sprintf(`
resource "aws_lambda_function" "test" {
filename = "test-fixtures/lambdatest.zip"
function_name = %[1]q
Expand All @@ -597,11 +625,25 @@ resource "aws_lambda_function" "test" {
data "aws_lambda_function" "test" {
function_name = aws_lambda_function.test.function_name
}
`, rName)
`, rName))
}

func testAccImagePreCheck(t *testing.T) {
if os.Getenv("AWS_LAMBDA_IMAGE_LATEST_ID") == "" {
t.Skip("AWS_LAMBDA_IMAGE_LATEST_ID env var must be set for Lambda Function Data Source Image Support acceptance tests.")
}
func testAccFunctionEphemeralStorageDataSourceConfig(rName string) string {
return acctest.ConfigCompose(testAccFunctionBaseDataSourceConfig(rName), fmt.Sprintf(`
resource "aws_lambda_function" "test" {
filename = "test-fixtures/lambdatest.zip"
function_name = %[1]q
handler = "exports.example"
role = aws_iam_role.lambda.arn
runtime = "nodejs12.x"
ephemeral_storage {
size = 1024
}
}
data "aws_lambda_function" "test" {
function_name = aws_lambda_function.test.function_name
}
`, rName))
}
Loading

0 comments on commit 9684760

Please sign in to comment.