Skip to content

Commit

Permalink
Merge pull request #35416 from deepakbshetty/f-aws_sagemaker_domain-d…
Browse files Browse the repository at this point in the history
…ocker-settings

sagemaker_domain add docker_settings & fix domain_settings update
  • Loading branch information
ewbankkit authored Sep 12, 2024
2 parents ba8d17e + 14f77a4 commit 1354c93
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 26 deletions.
7 changes: 7 additions & 0 deletions .changelog/35416.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:enhancement
resource/aws_sagemaker_domain: Add `default_user_settings.domain_settings.docker_settings` configuration block
```

```release-note:bug
resource/aws_sagemaker_domain: Fix update for `default_user_settings.domain_settings` to include missing `security_group_ids` and `r_studio_server_pro_domain_settings` values
```
106 changes: 106 additions & 0 deletions internal/service/sagemaker/domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,29 @@ func resourceDomain() *schema.Resource {
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"docker_settings": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"enable_docker_access": {
Type: schema.TypeString,
Optional: true,
ValidateDiagFunc: enum.Validate[awstypes.FeatureStatus](),
},
"vpc_only_trusted_accounts": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: verify.ValidAccountID,
},
MaxItems: 20,
},
},
},
},
"execution_role_identity_config": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -1412,6 +1435,10 @@ func expandDomainSettings(l []interface{}) *awstypes.DomainSettings {

config := &awstypes.DomainSettings{}

if v, ok := m["docker_settings"].([]interface{}); ok && len(v) > 0 {
config.DockerSettings = expandDockerSettings(v)
}

if v, ok := m["execution_role_identity_config"].(string); ok && v != "" {
config.ExecutionRoleIdentityConfig = awstypes.ExecutionRoleIdentityConfig(v)
}
Expand All @@ -1427,6 +1454,26 @@ func expandDomainSettings(l []interface{}) *awstypes.DomainSettings {
return config
}

func expandDockerSettings(l []interface{}) *awstypes.DockerSettings {
if len(l) == 0 || l[0] == nil {
return nil
}

m := l[0].(map[string]interface{})

config := &awstypes.DockerSettings{}

if v, ok := m["enable_docker_access"].(string); ok && v != "" {
config.EnableDockerAccess = awstypes.FeatureStatus(v)
}

if v, ok := m["vpc_only_trusted_accounts"].(*schema.Set); ok && v.Len() > 0 {
config.VpcOnlyTrustedAccounts = flex.ExpandStringValueSet(v)
}

return config
}

func expandRStudioServerProDomainSettings(l []interface{}) *awstypes.RStudioServerProDomainSettings {
if len(l) == 0 || l[0] == nil {
return nil
Expand Down Expand Up @@ -1464,10 +1511,50 @@ func expandDomainSettingsUpdate(l []interface{}) *awstypes.DomainSettingsForUpda

config := &awstypes.DomainSettingsForUpdate{}

if v, ok := m["docker_settings"].([]interface{}); ok && len(v) > 0 {
config.DockerSettings = expandDockerSettings(v)
}

if v, ok := m["execution_role_identity_config"].(string); ok && v != "" {
config.ExecutionRoleIdentityConfig = awstypes.ExecutionRoleIdentityConfig(v)
}

if v, ok := m[names.AttrSecurityGroupIDs].(*schema.Set); ok && v.Len() > 0 {
config.SecurityGroupIds = flex.ExpandStringValueSet(v)
}

if v, ok := m["r_studio_server_pro_domain_settings"].([]interface{}); ok && len(v) > 0 {
config.RStudioServerProDomainSettingsForUpdate = expandRStudioServerProDomainSettingsUpdate(v)
}

return config
}

func expandRStudioServerProDomainSettingsUpdate(l []interface{}) *awstypes.RStudioServerProDomainSettingsForUpdate {
if len(l) == 0 || l[0] == nil {
return nil
}

m := l[0].(map[string]interface{})

config := &awstypes.RStudioServerProDomainSettingsForUpdate{}

if v, ok := m["default_resource_spec"].([]interface{}); ok && len(v) > 0 {
config.DefaultResourceSpec = expandResourceSpec(v)
}

if v, ok := m["domain_execution_role_arn"].(string); ok && v != "" {
config.DomainExecutionRoleArn = aws.String(v)
}

if v, ok := m["r_studio_connect_url"].(string); ok && v != "" {
config.RStudioConnectUrl = aws.String(v)
}

if v, ok := m["r_studio_package_manager_url"].(string); ok && v != "" {
config.RStudioPackageManagerUrl = aws.String(v)
}

return config
}

Expand Down Expand Up @@ -2474,6 +2561,7 @@ func flattenDomainSettings(config *awstypes.DomainSettings) []map[string]interfa
}

m := map[string]interface{}{
"docker_settings": flattenDockerSettings(config.DockerSettings),
"execution_role_identity_config": config.ExecutionRoleIdentityConfig,
"r_studio_server_pro_domain_settings": flattenRStudioServerProDomainSettings(config.RStudioServerProDomainSettings),
names.AttrSecurityGroupIDs: flex.FlattenStringValueSet(config.SecurityGroupIds),
Expand All @@ -2482,6 +2570,24 @@ func flattenDomainSettings(config *awstypes.DomainSettings) []map[string]interfa
return []map[string]interface{}{m}
}

func flattenDockerSettings(config *awstypes.DockerSettings) []map[string]interface{} {
if config == nil {
return []map[string]interface{}{}
}

m := map[string]interface{}{}

if config.EnableDockerAccess != "" {
m["enable_docker_access"] = config.EnableDockerAccess
}

if config.VpcOnlyTrustedAccounts != nil {
m["vpc_only_trusted_accounts"] = flex.FlattenStringValueSet(config.VpcOnlyTrustedAccounts)
}

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

func flattenRStudioServerProDomainSettings(config *awstypes.RStudioServerProDomainSettings) []map[string]interface{} {
if config == nil {
return []map[string]interface{}{}
Expand Down
92 changes: 67 additions & 25 deletions internal/service/sagemaker/domain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,48 @@ func testAccDomain_domainSettings(t *testing.T) {
})
}

func testAccDomain_domainSettingsDockerSettingsUpdated(t *testing.T) {
ctx := acctest.Context(t)
var domain sagemaker.DescribeDomainOutput
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_sagemaker_domain.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.SageMakerServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckDomainDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccDomainConfig_domainSettingsDockerSettings(rName, "DISABLED"),
Check: resource.ComposeTestCheckFunc(
testAccCheckDomainExists(ctx, resourceName, &domain),
resource.TestCheckResourceAttr(resourceName, "domain_settings.#", acctest.Ct1),
resource.TestCheckResourceAttr(resourceName, "domain_settings.0.docker_settings.#", acctest.Ct1),
resource.TestCheckResourceAttr(resourceName, "domain_settings.0.docker_settings.0.enable_docker_access", "DISABLED"),
resource.TestCheckResourceAttr(resourceName, "domain_settings.0.docker_settings.0.vpc_only_trusted_accounts.#", acctest.Ct1),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"retention_policy"},
},
{
Config: testAccDomainConfig_domainSettingsDockerSettings(rName, "ENABLED"),
Check: resource.ComposeTestCheckFunc(
testAccCheckDomainExists(ctx, resourceName, &domain),
resource.TestCheckResourceAttr(resourceName, "domain_settings.#", acctest.Ct1),
resource.TestCheckResourceAttr(resourceName, "domain_settings.0.docker_settings.#", acctest.Ct1),
resource.TestCheckResourceAttr(resourceName, "domain_settings.0.docker_settings.0.enable_docker_access", "ENABLED"),
resource.TestCheckResourceAttr(resourceName, "domain_settings.0.docker_settings.0.vpc_only_trusted_accounts.#", acctest.Ct1),
),
},
},
})
}

func testAccDomain_kms(t *testing.T) {
ctx := acctest.Context(t)
var domain sagemaker.DescribeDomainOutput
Expand Down Expand Up @@ -176,7 +218,7 @@ func testAccDomain_tags(t *testing.T) {
})
}

func testAccDomain_securityGroup(t *testing.T) {
func testAccDomain_defaultUserSettingsSecurityGroupUpdated(t *testing.T) {
ctx := acctest.Context(t)
var domain sagemaker.DescribeDomainOutput
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
Expand All @@ -189,7 +231,7 @@ func testAccDomain_securityGroup(t *testing.T) {
CheckDestroy: testAccCheckDomainDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccDomainConfig_securityGroup1(rName),
Config: testAccDomainConfig_defaultUserSettingsSecurityGroupUpdated(rName, 1),
Check: resource.ComposeTestCheckFunc(
testAccCheckDomainExists(ctx, resourceName, &domain),
resource.TestCheckResourceAttr(resourceName, "default_user_settings.#", acctest.Ct1),
Expand All @@ -203,7 +245,7 @@ func testAccDomain_securityGroup(t *testing.T) {
ImportStateVerifyIgnore: []string{"retention_policy"},
},
{
Config: testAccDomainConfig_securityGroup2(rName),
Config: testAccDomainConfig_defaultUserSettingsSecurityGroupUpdated(rName, 2),
Check: resource.ComposeTestCheckFunc(
testAccCheckDomainExists(ctx, resourceName, &domain),
resource.TestCheckResourceAttr(resourceName, "default_user_settings.#", acctest.Ct1),
Expand Down Expand Up @@ -1672,52 +1714,52 @@ resource "aws_sagemaker_domain" "test" {
`, rName, config))
}

