diff --git a/.changelog/38567.txt b/.changelog/38567.txt new file mode 100644 index 00000000000..c44f2352255 --- /dev/null +++ b/.changelog/38567.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_sagemaker_user_profile: Add `user_settings.studio_web_portal_settings` block +``` \ No newline at end of file diff --git a/internal/service/sagemaker/sagemaker_test.go b/internal/service/sagemaker/sagemaker_test.go index 9550a5ccc6d..a79ab6f890e 100644 --- a/internal/service/sagemaker/sagemaker_test.go +++ b/internal/service/sagemaker/sagemaker_test.go @@ -106,6 +106,8 @@ func TestAccSageMaker_serial(t *testing.T) { "kernelGatewayAppSettings_imageConfig": testAccUserProfile_kernelGatewayAppSettings_imageconfig, "codeEditorAppSettings_customImage": testAccUserProfile_codeEditorAppSettings_customImage, "jupyterServerAppSettings": testAccUserProfile_jupyterServerAppSettings, + "studioWebPortalSettings_hiddenAppTypes": testAccUserProfile_studioWebPortalSettings_hiddenAppTypes, + "studioWebPortalSettings_hiddenMlTools": testAccUserProfile_studioWebPortalSettings_hiddenMlTools, }, "Workforce": { acctest.CtDisappears: testAccWorkforce_disappears, diff --git a/internal/service/sagemaker/user_profile.go b/internal/service/sagemaker/user_profile.go index f82ea57d48a..05604c6ba00 100644 --- a/internal/service/sagemaker/user_profile.go +++ b/internal/service/sagemaker/user_profile.go @@ -740,6 +740,31 @@ func resourceUserProfile() *schema.Resource { }, }, }, + "studio_web_portal_settings": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "hidden_app_types": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateDiagFunc: enum.Validate[awstypes.AppType](), + }, + }, + "hidden_ml_tools": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateDiagFunc: enum.Validate[awstypes.MlTools](), + }, + }, + }, + }, + }, }, }, }, diff --git a/internal/service/sagemaker/user_profile_test.go b/internal/service/sagemaker/user_profile_test.go index bf00b64d29d..c1e492d91ad 100644 --- a/internal/service/sagemaker/user_profile_test.go +++ b/internal/service/sagemaker/user_profile_test.go @@ -345,6 +345,90 @@ func testAccUserProfile_jupyterServerAppSettings(t *testing.T) { }) } +func testAccUserProfile_studioWebPortalSettings_hiddenAppTypes(t *testing.T) { + ctx := acctest.Context(t) + var domain sagemaker.DescribeUserProfileOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_sagemaker_user_profile.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SageMakerServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckUserProfileDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccUserProfileConfig_studioWebPortalSettings_hiddenAppTypes(rName, []string{"JupyterServer", "KernelGateway"}), + Check: resource.ComposeTestCheckFunc( + testAccCheckUserProfileExists(ctx, resourceName, &domain), + resource.TestCheckResourceAttr(resourceName, "user_settings.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "user_settings.0.studio_web_portal_settings.#", acctest.Ct1), + resource.TestCheckTypeSetElemAttr(resourceName, "user_settings.0.studio_web_portal_settings.0.hidden_app_types.*", "JupyterServer"), + resource.TestCheckTypeSetElemAttr(resourceName, "user_settings.0.studio_web_portal_settings.0.hidden_app_types.*", "KernelGateway"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccUserProfileConfig_studioWebPortalSettings_hiddenAppTypes(rName, []string{"JupyterServer", "KernelGateway", "CodeEditor"}), + Check: resource.ComposeTestCheckFunc( + testAccCheckUserProfileExists(ctx, resourceName, &domain), + resource.TestCheckResourceAttr(resourceName, "user_settings.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "user_settings.0.studio_web_portal_settings.#", acctest.Ct1), + resource.TestCheckTypeSetElemAttr(resourceName, "user_settings.0.studio_web_portal_settings.0.hidden_app_types.*", "JupyterServer"), + resource.TestCheckTypeSetElemAttr(resourceName, "user_settings.0.studio_web_portal_settings.0.hidden_app_types.*", "KernelGateway"), + resource.TestCheckTypeSetElemAttr(resourceName, "user_settings.0.studio_web_portal_settings.0.hidden_app_types.*", "CodeEditor"), + ), + }, + }, + }) +} + +func testAccUserProfile_studioWebPortalSettings_hiddenMlTools(t *testing.T) { + ctx := acctest.Context(t) + var domain sagemaker.DescribeUserProfileOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_sagemaker_user_profile.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SageMakerServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckUserProfileDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccUserProfileConfig_studioWebPortalSettings_hiddenMlTools(rName, []string{"DataWrangler", "FeatureStore"}), + Check: resource.ComposeTestCheckFunc( + testAccCheckUserProfileExists(ctx, resourceName, &domain), + resource.TestCheckResourceAttr(resourceName, "user_settings.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "user_settings.0.studio_web_portal_settings.#", acctest.Ct1), + resource.TestCheckTypeSetElemAttr(resourceName, "user_settings.0.studio_web_portal_settings.0.hidden_ml_tools.*", "DataWrangler"), + resource.TestCheckTypeSetElemAttr(resourceName, "user_settings.0.studio_web_portal_settings.0.hidden_ml_tools.*", "FeatureStore"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccUserProfileConfig_studioWebPortalSettings_hiddenMlTools(rName, []string{"DataWrangler", "FeatureStore", "EmrClusters"}), + Check: resource.ComposeTestCheckFunc( + testAccCheckUserProfileExists(ctx, resourceName, &domain), + resource.TestCheckResourceAttr(resourceName, "user_settings.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "user_settings.0.studio_web_portal_settings.#", acctest.Ct1), + resource.TestCheckTypeSetElemAttr(resourceName, "user_settings.0.studio_web_portal_settings.0.hidden_ml_tools.*", "DataWrangler"), + resource.TestCheckTypeSetElemAttr(resourceName, "user_settings.0.studio_web_portal_settings.0.hidden_ml_tools.*", "FeatureStore"), + resource.TestCheckTypeSetElemAttr(resourceName, "user_settings.0.studio_web_portal_settings.0.hidden_ml_tools.*", "EmrClusters"), + ), + }, + }, + }) +} + func testAccUserProfile_disappears(t *testing.T) { ctx := acctest.Context(t) var domain sagemaker.DescribeUserProfileOutput @@ -692,3 +776,51 @@ resource "aws_sagemaker_user_profile" "test" { } `, rName, baseImage)) } + +func testAccUserProfileConfig_studioWebPortalSettings_hiddenAppTypes(rName string, hiddenAppTypes []string) string { + var hiddenAppTypesString string + for i, appType := range hiddenAppTypes { + if i > 0 { + hiddenAppTypesString += ", " + } + hiddenAppTypesString += fmt.Sprintf("%q", appType) + } + return acctest.ConfigCompose(testAccUserProfileConfig_base(rName), fmt.Sprintf(` +resource "aws_sagemaker_user_profile" "test" { + domain_id = aws_sagemaker_domain.test.id + user_profile_name = %[1]q + + user_settings { + execution_role = aws_iam_role.test.arn + + studio_web_portal_settings { + hidden_app_types = [%[2]s] + } + } +} +`, rName, hiddenAppTypesString)) +} + +func testAccUserProfileConfig_studioWebPortalSettings_hiddenMlTools(rName string, hiddenMlTools []string) string { + var hiddenMlToolsString string + for i, mlTool := range hiddenMlTools { + if i > 0 { + hiddenMlToolsString += ", " + } + hiddenMlToolsString += fmt.Sprintf("%q", mlTool) + } + return acctest.ConfigCompose(testAccUserProfileConfig_base(rName), fmt.Sprintf(` +resource "aws_sagemaker_user_profile" "test" { + domain_id = aws_sagemaker_domain.test.id + user_profile_name = %[1]q + + user_settings { + execution_role = aws_iam_role.test.arn + + studio_web_portal_settings { + hidden_ml_tools = [%[2]s] + } + } +} +`, rName, hiddenMlToolsString)) +} diff --git a/website/docs/r/sagemaker_user_profile.html.markdown b/website/docs/r/sagemaker_user_profile.html.markdown index c062db7b8ca..7aba76d7bd9 100644 --- a/website/docs/r/sagemaker_user_profile.html.markdown +++ b/website/docs/r/sagemaker_user_profile.html.markdown @@ -50,6 +50,7 @@ This resource supports the following arguments: * `space_storage_settings` - (Optional) The storage settings for a private space. See [Space Storage Settings](#space_storage_settings) below. * `studio_web_portal` - (Optional) Whether the user can access Studio. If this value is set to `DISABLED`, the user cannot access Studio, even if that is the default experience for the domain. Valid values are `ENABLED` and `DISABLED`. * `tensor_board_app_settings` - (Optional) The TensorBoard app settings. See [TensorBoard App Settings](#tensor_board_app_settings) below. +* `studio_web_portal_settings` - (Optional) The Studio Web Portal settings. See [`studio_web_portal_settings` Block](#studio_web_portal_settings-block) below. #### space_storage_settings @@ -111,6 +112,11 @@ This resource supports the following arguments: * `access_status` - (Optional) Indicates whether the current user has access to the RStudioServerPro app. Valid values are `ENABLED` and `DISABLED`. * `user_group` - (Optional) The level of permissions that the user has within the RStudioServerPro app. This value defaults to `R_STUDIO_USER`. The `R_STUDIO_ADMIN` value allows the user access to the RStudio Administrative Dashboard. Valid values are `R_STUDIO_USER` and `R_STUDIO_ADMIN`. +#### `studio_web_portal_settings` Block + +* `hidden_app_types` - (Optional) The Applications supported in Studio that are hidden from the Studio left navigation pane. +* `hidden_ml_tools` - (Optional) The machine learning tools that are hidden from the Studio left navigation pane. + ##### code_repository * `repository_url` - (Optional) The URL of the Git repository.