mirror of
https://github.com/skoelle/kctl-tui.git
synced 2026-09-17 20:10:24 +00:00
Rework kubeexec to take explicit --context per call instead of mutating global kubectl state; drop functions superseded by config templates
This commit is contained in:
@@ -2,6 +2,12 @@
|
||||
// All functions here have side effects (they run external processes) and
|
||||
// are therefore not covered by unit tests; the pure logic they depend on
|
||||
// lives in the kctl package instead.
|
||||
//
|
||||
// Every kubectl-related function takes an explicit context argument
|
||||
// (passed as --context) instead of relying on/mutating the globally
|
||||
// active kubectl context. This lets the panel act on multiple resolved
|
||||
// contexts (e.g. beta and prod) without switching global state back and
|
||||
// forth.
|
||||
package kubeexec
|
||||
|
||||
import (
|
||||
@@ -21,45 +27,12 @@ func runOutput(name string, args ...string) (string, error) {
|
||||
return strings.TrimSpace(string(out)), nil
|
||||
}
|
||||
|
||||
// GetContexts returns all configured kubectl context names.
|
||||
func GetContexts() ([]string, error) {
|
||||
out, err := runOutput("kubectl", "config", "get-contexts", "-o", "name")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// kubectlArgs prepends a --context flag when context is non-empty.
|
||||
func kubectlArgs(context string, args ...string) []string {
|
||||
if context == "" {
|
||||
return args
|
||||
}
|
||||
if out == "" {
|
||||
return []string{}, nil
|
||||
}
|
||||
return strings.Split(out, "\n"), nil
|
||||
}
|
||||
|
||||
// GetCurrentContext returns the currently active kubectl context, or an
|
||||
// empty string if none is set.
|
||||
func GetCurrentContext() string {
|
||||
out, _ := runOutput("kubectl", "config", "current-context")
|
||||
return out
|
||||
}
|
||||
|
||||
// GetCurrentNamespace returns the namespace bound to the current context,
|
||||
// defaulting to "default" if unset.
|
||||
func GetCurrentNamespace() string {
|
||||
out, _ := runOutput("kubectl", "config", "view", "--minify", "-o", "jsonpath={..namespace}")
|
||||
if out == "" {
|
||||
return "default"
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// UseContext switches the active kubectl context.
|
||||
func UseContext(ctx string) error {
|
||||
_, err := runOutput("kubectl", "config", "use-context", ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// SetNamespace binds a namespace to the current kubectl context.
|
||||
func SetNamespace(ns string) error {
|
||||
_, err := runOutput("kubectl", "config", "set-context", "--current", "--namespace="+ns)
|
||||
return err
|
||||
return append([]string{"--context", context}, args...)
|
||||
}
|
||||
|
||||
type nsItem struct {
|
||||
@@ -74,9 +47,10 @@ type nsList struct {
|
||||
}
|
||||
|
||||
// GetNamespacesWithLabels returns a map of namespace name -> labels for all
|
||||
// namespaces visible in the current context.
|
||||
func GetNamespacesWithLabels() (map[string]map[string]string, error) {
|
||||
out, err := runOutput("kubectl", "get", "ns", "-o", "json")
|
||||
// namespaces visible in the given context.
|
||||
func GetNamespacesWithLabels(context string) (map[string]map[string]string, error) {
|
||||
args := kubectlArgs(context, "get", "ns", "-o", "json")
|
||||
out, err := runOutput("kubectl", args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -91,10 +65,11 @@ func GetNamespacesWithLabels() (map[string]map[string]string, error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetDeployments lists deployment names in the given namespace.
|
||||
func GetDeployments(namespace string) ([]string, error) {
|
||||
out, err := runOutput("kubectl", "-n", namespace, "get", "deploy",
|
||||
// GetDeployments lists deployment names in the given context/namespace.
|
||||
func GetDeployments(context, namespace string) ([]string, error) {
|
||||
args := kubectlArgs(context, "-n", namespace, "get", "deploy",
|
||||
"-o", `jsonpath={range .items[*]}{.metadata.name}{"\n"}{end}`)
|
||||
out, err := runOutput("kubectl", args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -105,26 +80,22 @@ func GetDeployments(namespace string) ([]string, error) {
|
||||
}
|
||||
|
||||
// RolloutRestart triggers a rolling restart of a deployment.
|
||||
func RolloutRestart(namespace, deployment string) (string, error) {
|
||||
return runOutput("kubectl", "-n", namespace, "rollout", "restart", "deploy/"+deployment)
|
||||
func RolloutRestart(context, namespace, deployment string) (string, error) {
|
||||
args := kubectlArgs(context, "-n", namespace, "rollout", "restart", "deploy/"+deployment)
|
||||
return runOutput("kubectl", args...)
|
||||
}
|
||||
|
||||
// RolloutStatus waits for and returns the rollout status of a deployment.
|
||||
func RolloutStatus(namespace, deployment string) (string, error) {
|
||||
return runOutput("kubectl", "-n", namespace, "rollout", "status", "deploy/"+deployment)
|
||||
}
|
||||
|
||||
// GetSecretValueBase64 returns the raw (still base64-encoded) value of a
|
||||
// single field in a Kubernetes secret.
|
||||
func GetSecretValueBase64(namespace, secretName, field string) (string, error) {
|
||||
path := fmt.Sprintf("jsonpath={.data.%s}", field)
|
||||
return runOutput("kubectl", "-n", namespace, "get", "secret", secretName, "-o", path)
|
||||
func RolloutStatus(context, namespace, deployment string) (string, error) {
|
||||
args := kubectlArgs(context, "-n", namespace, "rollout", "status", "deploy/"+deployment)
|
||||
return runOutput("kubectl", args...)
|
||||
}
|
||||
|
||||
// GetSecretAllFields returns all fields of a Kubernetes secret, already
|
||||
// base64-decoded into plain values.
|
||||
func GetSecretAllFields(namespace, secretName string) (map[string]string, error) {
|
||||
out, err := runOutput("kubectl", "-n", namespace, "get", "secret", secretName, "-o", "json")
|
||||
func GetSecretAllFields(context, namespace, secretName string) (map[string]string, error) {
|
||||
args := kubectlArgs(context, "-n", namespace, "get", "secret", secretName, "-o", "json")
|
||||
out, err := runOutput("kubectl", args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -156,29 +127,16 @@ func DecodeBase64(value string) (string, error) {
|
||||
|
||||
// AnnotateForceSync sets the force-sync annotation on an ExternalSecret
|
||||
// object to trigger an immediate re-sync from the upstream secret store.
|
||||
func AnnotateForceSync(namespace, externalSecretName string, unixTimestamp int64) (string, error) {
|
||||
func AnnotateForceSync(context, namespace, externalSecretName string, unixTimestamp int64) (string, error) {
|
||||
annotation := fmt.Sprintf("force-sync=%d", unixTimestamp)
|
||||
return runOutput("kubectl", "-n", namespace, "annotate", "externalsecret",
|
||||
args := kubectlArgs(context, "-n", namespace, "annotate", "externalsecret",
|
||||
externalSecretName, annotation, "--overwrite")
|
||||
}
|
||||
|
||||
// ListAWSSecrets returns all AWS Secrets Manager secret names/IDs visible
|
||||
// in the given region (subject to the caller's IAM permissions).
|
||||
func ListAWSSecrets(region string) ([]string, error) {
|
||||
out, err := runOutput("aws", "secretsmanager", "list-secrets",
|
||||
"--region", region, "--query", "SecretList[].Name", "--output", "json")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var names []string
|
||||
if err := json.Unmarshal([]byte(out), &names); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return names, nil
|
||||
return runOutput("kubectl", args...)
|
||||
}
|
||||
|
||||
// GetAWSSecretString fetches the SecretString of an AWS Secrets Manager
|
||||
// secret via the aws-cli.
|
||||
// secret via the aws-cli. The secret ID is computed from config templates
|
||||
// (see internal/config), not looked up interactively.
|
||||
func GetAWSSecretString(secretID, region string) (string, error) {
|
||||
return runOutput("aws", "secretsmanager", "get-secret-value",
|
||||
"--secret-id", secretID, "--region", region,
|
||||
|
||||
Reference in New Issue
Block a user