From 3ea9435a707311a873537b58fd7a9f5ff2ce7e4b Mon Sep 17 00:00:00 2001 From: Eshel Yaron Date: Fri, 26 Jul 2024 15:57:50 +0200 Subject: [PATCH] New commands 'kubed{-transient}-exec' --- lisp/net/kubed-transient.el | 21 +++++++++++- lisp/net/kubed.el | 64 +++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/lisp/net/kubed-transient.el b/lisp/net/kubed-transient.el index cb91e3fa3b1..b7f23afbb62 100644 --- a/lisp/net/kubed-transient.el +++ b/lisp/net/kubed-transient.el @@ -63,7 +63,7 @@ ("!" "Command line" kubed-kubectl-command)] (interactive) (transient-setup 'kubed-transient-attach nil nil - :value '("--stdin") + :value '("--stdin" "--tty") :scope '("attach"))) ;;;###autoload @@ -81,6 +81,25 @@ (transient-setup 'kubed-transient-diff nil nil :scope '("diff"))) +;;;###autoload +(transient-define-prefix kubed-transient-exec () + "Execute command in Kubernetes pod." + ["Switches" + ("-i" "Open stdin" "--stdin") + ("-t" "Allocate TTY" "--tty")] + ["Options" + ("-n" "Namespace" "--namespace=" + :prompt "Namespace" :reader kubed-transient-read-namespace) + ("--" "Command" "-- =" + :prompt "Command: ")] + ["Actions" + ("x" "Execute" kubed-exec) + ("!" "Command line" kubed-kubectl-command)] + (interactive) + (transient-setup 'kubed-transient-exec nil nil + :value '("--stdin" "--tty") + :scope '("exec"))) + ;;;###autoload (transient-define-prefix kubed-transient-run () "Run container image in a Kubernetes pod." diff --git a/lisp/net/kubed.el b/lisp/net/kubed.el index 8c2e80cc4e3..838e9e84b58 100644 --- a/lisp/net/kubed.el +++ b/lisp/net/kubed.el @@ -846,6 +846,7 @@ Optional argument DEFAULT is the minibuffer default argument." resource) ((phase ".status.phase" 10) (starttime ".status.startTime" 20)) :prefix ("L" #'kubed-logs "A" #'kubed-attach + "X" #'kubed-exec "F" #'kubed-forward-port-to-pod) (dired "C-d" "Start Dired in home directory of first container of" (let ((ns (when k8sns (concat "%" k8sns)))) @@ -857,6 +858,11 @@ Optional argument DEFAULT is the minibuffer default argument." resource) (attach "a" "Attach to remote process running on" (kubed-attach pod (kubed-read-container pod "Container" t k8sns) k8sns t t)) + (exec "X" "Execute command in" + (let ((container (kubed-read-container pod "Container" t k8sns)) + (cmd-args (split-string-and-unquote + (read-string "Execute command: ")))) + (kubed-exec pod (car cmd-args) container k8sns t t (cdr cmd-args)))) (logs "l" "Show logs for a container of" (kubed-logs pod (kubed-read-container pod "Container" t k8sns))) (forward-port "F" "Forward local network port to remote port of" @@ -1464,6 +1470,64 @@ argument) says to include managed fields in the comparison." (goto-char (point-min))) (display-buffer buf))) +;;;###autoload +(defun kubed-exec (pod command &optional container namespace stdin tty args) + "Execute COMMAND with ARGS in CONTAINER in Kubernetes POD. + +Optional argument NAMESPACE is the namespace in which to look for POD. +Non-nil STDIN says to connect local standard input to remote process. +Non-nil TTY says to use a TTY for standard input. + +Interactively, prompt for POD; if there are multiple pod containers, +prompt for CONTAINER as well; STDIN is t unless you call this command +with \\[universal-argument] \\[universal-argument]; and TTY is t unless\ + you call this command with \\[universal-argument]." + (interactive + (let ((namespace nil) (stdin t) (tty t) (command nil) (args nil)) + (when (<= 4 (prefix-numeric-value current-prefix-arg)) (setq tty nil)) + (when (<= 16 (prefix-numeric-value current-prefix-arg)) (setq stdin nil)) + (dolist (arg (kubed-transient-args 'kubed-transient-exec)) + (cond + ((string-match "--namespace=\\(.+\\)" arg) + (setq namespace (match-string 1 arg))) + ((equal "--stdin" arg) (setq stdin t)) + ((equal "--tty" arg) (setq tty t)) + ((string-match "-- =\\(.+\\)" arg) + (setq args (split-string-and-unquote (match-string 1 arg)) + command (car args) + args (cdr args))))) + (if (and kubed-all-namespaces-mode (not namespace)) + (let* ((p-s (kubed-read-namespaced-pod "Execute command in pod")) + (p (car p-s)) + (s (cadr p-s)) + (c (kubed-read-container p "Container" t s))) + (unless command + (setq args (split-string-and-unquote + (read-string "Execute command: ")) + command (car args) + args (cdr args))) + (list p command c s stdin tty args)) + ;; FIXME: Similarly to `kubed-attach', when namespace is set from + ;; transient prefix, read pod name in that namespace instead. + (let* ((p (kubed-read-pod "Execute command in pod")) + (c (kubed-read-container p "Container" t namespace))) + (unless command + (setq args (split-string-and-unquote + (read-string "Execute command: ")) + command (car args) + args (cdr args))) + (list p command c namespace stdin tty args))))) + (pop-to-buffer + (apply #'make-comint "kubed-exec" kubed-kubectl-program nil + "exec" pod + (append + (when namespace (list "-n" namespace)) + (when container (list "-c" container)) + (when stdin '("-i")) + (when tty '("-t")) + (list "--" command) + args)))) + (defvar kubed-kubectl-command-history nil "Minibuffer history for `kubed-kubectl-command'.") -- 2.39.2