services: Add the Guix Data Service.

* gnu/services/guix.scm: New file.
* gnu/tests/guix.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Add both new files.
* doc/guix.texi (Guix Services): New section documenting the Guix Data
Service.
This commit is contained in:
Christopher Baines 2019-09-15 19:16:11 +01:00
parent 1683e4863a
commit dd2a83270b
No known key found for this signature in database
GPG key ID: 5E28A33B0B84F577
4 changed files with 439 additions and 0 deletions

View file

@ -11788,6 +11788,7 @@ declaration.
* Virtualization Services:: Virtualization services.
* Version Control Services:: Providing remote access to Git repositories.
* Game Services:: Game servers.
* Guix Services:: Services relating specifically to Guix.
* Miscellaneous Services:: Other services.
@end menu
@ -24327,6 +24328,57 @@ The port to bind the server to.
@end table
@end deftp
@node Guix Services
@subsection Guix Services
@subsubheading Guix Data Service
The @uref{http://data.guix.gnu.org,Guix Data Service} processes, stores
and provides data about GNU Guix. This includes information about
packages, derivations and lint warnings.
The data is stored in a PostgreSQL database, and available through a web
interface.
@defvar {Scheme Variable} guix-data-service-type
Service type for the Guix Data Service. Its value must be a
@code{guix-data-service-configuration} object. The service optionally
extends the getmail service, as the guix-commits mailing list is used to
find out about changes in the Guix git repository.
@end defvar
@deftp {Data Type} guix-data-service-configuration
Data type representing the configuration of the Guix Data Service.
@table @asis
@item @code{package} (default: @code{guix-data-service})
The Guix Data Service package to use.
@item @code{user} (default: @code{"guix-data-service"})
The system user to run the service as.
@item @code{group} (default: @code{"guix-data-service"})
The system group to run the service as.
@item @code{port} (default: @code{8765})
The port to bind the web service to.
@item @code{host} (default: @code{"127.0.0.1"})
The host to bind the web service to.
@item @code{getmail-idle-mailboxes} (default: @code{#f})
If set, this is the list of mailboxes that the getmail service will be
configured to listen to.
@item @code{commits-getmail-retriever-configuration} (default: @code{#f})
If set, this is the @code{getmail-retriever-configuration} object with
which to configure getmail to fetch mail from the guix-commits mailing
list.
@end table
@end deftp
@node Miscellaneous Services
@subsection Miscellaneous Services

View file

@ -535,6 +535,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 \
@ -599,6 +600,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 \

212
gnu/services/guix.scm Normal file
View file

@ -0,0 +1,212 @@
;;; 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-package
guix-data-service-user
guix-data-service-group
guix-data-service-port
guix-data-service-host
guix-data-service-getmail-idle-mailboxes
guix-data-service-commits-getmail-retriever-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-record 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"))
(chmod "/var/lib/guix-data-service" #o755)
(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-record config <guix-data-service-configuration>
(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.")))

173
gnu/tests/guix.scm Normal file
View file

@ -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))))