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

r/aws_sagemaker_domain: add arguments to DefaultResourceSpec #21508

Merged
11 changes: 11 additions & 0 deletions .changelog/21508.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
```release-note:enhancement
resource/sagemaker_domain: Add `lifecycle_config_arn` and `sagemaker_image_version_arn` arguments to `default_resource_spec` configuration block
```

```release-note:enhancement
resource/sagemaker_user_profile: Add `lifecycle_config_arn` and `sagemaker_image_version_arn` arguments to `default_resource_spec` configuration block
```

```release-note:enhancement
resource/sagemaker_app: Add `lifecycle_config_arn` and `sagemaker_image_version_arn` arguments to `resource_spec` configuration block
```
10 changes: 10 additions & 0 deletions internal/service/sagemaker/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,22 @@ func ResourceApp() *schema.Resource {
Optional: true,
ValidateFunc: validation.StringInSlice(sagemaker.AppInstanceType_Values(), false),
},
"lifecycle_config_arn": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: verify.ValidARN,
},
"sagemaker_image_arn": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: verify.ValidARN,
},
"sagemaker_image_version_arn": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: verify.ValidARN,
},
},
},
},
Expand Down
72 changes: 72 additions & 0 deletions internal/service/sagemaker/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,38 @@ func testAccApp_resourceSpec(t *testing.T) {
})
}

