Skip to content

Commit

Permalink
feat: cat file from container (#287)
Browse files Browse the repository at this point in the history
  • Loading branch information
keidarcy authored Oct 1, 2024
1 parent 496e362 commit 80e2c2b
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 2 deletions.
10 changes: 9 additions & 1 deletion internal/view/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func (v *clusterView) headerPagesParam(c types.Cluster) (items []headerItem) {
if c.ServiceConnectDefaults != nil {
scd = *c.ServiceConnectDefaults.Namespace
}
active, draining, running, pending := 0, 0, 0, 0
active, draining, running, pending, activeEC2, activeFargate := 0, 0, 0, 0, 0, 0
for _, statistic := range c.Statistics {
v, err := strconv.Atoi(*statistic.Value)
if err != nil {
Expand All @@ -124,10 +124,18 @@ func (v *clusterView) headerPagesParam(c types.Cluster) (items []headerItem) {
if strings.HasPrefix(*statistic.Name, "pending") {
pending += v
}
if strings.HasPrefix(*statistic.Name, "activeEC2") {
activeEC2 += v
}
if strings.HasPrefix(*statistic.Name, "activeFargate") {
activeFargate += v
}
}
items = []headerItem{
{name: "Name", value: *c.ClusterName},
{name: "Active services count", value: strconv.Itoa(active)},
{name: "Active EC2 services count", value: strconv.Itoa(activeEC2)},
{name: "Active Fargate services count", value: strconv.Itoa(activeFargate)},
{name: "Draining services count", value: strconv.Itoa(draining)},
{name: "Running tasks count", value: strconv.Itoa(running)},
{name: "Pending tasks count", value: strconv.Itoa(pending)},
Expand Down
1 change: 1 addition & 0 deletions internal/view/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func newContainerView(containers []types.Container, app *App) *containerView {
hotKeyMap["F"],
hotKeyMap["T"],
hotKeyMap["P"],
hotKeyMap["D"],
hotKeyMap["E"],
hotKeyMap["enter"],
hotKeyMap["ctrlD"],
Expand Down
109 changes: 109 additions & 0 deletions internal/view/cp.go → internal/view/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,115 @@ import (
)

// Get cp form content
func (v *view) catFile() (*tview.Form, *string) {
selected, err := v.getCurrentSelection()
if err != nil {
return nil, nil
}
// container containerName
containerName := *selected.container.Name

readOnly := ""
if v.app.ReadOnly {
readOnly = readOnlyLabel
}

title := " Download text file [purple::b]" + containerName + readOnly

f := ui.StyledForm(title)
containerPathLabel := "Path to download(container)"
localPathLabel := "Local path(temp file when empty)"

f.AddInputField(containerPathLabel, "", 50, nil, nil)
f.AddInputField(localPathLabel, "", 50, nil, nil)

// handle form close
f.AddButton("Cancel", func() {
v.closeModal()
})

// readonly mode has no submit button
if v.app.ReadOnly {
return f, &title
}

// handle form submit
f.AddButton("Start", func() {
path := f.GetFormItemByLabel(containerPathLabel).(*tview.InputField).GetText()
localPath := f.GetFormItemByLabel(localPathLabel).(*tview.InputField).GetText()

args := []string{
"ecs",
"execute-command",
"--cluster",
*v.app.cluster.ClusterName,
"--task",
*v.app.task.TaskArn,
"--container",
containerName,
"--interactive",
"--command",
fmt.Sprintf("cat %s", path),
}
bin, _ := exec.LookPath(awsCli)
cmd := exec.Command(bin, args...)

go func() {
v.app.Notice.Info("Working in progress")
slog.Info("exec", "command", bin+" "+strings.Join(args, " "))

output, err := cmd.Output()
if err != nil {
v.app.Notice.Errorf("Failed, %s", err.Error())
}

lines := strings.Split(string(output), "\n")

if strings.Contains(lines[5], "cat:") {
v.app.Notice.Errorf("Failed cat file \"%s\"", lines[5])
}

content := ""

for _, l := range lines[5:] {
if strings.HasPrefix(l, "Exiting session with sessionId") {
break
}
content += l
content += "\n"
}
var file *os.File
if localPath == "" {
pwd, err := os.Getwd()
if err != nil {
v.app.Notice.Errorf("failed to get current directory to create file, err: %v", err)
}
names := strings.Split(path, "/")
file, err = os.Create(fmt.Sprintf("%s/%s", pwd, names[len(names)-1]))
if err != nil {
v.app.Notice.Errorf("failed to create file, err: %v", err)
}
} else {
file, err = os.Create(localPath)
if err != nil {
v.app.Notice.Errorf("failed to create file, err: %v", err)
}
}
defer file.Close()

if _, err := file.WriteString(content); err != nil {
v.app.Notice.Warnf("failed to write file %v", err)
} else {
v.app.Notice.Infof("write content to file %s", file.Name())
}
}()

v.closeModal()
v.reloadResource(false)
})
return f, &title
}

func (v *view) cpForm() (*tview.Form, *string) {
selected, err := v.getCurrentSelection()
if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion internal/view/header.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

const (
// column height in info page
oneColumnCount = 12
oneColumnCount = 13
headerTitleFmt = " [blue]info([purple::b]%s[blue:-:-]) "
headerItemFmt = " %s:[aqua::b] %s "
headerKeyFmt = " [purple::b]<%s> [green:-:-]%s "
Expand All @@ -28,6 +28,7 @@ var hotKeyMap = map[string]keyDescriptionPair{
"w": {key: "w", description: "Describe service events"},
"S": {key: "shift-s", description: "Stop task"},
"P": {key: "shift-p", description: "File transfer"},
"D": {key: "shift-d", description: "Download text file content(beta)"},
"F": {key: "shift-f", description: "Start port forwarding session"},
"T": {key: "shift-t", description: "Terminate port forwarding session"},
"U": {key: "shift-u", description: "Update service"},
Expand Down
4 changes: 4 additions & 0 deletions internal/view/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,10 @@ func (v *view) handleInputCapture(event *tcell.EventKey) *tcell.EventKey {
v.showFormModal(v.execCommandForm, 7)
return event
}
case 'D':
v.app.secondaryKind = ModalKind
v.showFormModal(v.catFile, 10)
return event
case '/':
v.app.secondaryKind = ModalKind
v.showSearchFormModal(v.searchForm, 5)
Expand Down

0 comments on commit 80e2c2b

Please sign in to comment.