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/sageamaker_model_package_group - new resource #17366

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
3 changes: 3 additions & 0 deletions .changelog/17366.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_sagemaker_model_package_group
```
19 changes: 19 additions & 0 deletions aws/internal/service/sagemaker/finder/finder.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,25 @@ func CodeRepositoryByName(conn *sagemaker.SageMaker, name string) (*sagemaker.De
return output, nil
}

// ModelPackageGroupByName returns the Model Package Group corresponding to the specified name.
// Returns nil if no Model Package Group is found.
func ModelPackageGroupByName(conn *sagemaker.SageMaker, name string) (*sagemaker.DescribeModelPackageGroupOutput, error) {
input := &sagemaker.DescribeModelPackageGroupInput{
ModelPackageGroupName: aws.String(name),
}

output, err := conn.DescribeModelPackageGroup(input)
if err != nil {
return nil, err
}

if output == nil {
return nil, nil
}

return output, nil
}

// ImageByName returns the Image corresponding to the specified name.
// Returns nil if no Image is found.
func ImageByName(conn *sagemaker.SageMaker, name string) (*sagemaker.DescribeImageOutput, error) {
Expand Down
44 changes: 35 additions & 9 deletions aws/internal/service/sagemaker/waiter/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ import (
)

const (
SagemakerNotebookInstanceStatusNotFound = "NotFound"
SagemakerImageStatusNotFound = "NotFound"
SagemakerImageStatusFailed = "Failed"
SagemakerImageVersionStatusNotFound = "NotFound"
SagemakerImageVersionStatusFailed = "Failed"
SagemakerDomainStatusNotFound = "NotFound"
SagemakerFeatureGroupStatusNotFound = "NotFound"
SagemakerFeatureGroupStatusUnknown = "Unknown"
SagemakerUserProfileStatusNotFound = "NotFound"
SagemakerNotebookInstanceStatusNotFound = "NotFound"
SagemakerImageStatusNotFound = "NotFound"
SagemakerImageStatusFailed = "Failed"
SagemakerImageVersionStatusNotFound = "NotFound"
SagemakerImageVersionStatusFailed = "Failed"
SagemakerDomainStatusNotFound = "NotFound"
SagemakerFeatureGroupStatusNotFound = "NotFound"
SagemakerFeatureGroupStatusUnknown = "Unknown"
SagemakerUserProfileStatusNotFound = "NotFound"
SagemakerModelPackageGroupStatusNotFound = "NotFound"
)

// NotebookInstanceStatus fetches the NotebookInstance and its Status
Expand Down Expand Up @@ -47,6 +48,31 @@ func NotebookInstanceStatus(conn *sagemaker.SageMaker, notebookName string) reso
}
}

// ModelPackageGroupStatus fetches the ModelPackageGroup and its Status
func ModelPackageGroupStatus(conn *sagemaker.SageMaker, name string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
input := &sagemaker.DescribeModelPackageGroupInput{
ModelPackageGroupName: aws.String(name),
}

output, err := conn.DescribeModelPackageGroup(input)

if tfawserr.ErrMessageContains(err, "ValidationException", "does not exist") {
return nil, SagemakerModelPackageGroupStatusNotFound, nil
}

if err != nil {
return nil, sagemaker.ModelPackageGroupStatusFailed, err
}

if output == nil {
return nil, SagemakerModelPackageGroupStatusNotFound, nil
}

return output, aws.StringValue(output.ModelPackageGroupStatus), nil
}
}

// ImageStatus fetches the Image and its Status
func ImageStatus(conn *sagemaker.SageMaker, name string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
Expand Down
69 changes: 56 additions & 13 deletions aws/internal/service/sagemaker/waiter/waiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,21 @@ import (
)

const (
NotebookInstanceInServiceTimeout = 10 * time.Minute
NotebookInstanceStoppedTimeout = 10 * time.Minute
NotebookInstanceDeletedTimeout = 10 * time.Minute
ImageCreatedTimeout = 10 * time.Minute
ImageDeletedTimeout = 10 * time.Minute
ImageVersionCreatedTimeout = 10 * time.Minute
ImageVersionDeletedTimeout = 10 * time.Minute
DomainInServiceTimeout = 10 * time.Minute
DomainDeletedTimeout = 10 * time.Minute
FeatureGroupCreatedTimeout = 10 * time.Minute
FeatureGroupDeletedTimeout = 10 * time.Minute
UserProfileInServiceTimeout = 10 * time.Minute
UserProfileDeletedTimeout = 10 * time.Minute
NotebookInstanceInServiceTimeout = 10 * time.Minute
NotebookInstanceStoppedTimeout = 10 * time.Minute
NotebookInstanceDeletedTimeout = 10 * time.Minute
ModelPackageGroupCompletedTimeout = 10 * time.Minute
ModelPackageGroupDeletedTimeout = 10 * time.Minute
ImageCreatedTimeout = 10 * time.Minute
ImageDeletedTimeout = 10 * time.Minute
ImageVersionCreatedTimeout = 10 * time.Minute
ImageVersionDeletedTimeout = 10 * time.Minute
DomainInServiceTimeout = 10 * time.Minute
DomainDeletedTimeout = 10 * time.Minute
FeatureGroupCreatedTimeout = 10 * time.Minute
FeatureGroupDeletedTimeout = 10 * time.Minute
UserProfileInServiceTimeout = 10 * time.Minute
UserProfileDeletedTimeout = 10 * time.Minute
)

// NotebookInstanceInService waits for a NotebookInstance to return InService
Expand Down Expand Up @@ -87,6 +89,47 @@ func NotebookInstanceDeleted(conn *sagemaker.SageMaker, notebookName string) (*s
return nil, err
}

// ModelPackageGroupCompleted waits for a ModelPackageGroup to return Created
func ModelPackageGroupCompleted(conn *sagemaker.SageMaker, name string) (*sagemaker.DescribeModelPackageGroupOutput, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{
sagemaker.ModelPackageGroupStatusPending,
sagemaker.ModelPackageGroupStatusInProgress,
},
Target: []string{sagemaker.ModelPackageGroupStatusCompleted},
Refresh: ModelPackageGroupStatus(conn, name),
Timeout: ModelPackageGroupCompletedTimeout,
}

outputRaw, err := stateConf.WaitForState()

if output, ok := outputRaw.(*sagemaker.DescribeModelPackageGroupOutput); ok {
return output, err
}

return nil, err
}

// ModelPackageGroupDeleted waits for a ModelPackageGroup to return Created
func ModelPackageGroupDeleted(conn *sagemaker.SageMaker, name string) (*sagemaker.DescribeModelPackageGroupOutput, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{
sagemaker.ModelPackageGroupStatusDeleting,
},
Target: []string{},
Refresh: ModelPackageGroupStatus(conn, name),
Timeout: ModelPackageGroupDeletedTimeout,
}

outputRaw, err := stateConf.WaitForState()

if output, ok := outputRaw.(*sagemaker.DescribeModelPackageGroupOutput); ok {
return output, err
}

return nil, err
}

// ImageCreated waits for a Image to return Created
func ImageCreated(conn *sagemaker.SageMaker, name string) (*sagemaker.DescribeImageOutput, error) {
stateConf := &resource.StateChangeConf{
Expand Down
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,7 @@ func Provider() *schema.Provider {
"aws_sagemaker_image": resourceAwsSagemakerImage(),
"aws_sagemaker_image_version": resourceAwsSagemakerImageVersion(),
"aws_sagemaker_model": resourceAwsSagemakerModel(),
"aws_sagemaker_model_package_group": resourceAwsSagemakerModelPackageGroup(),
"aws_sagemaker_notebook_instance_lifecycle_configuration": resourceAwsSagemakerNotebookInstanceLifeCycleConfiguration(),
"aws_sagemaker_notebook_instance": resourceAwsSagemakerNotebookInstance(),
"aws_sagemaker_user_profile": resourceAwsSagemakerUserProfile(),
Expand Down
152 changes: 152 additions & 0 deletions aws/resource_aws_sagemaker_model_package_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package aws

import (
"fmt"
"log"
"regexp"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/sagemaker"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/service/sagemaker/finder"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/service/sagemaker/waiter"
)

func resourceAwsSagemakerModelPackageGroup() *schema.Resource {
return &schema.Resource{
Create: resourceAwsSagemakerModelPackageGroupCreate,
Read: resourceAwsSagemakerModelPackageGroupRead,
Update: resourceAwsSagemakerModelPackageGroupUpdate,
Delete: resourceAwsSagemakerModelPackageGroupDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"arn": {
Type: schema.TypeString,
Computed: true,
},
"model_package_group_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.All(
validation.StringLenBetween(1, 63),
validation.StringMatch(regexp.MustCompile(`^[a-zA-Z0-9](-*[a-zA-Z0-9]){0,62}$`),
"Valid characters are a-z, A-Z, 0-9, and - (hyphen)."),
),
},
"model_package_group_description": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: validation.StringLenBetween(1, 1024),
},
"tags": tagsSchema(),
},
}
}

func resourceAwsSagemakerModelPackageGroupCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).sagemakerconn

name := d.Get("model_package_group_name").(string)
input := &sagemaker.CreateModelPackageGroupInput{
ModelPackageGroupName: aws.String(name),
}

if v, ok := d.GetOk("model_package_group_description"); ok {
input.ModelPackageGroupDescription = aws.String(v.(string))
}

if v, ok := d.GetOk("tags"); ok {
input.Tags = keyvaluetags.New(v.(map[string]interface{})).IgnoreAws().SagemakerTags()
}

_, err := conn.CreateModelPackageGroup(input)
if err != nil {
return fmt.Errorf("error creating SageMaker Model Package Group %s: %w", name, err)
}

d.SetId(name)

if _, err := waiter.ModelPackageGroupCompleted(conn, d.Id()); err != nil {
return fmt.Errorf("error waiting for Sagemaker Model Package Group (%s) to be created: %w", d.Id(), err)
}

return resourceAwsSagemakerModelPackageGroupRead(d, meta)
}

func resourceAwsSagemakerModelPackageGroupRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).sagemakerconn
ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig

mpg, err := finder.ModelPackageGroupByName(conn, d.Id())
if err != nil {
if isAWSErr(err, "ValidationException", "does not exist") {
d.SetId("")
log.Printf("[WARN] Unable to find Sagemaker Model Package Group (%s); removing from state", d.Id())
return nil
}
return fmt.Errorf("error reading SageMaker Model Package Group (%s): %w", d.Id(), err)

}

arn := aws.StringValue(mpg.ModelPackageGroupArn)
d.Set("model_package_group_name", mpg.ModelPackageGroupName)
d.Set("arn", arn)
d.Set("model_package_group_description", mpg.ModelPackageGroupDescription)

tags, err := keyvaluetags.SagemakerListTags(conn, arn)

if err != nil {
return fmt.Errorf("error listing tags for SageMaker Model Package Group (%s): %w", d.Id(), err)
}

if err := d.Set("tags", tags.IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()); err != nil {
return fmt.Errorf("error setting tags: %w", err)
}

return nil
}

func resourceAwsSagemakerModelPackageGroupUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).sagemakerconn

if d.HasChange("tags") {
o, n := d.GetChange("tags")

if err := keyvaluetags.SagemakerUpdateTags(conn, d.Get("arn").(string), o, n); err != nil {
return fmt.Errorf("error updating SageMaker Model Package Group (%s) tags: %s", d.Id(), err)
}
}

return resourceAwsSagemakerModelPackageGroupRead(d, meta)
}

func resourceAwsSagemakerModelPackageGroupDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).sagemakerconn

input := &sagemaker.DeleteModelPackageGroupInput{
ModelPackageGroupName: aws.String(d.Id()),
}

if _, err := conn.DeleteModelPackageGroup(input); err != nil {
if isAWSErr(err, "ValidationException", "does not exist") {
return nil
}
return fmt.Errorf("error deleting SageMaker Model Package Group (%s): %w", d.Id(), err)
}

if _, err := waiter.ModelPackageGroupDeleted(conn, d.Id()); err != nil {
if isAWSErr(err, "ValidationException", "does not exist") {
return nil
}
return fmt.Errorf("error waiting for SageMaker Model Package Group (%s) to delete: %w", d.Id(), err)
}

return nil
}
Loading