aboutsummaryrefslogtreecommitdiffstats
path: root/tramp-docker.el
blob: 453e3c2b946ae1d3bb61306f28a848e8dedb38ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
;;; tramp-docker.el --- Tramp integration for Docker containers  -*- lexical-binding: t; -*-

;; Copyright © 2022 Free Software Foundation, Inc.

;; Author: Brian Cully <bjc@kublai.com>
;; Maintainer: Brian Cully <bjc@kublai.com>
;; URL: https://git.spork.org/tramp-docker
;; Keywords: tramp, docker
;; Version: 1.0
;; Package-Requires: ((emacs "23"))

;;; License:

;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation, either version 3 of the
;; License, or (at your option) any later version.

;; This program is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;; General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:

;;
;; ‘tramp-docker’ allows Tramp access to environments provided by
;; Docker.
;;
;; ## Usage
;;
;; Call ‘tramp-docker-setup’ in your Emacs initialization.
;;
;;     (add-hook 'after-init-hook 'tramp-docker-setup)
;;
;; Open a file on a running systemd-docker container:
;;
;;     C-x C-f /docker:USER@CONTAINER:/path/to/file
;;
;; Where:
;;     USER          is the user on the container to connect as (optional)
;;     CONTAINER     is the container to connect to
;;

;;; Code:

(require 'tramp)

(defgroup tramp-docker nil
  "Tramp integration for Docker containers."
  :prefix "tramp-docker-"
  :group 'applications
  :link '(url-link :tag "Github" "https://git.spork.org/tramp-docker")
  :link '(emacs-commentary-link :tag "Commentary" "tramp-docker"))

(defcustom tramp-docker-program "docker"
  "Name of the Docker client program."
  :type '(choice (const "docker")
                 (const "podman")
                 (string))
  :group 'tramp-docker)

(defconst tramp-docker-method "docker"
  "Tramp method name to use to connect to Docker containers.")

(defun tramp-docker--completion-function (&rest _args)
  "List Docker containers available for connection.

This function is used by ‘tramp-set-completion-function’, please
see its function help for a description of the format."
  (message "cf: %s" _args)
  (let* ((raw-list (shell-command-to-string
                    (concat tramp-docker-program
                            " ps --format '{{.ID}}\t{{.Names}}'")))
         (lines (split-string raw-list "\n"))
         (names (mapcar (lambda (line)
                          (let ((words (split-string line "\t")))
                            (or (nth 1 words) (nth 0 words))))
                        lines))
         (machines (seq-take-while (lambda (name) name) names)))
    (message "rli: %s" raw-list)
    (message "lns: %s" lines)
    (message "ia: %s" names)
    (message "ma: %s" machines)
    (mapcar (lambda (m) (list nil m)) machines)))

;; todo: check tramp-async-args and tramp-direct-async
(defun tramp-docker--add-method ()
  "Add Tramp method handler for Docker containers."
  (push `(,tramp-docker-method
          (tramp-login-program ,tramp-docker-program)
          (tramp-login-args (("exec")
                             ("-it")
                             ("-u" "%u")
                             ("%h")
			     ("/bin/sh")))
          (tramp-remote-shell "/bin/sh")
          (tramp-remote-shell-login ("-l"))
          (tramp-remote-shell-args ("-i" "-c")))
        tramp-methods))

(defun tramp-docker--remove-method ()
  "Remove Tramp method handler for docker containers."
  (setf (alist-get tramp-docker-method tramp-methods nil t 'string=) nil))

(defun tramp-docker-unload-function ()
  "Remove Tramp method handler and completion functions."
  (tramp-set-completion-function tramp-docker-method nil)
  (tramp-docker--remove-method)
  nil)

(when nil
  (load-file (buffer-file-name))
  (setq tramp-docker-program "doas podman")
  (setq tramp-verbose 7) ;; default 3
  (tramp-docker-setup)
  (tramp-docker-unload-function))

;;;###autoload
(defun tramp-docker-setup ()
  "Initialize Docker support for Tramp."
  (tramp-docker--add-method)
  (tramp-set-completion-function tramp-docker-method
                                 '((tramp-docker--completion-function ""))))

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