From: Eshel Yaron Date: Mon, 22 Jul 2024 21:10:08 +0000 (+0200) Subject: Slightly simplify 'kubed-define-resource' X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=8af0c18cc51c70c5efc30a7067032f99752fd1b6;p=emacs.git Slightly simplify 'kubed-define-resource' --- diff --git a/lisp/net/kubed.el b/lisp/net/kubed.el index 785c2aecfd9..64a887076cd 100644 --- a/lisp/net/kubed.el +++ b/lisp/net/kubed.el @@ -25,8 +25,9 @@ ;; ;; Use `kubed-display-pod' to display a Kuberenetes pod, ;; `kubed-edit-pod' to edit it, `kubed-delete-pods' to delete it, and -;; `kubed-list-pods' to see a menu of all pods. To update the list of -;; current pods, use `kubed-update-pods' or `kubed-update-all'. +;; `kubed-list-pods' to see a menu of all pods. You can create new pods +;; from YAML or JSON files with `kubed-create-pod'. To update the list +;; of current pods, use `kubed-update-pods' or `kubed-update-all'. ;; ;; Similar commands are defined for other types of resources as well. ;; @@ -34,17 +35,13 @@ ;; current `kubectl' context and namespace. To change your current ;; Kuberenetes context or namespace, use `kubed-use-context' and ;; `kubed-set-namespace'; all resource lists are updated automatically -;; after you do so. +;; after you do so. In addition, you can use the minor mode +;; `kubed-all-namespaces-mode' to see resources from all namespaces. ;; ;; If you want to work with more or different types of Kubernetes ;; resources, use the macro `kubed-define-resource'. This macro defines ;; some common functions and commands that'll get you started with ease. -;;; TODO: - -;; - Add a way to filter resources lists. -;; - Add `kubed-create-*' commands for more resource types. - ;;; Code: (defgroup kubed nil @@ -94,9 +91,9 @@ obtaining new information from Kuberenetes clusters.") "Show Kubernetes resources from all namespaces, not just current namespace." :global t (message "Kubed \"all namespaces\" mode is now %s" - (if kubed-all-namespaces-mode "ON" "OFF")) - (kubed-update-all)) + (if kubed-all-namespaces-mode "ON" "OFF"))) +;;;###autoload (defmacro kubed-define-resource (resource &optional properties &rest commands) "Define Kubernetes RESOURCE with associated PROPERTIES and COMMANDS. @@ -112,10 +109,11 @@ interacting with Kubernetes RESOURCEs: current namespace. The RESOURCEs list buffer uses a dedicated major mode, `kubed-RESOURCEs-mode', which is also defined by this macro. - `kubed-update-RESROURCEs': update and repopulate RESOURCEs list. +- `kubed-create-RESROURCE': create a RESOURCE from a YAML or a JSON file. PROPERTIES is a list of elements (PROPERTY JSON-PATH WIDTH SORT . ATTRS) that specify properties of RESOURCEs. PROPERTY is the name of the -property, as a symbol; JSON-PATH is JSONPath expression that evaluates +property, as a symbol; JSON-PATH is a JSONPath expression that evaluates to the value of PROPERTY when applied to the full JSON representation of a RESOURCE. WIDTH, SORT and ATTRS are optional and can be omitted. WIDTH is used as the default width of the column corresponding to @@ -176,14 +174,9 @@ namespaceless resource type, put `:namespaced nil' before COMMANDS: (affx-fun (intern (format "kubed-%Ss-affixation" resource))) (updt-cmd (intern (format "kubed-update-%Ss" resource))) (list-cmd (intern (format "kubed-list-%Ss" resource))) - (edit-cmd (intern (format "kubed-%Ss-edit" resource))) - (slct-cmd (intern (format "kubed-%Ss-get" resource))) - (othr-cmd (intern (format "kubed-%Ss-get-in-other-window" resource))) - (desc-cmd (intern (format "kubed-%Ss-display" resource))) (mark-cmd (intern (format "kubed-%Ss-mark-for-deletion" resource))) (umrk-cmd (intern (format "kubed-%Ss-unmark" resource))) (exec-cmd (intern (format "kubed-%Ss-execute" resource))) - (dlt-cmd (intern (format "kubed-%Ss-delete" resource))) (list-buf (format "*kubed-%Ss*" resource)) (buf-name (format "*kubed-%S*" resource)) (out-name (format " *kubed-get-%Ss*" resource)) @@ -193,10 +186,65 @@ namespaceless resource type, put `:namespaced nil' before COMMANDS: (edt-name (intern (format "kubed-edit-%S" resource))) (dlt-name (intern (format "kubed-delete-%Ss" resource))) (mod-name (intern (format "kubed-%Ss-mode" resource))) - (namespaced t)) - (when (eq (car commands) :namespaced) - (pop commands) - (setq namespaced (pop commands))) + (crt-name (intern (format "kubed-create-%S" resource))) + (crt-spec nil) + (namespaced t) + (keyword nil)) + + ;; Process keyword arguments. + (while (keywordp (car commands)) + (setq keyword (pop commands)) + (cond + ((eq keyword :namespaced) (setq namespaced (pop commands))) + ((eq keyword :create) (setq crt-spec (pop commands))) + ;; FIXME: Add error for unknown keywords + (t (pop commands)))) + + ;; Extend `commands' with standard commands. + (dolist (c `((get "RET" "Switch to buffer showing description of" + (switch-to-buffer + ,(if namespaced + `(,desc-fun ,resource k8sns) + `(,desc-fun ,resource)))) + (get-in-other-window + "o" "Pop to buffer showing description of" + (switch-to-buffer-other-window + ,(if namespaced + `(,desc-fun ,resource k8sns) + `(,desc-fun ,resource)))) + (display "C-o" "Display description of" + (display-buffer + ,(if namespaced + `(,desc-fun ,resource k8sns) + `(,desc-fun ,resource)))) + (edit "e" "Edit" + ,(if namespaced + `(,edt-name ,resource k8sns) + `(,edt-name ,resource))) + (delete "D" "Delete" + ,(if namespaced + `(if k8sns + (when (y-or-n-p + (format ,(concat "Delete Kubernetes " + (symbol-name resource) + " `%s' in namespace `%s'?") + ,resource k8sns)) + (,dlt-name (list (list ,resource k8sns)))) + (when (y-or-n-p + (format ,(concat "Delete Kubernetes " + (symbol-name resource) + " `%s'?") + ,resource)) + (,dlt-name (list ,resource)))) + `(when (y-or-n-p + (format ,(concat "Delete Kubernetes " + (symbol-name resource) + " `%s'?") + ,resource)) + (,dlt-name (list ,resource))))))) + (push c commands)) + + ;; Generate code. `(progn (defvar ,hist-var nil ,(format "History list for `%S'." read-fun)) @@ -209,8 +257,7 @@ namespaceless resource type, put `:namespaced nil' before COMMANDS: (defun ,sure-fun () ,(format "Populate `%S', if not already populated." list-var) - (unless (or ,list-var (process-live-p ,proc-var)) - (,updt-cmd))) + (unless (or ,list-var (process-live-p ,proc-var)) (,updt-cmd))) (defun ,updt-cmd () ,(format "Update `%S'." list-var) @@ -367,26 +414,37 @@ Optional argument DEFAULT is the minibuffer default argument." resource) ,list-var) s p))) nil 'confirm nil ',hist-var default)) - (split (mapcar (lambda (c) (split-string c " ")) (ensure-list choice)))) + (split (mapcar (lambda (c) + (split-string c " ")) + (ensure-list choice)))) (if multi split (car split))))) ,(if namespaced `(defun ,cmd-name (,resource &optional k8sns) - ,(format "Display Kubernetes %S %s." resource (upcase (symbol-name resource))) + ,(format "Display Kubernetes %S %s." + resource (upcase (symbol-name resource))) (interactive (if kubed-all-namespaces-mode (,read-nms "Display") (list (,read-fun "Display")))) (display-buffer (,desc-fun ,resource k8sns))) `(defun ,cmd-name (,resource) - ,(format "Display Kubernetes %S %s." resource (upcase (symbol-name resource))) + ,(format "Display Kubernetes %S %s." + resource (upcase (symbol-name resource))) (interactive (list (,read-fun "Display"))) (display-buffer (,desc-fun ,resource)))) (add-hook 'kubed-update-hook #',updt-cmd) + ,(when namespaced + `(add-hook 'kubed-all-namespaces-mode-hook + (lambda () + (setq ,list-var nil) + (,updt-cmd)))) + ,(if namespaced `(defun ,edt-name (,resource &optional k8sns) - ,(format "Edit Kubernetes %S %s." resource (upcase (symbol-name resource))) + ,(format "Edit Kubernetes %S %s." + resource (upcase (symbol-name resource))) (interactive (if kubed-all-namespaces-mode (,read-nms "Edit") (list (,read-fun "Edit")))) @@ -413,7 +471,8 @@ Optional argument DEFAULT is the minibuffer default argument." resource) ,(if namespaced `(defun ,dlt-name (,plrl-var) - ,(format "Delete Kubernetes %S %s." plrl-var (upcase (symbol-name plrl-var))) + ,(format "Delete Kubernetes %S %s." + plrl-var (upcase (symbol-name plrl-var))) (interactive (if kubed-all-namespaces-mode (,read-nms "Delete" nil t) (list (,read-crm "Delete")))) @@ -421,29 +480,58 @@ Optional argument DEFAULT is the minibuffer default argument." resource) (user-error ,(format "You didn't specify %S to delete" plrl-var))) (if kubed-all-namespaces-mode (pcase-dolist (`(,name ,space) ,plrl-var) - (message ,(concat "Deleting Kubernetes " (symbol-name resource) " `%s' in namespace `%s'...") name space) + (message ,(concat "Deleting Kubernetes " + (symbol-name resource) + " `%s' in namespace `%s'...") + name space) (if (zerop (apply #'call-process kubed-kubectl-executable nil nil nil - "delete" "--namespace" space ,(symbol-name plrl-var) name)) - (message ,(concat "Deleting Kubernetes " (symbol-name resource) " `%s' in namespace `%s'... Done.") name space) - (error ,(concat "Failed to delete Kubernetes" (symbol-name resource) " `%s' in namespace `%s'") name space)))) - (message ,(concat "Deleting Kubernetes " (symbol-name plrl-var) " `%s'...") (string-join ,plrl-var "', `")) + "delete" "--namespace" space + ,(symbol-name plrl-var) name)) + (message ,(concat "Deleting Kubernetes " + (symbol-name resource) + " `%s' in namespace `%s'... Done.") + name space) + (error ,(concat "Failed to delete Kubernetes" + (symbol-name resource) + " `%s' in namespace `%s'") + name space)))) + (message ,(concat "Deleting Kubernetes " + (symbol-name plrl-var) + " `%s'...") + (string-join ,plrl-var "', `")) (if (zerop (apply #'call-process kubed-kubectl-executable nil nil nil "delete" ,(symbol-name plrl-var) ,plrl-var)) - (message ,(concat "Deleting Kubernetes " (symbol-name plrl-var) " `%s'... Done.") (string-join ,plrl-var "', `")) - (error ,(concat "Failed to delete Kubernetes" (symbol-name plrl-var) " `%s'") (string-join ,plrl-var "', `")))) + (message ,(concat "Deleting Kubernetes " + (symbol-name plrl-var) + " `%s'... Done.") + (string-join ,plrl-var "', `")) + (error ,(concat "Failed to delete Kubernetes" + (symbol-name plrl-var) + " `%s'") + (string-join ,plrl-var "', `")))) `(defun ,dlt-name (,plrl-var) - ,(format "Delete Kubernetes %S %s." plrl-var (upcase (symbol-name plrl-var))) + ,(format "Delete Kubernetes %S %s." plrl-var + (upcase (symbol-name plrl-var))) (interactive (list (,read-crm "Delete"))) (unless ,plrl-var (user-error ,(format "You didn't specify %S to delete" plrl-var))) - (message ,(concat "Deleting Kubernetes " (symbol-name plrl-var) " `%s'...") (string-join ,plrl-var "', `")) + (message ,(concat "Deleting Kubernetes " + (symbol-name plrl-var) + " `%s'...") + (string-join ,plrl-var "', `")) (if (zerop (apply #'call-process kubed-kubectl-executable nil nil nil "delete" ,(symbol-name plrl-var) ,plrl-var)) - (message ,(concat "Deleting Kubernetes " (symbol-name plrl-var) " `%s'... Done.") (string-join ,plrl-var "', `")) - (error ,(concat "Failed to delete Kubernetes" (symbol-name plrl-var) " `%s'") (string-join ,plrl-var "', `"))))) + (message ,(concat "Deleting Kubernetes " + (symbol-name plrl-var) + " `%s'... Done.") + (string-join ,plrl-var "', `")) + (error ,(concat "Failed to delete Kubernetes" + (symbol-name plrl-var) + " `%s'") + (string-join ,plrl-var "', `"))))) (defvar-local ,ents-var nil) @@ -458,80 +546,6 @@ Optional argument DEFAULT is the minibuffer default argument." resource) (apply #'vector c))) ,ents-var)) - (defun ,dlt-cmd () - ,(format "Delete Kubernetes %S at point." resource) - (interactive "" ,mod-name) - (if-let ,(if namespaced - `((k8sent (tabulated-list-get-entry)) - (,resource (aref k8sent 0))) - `(,resource (tabulated-list-get-id))) - ,(if namespaced - `(if-let ((k8sns (and kubed-all-namespaces-mode - (aref (tabulated-list-get-entry) 1)))) - (when (y-or-n-p (format ,(concat "Delete Kubernetes " (symbol-name resource) " `%s' in namespace `%s'?") ,resource k8sns)) - (,dlt-name (list (list ,resource k8sns)))) - (when (y-or-n-p (format ,(concat "Delete Kubernetes " (symbol-name resource) " `%s'?") ,resource)) - (,dlt-name (list ,resource)))) - `(when (y-or-n-p (format ,(concat "Delete Kubernetes " (symbol-name resource) " `%s'?") ,resource)) - (,dlt-name (list ,resource)))) - (user-error ,(format "No Kubernetes %S at point" resource)))) - - (defun ,slct-cmd () - ,(format "Switch to buffer showing description of Kubernetes %s at point." resource) - (interactive "" ,mod-name) - (if-let ,(if namespaced - `((k8sent (tabulated-list-get-entry)) - (,resource (aref k8sent 0))) - `(,resource (tabulated-list-get-id))) - ,(if namespaced - `(let ((k8sns (when kubed-all-namespaces-mode - (aref (tabulated-list-get-entry) 1)))) - (switch-to-buffer (,desc-fun ,resource k8sns))) - `(switch-to-buffer (,desc-fun ,resource))) - (user-error ,(format "No Kubernetes %S at point" resource)))) - - (defun ,othr-cmd () - ,(format "Pop to buffer showing description of Kubernetes %s at point." resource) - (interactive "" ,mod-name) - (if-let ,(if namespaced - `((k8sent (tabulated-list-get-entry)) - (,resource (aref k8sent 0))) - `(,resource (tabulated-list-get-id))) - ,(if namespaced - `(let ((k8sns (when kubed-all-namespaces-mode - (aref (tabulated-list-get-entry) 1)))) - (switch-to-buffer-other-window (,desc-fun ,resource k8sns))) - `(switch-to-buffer-other-window (,desc-fun ,resource))) - (user-error ,(format "No Kubernetes %S at point" resource)))) - - (defun ,desc-cmd () - ,(format "Display Kubernetes %S at point." resource) - (interactive "" ,mod-name) - (if-let ,(if namespaced - `((k8sent (tabulated-list-get-entry)) - (,resource (aref k8sent 0))) - `(,resource (tabulated-list-get-id))) - ,(if namespaced - `(let ((k8sns (when kubed-all-namespaces-mode - (aref (tabulated-list-get-entry) 1)))) - (display-buffer (,desc-fun ,resource k8sns))) - `(display-buffer (,desc-fun ,resource))) - (user-error ,(format "No Kubernetes %S at point" resource)))) - - (defun ,edit-cmd () - ,(format "Edit Kubernetes %S at point." resource) - (interactive "" ,mod-name) - (if-let ,(if namespaced - `((k8sent (tabulated-list-get-entry)) - (,resource (aref k8sent 0))) - `(,resource (tabulated-list-get-id))) - ,(if namespaced - `(let ((k8sns (when kubed-all-namespaces-mode - (aref (tabulated-list-get-entry) 1)))) - (,edt-name ,resource k8sns)) - `(,edt-name ,resource)) - (user-error ,(format "No Kubernetes %S at point" resource)))) - (defun ,mark-cmd () ,(format "Mark Kubernetes %S at point for deletion." resource) (interactive "" ,mod-name) @@ -644,6 +658,14 @@ Optional argument DEFAULT is the minibuffer default argument." resource) (display-buffer ,dlt-errb)))))))) (user-error ,(format "No Kubernetes %S marked for deletion" plrl-var))))) + ,(if crt-spec `(defun ,crt-name . ,crt-spec) + `(defun ,crt-name (definition) + ,(format "Create Kubernetes %s from definition file DEFINITION." + (symbol-name resource)) + (interactive (list (kubed-read-resource-definition-file-name + ,(capitalize (symbol-name resource))))) + (kubed-create definition ,(symbol-name resource)))) + ,@(mapcar (pcase-lambda (`(,suffix ,_key ,desc . ,body)) `(defun ,(intern (format "kubed-%Ss-%S" resource suffix)) () @@ -663,15 +685,12 @@ Optional argument DEFAULT is the minibuffer default argument." resource) (defvar-keymap ,(intern (format "kubed-%Ss-mode-map" resource)) :doc ,(format "Keymap for `%S" mod-name) - "RET" #',slct-cmd - "o" #',othr-cmd - "C-o" #',desc-cmd + "A" #'kubed-all-namespaces-mode "G" #',updt-cmd "d" #',mark-cmd "x" #',exec-cmd "u" #',umrk-cmd - "e" #',edit-cmd - "D" #',dlt-cmd + "+" #',crt-name ,@(mapcan (pcase-lambda (`(,suffix ,key ,_desc . ,_body)) (when key @@ -693,7 +712,6 @@ Optional argument DEFAULT is the minibuffer default argument." resource) `(let ((c (+ ,i (if kubed-all-namespaces-mode 1 0)))) (funcall ,sorter (aref (cadr l) c) (aref (cadr r) c))) `(funcall ,sorter (aref (cadr l) ,i) (aref (cadr r) ,i)))) - t)) (nthcdr 4 p)) res)) @@ -736,6 +754,7 @@ Optional argument DEFAULT is the minibuffer default argument." resource) (setq tabulated-list-format (,frmt-fun)) (setq tabulated-list-entries #',ents-fun) (setq tabulated-list-padding 2) + (setq-local truncate-string-ellipsis (propertize ">" 'face 'shadow)) (tabulated-list-init-header)) (defun ,buff-fun (,plrl-var &optional buffer frozen) @@ -771,6 +790,7 @@ Optional argument DEFAULT is the minibuffer default argument." resource) ;;;###autoload (autoload 'kubed-edit-pod "kubed" nil t) ;;;###autoload (autoload 'kubed-delete-pods "kubed" nil t) ;;;###autoload (autoload 'kubed-list-pods "kubed" nil t) +;;;###autoload (autoload 'kubed-create-pod "kubed" nil t) (kubed-define-resource pod ((phase ".status.phase" 10) (starttime ".status.startTime" 20)) (dired "C-d" "Start Dired in home directory of first container of" @@ -799,24 +819,39 @@ Optional argument DEFAULT is the minibuffer default argument." resource) ;;;###autoload (autoload 'kubed-edit-namespace "kubed" nil t) ;;;###autoload (autoload 'kubed-delete-namespaces "kubed" nil t) ;;;###autoload (autoload 'kubed-list-namespaces "kubed" nil t) -(kubed-define-resource namespace () :namespaced nil) +;;;###autoload (autoload 'kubed-create-namespace "kubed" nil t) +(kubed-define-resource namespace () + :namespaced nil + :create + ((name) "Create Kubernetes namespace with name NAME." + (interactive (list (read-string "Create namespace with name: "))) + (unless (zerop + (call-process + kubed-kubectl-executable nil nil nil + "create" "namespace" name)) + (user-error "Failed to create Kubernetes namespace with name `%s'" name)) + (message "Created Kubernetes namespace with name `%s'." name) + (kubed-update-namespaces))) ;;;###autoload (autoload 'kubed-display-persistentvolume "kubed" nil t) ;;;###autoload (autoload 'kubed-edit-persistentvolume "kubed" nil t) ;;;###autoload (autoload 'kubed-delete-persistentvolumes "kubed" nil t) ;;;###autoload (autoload 'kubed-list-persistentvolumes "kubed" nil t) +;;;###autoload (autoload 'kubed-create-persistentvolume "kubed" nil t) (kubed-define-resource persistentvolume () :namespaced nil) ;;;###autoload (autoload 'kubed-display-service "kubed" nil t) ;;;###autoload (autoload 'kubed-edit-service "kubed" nil t) ;;;###autoload (autoload 'kubed-delete-services "kubed" nil t) ;;;###autoload (autoload 'kubed-list-services "kubed" nil t) +;;;###autoload (autoload 'kubed-create-service "kubed" nil t) (kubed-define-resource service) ;;;###autoload (autoload 'kubed-display-secret "kubed" nil t) ;;;###autoload (autoload 'kubed-edit-secret "kubed" nil t) ;;;###autoload (autoload 'kubed-delete-secrets "kubed" nil t) ;;;###autoload (autoload 'kubed-list-secrets "kubed" nil t) +;;;###autoload (autoload 'kubed-create-secret "kubed" nil t) (kubed-define-resource secret ((type ".type" 32) (creationtimestamp ".metadata.creationTimestamp" 20))) @@ -824,6 +859,7 @@ Optional argument DEFAULT is the minibuffer default argument." resource) ;;;###autoload (autoload 'kubed-edit-job "kubed" nil t) ;;;###autoload (autoload 'kubed-delete-jobs "kubed" nil t) ;;;###autoload (autoload 'kubed-list-jobs "kubed" nil t) +;;;###autoload (autoload 'kubed-create-job "kubed" nil t) (kubed-define-resource job ((status ".status.conditions[0].type" 10) (starttime ".status.startTime" 20))) @@ -831,12 +867,18 @@ Optional argument DEFAULT is the minibuffer default argument." resource) ;;;###autoload (autoload 'kubed-edit-deployment "kubed" nil t) ;;;###autoload (autoload 'kubed-delete-deployments "kubed" nil t) ;;;###autoload (autoload 'kubed-list-deployments "kubed" nil t) -(kubed-define-resource deployment) +;;;###autoload (autoload 'kubed-create-deployment "kubed" nil t) +(kubed-define-resource deployment + ((reps ".status.replicas" 4 + (lambda (l r) (< (string-to-number l) (string-to-number r))) + :right-align t) + (creationtimestamp ".metadata.creationTimestamp" 20))) ;;;###autoload (autoload 'kubed-display-replicaset "kubed" nil t) ;;;###autoload (autoload 'kubed-edit-replicaset "kubed" nil t) ;;;###autoload (autoload 'kubed-delete-replicasets "kubed" nil t) ;;;###autoload (autoload 'kubed-list-replicasets "kubed" nil t) +;;;###autoload (autoload 'kubed-create-replicaset "kubed" nil t) (kubed-define-resource replicaset ((reps ".status.replicas" 4 (lambda (l r) (< (string-to-number l) (string-to-number r))) @@ -849,6 +891,7 @@ Optional argument DEFAULT is the minibuffer default argument." resource) ;;;###autoload (autoload 'kubed-edit-statefulset "kubed" nil t) ;;;###autoload (autoload 'kubed-delete-statefulsets "kubed" nil t) ;;;###autoload (autoload 'kubed-list-statefulsets "kubed" nil t) +;;;###autoload (autoload 'kubed-create-statefulset "kubed" nil t) (kubed-define-resource statefulset ((reps ".status.replicas" 4 (lambda (l r) (< (string-to-number l) (string-to-number r))) @@ -907,18 +950,67 @@ Optional argument DEFAULT is the minibuffer default argument." (message "Kubernetes namespace is now `%s'." ns) (kubed-update-all)) +(defcustom kubed-read-resource-definition-filter-files-by-kind t + "Whether to filter file completion candidates by their Kubernetes \"kind\". + +If this is non-nil, `kubed-read-resource-definition-file-name' only +suggests files with the right \"kind\" as completion candidates when you +call it with non-nil KIND argument. This is useful because you get more +relevant completions, but it may become slow in directories with many +large JSON and YAML files, in which case you can set this option to nil." + :type 'boolean) + +(defun kubed-read-resource-definition-file-name (&optional kind) + "Prompt for Kubernetes resource definition file name. + +Optional argument KIND is the kind of resource the file should define. +If `kubed-read-resource-definition-filter-files-by-kind' is non-nil, +this function suggests only files that define resources of kind KIND as +completion candidates." + (read-file-name + (format "%s definition file: " (or kind "Resource")) nil nil t nil + (if (and kind kubed-read-resource-definition-filter-files-by-kind + (executable-find "grep")) + (let ((cache (make-hash-table :test 'equal))) + (lambda (f) + (or (file-directory-p f) + (when-let ((ext (and (string-match "\\.[^.]*\\'" f) + (substring f (1+ (match-beginning 0)))))) + (or (and (member ext '("yaml" "yml")) + (pcase (gethash (expand-file-name f) cache 'noval) + ('noval + (puthash (expand-file-name f) + (zerop (call-process + "grep" f nil nil + (format "^kind: %s$" kind))) + cache)) + (val val))) + (and (equal ext "json") + (pcase (gethash (expand-file-name f) cache 'noval) + ('noval + (puthash (expand-file-name f) + (zerop (call-process + "grep" f nil nil + (format "^kind: %s$" kind))) + cache)) + (val val)))))))) + (lambda (f) + (or (file-directory-p f) + (when (string-match "\\.[^.]*\\'" f) + (member (substring f (1+ (match-beginning 0))) + '("yaml" "yml" "json")))))))) + ;;;###autoload -(defun kubed-create-pod (definition) - "Create Kubernetes pod with definition DEFINITION." - (interactive (list (read-file-name "Pod definition file: "))) - (message "Creating pod with definition `%s'..." definition) - (message "Creating pod with definition `%s'... Done. New pod name is `%s'." - definition (car (process-lines kubed-kubectl-executable - "create" "-f" - (expand-file-name definition) - "-o" "jsonpath={.metadata.name}")))) - -(keymap-set kubed-pods-mode-map "+" #'kubed-create-pod) +(defun kubed-create (definition &optional kind) + "Create Kubernetes resource of kind KIND with definition DEFINITION." + (interactive + (list (kubed-read-resource-definition-file-name))) + (message "Creating Kubernetes %s with definition `%s'..." (or kind "resource") definition) + (message "Creating Kubernetes %s with definition `%s'... Done. New %s name is `%s'." + (or kind "resource") definition (or kind "resource") + (car (process-lines kubed-kubectl-executable + "create" "-f" (expand-file-name definition) + "-o" "jsonpath={.metadata.name}")))) (defun kubed-pod-containers (pod &optional k8sns) "Return list of containers in Kubernetes pod POD in namespace K8SNS."