feat(webconsole,apigateway): display info for container exec (#20403)

This commit is contained in:
Zexi Li
2024-05-30 15:16:06 +08:00
committed by GitHub
parent a6a1c410e3
commit 618c1a059a
4 changed files with 83 additions and 4 deletions
+7
View File
@@ -20,10 +20,17 @@ type SK8sRequest struct {
Container string `json:"container"`
}
type SK8sShellDisplayInfo struct {
InstanceName string `json:"instanceName"`
IPs []string `json:"ips,omitempty"`
}
type SK8sShellRequest struct {
SK8sRequest
Command string `json:"command"`
Args []string `json:"args"`
Env map[string]string `json:"env"`
DisplayInfo *SK8sShellDisplayInfo `json:"display_info"`
}
@@ -16,15 +16,18 @@ package webconsole
import (
"fmt"
"strings"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
compute_api "yunion.io/x/onecloud/pkg/apis/compute"
webconsole_api "yunion.io/x/onecloud/pkg/apis/webconsole"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
"yunion.io/x/onecloud/pkg/mcclient/modules/compute"
"yunion.io/x/onecloud/pkg/mcclient/modules/k8s"
)
@@ -81,14 +84,40 @@ func (m WebConsoleManager) DoContainerExec(s *mcclient.ClientSession, data jsonu
if containerId == "" {
return nil, httperrors.NewNotEmptyError("container_id")
}
return m.doCloudShell(s, "/opt/yunion/bin/climc", "container-exec", containerId, "sh")
obj, err := compute.Containers.Get(s, containerId, nil)
if err != nil {
return nil, errors.Wrapf(err, "get container by %s", containerId)
}
containerName, _ := obj.GetString("name")
serverId, _ := obj.GetString("guest_id")
if serverId == "" {
return nil, httperrors.NewNotFoundError("not found guest_id from container %s", obj)
}
serverObj, err := compute.Servers.Get(s, serverId, nil)
if err != nil {
return nil, errors.Wrapf(err, "get server by %s", serverId)
}
serverDetails := &compute_api.ServerDetails{}
if err := serverObj.Unmarshal(serverDetails); err != nil {
return nil, errors.Wrapf(err, "unmarshal server details: %s", serverObj)
}
info := &webconsole_api.SK8sShellDisplayInfo{
InstanceName: containerName,
IPs: strings.Split(serverDetails.IPs, ","),
}
return m.doCloudShell(s, info, "/opt/yunion/bin/climc", "container-exec", containerId, "sh")
}
type CloudShellRequest struct {
InstanceName string `json:"instance_name"`
IPs []string `json:"ips"`
}
func (m WebConsoleManager) DoCloudShell(s *mcclient.ClientSession, _ jsonutils.JSONObject) (jsonutils.JSONObject, error) {
return m.doCloudShell(s, "/bin/bash")
return m.doCloudShell(s, nil, "/bin/bash")
}
func (m WebConsoleManager) doCloudShell(s *mcclient.ClientSession, cmd string, args ...string) (jsonutils.JSONObject, error) {
func (m WebConsoleManager) doCloudShell(s *mcclient.ClientSession, info *webconsole_api.SK8sShellDisplayInfo, cmd string, args ...string) (jsonutils.JSONObject, error) {
adminSession := auth.GetAdminSession(s.GetContext(), s.GetRegion())
query := jsonutils.NewDict()
@@ -154,6 +183,7 @@ func (m WebConsoleManager) doCloudShell(s *mcclient.ClientSession, cmd string, a
"OS_SECRET_KEY": "",
"OS_TRY_TERM_WIDTH": "false",
}
req.DisplayInfo = info
return m.DoK8sConnect(s, podName, "shell", jsonutils.Marshal(req))
}
+25 -1
View File
@@ -41,6 +41,9 @@ type K8sEnv struct {
type Kubectl struct {
*BaseCommand
kubeconfig string
// For display info
InstanceName string
IPs []string
}
func NewKubectlCommand(s *mcclient.ClientSession, kubeconfig, namespace string) *Kubectl {
@@ -55,6 +58,22 @@ func NewKubectlCommand(s *mcclient.ClientSession, kubeconfig, namespace string)
}
}
func (c *Kubectl) SetInstanceName(name string) {
c.InstanceName = name
}
func (c *Kubectl) GetInstanceName() string {
return c.InstanceName
}
func (c *Kubectl) SetIPs(ips []string) {
c.IPs = ips
}
func (c *Kubectl) GetIPs() []string {
return c.IPs
}
func (c *Kubectl) GetCommand() *exec.Cmd {
cmd := c.BaseCommand.GetCommand()
cmd.Env = append(cmd.Env, fmt.Sprintf("KUBECONFIG=%s", c.kubeconfig))
@@ -135,12 +154,17 @@ func NewPodBashCommand(env *K8sEnv) ICommand {
}
args = append(args, shellRequest.Args...)
return NewKubectlCommand(env.Session, env.Kubeconfig, env.Namespace).Exec().
kExec := NewKubectlCommand(env.Session, env.Kubeconfig, env.Namespace).Exec().
Stdin().
TTY().
Pod(env.Pod).
Container(env.Container).
Command(shellRequest.Command, args...)
if shellRequest.DisplayInfo != nil {
kExec.SetInstanceName(shellRequest.DisplayInfo.InstanceName)
kExec.SetIPs(shellRequest.DisplayInfo.IPs)
}
return kExec
}
type KubectlLog struct {
+18
View File
@@ -106,6 +106,13 @@ type ISessionData interface {
GetDisplayInfo(ctx context.Context) (*SDisplayInfo, error)
}
type ISessionCommand interface {
command.ICommand
GetInstanceName() string
GetIPs() []string
}
type RandomSessionData struct {
command.ICommand
id string
@@ -134,6 +141,17 @@ func (s *RandomSessionData) GetDisplayInfo(ctx context.Context) (*SDisplayInfo,
dispInfo := SDisplayInfo{}
dispInfo.WaterMark = fetchWaterMark(userInfo)
dispInfo.InstanceName = s.GetCommand().String()
si, ok := s.ICommand.(ISessionCommand)
if ok {
iName := si.GetInstanceName()
if iName != "" {
dispInfo.InstanceName = iName
}
ips := si.GetIPs()
if len(ips) > 0 {
dispInfo.Ips = strings.Join(ips, ",")
}
}
return &dispInfo, nil
}