~eshel/kubed

ea3bd2402a4933b179766a1fceedb075b6c059b0 — Eshel Yaron a month ago 883e78b
; Autoload 'kubed-tramp'

Ensure that 'kubed-tramp' is loaded by the time it is
needed, to avoid "Method 'kubedv1' is not known" errors.
Ideally, we'd like to load 'kubed-tramp' on the first
occasion of handling a '/kubedv1:...' remote file name.
However, Tramp does not facilitate loading extensions just
in time.  The best we can do is to arrange for 'kubed-tramp'
to be loaded right after Tramp.  This is too early, because
Tramp is often used without 'kubed-tramp', so we move some
definitions around so that it no longer pulls in 'kubed'.

See also preceding tramp-devel discussion here:
https://lists.gnu.org/archive/html/tramp-devel/2024-10/msg00005.html

* kubed-common.el: New file.
(kubed-tramp-method, kubed-kubectl-program): Move here from
'kubed' and 'kubed-tramp', respectively.
* kubed-tramp.el: Require 'kubed-common' instead of 'kubed'.
(kubed-tramp-method): Move to 'kubed-common'.
(kubed-tramp-remote-file-name): Remove in favor of new
'kubed-remote-file-name' in 'kubed'.
(kubed-tramp-enable): New function, arrange for it to be
called after 'tramp' is loaded.
* kubed.el: Require 'kubed-common'.
(kubed-kubectl-program): Move to 'kubed-common'.
(kubed-remote-file-name): New function, replaces
'kubed-tramp-remote-file-name'.
(pod): Use it.
3 files changed, 70 insertions(+), 47 deletions(-)

A kubed-common.el
M kubed-tramp.el
M kubed.el
A kubed-common.el => kubed-common.el +25 -0
@@ 0,0 1,25 @@
;;; kubed-common.el --- Common definitons for Kubed   -*- lexical-binding: t; -*-

;; Copyright (C) 2024  Free Software Foundation, Inc.

;; Author: Eshel Yaron <me@eshelyaron.com>
;; Keywords: tools

;;; Commentary:

;; This library provides definitions that both `kubed' and `kubed-tramp'
;; require.

;;; Code:

(defvar kubed-tramp-method "kubedv1"    ;Versioned, for compatibility.
  ;; (find-file "/kubedv1:CONTEXT%NAMESPACE%POD%CONTAINER:/some/file")
  "Name of the Kubed Tramp method.")

