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

sagemaker_domain add docker_settings & fix domain_settings update #35416

Merged
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
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
Loading