diff --git a/.changelog/42606.txt b/.changelog/42606.txt new file mode 100644 index 000000000000..e3746f30f812 --- /dev/null +++ b/.changelog/42606.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_sagemaker_image_version: Use version as part of resource id, avoiding mix up between similar resources +``` \ No newline at end of file diff --git a/.changelog/42609.txt b/.changelog/42609.txt new file mode 100644 index 000000000000..9f0c7adf791f --- /dev/null +++ b/.changelog/42609.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_sagemaker_image_version: Add `aliases` argument +``` \ No newline at end of file diff --git a/internal/service/sagemaker/image_version.go b/internal/service/sagemaker/image_version.go index 44f42b693034..140b79dfe3dd 100644 --- a/internal/service/sagemaker/image_version.go +++ b/internal/service/sagemaker/image_version.go @@ -5,7 +5,10 @@ package sagemaker import ( "context" + "fmt" "log" + "strconv" + "strings" "github.com/YakDriver/regexache" "github.com/aws/aws-sdk-go-v2/aws" @@ -40,6 +43,13 @@ func resourceImageVersion() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "aliases": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, "base_image": { Type: schema.TypeString, Required: true, @@ -139,15 +149,35 @@ func resourceImageVersionCreate(ctx context.Context, d *schema.ResourceData, met input.ProgrammingLang = aws.String(v.(string)) } + if v, ok := d.GetOk("aliases"); ok { + aliases := v.(*schema.Set).List() + input.Aliases = make([]string, len(aliases)) + for i, alias := range aliases { + input.Aliases[i] = alias.(string) + } + } + _, err := conn.CreateImageVersion(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "creating SageMaker AI Image Version %s: %s", name, err) } - d.SetId(name) + // Get the version from the API response + output, err := conn.DescribeImageVersion(ctx, &sagemaker.DescribeImageVersionInput{ + ImageName: aws.String(name), + }) + if err != nil { + return sdkdiag.AppendErrorf(diags, "describing SageMaker AI Image Version %s after creation: %s", name, err) + } - if _, err := waitImageVersionCreated(ctx, conn, d.Id()); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for SageMaker AI Image Version (%s) to be created: %s", d.Id(), err) + // Set the ID to be a combination of name and version + versionNumber := aws.ToInt32(output.Version) + id := fmt.Sprintf("%s:%d", name, versionNumber) + d.SetId(id) + + // Wait for the image version to be created + if _, err := waitImageVersionCreated(ctx, conn, id); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for SageMaker AI Image Version (%s) to be created: %s", id, err) } return append(diags, resourceImageVersionRead(ctx, d, meta)...) @@ -157,24 +187,46 @@ func resourceImageVersionRead(ctx context.Context, d *schema.ResourceData, meta var diags diag.Diagnostics conn := meta.(*conns.AWSClient).SageMakerClient(ctx) - image, err := findImageVersionByName(ctx, conn, d.Id()) + id := d.Id() + var image *sagemaker.DescribeImageVersionOutput + var err error + + // Check if the ID contains a version (has a colon) + if strings.Contains(id, ":") { + // New format - use the new function + image, err = findImageVersionByNameAndVersion(ctx, conn, id) + } else { + // Legacy format - just the name + image, err = findImageVersionByName(ctx, conn, id) + + // If successful, update the ID to the new format + if err == nil && image != nil { + newID := fmt.Sprintf("%s:%d", id, aws.ToInt32(image.Version)) + d.SetId(newID) + id = newID + } + } if !d.IsNewResource() && tfresource.NotFound(err) { d.SetId("") - log.Printf("[WARN] Unable to find SageMaker AI Image Version (%s); removing from state", d.Id()) + log.Printf("[WARN] Unable to find SageMaker AI Image Version (%s); removing from state", id) return diags } if err != nil { - return sdkdiag.AppendErrorf(diags, "reading SageMaker AI Image Version (%s): %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "reading SageMaker AI Image Version (%s): %s", id, err) } + // Parse the ID to get the name + parts := strings.Split(id, ":") + name := parts[0] + d.Set(names.AttrARN, image.ImageVersionArn) d.Set("base_image", image.BaseImage) d.Set("image_arn", image.ImageArn) d.Set("container_image", image.ContainerImage) d.Set(names.AttrVersion, image.Version) - d.Set("image_name", d.Id()) + d.Set("image_name", name) d.Set("horovod", image.Horovod) d.Set("job_type", image.JobType) d.Set("processor", image.Processor) @@ -183,6 +235,30 @@ func resourceImageVersionRead(ctx context.Context, d *schema.ResourceData, meta d.Set("ml_framework", image.MLFramework) d.Set("programming_lang", image.ProgrammingLang) + // The AWS SDK doesn't have an Aliases field in DescribeImageVersionOutput + // We need to fetch aliases separately using ListAliases API + idParts := strings.Split(id, ":") + imageName := idParts[0] + versionStr := idParts[1] + versionNum, err := strconv.Atoi(versionStr) + if err != nil { + return sdkdiag.AppendErrorf(diags, "invalid version number in resource ID: %s", d.Id()) + } + + aliasesInput := &sagemaker.ListAliasesInput{ + ImageName: aws.String(imageName), + Version: aws.Int32(int32(versionNum)), + } + + aliasesOutput, err := conn.ListAliases(ctx, aliasesInput) + if err != nil { + return sdkdiag.AppendErrorf(diags, "listing aliases for SageMaker AI Image Version (%s): %s", d.Id(), err) + } + + if err := d.Set("aliases", aliasesOutput.SageMakerImageVersionAliases); err != nil { + return sdkdiag.AppendErrorf(diags, "setting aliases: %s", err) + } + return diags } @@ -190,9 +266,23 @@ func resourceImageVersionUpdate(ctx context.Context, d *schema.ResourceData, met var diags diag.Diagnostics conn := meta.(*conns.AWSClient).SageMakerClient(ctx) + // Parse the ID to get name and version + parts := strings.Split(d.Id(), ":") + if len(parts) != 2 { + return sdkdiag.AppendErrorf(diags, "invalid resource ID format: %s", d.Id()) + } + + name := parts[0] + versionStr := parts[1] + + version, err := strconv.Atoi(versionStr) + if err != nil { + return sdkdiag.AppendErrorf(diags, "invalid version number in resource ID: %s", d.Id()) + } + input := &sagemaker.UpdateImageVersionInput{ - ImageName: aws.String(d.Id()), - Version: aws.Int32(int32(d.Get(names.AttrVersion).(int))), + ImageName: aws.String(name), + Version: aws.Int32(int32(version)), } if d.HasChange("horovod") { @@ -223,6 +313,52 @@ func resourceImageVersionUpdate(ctx context.Context, d *schema.ResourceData, met input.ProgrammingLang = aws.String(d.Get("programming_lang").(string)) } + if d.HasChange("aliases") { + // For UpdateImageVersion, we need to use AliasesToAdd and AliasesToDelete + // instead of Aliases directly + oldAliasesSet, newAliasesSet := d.GetChange("aliases") + oldAliases := oldAliasesSet.(*schema.Set).List() + newAliases := newAliasesSet.(*schema.Set).List() + + // Find aliases to add (in new but not in old) + var aliasesToAdd []string + for _, newAlias := range newAliases { + found := false + for _, oldAlias := range oldAliases { + if newAlias.(string) == oldAlias.(string) { + found = true + break + } + } + if !found { + aliasesToAdd = append(aliasesToAdd, newAlias.(string)) + } + } + + // Find aliases to delete (in old but not in new) + var aliasesToDelete []string + for _, oldAlias := range oldAliases { + found := false + for _, newAlias := range newAliases { + if oldAlias.(string) == newAlias.(string) { + found = true + break + } + } + if !found { + aliasesToDelete = append(aliasesToDelete, oldAlias.(string)) + } + } + + if len(aliasesToAdd) > 0 { + input.AliasesToAdd = aliasesToAdd + } + + if len(aliasesToDelete) > 0 { + input.AliasesToDelete = aliasesToDelete + } + } + if _, err := conn.UpdateImageVersion(ctx, input); err != nil { return sdkdiag.AppendErrorf(diags, "updating SageMaker AI Image Version (%s): %s", d.Id(), err) } @@ -234,9 +370,23 @@ func resourceImageVersionDelete(ctx context.Context, d *schema.ResourceData, met var diags diag.Diagnostics conn := meta.(*conns.AWSClient).SageMakerClient(ctx) + // Parse the ID to get name and version + parts := strings.Split(d.Id(), ":") + if len(parts) != 2 { + return sdkdiag.AppendErrorf(diags, "invalid resource ID format: %s", d.Id()) + } + + name := parts[0] + versionStr := parts[1] + + version, err := strconv.Atoi(versionStr) + if err != nil { + return sdkdiag.AppendErrorf(diags, "invalid version number in resource ID: %s", d.Id()) + } + input := &sagemaker.DeleteImageVersionInput{ - ImageName: aws.String(d.Id()), - Version: aws.Int32(int32(d.Get(names.AttrVersion).(int))), + ImageName: aws.String(name), + Version: aws.Int32(int32(version)), } if _, err := conn.DeleteImageVersion(ctx, input); err != nil { @@ -253,6 +403,47 @@ func resourceImageVersionDelete(ctx context.Context, d *schema.ResourceData, met return diags } +func findImageVersionByNameAndVersion(ctx context.Context, conn *sagemaker.Client, id string) (*sagemaker.DescribeImageVersionOutput, error) { + // Parse the ID to get name and version + parts := strings.Split(id, ":") + if len(parts) != 2 { + return nil, fmt.Errorf("invalid resource ID format: %s", id) + } + + name := parts[0] + versionStr := parts[1] + + version, err := strconv.Atoi(versionStr) + if err != nil { + return nil, fmt.Errorf("invalid version number in resource ID: %s", id) + } + + input := &sagemaker.DescribeImageVersionInput{ + ImageName: aws.String(name), + Version: aws.Int32(int32(version)), + } + + output, err := conn.DescribeImageVersion(ctx, input) + + if errs.IsAErrorMessageContains[*awstypes.ResourceNotFound](err, "does not exist") { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output, nil +} + +// Keep this for backward compatibility func findImageVersionByName(ctx context.Context, conn *sagemaker.Client, name string) (*sagemaker.DescribeImageVersionOutput, error) { input := &sagemaker.DescribeImageVersionInput{ ImageName: aws.String(name), @@ -277,3 +468,8 @@ func findImageVersionByName(ctx context.Context, conn *sagemaker.Client, name st return output, nil } + +// FindImageVersionByNameAndVersion finds a SageMaker Image Version by name and version +func FindImageVersionByNameAndVersion(ctx context.Context, conn *sagemaker.Client, id string) (*sagemaker.DescribeImageVersionOutput, error) { + return findImageVersionByNameAndVersion(ctx, conn, id) +} diff --git a/internal/service/sagemaker/image_version_test.go b/internal/service/sagemaker/image_version_test.go index fb07588de5ad..ee8511309bbd 100644 --- a/internal/service/sagemaker/image_version_test.go +++ b/internal/service/sagemaker/image_version_test.go @@ -94,6 +94,9 @@ func TestAccSageMakerImageVersion_full(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "job_type", "TRAINING"), resource.TestCheckResourceAttr(resourceName, "ml_framework", "TensorFlow 1.1"), resource.TestCheckResourceAttr(resourceName, "programming_lang", "Python 3.8"), + resource.TestCheckResourceAttr(resourceName, "aliases.#", "2"), + resource.TestCheckTypeSetElemAttr(resourceName, "aliases.*", "latest"), + resource.TestCheckTypeSetElemAttr(resourceName, "aliases.*", "stable"), ), }, { @@ -118,6 +121,9 @@ func TestAccSageMakerImageVersion_full(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "job_type", "TRAINING"), resource.TestCheckResourceAttr(resourceName, "ml_framework", "TensorFlow 1.1"), resource.TestCheckResourceAttr(resourceName, "programming_lang", "Python 3.8"), + resource.TestCheckResourceAttr(resourceName, "aliases.#", "2"), + resource.TestCheckTypeSetElemAttr(resourceName, "aliases.*", "latest"), + resource.TestCheckTypeSetElemAttr(resourceName, "aliases.*", "stable"), ), }, }, @@ -191,7 +197,7 @@ func testAccCheckImageVersionDestroy(ctx context.Context) resource.TestCheckFunc continue } - _, err := tfsagemaker.FindImageVersionByName(ctx, conn, rs.Primary.ID) + _, err := tfsagemaker.FindImageVersionByNameAndVersion(ctx, conn, rs.Primary.ID) if tfresource.NotFound(err) { continue @@ -220,7 +226,7 @@ func testAccCheckImageVersionExists(ctx context.Context, n string, image *sagema } conn := acctest.Provider.Meta().(*conns.AWSClient).SageMakerClient(ctx) - resp, err := tfsagemaker.FindImageVersionByName(ctx, conn, rs.Primary.ID) + resp, err := tfsagemaker.FindImageVersionByNameAndVersion(ctx, conn, rs.Primary.ID) if err != nil { return err } @@ -285,6 +291,7 @@ resource "aws_sagemaker_image_version" "test" { vendor_guidance = "STABLE" ml_framework = "TensorFlow 1.1" programming_lang = "Python 3.8" + aliases = ["latest", "stable"] } `, baseImage, notes) } diff --git a/internal/service/sagemaker/status.go b/internal/service/sagemaker/status.go index 18723b20915f..657952df9173 100644 --- a/internal/service/sagemaker/status.go +++ b/internal/service/sagemaker/status.go @@ -5,6 +5,7 @@ package sagemaker import ( "context" + "strings" "github.com/aws/aws-sdk-go-v2/service/sagemaker" awstypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" @@ -60,9 +61,19 @@ func statusImage(ctx context.Context, conn *sagemaker.Client, name string) retry } } -func statusImageVersion(ctx context.Context, conn *sagemaker.Client, name string) retry.StateRefreshFunc { +func statusImageVersion(ctx context.Context, conn *sagemaker.Client, id string) retry.StateRefreshFunc { return func() (any, string, error) { - output, err := findImageVersionByName(ctx, conn, name) + // Check if the ID contains a version (has a colon) + var output *sagemaker.DescribeImageVersionOutput + var err error + + if strings.Contains(id, ":") { + // New format - use the new function + output, err = findImageVersionByNameAndVersion(ctx, conn, id) + } else { + // Legacy format - just the name + output, err = findImageVersionByName(ctx, conn, id) + } if tfresource.NotFound(err) { return nil, "", nil diff --git a/internal/service/sagemaker/wait.go b/internal/service/sagemaker/wait.go index 8cbd00484f4c..942b040d15bd 100644 --- a/internal/service/sagemaker/wait.go +++ b/internal/service/sagemaker/wait.go @@ -213,11 +213,11 @@ func waitImageDeleted(ctx context.Context, conn *sagemaker.Client, name string) return err } -func waitImageVersionCreated(ctx context.Context, conn *sagemaker.Client, name string) (*sagemaker.DescribeImageVersionOutput, error) { +func waitImageVersionCreated(ctx context.Context, conn *sagemaker.Client, id string) (*sagemaker.DescribeImageVersionOutput, error) { stateConf := &retry.StateChangeConf{ Pending: enum.Slice(awstypes.ImageVersionStatusCreating), Target: enum.Slice(awstypes.ImageVersionStatusCreated), - Refresh: statusImageVersion(ctx, conn, name), + Refresh: statusImageVersion(ctx, conn, id), Timeout: imageVersionCreatedTimeout, } @@ -234,11 +234,11 @@ func waitImageVersionCreated(ctx context.Context, conn *sagemaker.Client, name s return nil, err } -func waitImageVersionDeleted(ctx context.Context, conn *sagemaker.Client, name string) (*sagemaker.DescribeImageVersionOutput, error) { +func waitImageVersionDeleted(ctx context.Context, conn *sagemaker.Client, id string) (*sagemaker.DescribeImageVersionOutput, error) { stateConf := &retry.StateChangeConf{ Pending: enum.Slice(awstypes.ImageVersionStatusDeleting), Target: []string{}, - Refresh: statusImageVersion(ctx, conn, name), + Refresh: statusImageVersion(ctx, conn, id), Timeout: imageVersionDeletedTimeout, } diff --git a/website/docs/cdktf/python/r/sagemaker_image_version.html.markdown b/website/docs/cdktf/python/r/sagemaker_image_version.html.markdown index de3ba91f55d1..ed0821178e18 100644 --- a/website/docs/cdktf/python/r/sagemaker_image_version.html.markdown +++ b/website/docs/cdktf/python/r/sagemaker_image_version.html.markdown @@ -34,12 +34,34 @@ class MyConvertedCode(TerraformStack): ) ``` +### With aliases + +```python +# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +from constructs import Construct +from cdktf import Token, TerraformStack +# +# Provider bindings are generated by running `cdktf get`. +# See https://cdk.tf/provider-generation for more details. +# +from imports.aws.sagemaker_image_version import SagemakerImageVersion +class MyConvertedCode(TerraformStack): + def __init__(self, scope, name): + super().__init__(scope, name) + SagemakerImageVersion(self, "test", + aliases=["latest", "stable"], + base_image="012345678912.dkr.ecr.us-west-2.amazonaws.com/image:latest", + image_name=Token.as_string(aws_sagemaker_image_test.id) + ) +``` + ## Argument Reference This resource supports the following arguments: * `image_name` - (Required) The name of the image. Must be unique to your account. * `base_image` - (Required) The registry path of the container image on which this image version is based. +* `aliases` - (Optional) A list of aliases for the image version. * `horovod` - (Optional) Indicates Horovod compatibility. * `job_type` - (Optional) Indicates SageMaker AI job type compatibility. Valid values are: `TRAINING`, `INFERENCE`, and `NOTEBOOK_KERNEL`. * `ml_framework` - (Optional) The machine learning framework vended in the image version. @@ -52,14 +74,14 @@ This resource supports the following arguments: This resource exports the following attributes in addition to the arguments above: -* `id` - The name of the Image. +* `id` - The image name and version in the format `name:version`. * `arn` - The Amazon Resource Name (ARN) assigned by AWS to this Image Version. * `version`- The version of the image. If not specified, the latest version is described. * `container_image` - The registry path of the container image that contains this image version. ## Import -In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import SageMaker AI Image Versions using the `name`. For example: +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import SageMaker AI Image Versions using the `name:version` format. For example: ```python # DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug @@ -73,13 +95,15 @@ from imports.aws.sagemaker_image_version import SagemakerImageVersion class MyConvertedCode(TerraformStack): def __init__(self, scope, name): super().__init__(scope, name) - SagemakerImageVersion.generate_config_for_import(self, "testImage", "my-code-repo") + SagemakerImageVersion.generate_config_for_import(self, "testImage", "my-image:1") ``` -Using `terraform import`, import SageMaker AI Image Versions using the `name`. For example: +Using `terraform import`, import SageMaker AI Image Versions using the `name:version` format. For example: ```console -% terraform import aws_sagemaker_image_version.test_image my-code-repo +% terraform import aws_sagemaker_image_version.test_image my-image:1 ``` - \ No newline at end of file +For backward compatibility, importing using just the image name is still supported, but the resource ID will be automatically updated to the `name:version` format after import. + + diff --git a/website/docs/cdktf/typescript/r/sagemaker_image_version.html.markdown b/website/docs/cdktf/typescript/r/sagemaker_image_version.html.markdown index b4ad81a3d90a..e80f7181c1d7 100644 --- a/website/docs/cdktf/typescript/r/sagemaker_image_version.html.markdown +++ b/website/docs/cdktf/typescript/r/sagemaker_image_version.html.markdown @@ -34,7 +34,29 @@ class MyConvertedCode extends TerraformStack { }); } } +``` + +### With aliases +```typescript +// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +import { Construct } from "constructs"; +import { Token, TerraformStack } from "cdktf"; +/* + * Provider bindings are generated by running `cdktf get`. + * See https://cdk.tf/provider-generation for more details. + */ +import { SagemakerImageVersion } from "./.gen/providers/aws/sagemaker-image-version"; +class MyConvertedCode extends TerraformStack { + constructor(scope: Construct, name: string) { + super(scope, name); + new SagemakerImageVersion(this, "test", { + aliases: ["latest", "stable"], + baseImage: "012345678912.dkr.ecr.us-west-2.amazonaws.com/image:latest", + imageName: Token.asString(awsSagemakerImageTest.id), + }); + } +} ``` ## Argument Reference @@ -43,6 +65,7 @@ This resource supports the following arguments: * `imageName` - (Required) The name of the image. Must be unique to your account. * `baseImage` - (Required) The registry path of the container image on which this image version is based. +* `aliases` - (Optional) A list of aliases for the image version. * `horovod` - (Optional) Indicates Horovod compatibility. * `jobType` - (Optional) Indicates SageMaker AI job type compatibility. Valid values are: `TRAINING`, `INFERENCE`, and `NOTEBOOK_KERNEL`. * `ml_framework` - (Optional) The machine learning framework vended in the image version. @@ -55,14 +78,14 @@ This resource supports the following arguments: This resource exports the following attributes in addition to the arguments above: -* `id` - The name of the Image. +* `id` - The image name and version in the format `name:version`. * `arn` - The Amazon Resource Name (ARN) assigned by AWS to this Image Version. * `version`- The version of the image. If not specified, the latest version is described. * `containerImage` - The registry path of the container image that contains this image version. ## Import -In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import SageMaker AI Image Versions using the `name`. For example: +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import SageMaker AI Image Versions using the `name:version` format. For example: ```typescript // DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug @@ -79,17 +102,18 @@ class MyConvertedCode extends TerraformStack { SagemakerImageVersion.generateConfigForImport( this, "testImage", - "my-code-repo" + "my-image:1" ); } } - ``` -Using `terraform import`, import SageMaker AI Image Versions using the `name`. For example: +Using `terraform import`, import SageMaker AI Image Versions using the `name:version` format. For example: ```console -% terraform import aws_sagemaker_image_version.test_image my-code-repo +% terraform import aws_sagemaker_image_version.test_image my-image:1 ``` - \ No newline at end of file +For backward compatibility, importing using just the image name is still supported, but the resource ID will be automatically updated to the `name:version` format after import. + + diff --git a/website/docs/r/sagemaker_image_version.html.markdown b/website/docs/r/sagemaker_image_version.html.markdown index 3d92e3ac73c8..e35e9b71e105 100644 --- a/website/docs/r/sagemaker_image_version.html.markdown +++ b/website/docs/r/sagemaker_image_version.html.markdown @@ -21,12 +21,23 @@ resource "aws_sagemaker_image_version" "test" { } ``` +### With aliases + +```terraform +resource "aws_sagemaker_image_version" "test" { + image_name = aws_sagemaker_image.test.id + base_image = "012345678912.dkr.ecr.us-west-2.amazonaws.com/image:latest" + aliases = ["latest", "stable"] +} +``` + ## Argument Reference This resource supports the following arguments: * `image_name` - (Required) The name of the image. Must be unique to your account. * `base_image` - (Required) The registry path of the container image on which this image version is based. +* `aliases` - (Optional) A list of aliases for the image version. * `horovod` - (Optional) Indicates Horovod compatibility. * `job_type` - (Optional) Indicates SageMaker AI job type compatibility. Valid values are: `TRAINING`, `INFERENCE`, and `NOTEBOOK_KERNEL`. * `ml_framework` - (Optional) The machine learning framework vended in the image version. @@ -39,24 +50,26 @@ This resource supports the following arguments: This resource exports the following attributes in addition to the arguments above: -* `id` - The name of the Image. +* `id` - The image name and version in the format `name:version`. * `arn` - The Amazon Resource Name (ARN) assigned by AWS to this Image Version. * `version`- The version of the image. If not specified, the latest version is described. * `container_image` - The registry path of the container image that contains this image version. ## Import -In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import SageMaker AI Image Versions using the `name`. For example: +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import SageMaker AI Image Versions using the `name:version` format. For example: ```terraform import { to = aws_sagemaker_image_version.test_image - id = "my-code-repo" + id = "my-image:1" } ``` -Using `terraform import`, import SageMaker AI Image Versions using the `name`. For example: +Using `terraform import`, import SageMaker AI Image Versions using the `name:version` format. For example: ```console -% terraform import aws_sagemaker_image_version.test_image my-code-repo +% terraform import aws_sagemaker_image_version.test_image my-image:1 ``` + +For backward compatibility, importing using just the image name is still supported, but the resource ID will be automatically updated to the `name:version` format after import.