add toogle suspend actions in CronJob (#1010)
add toggleSuspend action and remove separate suspend/unsuspend Allow to toggleSuspend on one resource only and update text fix showSuspendDialog Co-authored-by: Ludovico Russo <ludovico.russo@redcarbon.ai>mine
parent
e8c371b1a7
commit
b29e368cb4
|
|
@ -107,6 +107,32 @@ func (c *CronJob) ScanSA(ctx context.Context, fqn string, wait bool) (Refs, erro
|
||||||
return refs, nil
|
return refs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetSuspend a CronJob.
|
||||||
|
func (c *CronJob) SetSuspend(ctx context.Context, path string, suspend bool) error {
|
||||||
|
ns, n := client.Namespaced(path)
|
||||||
|
auth, err := c.Client().CanI(ns, "batch/v1beta1/CronJob", []string{client.GetVerb, client.UpdateVerb})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !auth {
|
||||||
|
return fmt.Errorf("user is not authorized to update a CronJob")
|
||||||
|
}
|
||||||
|
|
||||||
|
dial, err := c.Client().Dial()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cronjob, err := dial.BatchV1beta1().CronJobs(ns).Get(ctx, n, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cronjob.Spec.Suspend = &suspend
|
||||||
|
_, err = dial.BatchV1beta1().CronJobs(ns).Update(ctx, cronjob, metav1.UpdateOptions{})
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Scan scans for cluster resource refs.
|
// Scan scans for cluster resource refs.
|
||||||
func (c *CronJob) Scan(ctx context.Context, gvr, fqn string, wait bool) (Refs, error) {
|
func (c *CronJob) Scan(ctx context.Context, gvr, fqn string, wait bool) (Refs, error) {
|
||||||
ns, n := client.Namespaced(fqn)
|
ns, n := client.Namespaced(fqn)
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,14 @@ package view
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/derailed/k9s/internal"
|
"github.com/derailed/k9s/internal"
|
||||||
"github.com/derailed/k9s/internal/client"
|
"github.com/derailed/k9s/internal/client"
|
||||||
"github.com/derailed/k9s/internal/dao"
|
"github.com/derailed/k9s/internal/dao"
|
||||||
"github.com/derailed/k9s/internal/render"
|
"github.com/derailed/k9s/internal/render"
|
||||||
"github.com/derailed/k9s/internal/ui"
|
"github.com/derailed/k9s/internal/ui"
|
||||||
|
"github.com/derailed/tview"
|
||||||
"github.com/gdamore/tcell/v2"
|
"github.com/gdamore/tcell/v2"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
batchv1beta1 "k8s.io/api/batch/v1beta1"
|
batchv1beta1 "k8s.io/api/batch/v1beta1"
|
||||||
|
|
@ -17,6 +19,8 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const suspendDialogKey = "suspend"
|
||||||
|
|
||||||
// CronJob represents a cronjob viewer.
|
// CronJob represents a cronjob viewer.
|
||||||
type CronJob struct {
|
type CronJob struct {
|
||||||
ResourceViewer
|
ResourceViewer
|
||||||
|
|
@ -64,9 +68,99 @@ func jobCtx(path, uid string) ContextFunc {
|
||||||
func (c *CronJob) bindKeys(aa ui.KeyActions) {
|
func (c *CronJob) bindKeys(aa ui.KeyActions) {
|
||||||
aa.Add(ui.KeyActions{
|
aa.Add(ui.KeyActions{
|
||||||
tcell.KeyCtrlT: ui.NewKeyAction("Trigger", c.trigger, true),
|
tcell.KeyCtrlT: ui.NewKeyAction("Trigger", c.trigger, true),
|
||||||
|
ui.KeyShiftS: ui.NewKeyAction("ToggleSuspend", c.toggleSuspend, true),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CronJob) toggleSuspend(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
|
sel := c.GetTable().GetSelectedItem()
|
||||||
|
if sel == "" {
|
||||||
|
return evt
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Stop()
|
||||||
|
defer c.Start()
|
||||||
|
c.showSuspendDialog(sel)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CronJob) showSuspendDialog(sel string) {
|
||||||
|
cell := c.GetTable().GetCell(c.GetTable().GetSelectedRowIndex(), c.GetTable().NameColIndex() + 2)
|
||||||
|
if cell == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
suspended := strings.TrimSpace(cell.Text) == "true"
|
||||||
|
title := "Suspend"
|
||||||
|
if suspended {
|
||||||
|
title = "Unsuspend"
|
||||||
|
}
|
||||||
|
|
||||||
|
confirm := tview.NewModalForm(fmt.Sprintf("<%s>", title), c.makeSuspendForm(sel, !suspended))
|
||||||
|
confirm.SetText(fmt.Sprintf("%s CronJob %s", title, sel))
|
||||||
|
confirm.SetDoneFunc(func(int, string) {
|
||||||
|
c.dismissDialog()
|
||||||
|
})
|
||||||
|
c.App().Content.AddPage(suspendDialogKey, confirm, false, false)
|
||||||
|
c.App().Content.ShowPage(suspendDialogKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CronJob) makeSuspendForm(sel string, suspend bool) *tview.Form {
|
||||||
|
f := c.makeStyledForm()
|
||||||
|
action := "suspended"
|
||||||
|
if !suspend {
|
||||||
|
action ="unsuspended"
|
||||||
|
}
|
||||||
|
|
||||||
|
f.AddButton("OK", func() {
|
||||||
|
defer c.dismissDialog()
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), c.App().Conn().Config().CallTimeout())
|
||||||
|
defer cancel()
|
||||||
|
if err := c.setSuspend(ctx, sel, suspend); err != nil {
|
||||||
|
log.Error().Err(err).Msgf("CronJOb %s %s failed", sel, action)
|
||||||
|
c.App().Flash().Err(err)
|
||||||
|
} else {
|
||||||
|
c.App().Flash().Infof("CronJOb %s %s successfully", sel, action)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
f.AddButton("Cancel", func() {
|
||||||
|
c.dismissDialog()
|
||||||
|
})
|
||||||
|
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CronJob) setSuspend(ctx context.Context, path string, suspend bool) error {
|
||||||
|
res, err := dao.AccessorFor(c.App().factory, c.GVR())
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
cronJob, ok := res.(*dao.CronJob)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("expecting a scalable resource for %q", c.GVR())
|
||||||
|
}
|
||||||
|
|
||||||
|
return cronJob.SetSuspend(ctx, path, suspend)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CronJob) makeStyledForm() *tview.Form {
|
||||||
|
f := tview.NewForm()
|
||||||
|
f.SetItemPadding(0)
|
||||||
|
f.SetButtonsAlign(tview.AlignCenter).
|
||||||
|
SetButtonBackgroundColor(tview.Styles.PrimitiveBackgroundColor).
|
||||||
|
SetButtonTextColor(tview.Styles.PrimaryTextColor).
|
||||||
|
SetLabelColor(tcell.ColorAqua).
|
||||||
|
SetFieldTextColor(tcell.ColorOrange)
|
||||||
|
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CronJob) dismissDialog() {
|
||||||
|
c.App().Content.RemovePage(suspendDialogKey)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *CronJob) trigger(evt *tcell.EventKey) *tcell.EventKey {
|
func (c *CronJob) trigger(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
sel := c.GetTable().GetSelectedItem()
|
sel := c.GetTable().GetSelectedItem()
|
||||||
if sel == "" {
|
if sel == "" {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue