Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(delete/node): challenge deletion by text phrase #2248

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,8 @@ K9s uses aliases to navigate most K8s resources.
memory: 100Mi
# Enable TTY
tty: true
# When enabled adds extra input field in which you have to confirm the deletion of a node
idiotLight: false
```

---
Expand Down
7 changes: 7 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,13 @@ func initK9sFlags() {
"",
"Sets a path to a dir for a screen dumps",
)
rootCmd.Flags().BoolVar(
k9sFlags.IdiotLight,
"idiot-light",
false,
"Enable idiot light to warn the user for potentially destructive operations, e.g., delete a node",
)

rootCmd.Flags()
}

Expand Down
2 changes: 2 additions & 0 deletions internal/config/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type Flags struct {
Write *bool
Crumbsless *bool
ScreenDumpDir *string
IdiotLight *bool
}

// NewFlags returns new configuration flags.
Expand All @@ -43,6 +44,7 @@ func NewFlags() *Flags {
Write: boolPtr(false),
Crumbsless: boolPtr(false),
ScreenDumpDir: strPtr(AppDumpsDir),
IdiotLight: boolPtr(false),
}
}

Expand Down
14 changes: 14 additions & 0 deletions internal/config/k9s.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@ type K9s struct {
ImageScans ImageScans `json:"imageScans" yaml:"imageScans"`
Logger Logger `json:"logger" yaml:"logger"`
Thresholds Threshold `json:"thresholds" yaml:"thresholds"`
IdiotLight bool `json:"idiotLight" yaml:"idiotLight"`
manualRefreshRate int
manualHeadless *bool
manualLogoless *bool
manualCrumbsless *bool
manualReadOnly *bool
manualIdiotLight *bool
manualCommand *string
manualScreenDumpDir *string
dir *data.Dir
Expand Down Expand Up @@ -99,6 +101,7 @@ func (k *K9s) Merge(k1 *K9s) {
k.ShellPod = k1.ShellPod
k.Logger = k1.Logger
k.ImageScans = k1.ImageScans
k.IdiotLight = k1.IdiotLight
if k1.Thresholds != nil {
k.Thresholds = k1.Thresholds
}
Expand Down Expand Up @@ -249,9 +252,11 @@ func (k *K9s) Override(k9sFlags *Flags) {

k.manualHeadless = k9sFlags.Headless
k.manualLogoless = k9sFlags.Logoless
k.manualIdiotLight = k9sFlags.IdiotLight
k.manualCrumbsless = k9sFlags.Crumbsless
if k9sFlags.ReadOnly != nil && *k9sFlags.ReadOnly {
k.manualReadOnly = k9sFlags.ReadOnly

}
if k9sFlags.Write != nil && *k9sFlags.Write {
var false bool
Expand Down Expand Up @@ -310,6 +315,15 @@ func (k *K9s) IsReadOnly() bool {
return ro
}

func (k *K9s) HasIdiotLight() bool {
idiotLight := k.IdiotLight
if k.manualIdiotLight != nil {
idiotLight = *k.manualIdiotLight
}

return idiotLight
}

// Validate the current configuration.
func (k *K9s) Validate(c client.Connection, ks data.KubeSettings) {
if k.RefreshRate <= 0 {
Expand Down
18 changes: 17 additions & 1 deletion internal/ui/dialog/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
package dialog

import (
"fmt"

"github.com/derailed/k9s/internal/config"
"github.com/derailed/k9s/internal/ui"
"github.com/derailed/tview"
Expand All @@ -28,7 +30,7 @@ var propagationOptions []string = []string{
}

// ShowDelete pops a resource deletion dialog.
func ShowDelete(styles config.Dialog, pages *ui.Pages, msg string, ok okFunc, cancel cancelFunc) {
func ShowDelete(styles config.Dialog, pages *ui.Pages, msg string, ok okFunc, cancel cancelFunc, challenge string) {
propagation, force := "", false
f := tview.NewForm()
f.SetItemPadding(0)
Expand All @@ -48,11 +50,25 @@ func ShowDelete(styles config.Dialog, pages *ui.Pages, msg string, ok okFunc, ca
f.AddCheckbox("Force:", force, func(_ string, checked bool) {
force = checked
})

confirmCheck := ""
if challenge != "" {
f.AddInputField(fmt.Sprintf("Confirm with: \"%s\":", challenge), confirmCheck, 30, nil, func(text string) {
confirmCheck = text
})
}

f.AddButton("Cancel", func() {
dismiss(pages)
cancel()
})

f.AddButton("OK", func() {
if challenge != "" && confirmCheck != challenge {
cancel()
return
}

switch propagation {
case noDeletePropagation:
ok(nil, force)
Expand Down
2 changes: 1 addition & 1 deletion internal/ui/dialog/delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestDeleteDialog(t *testing.T) {
caFunc := func() {
assert.True(t, true)
}
ShowDelete(config.Dialog{}, p, "Yo", okFunc, caFunc)
ShowDelete(config.Dialog{}, p, "Yo", okFunc, caFunc, "")

d := p.GetPrimitive(dialogKey).(*tview.ModalForm)
assert.NotNil(t, d)
Expand Down
12 changes: 9 additions & 3 deletions internal/view/browser.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,13 @@ func (b *Browser) deleteCmd(evt *tcell.EventKey) *tcell.EventKey {
b.simpleDelete(selections, msg)
return nil
}
b.resourceDelete(selections, msg)

challenge := ""
if b.App().Config.K9s.HasIdiotLight() && b.GVR().R() == "nodes" {
challenge = "delete!"
}

b.resourceDelete(selections, msg, challenge)
}

return nil
Expand Down Expand Up @@ -577,7 +583,7 @@ func (b *Browser) simpleDelete(selections []string, msg string) {
}, func() {})
}

func (b *Browser) resourceDelete(selections []string, msg string) {
func (b *Browser) resourceDelete(selections []string, msg string, challenge string) {
okFn := func(propagation *metav1.DeletionPropagation, force bool) {
b.ShowDeleted()
if len(selections) > 1 {
Expand All @@ -599,5 +605,5 @@ func (b *Browser) resourceDelete(selections []string, msg string) {
}
b.refresh()
}
dialog.ShowDelete(b.app.Styles.Dialog(), b.app.Content.Pages, msg, okFn, func() {})
dialog.ShowDelete(b.app.Styles.Dialog(), b.app.Content.Pages, msg, okFn, func() {}, challenge)
}
2 changes: 1 addition & 1 deletion internal/view/workload.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func (w *Workload) resourceDelete(selections []string, msg string) {
}
w.GetTable().Start()
}
dialog.ShowDelete(w.App().Styles.Dialog(), w.App().Content.Pages, msg, okFn, func() {})
dialog.ShowDelete(w.App().Styles.Dialog(), w.App().Content.Pages, msg, okFn, func() {}, "")
}

func (w *Workload) describeCmd(evt *tcell.EventKey) *tcell.EventKey {
Expand Down
2 changes: 1 addition & 1 deletion internal/view/xray.go
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ func (x *Xray) resourceDelete(gvr client.GVR, spec *xray.NodeSpec, msg string) {
x.app.factory.DeleteForwarder(spec.Path())
}
x.Refresh()
}, func() {})
}, func() {}, "")
}

// ----------------------------------------------------------------------------
Expand Down