Skip to content

Commit

Permalink
feature(client status): add address column
Browse files Browse the repository at this point in the history
Signed-off-by: montaguelhz <[email protected]>
  • Loading branch information
montaguelhz committed Dec 15, 2023
1 parent 279c590 commit 46b57a9
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 2 deletions.
1 change: 1 addition & 0 deletions internal/errno/errno.go
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,7 @@ var (
ERR_INSPECT_CONTAINER_FAILED = EC(630012, "get container low-level information failed")
ERR_GET_CONTAINER_LOGS_FAILED = EC(630013, "get container logs failed")
ERR_UPDATE_CONTAINER_FAILED = EC(630014, "update container failed")
ERR_TOP_CONTAINER_FAILED = EC(630015, "top container failed")

// 690: execuetr task (others)
ERR_START_CRONTAB_IN_CONTAINER_FAILED = EC(690000, "start crontab in container failed")
Expand Down
12 changes: 12 additions & 0 deletions internal/task/step/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,12 @@ type (
Success *bool
module.ExecOptions
}

TopContainer struct {
ContainerId string
Out *string
module.ExecOptions
}
)

func (s *EngineInfo) Execute(ctx *context.Context) error {
Expand Down Expand Up @@ -337,3 +343,9 @@ func (s *UpdateContainer) Execute(ctx *context.Context) error {
out, err := cli.Execute(s.ExecOptions)
return PostHandle(s.Success, s.Out, out, err, errno.ERR_UPDATE_CONTAINER_FAILED.FD("(%s update ID)", s.ExecWithEngine))
}

func (s *TopContainer) Execute(ctx *context.Context) error {
cli := ctx.Module().DockerCli().TopContainer(s.ContainerId)
out, err := cli.Execute(s.ExecOptions)
return PostHandle(nil, s.Out, out, err, errno.ERR_TOP_CONTAINER_FAILED.FD("(%s top ID)", s.ExecWithEngine))
}
83 changes: 83 additions & 0 deletions internal/task/task/common/client_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ package common

import (
"fmt"
"regexp"
"strings"

"github.com/opencurve/curveadm/cli/cli"
comm "github.com/opencurve/curveadm/internal/common"
Expand All @@ -33,6 +35,7 @@ import (
"github.com/opencurve/curveadm/internal/task/task"
tui "github.com/opencurve/curveadm/internal/tui/common"
"github.com/opencurve/curveadm/internal/utils"
"github.com/opencurve/curveadm/pkg/module"
)

type (
Expand All @@ -41,6 +44,13 @@ type (
containerId string
status *string
memStorage *utils.SafeMap
address *string
}

step2GetAddress struct {
containerId string
address *string
execOptions module.ExecOptions
}

ClientStatus struct {
Expand All @@ -49,6 +59,7 @@ type (
Kind string
ContainerId string
Status string
Address string
AuxInfo string
}
)
Expand All @@ -69,6 +80,7 @@ func setClientStatus(memStorage *utils.SafeMap, id string, status ClientStatus)

func (s *step2FormatClientStatus) Execute(ctx *context.Context) error {
status := *s.status
address := *s.address
if len(status) == 0 { // container losed
status = comm.CLIENT_STATUS_LOSED
}
Expand All @@ -81,11 +93,75 @@ func (s *step2FormatClientStatus) Execute(ctx *context.Context) error {
Kind: client.Kind,
ContainerId: s.containerId,
Status: status,
Address: address,
AuxInfo: client.AuxInfo,
})
return nil
}

func (s *step2GetAddress) Execute(ctx *context.Context) error {
cmd := ctx.Module().DockerCli().TopContainer(s.containerId)
out, err := cmd.Execute(s.execOptions)
if err != nil {
return err
}

lines := strings.Split(out, "\n")
var pid string
if len(lines) > 1 {
reg := regexp.MustCompile(`\s+`)
res := reg.Split(lines[1], -1)
if len(res) > 1 {
pid = res[1]
}
}

if len(pid) == 0 {
return nil
}

// execute "ss" command in container
cli := ctx.Module().Shell().SocketStatistics("")
cli.AddOption("--no-header")
cli.AddOption("--processes")
cli.AddOption("--listening")
command, err := cli.String()
if err != nil {
return err
}

cmd = ctx.Module().DockerCli().ContainerExec(s.containerId, command)
out, err = cmd.Execute(s.execOptions)
if err != nil {
return err
}

// handle output
lines = strings.Split(out, "\n")
for _, line := range lines {
address := s.extractAddress(line, pid)
if len(address) > 0 {
*s.address = address
return nil
}
}

return nil
}

// e.g: tcp LISTEN 0 128 10.246.159.123:2379 *:* users:(("etcd",pid=7,fd=5))
// e.g: tcp LISTEN 0 128 *:2379 *:* users:(("etcd",pid=7,fd=5))
func (s *step2GetAddress) extractAddress(line, pid string) string {
regex, err := regexp.Compile(`^.* ((\d+\.\d+\.\d+\.\d+)|\*:\d+).*pid=` + pid + ".*$")
if err == nil {
mu := regex.FindStringSubmatch(line)
if len(mu) > 1 {
return mu[1]
}
}
return ""
}

func NewGetClientStatusTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, error) {
client := v.(storage.Client)
hc, err := curveadm.GetHost(client.Host)
Expand All @@ -100,18 +176,25 @@ func NewGetClientStatusTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task,

// add step
var status string
var address string
t.AddStep(&step.ListContainers{
ShowAll: true,
Format: `"{{.Status}}"`,
Filter: fmt.Sprintf("id=%s", containerId),
Out: &status,
ExecOptions: curveadm.ExecOptions(),
})
t.AddStep(&step2GetAddress{
containerId: containerId,
address: &address,
execOptions: curveadm.ExecOptions(),
})
t.AddStep(&step2FormatClientStatus{
client: client,
containerId: containerId,
status: &status,
memStorage: curveadm.MemStorage(),
address: &address,
})

return t, nil
Expand Down
6 changes: 4 additions & 2 deletions internal/tui/client/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func statusDecorate(status string) string {
return status
}

func sortStatues(statuses []task.ClientStatus) {
func sortStatuses(statuses []task.ClientStatus) {
sort.Slice(statuses, func(i, j int) bool {
s1, s2 := statuses[i], statuses[j]
if s1.Kind == s2.Kind {
Expand All @@ -59,21 +59,23 @@ func FormatStatus(statuses []task.ClientStatus, verbose bool) string {
"Host",
"Container Id",
"Status",
"Address",
"Aux Info",
}
first, second := tui.FormatTitle(title)
lines = append(lines, first)
lines = append(lines, second)

// status
sortStatues(statuses)
sortStatuses(statuses)
for _, status := range statuses {
lines = append(lines, []interface{}{
status.Id,
status.Kind,
status.Host,
tui.TrimContainerId(status.ContainerId),
tui.DecorateMessage{Message: status.Status, Decorate: statusDecorate},
status.Address,
status.AuxInfo,
})
}
Expand Down
7 changes: 7 additions & 0 deletions pkg/module/docker_cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const (
TEMPLATE_INSPECT_CONTAINER = "{{.engine}} inspect {{.options}} {{.container}}"
TEMPLATE_CONTAINER_LOGS = "{{.engine}} logs {{.options}} {{.container}}"
TEMPLATE_UPDATE_CONTAINER = "{{.engine}} update {{.options}} {{.container}}"
TEMPLATE_TOP_CONTAINER = "{{.engine}} top {{.container}}"
)

type DockerCli struct {
Expand Down Expand Up @@ -168,3 +169,9 @@ func (cli *DockerCli) UpdateContainer(containerId string) *DockerCli {
cli.data["container"] = containerId
return cli
}

func (cli *DockerCli) TopContainer(containerId string) *DockerCli {
cli.tmpl = template.Must(template.New("TopContainer").Parse(TEMPLATE_TOP_CONTAINER))
cli.data["container"] = containerId
return cli
}

0 comments on commit 46b57a9

Please sign in to comment.