Skip to content

Commit

Permalink
feat: get terminal params from args (#6428)
Browse files Browse the repository at this point in the history
* feat: get termial params from args

* feat: more sync watch logs

* feat: more sync watch logs

* polish: remove useless code

* feat: remove useless code

* polish: optimize log

Signed-off-by: CeerDecy <[email protected]>

* polish: use apistructs const

Signed-off-by: CeerDecy <[email protected]>

* polish: use httputil consts

Signed-off-by: CeerDecy <[email protected]>

---------

Signed-off-by: CeerDecy <[email protected]>
  • Loading branch information
CeerDecy authored Sep 12, 2024
1 parent 08013ed commit 0034b27
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 71 deletions.
13 changes: 11 additions & 2 deletions internal/tools/orchestrator/endpoints/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,9 +315,18 @@ func (e *Endpoints) getPodStatusFromK8s(runtimeID, serviceName string) ([]apistr
continue
}

// TODO change `DICE_CLUSTER_NAME` to `core.erda.cloud/cluster-name`
clusterName := ""
if _, ok := pod.Labels["DICE_CLUSTER_NAME"]; ok {
clusterName = pod.Labels["DICE_CLUSTER_NAME"]
for _, container := range pod.Spec.Containers {
if clusterName != "" {
break
}
for _, env := range container.Env {
if env.Name == apistructs.DICE_CLUSTER_NAME.String() {
clusterName = env.Value
break
}
}
}
message := PodDefaultMessage
if pod.Status.Message != "" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ func updatePodAndInstance(dbclient *instanceinfo.Client, podlist *corev1.PodList
mainContainer := getMainContainerStatus(pod.Status.ContainerStatuses, container.Name)
terminatedContainer := mainContainer.LastTerminationState.Terminated
if terminatedContainer != nil {
logrus.Infof("get [prevContainerID] from terminatedContainer")
if len(strings.Split(terminatedContainer.ContainerID, "://")) == 2 {
runtimeAndId := strings.Split(terminatedContainer.ContainerID, "://")
prevContainerID = runtimeAndId[1]
Expand All @@ -475,6 +476,7 @@ func updatePodAndInstance(dbclient *instanceinfo.Client, podlist *corev1.PodList
}
currentContainer := mainContainer.State.Running
if currentContainer != nil {
logrus.Infof("get [currentContainerID] from currentContainer")
if len(strings.Split(mainContainer.ContainerID, "://")) == 2 {
runtimeAndId := strings.Split(mainContainer.ContainerID, "://")
currentContainerID = runtimeAndId[1]
Expand All @@ -498,6 +500,7 @@ func updatePodAndInstance(dbclient *instanceinfo.Client, podlist *corev1.PodList
}
}
} else {
logrus.Infof("get [currentContainerID] from mainContainer")
currentTerminatedContainer := mainContainer.State.Terminated
if currentTerminatedContainer != nil {
if len(strings.Split(mainContainer.ContainerID, "://")) == 2 {
Expand Down Expand Up @@ -609,7 +612,10 @@ func updatePodAndInstance(dbclient *instanceinfo.Client, podlist *corev1.PodList
return orgs, err
}
}
logrus.Infof("latest instance id %v , others cleared by [prevContainerID]", instances[0].ID)
}
} else {
logrus.Infof("[prevContainerID] is empty, skip create or update")
}
if currentContainerID != "" {
instances, err := r.ByContainerID(currentContainerID).ByRuntimeID(runtimeID).ByApplicationID(applicationID).Do()
Expand Down Expand Up @@ -683,7 +689,10 @@ func updatePodAndInstance(dbclient *instanceinfo.Client, podlist *corev1.PodList
return orgs, err
}
}
logrus.Infof("latest instance id %v, others cleared by [currentContainerID]", instances[0].ID)
}
} else {
logrus.Infof("[currentContainerID] is empty, skip create or update")
}
}
return orgs, nil
Expand Down
162 changes: 93 additions & 69 deletions internal/tools/orchestrator/scheduler/impl/terminal/terminal.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,19 @@ var upgrader = websocket.Upgrader{
},
}

type ContainerInfo struct {
type PodInfo struct {
Env []string `json:"env"`
Name string `json:"name"`
Args json.RawMessage `json:"args"`
}

type ContainerInfoArg struct {
Host string `json:"host"`
Port int `json:"port"`
Container string `json:"container"`
type PodInfoArg struct {
Host string `json:"host"`
Port int `json:"port"`
ContainerId string `json:"container"`
PodName string `json:"podName,omitempty"`
Namespace string `json:"namespace,omitempty"`
ContainerName string `json:"containerName,omitempty"`
}

type Auditor struct {
Expand Down Expand Up @@ -116,7 +119,7 @@ func Terminal(clusterSvc clusterpb.ClusterServiceServer, w http.ResponseWriter,
if t != websocket.TextMessage {
return
}
containerinfo := ContainerInfo{}
containerinfo := PodInfo{}
if err := json.Unmarshal(message, &containerinfo); err != nil {
logrus.Errorf("failed to unmarshal containerinfo: %v, content: %s", err, string(message))
return
Expand All @@ -126,90 +129,111 @@ func Terminal(clusterSvc clusterpb.ClusterServiceServer, w http.ResponseWriter,
SoldierTerminal(clusterSvc, r, message, conn)
return
}
var args ContainerInfoArg
var args PodInfoArg
if err := json.Unmarshal(containerinfo.Args, &args); err != nil {
logrus.Errorf("failed to unmarshal containerinfoArgs: %v", err)
return
}

// 2. Query the containerid in the instance list
instances, err := instanceinfo.New(dbengine.MustOpen()).InstanceReader().ByContainerID(args.Container).Do()
if err != nil {
logrus.Errorf("failed to get instance by containerid: %v", err)
return
}
var (
k8snamespace string
k8spodname string
k8scontainername string
clustername string
orgID int
)

if len(instances) == 0 {
logrus.Errorf("no instances found: containerid: %v", args.Container)
return
}
if len(instances) > 1 {
logrus.Errorf("more than one instance found: containerid: %v", args.Container)
return
}
instance := instances[0]
clustername = r.URL.Query().Get("clusterName")

// 3. Check permissions
access := false
if instance.OrgID != "" {
orgid, err := strconv.ParseUint(instance.OrgID, 10, 64)
if args.PodName != "" && args.Namespace != "" && args.ContainerName != "" {
logrus.Infof("get termial connect param from args")
orgID, _ = strconv.Atoi(r.Header.Get(httputil.OrgHeader))
k8snamespace = args.Namespace
k8scontainername = args.ContainerName
k8spodname = args.PodName
} else {
logrus.Infof("get termial connect param from database")
// 2. Query the containerid in the instance list
instances, err := instanceinfo.New(dbengine.MustOpen()).InstanceReader().ByContainerID(args.ContainerId).Do()
if err != nil {
logrus.Errorf("failed to parse orgid for instance: %v, %v", instance.ContainerID, err)
logrus.Errorf("failed to get instance by containerid: %v", err)
return
}
p, err := bundle.New(bundle.WithErdaServer()).CheckPermission(&apistructs.PermissionCheckRequest{
UserID: r.Header.Get("User-ID"),
Scope: apistructs.OrgScope,
ScopeID: orgid,
Resource: "terminal",
Action: "OPERATE",
})
if err != nil {
logrus.Errorf("failed to check permissions for terminal: %v", err)

if len(instances) == 0 {
logrus.Errorf("no instances found: containerid: %v", args.ContainerId)
return
}
if p.Access {
access = true
}
}
if !access && instance.ApplicationID != "" {
appid, err := strconv.ParseUint(instance.ApplicationID, 10, 64)
if err != nil {
logrus.Errorf("failed to parse applicationid for instance: %v, %v", instance.ContainerID, err)
if len(instances) > 1 {
logrus.Errorf("more than one instance found: containerid: %v", args.ContainerId)
return
}
p, err := bundle.New(bundle.WithErdaServer()).CheckPermission(&apistructs.PermissionCheckRequest{
UserID: r.Header.Get("User-ID"),
Scope: apistructs.AppScope,
ScopeID: appid,
Resource: "terminal",
Action: "OPERATE",
})
if err != nil {
logrus.Errorf("failed to check permissions for terminal: %v", err)
return
instance := instances[0]

// 3. Check permissions
access := false
if instance.OrgID != "" {
orgid, err := strconv.ParseUint(instance.OrgID, 10, 64)
if err != nil {
logrus.Errorf("failed to parse orgid for instance: %v, %v", instance.ContainerID, err)
return
}
p, err := bundle.New(bundle.WithErdaServer()).CheckPermission(&apistructs.PermissionCheckRequest{
UserID: r.Header.Get(httputil.UserHeader),
Scope: apistructs.OrgScope,
ScopeID: orgid,
Resource: "terminal",
Action: "OPERATE",
})
if err != nil {
logrus.Errorf("failed to check permissions for terminal: %v", err)
return
}
if p.Access {
access = true
}
}
if !p.Access {
logrus.Errorf("permission denied for terminal, userid: %v, appid: %d", r.Header.Get("User-ID"), appid)
return
if !access && instance.ApplicationID != "" {
appid, err := strconv.ParseUint(instance.ApplicationID, 10, 64)
if err != nil {
logrus.Errorf("failed to parse applicationid for instance: %v, %v", instance.ContainerID, err)
return
}
p, err := bundle.New(bundle.WithErdaServer()).CheckPermission(&apistructs.PermissionCheckRequest{
UserID: r.Header.Get(httputil.UserHeader),
Scope: apistructs.AppScope,
ScopeID: appid,
Resource: "terminal",
Action: "OPERATE",
})
if err != nil {
logrus.Errorf("failed to check permissions for terminal: %v", err)
return
}
if !p.Access {
logrus.Errorf("permission denied for terminal, userid: %v, appid: %d", r.Header.Get("User-ID"), appid)
return
}
}
}

// 4. Determine whether it is a dcos path
k8snamespace, ok1 := instance.Metadata("k8snamespace")
k8spodname, ok2 := instance.Metadata("k8spodname")
k8scontainername, ok3 := instance.Metadata("k8scontainername")
clustername := instance.Cluster
// 4. Determine whether it is a dcos path
k8sNamespace, ok1 := instance.Metadata("k8snamespace")
k8sPodName, ok2 := instance.Metadata("k8spodname")
k8sContainerName, ok3 := instance.Metadata("k8scontainername")

if !ok1 || !ok2 || !ok3 {
// If there is no corresponding namespace, name, containername in the meta, it is considered to be the dcos path, and the original soldier is taken
logrus.Errorf("get terminial info failed, namespace %v, pod name %v, container name %v", ok1, ok2, ok3)
return
if !ok1 || !ok2 || !ok3 {
// If there is no corresponding namespace, name, containername in the meta, it is considered to be the dcos path, and the original soldier is taken
logrus.Errorf("get terminial info failed, namespace %v, pod name %v, container name %v", ok1, ok2, ok3)
return
}
orgID, _ = strconv.Atoi(instance.OrgID)
k8snamespace = k8sNamespace
k8spodname = k8sPodName
k8scontainername = k8sContainerName
}

orgID, _ := strconv.Atoi(instance.OrgID)
auditor := &Auditor{
userID: r.Header.Get("User-ID"),
userID: r.Header.Get(httputil.UserHeader),
orgID: uint64(orgID),
bdl: bundle.New(bundle.WithErdaServer()),
podName: k8spodname,
Expand Down

0 comments on commit 0034b27

Please sign in to comment.