diff --git a/.changelog/30267.txt b/.changelog/30267.txt new file mode 100644 index 000000000000..2c8a774abf00 --- /dev/null +++ b/.changelog/30267.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_sagemaker_endpoint_configuration: Add `production_variants.enable_ssm_access` and `shadow_production_variants.enable_ssm_access` arguments +``` \ No newline at end of file diff --git a/internal/service/sagemaker/endpoint_configuration.go b/internal/service/sagemaker/endpoint_configuration.go index d7fff5d30109..d408a52c1026 100644 --- a/internal/service/sagemaker/endpoint_configuration.go +++ b/internal/service/sagemaker/endpoint_configuration.go @@ -116,53 +116,6 @@ func ResourceEndpointConfiguration() *schema.Resource { ForceNew: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "enable_capture": { - Type: schema.TypeBool, - Optional: true, - ForceNew: true, - }, - - "initial_sampling_percentage": { - Type: schema.TypeInt, - Required: true, - ForceNew: true, - ValidateFunc: validation.IntBetween(0, 100), - }, - - "destination_s3_uri": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.All( - validation.StringMatch(regexp.MustCompile(`^(https|s3)://([^/])/?(.*)$`), ""), - validation.StringLenBetween(1, 512), - )}, - - "kms_key_id": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: verify.ValidARN, - }, - - "capture_options": { - Type: schema.TypeList, - Required: true, - MaxItems: 2, - MinItems: 1, - ForceNew: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "capture_mode": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice(sagemaker.CaptureMode_Values(), false), - }, - }, - }, - }, - "capture_content_type_header": { Type: schema.TypeList, Optional: true, @@ -201,21 +154,64 @@ func ResourceEndpointConfiguration() *schema.Resource { }, }, }, + "capture_options": { + Type: schema.TypeList, + Required: true, + MaxItems: 2, + MinItems: 1, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "capture_mode": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice(sagemaker.CaptureMode_Values(), false), + }, + }, + }, + }, + "destination_s3_uri": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.All( + validation.StringMatch(regexp.MustCompile(`^(https|s3)://([^/])/?(.*)$`), ""), + validation.StringLenBetween(1, 512), + ), + }, + "enable_capture": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + }, + "initial_sampling_percentage": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + ValidateFunc: validation.IntBetween(0, 100), + }, + "kms_key_id": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: verify.ValidARN, + }, }, }, }, - "name": { + "kms_key_arn": { Type: schema.TypeString, Optional: true, - Computed: true, ForceNew: true, - ValidateFunc: validName, + ValidateFunc: verify.ValidARN, }, - "kms_key_arn": { + "name": { Type: schema.TypeString, Optional: true, + Computed: true, ForceNew: true, - ValidateFunc: verify.ValidARN, + ValidateFunc: validName, }, "production_variants": { Type: schema.TypeList, @@ -261,6 +257,11 @@ func ResourceEndpointConfiguration() *schema.Resource { }, }, }, + "enable_ssm_access": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + }, "initial_instance_count": { Type: schema.TypeInt, Optional: true, @@ -373,6 +374,11 @@ func ResourceEndpointConfiguration() *schema.Resource { }, }, }, + "enable_ssm_access": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + }, "initial_instance_count": { Type: schema.TypeInt, Optional: true, @@ -641,6 +647,10 @@ func expandProductionVariants(configured []interface{}) []*sagemaker.ProductionV l.CoreDumpConfig = expandCoreDumpConfig(v) } + if v, ok := data["enable_ssm_access"].(bool); ok { + l.EnableSSMAccess = aws.Bool(v) + } + containers = append(containers, l) } @@ -686,6 +696,10 @@ func flattenProductionVariants(list []*sagemaker.ProductionVariant) []map[string l["core_dump_config"] = flattenCoreDumpConfig(i.CoreDumpConfig) } + if i.EnableSSMAccess != nil { + l["enable_ssm_access"] = aws.BoolValue(i.EnableSSMAccess) + } + result = append(result, l) } return result diff --git a/internal/service/sagemaker/endpoint_configuration_test.go b/internal/service/sagemaker/endpoint_configuration_test.go index 59dfa561d83c..a72793c84b4a 100644 --- a/internal/service/sagemaker/endpoint_configuration_test.go +++ b/internal/service/sagemaker/endpoint_configuration_test.go @@ -39,6 +39,7 @@ func TestAccSageMakerEndpointConfiguration_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "production_variants.0.initial_variant_weight", "1"), resource.TestCheckResourceAttr(resourceName, "production_variants.0.serverless_config.#", "0"), resource.TestCheckResourceAttr(resourceName, "production_variants.0.core_dump_config.#", "0"), + resource.TestCheckResourceAttr(resourceName, "production_variants.0.enable_ssm_access", "false"), resource.TestCheckResourceAttr(resourceName, "data_capture_config.#", "0"), resource.TestCheckResourceAttr(resourceName, "async_inference_config.#", "0"), resource.TestCheckResourceAttr(resourceName, "shadow_production_variants.#", "0"), @@ -468,6 +469,50 @@ func TestAccSageMakerEndpointConfiguration_Async_client(t *testing.T) { }) } +func TestAccSageMakerEndpointConfiguration_upgradeToEnableSSMAccess(t *testing.T) { + ctx := acctest.Context(t) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_sagemaker_endpoint_configuration.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, sagemaker.EndpointsID), + CheckDestroy: testAccCheckEndpointConfigurationDestroy(ctx), + Steps: []resource.TestStep{ + { + ExternalProviders: map[string]resource.ExternalProvider{ + "aws": { + Source: "hashicorp/aws", + VersionConstraint: "4.60.0", + }, + }, + Config: testAccEndpointConfigurationConfig_basic(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckEndpointConfigurationExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "production_variants.#", "1"), + resource.TestCheckResourceAttr(resourceName, "production_variants.0.variant_name", "variant-1"), + resource.TestCheckResourceAttr(resourceName, "production_variants.0.model_name", rName), + resource.TestCheckResourceAttr(resourceName, "production_variants.0.initial_instance_count", "2"), + resource.TestCheckResourceAttr(resourceName, "production_variants.0.instance_type", "ml.t2.medium"), + resource.TestCheckResourceAttr(resourceName, "production_variants.0.initial_variant_weight", "1"), + resource.TestCheckResourceAttr(resourceName, "production_variants.0.serverless_config.#", "0"), + resource.TestCheckResourceAttr(resourceName, "production_variants.0.core_dump_config.#", "0"), + resource.TestCheckNoResourceAttr(resourceName, "production_variants.0.enable_ssm_access"), + resource.TestCheckResourceAttr(resourceName, "data_capture_config.#", "0"), + resource.TestCheckResourceAttr(resourceName, "async_inference_config.#", "0"), + resource.TestCheckResourceAttr(resourceName, "shadow_production_variants.#", "0"), + ), + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Config: testAccEndpointConfigurationConfig_basic(rName), + PlanOnly: true, + }, + }, + }) +} + func testAccCheckEndpointConfigurationDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).SageMakerConn() @@ -711,11 +756,6 @@ resource "aws_s3_bucket" "test" { force_destroy = true } -resource "aws_s3_bucket_acl" "test" { - bucket = aws_s3_bucket.test.id - acl = "private" -} - resource "aws_sagemaker_endpoint_configuration" "test" { name = %[1]q @@ -755,11 +795,6 @@ resource "aws_s3_bucket" "test" { force_destroy = true } -resource "aws_s3_bucket_acl" "test" { - bucket = aws_s3_bucket.test.id - acl = "private" -} - resource "aws_kms_key" "test" { description = %[1]q deletion_window_in_days = 7 @@ -821,11 +856,6 @@ resource "aws_s3_bucket" "test" { force_destroy = true } -resource "aws_s3_bucket_acl" "test" { - bucket = aws_s3_bucket.test.id - acl = "private" -} - resource "aws_sns_topic" "test" { name = %[1]q } @@ -868,11 +898,6 @@ resource "aws_s3_bucket" "test" { force_destroy = true } -resource "aws_s3_bucket_acl" "test" { - bucket = aws_s3_bucket.test.id - acl = "private" -} - resource "aws_kms_key" "test" { description = %[1]q deletion_window_in_days = 7 diff --git a/website/docs/r/sagemaker_endpoint_configuration.html.markdown b/website/docs/r/sagemaker_endpoint_configuration.html.markdown index 33cb93562b06..941e009fc675 100644 --- a/website/docs/r/sagemaker_endpoint_configuration.html.markdown +++ b/website/docs/r/sagemaker_endpoint_configuration.html.markdown @@ -48,6 +48,7 @@ The following arguments are supported: * `accelerator_type` - (Optional) The size of the Elastic Inference (EI) instance to use for the production variant. * `container_startup_health_check_timeout_in_seconds` - (Optional) The timeout value, in seconds, for your inference container to pass health check by SageMaker Hosting. For more information about health check, see [How Your Container Should Respond to Health Check (Ping) Requests](https://docs.aws.amazon.com/sagemaker/latest/dg/your-algorithms-inference-code.html#your-algorithms-inference-algo-ping-requests). Valid values between `60` and `3600`. * `core_dump_config` - (Optional) Specifies configuration for a core dump from the model container when the process crashes. Fields are documented below. +* `enable_ssm_access` - (Optional) You can use this parameter to turn on native Amazon Web Services Systems Manager (SSM) access for a production variant behind an endpoint. By default, SSM access is disabled for all production variants behind an endpoints. * `initial_instance_count` - (Optional) Initial number of instances used for auto-scaling. * `instance_type` - (Optional) The type of instance to start. * `initial_variant_weight` - (Optional) Determines initial traffic distribution among all of the models that you specify in the endpoint configuration. If unspecified, it defaults to `1.0`.