75 Commits

Author SHA1 Message Date
Ahmet Alp Balkan
6f8704f966 Extract common shell logic into shellSession
Deduplicates code between ShellOp and ReadonlyShellOp by extracting
shared logic (context validation, kubeconfig extraction, temp file
management, shell spawning) into a shellSession struct.

Callers configure behavior via:
- printEntry/printExit callbacks for banner messages
- extraEnv for additional environment variables
- transformKubeconfig hook for kubeconfig transformation (e.g. proxy)

Also extracts fzfPickContext for shared interactive mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 11:45:50 -04:00
Ahmet Alp Balkan
c20f59254a Update help text for kubectx and kubens
- Add description strings from bash scripts to Go help output
- Add -r/--readonly usage lines to kubectx help
- Reorder help to show -s/-r flags more prominently
- Normalize flag separators to comma-space consistently

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 23:27:38 -04:00
Ahmet Alp Balkan
2b2a3bacce Add -r/--readonly flag for read-only shell mode
Introduces ReadonlyShellOp and InteractiveReadonlyShellOp that spawn
an isolated sub-shell routing kubectl traffic through the readonly
reverse proxy. The proxy blocks write operations while allowing reads.

- Extracts minimal kubeconfig, starts proxy, rewrites kubeconfig to
  point at proxy, spawns shell with KUBECTX_READONLY_SHELL=1
- Proxy and temp files cleaned up on shell exit
- Flag parsing mirrors -s/--shell pattern with optional context arg
- Interactive fzf mode supported when no context specified

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 23:27:32 -04:00
Ahmet Alp Balkan
2cb7500e34 Support interactive fzf selection for kubectx -s with no arguments
When `kubectx -s` (or `--shell`) is invoked without a context name and
fzf is available in an interactive terminal, launch fzf to let the user
pick a context, then start an isolated shell scoped to that selection.

