emacs.d/elpa/kubernetes-20200114.436/kubernetes-utils.el
2020-02-03 19:45:34 +01:00

183 lines
6.8 KiB
EmacsLisp

;; kubernetes-utils.el --- Common utilities. -*- lexical-binding: t; -*-
;;; Commentary:
;;; Code:
(require 'dash)
(require 'subr-x)
(require 'term)
(require 'kubernetes-ast)
(require 'kubernetes-kubectl)
(require 'kubernetes-props)
(require 'kubernetes-state)
(require 'kubernetes-timers)
(require 'kubernetes-vars)
(autoload 'org-read-date "org")
(defalias 'kubernetes-utils-read-pod-name 'kubernetes-pods--read-name
"Exporting `kubernetes-pods--read-name'")
(defun kubernetes-utils-read-iso-datetime (&rest _)
(let* ((date (org-read-date nil t))
(tz (format-time-string "%z" date)))
(concat
(format-time-string "%Y-%m-%dT%H:%M:%S" date)
(replace-regexp-in-string (rx (group (? (any "+-")) digit digit)
(group digit digit))
"\\1:\\2"
tz))))
(defun kubernetes-get-pod-container-names (pod)
"Return the names of all containers available in the specified pod."
(-let [(&alist 'spec (&alist 'containers containers)) pod]
(-map (-lambda ((&alist 'name name)) name) containers)))
(defun kubernetes-utils-read-container-name (&rest _)
"Read a container name from the pod at POINT or a user-supplied pod."
(letrec ((state (kubernetes-state))
(pod-name (or (kubernetes-utils-maybe-pod-name-at-point)
(kubernetes-utils-read-pod-name state)))
(pod (kubernetes-state-lookup-pod pod-name state))
(pod-containers (kubernetes-get-pod-container-names pod)))
(completing-read "Container name: " pod-containers nil t)))
(defun kubernetes-utils-read-time-value (&rest _)
"Read a relative time value in the style accepted by kubectl. E.g. 20s, 3h, 5m."
(let (result)
(while (null result)
(let ((input (read-string "Time value (e.g. 20s): ")))
(if (string-match-p (rx bol (* space) (+ digit) (* space) (any "smh") (* space) eol)
input)
(setq result input)
(message "Invalid time value")
(sit-for 1))))
result))
(defun kubernetes-utils-maybe-pod-name-at-point ()
(let ((nav-buffer (get-buffer kubernetes-overview-buffer-name)))
(with-current-buffer nav-buffer
(pcase (get-text-property (point) 'kubernetes-nav nav-buffer)
(`(:pod-name ,value)
value)))))
(defun kubernetes-utils-ellipsize (s threshold)
(if (> (length s) threshold)
(concat (substring s 0 (1- threshold)) "")
s))
(defun kubernetes-utils-parse-utc-timestamp (timestamp)
"Parse TIMESTAMP string from the API into the representation used by Emacs."
(let ((parsed (parse-time-string (replace-regexp-in-string "Z" "" (replace-regexp-in-string "T" " " timestamp)))))
(setf (nth 8 parsed) 0)
parsed))
(defun kubernetes-utils-time-diff-string (start now)
"Find the interval between START and NOW, and return a string of the coarsest unit."
(let ((diff (time-to-seconds (time-subtract now start))))
(car (split-string (format-seconds "%yy,%dd,%hh,%mm,%ss%z" diff) ","))))
(defun kubernetes-utils-kill-buffer (proc-buf &rest _)
(if-let (win (get-buffer-window proc-buf))
(quit-window t win)
(kill-buffer proc-buf)))
(defun kubernetes-utils-make-cleanup-fn (buf)
"Make a function to add to `kill-buffer-hook' for a Kubernetes buffer.
BUF is the buffer used to display a Kubernetes feature. A
reference to it is needed to determine which buffers remain.
The function will terminate polling when the last Kubernetes
buffer is killed."
(lambda ()
(let* ((bufs (-keep #'get-buffer (list kubernetes-label-query-buffer-name
kubernetes-overview-buffer-name)))
(more-buffers (remove buf bufs)))
(unless more-buffers
(dolist (b bufs)
(with-current-buffer b
(kubernetes-state-clear)))
(kubernetes-process-kill-polling-processes)
(kubernetes-timers-kill-timers)))))
(defun kubernetes-utils-term-buffer-start (bufname command args)
;; Kill existing process.
(when-let ((existing (get-buffer bufname))
(proc (get-buffer-process existing)))
(kubernetes-process-kill-quietly proc))
(let ((buf (get-buffer-create bufname)))
(with-current-buffer buf
(erase-buffer)
(buffer-disable-undo)
(term-mode)
(goto-char (point-min))
(let ((time-str (format "Session started at %s" (substring (current-time-string) 0 19)))
(command-str (format "%s %s" command (string-join args " "))))
(kubernetes-ast-eval
`((line ,(propertize time-str 'face 'magit-dimmed))
(padding)
(line ,(propertize command-str 'face 'magit-dimmed))
(padding))))
(term-exec (current-buffer) "kuberenetes-term" command nil args)
(let ((proc (get-buffer-process (current-buffer))))
(set-process-query-on-exit-flag proc nil)
(term-char-mode)
(add-hook 'kill-buffer-hook (lambda ()
(when-let (win (get-buffer-window buf))
(quit-window nil win)))
nil t)))
buf))
(defun kubernetes-utils-process-buffer-start (bufname setup-fn command args &optional process-filter)
(let ((buf (get-buffer-create bufname)))
(buffer-disable-undo buf)
(with-current-buffer buf
(let ((inhibit-read-only t))
(erase-buffer)
(funcall setup-fn)
(let ((time-str (format "Process started at %s" (substring (current-time-string) 0 19)))
(command-str (format "%s %s" command (string-join args " "))))
(kubernetes-ast-eval
`((line ,(propertize time-str 'face 'magit-dimmed))
(padding)
(line ,(propertize command-str 'face 'magit-dimmed))
(padding))))))
(let ((proc (apply #'start-process "kubernetes-exec" buf command args)))
(when process-filter
(set-process-filter proc process-filter))
(set-process-query-on-exit-flag proc nil))
buf))
(defun kubernetes-utils-overview-buffer-selected-p ()
(equal (current-buffer) (get-buffer kubernetes-overview-buffer-name)))
(defmacro kubernetes-utils--save-window-state (&rest body)
"Restore window state after executing BODY.
This is useful if the buffer is erased and repopulated in BODY,
in which case `save-excursion' is insufficient to restore the
window state."
`(let ((pos (point))
(col (current-column))
(window-start-line (window-start))
(inhibit-redisplay t))
(save-excursion
,@body)
(goto-char pos)
(move-to-column col)
(set-window-start (selected-window) window-start-line)))
(defun kubernetes-utils-up-to-existing-dir (dir)
(while (not (file-directory-p dir))
(setq dir (file-name-directory (directory-file-name dir))))
dir)
(provide 'kubernetes-utils)
;;; kubernetes-utils.el ends here