diff --git a/cmd/port-forward.go b/cmd/port-forward.go index edf06126..44ade4dd 100644 --- a/cmd/port-forward.go +++ b/cmd/port-forward.go @@ -303,7 +303,7 @@ func portForwardRequestWithApplicationUrl(args []string) (*pkg.PortForwardReques func init() { var portForwardCmd = portForwardCmd portForwardCmd.Flags().StringVarP(&podName, "pod", "", "", "pod name where to forward traffic") - portForwardCmd.Flags().StringSliceVarP(&ports, "port", "p", nil, "port that will be forwarded. Format \"local_port:remote_port\" i.e: 8080:80") + portForwardCmd.Flags().StringSliceVarP(&ports, "port", "p", nil, "port that will be forwarded. Can be specified multiple time. Format \"local_port:remote_port\" i.e: 8080:80") _ = portForwardCmd.MarkFlagRequired("port") rootCmd.AddCommand(portForwardCmd) diff --git a/cmd/service_list_pods.go b/cmd/service_list_pods.go new file mode 100644 index 00000000..81bd4428 --- /dev/null +++ b/cmd/service_list_pods.go @@ -0,0 +1,50 @@ +package cmd + +import ( + "github.com/qovery/qovery-cli/pkg" + "github.com/qovery/qovery-cli/utils" + "github.com/spf13/cobra" + "strconv" + "strings" +) + +var serviceListPods = &cobra.Command{ + Use: "list-pods", + Short: "List the pods of a service with their pods", + Run: func(cmd *cobra.Command, args []string) { + utils.Capture(cmd) + + var portForwardRequest *pkg.PortForwardRequest + var err error + if len(args) > 0 { + portForwardRequest, err = portForwardRequestWithApplicationUrl(args) + } else { + portForwardRequest, err = portForwardRequestWithoutArg() + } + if err != nil { + utils.PrintlnError(err) + return + } + + pods, err := pkg.ExecListPods(portForwardRequest) + if err != nil { + utils.PrintlnError(err) + return + } + + var data [][]string + for _, pod := range pods.Pods { + ports := make([]string, len(pod.Ports)) + for i, x := range pod.Ports { + ports[i] = strconv.FormatUint(uint64(x), 10) + } + data = append(data, []string{pod.Name, strings.Join(ports, ", ")}) + } + _ = utils.PrintTable([]string{"Pod Name", "Ports"}, data) + }, +} + +func init() { + var serviceListPodsCmd = serviceListPods + rootCmd.AddCommand(serviceListPodsCmd) +} diff --git a/pkg/service_list_pods.go b/pkg/service_list_pods.go new file mode 100644 index 00000000..a3054198 --- /dev/null +++ b/pkg/service_list_pods.go @@ -0,0 +1,65 @@ +package pkg + +import ( + "encoding/json" + "errors" + "github.com/appscode/go-querystring/query" + "github.com/gorilla/websocket" + "github.com/qovery/qovery-cli/utils" + "net/http" + "net/url" + "regexp" +) + +type PodResponse struct { + Name string + Ports []uint16 +} +type ListPodResponse struct { + Pods []PodResponse +} + +func ExecListPods(req *PortForwardRequest) (*ListPodResponse, error) { + command, err := query.Values(req) + if err != nil { + return nil, err + } + + wsURL, err := url.Parse("wss://ws.qovery.com/service/pods") + if err != nil { + return nil, err + } + pattern := regexp.MustCompile("%5B([0-9]+)%5D=") + wsURL.RawQuery = pattern.ReplaceAllString(command.Encode(), "[${1}]=") + + tokenType, token, err := utils.GetAccessToken() + if err != nil { + return nil, err + } + + headers := http.Header{"Authorization": {utils.GetAuthorizationHeaderValue(tokenType, token)}} + wsConn, _, err := websocket.DefaultDialer.Dial(wsURL.String(), headers) + if err != nil { + return nil, err + } + defer func() { + _ = wsConn.Close() + }() + + msgType, payload, err := wsConn.ReadMessage() + if err != nil { + return nil, err + } + + switch msgType { + case websocket.TextMessage: + var data ListPodResponse + err = json.Unmarshal(payload, &data) + if err != nil { + return nil, err + } + return &data, nil + default: + return nil, errors.New("received invalid message while listing pods: " + string(rune(msgType)) + " " + string(payload)) + } +}