(defcustom kubed-kubectl-program "kubectl"
  "Name of `kubectl' executable to use for interacting with Kubernetes."
  :type 'string
  :group 'kubed)

(provide 'kubed-common)
;;; kubed-tramp.el ends here

M kubed-tramp.el => kubed-tramp.el +34 -39
@@ 19,7 19,7 @@

;;; Code:

(require 'kubed)
(require 'kubed-common)
(require 'tramp)

(defun kubed-tramp--context (vec)


@@ 46,17 46,6 @@
        (nth 3 (split-string host "%")))
      ""))

(defvar kubed-tramp-method "kubedv1"    ;Versioned, for compatibility.
  ;; (find-file "/kubedv1:CONTEXT%NAMESPACE%POD%CONTAINER:/some/file")
  "Name of the Kubed Tramp method.")

(defun kubed-tramp-remote-file-name (context namespace pod &optional file-name)
  "Return Tramp remote FILE-NAME for POD in NAMESPACE and CONTEXT."
  (concat "/" kubed-tramp-method ":"
          context "%" namespace "%" pod
          "%" (kubed-read-container pod "Container" t context namespace)
          ":" file-name))

;;;###autoload
(defun kubed-tramp-context (file-name)
  "Extract `kubectl' context from Kubed Tramp remote file name FILE-NAME."


@@ 75,33 64,39 @@
  (unless (assoc kubed-tramp-method tramp-methods)
    (user-error "Kubed Tramp support requires Tramp version 2.7 or later")))

(when (boundp 'tramp-extra-expand-args) ; Tramp 2.7+
  (setf (alist-get kubed-tramp-method tramp-methods nil nil #'string=)
        `((tramp-login-program ,kubed-kubectl-program)
          (tramp-login-args (("exec")
                             ("--context" "%x")
                             ("--namespace" "%y")
                             ("-c" "%a")
                             ("%h")
                             ("-it")
                             ("--")
			     ("%l")))
          (tramp-direct-async (,tramp-default-remote-shell "-c"))
          (tramp-remote-shell ,tramp-default-remote-shell)
          (tramp-remote-shell-login ("-l"))
          (tramp-remote-shell-args ("-i" "-c"))))

  (connection-local-set-profile-variables
   'kubed-tramp-connection-local-default-profile
   '((tramp-extra-expand-args
      ?a (kubed-tramp--container (car tramp-current-connection))
      ?h (kubed-tramp--pod       (car tramp-current-connection))
      ?x (kubed-tramp--context   (car tramp-current-connection))
      ?y (kubed-tramp--namespace (car tramp-current-connection)))))

  (connection-local-set-profiles
   `(:application tramp :protocol ,kubed-tramp-method)
   'kubed-tramp-connection-local-default-profile))
;;;###autoload
(defun kubed-tramp-enable ()
  "Enable Kubed integration with Tramp."
  (when (boundp 'tramp-extra-expand-args) ; Tramp 2.7+

    (setf (alist-get kubed-tramp-method tramp-methods nil nil #'string=)
          `((tramp-login-program ,kubed-kubectl-program)
            (tramp-login-args (("exec")
                               ("--context" "%x")
                               ("--namespace" "%y")
                               ("-c" "%a")
                               ("%h")
                               ("-it")
                               ("--")
		               ("%l")))
            (tramp-direct-async (,tramp-default-remote-shell "-c"))
            (tramp-remote-shell ,tramp-default-remote-shell)
            (tramp-remote-shell-login ("-l"))
            (tramp-remote-shell-args ("-i" "-c"))))

    (connection-local-set-profile-variables
     'kubed-tramp-connection-local-default-profile
     '((tramp-extra-expand-args
        ?a (kubed-tramp--container (car tramp-current-connection))
        ?h (kubed-tramp--pod       (car tramp-current-connection))
        ?x (kubed-tramp--context   (car tramp-current-connection))
        ?y (kubed-tramp--namespace (car tramp-current-connection)))))

    (connection-local-set-profiles
     `(:application tramp :protocol ,kubed-tramp-method)
     'kubed-tramp-connection-local-default-profile)))

;;;###autoload (with-eval-after-load 'tramp (kubed-tramp-enable))

(provide 'kubed-tramp)
;;; kubed-tramp.el ends here

M kubed.el => kubed.el +11 -8
@@ 48,14 48,12 @@

;;; Code:

(require 'kubed-common)

(defgroup kubed nil
  "Kubernetes interface."
  :group 'tools)

(defcustom kubed-kubectl-program "kubectl"
  "Name of `kubectl' executable to use for interacting with Kubernetes."
  :type 'string)

(defcustom kubed-default-context-and-namespace nil
  "Default `kubectl' context and Kubernetes namespace.



@@ 1663,11 1661,16 @@ Interactively, use the current context.  With a prefix argument
               "\\)")
       1))

(defun kubed-remote-file-name (context namespace pod &optional file-name)
  "Return remote FILE-NAME for POD in NAMESPACE and CONTEXT."
  (concat "/" kubed-tramp-method ":"
          context "%" namespace "%" pod
          "%" (kubed-read-container pod "Container" t context namespace)
          ":" file-name))

(declare-function kubed-tramp-context          "kubed-tramp" (file-name))
(declare-function kubed-tramp-namespace        "kubed-tramp" (file-name))
(declare-function kubed-tramp-assert-support   "kubed-tramp" ())
(declare-function kubed-tramp-remote-file-name "kubed-tramp"
                  (context namespace pod &optional file-name))

;;;###autoload (autoload 'kubed-display-pod "kubed" nil t)
;;;###autoload (autoload 'kubed-edit-pod "kubed" nil t)


@@ 1714,11 1717,11 @@ Interactively, use the current context.  With a prefix argument
               ("F" "Forward port" kubed-pods-forward-port)])
  (dired "C-d" "Start Dired in"
         (kubed-tramp-assert-support)
         (dired (kubed-tramp-remote-file-name
         (dired (kubed-remote-file-name
                 kubed-list-context kubed-list-namespace pod)))
  (shell "s" "Start shell in"
         (kubed-tramp-assert-support)
         (let* ((default-directory (kubed-tramp-remote-file-name
         (let* ((default-directory (kubed-remote-file-name
                                    kubed-list-context kubed-list-namespace pod)))
           (shell
            (concat "*Kubed Shell "