From c44ed414910770f4b3691a52299a25af37612ed4 Mon Sep 17 00:00:00 2001 From: nikhil Date: Sat, 8 Jun 2024 12:12:58 +0100 Subject: [PATCH 1/6] aws_emrserverless_application --- internal/service/emrserverless/application.go | 68 ++++++++++++++++++ .../service/emrserverless/application_test.go | 71 +++++++++++++++++++ 2 files changed, 139 insertions(+) diff --git a/internal/service/emrserverless/application.go b/internal/service/emrserverless/application.go index 0c2b1b2cb9ba..996af4ed4f7e 100644 --- a/internal/service/emrserverless/application.go +++ b/internal/service/emrserverless/application.go @@ -155,6 +155,26 @@ func resourceApplication() *schema.Resource { }, }, }, + "interactive_configuration": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "livy_endpoint_enabled": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "studio_enabled": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + }, + }, + }, "maximum_capacity": { Type: schema.TypeList, Optional: true, @@ -258,6 +278,10 @@ func resourceApplicationCreate(ctx context.Context, d *schema.ResourceData, meta input.InitialCapacity = expandInitialCapacity(v.(*schema.Set)) } + if v, ok := d.GetOk("interactive_configuration"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + input.InteractiveConfiguration = expandInteractiveConfiguration(v.([]interface{})[0].(map[string]interface{})) + } + if v, ok := d.GetOk("maximum_capacity"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { input.MaximumCapacity = expandMaximumCapacity(v.([]interface{})[0].(map[string]interface{})) } @@ -319,6 +343,10 @@ func resourceApplicationRead(ctx context.Context, d *schema.ResourceData, meta i return sdkdiag.AppendErrorf(diags, "setting initial_capacity: %s", err) } + if err := d.Set("interactive_configuration", []interface{}{flattenInteractiveConfiguration(application.InteractiveConfiguration)}); err != nil { + return sdkdiag.AppendErrorf(diags, "setting interactive_configuration: %s", err) + } + if err := d.Set("maximum_capacity", []interface{}{flattenMaximumCapacity(application.MaximumCapacity)}); err != nil { return sdkdiag.AppendErrorf(diags, "setting maximum_capacity: %s", err) } @@ -362,6 +390,10 @@ func resourceApplicationUpdate(ctx context.Context, d *schema.ResourceData, meta input.InitialCapacity = expandInitialCapacity(v.(*schema.Set)) } + if v, ok := d.GetOk("interactive_configuration"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + input.InteractiveConfiguration = expandInteractiveConfiguration(v.([]interface{})[0].(map[string]interface{})) + } + if v, ok := d.GetOk("maximum_capacity"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { input.MaximumCapacity = expandMaximumCapacity(v.([]interface{})[0].(map[string]interface{})) } @@ -573,6 +605,42 @@ func flattenAutoStopConfig(apiObject *types.AutoStopConfig) map[string]interface return tfMap } +func expandInteractiveConfiguration(tfMap map[string]interface{}) *types.InteractiveConfiguration { + if tfMap == nil { + return nil + } + + apiObject := &types.InteractiveConfiguration{} + + if v, ok := tfMap["livy_endpoint_enabled"].(bool); ok { + apiObject.LivyEndpointEnabled = aws.Bool(v) + } + + if v, ok := tfMap["studio_enabled"].(bool); ok { + apiObject.StudioEnabled = aws.Bool(v) + } + + return apiObject +} + +func flattenInteractiveConfiguration(apiObject *types.InteractiveConfiguration) map[string]interface{} { + if apiObject == nil { + return nil + } + + tfMap := map[string]interface{}{} + + if v := apiObject.LivyEndpointEnabled; v != nil { + tfMap["livy_endpoint_enabled"] = aws.ToBool(v) + } + + if v := apiObject.StudioEnabled; v != nil { + tfMap["studio_enabled"] = aws.ToBool(v) + } + + return tfMap +} + func expandMaximumCapacity(tfMap map[string]interface{}) *types.MaximumAllowedResources { if tfMap == nil { return nil diff --git a/internal/service/emrserverless/application_test.go b/internal/service/emrserverless/application_test.go index 58499d1f5d20..46a72bd72ff7 100644 --- a/internal/service/emrserverless/application_test.go +++ b/internal/service/emrserverless/application_test.go @@ -230,6 +230,63 @@ func TestAccEMRServerlessApplication_imageConfiguration(t *testing.T) { }) } +func TestAccEMRServerlessApplication_interactiveConfiguration(t *testing.T) { + ctx := acctest.Context(t) + var application types.Application + resourceName := "aws_emrserverless_application.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.EMRServerlessServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckApplicationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccApplicationConfig_interactiveConfiguration(rName, true, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckApplicationExists(ctx, resourceName, &application), + resource.TestCheckResourceAttr(resourceName, "interactive_configuration.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.livy_endpoint_enabled", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.studio_enabled.#", acctest.CtTrue), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccApplicationConfig_interactiveConfiguration(rName, true, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckApplicationExists(ctx, resourceName, &application), + resource.TestCheckResourceAttr(resourceName, "interactive_configuration.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.livy_endpoint_enabled", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.studio_enabled.#", acctest.CtFalse), + ), + }, + { + Config: testAccApplicationConfig_interactiveConfiguration(rName, false, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckApplicationExists(ctx, resourceName, &application), + resource.TestCheckResourceAttr(resourceName, "interactive_configuration.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.livy_endpoint_enabled", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.studio_enabled.#", acctest.CtTrue), + ), + }, + { + Config: testAccApplicationConfig_interactiveConfiguration(rName, false, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckApplicationExists(ctx, resourceName, &application), + resource.TestCheckResourceAttr(resourceName, "interactive_configuration.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.livy_endpoint_enabled", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.studio_enabled.#", acctest.CtFalse), + ), + }, + }, + }) +} + func TestAccEMRServerlessApplication_maxCapacity(t *testing.T) { ctx := acctest.Context(t) var application types.Application @@ -460,6 +517,20 @@ resource "aws_emrserverless_application" "test" { `, rName, cpu) } +func testAccApplicationConfig_interactiveConfiguration(rName string, livyEndpointEnabled, studioEnabled bool) string { + return fmt.Sprintf(` +resource "aws_emrserverless_application" "test" { + name = %[1]q + release_label = "emr-6.6.0" + type = "hive" + interactive_configuration { + livy_endpoint_enabled = %[2]t + studio_enabled = %[3]t + } +} +`, rName, livyEndpointEnabled, studioEnabled) +} + func testAccApplicationConfig_maxCapacity(rName, cpu string) string { return fmt.Sprintf(` resource "aws_emrserverless_application" "test" { From 962bcf345b968a5e7d72f1b3871689b0f4b04b14 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 16 Jul 2024 13:48:59 -0400 Subject: [PATCH 2/6] Add CHANGELOG entry. --- .changelog/37889.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/37889.txt diff --git a/.changelog/37889.txt b/.changelog/37889.txt new file mode 100644 index 000000000000..190c669a721c --- /dev/null +++ b/.changelog/37889.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_emrserverless_application: Add `interactive_configuration` argument +``` \ No newline at end of file From d9582836eb5ab26d995aa6cd81d82d93bbde15b7 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 16 Jul 2024 13:53:02 -0400 Subject: [PATCH 3/6] Update documentation. --- website/docs/r/emrserverless_application.html.markdown | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/website/docs/r/emrserverless_application.html.markdown b/website/docs/r/emrserverless_application.html.markdown index d6d7dc907448..aebec5bac01a 100644 --- a/website/docs/r/emrserverless_application.html.markdown +++ b/website/docs/r/emrserverless_application.html.markdown @@ -68,6 +68,7 @@ The following arguments are required: * `auto_stop_configuration` – (Optional) The configuration for an application to automatically stop after a certain amount of time being idle. * `image_configuration` – (Optional) The image configuration applied to all worker types. * `initial_capacity` – (Optional) The capacity to initialize when the application is created. +* `interactive_configuration` – (Optional) Enables the interactive use cases to use when running an application. * `maximum_capacity` – (Optional) The maximum capacity to allocate when the application is created. This is cumulative across all workers at any given point in time, not just when an application is created. No new resources will be created once any one of the defined limits is hit. * `name` – (Required) The name of the application. * `network_configuration` – (Optional) The network configuration for customer VPC connectivity. @@ -109,6 +110,11 @@ The following arguments are required: * `worker_configuration` - (Optional) The resource configuration of the initial capacity configuration. * `worker_count` - (Required) The number of workers in the initial capacity configuration. +### interactive_configuration Arguments + +* `livy_endpoint_enabled` - (Optional) Enables an Apache Livy endpoint that you can connect to and run interactive jobs. +* `studio_enabled` - (Optional) Enables you to connect an application to Amazon EMR Studio to run interactive workloads in a notebook. + ##### worker_configuration Arguments * `cpu` - (Required) The CPU requirements for every worker instance of the worker type. From efd4ab22146ab64e0892ef18e8bcf17867fb2e59 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 16 Jul 2024 14:08:33 -0400 Subject: [PATCH 4/6] Fix 'TestAccEMRServerlessApplication_interactiveConfiguration'. --- internal/service/emrserverless/application_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/service/emrserverless/application_test.go b/internal/service/emrserverless/application_test.go index 46a72bd72ff7..e346de1fbadb 100644 --- a/internal/service/emrserverless/application_test.go +++ b/internal/service/emrserverless/application_test.go @@ -521,7 +521,7 @@ func testAccApplicationConfig_interactiveConfiguration(rName string, livyEndpoin return fmt.Sprintf(` resource "aws_emrserverless_application" "test" { name = %[1]q - release_label = "emr-6.6.0" + release_label = "emr-6.14.0" type = "hive" interactive_configuration { livy_endpoint_enabled = %[2]t From 3a4d7d56c0bfb0e6653a0b173621dfc8b15acb02 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 16 Jul 2024 14:18:30 -0400 Subject: [PATCH 5/6] Fix 'TestAccEMRServerlessApplication_interactiveConfiguration'. --- internal/service/emrserverless/application_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/service/emrserverless/application_test.go b/internal/service/emrserverless/application_test.go index e346de1fbadb..d0d2d059a95a 100644 --- a/internal/service/emrserverless/application_test.go +++ b/internal/service/emrserverless/application_test.go @@ -248,7 +248,7 @@ func TestAccEMRServerlessApplication_interactiveConfiguration(t *testing.T) { testAccCheckApplicationExists(ctx, resourceName, &application), resource.TestCheckResourceAttr(resourceName, "interactive_configuration.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.livy_endpoint_enabled", acctest.CtTrue), - resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.studio_enabled.#", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.studio_enabled", acctest.CtTrue), ), }, { @@ -262,7 +262,7 @@ func TestAccEMRServerlessApplication_interactiveConfiguration(t *testing.T) { testAccCheckApplicationExists(ctx, resourceName, &application), resource.TestCheckResourceAttr(resourceName, "interactive_configuration.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.livy_endpoint_enabled", acctest.CtTrue), - resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.studio_enabled.#", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.studio_enabled", acctest.CtFalse), ), }, { @@ -271,7 +271,7 @@ func TestAccEMRServerlessApplication_interactiveConfiguration(t *testing.T) { testAccCheckApplicationExists(ctx, resourceName, &application), resource.TestCheckResourceAttr(resourceName, "interactive_configuration.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.livy_endpoint_enabled", acctest.CtFalse), - resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.studio_enabled.#", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.studio_enabled", acctest.CtTrue), ), }, { @@ -280,7 +280,7 @@ func TestAccEMRServerlessApplication_interactiveConfiguration(t *testing.T) { testAccCheckApplicationExists(ctx, resourceName, &application), resource.TestCheckResourceAttr(resourceName, "interactive_configuration.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.livy_endpoint_enabled", acctest.CtFalse), - resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.studio_enabled.#", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.studio_enabled", acctest.CtFalse), ), }, }, @@ -521,8 +521,8 @@ func testAccApplicationConfig_interactiveConfiguration(rName string, livyEndpoin return fmt.Sprintf(` resource "aws_emrserverless_application" "test" { name = %[1]q - release_label = "emr-6.14.0" - type = "hive" + release_label = "emr-7.1.0" + type = "spark" interactive_configuration { livy_endpoint_enabled = %[2]t studio_enabled = %[3]t From 34c2b3cdae3bfa5eb768dc5cd05267088844afeb Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 16 Jul 2024 14:40:23 -0400 Subject: [PATCH 6/6] Fix 'TestAccEMRServerlessApplication_interactiveConfiguration'. --- internal/service/emrserverless/application_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/service/emrserverless/application_test.go b/internal/service/emrserverless/application_test.go index d0d2d059a95a..a0317904a3c8 100644 --- a/internal/service/emrserverless/application_test.go +++ b/internal/service/emrserverless/application_test.go @@ -279,8 +279,8 @@ func TestAccEMRServerlessApplication_interactiveConfiguration(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckApplicationExists(ctx, resourceName, &application), resource.TestCheckResourceAttr(resourceName, "interactive_configuration.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.livy_endpoint_enabled", acctest.CtFalse), - resource.TestCheckResourceAttr(resourceName, "interactive_configuration.0.studio_enabled", acctest.CtFalse), + resource.TestCheckNoResourceAttr(resourceName, "interactive_configuration.0.livy_endpoint_enabled"), + resource.TestCheckNoResourceAttr(resourceName, "interactive_configuration.0.studio_enabled"), ), }, },