Skip to content

Commit

Permalink
Merge pull request #95 from keidarcy/feat/improve-reload
Browse files Browse the repository at this point in the history
Support reload resources
  • Loading branch information
keidarcy authored Dec 30, 2023
2 parents 2d843e9 + 63abdc8 commit 3596a22
Show file tree
Hide file tree
Showing 13 changed files with 96 additions and 60 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,14 @@ $ e1s -version
| `k`, `` | Select previous item |
| `l`, ``, `Enter` | Enter current resource/SSH |
| `h`, ``, `Esc` | Go to previous view |
| `d` | Describe selected resource |
| `d` | Describe selected resource(show json) |
| `t` | Describe task definition |
| `w` | Describe service events |
| `a` | Show service auto scaling |
| `m` | Show service metrics(CPUUtilization/MemoryUtilization) |
| `r` | List task definition revisions |
| `r` | Reload resources |
| `v` | List task definition revisions |
| `f` | Toggle full screen |
| `e` | Edit resource |
| `b` | Open selected resource in AWS web console |
| `ctrl` + `c` | Quit |
Expand Down
2 changes: 1 addition & 1 deletion api/auto_scaling.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func (store *Store) describeScheduledAction(serviceArn *string) ([]types.Schedul
actionsOutput, err := store.autoScaling.DescribeScheduledActions(context.Background(), actionsInput)

if err != nil {
logger.Printf("aws failed to auto scaling scheduled actions serviceArn: \"%s\", err: %v\n", *serviceArn, err)
logger.Printf("e1s - aws failed to auto scaling scheduled actions serviceArn: \"%s\", err: %v\n", *serviceArn, err)
return nil, err
}

Expand Down
2 changes: 1 addition & 1 deletion api/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type Store struct {
func NewStore() *Store {
cfg, err := config.LoadDefaultConfig(context.Background(), config.WithRegion(os.Getenv("AWS_REGION")))
if err != nil {
logger.Printf("unable to load SDK config, error: %v\n", err)
logger.Printf("e1s - aws unable to load SDK config, error: %v\n", err)
}
ecsClient := ecs.NewFromConfig(cfg)
return &Store{
Expand Down
7 changes: 5 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package main

import (
"fmt"
"os"

"github.com/keidarcy/e1s/ui"
"github.com/keidarcy/e1s/util"
)

func main() {
if err := ui.Show(); err != nil {
fmt.Println("e1s failed to start, valid aws cli and aws cli profile are required")
panic(err)
util.Logger.Printf("e1s - failed to start, error: %v\n", err)
fmt.Println("e1s failed to start, please check your aws cli credential.")
os.Exit(1)
}
}
8 changes: 6 additions & 2 deletions ui/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ui

import (
"fmt"
"os"
"strconv"
"strings"

Expand All @@ -25,14 +26,17 @@ func newClusterView(clusters []types.Cluster, app *App) *ClusterView {
func (app *App) showClustersPage() error {
clusters, err := app.Store.ListClusters()
if err != nil {
logger.Printf("show clusters failed, error: %v\n", err)
logger.Printf("e1s - show clusters failed, error: %v\n", err)
return err
}

view := newClusterView(clusters, app)

if len(clusters) == 0 {
go view.flashModal(fmt.Sprintf(initErrorFmt, app.Region), 10)
fmt.Printf("There is no valid clusters in \033[31m%s\033[0m. Please check you ecs cluster via `AWS_REGION=%s aws ecs list-clusters`.\n", app.Region, app.Region)
os.Exit(0)
}

page := buildAppPage(view)
view.addAppPage(page)
return nil
Expand Down
14 changes: 8 additions & 6 deletions ui/components.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,21 @@ func (v *View) styledForm(title string) *tview.Form {
return f
}

func (v *View) errorModal(text string) {
v.flashModal(fmt.Sprintf("[red::b]%s ", text), 3)
// Call this function need a new goroutine
func (v *View) errorModal(text string, duration, width, height int) {
v.flashModal(fmt.Sprintf("[red::b]%s ", text), duration, width, height)
}

func (v *View) successModal(text string) {
v.flashModal(fmt.Sprintf("[green::b]%s ", text), 3)
// Call this function need a new goroutine
func (v *View) successModal(text string, duration, width, height int) {
v.flashModal(fmt.Sprintf("[green::b]%s ", text), duration, width, height)
}

// show a flash modal in a given time duration
func (v *View) flashModal(text string, duration int) {
func (v *View) flashModal(text string, duration, width, height int) {
t := tview.NewTextView().SetDynamicColors(true).SetText(text)
t.SetBorder(true)
v.app.Pages.AddPage(text, v.modal(t, 100, 10), true, true)
v.app.Pages.AddPage(text, v.modal(t, width, height), true, true)
t.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
v.closeModal()
return event
Expand Down
56 changes: 32 additions & 24 deletions ui/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
const (
shell = "/bin/sh"
awsCli = "aws"
sshBannerFmt = "\033[1;31m\033[46m <<ECS-SSH>>: \033[0m Cluster: \"%s\" | Service: \"%s\" | Task: \"%s\" | Container: \"%s\""
sshBannerFmt = "\033[1;31m<<ECS-EXEC-SSH>>\033[0m: \n#######################################\n\033[1;32mCluster\033[0m: \"%s\" \n\033[1;32mService\033[0m: \"%s\" \n\033[1;32mTask\033[0m: \"%s\" \n\033[1;32mContainer\033[0m: \"%s\"\n#######################################\n"
)

type ContainerView struct {
Expand Down Expand Up @@ -89,31 +89,39 @@ func (v *ContainerView) tableHandler() {
v.ssh(containerName)
})

v.table.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
// simulate selected action(ssh)
sshHandler := func() {
selected := v.getCurrentSelection()
containerName := *selected.container.Name
v.ssh(containerName)
}

// handle right arrow key
if event.Key() == tcell.KeyRight {
sshHandler()
return event
}
v.table.SetInputCapture(v.handleInputCapture)
}

// handle l key
key := event.Rune()
switch key {
case lKey, lKey - upperLowerDiff:
// Container page specific input handler
func (v *ContainerView) handleInputCapture(event *tcell.EventKey) *tcell.EventKey {
// simulate selected action(ssh)
sshHandler := func() {
selected := v.getCurrentSelection()
containerName := *selected.container.Name
v.ssh(containerName)
}

sshHandler()
case hKey, hKey - upperLowerDiff:
v.handleDone(0)
}
// handle right arrow key
if event.Key() == tcell.KeyRight {
sshHandler()
return event
})
}

// handle l key
key := event.Rune()
switch key {
case rKey, rKey - upperLowerDiff:
v.reloadResource()
case lKey, lKey - upperLowerDiff:
sshHandler()
case hKey, hKey - upperLowerDiff:
v.handleDone(0)
case bKey, bKey - upperLowerDiff:
v.openInBrowser()
case dKey, dKey - upperLowerDiff:
v.switchToResourceJson()
}
return event
}

// Generate info pages params
Expand Down Expand Up @@ -184,7 +192,7 @@ func (v *ContainerView) ssh(containerName string) {
}
bin, err := exec.LookPath(awsCli)
if err != nil {
logger.Printf("aws binary not found, error: %v\n", err)
logger.Printf("e1s - aws cli binary not found, error: %v\n", err)
v.back()
}
arg := []string{
Expand Down
2 changes: 1 addition & 1 deletion ui/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ func (v *View) getJsonString(entity Entity, which string) string {
jsonBytes, err := json.MarshalIndent(data, "", " ")

if err != nil {
logger.Printf("json page marshal indent failed, error: %v\n", err)
logger.Printf("e1s - json page marshal indent failed, error: %v\n", err)
return "json page marshal indent failed"
}

Expand Down
10 changes: 6 additions & 4 deletions ui/modal.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ func (v *View) serviceUpdateContent() (*tview.Form, string) {
// get data for form
families, err := v.app.Store.ListTaskDefinitionFamilies()
if err != nil {
v.errorModal("aws api error!")
v.errorModal("aws api error!", 2, 20, 10)
v.closeModal()
}

Expand Down Expand Up @@ -247,7 +247,7 @@ func (v *View) serviceUpdateContent() (*tview.Form, string) {
// when family option change, change revision drop down value
taskDefinitions, err := v.app.Store.ListTaskDefinition(&text)
if err != nil {
v.errorModal("aws api error!")
v.errorModal("aws api error!", 2, 20, 10)
v.closeModal()
}
revisions := []string{}
Expand Down Expand Up @@ -315,10 +315,12 @@ func (v *View) serviceUpdateContent() (*tview.Form, string) {

if err != nil {
v.closeModal()
go v.errorModal(err.Error())
go v.errorModal(err.Error(), 5, 100, 10)
v.reloadResource()
} else {
v.closeModal()
go v.successModal(fmt.Sprintf("SUCCESS 🚀\nDesiredCount: %d\nTaskDefinition: %s\n", s.DesiredCount, *s.TaskDefinition))
go v.successModal(fmt.Sprintf("SUCCESS 🚀\nDesiredCount: %d\nTaskDefinition: %s\n", s.DesiredCount, *s.TaskDefinition), 5, 110, 5)
v.reloadResource()
}
})
return f, title
Expand Down
2 changes: 1 addition & 1 deletion ui/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func newServiceView(services []types.Service, app *App) *ServiceView {
func (app *App) showServicesPage() error {
services, err := app.Store.ListServices(app.cluster.ClusterName)
if err != nil {
logger.Printf("show services page failed, error: %v\n", err)
logger.Printf("e1s - show services page failed, error: %v\n", err)
return err
}

Expand Down
26 changes: 14 additions & 12 deletions ui/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func (v *View) handleSelectionChanged(row, column int) {
func (v *View) handleSelected(row, column int) {
err := v.handleAppPageSwitch(v.app.entityName, false)
if err != nil {
logger.Printf("page change failed, error: %v\n", err)
logger.Printf("e1s - page change failed, error: %v\n", err)
v.back()
}
}
Expand Down Expand Up @@ -109,6 +109,8 @@ func (v *View) handleInputCapture(event *tcell.EventKey) *tcell.EventKey {
case tKey, tKey - upperLowerDiff:
v.switchToTaskDefinitionJson()
case rKey, rKey - upperLowerDiff:
v.reloadResource()
case vKey, vKey - upperLowerDiff:
v.switchToTaskDefinitionRevisionsJson()
case wKey, wKey - upperLowerDiff:
v.switchToServiceEventsJson()
Expand Down Expand Up @@ -180,7 +182,7 @@ func (v *View) openInBrowser() {
logger.Printf("open url: %s\n", url)
err := util.OpenURL(url)
if err != nil {
logger.Printf("failed open url %s\n", url)
logger.Printf("e1s - failed open url %s\n", url)
}
}

Expand All @@ -195,7 +197,7 @@ func (v *View) editTaskDefinition() {
taskDefinition := *selected.task.TaskDefinitionArn
td, err := v.app.Store.DescribeTaskDefinition(&taskDefinition)
if err != nil {
v.errorModal(errMsg)
v.errorModal(errMsg, 2, 110, 10)
return
}
names := strings.Split(selected.entityName, "/")
Expand All @@ -204,7 +206,7 @@ func (v *View) editTaskDefinition() {
tmpfile, err := os.CreateTemp("", names[len(names)-1])
if err != nil {
logger.Println("Error creating temporary file:", err)
v.errorModal(errMsg)
v.errorModal(errMsg, 2, 110, 10)
return
}
defer os.Remove(tmpfile.Name())
Expand All @@ -213,13 +215,13 @@ func (v *View) editTaskDefinition() {
originalTD, err := json.MarshalIndent(td, "", " ")
if err != nil {
logger.Println("Error reading temporary file:", err)
v.errorModal(errMsg)
v.errorModal(errMsg, 2, 110, 10)
return
}

if _, err := tmpfile.Write(originalTD); err != nil {
logger.Println("Error writing to temporary file:", err)
v.errorModal(errMsg)
v.errorModal(errMsg, 2, 110, 10)
return
}

Expand All @@ -236,14 +238,14 @@ func (v *View) editTaskDefinition() {

if err := cmd.Run(); err != nil {
logger.Println("Error opening editor:", err)
v.errorModal(errMsg)
v.errorModal(errMsg, 2, 110, 10)
return
}

editedTD, err := os.ReadFile(tmpfile.Name())
if err != nil {
logger.Println("Error reading temporary file:", err)
v.errorModal(errMsg)
v.errorModal(errMsg, 2, 110, 10)
return
}

Expand All @@ -254,14 +256,14 @@ func (v *View) editTaskDefinition() {

// if no change do nothing
if bytes.Equal(originalTD, editedTD) {
v.flashModal(" no change", 2)
v.flashModal(" Task definition has no change.", 2, 50, 3)
return
}

var updatedTd ecs.RegisterTaskDefinitionInput
if err := json.Unmarshal(editedTD, &updatedTd); err != nil {
logger.Println("Error unmarshaling JSON:", err)
v.errorModal(errMsg)
v.errorModal(errMsg, 2, 110, 10)
return
}

Expand All @@ -270,10 +272,10 @@ func (v *View) editTaskDefinition() {

if err != nil {
logger.Println("Error opening editor:", err)
v.errorModal(errMsg)
v.errorModal(errMsg, 2, 110, 10)
return
}
v.successModal(fmt.Sprintf("SUCCESS 🚀\nTaskDefinition Family: %s\nRevision: %d\n", family, revision))
v.successModal(fmt.Sprintf("SUCCESS 🚀\nTaskDefinition Family: %s\nRevision: %d\n", family, revision), 5, 110, 5)
}

v.showTaskDefinitionConfirm(register)
Expand Down
2 changes: 1 addition & 1 deletion ui/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func (app *App) showTasksPages() error {
tasks, err := app.Store.ListTasks(app.cluster.ClusterName, app.service.ServiceName)

if err != nil {
logger.Printf("show tasks pages failed, error: %v\n", err)
logger.Printf("e1s - show tasks pages failed, error: %v\n", err)
return err
}

Expand Down
Loading

0 comments on commit 3596a22

Please sign in to comment.