Add Tramp method "apptainer"

* doc/misc/tramp.texi (Top, Configuration): Add "Optional methods".
(Optional methods): New section.
(Inline methods) <androidsu, toolbox, flatpak>: These are optional
methods.
(Inline methods) <apptainer>: Add.

* etc/NEWS: New Tramp method "apptainer".
Some Tramp methods are optional.
Fix typos.

* lisp/net/tramp-androidsu.el (tramp-enable-androidsu-method):
New defun.  Call it when `system-type' is `android'.

* lisp/net/tramp-container.el (tramp-apptainer-program): New defcustom.
(tramp-apptainer-method): New defconst.
(tramp-apptainer--completion-function)
(tramp-enable-toolbox-method, tramp-enable-flatpak-method)
(tramp-enable-apptainer-method): New defuns.

* lisp/net/tramp.el (tramp-enable-method): New defun.

* test/lisp/net/tramp-tests.el (tramp--test-container-p):
Add "apptainer".
(tramp--test-supports-processes-p): Extend function.
This commit is contained in:
Michael Albinus 2024-05-07 09:56:05 +02:00
parent 3bc9c38c47
commit 4808c63d43
6 changed files with 242 additions and 106 deletions

View file

@ -119,6 +119,7 @@ Installing @value{tramp} with your Emacs
Configuring @value{tramp} for use
* Optional methods:: Optional methods which must be enabled first.
* Connection types:: Types of connections to remote hosts.
* Inline methods:: Inline methods.
* External methods:: External methods.
@ -685,6 +686,7 @@ to non-@code{nil}, @xref{Directory Variables, , , emacs}.
@menu
* Optional methods:: Optional methods which must be enabled first.
* Connection types:: Types of connections to remote hosts.
* Inline methods:: Inline methods.
* External methods:: External methods.
@ -718,6 +720,30 @@ on the remote host.
@end menu
@node Optional methods
@section Optional methods which must be enabled first
@cindex optional methods
Not all methods are enabled by default after loading @value{tramp}.
Some of them don't work on the local host. Some of them are optional,
and must be enabled if it is intended to use them. For all methods
described in this manual, it is indicated when the method is optional.
@deffn Command tramp-enable-method method
This command enables the optional method @var{method}, a string. The
command can be invoked interactively like @kbd{M-x tramp-enable-method
@key{RET} toolbox @key{RET}}, with @option{toolbox} being an optional
method.
@end deffn
If you want to enable an optional method permanently, add something
like this to your @file{.emacs} file:
@lisp
(with-eval-after-load 'tramp (tramp-enable-method "toolbox"))
@end lisp
@node Connection types
@section Types of connections to remote hosts
@cindex connection types, overview
@ -834,6 +860,9 @@ equivalent @option{androidsu} method is provided for that system with
workarounds for its many idiosyncrasies, with the exception that
multi-hops are unsupported.
This is an optional method, @ref{Optional methods}. It is enabled by
default on @code{android} systems only.
@item @option{sudo}
@cindex method @option{sudo}
@cindex @option{sudo} method
@ -960,7 +989,8 @@ a container's name or ID, as returned by @samp{toolbox list -c}.
Without a host name, the default Toolbox container for the host will
be used.
This method does not support user names.
This is an optional method, @ref{Optional methods}. It does not
support user names.
@item @option{flatpak}
@cindex method @option{flatpak}
@ -970,7 +1000,18 @@ Integration of Flatpak sandboxes. The host name may be either an
application ID, a sandbox instance ID, or a PID, as returned by
@samp{flatpak ps}.
This method does not support user names.
This is an optional method, @ref{Optional methods}. It does not
support user names.
@item @option{apptainer}
@cindex method @option{apptainer}
@cindex @option{apptainer} method
Integration of Apptainer instances. The host name is the instance
name, as returned by @samp{apptainer instance list}.
This is an optional method, @ref{Optional methods}. It does not
support user names.
@end table

View file

@ -171,7 +171,7 @@ This user option controls outline visibility in the output buffer of
*** 'C-h m' ('describe-mode') uses outlining by default.
Set 'describe-mode-outline' to nil to get back the old behavior.
** Outline Mode
** Outline mode
+++
*** 'outline-minor-mode' is supported in tree-sitter major modes.
@ -401,7 +401,7 @@ them.
** New optional argument for modifying directory-local variables.
The commands 'add-dir-local-variable', 'delete-dir-local-variable' and
'copy-file-locals-to-dir-locals' now take an optional prefix argument,
to enter the file you want to modify.
to enter the file name you want to modify.
** Emacs Server and Client
@ -1051,7 +1051,12 @@ mode line. 'header' will display in the header line;
** Tramp
+++
*** New connection method "androidsu".
*** Tramp methods can be optional.
An optional connection method is not enabled by default. The user must
enable it explicitly by the 'tramp-enable-method' command.
+++
*** New optional connection method "androidsu".
This provides access to system files with elevated privileges granted by
the idiosyncratic 'su' implementations and system utilities customary on
Android.
@ -1061,9 +1066,9 @@ Android.
These are the external methods counterparts of "docker" and "podman".
+++
*** New connection methods "toolbox" and "flatpak".
They allow accessing system containers provided by Toolbox or
sandboxes provided by Flatpak.
*** New optional connection methods "toolbox", "flatpak" and "apptainer".
They allow accessing system containers provided by Toolbox, sandboxes
provided by Flatpak, or instances managed by Apptainer.
+++
*** Connection method "kubernetes" supports now optional container name.
@ -1138,7 +1143,7 @@ input, as the case may be.
*** EWW text input fields and areas are now fields.
In consequence, movement commands and OS input method features now
recognize and confine their activities to the text input field around
point. See also (elisp)Fields.
point. See also the Info node "(elisp) Fields".
+++
*** 'eww-open-file' can now display the file in a new buffer.
@ -1298,7 +1303,7 @@ the margin indicator.
*** New user option 'flymake-autoresize-margins'.
If non-nil, Flymake will resize the margins when 'flymake-mode' is
turned on or off.
Only relevant if `flymake-indicator-type` is set to `margins`.
Only relevant if 'flymake-indicator-type' is set to 'margins'.
+++
*** New user option 'flymake-margin-indicator-position'.
@ -1384,12 +1389,12 @@ when using the ':vc' keyword.
** Gnus
+++
*** New back end 'nnfeed'.
This allows back end developers to easily create new back ends for web
feeds, as inheriting back ends of 'nnfeed'.
*** New backend 'nnfeed'.
This allows backend developers to easily create new backends for web
feeds, as inheriting backends of 'nnfeed'.
+++
*** New back end 'nnatom'.
*** New backend 'nnatom'.
This allow users to add Atom Syndication Format feeds to Gnus as
servers.
@ -1610,7 +1615,8 @@ macros with many lines, such as from 'kmacro-edit-lossage'.
The user option 'proced-auto-update-flag' can now be set to 2 additional
values, which control automatic updates of Proced buffers that are not
displayed in some window.
** Kmacro Menu Mode
** Kmacro Menu mode
+++
*** New mode 'kmacro-menu-mode' and new command 'list-keyboard-macros'.
@ -1678,7 +1684,7 @@ options of GNU 'ls'.
+++
*** New user option 'widget-skip-inactive'.
If non-nil, moving point forward or backward between widgets by typing
TAB or S-TAB skips over inactive widgets. The default value is nil.
'TAB' or 'S-TAB' skips over inactive widgets. The default value is nil.
** Miscellaneous
@ -1694,7 +1700,7 @@ Now, calling '(thing-at-point 'url)' when point is on a bug reference
will return the URL for that bug.
+++
*** New user option 'rcirc-log-time-format'
*** New user option 'rcirc-log-time-format'.
This allows for rcirc logs to use a custom timestamp format, than the
chat buffers use by default.
@ -1818,9 +1824,9 @@ various subparts (when 'interactive-form', 'documentation', and
** 'define-globalized-minor-mode' requires that modes use 'run-mode-hooks'.
Minor modes defined with 'define-globalized-minor-mode', such as
'global-font-lock-mode', will not be enabled any more in those buffers
whose major modes fails to use 'run-mode-hooks'. Major modes defined
with 'define-derived-mode' are not affected. `run-mode-hooks` has been the
recommended way to run major mode hooks since Emacs-22.
whose major modes fail to use 'run-mode-hooks'. Major modes defined
with 'define-derived-mode' are not affected. 'run-mode-hooks' has been the
recommended way to run major mode hooks since Emacs 22.
---
** Old derived.el functions removed.
@ -1962,8 +1968,9 @@ arguments and its return type using the 'declare' macro.
'interpreted-function' is the new type used for interpreted functions,
and 'closure' is the common parent type of 'interpreted-function'
and 'byte-code-function'.
Those new types come with the associated new predicates
'closurep' and `interpreted-function-p' as well as a new constructor
Those new types come with the associated new predicates 'closurep' and
`interpreted-function-p' as well as a new constructor
'make-interpreted-closure'.
** New function 'help-fns-function-name'.
@ -2023,9 +2030,9 @@ the Info node "(elisp) Handling Errors".
+++
** Tooltips on fringes.
It is now possible to provide tooltips on fringes by adding special text
properties 'left-fringe-help' and 'right-fringe-help'. See the "Special
Properties" Info node in the Emacs Lisp Reference Manual for more
details.
properties 'left-fringe-help' and 'right-fringe-help'. See the "(elisp)
Special Properties" Info node in the Emacs Lisp Reference Manual for
more details.
+++
** New 'pop-up-frames' action alist entry for 'display-buffer'.
@ -2594,7 +2601,7 @@ correctly UTF-8 encoded.
*** The parser and encoder now accept arbitrarily large integers.
Previously, they were limited to the range of signed 64-bit integers.
** New tree-sitter functions and variables for defining and using "things".
** New tree-sitter functions and variables for defining and using "things"
+++
*** New variable 'treesit-thing-settings'.
@ -2618,7 +2625,7 @@ accept more kinds of predicates. Lisp programs can now use thing
symbols (defined in 'treesit-thing-settings') and any thing definitions
for the predicate argument.
** Other tree-sitter function and variable changes.
** Other tree-sitter function and variable changes
+++
*** 'treesit-parser-list' now takes additional optional arguments.
@ -2629,13 +2636,11 @@ all parsers, but rather "all parsers with no tags".
+++
*** New function 'treesit-parser-changed-ranges'.
This function returns buffer regions that are affected by the last
buffer edits.
*** New function 'treesit-add-font-lock-rules'.
This function helps user to add custom font-lock rules to a tree-sitter
This function helps users to add custom font-lock rules to a tree-sitter
major mode.
---

View file

@ -77,19 +77,25 @@ may edit files belonging to any and all applications."
"Name of the local temporary directory on Android.")
;;;###tramp-autoload
(tramp--with-startup
(add-to-list 'tramp-methods
`(,tramp-androidsu-method
(tramp-login-program "su")
(tramp-login-args (("-") ("%u")))
(tramp-remote-shell ,tramp-androidsu-local-shell-name)
(tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-tmpdir ,tramp-androidsu-local-tmp-directory)
(tramp-connection-timeout 10)
(tramp-shell-name ,tramp-androidsu-local-shell-name)))
(add-to-list 'tramp-default-user-alist
`(,tramp-androidsu-method nil ,tramp-root-id-string)))
(defun tramp-enable-androidsu-method ()
"Enable \"androidsu\" method."
(add-to-list 'tramp-methods
`(,tramp-androidsu-method
(tramp-login-program "su")
(tramp-login-args (("-") ("%u")))
(tramp-remote-shell ,tramp-androidsu-local-shell-name)
(tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-tmpdir ,tramp-androidsu-local-tmp-directory)
(tramp-connection-timeout 10)
(tramp-shell-name ,tramp-androidsu-local-shell-name)))
(add-to-list 'tramp-default-user-alist
`(,tramp-androidsu-method nil ,tramp-root-id-string)))
;;;###tramp-autoload
(when (eq system-type 'android)
(tramp-enable-androidsu-method))
(defvar android-use-exec-loader) ; androidfns.c.

View file

@ -83,6 +83,15 @@
;; Where:
;; SANDBOX is the running sandbox to connect to.
;; It could be an application ID, an instance ID, or a PID.
;;
;;
;;
;; Open a file on a running Apptainer instance:
;;
;; C-x C-f /apptainer:INSTANCE:/path/to/file
;;
;; Where:
;; INSTANCE is the running instance to connect to.
;;; Code:
@ -142,6 +151,14 @@ If it is nil, the default context will be used."
:type '(choice (const "flatpak")
(string)))
;;;###tramp-autoload
(defcustom tramp-apptainer-program "apptainer"
"Name of the Apptainer client program."
:group 'tramp
:version "30.1"
:type '(choice (const "apptainer")
(string)))
;;;###tramp-autoload
(defconst tramp-docker-method "docker"
"Tramp method name to use to connect to Docker containers.")
@ -172,6 +189,10 @@ This is for out-of-band connections.")
(defconst tramp-flatpak-method "flatpak"
"Tramp method name to use to connect to Flatpak sandboxes.")
;;;###tramp-autoload
(defconst tramp-apptainer-method "apptainer"
"Tramp method name to use to connect to Apptainer instances.")
;;;###tramp-autoload
(defmacro tramp-skeleton-completion-function (method &rest body)
"Skeleton for `tramp-*-completion-function' with multi-hop support.
@ -373,6 +394,28 @@ see its function help for a description of the format."
lines)))
(mapcar (lambda (name) (list nil name)) (delq nil names)))))
;;;###tramp-autoload
(defun tramp-apptainer--completion-function (method)
"List Apptainer instances available for connection.
This function is used by `tramp-set-completion-function', please
see its function help for a description of the format."
(tramp-skeleton-completion-function method
(when-let ((raw-list
(shell-command-to-string (concat program " instance list")))
;; Ignore header line.
(lines (cdr (split-string raw-list "\n" 'omit)))
(names (mapcar
(lambda (line)
(when (string-match
(rx bol (group (1+ (not space)))
(1+ space) (1+ (not space))
(1+ space) (1+ (not space)))
line)
(match-string 1 line)))
lines)))
(mapcar (lambda (name) (list nil name)) (delq nil names)))))
;;;###tramp-autoload
(defvar tramp-default-remote-shell) ;; Silence byte compiler.
@ -453,29 +496,9 @@ see its function help for a description of the format."
(tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-i" "-c"))))
(add-to-list 'tramp-methods
`(,tramp-toolbox-method
(tramp-login-program ,tramp-toolbox-program)
(tramp-login-args (("run")
("-c" "%h")
("%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 ("-c"))))
(add-to-list 'tramp-default-host-alist `(,tramp-toolbox-method nil ""))
(add-to-list 'tramp-methods
`(,tramp-flatpak-method
(tramp-login-program ,tramp-flatpak-program)
(tramp-login-args (("enter")
("%h")
("%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 ("-c"))))
(add-to-list 'tramp-completion-multi-hop-methods tramp-docker-method)
(add-to-list 'tramp-completion-multi-hop-methods tramp-podman-method)
(add-to-list 'tramp-completion-multi-hop-methods tramp-kubernetes-method)
(tramp-set-completion-function
tramp-docker-method
@ -495,53 +518,99 @@ see its function help for a description of the format."
(tramp-set-completion-function
tramp-kubernetes-method
`((tramp-kubernetes--completion-function ,tramp-kubernetes-method)))
`((tramp-kubernetes--completion-function ,tramp-kubernetes-method))))
(tramp-set-completion-function
tramp-toolbox-method
`((tramp-toolbox--completion-function ,tramp-toolbox-method)))
;;;###tramp-autoload
(defun tramp-enable-toolbox-method ()
"Enable connection to Toolbox containers."
(add-to-list 'tramp-methods
`(,tramp-toolbox-method
(tramp-login-program ,tramp-toolbox-program)
(tramp-login-args (("run")
("-c" "%h")
("%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 ("-c"))))
(tramp-set-completion-function
tramp-flatpak-method
`((tramp-flatpak--completion-function ,tramp-flatpak-method)))
(add-to-list 'tramp-default-host-alist `(,tramp-toolbox-method nil ""))
(add-to-list 'tramp-completion-multi-hop-methods tramp-toolbox-method)
(add-to-list 'tramp-completion-multi-hop-methods tramp-docker-method)
(add-to-list 'tramp-completion-multi-hop-methods tramp-podman-method)
(add-to-list 'tramp-completion-multi-hop-methods tramp-kubernetes-method)
(add-to-list 'tramp-completion-multi-hop-methods tramp-toolbox-method)
(add-to-list 'tramp-completion-multi-hop-methods tramp-flatpak-method)
(tramp-set-completion-function
tramp-toolbox-method
`((tramp-toolbox--completion-function ,tramp-toolbox-method))))
;; Default connection-local variables for Tramp.
;;;###tramp-autoload
(defun tramp-enable-flatpak-method ()
"Enable connection to Flatpak sandboxes."
(add-to-list 'tramp-methods
`(,tramp-flatpak-method
(tramp-login-program ,tramp-flatpak-program)
(tramp-login-args (("enter")
("%h")
("%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 ("-c"))))
(defconst tramp-kubernetes-connection-local-default-variables
'((tramp-config-check . tramp-kubernetes--current-context-data)
;; This variable will be eval'ed in `tramp-expand-args'.
(tramp-extra-expand-args
. (?a (tramp-kubernetes--container (car tramp-current-connection))
?h (tramp-kubernetes--pod (car tramp-current-connection))
?x (tramp-kubernetes--context-namespace
(car tramp-current-connection)))))
"Default connection-local variables for remote kubernetes connections.")
(add-to-list 'tramp-completion-multi-hop-methods tramp-flatpak-method)
(connection-local-set-profile-variables
'tramp-kubernetes-connection-local-default-profile
tramp-kubernetes-connection-local-default-variables)
(tramp-set-completion-function
tramp-flatpak-method
`((tramp-flatpak--completion-function ,tramp-flatpak-method))))
(connection-local-set-profiles
`(:application tramp :protocol ,tramp-kubernetes-method)
'tramp-kubernetes-connection-local-default-profile)
;;;###tramp-autoload
(defun tramp-enable-apptainer-method ()
"Enable connection to Apptainer instances."
(add-to-list 'tramp-methods
`(,tramp-apptainer-method
(tramp-login-program ,tramp-apptainer-program)
(tramp-login-args (("shell")
("instance://%h")
("%h"))) ; Needed for multi-hop check.
(tramp-remote-shell ,tramp-default-remote-shell)
(tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))))
(defconst tramp-flatpak-connection-local-default-variables
`((tramp-remote-path . ,(cons "/app/bin" tramp-remote-path)))
"Default connection-local variables for remote flatpak connections.")
(add-to-list 'tramp-completion-multi-hop-methods tramp-apptainer-method)
(connection-local-set-profile-variables
'tramp-flatpak-connection-local-default-profile
tramp-flatpak-connection-local-default-variables)
(tramp-set-completion-function
tramp-apptainer-method
`((tramp-apptainer--completion-function ,tramp-apptainer-method))))
(connection-local-set-profiles
`(:application tramp :protocol ,tramp-flatpak-method)
'tramp-flatpak-connection-local-default-profile))
;; Default connection-local variables for Tramp.
(defconst tramp-kubernetes-connection-local-default-variables
'((tramp-config-check . tramp-kubernetes--current-context-data)
;; This variable will be eval'ed in `tramp-expand-args'.
(tramp-extra-expand-args
. (?a (tramp-kubernetes--container (car tramp-current-connection))
?h (tramp-kubernetes--pod (car tramp-current-connection))
?x (tramp-kubernetes--context-namespace
(car tramp-current-connection)))))
"Default connection-local variables for remote kubernetes connections.")
(connection-local-set-profile-variables
'tramp-kubernetes-connection-local-default-profile
tramp-kubernetes-connection-local-default-variables)
(connection-local-set-profiles
`(:application tramp :protocol ,tramp-kubernetes-method)
'tramp-kubernetes-connection-local-default-profile)
(defconst tramp-flatpak-connection-local-default-variables
`((tramp-remote-path . ,(cons "/app/bin" tramp-remote-path)))
"Default connection-local variables for remote flatpak connections.")
(connection-local-set-profile-variables
'tramp-flatpak-connection-local-default-profile
tramp-flatpak-connection-local-default-variables)
(connection-local-set-profiles
`(:application tramp :protocol ,tramp-flatpak-method)
'tramp-flatpak-connection-local-default-profile)
(add-hook 'tramp-unload-hook
(lambda ()

View file

@ -1460,6 +1460,15 @@ calling HANDLER.")
;;; Internal functions which must come first:
(defun tramp-enable-method (method)
"Enable optional METHOD if possible."
(interactive "Mmethod: ")
(when-let (((not (assoc method tramp-methods)))
(fn (intern (format "tramp-enable-%s-method" method)))
((functionp fn)))
(funcall fn)
(message "Tramp method \"%s\" enabled" method)))
;; Conversion functions between external representation and
;; internal data structure. Convenience functions for internal
;; data structure.

View file

@ -7064,7 +7064,7 @@ This is used in tests which we don't want to tag
"Check, whether a container method is used.
This does not support some special file names."
(string-match-p
(rx bol (| "docker" "podman"))
(rx bol (| "docker" "podman" "apptainer"))
(file-remote-p ert-remote-temporary-file-directory 'method)))
(defun tramp--test-container-oob-p ()
@ -7233,8 +7233,14 @@ This requires restrictions of file name syntax."
(defun tramp--test-supports-processes-p ()
"Return whether the method under test supports external processes."
(and (or (tramp--test-adb-p) (tramp--test-sh-p) (tramp--test-sshfs-p))
(not (tramp--test-crypt-p))))
;; We use it to enable/disable tests in a given test run, for
;; example for remote processes on MS Windows.
(if (tramp-connection-property-p
tramp-test-vec "tramp--test-supports-processes-p")
(tramp-get-connection-property
tramp-test-vec "tramp--test-supports-processes-p")
(and (or (tramp--test-adb-p) (tramp--test-sh-p) (tramp--test-sshfs-p))
(not (tramp--test-crypt-p)))))
(defun tramp--test-supports-set-file-modes-p ()
"Return whether the method under test supports setting file modes."