Skip to content

Commit a6dcd9c

Browse files
committed
Add initial command-line completion for service IDs
1 parent 0833c4b commit a6dcd9c

2 files changed

Lines changed: 69 additions & 12 deletions

File tree

internal/tiger/cmd/db.go

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,9 @@ func buildDbConnectionStringCmd() *cobra.Command {
5050
var dbConnectionStringWithPassword bool
5151

5252
cmd := &cobra.Command{
53-
Use: "connection-string [service-id]",
54-
Short: "Get connection string for a service",
53+
Use: "connection-string [service-id]",
54+
Short: "Get connection string for a service",
55+
ValidArgsFunction: serviceIDCompletion,
5556
Long: `Get a PostgreSQL connection string for connecting to a database service.
5657
5758
The service ID can be provided as an argument or will use the default service
@@ -117,9 +118,10 @@ func buildDbConnectCmd() *cobra.Command {
117118
var dbConnectRole string
118119

119120
cmd := &cobra.Command{
120-
Use: "connect [service-id]",
121-
Aliases: []string{"psql"},
122-
Short: "Connect to a database",
121+
Use: "connect [service-id]",
122+
Aliases: []string{"psql"},
123+
Short: "Connect to a database",
124+
ValidArgsFunction: serviceIDCompletion,
123125
Long: `Connect to a database service using psql client.
124126
125127
The service ID can be provided as an argument or will use the default service
@@ -196,8 +198,9 @@ func buildDbTestConnectionCmd() *cobra.Command {
196198
var dbTestConnectionRole string
197199

198200
cmd := &cobra.Command{
199-
Use: "test-connection [service-id]",
200-
Short: "Test database connectivity",
201+
Use: "test-connection [service-id]",
202+
Short: "Test database connectivity",
203+
ValidArgsFunction: serviceIDCompletion,
201204
Long: `Test database connectivity to a service.
202205
203206
The service ID can be provided as an argument or will use the default service
@@ -268,8 +271,9 @@ func buildDbSavePasswordCmd() *cobra.Command {
268271
var dbSavePasswordValue string
269272

270273
cmd := &cobra.Command{
271-
Use: "save-password [service-id]",
272-
Short: "Save password for a database service",
274+
Use: "save-password [service-id]",
275+
Short: "Save password for a database service",
276+
ValidArgsFunction: serviceIDCompletion,
273277
Long: `Save a password for a database service to configured password storage.
274278
275279
The service ID can be provided as an argument or will use the default service
@@ -574,8 +578,9 @@ func buildDbCreateRoleCmd() *cobra.Command {
574578
var output string
575579

576580
cmd := &cobra.Command{
577-
Use: "role [service-id]",
578-
Short: "Create a new database role",
581+
Use: "role [service-id]",
582+
Short: "Create a new database role",
583+
ValidArgsFunction: serviceIDCompletion,
579584
Long: `Create a new database role with optional read-only enforcement.
580585
581586
The service ID can be provided as an argument or will use the default service

internal/tiger/cmd/service.go

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ Examples:
7272
7373
# Get service details in YAML format
7474
tiger service get svc-12345 --output yaml`,
75+
ValidArgsFunction: serviceIDCompletion,
7576
RunE: func(cmd *cobra.Command, args []string) error {
7677
// Get config
7778
cfg, err := config.Load()
@@ -470,6 +471,7 @@ Examples:
470471
471472
# Update password without saving (using global flag)
472473
tiger service update-password svc-12345 --new-password new-secure-password --password-storage none`,
474+
ValidArgsFunction: serviceIDCompletion,
473475
RunE: func(cmd *cobra.Command, args []string) error {
474476
// Get config
475477
cfg, err := config.Load()
@@ -901,6 +903,7 @@ Examples:
901903
902904
# Delete service with custom wait timeout
903905
tiger service delete svc-12345 --wait-timeout 15m`,
906+
ValidArgsFunction: serviceIDCompletion,
904907
RunE: func(cmd *cobra.Command, args []string) error {
905908
// Require explicit service ID for safety
906909
if len(args) < 1 {
@@ -1092,7 +1095,8 @@ Examples:
10921095
10931096
# Fork with custom wait timeout
10941097
tiger service fork svc-12345 --now --wait-timeout 45m`,
1095-
Args: cobra.MaximumNArgs(1),
1098+
Args: cobra.MaximumNArgs(1),
1099+
ValidArgsFunction: serviceIDCompletion,
10961100
RunE: func(cmd *cobra.Command, args []string) error {
10971101
// Validate timing flags first - exactly one must be specified
10981102
timingFlagsSet := 0
@@ -1287,3 +1291,51 @@ Examples:
12871291

12881292
return cmd
12891293
}
1294+
func serviceIDCompletion(cmd *cobra.Command, _ []string, toComplete string) ([]string, cobra.ShellCompDirective) {
1295+
services, err := listServices(cmd)
1296+
if err != nil {
1297+
return nil, cobra.ShellCompDirectiveError
1298+
}
1299+
1300+
results := make([]string, 0, len(services))
1301+
for _, service := range services {
1302+
if service.ServiceId != nil && strings.HasPrefix(*service.ServiceId, toComplete) {
1303+
results = append(results, cobra.CompletionWithDesc(*service.ServiceId, *service.Name))
1304+
}
1305+
}
1306+
return results, cobra.ShellCompDirectiveNoFileComp
1307+
}
1308+
1309+
func listServices(cmd *cobra.Command) ([]api.Service, error) {
1310+
// Get API key and project ID for authentication
1311+
apiKey, projectID, err := getCredentialsForService()
1312+
if err != nil {
1313+
return nil, exitWithCode(ExitAuthenticationError, fmt.Errorf("authentication required: %w. Please run 'tiger auth login'", err))
1314+
}
1315+
1316+
// Create API client
1317+
client, err := api.NewTigerClient(apiKey)
1318+
if err != nil {
1319+
return nil, fmt.Errorf("failed to create API client: %w", err)
1320+
}
1321+
1322+
// Make API call to list services
1323+
ctx, cancel := context.WithTimeout(cmd.Context(), 30*time.Second)
1324+
defer cancel()
1325+
1326+
resp, err := client.GetProjectsProjectIdServicesWithResponse(ctx, projectID)
1327+
if err != nil {
1328+
return nil, fmt.Errorf("failed to list services: %w", err)
1329+
}
1330+
1331+
// Handle API response
1332+
if resp.StatusCode() != 200 {
1333+
return nil, exitWithErrorFromStatusCode(resp.StatusCode(), resp.JSON4XX)
1334+
}
1335+
1336+
if resp.JSON200 == nil || len(*resp.JSON200) == 0 {
1337+
return []api.Service{}, nil
1338+
}
1339+
1340+
return *resp.JSON200, nil
1341+
}

0 commit comments

Comments
 (0)