diff --git a/internal/pkg/cli/command/backup/backup_test.go b/internal/pkg/cli/command/backup/backup_test.go deleted file mode 100644 index 9067f716..00000000 --- a/internal/pkg/cli/command/backup/backup_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package backup - -import ( - "context" - - "github.com/pinecone-io/go-pinecone/v5/pinecone" -) - -type mockBackupService struct { - lastCreateBackupReq *pinecone.CreateBackupParams - lastDescribeBackupId string - lastListBackupsParams *pinecone.ListBackupsParams - lastDeleteBackupId string - lastCreateIndexFromBackupReq *pinecone.CreateIndexFromBackupParams - - createBackupResp *pinecone.Backup - describeBackupResp *pinecone.Backup - listBackupsResp *pinecone.BackupList - createIndexFromBackupResp *pinecone.CreateIndexFromBackupResponse - - createBackupErr error - describeBackupErr error - listBackupsErr error - deleteBackupErr error - createIndexFromBackupErr error -} - -func (m *mockBackupService) CreateBackup(ctx context.Context, in *pinecone.CreateBackupParams) (*pinecone.Backup, error) { - m.lastCreateBackupReq = in - return m.createBackupResp, m.createBackupErr -} - -func (m *mockBackupService) DescribeBackup(ctx context.Context, backupId string) (*pinecone.Backup, error) { - m.lastDescribeBackupId = backupId - return m.describeBackupResp, m.describeBackupErr -} - -func (m *mockBackupService) ListBackups(ctx context.Context, in *pinecone.ListBackupsParams) (*pinecone.BackupList, error) { - m.lastListBackupsParams = in - return m.listBackupsResp, m.listBackupsErr -} - -func (m *mockBackupService) DeleteBackup(ctx context.Context, backupId string) error { - m.lastDeleteBackupId = backupId - return m.deleteBackupErr -} - -func (m *mockBackupService) CreateIndexFromBackup(ctx context.Context, in *pinecone.CreateIndexFromBackupParams) (*pinecone.CreateIndexFromBackupResponse, error) { - m.lastCreateIndexFromBackupReq = in - return m.createIndexFromBackupResp, m.createIndexFromBackupErr -} diff --git a/internal/pkg/cli/command/index/backup/backup_test.go b/internal/pkg/cli/command/index/backup/backup_test.go new file mode 100644 index 00000000..4a547207 --- /dev/null +++ b/internal/pkg/cli/command/index/backup/backup_test.go @@ -0,0 +1,43 @@ +package backup + +import ( + "context" + + "github.com/pinecone-io/go-pinecone/v5/pinecone" +) + +type mockBackupService struct { + lastCreateBackupReq *pinecone.CreateBackupParams + lastDescribeBackupId string + lastListBackupsParams *pinecone.ListBackupsParams + lastDeleteBackupId string + + createBackupResp *pinecone.Backup + describeBackupResp *pinecone.Backup + listBackupsResp *pinecone.BackupList + + createBackupErr error + describeBackupErr error + listBackupsErr error + deleteBackupErr error +} + +func (m *mockBackupService) CreateBackup(ctx context.Context, in *pinecone.CreateBackupParams) (*pinecone.Backup, error) { + m.lastCreateBackupReq = in + return m.createBackupResp, m.createBackupErr +} + +func (m *mockBackupService) DescribeBackup(ctx context.Context, backupId string) (*pinecone.Backup, error) { + m.lastDescribeBackupId = backupId + return m.describeBackupResp, m.describeBackupErr +} + +func (m *mockBackupService) ListBackups(ctx context.Context, in *pinecone.ListBackupsParams) (*pinecone.BackupList, error) { + m.lastListBackupsParams = in + return m.listBackupsResp, m.listBackupsErr +} + +func (m *mockBackupService) DeleteBackup(ctx context.Context, backupId string) error { + m.lastDeleteBackupId = backupId + return m.deleteBackupErr +} diff --git a/internal/pkg/cli/command/backup/cmd.go b/internal/pkg/cli/command/index/backup/cmd.go similarity index 60% rename from internal/pkg/cli/command/backup/cmd.go rename to internal/pkg/cli/command/index/backup/cmd.go index 14a21354..0b15f1de 100644 --- a/internal/pkg/cli/command/backup/cmd.go +++ b/internal/pkg/cli/command/index/backup/cmd.go @@ -1,19 +1,18 @@ package backup import ( - "github.com/pinecone-io/cli/internal/pkg/cli/command/backup/restore" "github.com/pinecone-io/cli/internal/pkg/utils/help" "github.com/spf13/cobra" ) + var ( backupHelp = help.Long(` Manage backups for serverless indexes. A backup is a static copy of a serverless index that only consumes storage. It is a non-queryable representation of a set of records. You can create a backup of a serverless index, and you can create a new index from a backup. - Use these commands to create, describe, list, and delete backups, or to - restore an index from a backup, or inspect restore jobs. + Use these commands to create, describe, list, and delete backups. See: https://docs.pinecone.io/guides/manage-data/backups-overview `) @@ -21,24 +20,25 @@ var ( func NewBackupCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "backup", - Short: "Manage serverless index backups", - Long: backupHelp, + Use: "backup", + Short: "Manage serverless index backups", + Long: backupHelp, + GroupID: help.GROUP_INDEX_MANAGEMENT.ID, Example: help.Examples(` # Create a backup for a serverless index - pc backup create --index-name my-index --name daily-backup + pc index backup create --index-name my-index --name daily-backup # List backups for a serverless index - pc backup list --index-name my-index + pc index backup list --index-name my-index - # Restore an index from a backup - pc backup restore --id backup-123 --name restored-index + # List all backups in the project + pc index backup list - # List restore jobs - pc backup restore list + # Describe a backup + pc index backup describe --id backup-123 - # Describe a restore job - pc backup restore describe --id rj-123 + # Delete a backup + pc index backup delete --id backup-123 `), } @@ -47,7 +47,5 @@ func NewBackupCmd() *cobra.Command { cmd.AddCommand(NewListBackupsCmd()) cmd.AddCommand(NewDeleteBackupCmd()) - cmd.AddCommand(restore.NewRestoreJobCmd()) - return cmd } diff --git a/internal/pkg/cli/command/backup/create.go b/internal/pkg/cli/command/index/backup/create.go similarity index 91% rename from internal/pkg/cli/command/backup/create.go rename to internal/pkg/cli/command/index/backup/create.go index 322a7e66..74d42a06 100644 --- a/internal/pkg/cli/command/backup/create.go +++ b/internal/pkg/cli/command/index/backup/create.go @@ -16,12 +16,12 @@ import ( "github.com/spf13/cobra" ) +// BackupService defines the SDK operations used by backup commands. type BackupService interface { CreateBackup(ctx context.Context, in *pinecone.CreateBackupParams) (*pinecone.Backup, error) DescribeBackup(ctx context.Context, backupId string) (*pinecone.Backup, error) ListBackups(ctx context.Context, in *pinecone.ListBackupsParams) (*pinecone.BackupList, error) DeleteBackup(ctx context.Context, backupId string) error - CreateIndexFromBackup(ctx context.Context, in *pinecone.CreateIndexFromBackupParams) (*pinecone.CreateIndexFromBackupResponse, error) } type createBackupCmdOptions struct { @@ -44,8 +44,8 @@ func NewCreateBackupCmd() *cobra.Command { the backup later. `), Example: help.Examples(` - pc backup create --index-name my-index - pc backup create --index-name my-index --name nightly --description "Nightly backup" + pc index backup create --index-name my-index + pc index backup create --index-name my-index --name nightly --description "Nightly backup" `), Run: func(cmd *cobra.Command, args []string) { ctx := cmd.Context() diff --git a/internal/pkg/cli/command/backup/create_test.go b/internal/pkg/cli/command/index/backup/create_test.go similarity index 100% rename from internal/pkg/cli/command/backup/create_test.go rename to internal/pkg/cli/command/index/backup/create_test.go diff --git a/internal/pkg/cli/command/backup/delete.go b/internal/pkg/cli/command/index/backup/delete.go similarity index 97% rename from internal/pkg/cli/command/backup/delete.go rename to internal/pkg/cli/command/index/backup/delete.go index 5fe4c97c..1e4ff98a 100644 --- a/internal/pkg/cli/command/backup/delete.go +++ b/internal/pkg/cli/command/index/backup/delete.go @@ -26,7 +26,7 @@ func NewDeleteBackupCmd() *cobra.Command { Use: "delete", Short: "Delete a backup by ID", Example: help.Examples(` - pc backup delete --id backup-123 + pc index backup delete --id backup-123 `), Run: func(cmd *cobra.Command, args []string) { ctx := cmd.Context() diff --git a/internal/pkg/cli/command/backup/delete_test.go b/internal/pkg/cli/command/index/backup/delete_test.go similarity index 100% rename from internal/pkg/cli/command/backup/delete_test.go rename to internal/pkg/cli/command/index/backup/delete_test.go diff --git a/internal/pkg/cli/command/backup/describe.go b/internal/pkg/cli/command/index/backup/describe.go similarity index 91% rename from internal/pkg/cli/command/backup/describe.go rename to internal/pkg/cli/command/index/backup/describe.go index c2946aa4..e4a00bf4 100644 --- a/internal/pkg/cli/command/backup/describe.go +++ b/internal/pkg/cli/command/index/backup/describe.go @@ -25,8 +25,11 @@ func NewDescribeBackupCmd() *cobra.Command { cmd := &cobra.Command{ Use: "describe", Short: "Describe a backup by ID", + Long: help.Long(` + Describe a backup by its ID, showing status, source index, and storage details. + `), Example: help.Examples(` - pc backup describe --id backup-123 + pc index backup describe --id backup-123 `), Run: func(cmd *cobra.Command, args []string) { ctx := cmd.Context() diff --git a/internal/pkg/cli/command/backup/describe_test.go b/internal/pkg/cli/command/index/backup/describe_test.go similarity index 100% rename from internal/pkg/cli/command/backup/describe_test.go rename to internal/pkg/cli/command/index/backup/describe_test.go diff --git a/internal/pkg/cli/command/backup/list.go b/internal/pkg/cli/command/index/backup/list.go similarity index 96% rename from internal/pkg/cli/command/backup/list.go rename to internal/pkg/cli/command/index/backup/list.go index 4cf98629..90ef9ce6 100644 --- a/internal/pkg/cli/command/backup/list.go +++ b/internal/pkg/cli/command/index/backup/list.go @@ -2,7 +2,6 @@ package backup import ( "context" - "fmt" "github.com/pinecone-io/cli/internal/pkg/utils/exit" @@ -33,10 +32,10 @@ func NewListBackupsCmd() *cobra.Command { `), Example: help.Examples(` # List backups for the current project - pc backup list + pc index backup list # List backups for a specific index - pc backup list --index-name my-index --limit 10 + pc index backup list --index-name my-index --limit 10 `), Run: func(cmd *cobra.Command, args []string) { ctx := cmd.Context() diff --git a/internal/pkg/cli/command/backup/list_test.go b/internal/pkg/cli/command/index/backup/list_test.go similarity index 100% rename from internal/pkg/cli/command/backup/list_test.go rename to internal/pkg/cli/command/index/backup/list_test.go diff --git a/internal/pkg/cli/command/index/cmd.go b/internal/pkg/cli/command/index/cmd.go index d6818783..7dca57f5 100644 --- a/internal/pkg/cli/command/index/cmd.go +++ b/internal/pkg/cli/command/index/cmd.go @@ -1,8 +1,11 @@ package index import ( + "github.com/pinecone-io/cli/internal/pkg/cli/command/index/backup" + "github.com/pinecone-io/cli/internal/pkg/cli/command/index/collection" "github.com/pinecone-io/cli/internal/pkg/cli/command/index/namespace" "github.com/pinecone-io/cli/internal/pkg/cli/command/index/record" + "github.com/pinecone-io/cli/internal/pkg/cli/command/index/restore" "github.com/pinecone-io/cli/internal/pkg/cli/command/index/vector" "github.com/pinecone-io/cli/internal/pkg/utils/help" "github.com/spf13/cobra" @@ -49,5 +52,10 @@ func NewIndexCmd() *cobra.Command { cmd.AddGroup(help.GROUP_INDEX_NAMESPACE) cmd.AddCommand(namespace.NewNamespaceCmd()) + cmd.AddGroup(help.GROUP_INDEX_MANAGEMENT) + cmd.AddCommand(backup.NewBackupCmd()) + cmd.AddCommand(restore.NewRestoreCmd()) + cmd.AddCommand(collection.NewCollectionCmd()) + return cmd } diff --git a/internal/pkg/cli/command/collection/cmd.go b/internal/pkg/cli/command/index/collection/cmd.go similarity index 80% rename from internal/pkg/cli/command/collection/cmd.go rename to internal/pkg/cli/command/index/collection/cmd.go index 4b805350..134409c4 100644 --- a/internal/pkg/cli/command/collection/cmd.go +++ b/internal/pkg/cli/command/index/collection/cmd.go @@ -29,7 +29,13 @@ func NewCollectionCmd() *cobra.Command { Use: "collection", Short: "Work with collections (pod-based indexes only)", Long: collectionHelp, - GroupID: help.GROUP_VECTORDB.ID, + GroupID: help.GROUP_INDEX_MANAGEMENT.ID, + Example: help.Examples(` + pc index collection list + pc index collection create --name my-collection --source my-index + pc index collection describe --name my-collection + pc index collection delete --name my-collection + `), } cmd.AddCommand(NewCreateCollectionCmd()) diff --git a/internal/pkg/cli/command/collection/create.go b/internal/pkg/cli/command/index/collection/create.go similarity index 90% rename from internal/pkg/cli/command/collection/create.go rename to internal/pkg/cli/command/index/collection/create.go index 1a241561..6b37fe81 100644 --- a/internal/pkg/cli/command/collection/create.go +++ b/internal/pkg/cli/command/index/collection/create.go @@ -29,7 +29,7 @@ func NewCreateCollectionCmd() *cobra.Command { Use: "create", Short: "Create a collection from a pod-based index", Example: help.Examples(` - pc collection create --name "collection-name" --source "index-source-name" + pc index collection create --name my-collection --source my-index `), Run: func(cmd *cobra.Command, args []string) { ctx := cmd.Context() @@ -49,20 +49,17 @@ func NewCreateCollectionCmd() *cobra.Command { json := text.IndentJSON(collection) fmt.Fprintln(os.Stdout, json) } else { - describeCommand := fmt.Sprintf("pc collection describe --name %s", collection.Name) + describeCommand := fmt.Sprintf("pc index collection describe --name %s", collection.Name) msg.SuccessMsg("Collection %s created successfully. Run %s to check status. \n\n", style.Emphasis(collection.Name), style.Code(describeCommand)) presenters.PrintDescribeCollectionTable(collection) } }, } - // Required flags cmd.Flags().StringVarP(&options.name, "name", "n", "", "name you want to give the collection") _ = cmd.MarkFlagRequired("name") cmd.Flags().StringVarP(&options.sourceIndex, "source", "s", "", "name of the index to use as the source for the collection") _ = cmd.MarkFlagRequired("source") - - // Optional flags cmd.Flags().BoolVarP(&options.json, "json", "j", false, "output as JSON") return cmd diff --git a/internal/pkg/cli/command/collection/delete.go b/internal/pkg/cli/command/index/collection/delete.go similarity index 96% rename from internal/pkg/cli/command/collection/delete.go rename to internal/pkg/cli/command/index/collection/delete.go index bedfc986..20931ada 100644 --- a/internal/pkg/cli/command/collection/delete.go +++ b/internal/pkg/cli/command/index/collection/delete.go @@ -29,7 +29,7 @@ func NewDeleteCollectionCmd() *cobra.Command { Use: "delete", Short: "Delete a collection", Example: help.Examples(` - pc collection delete --name "collection-name" + pc index collection delete --name my-collection `), Run: func(cmd *cobra.Command, args []string) { ctx := cmd.Context() @@ -43,10 +43,8 @@ func NewDeleteCollectionCmd() *cobra.Command { }, } - // required flags cmd.Flags().StringVarP(&options.name, "name", "n", "", "name of collection to delete") cmd.Flags().BoolVarP(&options.json, "json", "j", false, "Output result as JSON") - _ = cmd.MarkFlagRequired("name") return cmd diff --git a/internal/pkg/cli/command/collection/delete_test.go b/internal/pkg/cli/command/index/collection/delete_test.go similarity index 100% rename from internal/pkg/cli/command/collection/delete_test.go rename to internal/pkg/cli/command/index/collection/delete_test.go diff --git a/internal/pkg/cli/command/collection/describe.go b/internal/pkg/cli/command/index/collection/describe.go similarity index 94% rename from internal/pkg/cli/command/collection/describe.go rename to internal/pkg/cli/command/index/collection/describe.go index c7ea475d..2bc4026f 100644 --- a/internal/pkg/cli/command/collection/describe.go +++ b/internal/pkg/cli/command/index/collection/describe.go @@ -25,7 +25,7 @@ func NewDescribeCollectionCmd() *cobra.Command { Use: "describe", Short: "Describe a collection by name", Example: help.Examples(` - pc collection describe --name "collection-name" + pc index collection describe --name my-collection `), Run: func(cmd *cobra.Command, args []string) { ctx := cmd.Context() @@ -46,11 +46,8 @@ func NewDescribeCollectionCmd() *cobra.Command { }, } - // required flags cmd.Flags().StringVarP(&options.name, "name", "n", "", "name of collection to describe") _ = cmd.MarkFlagRequired("name") - - // optional flags cmd.Flags().BoolVarP(&options.json, "json", "j", false, "output as JSON") return cmd diff --git a/internal/pkg/cli/command/collection/list.go b/internal/pkg/cli/command/index/collection/list.go similarity index 95% rename from internal/pkg/cli/command/collection/list.go rename to internal/pkg/cli/command/index/collection/list.go index 33cea4e3..e24d3687 100644 --- a/internal/pkg/cli/command/collection/list.go +++ b/internal/pkg/cli/command/index/collection/list.go @@ -29,7 +29,7 @@ func NewListCollectionsCmd() *cobra.Command { Use: "list", Short: "See the list of collections in your project", Example: help.Examples(` - pc collection list + pc index collection list `), Run: func(cmd *cobra.Command, args []string) { ctx := cmd.Context() @@ -41,7 +41,6 @@ func NewListCollectionsCmd() *cobra.Command { exit.Error(err, "Failed to list collections") } - // Sort results alphabetically by name sort.SliceStable(collections, func(i, j int) bool { return collections[i].Name < collections[j].Name }) @@ -55,7 +54,6 @@ func NewListCollectionsCmd() *cobra.Command { }, } - // Optional flags cmd.Flags().BoolVarP(&options.json, "json", "j", false, "output as JSON") return cmd diff --git a/internal/pkg/cli/command/index/configure.go b/internal/pkg/cli/command/index/configure.go index d0636eaf..5e55925c 100644 --- a/internal/pkg/cli/command/index/configure.go +++ b/internal/pkg/cli/command/index/configure.go @@ -59,6 +59,7 @@ func NewConfigureIndexCmd() *cobra.Command { // Required flags cmd.Flags().StringVarP(&options.name, "name", "n", "", "Name of index to configure") + _ = cmd.MarkFlagRequired("name") // pods cmd.Flags().StringVarP(&options.podType, "pod-type", "t", "", "Type of pod to use, can only upgrade when configuring") diff --git a/internal/pkg/cli/command/index/create.go b/internal/pkg/cli/command/index/create.go index 14cfaa52..de037b5f 100644 --- a/internal/pkg/cli/command/index/create.go +++ b/internal/pkg/cli/command/index/create.go @@ -262,6 +262,14 @@ func runCreateIndexCmd(ctx context.Context, cmd *cobra.Command, service CreateIn return nil, err } + // Only forward metric if explicitly set — the model has its own default and + // the flag default ("cosine") must not silently override it. + var embedMetric *pinecone.IndexMetric + if cmd.Flags().Changed("metric") { + m := pinecone.IndexMetric(options.metric) + embedMetric = &m + } + args := pinecone.CreateIndexForModelRequest{ Name: options.name, Cloud: pinecone.Cloud(options.cloud), @@ -270,6 +278,8 @@ func runCreateIndexCmd(ctx context.Context, cmd *cobra.Command, service CreateIn Embed: pinecone.CreateIndexForModelEmbed{ Model: options.model, FieldMap: toInterfaceMap(options.fieldMap), + Metric: embedMetric, + Dimension: pointerOrNil(int(options.dimension)), ReadParameters: &readParams, WriteParameters: &writeParams, }, diff --git a/internal/pkg/cli/command/index/create_test.go b/internal/pkg/cli/command/index/create_test.go index f47d79ac..ce4ca194 100644 --- a/internal/pkg/cli/command/index/create_test.go +++ b/internal/pkg/cli/command/index/create_test.go @@ -134,6 +134,38 @@ func Test_runCreateIndexWithService_Integrated_Args(t *testing.T) { assert.Equal(t, toInterfaceMap(options.readParameters), *svc.lastIntegrated.Embed.ReadParameters) assert.Equal(t, toInterfaceMap(options.writeParameters), *svc.lastIntegrated.Embed.WriteParameters) assert.Equal(t, pinecone.IndexTags(options.tags), *svc.lastIntegrated.Tags) + // metric and dimension not explicitly set — must not be forwarded to the embed request + assert.Nil(t, svc.lastIntegrated.Embed.Metric) + assert.Nil(t, svc.lastIntegrated.Embed.Dimension) +} + +func Test_runCreateIndexWithService_Integrated_MetricAndDimension(t *testing.T) { + cmd := NewCreateIndexCmd() + _ = cmd.Flags().Set("metric", "dotproduct") + _ = cmd.Flags().Set("dimension", "512") + + svc := &mockIndexService{result: &pinecone.Index{Name: "my-index"}} + options := createIndexOptions{ + name: "my-index", + cloud: "aws", + region: "us-east-1", + model: "multilingual-e5-large", + fieldMap: map[string]string{"text": "chunk"}, + metric: "dotproduct", + dimension: 512, + } + + _, err := runCreateIndexCmd(context.Background(), cmd, svc, options) + assert.NoError(t, err) + + if assert.NotNil(t, svc.lastIntegrated) { + if assert.NotNil(t, svc.lastIntegrated.Embed.Metric) { + assert.Equal(t, pinecone.IndexMetric("dotproduct"), *svc.lastIntegrated.Embed.Metric) + } + if assert.NotNil(t, svc.lastIntegrated.Embed.Dimension) { + assert.Equal(t, 512, *svc.lastIntegrated.Embed.Dimension) + } + } } func Test_createIndexOptions_deriveIndexType(t *testing.T) { diff --git a/internal/pkg/cli/command/backup/restore/cmd.go b/internal/pkg/cli/command/index/restore/cmd.go similarity index 74% rename from internal/pkg/cli/command/backup/restore/cmd.go rename to internal/pkg/cli/command/index/restore/cmd.go index 3732a9bd..e6233b63 100644 --- a/internal/pkg/cli/command/backup/restore/cmd.go +++ b/internal/pkg/cli/command/index/restore/cmd.go @@ -16,18 +16,19 @@ import ( ) var ( - restoreJobHelp = help.Long(` - Restore an index from a backup, and list/describe restore jobs. + restoreHelp = help.Long(` + Restore an index from a backup, and list or describe restore jobs. - When restoring a serverless index from backup, you can change the index name, tags, and deletion protection setting. - All other properties of the restored index will remain identical to the source index, including cloud and region, - dimension and similarity metric, and associated embedding model when restoring an index with integrated embedding. + When restoring a serverless index from a backup, you can change the index name, tags, + and deletion protection setting. All other properties of the restored index will remain + identical to the source index, including cloud and region, dimension and similarity metric, + and associated embedding model when restoring an index with integrated embedding. See: https://docs.pinecone.io/guides/manage-data/restore-an-index `) ) -type restoreJobCmdOptions struct { +type restoreCmdOptions struct { backupId string name string deletionProtection string @@ -35,33 +36,35 @@ type restoreJobCmdOptions struct { json bool } +// RestoreJobService defines the SDK operations used by restore commands. type RestoreJobService interface { DescribeRestoreJob(ctx context.Context, restoreJobId string) (*pinecone.RestoreJob, error) ListRestoreJobs(ctx context.Context, in *pinecone.ListRestoreJobsParams) (*pinecone.RestoreJobList, error) CreateIndexFromBackup(ctx context.Context, in *pinecone.CreateIndexFromBackupParams) (*pinecone.CreateIndexFromBackupResponse, error) } -func NewRestoreJobCmd() *cobra.Command { - options := restoreJobCmdOptions{} +func NewRestoreCmd() *cobra.Command { + options := restoreCmdOptions{} cmd := &cobra.Command{ - Use: "restore", - Short: "Restore an index from a backup, and inspect restore jobs", - Long: restoreJobHelp, + Use: "restore", + Short: "Restore an index from a backup and manage restore jobs", + Long: restoreHelp, + GroupID: help.GROUP_INDEX_MANAGEMENT.ID, Example: help.Examples(` # Restore an index from a backup - pc backup restore --id backup-123 --name restored-index --tags env=prod,team=search --deletion-protection enabled + pc index restore --id backup-123 --name restored-index --tags env=prod,team=search --deletion-protection enabled # List restore jobs - pc backup restore list + pc index restore list # Describe a restore job - pc backup restore describe --id rj-123 + pc index restore describe --id rj-123 `), Run: func(cmd *cobra.Command, args []string) { ctx := cmd.Context() pc := sdk.NewPineconeClient(ctx) - err := runRestoreJobCmd(ctx, pc, options) + err := runRestoreCmd(ctx, pc, options) if err != nil { msg.FailJSON(options.json, "Failed to create restore job: %s\n", err) exit.Error(err, "Failed to create restore job") @@ -83,7 +86,7 @@ func NewRestoreJobCmd() *cobra.Command { return cmd } -func runRestoreJobCmd(ctx context.Context, svc RestoreJobService, options restoreJobCmdOptions) error { +func runRestoreCmd(ctx context.Context, svc RestoreJobService, options restoreCmdOptions) error { if strings.TrimSpace(options.backupId) == "" { return fmt.Errorf("--id is required") } @@ -119,7 +122,7 @@ func runRestoreJobCmd(ctx context.Context, svc RestoreJobService, options restor msg.SuccessMsg("Restore job %s started for backup %s.\n", style.Emphasis(resp.RestoreJobId), style.Emphasis(options.backupId)) msg.InfoMsg("Created index ID: %s\n", style.Emphasis(resp.IndexId)) - msg.InfoMsg("Use %s to monitor progress.\n", style.Code("pc backup restore describe --id "+resp.RestoreJobId)) + msg.InfoMsg("Use %s to monitor progress.\n", style.Code("pc index restore describe --id "+resp.RestoreJobId)) return nil } diff --git a/internal/pkg/cli/command/backup/restore/describe.go b/internal/pkg/cli/command/index/restore/describe.go similarity index 97% rename from internal/pkg/cli/command/backup/restore/describe.go rename to internal/pkg/cli/command/index/restore/describe.go index 7aa2be33..c47fad39 100644 --- a/internal/pkg/cli/command/backup/restore/describe.go +++ b/internal/pkg/cli/command/index/restore/describe.go @@ -26,7 +26,7 @@ func NewDescribeRestoreJobCmd() *cobra.Command { Use: "describe", Short: "Describe a restore job by ID", Example: help.Examples(` - pc backup restore describe --id rj-123 + pc index restore describe --id rj-123 `), Run: func(cmd *cobra.Command, args []string) { ctx := cmd.Context() diff --git a/internal/pkg/cli/command/backup/restore/list.go b/internal/pkg/cli/command/index/restore/list.go similarity index 95% rename from internal/pkg/cli/command/backup/restore/list.go rename to internal/pkg/cli/command/index/restore/list.go index ec483147..f32086cd 100644 --- a/internal/pkg/cli/command/backup/restore/list.go +++ b/internal/pkg/cli/command/index/restore/list.go @@ -27,8 +27,8 @@ func NewListRestoreJobsCmd() *cobra.Command { Use: "list", Short: "List restore jobs in the current project", Example: help.Examples(` - pc backup restore list - pc backup restore list --limit 5 --pagination-token token + pc index restore list + pc index restore list --limit 5 --pagination-token token `), Run: func(cmd *cobra.Command, args []string) { ctx := cmd.Context() diff --git a/internal/pkg/cli/command/backup/restore/restore_test.go b/internal/pkg/cli/command/index/restore/restore_test.go similarity index 90% rename from internal/pkg/cli/command/backup/restore/restore_test.go rename to internal/pkg/cli/command/index/restore/restore_test.go index c7228227..8316472d 100644 --- a/internal/pkg/cli/command/backup/restore/restore_test.go +++ b/internal/pkg/cli/command/index/restore/restore_test.go @@ -90,31 +90,31 @@ func Test_runListRestoreJobsCmd_PopulatesParams(t *testing.T) { } } -func Test_runRestoreJobCmd_ValidatesRequired(t *testing.T) { +func Test_runRestoreCmd_ValidatesRequired(t *testing.T) { svc := &mockRestoreJobService{} - err := runRestoreJobCmd(context.Background(), svc, restoreJobCmdOptions{}) + err := runRestoreCmd(context.Background(), svc, restoreCmdOptions{}) assert.Error(t, err) - err = runRestoreJobCmd(context.Background(), svc, restoreJobCmdOptions{backupId: "b1"}) + err = runRestoreCmd(context.Background(), svc, restoreCmdOptions{backupId: "b1"}) assert.Error(t, err) } -func Test_runCreateIndexFromBackupCmd_Succeeds(t *testing.T) { +func Test_runRestoreCmd_Succeeds(t *testing.T) { svc := &mockRestoreJobService{ createIndexFromBackupResp: &pinecone.CreateIndexFromBackupResponse{ IndexId: "idx-id", RestoreJobId: "rj-1", }, } - opts := restoreJobCmdOptions{ + opts := restoreCmdOptions{ backupId: "b1", name: "new-index", deletionProtection: "enabled", tags: map[string]string{"env": "prod"}, } - err := runRestoreJobCmd(context.Background(), svc, opts) + err := runRestoreCmd(context.Background(), svc, opts) if assert.NoError(t, err) { if assert.NotNil(t, svc.lastCreateIndexFromBackupReq) { diff --git a/internal/pkg/cli/command/root/root.go b/internal/pkg/cli/command/root/root.go index 674eb192..a05007ce 100644 --- a/internal/pkg/cli/command/root/root.go +++ b/internal/pkg/cli/command/root/root.go @@ -11,8 +11,6 @@ import ( "github.com/pinecone-io/cli/internal/pkg/cli/command/apiKey" "github.com/pinecone-io/cli/internal/pkg/cli/command/auth" - "github.com/pinecone-io/cli/internal/pkg/cli/command/backup" - "github.com/pinecone-io/cli/internal/pkg/cli/command/collection" "github.com/pinecone-io/cli/internal/pkg/cli/command/config" "github.com/pinecone-io/cli/internal/pkg/cli/command/index" "github.com/pinecone-io/cli/internal/pkg/cli/command/login" @@ -172,8 +170,6 @@ func init() { // Vector database group rootCmd.AddGroup(help.GROUP_VECTORDB) rootCmd.AddCommand(index.NewIndexCmd()) - rootCmd.AddCommand(collection.NewCollectionCmd()) - rootCmd.AddCommand(backup.NewBackupCmd()) // Misc group rootCmd.AddCommand(version.NewVersionCmd()) diff --git a/internal/pkg/utils/help/groups.go b/internal/pkg/utils/help/groups.go index 69605f3d..d0d204ed 100644 --- a/internal/pkg/utils/help/groups.go +++ b/internal/pkg/utils/help/groups.go @@ -38,4 +38,8 @@ var ( ID: "index-namespace", Title: style.Heading("Index Namespace Commands"), } + GROUP_INDEX_MANAGEMENT = &cobra.Group{ + ID: "index-management", + Title: style.Heading("Index Management Commands"), + } ) diff --git a/internal/pkg/utils/presenters/backup.go b/internal/pkg/utils/presenters/backup.go index fb21c40f..4d903e80 100644 --- a/internal/pkg/utils/presenters/backup.go +++ b/internal/pkg/utils/presenters/backup.go @@ -23,10 +23,13 @@ func PrintBackupTable(backup *pinecone.Backup) { fmt.Fprintf(writer, "Backup ID\t%s\n", backup.BackupId) fmt.Fprintf(writer, "Name\t%s\n", DisplayOrNone(backup.Name)) + fmt.Fprintf(writer, "Description\t%s\n", DisplayOrNone(backup.Description)) fmt.Fprintf(writer, "Status\t%s\n", colorizeBackupStatus(backup.Status)) fmt.Fprintf(writer, "Source Index\t%s\n", backup.SourceIndexName) + fmt.Fprintf(writer, "Source Index ID\t%s\n", backup.SourceIndexId) fmt.Fprintf(writer, "Cloud\t%s\n", backup.Cloud) fmt.Fprintf(writer, "Region\t%s\n", backup.Region) + fmt.Fprintf(writer, "Dimension\t%s\n", DisplayOrNone(backup.Dimension)) fmt.Fprintf(writer, "Record Count\t%s\n", DisplayOrNone(backup.RecordCount)) fmt.Fprintf(writer, "Namespace Count\t%s\n", DisplayOrNone(backup.NamespaceCount)) fmt.Fprintf(writer, "Size (bytes)\t%s\n", DisplayOrNone(backup.SizeBytes))