func testAccApp_resourceSpecLifecycle(t *testing.T) {
var app sagemaker.DescribeAppOutput
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
uName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_sagemaker_app.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, sagemaker.EndpointsID),
Providers: acctest.Providers,
CheckDestroy: testAccCheckAppDestroy,
Steps: []resource.TestStep{
{
Config: testAccAppResourceSpecLifecycleConfig(rName, uName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAppExists(resourceName, &app),
resource.TestCheckResourceAttr(resourceName, "app_name", rName),
resource.TestCheckResourceAttr(resourceName, "resource_spec.#", "1"),
resource.TestCheckResourceAttr(resourceName, "resource_spec.0.instance_type", "system"),
resource.TestCheckResourceAttrSet(resourceName, "resource_spec.0.sagemaker_image_arn"),
resource.TestCheckResourceAttrPair(resourceName, "resource_spec.0.lifecycle_config_arn", "aws_sagemaker_studio_lifecycle_config.test", "arn"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccApp_tags(t *testing.T) {
var app sagemaker.DescribeAppOutput
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
Expand Down Expand Up @@ -334,3 +366,43 @@ resource "aws_sagemaker_app" "test" {
}
`, rName)
}

func testAccAppResourceSpecLifecycleConfig(rName, uName string) string {
return testAccAppBaseConfig(rName) + fmt.Sprintf(`
resource "aws_sagemaker_studio_lifecycle_config" "test" {
studio_lifecycle_config_name = %[1]q
studio_lifecycle_config_app_type = "JupyterServer"
studio_lifecycle_config_content = base64encode("echo Hello")
}

resource "aws_sagemaker_user_profile" "lifecycletest" {
domain_id = aws_sagemaker_domain.test.id
user_profile_name = %[2]q

user_settings {
execution_role = aws_iam_role.test.arn

jupyter_server_app_settings {
default_resource_spec {
instance_type = "system"
lifecycle_config_arn = aws_sagemaker_studio_lifecycle_config.test.arn
}

lifecycle_config_arns = [aws_sagemaker_studio_lifecycle_config.test.arn]
}
}
}

resource "aws_sagemaker_app" "test" {
domain_id = aws_sagemaker_domain.test.id
user_profile_name = aws_sagemaker_user_profile.lifecycletest.user_profile_name
app_name = %[1]q
app_type = "JupyterServer"

resource_spec {
instance_type = "system"
lifecycle_config_arn = aws_sagemaker_studio_lifecycle_config.test.arn
}
}
`, rName, uName)
}
46 changes: 46 additions & 0 deletions internal/service/sagemaker/domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,21 @@ func ResourceDomain() *schema.Resource {
Optional: true,
ValidateFunc: validation.StringInSlice(sagemaker.AppInstanceType_Values(), false),
},
"lifecycle_config_arn": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: verify.ValidARN,
},
"sagemaker_image_arn": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: verify.ValidARN,
},
"sagemaker_image_version_arn": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: verify.ValidARN,
},
},
},
},
Expand All @@ -162,11 +172,21 @@ func ResourceDomain() *schema.Resource {
Optional: true,
ValidateFunc: validation.StringInSlice(sagemaker.AppInstanceType_Values(), false),
},
"lifecycle_config_arn": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: verify.ValidARN,
},
"sagemaker_image_arn": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: verify.ValidARN,
},
"sagemaker_image_version_arn": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: verify.ValidARN,
},
},
},
},
Expand Down Expand Up @@ -199,11 +219,21 @@ func ResourceDomain() *schema.Resource {
Optional: true,
ValidateFunc: validation.StringInSlice(sagemaker.AppInstanceType_Values(), false),
},
"lifecycle_config_arn": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: verify.ValidARN,
},
"sagemaker_image_arn": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: verify.ValidARN,
},
"sagemaker_image_version_arn": {
philof marked this conversation as resolved.
Show resolved Hide resolved
Type: schema.TypeString,
Optional: true,
ValidateFunc: verify.ValidARN,
},
},
},
},
Expand Down Expand Up @@ -556,10 +586,18 @@ func expandSagemakerDomainDefaultResourceSpec(l []interface{}) *sagemaker.Resour
config.InstanceType = aws.String(v)
}

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

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

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

return config
}

Expand Down Expand Up @@ -651,10 +689,18 @@ func flattenSagemakerDomainDefaultResourceSpec(config *sagemaker.ResourceSpec) [
m["instance_type"] = aws.StringValue(config.InstanceType)
}

if config.LifecycleConfigArn != nil {
m["lifecycle_config_arn"] = aws.StringValue(config.LifecycleConfigArn)
}

if config.SageMakerImageArn != nil {
m["sagemaker_image_arn"] = aws.StringValue(config.SageMakerImageArn)
}

if config.SageMakerImageVersionArn != nil {
m["sagemaker_image_version_arn"] = aws.StringValue(config.SageMakerImageVersionArn)
}

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

Expand Down
97 changes: 96 additions & 1 deletion internal/service/sagemaker/domain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ func testAccDomain_kernelGatewayAppSettings_lifecycleConfig(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "default_user_settings.0.kernel_gateway_app_settings.0.lifecycle_config_arns.#", "1"),
resource.TestCheckResourceAttr(resourceName, "default_user_settings.0.kernel_gateway_app_settings.0.default_resource_spec.#", "1"),
resource.TestCheckResourceAttr(resourceName, "default_user_settings.0.kernel_gateway_app_settings.0.default_resource_spec.0.instance_type", "ml.t3.micro"),
resource.TestCheckResourceAttrPair(resourceName, "default_user_settings.0.kernel_gateway_app_settings.0.default_resource_spec.0.lifecycle_config_arn", "aws_sagemaker_studio_lifecycle_config.test", "arn"),
),
},
{
Expand Down Expand Up @@ -363,6 +364,46 @@ func testAccDomain_kernelGatewayAppSettings_customImage(t *testing.T) {
})
}

func testAccDomain_kernelGatewayAppSettings_defaultResourceSpecAndCustomImage(t *testing.T) {

if os.Getenv("SAGEMAKER_IMAGE_VERSION_BASE_IMAGE") == "" {
t.Skip("Environment variable SAGEMAKER_IMAGE_VERSION_BASE_IMAGE is not set")
}

var domain sagemaker.DescribeDomainOutput
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_sagemaker_domain.test"
baseImage := os.Getenv("SAGEMAKER_IMAGE_VERSION_BASE_IMAGE")

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, sagemaker.EndpointsID),
Providers: acctest.Providers,
CheckDestroy: testAccCheckDomainDestroy,
Steps: []resource.TestStep{
{
Config: testAccDomainKernelGatewayAppSettingsDefaultResourceSpecAndCustomImageConfig(rName, baseImage),
Check: resource.ComposeTestCheckFunc(
testAccCheckDomainExists(resourceName, &domain),
resource.TestCheckResourceAttr(resourceName, "default_user_settings.#", "1"),
resource.TestCheckResourceAttr(resourceName, "default_user_settings.0.kernel_gateway_app_settings.#", "1"),
resource.TestCheckResourceAttr(resourceName, "default_user_settings.0.kernel_gateway_app_settings.0.default_resource_spec.#", "1"),
resource.TestCheckResourceAttr(resourceName, "default_user_settings.0.kernel_gateway_app_settings.0.custom_image.#", "1"),
resource.TestCheckResourceAttrPair(resourceName, "default_user_settings.0.kernel_gateway_app_settings.0.default_resource_spec.0.sagemaker_image_version_arn", "aws_sagemaker_image_version.test", "arn"),
resource.TestCheckResourceAttrPair(resourceName, "default_user_settings.0.kernel_gateway_app_settings.0.custom_image.0.app_image_config_name", "aws_sagemaker_app_image_config.test", "app_image_config_name"),
resource.TestCheckResourceAttrPair(resourceName, "default_user_settings.0.kernel_gateway_app_settings.0.custom_image.0.image_name", "aws_sagemaker_image.test", "image_name"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"retention_policy"},
},
},
})
}

func testAccDomain_jupyterServerAppSettings(t *testing.T) {
var domain sagemaker.DescribeDomainOutput
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
Expand Down Expand Up @@ -821,7 +862,8 @@ resource "aws_sagemaker_domain" "test" {

kernel_gateway_app_settings {
default_resource_spec {
instance_type = "ml.t3.micro"
instance_type = "ml.t3.micro"
lifecycle_config_arn = aws_sagemaker_studio_lifecycle_config.test.arn
}

lifecycle_config_arns = [aws_sagemaker_studio_lifecycle_config.test.arn]
Expand Down Expand Up @@ -882,3 +924,56 @@ resource "aws_sagemaker_domain" "test" {
}
`, rName, baseImage)
}

func testAccDomainKernelGatewayAppSettingsDefaultResourceSpecAndCustomImageConfig(rName, baseImage string) string {
return testAccDomainBaseConfig(rName) + fmt.Sprintf(`
resource "aws_sagemaker_image" "test" {
image_name = %[1]q
role_arn = aws_iam_role.test.arn

depends_on = [aws_iam_role_policy_attachment.test]
}

resource "aws_sagemaker_app_image_config" "test" {
app_image_config_name = %[1]q

kernel_gateway_image_config {
kernel_spec {
name = %[1]q
}
}
}

resource "aws_sagemaker_image_version" "test" {
image_name = aws_sagemaker_image.test.id
base_image = %[2]q
}

resource "aws_sagemaker_domain" "test" {
domain_name = %[1]q
auth_mode = "IAM"
vpc_id = aws_vpc.test.id
subnet_ids = [aws_subnet.test.id]

default_user_settings {
execution_role = aws_iam_role.test.arn

kernel_gateway_app_settings {
default_resource_spec {
instance_type = "ml.t3.micro"
sagemaker_image_version_arn = aws_sagemaker_image_version.test.arn
}

custom_image {
app_image_config_name = aws_sagemaker_app_image_config.test.app_image_config_name
image_name = aws_sagemaker_image_version.test.image_name
}
}
}

retention_policy {
home_efs_file_system = "Delete"
}
}
`, rName, baseImage)
}
19 changes: 11 additions & 8 deletions internal/service/sagemaker/sagemaker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ func testAccErrorCheckSkipSagemaker(t *testing.T) resource.ErrorCheckFunc {
func TestAccSageMaker_serial(t *testing.T) {
testCases := map[string]map[string]func(t *testing.T){
"App": {
"basic": testAccApp_basic,
"disappears": testAccApp_tags,
"tags": testAccApp_disappears,
"resourceSpec": testAccApp_resourceSpec,
"basic": testAccApp_basic,
"disappears": testAccApp_tags,
"tags": testAccApp_disappears,
"resourceSpec": testAccApp_resourceSpec,
"resourceSpecLifecycle": testAccApp_resourceSpecLifecycle,
},
"Domain": {
"basic": testAccDomain_basic,
Expand All @@ -39,10 +40,11 @@ func TestAccSageMaker_serial(t *testing.T) {
"kernelGatewayAppSettings": testAccDomain_kernelGatewayAppSettings,
"kernelGatewayAppSettings_customImage": testAccDomain_kernelGatewayAppSettings_customImage,
"kernelGatewayAppSettings_lifecycleConfig": testAccDomain_kernelGatewayAppSettings_lifecycleConfig,
"jupyterServerAppSettings": testAccDomain_jupyterServerAppSettings,
"kms": testAccDomain_kms,
"securityGroup": testAccDomain_securityGroup,
"sharingSettings": testAccDomain_sharingSettings,
"kernelGatewayAppSettings_defaultResourceAndCustomImage": testAccDomain_kernelGatewayAppSettings_defaultResourceSpecAndCustomImage,
"jupyterServerAppSettings": testAccDomain_jupyterServerAppSettings,
"kms": testAccDomain_kms,
"securityGroup": testAccDomain_securityGroup,
"sharingSettings": testAccDomain_sharingSettings,
},
"FlowDefinition": {
"basic": testAccFlowDefinition_basic,
Expand All @@ -59,6 +61,7 @@ func TestAccSageMaker_serial(t *testing.T) {
"tensorboardAppSettingsWithImage": testAccUserProfile_tensorboardAppSettingsWithImage,
"kernelGatewayAppSettings": testAccUserProfile_kernelGatewayAppSettings,
"kernelGatewayAppSettings_lifecycleConfig": testAccUserProfile_kernelGatewayAppSettings_lifecycleconfig,
"kernelGatewayAppSettings_imageConfig": testAccUserProfile_kernelGatewayAppSettings_imageconfig,
"jupyterServerAppSettings": testAccUserProfile_jupyterServerAppSettings,
},
"Workforce": {
Expand Down
Loading