diff mbox series

[bug#37412,2/2] services: Add the Guix Data Service.

Message ID 20190915182127.10525-2-mail@cbaines.net
State Accepted
Headers show
Series Add package and service for the Guix Data Service. | expand

Commit Message

Christopher Baines Sept. 15, 2019, 6:21 p.m. UTC
* gnu/services/guix.scm: New file.
* gnu/tests/guix.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Add both new files.
---
 gnu/local.mk          |   2 +
 gnu/services/guix.scm | 204 ++++++++++++++++++++++++++++++++++++++++++
 gnu/tests/guix.scm    | 173 +++++++++++++++++++++++++++++++++++
 3 files changed, 379 insertions(+)
 create mode 100644 gnu/services/guix.scm
 create mode 100644 gnu/tests/guix.scm

Comments

Ludovic Courtès Sept. 16, 2019, 7:53 a.m. UTC | #1
Christopher Baines <mail@cbaines.net> skribis:

> * gnu/services/guix.scm: New file.
> * gnu/tests/guix.scm: New file.
> * gnu/local.mk (GNU_SYSTEM_MODULES): Add both new files.

Yay, nice!

> +  (commits-getmail-retriever-configuration
> +   guix-data-service-commits-getmail-retriever-configuration

New world record: longer than ‘call-with-current-continuation’.  :-)

> +(define (guix-data-service-shepherd-services config)
> +  (match config
> +    (($ <guix-data-service-configuration> package user group
> +                                          port host)

Perhaps use ‘match-record’ here and elsewhere, to avoid mistakes when
the record type changes.

> +(define %test-guix-data-service
> +  (system-test
> +   (name "guix-data-service")
> +   (description "Connect to a running Guix Data Service.")
> +   (value (run-guix-data-service-test))))

Nice.

Could you add a bit to guix.texi, maybe under “Continuous Integration”?
You don’t have to go into too much detail if you think some of the
configuration elements are subject to change.

Thank you!

Ludo’.
Christopher Baines Sept. 22, 2019, 12:15 p.m. UTC | #2
Ludovic Courtès <ludo@gnu.org> writes:

> Christopher Baines <mail@cbaines.net> skribis:
>
>> +(define (guix-data-service-shepherd-services config)
>> +  (match config
>> +    (($ <guix-data-service-configuration> package user group
>> +                                          port host)
>
> Perhaps use ‘match-record’ here and elsewhere, to avoid mistakes when
> the record type changes.

Yeah, I've switched a couple of the match statements across to
match-record, but I've left one, as it has a couple of clauses.

>> +(define %test-guix-data-service
>> +  (system-test
>> +   (name "guix-data-service")
>> +   (description "Connect to a running Guix Data Service.")
>> +   (value (run-guix-data-service-test))))
>
> Nice.
>
> Could you add a bit to guix.texi, maybe under “Continuous Integration”?
> You don’t have to go into too much detail if you think some of the
> configuration elements are subject to change.

I forgot you mentioned the "Continuous Integration" section, so I
actually added something under a new "Guix" section, but regardless,
I've now sent some new patches, which includes some documentation.
diff mbox series

Patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 3f32b9cbf2..b30afdd585 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -532,6 +532,7 @@  GNU_SYSTEM_MODULES =				\
   %D%/services/authentication.scm		\
   %D%/services/games.scm			\
   %D%/services/getmail.scm				\
+  %D%/services/guix.scm			\
   %D%/services/kerberos.scm			\
   %D%/services/lirc.scm				\
   %D%/services/virtualization.scm		\
@@ -596,6 +597,7 @@  GNU_SYSTEM_MODULES =				\
   %D%/tests/desktop.scm				\
   %D%/tests/dict.scm				\
   %D%/tests/docker.scm				\
+  %D%/tests/guix.scm				\
   %D%/tests/monitoring.scm                      \
   %D%/tests/nfs.scm				\
   %D%/tests/install.scm				\
diff --git a/gnu/services/guix.scm b/gnu/services/guix.scm
new file mode 100644
index 0000000000..65cffce2c0
--- /dev/null
+++ b/gnu/services/guix.scm
@@ -0,0 +1,204 @@ 
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Christopher Baines <mail@cbaines.net>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix 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.
+;;;
+;;; GNU Guix 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 GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu services guix)
+  #:use-module (ice-9 match)
+  #:use-module (guix gexp)
+  #:use-module (guix records)
+  #:use-module ((gnu packages base)
+                #:select (glibc-utf8-locales))
+  #:use-module (gnu packages admin)
+  #:use-module (gnu packages web)
+  #:use-module (gnu services)
+  #:use-module (gnu services base)
+  #:use-module (gnu services admin)
+  #:use-module (gnu services shepherd)
+  #:use-module (gnu services getmail)
+  #:use-module (gnu system shadow)
+  #:export (<guix-data-service-configuration>
+            guix-data-service-configuration
+            guix-data-service-configuration?
+
+            guix-data-service-type))
+
+;;;; Commentary:
+;;;
+;;; This module implements a service that to run instances of the Guix Data
+;;; Service, which provides data about Guix over time.
+;;;
+;;;; Code:
+
+(define-record-type* <guix-data-service-configuration>
+  guix-data-service-configuration make-guix-data-service-configuration
+  guix-data-service-configuration?
+  (package          guix-data-service-package
+                    (default guix-data-service))
+  (user             guix-data-service-configuration-user
+                    (default "guix-data-service"))
+  (group            guix-data-service-configuration-group
+                    (default "guix-data-service"))
+  (port             guix-data-service-port
+                    (default 8765))
+  (host             guix-data-service-host
+                    (default "127.0.0.1"))
+  (getmail-idle-mailboxes
+   guix-data-service-getmail-idle-mailboxes
+   (default #f))
+  (commits-getmail-retriever-configuration
+   guix-data-service-commits-getmail-retriever-configuration
+   (default #f)))
+
+(define (guix-data-service-profile-packages config)
+  "Return the guix-data-service package, this will populate the
+ca-certificates.crt file in the system profile."
+  (list
+   (guix-data-service-package config)))
+
+(define (guix-data-service-shepherd-services config)
+  (match config
+    (($ <guix-data-service-configuration> package user group
+                                          port host)
+     (list
+      (shepherd-service
+       (documentation "Guix Data Service web server")
+       (provision '(guix-data-service))
+       (requirement '(postgres networking))
+       (start #~(make-forkexec-constructor
+                 (list #$(file-append package
+                                      "/bin/guix-data-service")
+                       "--pid-file=/var/run/guix-data-service/pid"
+                       #$(string-append "--port=" (number->string port))
+                       #$(string-append "--host=" host)
+                       ;; Perform any database migrations when the
+                       ;; service is started
+                       "--update-database")
+
+                 #:user #$user
+                 #:group #$group
+                 #:pid-file "/var/run/guix-data-service/pid"
+                 ;; Allow time for migrations to run
+                 #:pid-file-timeout 60
+                 #:environment-variables
+                 `(,(string-append
+                     "GUIX_LOCPATH=" #$glibc-utf8-locales "/lib/locale")
+                   "LC_ALL=en_US.utf8")
+                 #:log-file "/var/log/guix-data-service/web.log"))
+       (stop #~(make-kill-destructor)))
+
+      (shepherd-service
+       (documentation "Guix Data Service process jobs")
+       (provision '(guix-data-service-process-jobs))
+       (requirement '(postgres
+                      networking
+                      ;; Require guix-data-service, as that the database
+                      ;; migrations are handled through this service
+                      guix-data-service))
+       (start #~(make-forkexec-constructor
+                 (list
+                  #$(file-append package
+                                 "/bin/guix-data-service-process-jobs"))
+                 #:user #$user
+                 #:group #$group
+                 #:environment-variables
+                 `("HOME=/var/lib/guix-data-service"
+                   "GIT_SSL_CAINFO=/etc/ssl/certs/ca-certificates.crt"
+                   ,(string-append
+                     "GUIX_LOCPATH=" #$glibc-utf8-locales "/lib/locale")
+                   "LC_ALL=en_US.utf8")
+                 #:log-file "/var/log/guix-data-service/process-jobs.log"))
+       (stop #~(make-kill-destructor)))))))
+
+(define (guix-data-service-activation config)
+  #~(begin
+      (use-modules (guix build utils))
+
+      (define %user (getpw "guix-data-service"))
+
+      (mkdir-p "/var/log/guix-data-service")
+
+      ;; Allow writing the PID file
+      (mkdir-p "/var/run/guix-data-service")
+      (chown "/var/run/guix-data-service"
+             (passwd:uid %user)
+             (passwd:gid %user))))
+
+(define (guix-data-service-account config)
+  (match config
+    (($ <guix-data-service-configuration> package user group)
+     (list (user-group
+            (name group)
+            (system? #t))
+           (user-account
+            (name user)
+            (group group)
+            (system? #t)
+            (comment "Guix Data Service user")
+            (home-directory "/var/lib/guix-data-service")
+            (shell (file-append shadow "/sbin/nologin")))))))
+
+(define (guix-data-service-getmail-configuration config)
+  (match config
+    (($ <guix-data-service-configuration> package user group
+                                          port host
+                                          #f #f)
+     '())
+    (($ <guix-data-service-configuration> package user group
+                                          port host
+                                          getmail-idle-mailboxes
+                                          commits-getmail-retriever-configuration)
+     (list
+      (getmail-configuration
+       (name 'guix-data-service)
+       (user user)
+       (group group)
+       (directory "/var/lib/getmail/guix-data-service")
+       (rcfile
+        (getmail-configuration-file
+         (retriever commits-getmail-retriever-configuration)
+         (destination
+          (getmail-destination-configuration
+           (type "MDA_external")
+           (path (file-append
+                  package
+                  "/bin/guix-data-service-process-branch-updated-email"))))
+         (options
+          (getmail-options-configuration
+           (read-all #f)
+           (delivered-to #f)
+           (received #f)))))
+       (idle getmail-idle-mailboxes))))))
+
+(define guix-data-service-type
+  (service-type
+   (name 'guix-data-service)
+   (extensions
+    (list
+     (service-extension profile-service-type
+                        guix-data-service-profile-packages)
+     (service-extension shepherd-root-service-type
+                        guix-data-service-shepherd-services)
+     (service-extension activation-service-type
+                        guix-data-service-activation)
+     (service-extension account-service-type
+                        guix-data-service-account)
+     (service-extension getmail-service-type
+                        guix-data-service-getmail-configuration)))
+   (default-value
+     (guix-data-service-configuration))
+   (description
+    "Run an instance of the Guix Data Service.")))
diff --git a/gnu/tests/guix.scm b/gnu/tests/guix.scm
new file mode 100644
index 0000000000..6139e31cf0
--- /dev/null
+++ b/gnu/tests/guix.scm
@@ -0,0 +1,173 @@ 
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Christopher Baines <mail@cbaines.net>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix 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.
+;;;
+;;; GNU Guix 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 GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu tests guix)
+  #:use-module (gnu tests)
+  #:use-module (gnu system)
+  #:use-module (gnu system file-systems)
+  #:use-module (gnu system shadow)
+  #:use-module (gnu system vm)
+  #:use-module (gnu services)
+  #:use-module (gnu services guix)
+  #:use-module (gnu services databases)
+  #:use-module (gnu services shepherd)
+  #:use-module (gnu services networking)
+  #:use-module (gnu packages databases)
+  #:use-module (guix packages)
+  #:use-module (guix modules)
+  #:use-module (guix records)
+  #:use-module (guix gexp)
+  #:use-module (guix store)
+  #:use-module (guix utils)
+  #:use-module (ice-9 match)
+  #:export (%test-guix-data-service))
+
+
+;;;
+;;; Guix Data Service
+;;;
+
+(define guix-data-service-initial-database-setup-service
+  (let ((user "guix_data_service")
+        (name "guix_data_service"))
+    (define start-gexp
+      #~(lambda ()
+          (let ((pid (primitive-fork))
+                (postgres (getpwnam "postgres")))
+            (if (eq? pid 0)
+                (dynamic-wind
+                  (const #t)
+                  (lambda ()
+                    (setgid (passwd:gid postgres))
+                    (setuid (passwd:uid postgres))
+                    (primitive-exit
+                     (if (and
+                          (zero?
+                           (system* #$(file-append postgresql "/bin/createuser")
+                                    #$user))
+                          (zero?
+                           (system* #$(file-append postgresql "/bin/createdb")
+                                    "-O" #$user #$name)))
+                         0
+                         1)))
+                  (lambda ()
+                    (primitive-exit 1)))
+                (zero? (cdr (waitpid pid)))))))
+
+    (shepherd-service
+     (requirement '(postgres))
+     (provision '(guix-data-service-initial-database-setup))
+     (start start-gexp)
+     (stop #~(const #f))
+     (respawn? #f)
+     (one-shot? #t)
+     (documentation "Setup Guix Data Service database."))))
+
+(define %guix-data-service-os
+  (simple-operating-system
+   (service dhcp-client-service-type)
+   (service postgresql-service-type
+            (postgresql-configuration
+             (config-file
+              (postgresql-config-file
+               (hba-file
+                (plain-file "pg_hba.conf"
+                            "
+local	all	all			trust
+host	all	all	127.0.0.1/32 	trust
+host	all	all	::1/128 	trust"))))))
+   (service guix-data-service-type
+            (guix-data-service-configuration
+             (host "0.0.0.0")))
+   (simple-service 'guix-data-service-database-setup
+                   shepherd-root-service-type
+                   (list guix-data-service-initial-database-setup-service))))
+
+(define (run-guix-data-service-test)
+  (define os
+    (marionette-operating-system
+     %guix-data-service-os
+     #:imported-modules '((gnu services herd)
+                          (guix combinators))))
+
+  (define forwarded-port 8080)
+
+  (define vm
+    (virtual-machine
+     (operating-system os)
+     (memory-size 1024)
+     (port-forwardings `((,forwarded-port . 8765)))))
+
+  (define test
+    (with-imported-modules '((gnu build marionette))
+      #~(begin
+          (use-modules (srfi srfi-11) (srfi srfi-64)
+                       (gnu build marionette)
+                       (web uri)
+                       (web client)
+                       (web response))
+
+          (define marionette
+            (make-marionette (list #$vm)))
+
+          (mkdir #$output)
+          (chdir #$output)
+
+          (test-begin "guix-data-service")
+
+          (test-assert "service running"
+            (marionette-eval
+             '(begin
+                (use-modules (gnu services herd))
+                (match (start-service 'guix-data-service)
+                  (#f #f)
+                  (('service response-parts ...)
+                   (match (assq-ref response-parts 'running)
+                     ((pid) (number? pid))))))
+             marionette))
+
+          (test-assert "process jobs service running"
+            (marionette-eval
+             '(begin
+                (use-modules (gnu services herd))
+                (match (start-service 'guix-data-service-process-jobs)
+                  (#f #f)
+                  (('service response-parts ...)
+                   (match (assq-ref response-parts 'running)
+                     ((pid) (number? pid))))))
+             marionette))
+
+          (test-equal "http-get"
+            200
+            (let-values
+                (((response text)
+                  (http-get #$(simple-format
+                               #f "http://localhost:~A/healthcheck" forwarded-port)
+                            #:decode-body? #t)))
+              (response-code response)))
+
+          (test-end)
+          (exit (= (test-runner-fail-count (test-runner-current)) 0)))))
+
+  (gexp->derivation "guix-data-service-test" test))
+
+(define %test-guix-data-service
+  (system-test
+   (name "guix-data-service")
+   (description "Connect to a running Guix Data Service.")
+   (value (run-guix-data-service-test))))