diff --git a/cmd/delete/delete.go b/cmd/delete/delete.go index c67dbe6..0ba8bd2 100644 --- a/cmd/delete/delete.go +++ b/cmd/delete/delete.go @@ -47,6 +47,9 @@ func NewDeleteCmd() *cobra.Command { cmd.AddCommand(log_group.NewResource().NewDeleteCmd()) cmd.AddCommand(nodegroup.NewResource().NewDeleteCmd()) cmd.AddCommand(organization.NewResource().NewDeleteCmd()) + cmd.AddCommand(NewSageMakerCmd()) + cmd.AddCommand(NewDeleteAliasCmds(sagemaker, "sagemaker-")...) + cmd.AddCommand(NewDeleteAliasCmds(sagemaker, "sm-")...) cmd.AddCommand(security_group.NewResource().NewDeleteCmd()) cmd.AddCommand(target_group.NewResource().NewDeleteCmd()) cmd.AddCommand(volume.NewResource().NewDeleteCmd()) diff --git a/cmd/delete/sagemaker.go b/cmd/delete/sagemaker.go new file mode 100644 index 0000000..71a9e04 --- /dev/null +++ b/cmd/delete/sagemaker.go @@ -0,0 +1,32 @@ +package delete + +import ( + "github.com/awslabs/eksdemo/pkg/resource" + "github.com/awslabs/eksdemo/pkg/resource/sagemaker/userprofile" + "github.com/spf13/cobra" +) + +var sagemaker []func() *resource.Resource + +func NewSageMakerCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "sagemaker", + Short: "Amazon SageMaker Resources", + Aliases: []string{"sm"}, + } + + // Don't show flag errors for `delete sagemaker` without a subcommand + cmd.DisableFlagParsing = true + + for _, sm := range sagemaker { + cmd.AddCommand(sm().NewDeleteCmd()) + } + + return cmd +} + +func init() { + sagemaker = []func() *resource.Resource{ + userprofile.New, + } +} diff --git a/pkg/aws/sagemaker.go b/pkg/aws/sagemaker.go index 5e34f7a..9543177 100644 --- a/pkg/aws/sagemaker.go +++ b/pkg/aws/sagemaker.go @@ -16,6 +16,15 @@ func NewSageMakerClient() *SageMakerClient { return &SageMakerClient{sagemaker.NewFromConfig(GetConfig())} } +func (c *SageMakerClient) DeleteUserProfile(domainID, userProfileName string) error { + _, err := c.Client.DeleteUserProfile(context.Background(), &sagemaker.DeleteUserProfileInput{ + DomainId: aws.String(domainID), + UserProfileName: aws.String(userProfileName), + }) + + return err +} + func (c *SageMakerClient) DescribeDomain(id string) (*sagemaker.DescribeDomainOutput, error) { result, err := c.Client.DescribeDomain(context.Background(), &sagemaker.DescribeDomainInput{ DomainId: aws.String(id), diff --git a/pkg/resource/manager.go b/pkg/resource/manager.go index 1341b5c..297dbaa 100644 --- a/pkg/resource/manager.go +++ b/pkg/resource/manager.go @@ -1,13 +1,41 @@ package resource import ( + "fmt" + "github.com/spf13/cobra" ) type Manager interface { - Create(options Options) error - Delete(options Options) error + Create(Options) error + Delete(Options) error Init() SetDryRun() - Update(options Options, cmd *cobra.Command) error + Update(Options, *cobra.Command) error +} + +type CreateNotSupported struct{} + +func (*CreateNotSupported) Create(_ Options) error { + return fmt.Errorf("create not supported for this resource") +} + +type DeleteNotSupported struct{} + +func (*DeleteNotSupported) Delete(_ Options) error { + return fmt.Errorf("delete not supported for this resource") +} + +type UpdateNotSupported struct{} + +func (*UpdateNotSupported) Update(_ Options, _ *cobra.Command) error { + return fmt.Errorf("update not supported for this resource") +} + +type DryRun struct { + DryRun bool +} + +func (m *DryRun) SetDryRun() { + m.DryRun = true } diff --git a/pkg/resource/sagemaker/userprofile/manager.go b/pkg/resource/sagemaker/userprofile/manager.go new file mode 100644 index 0000000..3e667a4 --- /dev/null +++ b/pkg/resource/sagemaker/userprofile/manager.go @@ -0,0 +1,57 @@ +package userprofile + +import ( + "errors" + "fmt" + + awssdk "github.com/aws/aws-sdk-go-v2/aws" + "github.com/awslabs/eksdemo/pkg/aws" + "github.com/awslabs/eksdemo/pkg/resource" +) + +type Manager struct { + resource.CreateNotSupported + resource.DryRun + resource.UpdateNotSupported + sagemakerClient *aws.SageMakerClient + userProfileGetter *Getter +} + +func (m *Manager) Init() { + if m.sagemakerClient == nil { + m.sagemakerClient = aws.NewSageMakerClient() + } + m.userProfileGetter = NewGetter(m.sagemakerClient) +} + +func (m *Manager) Delete(o resource.Options) error { + options, ok := o.(*Options) + if !ok { + return fmt.Errorf("internal error, unable to cast options to userprofile.Options") + } + + domainID := options.DomainID + userProfileName := options.Name + + if domainID == "" { + userProfile, err := m.userProfileGetter.GetUserProfileByName(userProfileName) + + if err != nil { + var rnfe *resource.NotFoundByNameError + if errors.As(err, &rnfe) { + fmt.Printf("SageMaker User Profile with name %q does not exist\n", userProfileName) + return nil + } + return err + } + domainID = awssdk.ToString(userProfile.DomainId) + } + + err := m.sagemakerClient.DeleteUserProfile(domainID, userProfileName) + if err != nil { + return aws.FormatErrorAsMessageOnly(err) + } + fmt.Printf("SageMaker User Profile %q with Domain Id %q deleted\n", userProfileName, domainID) + + return nil +} diff --git a/pkg/resource/sagemaker/userprofile/options.go b/pkg/resource/sagemaker/userprofile/options.go index 7f0df85..5f5c8d1 100644 --- a/pkg/resource/sagemaker/userprofile/options.go +++ b/pkg/resource/sagemaker/userprofile/options.go @@ -9,11 +9,11 @@ import ( type Options struct { resource.CommonOptions - // Get + // Get, Delete DomainID string } -func newOptions() (options *Options, getFlags cmd.Flags) { +func newOptions() (options *Options, deleteFlags, getFlags cmd.Flags) { options = &Options{ CommonOptions: resource.CommonOptions{ Name: "sagemaker-domain", @@ -21,6 +21,17 @@ func newOptions() (options *Options, getFlags cmd.Flags) { }, } + deleteFlags = cmd.Flags{ + &cmd.StringFlag{ + CommandFlag: cmd.CommandFlag{ + Name: "domain-id", + Description: "id of the sagemaker domain", + Shorthand: "D", + }, + Option: &options.DomainID, + }, + } + getFlags = cmd.Flags{ &cmd.StringFlag{ CommandFlag: cmd.CommandFlag{ diff --git a/pkg/resource/sagemaker/userprofile/user_profile.go b/pkg/resource/sagemaker/userprofile/user_profile.go index a40f47e..3b0d5df 100644 --- a/pkg/resource/sagemaker/userprofile/user_profile.go +++ b/pkg/resource/sagemaker/userprofile/user_profile.go @@ -6,7 +6,7 @@ import ( ) func New() *resource.Resource { - options, getFlags := newOptions() + options, deleteFlags, getFlags := newOptions() return &resource.Resource{ Command: cmd.Command{ @@ -16,10 +16,13 @@ func New() *resource.Resource { Args: []string{"USER_PROFILE_NAME"}, }, - GetFlags: getFlags, + DeleteFlags: deleteFlags, + GetFlags: getFlags, Getter: &Getter{}, + Manager: &Manager{}, + Options: options, } }