Skip to content
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
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ The `pc config` command manages these settings via a key-based interface. Valid

### `--json` flag

Available on most commands. Forces structured, machine-readable output. Also activated automatically when stdout is not a TTY.
Available on most commands. Must be set explicitly to force structured, machine-readable output — it is **not** inferred from whether stdout is a TTY. (Color is suppressed automatically on a non-TTY, but the data output format is not.) The interactive auth flows — `login`, `target`, and `auth` — are the exception: they additionally infer JSON output when stdout is not a TTY, since an agent on a non-TTY can't drive their prompts.

---

Expand Down
38 changes: 6 additions & 32 deletions internal/pkg/cli/command/apiKey/delete.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package apiKey

import (
"bufio"
"fmt"
"os"
"strings"

"github.com/pinecone-io/cli/internal/pkg/utils/configuration/secrets"
"github.com/pinecone-io/cli/internal/pkg/utils/configuration/state"
"github.com/pinecone-io/cli/internal/pkg/utils/confirm"
"github.com/pinecone-io/cli/internal/pkg/utils/exit"
"github.com/pinecone-io/cli/internal/pkg/utils/help"
"github.com/pinecone-io/cli/internal/pkg/utils/msg"
Expand Down Expand Up @@ -61,7 +59,11 @@ func NewDeleteKeyCmd() *cobra.Command {
}

if !options.skipConfirmation && !options.json {
confirmDeleteApiKey(keyToDelete.Name)
confirm.Deletion(
fmt.Sprintf("This operation will delete API key %s from project %s.", style.Emphasis(keyToDelete.Name), style.Emphasis(state.TargetProj.Get().Name)),
"Any integrations that authenticate with this API key will immediately stop working.",
"This action cannot be undone.",
)
}

err = ac.APIKey.Delete(cmd.Context(), keyToDelete.Id)
Expand Down Expand Up @@ -96,31 +98,3 @@ func NewDeleteKeyCmd() *cobra.Command {
cmd.Flags().BoolVarP(&options.json, "json", "j", false, "Output result as JSON (also skips confirmation prompt)")
return cmd
}

func confirmDeleteApiKey(apiKeyName string) {
msg.WarnMsg("This operation will delete API key %s from project %s.", style.Emphasis(apiKeyName), style.Emphasis(state.TargetProj.Get().Name))
msg.WarnMsg("Any integrations that authenticate with this API key will immediately stop working.")
msg.WarnMsg("This action cannot be undone.")

// Prompt the user
fmt.Fprint(os.Stderr, "Do you want to continue? (y/N): ")

// Read the user's input
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
msg.FailMsg("Error reading input: %+v", err)
exit.Error(err, "Error reading input")
}

// Trim any whitespace from the input and convert to lowercase
input = strings.TrimSpace(strings.ToLower(input))

// Check if the user entered "y" or "yes"
if input == "y" || input == "yes" {
msg.InfoMsg("You chose to continue delete.")
} else {
msg.InfoMsg("Operation canceled.")
exit.Success()
}
}
2 changes: 1 addition & 1 deletion internal/pkg/cli/command/apiKey/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func NewListKeysCmd() *cobra.Command {
if projId == "" {
projId, err = state.GetTargetProjectId()
if err != nil {
msg.FailJSON(options.json, "No target project set, and no project ID provided. Use %s to set the target project. Use %s to create the key in a specific project.", style.Code("pc target -o <org> -p <project>"), style.Code("pc api-key create -i <project-id> -n <name>"))
msg.FailJSON(options.json, "No target project set, and no project ID provided. Use %s to set the target project. Use %s to list keys for a specific project.", style.Code("pc target -o <org> -p <project>"), style.Code("pc api-key list -i <project-id>"))
exit.ErrorMsg("No project ID provided, and no target project set")
}
}
Expand Down
4 changes: 4 additions & 0 deletions internal/pkg/cli/command/auth/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ func Run(ctx context.Context, opts configureCmdOptions) {
break
}
}
if targetProject == nil {
msg.FailJSON(opts.json, "No project found with ID %s for the service account", opts.projectID)
exit.ErrorMsg(fmt.Sprintf("No project found with ID %s for the service account", opts.projectID))
}
} else {
targetProject = uiProjectSelector(projects, opts.json)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/cli/command/auth/local_keys_prune.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func runPruneLocalKeys(ctx context.Context, options pruneLocalKeysCmdOptions) {
// Dry run preview
if options.dryRun {
printDryRunPlan(plan, options)
msg.InfoMsg("Dry run complete. Re-run with %s and %s to apply changes", style.Emphasis("--yes"), style.Emphasis("--dry-run=false"))
msg.InfoMsg("Dry run complete. Re-run without %s to apply changes (add %s to skip the prompt)", style.Emphasis("--dry-run"), style.Emphasis("--skip-confirmation"))
return
}

Expand Down
16 changes: 13 additions & 3 deletions internal/pkg/cli/command/index/backup/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"strings"

"github.com/pinecone-io/cli/internal/pkg/utils/confirm"
"github.com/pinecone-io/cli/internal/pkg/utils/exit"
"github.com/pinecone-io/cli/internal/pkg/utils/help"
"github.com/pinecone-io/cli/internal/pkg/utils/msg"
Expand All @@ -15,8 +16,9 @@ import (
)

type deleteBackupCmdOptions struct {
backupId string
json bool
backupId string
skipConfirmation bool
json bool
}

func NewDeleteBackupCmd() *cobra.Command {
Expand All @@ -32,6 +34,13 @@ func NewDeleteBackupCmd() *cobra.Command {
ctx := cmd.Context()
pc := sdk.NewPineconeClient(ctx)

if !options.skipConfirmation && !options.json {
confirm.Deletion(
fmt.Sprintf("This will delete backup %s.", style.Emphasis(options.backupId)),
"This action cannot be undone.",
)
}

err := runDeleteBackupCmd(ctx, pc, options)
if err != nil {
msg.FailJSON(options.json, "Failed to delete backup: %s\n", err)
Expand All @@ -42,7 +51,8 @@ func NewDeleteBackupCmd() *cobra.Command {

cmd.Flags().StringVarP(&options.backupId, "id", "i", "", "ID of the backup to delete")
_ = cmd.MarkFlagRequired("id")
cmd.Flags().BoolVarP(&options.json, "json", "j", false, "Output result as JSON")
cmd.Flags().BoolVar(&options.skipConfirmation, "skip-confirmation", false, "Skip the deletion confirmation prompt")
cmd.Flags().BoolVarP(&options.json, "json", "j", false, "Output result as JSON (also skips confirmation prompt)")

return cmd
}
Expand Down
16 changes: 13 additions & 3 deletions internal/pkg/cli/command/index/collection/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"

"github.com/pinecone-io/cli/internal/pkg/utils/confirm"
"github.com/pinecone-io/cli/internal/pkg/utils/exit"
"github.com/pinecone-io/cli/internal/pkg/utils/help"
"github.com/pinecone-io/cli/internal/pkg/utils/msg"
Expand All @@ -14,8 +15,9 @@ import (
)

type deleteCollectionCmdOptions struct {
name string
json bool
name string
skipConfirmation bool
json bool
}

// DeleteCollectionService abstracts the Pinecone Go SDK for unit testing (runDeleteCollectionCmd)
Expand All @@ -36,6 +38,13 @@ func NewDeleteCollectionCmd() *cobra.Command {
ctx := cmd.Context()
pc := sdk.NewPineconeClient(ctx)

if !options.skipConfirmation && !options.json {
confirm.Deletion(
fmt.Sprintf("This will delete collection %s.", style.Emphasis(options.name)),
"This action cannot be undone.",
)
}

err := runDeleteCollectionCmd(ctx, pc, options)
if err != nil {
msg.FailJSON(options.json, "Failed to delete collection %s: %s\n", style.Emphasis(options.name), err)
Expand All @@ -49,7 +58,8 @@ func NewDeleteCollectionCmd() *cobra.Command {
_ = cmd.MarkFlagRequired("name")

// Optional flags
cmd.Flags().BoolVarP(&options.json, "json", "j", false, "Output result as JSON")
cmd.Flags().BoolVar(&options.skipConfirmation, "skip-confirmation", false, "Skip the deletion confirmation prompt")
cmd.Flags().BoolVarP(&options.json, "json", "j", false, "Output result as JSON (also skips confirmation prompt)")

return cmd
}
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/cli/command/index/collection/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func printTable(collections []*pinecone.Collection) {
fmt.Fprint(writer, header)

for _, coll := range collections {
values := []string{coll.Name, string(coll.Dimension), strconv.FormatInt(coll.Size, 10), string(coll.Status), string(coll.VectorCount), coll.Environment}
values := []string{coll.Name, strconv.Itoa(int(coll.Dimension)), strconv.FormatInt(coll.Size, 10), string(coll.Status), strconv.Itoa(int(coll.VectorCount)), coll.Environment}
fmt.Fprint(writer, strings.Join(values, "\t")+"\n")
}
writer.Flush()
Expand Down
3 changes: 2 additions & 1 deletion internal/pkg/cli/command/index/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,9 @@ func NewConfigureIndexCmd() *cobra.Command {
cmd.Flags().Int32Var(&options.readReplicas, "read-replicas", 0, "The number of replicas to use. Replicas duplicate the compute resources and data of an index, allowing higher query throughput and availability")

// optional for all index types
cmd.Flags().StringVarP(&options.deletionProtection, "deletion-protection", "p", "", "Enable or disable deletion protection for the index. One of: enabled, disabled")
cmd.Flags().StringVar(&options.deletionProtection, "deletion-protection", "", "Enable or disable deletion protection for the index. One of: enabled, disabled")
cmd.Flags().StringToStringVar(&options.tags, "tags", map[string]string{}, "Custom user tags to add to an index")
cmd.Flags().BoolVarP(&options.json, "json", "j", false, "Output as JSON")

return cmd
}
Expand Down
16 changes: 13 additions & 3 deletions internal/pkg/cli/command/index/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"strings"

"github.com/pinecone-io/cli/internal/pkg/utils/confirm"
"github.com/pinecone-io/cli/internal/pkg/utils/exit"
"github.com/pinecone-io/cli/internal/pkg/utils/help"
"github.com/pinecone-io/cli/internal/pkg/utils/msg"
Expand All @@ -15,8 +16,9 @@ import (
)

type deleteCmdOptions struct {
indexName string
json bool
indexName string
skipConfirmation bool
json bool
}

// DeleteIndexService abstracts the Pinecone Go SDK for unit testing (runDeleteIndexCmd)
Expand All @@ -43,6 +45,13 @@ func NewDeleteCmd() *cobra.Command {
ctx := cmd.Context()
pc := sdk.NewPineconeClient(ctx)

if !options.skipConfirmation && !options.json {
confirm.Deletion(
fmt.Sprintf("This will delete index %s and all of its data.", style.Emphasis(options.indexName)),
"This action cannot be undone.",
)
}

err := runDeleteIndexCmd(ctx, pc, options)
if err != nil {
if strings.Contains(err.Error(), "not found") {
Expand All @@ -60,7 +69,8 @@ func NewDeleteCmd() *cobra.Command {
cmd.Flags().StringVarP(&options.indexName, "index-name", "i", "", "name of index to delete")
cmd.Flags().StringVarP(&options.indexName, "name", "n", "", "name of index to delete")
_ = cmd.Flags().MarkDeprecated("name", "use --index-name instead")
cmd.Flags().BoolVarP(&options.json, "json", "j", false, "Output result as JSON")
cmd.Flags().BoolVar(&options.skipConfirmation, "skip-confirmation", false, "Skip the deletion confirmation prompt")
cmd.Flags().BoolVarP(&options.json, "json", "j", false, "Output result as JSON (also skips confirmation prompt)")

return cmd
}
Expand Down
24 changes: 19 additions & 5 deletions internal/pkg/cli/command/index/namespace/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,21 @@ import (
"fmt"
"strings"

"github.com/pinecone-io/cli/internal/pkg/utils/confirm"
"github.com/pinecone-io/cli/internal/pkg/utils/exit"
"github.com/pinecone-io/cli/internal/pkg/utils/help"
"github.com/pinecone-io/cli/internal/pkg/utils/msg"
"github.com/pinecone-io/cli/internal/pkg/utils/sdk"
"github.com/pinecone-io/cli/internal/pkg/utils/style"
"github.com/pinecone-io/cli/internal/pkg/utils/text"
"github.com/spf13/cobra"
)

type deleteNamespaceCmdOptions struct {
indexName string
name string
json bool
indexName string
name string
skipConfirmation bool
json bool
}

func NewDeleteNamespaceCmd() *cobra.Command {
Expand All @@ -34,6 +37,9 @@ func NewDeleteNamespaceCmd() *cobra.Command {
Example: help.Examples(`
# delete a namespace from an index
pc index namespace delete --index-name "my-index" --name "tenant-a"

# delete the default namespace
pc index namespace delete --index-name "my-index" --name "__default__"
`),
Run: func(cmd *cobra.Command, args []string) {
ctx := cmd.Context()
Expand All @@ -50,6 +56,13 @@ func NewDeleteNamespaceCmd() *cobra.Command {
exit.Error(err, "Failed to delete namespace")
}

if !options.skipConfirmation && !options.json {
confirm.Deletion(
fmt.Sprintf("This will delete namespace %s from index %s and remove all of its data.", style.Emphasis(options.name), style.Emphasis(options.indexName)),
"This action cannot be undone.",
)
}

err = runDeleteNamespaceCmd(ctx, ic, options)
if err != nil {
msg.FailJSON(options.json, "Failed to delete namespace: %s", err)
Expand All @@ -59,10 +72,11 @@ func NewDeleteNamespaceCmd() *cobra.Command {
}

cmd.Flags().StringVarP(&options.indexName, "index-name", "i", "", "name of the index to delete the namespace from")
cmd.Flags().StringVar(&options.name, "name", "", "name of the namespace to delete")
cmd.Flags().StringVar(&options.name, "name", "", "name of the namespace to delete (use \"__default__\" for the default namespace)")
_ = cmd.MarkFlagRequired("index-name")
_ = cmd.MarkFlagRequired("name")
cmd.Flags().BoolVarP(&options.json, "json", "j", false, "Output result as JSON")
cmd.Flags().BoolVar(&options.skipConfirmation, "skip-confirmation", false, "Skip the deletion confirmation prompt")
cmd.Flags().BoolVarP(&options.json, "json", "j", false, "Output result as JSON (also skips confirmation prompt)")

return cmd
}
Expand Down
5 changes: 4 additions & 1 deletion internal/pkg/cli/command/index/namespace/describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ func NewDescribeNamespaceCmd() *cobra.Command {
# describe a namespace
pc index namespace describe --index-name "my-index" --name "tenant-a"

# describe the default namespace
pc index namespace describe --index-name "my-index" --name "__default__"

# describe a namespace and return JSON
pc index namespace describe --index-name "my-index" --name "tenant-a" --json
`),
Expand Down Expand Up @@ -61,7 +64,7 @@ func NewDescribeNamespaceCmd() *cobra.Command {
}

cmd.Flags().StringVarP(&options.indexName, "index-name", "i", "", "name of the index to describe the namespace from")
cmd.Flags().StringVar(&options.name, "name", "", "name of the namespace to describe")
cmd.Flags().StringVar(&options.name, "name", "", "name of the namespace to describe (use \"__default__\" for the default namespace)")
cmd.Flags().BoolVarP(&options.json, "json", "j", false, "output as JSON")
_ = cmd.MarkFlagRequired("index-name")
_ = cmd.MarkFlagRequired("name")
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/cli/command/index/restore/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func NewRestoreCmd() *cobra.Command {

cmd.Flags().StringVarP(&options.backupId, "id", "i", "", "ID of the backup to restore from")
cmd.Flags().StringVarP(&options.name, "name", "n", "", "Name of the index to create from the backup")
cmd.Flags().StringVarP(&options.deletionProtection, "deletion-protection", "d", "", "Whether to enable deletion protection on the new index (enabled|disabled)")
cmd.Flags().StringVar(&options.deletionProtection, "deletion-protection", "", "Whether to enable deletion protection on the new index (enabled|disabled)")
cmd.Flags().StringToStringVarP(&options.tags, "tags", "t", map[string]string{}, "Tags to apply to the new index")
cmd.Flags().BoolVarP(&options.json, "json", "j", false, "Output as JSON")
_ = cmd.MarkFlagRequired("id")
Expand Down
17 changes: 16 additions & 1 deletion internal/pkg/cli/command/index/vector/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ package vector

import (
"context"
"fmt"

"github.com/pinecone-io/cli/internal/pkg/utils/confirm"
"github.com/pinecone-io/cli/internal/pkg/utils/exit"
"github.com/pinecone-io/cli/internal/pkg/utils/flags"
"github.com/pinecone-io/cli/internal/pkg/utils/help"
"github.com/pinecone-io/cli/internal/pkg/utils/msg"
"github.com/pinecone-io/cli/internal/pkg/utils/sdk"
"github.com/pinecone-io/cli/internal/pkg/utils/style"
"github.com/pinecone-io/go-pinecone/v5/pinecone"
"github.com/spf13/cobra"
)
Expand All @@ -18,6 +21,7 @@ type deleteVectorsCmdOptions struct {
ids flags.StringList
filter flags.JSONObject
deleteAllVectors bool
skipConfirmation bool
json bool
}

Expand Down Expand Up @@ -48,7 +52,8 @@ func NewDeleteVectorsCmd() *cobra.Command {
cmd.Flags().Var(&options.ids, "ids", "IDs of the vectors to delete (inline JSON string array, ./path.json, or '-' for stdin)")
cmd.Flags().Var(&options.filter, "filter", "filter to delete the vectors with (inline JSON, ./path.json, or '-' for stdin)")
cmd.Flags().BoolVar(&options.deleteAllVectors, "all-vectors", false, "delete all vectors from the namespace")
cmd.Flags().BoolVarP(&options.json, "json", "j", false, "output as JSON")
cmd.Flags().BoolVar(&options.skipConfirmation, "skip-confirmation", false, "Skip the deletion confirmation prompt")
cmd.Flags().BoolVarP(&options.json, "json", "j", false, "output as JSON (also skips confirmation prompt)")

_ = cmd.MarkFlagRequired("index-name")

Expand All @@ -70,6 +75,16 @@ func runDeleteVectorsCmd(ctx context.Context, options deleteVectorsCmdOptions) {

// Delete all vectors in namespace
if options.deleteAllVectors {
if !options.skipConfirmation && !options.json {
target := "the default namespace"
if options.namespace != "" {
target = fmt.Sprintf("namespace %s", style.Emphasis(options.namespace))
}
confirm.Deletion(
fmt.Sprintf("This will delete ALL vectors in %s of index %s.", target, style.Emphasis(options.indexName)),
"This action cannot be undone.",
)
}
err = ic.DeleteAllVectorsInNamespace(ctx)
if err != nil {
msg.FailJSON(options.json, "Failed to delete all vectors in namespace: %s", err)
Expand Down
Loading
Loading