1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2019 Danny Milosavljevic <dannym@scratchpost.org>
3 ;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
5 ;;; This file is part of GNU Guix.
7 ;;; GNU Guix is free software; you can redistribute it and/or modify it
8 ;;; under the terms of the GNU General Public License as published by
9 ;;; the Free Software Foundation; either version 3 of the License, or (at
10 ;;; your option) any later version.
12 ;;; GNU Guix is distributed in the hope that it will be useful, but
13 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;;; GNU General Public License for more details.
17 ;;; You should have received a copy of the GNU General Public License
18 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
20 (define-module (gnu tests docker)
21 #:use-module (gnu tests)
22 #:use-module (gnu system)
23 #:use-module (gnu system file-systems)
24 #:use-module (gnu system vm)
25 #:use-module (gnu services)
26 #:use-module (gnu services dbus)
27 #:use-module (gnu services networking)
28 #:use-module (gnu services docker)
29 #:use-module (gnu services desktop)
30 #:use-module (gnu packages bootstrap) ; %bootstrap-guile
31 #:use-module (gnu packages docker)
32 #:use-module (gnu packages guile)
33 #:use-module (guix gexp)
34 #:use-module (guix grafts)
35 #:use-module (guix monads)
36 #:use-module (guix packages)
37 #:use-module (guix profiles)
38 #:use-module (guix scripts pack)
39 #:use-module (guix store)
40 #:use-module (guix tests)
41 #:use-module (guix build-system trivial)
42 #:use-module ((guix licenses) #:prefix license:)
43 #:export (%test-docker
47 (simple-operating-system
48 (service dhcp-client-service-type)
51 (service elogind-service-type)
52 (service docker-service-type)))
54 (define (run-docker-test docker-tarball)
55 "Load DOCKER-TARBALL as Docker image and run it in a Docker container,
58 (marionette-operating-system
60 #:imported-modules '((gnu services herd)
67 (disk-image-size (* 1500 (expt 2 20)))
68 (port-forwardings '())))
71 (with-imported-modules '((gnu build marionette))
73 (use-modules (srfi srfi-11) (srfi srfi-64)
74 (gnu build marionette))
77 (make-marionette (list #$vm)))
84 (test-assert "service running"
87 (use-modules (gnu services herd))
88 (match (start-service 'dockerd)
90 (('service response-parts ...)
91 (match (assq-ref response-parts 'running)
92 ((pid) (number? pid))))))
95 (test-eq "fetch version"
99 (system* ,(string-append #$docker-cli "/bin/docker")
103 (test-equal "Load docker image and run it"
109 (let* ((port (apply open-pipe* OPEN_READ args))
110 (output (read-line port))
111 (status (close-pipe port)))
113 (let* ((raw-line (slurp ,(string-append #$docker-cli
117 (repository&tag (string-drop raw-line
121 ,(string-append #$docker-cli "/bin/docker")
122 "run" "--entrypoint" "bin/Guile"
129 (exit (= (test-runner-fail-count (test-runner-current)) 0)))))
131 (gexp->derivation "docker-test" test))
133 (define (build-tarball&run-docker-test)
135 ((_ (set-grafting #f))
136 (guile (set-guile-for-build (default-guile)))
137 (guest-script-package ->
139 (name "guest-script")
142 (build-system trivial-build-system)
143 (arguments `(#:guile ,%bootstrap-guile
145 (let ((out (assoc-ref %outputs "out")))
147 (call-with-output-file (string-append out "/a.scm")
149 (display "(display \"hello world\n\")" port)))
151 (synopsis "Display hello world using Guile")
152 (description "This package displays the text \"hello world\" on the
153 standard output device and then enters a new line.")
155 (license license:public-domain)))
156 (profile (profile-derivation (packages->manifest
157 (list %bootstrap-guile
158 guest-script-package))
161 (tarball (docker-image "docker-pack" profile
162 #:symlinks '(("/bin/Guile" -> "bin/guile")
163 ("aa.scm" -> "a.scm"))
164 #:localstatedir? #t)))
165 (run-docker-test tarball)))
170 (description "Test Docker container of Guix.")
171 (value (build-tarball&run-docker-test))))
174 (define (run-docker-system-test tarball)
175 "Load DOCKER-TARBALL as Docker image and run it in a Docker container,
178 (marionette-operating-system
180 #:imported-modules '((gnu services herd)
181 (guix combinators))))
185 (operating-system os)
186 ;; FIXME: Because we're using the volatile-root setup where the root file
187 ;; system is a tmpfs overlaid over a small root file system, 'docker
188 ;; load' must be able to store the whole image into memory, hence the
189 ;; huge memory requirements. We should avoid the volatile-root setup
192 (port-forwardings '())))
195 (with-imported-modules '((gnu build marionette)
198 (use-modules (srfi srfi-11) (srfi srfi-64)
199 (gnu build marionette)
203 (make-marionette (list #$vm)))
208 (test-begin "docker")
210 (test-assert "service running"
213 (use-modules (gnu services herd))
214 (match (start-service 'dockerd)
216 (('service response-parts ...)
217 (match (assq-ref response-parts 'running)
218 ((pid) (number? pid))))))
221 (test-assert "load system image and run it"
224 (define (slurp command . args)
225 ;; Return the output from COMMAND.
226 (let* ((port (apply open-pipe* OPEN_READ command args))
227 (output (read-line port))
228 (status (close-pipe port)))
231 (define (docker-cli command . args)
232 ;; Run the given Docker COMMAND.
233 (apply invoke #$(file-append docker-cli "/bin/docker")
236 (define (wait-for-container-file container file)
237 ;; Wait for FILE to show up in CONTAINER.
238 (docker-cli "exec" container
239 #$(file-append guile-2.2 "/bin/guile")
244 (error "file didn't show up" ,file))
245 (unless (file-exists? ,file)
249 (let* ((line (slurp #$(file-append docker-cli "/bin/docker")
250 "load" "-i" #$tarball))
251 (repository&tag (string-drop line
255 #$(file-append docker-cli "/bin/docker")
256 "create" repository&tag)))
257 (docker-cli "start" container)
259 ;; Wait for shepherd to be ready.
260 (wait-for-container-file container
261 "/var/run/shepherd/socket")
263 (docker-cli "exec" container
264 "/run/current-system/profile/bin/herd"
266 (slurp #$(file-append docker-cli "/bin/docker")
268 "/run/current-system/profile/bin/herd"
269 "status" "guix-daemon")))
273 (exit (= (test-runner-fail-count (test-runner-current)) 0)))))
275 (gexp->derivation "docker-system-test" test))
277 (define %test-docker-system
279 (name "docker-system")
280 (description "Run a system image as produced by @command{guix system
281 docker-image} inside Docker.")
282 (value (with-monad %store-monad
283 (>>= (system-docker-image (simple-operating-system))
284 run-docker-system-test)))))