emacs.d/elpa/kubernetes-20200114.436/kubernetes-commands.el

399 lines
16 KiB
EmacsLisp
Raw Normal View History

2020-02-03 19:45:34 +01:00
;;; kubernetes-commands.el --- Interactive commands for Kubernetes modes. -*- lexical-binding: t; -*-
;;; Commentary:
;;; Code:
(require 'kubernetes-ast)
(require 'kubernetes-modes)
(require 'kubernetes-popups)
(require 'kubernetes-props)
(require 'kubernetes-state)
(require 'kubernetes-utils)
(autoload 'kubernetes-configmaps-delete-marked "kubernetes-configmaps")
(autoload 'kubernetes-deployments-delete-marked "kubernetes-deployments")
(autoload 'kubernetes-statefulsets-delete-marked "kubernetes-statefulsets")
(autoload 'kubernetes-ingress-delete-marked "kubernetes-ingress")
(autoload 'kubernetes-display-config "kubernetes-contexts")
(autoload 'kubernetes-display-configmap "kubernetes-configmaps")
(autoload 'kubernetes-display-deployment "kubernetes-deployments")
(autoload 'kubernetes-display-statefulset "kubernetes-statefulsets")
(autoload 'kubernetes-display-ingress "kubernetes-ingress")
(autoload 'kubernetes-display-node "kubernetes-nodes")
(autoload 'kubernetes-display-job "kubernetes-jobs")
(autoload 'kubernetes-display-namespace "kubernetes-namespaces")
(autoload 'kubernetes-display-pod "kubernetes-pods")
(autoload 'kubernetes-display-secret "kubernetes-secrets")
(autoload 'kubernetes-display-service "kubernetes-services")
(autoload 'kubernetes-jobs-delete-marked "kubernetes-jobs")
(autoload 'kubernetes-pods-delete-marked "kubernetes-pods")
(autoload 'kubernetes-secrets-delete-marked "kubernetes-secrets")
(autoload 'kubernetes-services-delete-marked "kubernetes-services")
(autoload 'kubernetes-show-pods-for-label "kubernetes-labels")
;; Mark management
;;;###autoload
(defun kubernetes-mark-for-delete (point)
"Mark the thing at POINT for deletion, then advance to the next line."
(interactive "d")
(pcase (get-text-property point 'kubernetes-nav)
(`(:pod-name ,name)
(kubernetes-state-mark-pod name))
(`(:configmap-name ,name)
(kubernetes-state-mark-configmap name))
(`(:ingress-name ,name)
(kubernetes-state-mark-ingress name))
(`(:job-name ,name)
(kubernetes-state-mark-job name))
(`(:secret-name ,name)
(kubernetes-state-mark-secret name))
(`(:service-name ,name)
(kubernetes-state-mark-service name))
(`(:deployment-name ,name)
(kubernetes-state-mark-deployment name))
(`(:statefulset-name ,name)
(kubernetes-state-mark-statefulset name))
(_
(user-error "Nothing here can be marked")))
(let ((inhibit-read-only t))
(kubernetes-ast-put-delete-mark-on-line-at-pt point))
(magit-section-forward))
;;;###autoload
(defun kubernetes-unmark (point)
"Unmark the thing at POINT, then advance to the next line."
(interactive "d")
(pcase (get-text-property point 'kubernetes-nav)
(`(:pod-name ,name)
(kubernetes-state-unmark-pod name))
(`(:configmap-name ,name)
(kubernetes-state-unmark-configmap name))
(`(:ingress-name ,name)
(kubernetes-state-unmark-ingress name))
(`(:job-name ,name)
(kubernetes-state-unmark-job name))
(`(:secret-name ,name)
(kubernetes-state-unmark-secret name))
(`(:service-name ,name)
(kubernetes-state-unmark-service name))
(`(:deployment-name ,name)
(kubernetes-state-unmark-deployment name))
(`(:statefulset-name ,name)
(kubernetes-state-unmark-statefulset name)))
(kubernetes-state-trigger-redraw)
(goto-char point)
(magit-section-forward))
;;;###autoload
(defun kubernetes-unmark-all ()
"Unmark everything in the buffer."
(interactive)
(kubernetes-state-unmark-all)
(let ((pt (point)))
(kubernetes-state-trigger-redraw)
(goto-char pt)))
;;;###autoload
(defun kubernetes-execute-marks ()
"Action all marked items in the buffer."
(interactive)
(let ((state (kubernetes-state)))
(let ((n (length (kubernetes-state-marked-pods state))))
(when (and (not (zerop n))
(y-or-n-p (format "Delete %s pod%s? " n (if (equal 1 n) "" "s"))))
(kubernetes-pods-delete-marked state)))
(let ((n (length (kubernetes-state-marked-configmaps state))))
(when (and (not (zerop n))
(y-or-n-p (format "Delete %s configmap%s? " n (if (equal 1 n) "" "s"))))
(kubernetes-configmaps-delete-marked state)))
(let ((n (length (kubernetes-state-marked-ingress state))))
(when (and (not (zerop n))
(y-or-n-p (format "Delete %s ingress%s? " n (if (equal 1 n) "" "s"))))
(kubernetes-ingress-delete-marked state)))
(let ((n (length (kubernetes-state-marked-secrets state))))
(when (and (not (zerop n))
(y-or-n-p (format "Delete %s secret%s? " n (if (equal 1 n) "" "s"))))
(kubernetes-secrets-delete-marked state)))
(let ((n (length (kubernetes-state-marked-deployments state))))
(when (and (not (zerop n))
(y-or-n-p (format "Delete %s deployment%s? " n (if (equal 1 n) "" "s"))))
(kubernetes-deployments-delete-marked state)))
(let ((n (length (kubernetes-state-marked-statefulsets state))))
(when (and (not (zerop n))
(y-or-n-p (format "Delete %s statefulsets%s? " n (if (equal 1 n) "" "s"))))
(kubernetes-statefulsets-delete-marked state)))
(let ((n (length (kubernetes-state-marked-jobs state))))
(when (and (not (zerop n))
(y-or-n-p (format "Delete %s job%s? " n (if (equal 1 n) "" "s"))))
(kubernetes-jobs-delete-marked state)))
(let ((n (length (kubernetes-state-marked-services state))))
(when (and (not (zerop n))
(y-or-n-p (format "Delete %s service%s? " n (if (equal 1 n) "" "s"))))
(kubernetes-services-delete-marked state))))
(kubernetes-unmark-all))
;; Misc commands
;;;###autoload
(defun kubernetes-copy-thing-at-point (point)
"Perform a context-sensitive copy action.
Inspects the `kubernetes-copy' text property at POINT to determine
what to copy."
(interactive "d")
(when-let (s (get-text-property point 'kubernetes-copy))
(kill-new s)
;; Print a user-friendly message for feedback.
(let ((n-lines 1) (first-line nil))
(with-temp-buffer
(insert s)
(goto-char (point-min))
(setq first-line (buffer-substring (line-beginning-position) (line-end-position)))
(while (search-forward "\n" nil t)
(setq n-lines (1+ n-lines))))
(let ((ellipsized (kubernetes-utils-ellipsize first-line 70)))
(if (< 1 n-lines)
(message "Copied %s lines, starting with: %s" n-lines ellipsized)
(message "Copied: %s" ellipsized))))))
;;;###autoload
(defun kubernetes-refresh (&optional verbose)
"Force Kubernetes buffers to redraw.
With optional argument VERBOSE, log status changes."
(interactive "p")
(run-hook-with-args 'kubernetes-poll-hook verbose)
(kubernetes-state-trigger-redraw))
;;;###autoload
(defun kubernetes-navigate (point state)
"Perform a context-sensitive navigation action.
STATE is the current application state.
Inspecs the `kubernetes-nav' text property at POINT to determine
how to navigate. If that property is not found, attempt to toggle
the magit section at point."
(interactive (list (point) (kubernetes-state)))
(pcase (get-text-property point 'kubernetes-nav)
(:display-config
(kubernetes-display-config (alist-get 'config state)))
(`(:configmap-name ,configmap-name)
(kubernetes-display-configmap configmap-name state))
(`(:service-name ,service-name)
(kubernetes-display-service service-name state))
(`(:deployment-name ,deployment-name)
(kubernetes-display-deployment deployment-name state))
(`(:statefulset-name ,statefulset-name)
(kubernetes-display-statefulset statefulset-name state))
(`(:ingress-name ,ingress-name)
(kubernetes-display-ingress ingress-name state))
(`(:node-name ,node-name)
(kubernetes-display-node node-name state))
(`(:job-name ,job-name)
(kubernetes-display-job job-name state))
(`(:secret-name ,secret-name)
(kubernetes-display-secret secret-name state))
(`(:namespace-name ,namespace-name)
(kubernetes-display-namespace namespace-name state))
(`(:pod-name ,pod-name)
(kubernetes-display-pod pod-name state))
(`(:selector ,selector)
(kubernetes-show-pods-for-label selector))
(_
(when-let (section (get-text-property (point) 'magit-section))
(magit-section-toggle section)))))
(defun kubernetes--describable-thing-at-pt ()
(save-excursion
(back-to-indentation)
(get-text-property (point) 'kubernetes-nav)))
;;;###autoload
(defun kubernetes-describe-dwim (thing)
"Describe the thing at point.
THING must be a valid target for `kubectl describe'."
(interactive (list (kubernetes--describable-thing-at-pt)))
(pcase thing
(`(:pod-name ,pod-name)
(kubernetes-describe-pod pod-name))
(_
(user-error "Nothing at point to describe"))))
;;;###autoload
(defun kubernetes-describe-pod (pod-name)
"Display a buffer for describing a pod.
POD-NAME is the name of the pod to describe."
(interactive (list (or (kubernetes-utils-maybe-pod-name-at-point) (kubernetes-utils-read-pod-name (kubernetes-state)))))
(let ((buf (get-buffer-create kubernetes-pod-buffer-name))
(marker (make-marker)))
(with-current-buffer buf
(kubernetes-display-thing-mode)
(let ((inhibit-read-only t))
(erase-buffer)
(set-marker marker (point))
(insert (propertize "Loading..." 'face 'magit-dimmed))))
(let* ((populate-buffer (lambda (s)
(with-current-buffer (marker-buffer marker)
(setq-local tab-width 8)
(let ((inhibit-read-only t)
(inhibit-redisplay t))
(erase-buffer)
(insert "---\n")
(insert s)
(untabify (point-min) (point-max))
(goto-char (point-min))))))
(proc (kubernetes-kubectl-describe-pod kubernetes-props
(kubernetes-state)
pod-name
populate-buffer)))
(with-current-buffer buf
(add-hook 'kill-buffer-hook (lambda () (kubernetes-process-kill-quietly proc)) nil t)))
(select-window (display-buffer buf))
buf))
;;;###autoload
(defun kubernetes-exec-into (pod-name args exec-command state)
"Open a terminal for execting into a pod.
POD-NAME is the name of the pod to exec into.
ARGS are additional args to pass to kubectl.
EXEC-COMMAND is the command to run in the container.
STATE is the current application state.
Should be invoked via command `kubernetes-logs-popup'."
(interactive (let* ((state (kubernetes-state))
(pod-name (or (kubernetes-utils-maybe-pod-name-at-point) (kubernetes-utils-read-pod-name state)))
(command
(let ((cmd (string-trim (read-string (format "Command (default: %s): " kubernetes-default-exec-command)
nil 'kubernetes-exec-history))))
(if (string-empty-p cmd) kubernetes-default-exec-command cmd))))
(list pod-name (kubernetes-exec-arguments) command state)))
(let* ((command-args (append (list "exec") (kubernetes-kubectl--flags-from-state (kubernetes-state))
args
(when-let (ns (kubernetes-state-current-namespace state))
(list (format "--namespace=%s" ns)))
(list pod-name exec-command)))
(interactive-tty (member "-t" args))
(buf
(if interactive-tty
(kubernetes-utils-term-buffer-start kubernetes-exec-buffer-name
kubernetes-kubectl-executable
command-args)
(kubernetes-utils-process-buffer-start kubernetes-exec-buffer-name
#'kubernetes-mode
kubernetes-kubectl-executable
command-args))))
(when (and interactive-tty kubernetes-clean-up-interactive-exec-buffers)
(set-process-sentinel (get-buffer-process buf) #'kubernetes-process-kill-quietly))
(select-window (display-buffer buf))))
;; View management
(defun kubernetes-commands-display-buffer-fullframe (buffer)
(let ((display-fn
(lambda (buffer alist)
(when-let (window (or (display-buffer-reuse-window buffer alist)
(display-buffer-same-window buffer alist)
(display-buffer-pop-up-window buffer alist)
(display-buffer-use-some-window buffer alist)))
(delete-other-windows window)
window))))
(display-buffer buffer (list display-fn))))
(defun kubernetes-commands-display-buffer (buffer)
(let ((window (funcall kubernetes-commands-display-buffer-function buffer)))
(when kubernetes-commands-display-buffer-select
(select-frame-set-input-focus
(window-frame (select-window window))))))
;; Config management
;;;###autoload
(defun kubernetes-set-namespace (ns state)
"Set the namespace to query to NS.
Overrides the namespace settings for the current context.
STATE is the current application state."
(interactive
(let ((state (kubernetes-state)))
(list (completing-read "Use namespace: " (kubernetes--namespace-names state) nil t)
state)))
(kubernetes-process-kill-polling-processes)
(kubernetes-state-clear)
(goto-char (point-min))
;; State for the context and view should be preserved.
(kubernetes-state-update-config (kubernetes-state-config state))
(kubernetes-state-update-current-namespace ns)
(kubernetes-state-update-overview-sections (kubernetes-state-overview-sections state))
(kubernetes-state-trigger-redraw))
(defun kubernetes--namespace-names (state)
(-let* ((config (or (kubernetes-state-namespaces state) (kubernetes-kubectl-await-on-async kubernetes-props state #'kubernetes-kubectl-get-namespaces)))
((&alist 'items items) config))
(-map (-lambda ((&alist 'metadata (&alist 'name name))) name) items)))
(defun kubernetes-use-context (context)
"Switch Kubernetes context refresh the pods buffer.
CONTEXT is the name of a context as a string."
(interactive (list (completing-read "Context: " (kubernetes--context-names (kubernetes-state)) nil t)))
(kubernetes-process-kill-polling-processes)
(let ((state (kubernetes-state)))
(kubernetes-state-clear)
(kubernetes-state-update-overview-sections (kubernetes-state-overview-sections state)))
(kubernetes-state-trigger-redraw)
(when-let (buf (get-buffer kubernetes-overview-buffer-name))
(with-current-buffer buf
(goto-char (point-min))))
(let ((state (kubernetes-state)))
(kubernetes-kubectl-config-use-context
kubernetes-props
state
context
(lambda (_)
(when kubernetes-default-overview-namespace
(kubernetes-set-namespace kubernetes-default-overview-namespace
state))
(kubernetes-state-trigger-redraw)))))
(defun kubernetes--context-names (state)
(-let* ((config (or (kubernetes-state-config state) (kubernetes-kubectl-await-on-async kubernetes-props state #'kubernetes-kubectl-config-view)))
((&alist 'contexts contexts) config))
(--map (alist-get 'name it) contexts)))
(provide 'kubernetes-commands)
;;; kubernetes-commands.el ends here