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 <1443171175@qq.com>
  • Loading branch information
montaguelhz committed Dec 18, 2023
1 parent a703f1e commit 656fccc
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 8 deletions.
1 change: 1 addition & 0 deletions internal/errno/errno.go
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,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 @@ -155,6 +155,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 @@ -324,3 +330,9 @@ func (s *ContainerLogs) Execute(ctx *context.Context) error {
out, err := cli.Execute(s.ExecOptions)
return PostHandle(s.Success, s.Out, out, err, errno.ERR_GET_CONTAINER_LOGS_FAILED.FD("(%s logs 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))
}
98 changes: 92 additions & 6 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 @@ -34,6 +36,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"
)

const (
Expand All @@ -48,9 +51,17 @@ type (
}

step2FormatClientStatus struct {
client storage.Client
status *string
memStorage *utils.SafeMap
client storage.Client
status *string
memStorage *utils.SafeMap
containerId string
address *string
}

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

ClientStatus struct {
Expand All @@ -59,6 +70,7 @@ type (
Kind string
ContainerId string
Status string
Address string
AuxInfo string
CfgPath string
}
Expand Down Expand Up @@ -109,6 +121,7 @@ func (s *step2InitClientStatus) Execute(ctx *context.Context) error {
Kind: client.Kind,
ContainerId: client.ContainerId,
Status: comm.CLIENT_STATUS_UNKNOWN,
Address: "",
AuxInfo: client.AuxInfo,
CfgPath: *s.cfgPath,
})
Expand All @@ -117,6 +130,7 @@ func (s *step2InitClientStatus) Execute(ctx *context.Context) error {

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 @@ -129,6 +143,7 @@ func (s *step2FormatClientStatus) Execute(ctx *context.Context) error {
// update the status
s := m[id]
s.Status = status
s.Address = address
m[id] = s
kv.Set(comm.KEY_ALL_CLIENT_STATUS, m)
return nil
Expand All @@ -154,6 +169,69 @@ func NewInitClientStatusTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task,
return t, 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 nil
}

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 nil
}

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

// 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 @@ -168,17 +246,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,
status: &status,
memStorage: curveadm.MemStorage(),
client: client,
status: &status,
memStorage: curveadm.MemStorage(),
containerId: containerId,
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,6 +59,7 @@ func FormatStatus(statuses []task.ClientStatus, verbose bool) string {
"Host",
"Container Id",
"Status",
"Address",
"Aux Info",
}
if verbose {
Expand All @@ -69,7 +70,7 @@ func FormatStatus(statuses []task.ClientStatus, verbose bool) string {
lines = append(lines, second)

// status
sortStatues(statuses)
sortStatuses(statuses)
for _, status := range statuses {
// line
line := []interface{}{
Expand All @@ -78,6 +79,7 @@ func FormatStatus(statuses []task.ClientStatus, verbose bool) string {
status.Host,
tui.TrimContainerId(status.ContainerId),
tui.DecorateMessage{Message: status.Status, Decorate: statusDecorate},
status.Address,
status.AuxInfo,
}
if verbose {
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 @@ -162,3 +163,9 @@ func (cli *DockerCli) ContainerLogs(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 656fccc

Please sign in to comment.