-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Create and Duplicate Resource actions #2563
Open
nobbs
wants to merge
6
commits into
derailed:master
Choose a base branch
from
nobbs:feat/resource-creation
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
bb1592a
fix: editor from env vars failed with arguments
nobbs 1ae6108
feat: implement "Create" and "Duplicate" actions
nobbs 1d511fd
fix: dump tmp file into screen dump dir
nobbs b21744e
test: forgot to use fake lookPath in exec_tests
nobbs 19d13a3
docs: add create and duplicate actions
0ba3bd2
chore: update helper messages
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
<img src="assets/k9s.png" alt="k9s"> | ||
|
||
## K9s - Kubernetes CLI To Manage Your Clusters In Style! | ||
## K9s - Kubernetes CLI To Manage Your Clusters In Style | ||
|
||
K9s provides a terminal UI to interact with your Kubernetes clusters. | ||
The aim of this project is to make it easier to navigate, observe and manage | ||
|
@@ -9,7 +9,7 @@ for changes and offers subsequent commands to interact with your observed resour | |
|
||
--- | ||
|
||
## Note... | ||
## Note | ||
|
||
K9s is not pimped out by a big corporation with deep pockets. | ||
It is a complex OSS project that demands a lot of my time to maintain and support. | ||
|
@@ -356,8 +356,10 @@ K9s uses aliases to navigate most K8s resources. | |
| To view and switch directly to another Kubernetes context (Last used view) | `:`ctx context-name⏎ | | | ||
| To view and switch to another Kubernetes namespace | `:`ns⏎ | | | ||
| To view all saved resources | `:`screendump or sd⏎ | | | ||
| To launch a new editor to create a new resource | `ctrl-n` | | | ||
| To delete a resource (TAB and ENTER to confirm) | `ctrl-d` | | | ||
| To kill a resource (no confirmation dialog, equivalent to kubectl delete --now) | `ctrl-k` | | | ||
| To duplicate a resource | `shift-d` | Only in YAML view, opens a new editor with the current resource | | ||
| Launch pulses view | `:`pulses or pu⏎ | | | ||
| Launch XRay view | `:`xray RESOURCE [NAMESPACE]⏎ | RESOURCE can be one of po, svc, dp, rs, sts, ds, NAMESPACE is optional | | ||
| Launch Popeye view | `:`popeye or pop⏎ | See [popeye](#popeye) | | ||
|
@@ -1056,18 +1058,18 @@ K9s will most likely blow up if... | |
|
||
--- | ||
|
||
## ATTA Girls/Boys! | ||
## ATTA Girls/Boys | ||
|
||
K9s sits on top of many open source projects and libraries. Our *sincere* | ||
appreciations to all the OSS contributors that work nights and weekends | ||
to make this project a reality! | ||
|
||
--- | ||
|
||
## Meet The Core Team! | ||
## Meet The Core Team | ||
|
||
* [Fernand Galiana](https://github.com/derailed) | ||
* <img src="assets/mail.png" width="16" height="auto" alt="email"/> [email protected] | ||
* <img src="assets/mail.png" width="16" height="auto" alt="email"/> <[email protected]> | ||
* <img src="assets/twitter.png" width="16" height="auto" alt="twitter"/> [@kitesurfer](https://twitter.com/kitesurfer?lang=en) | ||
|
||
* [Aleksei Romanenko](https://github.com/slimus) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,9 @@ package view | |
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"os" | ||
"sort" | ||
"strconv" | ||
"strings" | ||
|
@@ -14,6 +16,7 @@ import ( | |
|
||
"github.com/derailed/k9s/internal" | ||
"github.com/derailed/k9s/internal/client" | ||
"github.com/derailed/k9s/internal/config" | ||
"github.com/derailed/k9s/internal/config/data" | ||
"github.com/derailed/k9s/internal/dao" | ||
"github.com/derailed/k9s/internal/model" | ||
|
@@ -305,6 +308,31 @@ func (b *Browser) TableLoadFailed(err error) { | |
// ---------------------------------------------------------------------------- | ||
// Actions... | ||
|
||
func (b *Browser) createCmd(_ *tcell.EventKey) *tcell.EventKey { | ||
tmpFile, err := createTmpYaml() | ||
if err != nil { | ||
b.App().Flash().Err(errors.New("Failed to create temporary resource file: " + err.Error())) | ||
return nil | ||
} | ||
defer os.Remove(tmpFile.Name()) | ||
defer tmpFile.Close() | ||
|
||
_, err = tmpFile.WriteString(strings.Join([]string{ | ||
"# Please add your resource definitions below. Lines beginning with a '#' will be ignored.", | ||
"# Multiple resources are supported and can be separated by '---'.", | ||
"# When done, save and close the editor, K9s will then `kubectl create` the resource.", | ||
fmt.Sprintf("# The content will also be saved in '%s'", b.App().Config.K9s.ContextScreenDumpDir()), | ||
"# in case you need to recover it.", | ||
"#", | ||
}, "\n")) | ||
if err != nil { | ||
b.App().Flash().Err(errors.New("Failed to write to temporary resource file: " + err.Error())) | ||
return nil | ||
} | ||
|
||
return editAndCreateFromFile(b.App(), tmpFile.Name()) | ||
} | ||
|
||
func (b *Browser) viewCmd(evt *tcell.EventKey) *tcell.EventKey { | ||
path := b.GetSelectedItem() | ||
if path == "" { | ||
|
@@ -558,6 +586,10 @@ func (b *Browser) refreshActions() { | |
if !dao.IsK9sMeta(b.meta) { | ||
aa.Add(ui.KeyY, ui.NewKeyAction(yamlAction, b.viewCmd, true)) | ||
aa.Add(ui.KeyD, ui.NewKeyAction("Describe", b.describeCmd, true)) | ||
|
||
if !b.app.Config.K9s.IsReadOnly() { | ||
aa.Add(tcell.KeyCtrlN, ui.NewKeyAction("Create", b.createCmd, true)) | ||
} | ||
} | ||
for _, f := range b.bindKeysFn { | ||
f(aa) | ||
|
@@ -644,3 +676,80 @@ func (b *Browser) resourceDelete(selections []string, msg string) { | |
} | ||
dialog.ShowDelete(b.app.Styles.Dialog(), b.app.Content.Pages, msg, okFn, func() {}) | ||
} | ||
|
||
func editAndCreateFromFile(app *App, filePath string) *tcell.EventKey { | ||
if !edit(app, shellOpts{clear: true, args: []string{filePath}}) { | ||
app.Flash().Errf("Failed to launch editor") | ||
return nil | ||
} | ||
|
||
if isEmpty, err := isFileEmpty(filePath); err != nil || isEmpty { | ||
if err != nil { | ||
app.Flash().Err(err) | ||
} | ||
return nil | ||
} | ||
|
||
content, err := os.ReadFile(filePath) | ||
if err != nil { | ||
app.Flash().Errf("Failed to create resource from file %s", err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are reading the file at this stage. The error should reflect that |
||
return nil | ||
} | ||
|
||
dumpedFile, err := saveYAML(app.Config.K9s.ContextScreenDumpDir(), "create", string(content)) | ||
if err != nil { | ||
app.Flash().Err(err) | ||
return nil | ||
} | ||
|
||
return createFromFile(app, dumpedFile) | ||
} | ||
|
||
func isFileEmpty(filePath string) (bool, error) { | ||
fileStat, err := os.Stat(filePath) | ||
if err != nil { | ||
return false, errors.New("Failed to get temporary resource file information: " + err.Error()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer error wrapping as mentioned above |
||
} | ||
|
||
return fileStat.Size() == 0, nil | ||
} | ||
|
||
func createFromFile(app *App, filePath string) *tcell.EventKey { | ||
args := []string{ | ||
"create", | ||
"-f", | ||
filePath, | ||
} | ||
res, err := runKu(app, shellOpts{clear: false, args: args}) | ||
if err != nil { | ||
res = "status:\n " + err.Error() + "\nmessage:\n" + fmtResults(res) | ||
} else { | ||
res = "message:\n" + fmtResults(res) | ||
} | ||
|
||
details := NewDetails(app, "Applied Manifest", filePath, contentYAML, true).Update(res) | ||
if err := app.inject(details, false); err != nil { | ||
app.Flash().Err(err) | ||
return nil | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func createTmpYaml() (*os.File, error) { | ||
tmpDir, err := config.UserTmpDir() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if err := ensureDir(tmpDir); err != nil { | ||
return nil, err | ||
} | ||
|
||
tmpFile, err := os.CreateTemp(tmpDir, "tmp--*.yml") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return tmpFile, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package view | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
var fakeLookPath = func(file string) (string, error) { | ||
return fmt.Sprintf("/usr/bin/%s", file), nil | ||
} | ||
|
||
func TestFindEditor(t *testing.T) { | ||
lookPath = fakeLookPath | ||
|
||
type result struct { | ||
binary string | ||
args []string | ||
} | ||
|
||
uu := map[string]struct { | ||
env map[string]string | ||
e result | ||
err bool | ||
}{ | ||
"no-editor": { | ||
env: map[string]string{}, | ||
e: result{binary: "", args: nil}, | ||
err: true, | ||
}, | ||
"vi-by-EDITOR": { | ||
env: map[string]string{"EDITOR": "vi"}, | ||
e: result{binary: "vi", args: nil}, | ||
}, | ||
"vim-with-args-by-EDITOR": { | ||
env: map[string]string{"EDITOR": "vim --wait --some=thing"}, | ||
e: result{binary: "vim", args: []string{"--wait", "--some=thing"}}, | ||
}, | ||
"code-with-args-by-KUBE_EDITOR": { | ||
env: map[string]string{"KUBE_EDITOR": "code -w"}, | ||
e: result{binary: "code", args: []string{"-w"}}, | ||
}, | ||
"code-with-args-by-K9S-EDITOR": { | ||
env: map[string]string{"K9S_EDITOR": "code --wait"}, | ||
e: result{binary: "code", args: []string{"--wait"}}, | ||
}, | ||
} | ||
|
||
for k := range uu { | ||
u := uu[k] | ||
t.Run(k, func(t *testing.T) { | ||
opts := shellOpts{} | ||
|
||
for _, v := range editorEnvVars { | ||
if _, ok := u.env[v]; !ok { | ||
t.Setenv(v, "") | ||
} | ||
} | ||
|
||
for k, v := range u.env { | ||
t.Setenv(k, v) | ||
} | ||
|
||
got, err := findEditor(opts) | ||
assert.Equal(t, u.err, err != nil) | ||
assert.Contains(t, got.binary, u.e.binary) | ||
assert.Equal(t, u.e.args, got.args) | ||
}) | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Errors in go should not be capitalized. Also prefer wrapping the error ie fmt.Errorf("failed ...: %w", err)
Please follow similar logic for here down.