This mirrors the existing behavior where `kubectx` with no arguments
launches fzf for context switching, and `kubectx -d` with no arguments
launches fzf for context deletion.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 16:28:25 -07:00
Ahmet Alp Balkan
e4727d38f8 Fix relative path resolution in exec credential plugins (#490)
When kubens needs to query the Kubernetes API (e.g. to check if a
namespace exists), it builds a REST client from the in-memory
kubeconfig bytes using clientcmd.RESTConfigFromKubeConfig(). This
function has no knowledge of the kubeconfig file's location on disk,
so it cannot resolve relative paths in exec credential plugin commands
(e.g. `command: ../scripts/get-token.sh`). This causes a "no such file
or directory" error for users whose kubeconfig uses relative paths in
exec-based authentication.

The fix threads the kubeconfig file path through a new PathHinter
optional interface on ReadWriteResetCloser. When a file path is
available, newKubernetesClientSet now uses
clientcmd.NewNonInteractiveDeferredLoadingClientConfig with
ExplicitPath, which resolves relative paths relative to the kubeconfig
file's directory — matching kubectl's own behavior. The old
bytes-based fallback is preserved for in-memory configs (e.g. tests).

Fixes #488

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 10:18:48 -07:00
Ahmet Alp Balkan
f500964e24 fix: skip fzf launch in kubens when no contexts exist in kubeconfig (#481)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 07:30:21 +00:00
Ahmet Alp Balkan
039f5ed1ef fix: skip fzf launch when no contexts exist in kubeconfig (#480)
Return an error early in InteractiveSwitchOp if the kubeconfig has no
contexts, instead of launching fzf with an empty list.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 06:54:27 +00:00
Ahmet Alp Balkan
81defc835f refactor: replace testutil.WithEnvVar with t.Setenv (#479)
t.Setenv is the modern standard Go testing utility (since Go 1.17) that automatically restores environment variables when the test completes. This replaces the custom testutil.WithEnvVar function which manually saved and restored env var state.

The testutil.go file is deleted as it only contained WithEnvVar. The testutil package remains for its other utilities like KubeconfigBuilder.
2026-03-08 20:26:40 -07:00
Ahmet Alp Balkan
d3576731a0 feat: add XDG_CACHE_HOME support to Go implementations (#478)
Adds a new CacheDir() function that respects the XDG_CACHE_HOME environment variable,
matching the bash scripts' behavior. kubectx and kubens now prefer XDG_CACHE_HOME when
set, falling back to $HOME/.kube otherwise. This aligns the Go implementations with
the bash scripts' cache directory logic.

Includes comprehensive tests covering all scenarios:
- XDG_CACHE_HOME set (returns the XDG value)
- XDG_CACHE_HOME unset (falls back to $HOME/.kube)
- Neither set (returns empty string)
2026-03-08 20:19:35 -07:00
Ahmet Alp Balkan
0d800e1367 fix: improve error handling and resource management in kubeconfig (#476)
This change addresses eight key improvements to the kubectx/kubens codebase:

Resource Management Fixes:
- Fix use-after-close bugs where Kubeconfig was accessed after Close()
- Fix resource leaks on error paths by ensuring defer kc.Close() is called
- Fix YAML encoder not being closed after Encode(), causing buffered data loss

API Design Improvements:
- Change ContextNames() to return ([]string, error) instead of silently returning
  nil on error, making parse failures distinguishable from empty results
- Change GetCurrentContext() to return (string, error) instead of returning ""
  for both "not set" and parse error cases
- Update all 16 call sites across cmd/kubectx and cmd/kubens packages to handle
  the new error returns while preserving backward-compatible behavior

Error Handling:
- Add explicit error handling for printer.Success() calls in 5+ locations
  by prefixing unchecked calls with _ =

Performance:
- Add slice pre-allocation in namespace list pagination using slices.Grow()
  before append loops, reducing allocations when fetching 500+ item batches

All changes maintain backward compatibility for missing kubeconfig keys while
improving error transparency and resource safety.
2026-03-08 17:44:18 -07:00
Ahmet Alp Balkan
860e09775b refactor: modernize Go codebase for Go 1.25 (#473)
Modernize the codebase to use idiomatic Go 1.25 patterns, removing deprecated APIs and reducing external dependencies.

- Replace deprecated `io/ioutil` with `os.ReadFile`, `os.WriteFile`, `os.MkdirTemp`, `os.CreateTemp`
- Replace `interface{}` with `any` (Go 1.18+)
- Remove `github.com/pkg/errors` dependency entirely, using stdlib `fmt.Errorf` with `%w` and `errors.New`
- Use `errors.As()` instead of direct type assertions on error values
- Use `strings.Cut()` for delimiter parsing instead of `strings.Split` + length check
- Use `slices.Contains()` for linear search in `ContextExists()`
- Use `t.Setenv()` and `t.TempDir()` in tests instead of manual env save/restore and temp dir cleanup
- Delete unused `internal/testutil/tempfile.go` helper
- Update GitHub Actions CI and release workflows from Go 1.22 to 1.25

Net result: -70 lines, 1 fewer external dependency.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 17:07:59 -07:00
Joffrey Mischler
c13bf5a18b feat(kubens): add unset option (#440)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Ahmet Alp Balkan <ahmet@linkedin.com>
2026-03-08 16:19:49 -07:00
Ahmet Alp Balkan
4c9e8fb81e feat: add -s/--shell flag for scoped sub-shell (#461)
Spawns an isolated sub-shell with a minimal kubeconfig containing only the specified context.

This allows the user to launch a shell where they can only interact with a single cluster without having to worry about a command or an LLM agent interacting with other contexts.

Inside the isolated shell, most context switching/editing operations on kubectx are blocked. Nested shells not allowed.

Fixes #12.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 14:48:03 -07:00
Antoine
0bcd0d5dd5 fix some ci enhancement (#435)
* fix(release): customize goreleaser config file, by adding json schema and fixing configuration version

* fix(go): rename invalid comment format

* fix(ci): made release workflow work again

replace goreleaser --rm-dist flag by --clean
increment go version for release pipeline
fetch previous tags use by goreleaser
give release workflow content write permissions to publish release
2025-01-07 12:25:01 -08:00
Suleiman Dibirov
b5daf2cef7 feat(kubens): added force flag to switch namespaces even if it doesn'… (#416)
* feat(kubens): added force flag to switch namespaces even if it doesn't exist

* Merged lines

* fixed README.md and flags.go

* updated flags.go, flags_test.go
2024-07-09 21:38:40 -07:00
pullmerge
4997a261dc Fix some comments (#418) 2024-04-15 09:31:07 -07:00
Yankee
58a5c4693e Add interactive delete op (#304) 2021-07-07 11:48:32 -07:00
Ahmet Alp Balkan
34e9024835 add -V/--version flag to go implementations (#295)
Uses goreleaser to pass ldflags.

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2021-04-09 09:43:48 -07:00
Andrey Viktorov
9b4aea3b59 Bump up go-client to fix auth plugin panic (#281) 2021-02-02 15:38:27 -08:00
Jeff MAURY
767218a9a6 Check correct variable after current namespace retrieval (#287) 2021-01-31 17:48:35 -08:00
Ahmet Alp Balkan
1e49c336fc Add license headers for 2021
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-12-29 13:38:42 -08:00
Jason Harmon
8c323c5653 Fix color in kubens success message when using fzf (#228) 2020-11-16 09:01:28 -08:00
Sedat Gökcen
1db00a20d9 Structural refactoring for multiple kubeconfig support (#219) 2020-06-02 13:04:13 -07:00
Ahmet Alp Balkan
170233bffd query namespace exists with GET Namespace (#236)
More efficient ns switches with kubens by querying only the namespace (instead
of listing all namespaces).

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-05-31 15:32:44 -07:00
Ahmet Alp Balkan
0141ee19d2 handle ctxs with ':' in the name for windows (#235)
For windows, if the ctx name for kubens state file
contains a colon ':' (EKS), we replace it with __ (both while reading/writing).

It doesn't break existing users (as it didn't work in the first place).

Other characters remain unhandled, hoping it won't happen again.

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-05-31 14:24:01 -07:00
Jason Harmon
401188fefd Fix color output on Windows (#220) 2020-05-15 15:26:00 -07:00
Ahmet Alp Balkan
956d5953c2 kubens: fix interactive switch messages
Fixes #209.

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-30 07:36:21 -07:00
Curro Rodriguez
f2021bb08b changed help in kubens, return had a typo (#210) 2020-04-30 07:34:06 -07:00
Ahmet Alp Balkan
7f3f0699b3 Extend CI workflow with gofmt
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 13:28:12 -07:00
Ahmet Alp Balkan
5348d7aa7e kubens add a short-circuit to bypass API call for tests
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:56 -07:00
Ahmet Alp Balkan
04689f571e ns list: increase page size to 500
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:56 -07:00
Ahmet Alp Balkan
1881107d55 Load namespaces using client-go
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:56 -07:00
Ahmet Alp Balkan
52bbf5c786 fix compile error
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:56 -07:00
Ahmet Alp Balkan
4bbe0fad79 deprecation msgs for KUBECTX_CURRENT_{BG,FG}COLOR
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:56 -07:00
Ahmet Alp Balkan
5b745727c3 Add interactive switching to kubens
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:56 -07:00
Ahmet Alp Balkan
2915103e3d kubens: implement namespace switching
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:56 -07:00
Ahmet Alp Balkan
6c3977d574 kubens: Add facility to store state file
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:56 -07:00
Ahmet Alp Balkan
de2867a622 Implement list (via exec kubectl), clearer color settings
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:56 -07:00
Ahmet Alp Balkan
c4252b5795 Move kubeconfig loader utils to cmdutil pkg
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:56 -07:00
Ahmet Alp Balkan
1982becb15 kubens: Start implementing stubs
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:56 -07:00
Ahmet Alp Balkan
62d8dad7d5 extract kubeconfig test utils to a type
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:56 -07:00
Ahmet Alp Balkan
68b842f39b do not fail on non-existing kubeconfig files
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:56 -07:00
Ahmet Alp Balkan
0e50f15393 Better success msgs, handle -d without args
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:56 -07:00
Ahmet Alp Balkan
f4f558004a Tidy up colors, help msgs, TODOs
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:56 -07:00
Ahmet Alp Balkan
7598c4d4dd Create printer pkg, fix color force enable/disable
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:56 -07:00
Ahmet Alp Balkan
bef0a4cca7 Move kubeconfig utility to a shared pkg
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:56 -07:00
Ahmet Alp Balkan
d5546f062d Extend test coverage
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:55 -07:00
Ahmet Alp Balkan
bf5b715798 Fix UnsupportedOp tests through custom comparer
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:55 -07:00
Ahmet Alp Balkan
a01db6ecde Re-introduce DEBUG env var stack traces
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:55 -07:00
Ahmet Alp Balkan
280fcec765 Update tests for homeDir and kubeconfigPath()
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2020-04-29 12:52:55 -07:00