func testAccDomainConfig_kms(rName string) string {
func testAccDomainConfig_domainSettingsDockerSettings(rName, config string) string {
return acctest.ConfigCompose(testAccDomainConfig_base(rName), fmt.Sprintf(`
resource "aws_kms_key" "test" {
description = %[1]q
deletion_window_in_days = 7
}
data "aws_caller_identity" "current" {}
resource "aws_sagemaker_domain" "test" {
domain_name = %[1]q
auth_mode = "IAM"
vpc_id = aws_vpc.test.id
subnet_ids = aws_subnet.test[*].id
kms_key_id = aws_kms_key.test.key_id
default_user_settings {
execution_role = aws_iam_role.test.arn
}
app_network_access_type = "VpcOnly"
domain_settings {
docker_settings {
enable_docker_access = %[2]q
vpc_only_trusted_accounts = [data.aws_caller_identity.current.account_id]
}
}
retention_policy {
home_efs_file_system = "Delete"
}
}
`, rName))
`, rName, config))
}

func testAccDomainConfig_securityGroup1(rName string) string {
func testAccDomainConfig_kms(rName string) string {
return acctest.ConfigCompose(testAccDomainConfig_base(rName), fmt.Sprintf(`
resource "aws_security_group" "test" {
count = 1
name = "%[1]s-${count.index}"
tags = {
Name = %[1]q
}
resource "aws_kms_key" "test" {
description = %[1]q
deletion_window_in_days = 7
}
resource "aws_sagemaker_domain" "test" {
domain_name = %[1]q
auth_mode = "IAM"
vpc_id = aws_vpc.test.id
subnet_ids = aws_subnet.test[*].id
kms_key_id = aws_kms_key.test.key_id
default_user_settings {
execution_role = aws_iam_role.test.arn
security_groups = aws_security_group.test[*].id
execution_role = aws_iam_role.test.arn
}
retention_policy {
Expand All @@ -1727,15 +1769,15 @@ resource "aws_sagemaker_domain" "test" {
`, rName))
}

func testAccDomainConfig_securityGroup2(rName string) string {
func testAccDomainConfig_defaultUserSettingsSecurityGroupUpdated(rName string, sgCount int) string {
return acctest.ConfigCompose(testAccDomainConfig_base(rName), fmt.Sprintf(`
resource "aws_security_group" "test" {
count = 2
count = %[2]d
name = "%[1]s-${count.index}"
tags = {
Name = %[1]q
Name = "%[1]s-${count.index}"
}
}
Expand All @@ -1754,7 +1796,7 @@ resource "aws_sagemaker_domain" "test" {
home_efs_file_system = "Delete"
}
}
`, rName))
`, rName, sgCount))
}

func testAccDomainConfig_tags1(rName, tagKey1, tagValue1 string) string {
Expand Down
3 changes: 2 additions & 1 deletion internal/service/sagemaker/sagemaker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func TestAccSageMaker_serial(t *testing.T) {
"codeEditorAppSettings_defaultResourceSpecAndCustomImage": testAccDomain_codeEditorAppSettings_defaultResourceSpecAndCustomImage,
"jupyterLabAppSettings": testAccDomain_jupyterLabAppSettings,
"kms": testAccDomain_kms,
"securityGroup": testAccDomain_securityGroup,
"defaultUserSettingsSecurityGroupUpdated": testAccDomain_defaultUserSettingsSecurityGroupUpdated,
"sharingSettings": testAccDomain_sharingSettings,
"defaultUserSettingsUpdated": testAccDomain_defaultUserSettingsUpdated,
"canvas": testAccDomain_canvasAppSettings,
Expand All @@ -66,6 +66,7 @@ func TestAccSageMaker_serial(t *testing.T) {
"kendraSettings": testAccDomain_kendraSettings,
"workspaceSettings": testAccDomain_workspaceSettings,
"domainSettings": testAccDomain_domainSettings,
"domainSettingsDockerSettingsUpdated": testAccDomain_domainSettingsDockerSettingsUpdated,
"rSessionAppSettings": testAccDomain_rSessionAppSettings,
"rStudioServerProAppSettings": testAccDomain_rStudioServerProAppSettings,
"rStudioServerProDomainSettings": testAccDomain_rStudioServerProDomainSettings,
Expand Down
6 changes: 6 additions & 0 deletions website/docs/r/sagemaker_domain.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -268,10 +268,16 @@ The following arguments are optional:

### `domain_settings` Block

* `docker_settings` - (Optional) A collection of settings that configure the domain’s Docker interaction. see [`docker_settings` Block](#docker_settings-block) below.
* `execution_role_identity_config` - (Optional) The configuration for attaching a SageMaker user profile name to the execution role as a sts:SourceIdentity key [AWS Docs](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_monitor.html). Valid values are `USER_PROFILE_NAME` and `DISABLED`.
* `r_studio_server_pro_domain_settings` - (Optional) A collection of settings that configure the RStudioServerPro Domain-level app. see [`r_studio_server_pro_domain_settings` Block](#r_studio_server_pro_domain_settings-block) below.
* `security_group_ids` - (Optional) The security groups for the Amazon Virtual Private Cloud that the Domain uses for communication between Domain-level apps and user apps.

#### `docker_settings` Block

* `enable_docker_access` - (Optional) Indicates whether the domain can access Docker. Valid values are `ENABLED` and `DISABLED`.
* `vpc_only_trusted_accounts` - (Optional) The list of Amazon Web Services accounts that are trusted when the domain is created in VPC-only mode.

#### `r_studio_server_pro_domain_settings` Block

* `default_resource_spec` - (Optional) The default instance type and the Amazon Resource Name (ARN) of the SageMaker image created on the instance. see [`default_resource_spec` Block](#default_resource_spec-block) above.
Expand Down

0 comments on commit 1354c93

Please sign in to comment.