From 22dd558c70901a336de97187f0470be584571158 Mon Sep 17 00:00:00 2001 From: Bruno Victal Date: Fri, 27 Jan 2023 21:06:11 +0000 Subject: services: Add hosts-service-type. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * gnu/services/base.scm (): New record type. (host): New procedure. (hosts-service-type): New variable. * doc/guix.texi (Service Reference): Document it. Co-authored-by: Ludovic Courtès --- gnu/services/base.scm | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) (limited to 'gnu/services') diff --git a/gnu/services/base.scm b/gnu/services/base.scm index 9e799445d2..e9fdafd5d0 100644 --- a/gnu/services/base.scm +++ b/gnu/services/base.scm @@ -20,6 +20,7 @@ ;;; Copyright © 2022 Guillaume Le Vaillant ;;; Copyright © 2022 Justin Veilleux ;;; Copyright © 2022 ( +;;; Copyright © 2023 Bruno Victal ;;; ;;; This file is part of GNU Guix. ;;; @@ -103,6 +104,14 @@ console-font-service virtual-terminal-service-type + host + %host + host? + host-address + host-canonical-name + host-aliases + hosts-service-type + static-networking static-networking? static-networking-addresses @@ -685,6 +694,72 @@ to add @var{device} to the kernel's entropy pool. The service will fail if (rngd-configuration (rng-tools rng-tools) (device device)))) + +;;; +;;; /etc/hosts +;;; + +(define (valid-name? name) + "Return true if @var{name} is likely to be a valid host name." + (false-if-exception (not (string-any char-set:whitespace name)))) + +(define-compile-time-procedure (assert-valid-name (name valid-name?)) + "Ensure @var{name} is likely to be a valid host name." + ;; TODO: RFC compliant implementation. + (unless (valid-name? name) + (raise + (make-compound-condition + (formatted-message (G_ "host name '~a' contains invalid characters") + name) + (condition (&error-location + (location + (source-properties->location procedure-call-location))))))) + name) + +(define-record-type* %host + ;; XXX: Using the record type constructor becomes tiresome when + ;; there's multiple records to make. + make-host host? + (address host-address) + (canonical-name host-canonical-name + (sanitize assert-valid-name)) + (aliases host-aliases + (default '()) + (sanitize (cut map assert-valid-name <>)))) + +(define* (host address canonical-name #:optional (aliases '())) + "Return a new record for the host at @var{address} with the given +@var{canonical-name} and possibly @var{aliases}. + +@var{address} must be a string denoting a valid IPv4 or IPv6 address, and +@var{canonical-name} and the strings listed in @var{aliases} must be valid +host names." + (%host + (address address) + (canonical-name canonical-name) + (aliases aliases))) + +(define hosts-service-type + ;; Extend etc-service-type with a entry for @file{/etc/hosts}. + (let* ((serialize-host-record + (lambda (record) + (match-record record (address canonical-name aliases) + (format #f "~a~/~a~{~^~/~a~}~%" address canonical-name aliases)))) + (host-etc-service + (lambda (lst) + `(("hosts" ,(plain-file "hosts" + (format #f "~{~a~}" + (map serialize-host-record + lst)))))))) + (service-type + (name 'etc-hosts) + (extensions + (list + (service-extension etc-service-type + host-etc-service))) + (compose concatenate) + (extend append) + (description "Populate the @file{/etc/hosts} file.")))) ;;; -- cgit v1.2.3