Skip to content

Commit

Permalink
feat: support service revision (#309)
Browse files Browse the repository at this point in the history
  • Loading branch information
keidarcy authored Dec 29, 2024
1 parent 03c7d7b commit a0792ec
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 34 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ tail -f /tmp/e1s.log
- [x] Auto refresh
- [x] Describe clusters
- [x] Describe services
- [x] Describe service deployments(new)
- [x] Describe service deployments
- [x] Describe service revisions
- [x] Describe tasks(running, stopped)
- [x] Describe containers
- [x] Describe task definitions
Expand Down
13 changes: 13 additions & 0 deletions internal/api/service_deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,16 @@ func (store *Store) ListServiceDeployments(cluster, service *string) ([]types.Se

return describeOutput.ServiceDeployments, nil
}

// Equivalent to
// aws ecs describe-service-revisions --service-revision-arns ${arn1}
func (store *Store) GetServiceRevision(serviceRevisionArn *string) (*types.ServiceRevision, error) {
describeServiceRevisionOutput, err := store.ecs.DescribeServiceRevisions(context.Background(), &ecs.DescribeServiceRevisionsInput{
ServiceRevisionArns: []string{*serviceRevisionArn},
})
if err != nil {
slog.Warn("failed to run aws api to describe service revision", "error", err)
return nil, err
}
return &describeServiceRevisionOutput.ServiceRevisions[0], nil
}
3 changes: 2 additions & 1 deletion internal/view/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type Entity struct {
metrics *api.MetricsData
autoScaling *api.AutoScalingData
serviceDeployment *types.ServiceDeployment
serviceRevision *types.ServiceRevision
entityName string
}

Expand Down Expand Up @@ -282,7 +283,7 @@ func (app *App) showPrimaryKindPage(k kind, reload bool) error {
err = app.showContainersPage(reload)
case TaskDefinitionKind:
err = app.showTaskDefinitionPage(reload)
case ServiceDeployment:
case ServiceDeploymentKind:
err = app.showServiceDeploymentPage(reload)
default:
app.kind = ClusterKind
Expand Down
4 changes: 2 additions & 2 deletions internal/view/footer.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func newFooter() *footer {
task: tview.NewTextView().SetDynamicColors(true).SetText(fmt.Sprintf(color.FooterItemFmt, TaskKind)),
container: tview.NewTextView().SetDynamicColors(true).SetText(fmt.Sprintf(color.FooterItemFmt, ContainerKind)),
taskDefinition: tview.NewTextView().SetDynamicColors(true).SetText(fmt.Sprintf(color.FooterItemFmt, TaskDefinitionKind)).SetTextAlign(L),
serviceDeployment: tview.NewTextView().SetDynamicColors(true).SetText(fmt.Sprintf(color.FooterItemFmt, ServiceDeployment)).SetTextAlign(L),
serviceDeployment: tview.NewTextView().SetDynamicColors(true).SetText(fmt.Sprintf(color.FooterItemFmt, ServiceDeploymentKind)).SetTextAlign(L),
help: tview.NewTextView().SetDynamicColors(true).SetText(fmt.Sprintf(color.FooterItemFmt, HelpKind)).SetTextAlign(L),
}
}
Expand All @@ -46,7 +46,7 @@ func (v *view) addFooterItems() {
v.footer.footerFlex.
AddItem(tview.NewTextView(), 5, 0, false).
AddItem(v.footer.taskDefinition, 0, 1, false)
} else if v.app.kind == ServiceDeployment {
} else if v.app.kind == ServiceDeploymentKind {
v.footer.footerFlex.
AddItem(tview.NewTextView(), 5, 0, false).
AddItem(v.footer.serviceDeployment, 0, 1, false)
Expand Down
7 changes: 4 additions & 3 deletions internal/view/header.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@ const (

var hotKeyMap = map[string]keyDescriptionPair{
"/": {key: "/", description: "Search in table"},
"a": {key: "a", description: "Describe service auto scaling"},
"a": {key: "a", description: "Show service auto scaling"},
"f": {key: "f", description: "Toggle full screen"},
"l": {key: "l", description: "Show cloudwatch logs(Only support awslogs logDriver)"},
"m": {key: "m", description: "Show metrics(CPU/Memory)"},
"r": {key: "r", description: "Realtime log streaming(Only support one log group)"},
"t": {key: "t", description: "Show task definitions"},
"p": {key: "t", description: "Show service deployments"},
"p": {key: "p", description: "Show service deployments"},
"n": {key: "n", description: "Show all cluster tasks"},
"s": {key: "s", description: "Toggle running/stopped tasks"},
"w": {key: "w", description: "Describe service events"},
"w": {key: "w", description: "Show service events"},
"v": {key: "v", description: "Show service revision"},
"S": {key: "shift-s", description: "Stop task"},
"P": {key: "shift-p", description: "Transfer file though a S3 bucket"},
"D": {key: "shift-d", description: "Download text file content(beta)"},
Expand Down
25 changes: 24 additions & 1 deletion internal/view/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,27 @@ func (v *view) switchToAutoScalingJson() {
v.showJsonPages(entity)
}

// Switch to service revision
func (v *view) switchToServiceRevisionJson() {
selected, err := v.getCurrentSelection()
if err != nil {
return
}
serviceRevisionArn := selected.serviceDeployment.TargetServiceRevision.Arn

if serviceRevisionArn == nil {
return
}

serviceRevision, err := v.app.Store.GetServiceRevision(serviceRevisionArn)

if err != nil {
return
}
entity := Entity{serviceRevision: serviceRevision, entityName: *selected.serviceDeployment.ServiceDeploymentArn}
v.showJsonPages(entity)
}

// Show new page from JSON content in table area and handle done event to go back
func (v *view) showJsonPages(entity Entity) {
colorizedJsonString, rawJsonString, err := v.getJsonString(entity)
Expand Down Expand Up @@ -218,7 +239,7 @@ func (v *view) getJsonString(entity Entity) (string, []byte, error) {
data = entity.events
case entity.service != nil && v.app.kind == ServiceKind:
data = entity.service
case entity.serviceDeployment != nil && v.app.kind == ServiceDeployment:
case entity.serviceDeployment != nil && v.app.kind == ServiceDeploymentKind:
data = entity.serviceDeployment
case entity.task != nil && v.app.kind == TaskKind:
data = entity.task
Expand All @@ -230,6 +251,8 @@ func (v *view) getJsonString(entity Entity) (string, []byte, error) {
data = entity.metrics
case entity.autoScaling != nil:
data = entity.autoScaling
case entity.serviceRevision != nil:
data = entity.serviceRevision
default:
slog.Error("failed to get json string", "data", data)
data = struct {
Expand Down
11 changes: 7 additions & 4 deletions internal/view/kind.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ const (
HelpKind
DescriptionKind
ServiceEventsKind
ServiceDeployment
ServiceDeploymentKind
LogKind
AutoScalingKind
ServiceRevisionKind
ModalKind
EmptyKind
)
Expand All @@ -36,8 +37,10 @@ func (k kind) String() string {
return "task definitions"
case ServiceEventsKind:
return "service events"
case ServiceDeployment:
case ServiceDeploymentKind:
return "service deployments"
case ServiceRevisionKind:
return "service revision"
case LogKind:
return "logs"
case AutoScalingKind:
Expand Down Expand Up @@ -68,7 +71,7 @@ func (k kind) prevKind() kind {
return ClusterKind
case ServiceKind:
return ClusterKind
case TaskKind, TaskDefinitionKind, ServiceDeployment:
case TaskKind, TaskDefinitionKind, ServiceDeploymentKind:
return ServiceKind
case ContainerKind:
return TaskKind
Expand All @@ -82,7 +85,7 @@ func (k kind) getAppPageName(name string) string {
switch k {
case ClusterKind:
return k.String()
case ServiceKind, TaskKind, ContainerKind, TaskDefinitionKind, ServiceDeployment, DescriptionKind:
case ServiceKind, TaskKind, ContainerKind, TaskDefinitionKind, ServiceDeploymentKind, DescriptionKind:
return k.String() + "." + name
default:
return k.String()
Expand Down
36 changes: 18 additions & 18 deletions internal/view/service_deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ type serviceDeploymentView struct {
// Constructor for service deployment view
func newServiceDeploymentView(serviceDeployments []types.ServiceDeployment, app *App) *serviceDeploymentView {
keys := append(basicKeyInputs, []keyDescriptionPair{
hotKeyMap["U"],
hotKeyMap["v"],
}...)
return &serviceDeploymentView{
view: *newView(app, keys, secondaryPageKeyMap{
DescriptionKind: describePageKeys,
DescriptionKind: describePageKeys,
ServiceRevisionKind: describePageKeys,
}),
serviceDeployments: serviceDeployments,
}
Expand Down Expand Up @@ -91,8 +92,8 @@ func (v *serviceDeploymentView) headerPagesParam(d types.ServiceDeployment) (ite
return "-"
}
return fmt.Sprintf("Max: %d%%, Min: %d%%",
d.DeploymentConfiguration.MaximumPercent,
d.DeploymentConfiguration.MinimumHealthyPercent)
*d.DeploymentConfiguration.MaximumPercent,
*d.DeploymentConfiguration.MinimumHealthyPercent)
}()},
{name: "Circuit Breaker Config", value: func() string {
if d.DeploymentConfiguration == nil || d.DeploymentConfiguration.DeploymentCircuitBreaker == nil {
Expand All @@ -102,24 +103,23 @@ func (v *serviceDeploymentView) headerPagesParam(d types.ServiceDeployment) (ite
d.DeploymentConfiguration.DeploymentCircuitBreaker.Enable,
d.DeploymentConfiguration.DeploymentCircuitBreaker.Rollback)
}()},
{name: "Source revision", value: func() string {
if len(d.SourceServiceRevisions) == 0 {
{name: "Target task count", value: func() string {
if d.TargetServiceRevision == nil {
return "-"
}
return fmt.Sprintf("%s (Running: %d, Pending: %d)",
utils.ArnToName(d.SourceServiceRevisions[0].Arn),
d.SourceServiceRevisions[0].RunningTaskCount,
d.SourceServiceRevisions[0].PendingTaskCount)
return fmt.Sprintf("Requested: %d, Running: %d, Pending: %d",
d.TargetServiceRevision.RequestedTaskCount,
d.TargetServiceRevision.RunningTaskCount,
d.TargetServiceRevision.PendingTaskCount)
}()},
{name: "Target revision", value: func() string {
if d.TargetServiceRevision == nil {
{name: "Source task count", value: func() string {
if len(d.SourceServiceRevisions) == 0 {
return "-"
}
return fmt.Sprintf("%s (Running: %d, Pending: %d, Requested: %d)",
utils.ArnToName(d.TargetServiceRevision.Arn),
d.TargetServiceRevision.RunningTaskCount,
d.TargetServiceRevision.PendingTaskCount,
d.TargetServiceRevision.RequestedTaskCount)
return fmt.Sprintf("Requested: %d, Running: %d, Pending: %d",
d.SourceServiceRevisions[0].RequestedTaskCount,
d.SourceServiceRevisions[0].RunningTaskCount,
d.SourceServiceRevisions[0].PendingTaskCount)
}()},
{name: "Created At", value: utils.ShowTime(d.CreatedAt)},
{name: "Started At", value: utils.ShowTime(d.StartedAt)},
Expand Down Expand Up @@ -163,7 +163,7 @@ func (v *serviceDeploymentView) tableParam() (title string, headers []string, da
headers = []string{
"Deployment ID ▾",
"Status",
"Revision",
"Target service revision",
"Created At",
"Started At",
"Finished At",
Expand Down
12 changes: 9 additions & 3 deletions internal/view/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,13 @@ func (v *view) handleInputCapture(event *tcell.EventKey) *tcell.EventKey {
}
case 'p':
if v.app.kind == ServiceKind {
v.showKindPage(ServiceDeployment, false)
v.showKindPage(ServiceDeploymentKind, false)
return event
}
case 'v':
if v.app.kind == ServiceDeploymentKind {
v.app.secondaryKind = ServiceRevisionKind
v.showSecondaryKindPage(false)
return event
}
case 's':
Expand Down Expand Up @@ -284,7 +290,7 @@ func (v *view) changeSelectedValues() {
slog.Warn("unexpected in changeSelectedValues", "kind", v.app.kind)
return
}
case ServiceDeployment:
case ServiceDeploymentKind:
serviceDeployment := selected.serviceDeployment
if serviceDeployment != nil {
v.app.serviceDeployment = selected.serviceDeployment
Expand Down Expand Up @@ -320,7 +326,7 @@ func (v *view) openInBrowser() {
arn = *v.app.task.TaskArn
case TaskDefinitionKind:
arn = *v.app.taskDefinition.TaskDefinitionArn
case ServiceDeployment:
case ServiceDeploymentKind:
arn = *v.app.serviceDeployment.ServiceDeploymentArn
}
url := utils.ArnToUrl(arn, taskService)
Expand Down
4 changes: 3 additions & 1 deletion internal/view/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ func (v *view) showSecondaryKindPage(reload bool) {
v.switchToLogsList()
case ServiceEventsKind:
v.switchToServiceEventsList()
case ServiceRevisionKind:
v.switchToServiceRevisionJson()
}
if !reload {
v.app.Notice.Infof("Viewing %s...", v.app.secondaryKind.String())
Expand Down Expand Up @@ -158,7 +160,7 @@ func (v *view) handleSecondaryPageSwitch(entity Entity, colorizedJsonString stri
v.realtimeAwsLog(entity)
}
case 'e':
if v.app.secondaryKind == DescriptionKind || v.app.secondaryKind == AutoScalingKind || v.app.secondaryKind == LogKind {
if v.app.secondaryKind == DescriptionKind || v.app.secondaryKind == AutoScalingKind || v.app.secondaryKind == ServiceRevisionKind || v.app.secondaryKind == LogKind {
v.openInEditor(jsonBytes)
}
}
Expand Down

0 comments on commit a0792ec

Please sign in to comment.