From 8eaa56ad3e196c55e1e9fbaf6502a6a55f090e9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=A3rebe=20-=20Romain=20GERARD?= Date: Tue, 21 Jan 2025 09:31:53 +0100 Subject: [PATCH] feat(debug): Add cluster debug-pod command --- cmd/cluster_debug_pod.go | 71 ++++++++++++++++++++++++++++++++++++++++ cmd/shell.go | 4 +-- pkg/shell.go | 20 +++++++---- 3 files changed, 87 insertions(+), 8 deletions(-) create mode 100644 cmd/cluster_debug_pod.go diff --git a/cmd/cluster_debug_pod.go b/cmd/cluster_debug_pod.go new file mode 100644 index 00000000..9991b09c --- /dev/null +++ b/cmd/cluster_debug_pod.go @@ -0,0 +1,71 @@ +package cmd + +import ( + "github.com/qovery/qovery-cli/pkg" + "github.com/qovery/qovery-cli/pkg/usercontext" + "github.com/qovery/qovery-cli/utils" + "github.com/spf13/cobra" + "os" +) + +var clusterDebugPodCmd = &cobra.Command{ + Use: "debug-pod", + Short: "Launch a debug pod and attach to it", + Run: func(cmd *cobra.Command, args []string) { + utils.Capture(cmd) + + tokenType, token, err := utils.GetAccessToken() + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + client := utils.GetQoveryClient(tokenType, token) + organizationId, err := usercontext.GetOrganizationContextResourceId(client, organizationName) + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + flavor := "REGULAR_PRIVILEGE" + if fullPriviledge { + flavor = "FULL_PRIVILEGE" + } + request := DebugPodRequest{ + utils.Id(organizationId), + utils.Id(clusterId), + 0, + 0, + flavor, + nodeSelector, + } + + pkg.ExecShell(&request, "/shell/debug") + }, +} + +type DebugPodRequest struct { + OrganizationID utils.Id `url:"organization"` + ClusterID utils.Id `url:"cluster"` + TtyWidth uint16 `url:"tty_width"` + TtyHeight uint16 `url:"tty_height"` + Flavor string `url:"flavor"` + NodeSelector string `url:"node_selector,omitempty"` +} + +func (s *DebugPodRequest) SetTtySize(width uint16, height uint16) { + s.TtyWidth = width + s.TtyHeight = height +} + +var fullPriviledge bool +var nodeSelector string + +func init() { + clusterCmd.AddCommand(clusterDebugPodCmd) + clusterDebugPodCmd.Flags().StringVarP(&clusterId, "cluster-id", "c", "", "Cluster ID") + clusterDebugPodCmd.Flags().StringVarP(&nodeSelector, "node-selector", "n", "", "Specify a node selector for the debug pod to be started on") + clusterDebugPodCmd.Flags().BoolVarP(&fullPriviledge, "full-privilege", "p", false, "Start a full privileged debug pod which has access to host machine. ") +} diff --git a/cmd/shell.go b/cmd/shell.go index 8ea920d0..da227d15 100644 --- a/cmd/shell.go +++ b/cmd/shell.go @@ -11,8 +11,8 @@ import ( "golang.org/x/net/context" "github.com/qovery/qovery-cli/pkg" - "github.com/qovery/qovery-cli/utils" "github.com/qovery/qovery-cli/pkg/usercontext" + "github.com/qovery/qovery-cli/utils" ) var shellCmd = &cobra.Command{ @@ -52,7 +52,7 @@ var shellCmd = &cobra.Command{ return } - pkg.ExecShell(shellRequest) + pkg.ExecShell(shellRequest, "/shell/exec") }, } diff --git a/pkg/shell.go b/pkg/shell.go index 0fc08d7b..f3a76fba 100644 --- a/pkg/shell.go +++ b/pkg/shell.go @@ -16,6 +16,10 @@ import ( const StdinBufferSize = 4096 +type TerminalSize interface { + SetTtySize(width uint16, height uint16) +} + type ShellRequest struct { ServiceID utils.Id `url:"service"` EnvironmentID utils.Id `url:"environment"` @@ -29,7 +33,12 @@ type ShellRequest struct { TtyHeight uint16 `url:"tty_height"` } -func ExecShell(req *ShellRequest) { +func (s *ShellRequest) SetTtySize(width uint16, height uint16) { + s.TtyWidth = width + s.TtyHeight = height +} + +func ExecShell(req TerminalSize, path string) { currentConsole := console.Current() defer func() { _ = currentConsole.Reset() @@ -39,10 +48,9 @@ func ExecShell(req *ShellRequest) { if err != nil { log.Fatal("Cannot get terminal size", err) } - req.TtyWidth = winSize.Width - req.TtyHeight = winSize.Height + req.SetTtySize(winSize.Width, winSize.Height) - wsConn, err := createWebsocketConn(req) + wsConn, err := createWebsocketConn(req, path) if err != nil { log.Fatal("error while creating websocket connection", err) } @@ -75,13 +83,13 @@ func ExecShell(req *ShellRequest) { } } -func createWebsocketConn(req *ShellRequest) (*websocket.Conn, error) { +func createWebsocketConn(req interface{}, path string) (*websocket.Conn, error) { command, err := query.Values(req) if err != nil { return nil, err } - wsURL, err := url.Parse(fmt.Sprintf("%s/shell/exec", utils.WebsocketUrl())) + wsURL, err := url.Parse(fmt.Sprintf("%s%s", utils.WebsocketUrl(), path)) if err != nil { return nil, err }