From ae4ba0de59fb262c3ba30f228cee569901b25274 Mon Sep 17 00:00:00 2001 From: Eshel Yaron Date: Thu, 15 Aug 2024 09:44:30 +0200 Subject: [PATCH] Teach additional commands about buffer-local contexts * kubed.el (kubed-set-namespace): Update docstring. (kubed-apply, kubed-run, kubed-logs, kubed-attach) (kubed-forward-port-to-pod, kubed-stop-port-forward): Use buffer-local context. --- kubed-transient.el | 12 +++- kubed.el | 147 ++++++++++++++++++++++++++++++--------------- 2 files changed, 107 insertions(+), 52 deletions(-) diff --git a/kubed-transient.el b/kubed-transient.el index 0462b28..dc2dcbe 100644 --- a/kubed-transient.el +++ b/kubed-transient.el @@ -94,7 +94,9 @@ ("-t" "Allocate TTY" "--tty")] ["Options" ("-n" "Namespace" "--namespace=" - :prompt "Namespace" :reader kubed-transient-read-namespace)]] + :prompt "Namespace" :reader kubed-transient-read-namespace) + ("-C" "Context" "--context=" + :prompt "Context" :reader kubed-transient-read-context)]] (interactive) (transient-setup 'kubed-transient-attach nil nil :value '("--stdin" "--tty") @@ -152,10 +154,12 @@ ("-i" "Open stdin" "--stdin") ("-t" "Allocate TTY" "--tty") ("-R" "Remove after exit" "--rm") - ("-C" "Override container command" "--command")] + ("-c" "Override container command" "--command")] ["Options" ("-n" "Namespace" "--namespace=" :prompt "Namespace" :reader kubed-transient-read-namespace) + ("-C" "Context" "--context=" + :prompt "Context" :reader kubed-transient-read-context) ("-I" "Image" "--image=" :prompt "Image to deploy: ") ("-p" "Port" "--port=" @@ -178,7 +182,9 @@ ("!" "Command line" kubed-kubectl-command)] ["Options" ("-f" "Definition file" "--filename=" - :reader kubed-transient-read-resource-definition-file-name)]] + :reader kubed-transient-read-resource-definition-file-name) + ("-C" "Context" "--context=" + :prompt "Context" :reader kubed-transient-read-context)]] (interactive) (transient-setup 'kubed-transient-apply nil nil :scope '("apply"))) diff --git a/kubed.el b/kubed.el index d73c53b..af67126 100644 --- a/kubed.el +++ b/kubed.el @@ -2390,7 +2390,10 @@ Optional argument DEFAULT is the minibuffer default argument." ;;;###autoload (defun kubed-set-namespace (namespace &optional context) - "Set default Kubernetes namespace in CONTEXT to NAMESPACE." + "Set default Kubernetes namespace in CONTEXT to NAMESPACE. + +Interactively, prompt for NAMESPACE and use the current context. With a +prefix argument, prompt for CONTEXT as well." (interactive (let* ((context (kubed-local-context)) (context (if current-prefix-arg @@ -2461,17 +2464,27 @@ completion candidates." (defun kubed-apply (config &optional kind context) "Apply CONFIG to Kubernetes resource of kind KIND via CONTEXT." (interactive - (list (or (seq-some - (lambda (arg) - (when (string-match "--filename=\\(.+\\)" arg) - (match-string 1 arg))) - (kubed-transient-args 'kubed-transient-apply)) - (kubed-read-resource-definition-file-name)))) - (let ((kind (or kind "resource"))) + (let ((config nil) (context nil)) + (dolist (arg (kubed-transient-args 'kubed-transient-apply)) + (cond + ((string-match "--context=\\(.+\\)" arg) + (setq context (match-string 1 arg))) + ((string-match "--filename=\\(.+\\)" arg) + (setq config (match-string 1 arg))))) + (unless context + (setq context + (let ((cxt (kubed-local-context))) + (if current-prefix-arg + (kubed-read-context "Context" cxt) + cxt)))) + (unless config + (setq config (kubed-read-resource-definition-file-name))) + (list config nil context))) + (let ((kind (or kind "resource")) + (context (or context (kubed-local-context)))) (message "Applying Kubernetes %s configuration `%s'..." kind config) - (apply #'call-process kubed-kubectl-program nil nil nil - "apply" "-f" (expand-file-name config) - (when context (list "--context" context))) + (call-process kubed-kubectl-program nil nil nil + "apply" "-f" (expand-file-name config) "--context" context) (message "Applying Kubernetes %s configuration `%s'... Done." kind config))) ;;;###autoload @@ -2505,10 +2518,12 @@ completion candidates." ;;;###autoload (defun kubed-run - (pod image &optional context namespace port attach stdin tty rm envs command args) - "Run IMAGE in Kubernetes POD. + ( pod image + &optional context namespace port attach stdin tty rm envs command args) + "Run container IMAGE in a new Kubernetes POD. -Optional argument NAMESPACE is the namespace to use for the created pod, +Optional argument CONTEXT is the `kubectl' context to use, defaulting to +the current context. NAMESPACE is the namespace in which to create POD, defaulting to the current namespace. PORT is the port to expose, defaulting to none. If ATTACH is non-nil, then attach to the created image with a `comint-mode' buffer, and pop to that buffer. Non-nil @@ -2519,10 +2534,12 @@ which specify environment variables VAR and values VAL to give them in the created container. ARGS are command line arguments for the container command. If COMMAND is non-nil, ARGS consist of a complete command line, that overrides the container command instead of just -providing it with arguments." +providing it with arguments. + +Interactively, prompt for POD and IMAGE. With a prefix argument, prompt +for NAMESPACE; with a double prefix argument, also prompt for CONTEXT." (interactive - (let ((pod (read-string "Run image in pod with name: ")) - (image nil) (port nil) (context nil) (namespace nil) + (let ((pod nil) (image nil) (port nil) (context nil) (namespace nil) (attach nil) (stdin nil) (tty nil) (rm nil) (envs nil) (command nil) (args nil)) (dolist (arg (kubed-transient-args 'kubed-transient-run)) @@ -2544,6 +2561,19 @@ providing it with arguments." (push (match-string 1 arg) envs)) ((string-match "-- =\\(.+\\)" arg) (setq args (split-string-and-unquote (match-string 1 arg)))))) + (unless context + (setq context + (let ((cxt (kubed-local-context))) + (if (equal current-prefix-arg '(16)) + (kubed-read-context "Context" cxt) + cxt)))) + (unless namespace + (setq namespace + (let ((cur (kubed-local-namespace context))) + (if current-prefix-arg + (kubed-read-namespace "Namespace" cur nil context) + cur)))) + (setq pod (read-string "Run image in pod with name: ")) (unless image (setq image (read-string "Image to run: " nil 'kubed-container-image-history))) (list pod image context namespace port attach stdin tty rm envs command args))) @@ -2634,23 +2664,29 @@ use it; otherwise, fall back to prompting." (defun kubed-logs (pod container context namespace) "Show logs for container CONTAINER in Kubernetes pod POD." (interactive - (let* ((context (kubed-current-context)) - (n (kubed-current-namespace context)) - (n (if current-prefix-arg (kubed-read-namespace "Namespace" n nil context) n)) + (let* ((context (kubed-local-context)) + (context (if (equal current-prefix-arg '(16)) + (kubed-read-context "Context" context) + context)) + (n (kubed-local-namespace context)) + (n (if current-prefix-arg + (kubed-read-namespace "Namespace" n nil context) + n)) (p (kubed-read-pod "Show logs for pod" nil nil context n)) (c (kubed-read-container p "Container" nil context n))) (list p c context n))) - (let ((buf (generate-new-buffer - (format "*kubed-logs %s[%s] in %s*" pod container namespace)))) + (let* ((context (or context (kubed-local-context))) + (namespace (or namespace (kubed-local-namespace context))) + (buf (generate-new-buffer + (format "*kubed-logs %s[%s] in %s[%s]*" + pod container namespace context)))) (with-current-buffer buf (run-hooks 'kubed-logs-setup-hook)) - (message "Getting logs for container `%s' in pod `%s' in namespace `%s'..." container pod namespace) - (apply #'start-process - "*kubed-logs*" buf - kubed-kubectl-program "logs" - "-f" "-c" container pod - (append - (when namespace (list "-n" namespace)) - (when context (list "--context" context)))) + (message "Getting logs for container `%s' in pod `%s' in namespace `%s'..." + container pod namespace) + (start-process "*kubed-logs*" buf + kubed-kubectl-program "logs" + "-f" "-c" container pod + "-n" namespace "--context" context) (display-buffer buf))) (defvar kubed-port-forward-process-alist nil @@ -2668,9 +2704,14 @@ use it; otherwise, fall back to prompting." (pod local-port remote-port context namespace) "Forward LOCAL-PORT to REMOTE-PORT of Kubernetes pod POD." (interactive - (let* ((c (kubed-current-context)) - (n (kubed-current-namespace c)) - (n (if current-prefix-arg (kubed-read-namespace "Namespace" n nil c) n)) + (let* ((c (kubed-local-context)) + (c (if (equal current-prefix-arg '(16)) + (kubed-read-context "Context" c) + c)) + (n (kubed-local-namespace c)) + (n (if current-prefix-arg + (kubed-read-namespace "Namespace" n nil c) + n)) (p (kubed-read-pod "Forward port to pod" nil nil c n)) (l (read-number "Local port: ")) (r (read-number "Remote port: "))) @@ -2679,7 +2720,7 @@ use it; otherwise, fall back to prompting." local-port remote-port pod namespace) (push (cons - (format "pod %s %d:%d in %s" pod local-port remote-port namespace) + (format "%s %d:%d in %s[%s]" pod local-port remote-port namespace context) (apply #'start-process "*kubed-port-forward*" nil kubed-kubectl-program "port-forward" @@ -2693,10 +2734,11 @@ use it; otherwise, fall back to prompting." "Stop Kubernetes port-forwarding with descriptor DESCRIPTOR. DESCRIPTOR is a string that says which port-forwarding process to stop, -it has the format \"pod POD LOCAL-PORT:REMOTE-PORT\", where POD is the -name of the pod that is the target of the port-forwarding, LOCAL-PORT is -the local port that is being forwarded, and REMOTE-PORT is the -correspoding remote port of POD. +it has the format \"POD LOCAL-PORT:REMOTE-PORT in NAMESPACE[CONTEXT]\", +where POD is the name of the pod that is the target of the +port-forwarding, LOCAL-PORT is the local port that is being forwarded, +REMOTE-PORT is the correspoding remote port of POD, NAMESPACE is the +namespace of POD and CONTEXT is the `kubectl' context. Interactively, prompt for DESCRIPTOR with completion. If there is only one port-forwarding process, stop that process without prompting." @@ -2762,13 +2804,11 @@ 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]." +prompt for CONTAINER as well. With a prefix argument, prompt for +NAMESPACE too. With a double prefix argument, also prompt for CONTEXT. +STDIN and TTY are t interactively." (interactive (let ((context nil) (namespace nil) (stdin t) (tty t)) - (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-attach)) (cond ((string-match "--namespace=\\(.+\\)" arg) @@ -2777,12 +2817,21 @@ with \\[universal-argument] \\[universal-argument]; and TTY is t unless\ (setq context (match-string 1 arg))) ((equal "--stdin" arg) (setq stdin t)) ((equal "--tty" arg) (setq tty t)))) - (let* ((c (or context (kubed-current-context))) - (n (or namespace - (when current-prefix-arg - (kubed-read-namespace "Namespace" (kubed-current-namespace) nil c)))) - (p (kubed-read-pod "Attach to pod" nil nil c n))) - (list p (kubed-read-container p "Container" t c n) c n stdin tty)))) + (unless context + (setq context + (let ((cxt (kubed-local-context))) + (if (equal current-prefix-arg '(16)) + (kubed-read-context "Context" cxt) + cxt)))) + (unless namespace + (setq namespace + (let ((cur (kubed-local-namespace context))) + (if current-prefix-arg + (kubed-read-namespace "Namespace" cur nil context) + cur)))) + (let* ((p (kubed-read-pod "Exec on pod" nil nil context namespace)) + (c (kubed-read-container p "Container" t context namespace))) + (list p c context namespace stdin tty)))) (pop-to-buffer (apply #'make-comint "kubed-attach" kubed-kubectl-program nil "attach" pod -- 2.39.2