mirror of
https://github.com/ahmetb/kubectx.git
synced 2026-03-15 18:32:12 +00:00
Compare commits
3 Commits
dependabot
...
claude/kub
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b0e4de615 | ||
|
|
f1283e7ebc | ||
|
|
c57909e31a |
2
.github/workflows/bash-frozen.yml
vendored
2
.github/workflows/bash-frozen.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
steps:
|
||||
- name: Comment on PR if author is not ahmetb
|
||||
if: github.event.pull_request.user.login != 'ahmetb'
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const body = [
|
||||
|
||||
@@ -38,7 +38,7 @@ func parseArgs(argv []string) Op {
|
||||
|
||||
if n == 0 {
|
||||
if cmdutil.IsInteractiveMode(os.Stdout) {
|
||||
return InteractiveSwitchOp{SelfCmd: os.Args[0]}
|
||||
return InteractiveSwitchOp{}
|
||||
}
|
||||
return ListOp{}
|
||||
}
|
||||
|
||||
@@ -16,26 +16,23 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ahmetb/kubectx/internal/cmdutil"
|
||||
"github.com/ahmetb/kubectx/internal/env"
|
||||
"github.com/ahmetb/kubectx/internal/kubeconfig"
|
||||
"github.com/ahmetb/kubectx/internal/printer"
|
||||
)
|
||||
|
||||
type InteractiveSwitchOp struct {
|
||||
SelfCmd string
|
||||
}
|
||||
type InteractiveSwitchOp struct{}
|
||||
|
||||
// TODO(ahmetb) This method is heavily repetitive vs kubectx/fzf.go.
|
||||
func (op InteractiveSwitchOp) Run(_, stderr io.Writer) error {
|
||||
// parse kubeconfig just to see if it can be loaded
|
||||
kc := new(kubeconfig.Kubeconfig).WithLoader(kubeconfig.DefaultLoader)
|
||||
defer kc.Close()
|
||||
if err := kc.Parse(); err != nil {
|
||||
@@ -46,23 +43,48 @@ func (op InteractiveSwitchOp) Run(_, stderr io.Writer) error {
|
||||
return fmt.Errorf("kubeconfig error: %w", err)
|
||||
}
|
||||
|
||||
ctxNames, err := kc.ContextNames()
|
||||
ctx, err := kc.GetCurrentContext()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get context names: %w", err)
|
||||
return fmt.Errorf("failed to get current context: %w", err)
|
||||
}
|
||||
if len(ctxNames) == 0 {
|
||||
return errors.New("no contexts found in the kubeconfig file")
|
||||
if ctx == "" {
|
||||
return errors.New("current-context is not set")
|
||||
}
|
||||
curNs, err := kc.NamespaceOfContext(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot read current namespace: %w", err)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
go func() {
|
||||
select {
|
||||
case <-time.After(3 * time.Second):
|
||||
printer.Warning(stderr, `listing namespaces is taking long, switch to a namespace directly with "kubens -f <ns>"`)
|
||||
case <-ctx.Done():
|
||||
}
|
||||
}()
|
||||
|
||||
ns, err := queryNamespaces(ctx, kc)
|
||||
cancel()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not list namespaces (is the cluster accessible?): %w", err)
|
||||
}
|
||||
|
||||
var input bytes.Buffer
|
||||
for _, c := range ns {
|
||||
s := c
|
||||
if c == curNs {
|
||||
s = printer.ActiveItemColor.Sprint(c)
|
||||
}
|
||||
fmt.Fprintf(&input, "%s\n", s)
|
||||
}
|
||||
|
||||
cmd := exec.Command("fzf", "--ansi", "--no-preview")
|
||||
var out bytes.Buffer
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdin = &input
|
||||
cmd.Stderr = stderr
|
||||
var out bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
|
||||
cmd.Env = append(os.Environ(),
|
||||
fmt.Sprintf("FZF_DEFAULT_COMMAND=%s", op.SelfCmd),
|
||||
fmt.Sprintf("%s=1", env.EnvForceColor))
|
||||
if err := cmd.Run(); err != nil {
|
||||
var exitErr *exec.ExitError
|
||||
if !errors.As(err, &exitErr) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
@@ -52,7 +53,17 @@ func (op ListOp) Run(stdout, stderr io.Writer) error {
|
||||
return fmt.Errorf("cannot read current namespace: %w", err)
|
||||
}
|
||||
|
||||
ns, err := queryNamespaces(kc)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
go func() {
|
||||
select {
|
||||
case <-time.After(3 * time.Second):
|
||||
printer.Warning(stderr, `listing namespaces is taking long, switch to a namespace directly with "kubens -f <ns>"`)
|
||||
case <-ctx.Done():
|
||||
}
|
||||
}()
|
||||
|
||||
ns, err := queryNamespaces(ctx, kc)
|
||||
cancel()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not list namespaces (is the cluster accessible?): %w", err)
|
||||
}
|
||||
@@ -67,7 +78,7 @@ func (op ListOp) Run(stdout, stderr io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func queryNamespaces(kc *kubeconfig.Kubeconfig) ([]string, error) {
|
||||
func queryNamespaces(ctx context.Context, kc *kubeconfig.Kubeconfig) ([]string, error) {
|
||||
if os.Getenv("_MOCK_NAMESPACES") != "" {
|
||||
return []string{"ns1", "ns2"}, nil
|
||||
}
|
||||
@@ -81,7 +92,7 @@ func queryNamespaces(kc *kubeconfig.Kubeconfig) ([]string, error) {
|
||||
var next string
|
||||
for {
|
||||
list, err := clientset.CoreV1().Namespaces().List(
|
||||
context.Background(),
|
||||
ctx,
|
||||
metav1.ListOptions{
|
||||
Limit: 500,
|
||||
Continue: next,
|
||||
|
||||
Reference in New Issue
Block a user