diff --git a/cmd/root.go b/cmd/root.go index 8210f27..2aabd77 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -511,14 +511,16 @@ func createServiceCommand(serviceName string) *cobra.Command { sortBy := "" columns := "" - limit := 0 - pageSize := 100 // 기본 페이지 크기 + rows := 0 + pageSize := 100 + noPaging := false if verb == "list" { sortBy, _ = cmd.Flags().GetString("sort") columns, _ = cmd.Flags().GetString("columns") - limit, _ = cmd.Flags().GetInt("limit") - pageSize, _ = cmd.Flags().GetInt("page-size") + rows, _ = cmd.Flags().GetInt("rows") + pageSize, _ = cmd.Flags().GetInt("rows-per-page") + noPaging, _ = cmd.Flags().GetBool("no-paging") } options := &transport.FetchOptions{ @@ -531,8 +533,9 @@ func createServiceCommand(serviceName string) *cobra.Command { SortBy: sortBy, MinimalColumns: verb == "list" && cmd.Flag("minimal") != nil && cmd.Flag("minimal").Changed, Columns: columns, - Limit: limit, + Rows: rows, PageSize: pageSize, + NoPaging: noPaging, } if verb == "list" && !cmd.Flags().Changed("output") { @@ -561,8 +564,9 @@ func createServiceCommand(serviceName string) *cobra.Command { cmd.Flags().StringP("sort", "s", "", "Sort by field (e.g. 'name', 'created_at')") cmd.Flags().BoolP("minimal", "m", false, "Show minimal columns") cmd.Flags().StringP("columns", "c", "", "Specific columns (-c id,name)") - cmd.Flags().IntP("limit", "l", 0, "Number of rows") - cmd.Flags().IntP("page-size", "n", 15, "Number of items per page") + cmd.Flags().IntP("rows", "r", 0, "Number of rows") + cmd.Flags().IntP("rows-per-page", "n", 15, "Number of rows per page") + cmd.Flags().BoolP("no-paging", "", false, "Disable pagination and show all results") // Add existing flags cmd.Flags().StringArrayP("parameter", "p", []string{}, "Input Parameter (-p = -p ...)") diff --git a/pkg/configs/alias.go b/pkg/configs/alias.go index 17f9703..bee5dbe 100644 --- a/pkg/configs/alias.go +++ b/pkg/configs/alias.go @@ -95,22 +95,45 @@ func RemoveAlias(service, key string) error { return fmt.Errorf("alias '%s' not found in service '%s'", key, service) } + // Delete the specific alias delete(serviceAliases, key) + + // If service has no more aliases, remove the service if len(serviceAliases) == 0 { delete(aliases, service) } else { aliases[service] = serviceAliases } - config["aliases"] = aliases + // Only remove aliases section if there are no services left + if len(aliases) == 0 { + delete(config, "aliases") + newData, err := yaml.Marshal(config) + if err != nil { + return fmt.Errorf("failed to encode config: %v", err) + } + if err := os.WriteFile(settingPath, newData, 0644); err != nil { + return fmt.Errorf("failed to write config: %v", err) + } + } else { + // Keep aliases and write at the end + delete(config, "aliases") + newData, err := yaml.Marshal(config) + if err != nil { + return fmt.Errorf("failed to encode config: %v", err) + } - newData, err := yaml.Marshal(config) - if err != nil { - return fmt.Errorf("failed to encode config: %v", err) - } + aliasData, err := yaml.Marshal(map[string]interface{}{ + "aliases": aliases, + }) + if err != nil { + return fmt.Errorf("failed to encode aliases: %v", err) + } - if err := os.WriteFile(settingPath, newData, 0644); err != nil { - return fmt.Errorf("failed to write config: %v", err) + finalData := append(newData, aliasData...) + if err := os.WriteFile(settingPath, finalData, 0644); err != nil { + return fmt.Errorf("failed to write config: %v", err) + } } return nil diff --git a/pkg/configs/endpoint.go b/pkg/configs/endpoint.go index d65c960..704fddd 100644 --- a/pkg/configs/endpoint.go +++ b/pkg/configs/endpoint.go @@ -22,7 +22,7 @@ import ( // GetAPIEndpoint fetches the actual API endpoint from the config endpoint func GetAPIEndpoint(endpoint string) (string, error) { // Handle gRPC+SSL protocol - if strings.HasPrefix(endpoint, "grpc+ssl://") { + if strings.HasPrefix(endpoint, "grpc+ssl://") || strings.HasPrefix(endpoint, "grpc://") { // For gRPC+SSL endpoints, return as is since it's already in the correct format return endpoint, nil } @@ -66,7 +66,7 @@ func GetAPIEndpoint(endpoint string) (string, error) { // GetIdentityEndpoint fetches the identity service endpoint from the API endpoint func GetIdentityEndpoint(apiEndpoint string) (string, bool, error) { // If the endpoint is already gRPC+SSL - if strings.HasPrefix(apiEndpoint, "grpc+ssl://") { + if strings.HasPrefix(apiEndpoint, "grpc+ssl://") || strings.HasPrefix(apiEndpoint, "grpc://") { // Check if it contains 'identity' containsIdentity := strings.Contains(apiEndpoint, "identity") diff --git a/pkg/transport/service.go b/pkg/transport/service.go index 6f6c467..d7c8d47 100644 --- a/pkg/transport/service.go +++ b/pkg/transport/service.go @@ -38,7 +38,6 @@ type Environment struct { Endpoint string `yaml:"endpoint"` Proxy string `yaml:"proxy"` Token string `yaml:"token"` - URL string `yaml:"url"` } type Config struct { @@ -58,9 +57,10 @@ type FetchOptions struct { SortBy string MinimalColumns bool Columns string - Limit int + Rows int Page int PageSize int + NoPaging bool } // FetchService handles the execution of gRPC commands for all services @@ -205,12 +205,16 @@ func FetchService(serviceName string, verb string, resourceName string, options } domainParts := strings.Split(urlParts[1], ".") - if len(domainParts) < 4 { - return nil, fmt.Errorf("invalid domain format in API endpoint: %s", apiEndpoint) - } + if len(domainParts) > 0 { + port := extractPortFromParts(domainParts) + if strings.Contains(domainParts[len(domainParts)-1], ":") { + parts := strings.Split(domainParts[len(domainParts)-1], ":") + domainParts[len(domainParts)-1] = parts[0] + } - domainParts[0] = format.ConvertServiceName(serviceName) - hostPort = strings.Join(domainParts, ".") + ":443" + domainParts[0] = format.ConvertServiceName(serviceName) + hostPort = strings.Join(domainParts, ".") + port + } } else { trimmedEndpoint := strings.TrimPrefix(identityEndpoint, "grpc+ssl://") parts := strings.Split(trimmedEndpoint, ".") @@ -349,11 +353,10 @@ func FetchService(serviceName string, verb string, resourceName string, options } } - // Apply limit if specified - if options.Limit > 0 && verb == "list" { + if options.Rows > 0 && verb == "list" { if results, ok := respMap["results"].([]interface{}); ok { - if len(results) > options.Limit { - respMap["results"] = results[:options.Limit] + if len(results) > options.Rows { + respMap["results"] = results[:options.Rows] } } } @@ -397,6 +400,22 @@ func extractParameterName(errMsg string) string { return "" } +func extractPortFromParts(parts []string) string { + if len(parts) == 0 { + return ":443" + } + + lastPart := parts[len(parts)-1] + if strings.Contains(lastPart, ":") { + portParts := strings.Split(lastPart, ":") + if len(portParts) == 2 { + return ":" + portParts[1] + } + } + + return ":443" +} + // promptForParameter prompts the user to enter a value for the given parameter func promptForParameter(paramName string) (string, error) { prompt := fmt.Sprintf("Please enter value for '%s'", paramName) @@ -431,7 +450,7 @@ func loadConfig() (*Config, error) { envConfig := &Environment{ Endpoint: mainV.GetString(fmt.Sprintf("environments.%s.endpoint", currentEnv)), Proxy: mainV.GetString(fmt.Sprintf("environments.%s.proxy", currentEnv)), - URL: mainV.GetString(fmt.Sprintf("environments.%s.url", currentEnv)), + Token: mainV.GetString(fmt.Sprintf("environments.%s.token", currentEnv)), } // Handle token based on environment type @@ -510,12 +529,16 @@ func fetchJSONResponse(config *Config, serviceName string, verb string, resource } domainParts := strings.Split(urlParts[1], ".") - if len(domainParts) < 4 { - return nil, fmt.Errorf("invalid domain format in API endpoint: %s", apiEndpoint) - } + if len(domainParts) > 0 { + port := extractPortFromParts(domainParts) + if strings.Contains(domainParts[len(domainParts)-1], ":") { + parts := strings.Split(domainParts[len(domainParts)-1], ":") + domainParts[len(domainParts)-1] = parts[0] + } - domainParts[0] = format.ConvertServiceName(serviceName) - hostPort = strings.Join(domainParts, ".") + ":443" + domainParts[0] = format.ConvertServiceName(serviceName) + hostPort = strings.Join(domainParts, ".") + port + } } } else { trimmedEndpoint := strings.TrimPrefix(identityEndpoint, "grpc+ssl://") @@ -985,9 +1008,14 @@ func getMinimalFields(serviceName, resourceName string, refClient *grpcreflect.C func printTable(data map[string]interface{}, options *FetchOptions, serviceName, verbName, resourceName string, refClient *grpcreflect.Client) string { if results, ok := data["results"].([]interface{}); ok { - // Set default page size if not specified - if options.PageSize == 0 { - options.PageSize = 10 + // Set default page size if not specified and paging is enabled + if !options.NoPaging { + if options.PageSize == 0 { + options.PageSize = 15 + } + } else { + // Show all results when no-paging is true + options.PageSize = len(results) } // Initialize keyboard