From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52818) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eQIuO-0005tI-0y for guix-patches@gnu.org; Sat, 16 Dec 2017 15:18:10 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eQIuJ-0003Hi-3j for guix-patches@gnu.org; Sat, 16 Dec 2017 15:18:07 -0500 Received: from debbugs.gnu.org ([208.118.235.43]:57255) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eQIuI-0003HP-Um for guix-patches@gnu.org; Sat, 16 Dec 2017 15:18:03 -0500 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1eQIuI-0002AW-OT for guix-patches@gnu.org; Sat, 16 Dec 2017 15:18:02 -0500 Subject: [bug#29741] [PATCH 2/2] gnu: services: web: Add service for apache-httpd. Resent-Message-ID: From: Christopher Baines Date: Sat, 16 Dec 2017 20:17:00 +0000 Message-Id: <20171216201700.23564-2-mail@cbaines.net> In-Reply-To: <20171216201700.23564-1-mail@cbaines.net> References: <20171216201700.23564-1-mail@cbaines.net> List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+kyle=kyleam.com@gnu.org Sender: "Guix-patches" To: 29741@debbugs.gnu.org * gnu/services/web.scm (, , ): New record types. (%default-apache-httpd-modules, %apache-httpd-accounts, apache-httpd-service-type): New variables. (apache-httpd-shepherd-services, apache-httpd-activation, apache-httpd-process-extensions): New procedures. * gnu/tests/web.scm (run-apache-httpd-test): New procedure. (%apache-httpd-os, %tests-apache-httpd): New variables. --- gnu/services/web.scm | 227 ++++++++++++++++++++++++++++++++++++++++++++++++++- gnu/tests/web.scm | 82 ++++++++++++++++++- 2 files changed, 307 insertions(+), 2 deletions(-) diff --git a/gnu/services/web.scm b/gnu/services/web.scm index 582cf535c..8bfa1bc9b 100644 --- a/gnu/services/web.scm +++ b/gnu/services/web.scm @@ -33,8 +33,36 @@ #:use-module ((guix utils) #:select (version-major)) #:use-module ((guix packages) #:select (package-version)) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-9) #:use-module (ice-9 match) - #:export ( + #:export ( + apache-httpd-configuration + apache-httpd-configuration? + apache-httpd-configuration-package + apache-httpd-configuration-pid-file + apache-httpd-configuration-config + + + apache-httpd-virtualhost + apache-httpd-virtualhost? + apache-httpd-virtualhost-addresses-and-ports + apache-httpd-virtualhost-contents + + + apache-httpd-config-file + apache-httpd-config-file? + apache-httpd-config-file-load-modules + apache-httpd-config-file-server-root + apache-httpd-config-file-server-name + apache-httpd-config-file-listen + apache-httpd-config-file-pid-file + apache-httpd-config-file-error-log + apache-httpd-config-file-user + apache-httpd-config-file-group + + apache-httpd-service-type + + nginx-configuration nginx-configuration? nginx-configuartion-nginx @@ -132,6 +160,203 @@ ;;; ;;; Code: +(define-record-type* + apache-httpd-load-module make-apache-httpd-load-module + apache-httpd-load-module? + (name apache-httpd-load-module-name) + (file apache-httpd-load-module-file)) + +(define %default-apache-httpd-modules + (map (match-lambda + ((name file) + (apache-httpd-load-module + (name name) + (file file)))) + '(("authn_file_module" "modules/mod_authn_file.so") + ("authn_core_module" "modules/mod_authn_core.so") + ("authz_host_module" "modules/mod_authz_host.so") + ("authz_groupfile_module" "modules/mod_authz_groupfile.so") + ("authz_user_module" "modules/mod_authz_user.so") + ("authz_core_module" "modules/mod_authz_core.so") + ("access_compat_module" "modules/mod_access_compat.so") + ("auth_basic_module" "modules/mod_auth_basic.so") + ("reqtimeout_module" "modules/mod_reqtimeout.so") + ("filter_module" "modules/mod_filter.so") + ("mime_module" "modules/mod_mime.so") + ("log_config_module" "modules/mod_log_config.so") + ("env_module" "modules/mod_env.so") + ("headers_module" "modules/mod_headers.so") + ("setenvif_module" "modules/mod_setenvif.so") + ("version_module" "modules/mod_version.so") + ("unixd_module" "modules/mod_unixd.so") + ("status_module" "modules/mod_status.so") + ("autoindex_module" "modules/mod_autoindex.so") + ("dir_module" "modules/mod_dir.so") + ("alias_module" "modules/mod_alias.so")))) + +(define-record-type* + apache-httpd-config-file make-apache-httpd-config-file + apache-httpd-config-file? + (load-modules apache-httpd-config-file-load-modules + (default %default-apache-httpd-modules)) + (server-root apache-httpd-config-file-server-root + (default httpd)) + (server-name apache-httpd-config-file-server-name + (default #f)) + (document-root apache-httpd-config-file-document-root + (default "/srv/http")) + (listen apache-httpd-config-file-listen + (default '("80"))) + (pid-file apache-httpd-config-file-pid-file + (default "/var/run/apache-httpd")) + (error-log apache-httpd-config-file-error-log + (default "/var/log/apache-httpd/error_log")) + (user apache-httpd-config-file-user + (default "apache-httpd")) + (group apache-httpd-config-file-group + (default "apache-httpd")) + (extra-config apache-httpd-config-file-extra-config + (default + `("TypesConfig " ,(file-append httpd "/etc/httpd/mime.types") "\n")))) + +(define-gexp-compiler (apache-httpd-config-file-compiler + (file ) system target) + (match file + (($ load-modules server-root server-name + document-root listen pid-file error-log + user group extra-config) + (gexp->derivation + "httpd.conf" + #~(call-with-output-file (ungexp output "out") + (lambda (port) + (display + (string-append + (ungexp-splicing + `(,@(append-map + (match-lambda + (($ name module) + `("LoadModule " ,name " " ,module "\n"))) + load-modules) + ,@`("ServerRoot " ,server-root "\n") + ,@(if server-name + `("ServerName " ,server-name "\n") + '()) + ,@`("DocumentRoot " ,document-root "\n") + ,@(append-map + (lambda (listen-value) + `("Listen " ,listen-value "\n")) + listen) + ,@(if pid-file + `("Pidfile " ,pid-file "\n") + '()) + ,@(if error-log + `("ErrorLog " ,error-log "\n") + '()) + ,@(if user + `("User " ,user "\n") + '()) + ,@(if group + `("Group " ,group "\n") + '()) + "\n\n" + ,@extra-config))) + port))) + #:local-build? #t)))) + +(define-record-type + (apache-httpd-virtualhost addresses-and-ports contents) + apache-httpd-virtualhost? + (addresses-and-ports apache-httpd-virtualhost-addresses-and-ports) + (contents apache-httpd-virtualhost-contents)) + +(define-record-type* + apache-httpd-configuration make-apache-httpd-configuration + apache-httpd-configuration? + (package apache-httpd-configuration-package + (default httpd)) + (pid-file apache-httpd-configuration-pid-file + (default "/var/run/apache-httpd")) + (config apache-httpd-configuration-config + (default (apache-httpd-config-file)))) + +(define %apache-httpd-accounts + (list (user-group (name "apache-httpd") (system? #t)) + (user-account + (name "apache-httpd") + (group "apache-httpd") + (system? #t) + (comment "Apache HTTPD server user") + (home-directory "/var/empty") + (shell (file-append shadow "/sbin/nologin"))))) + +(define apache-httpd-shepherd-services + (match-lambda + (($ package pid-file config) + (list (shepherd-service + (provision '(apache-httpd)) + (documentation "The Apache HTTP Server") + (requirement '(networking)) + (start #~(make-forkexec-constructor + `(#$(file-append package "/bin/httpd") + #$@(if config + (list "-f" config) + '())) + #:pid-file #$pid-file)) + (stop #~(make-kill-destructor))))))) + +(define apache-httpd-activation + (match-lambda + (($ package pid-file config) + (match-record + config + + (error-log document-root) + #~(begin + (use-modules (guix build utils)) + + (mkdir-p #$(dirname error-log)) + (mkdir-p #$document-root)))))) + +(define (apache-httpd-process-extensions original-config extension-configs) + (let ((config (apache-httpd-configuration-config + original-config))) + (if (apache-httpd-config-file? config) + (apache-httpd-configuration + (inherit original-config) + (config + (apache-httpd-config-file + (inherit config) + (extra-config + (append (apache-httpd-config-file-extra-config config) + (append-map + (match-lambda + (($ + addresses-and-ports + contents) + `(,(string-append + "\n") + ,@contents + "\n\n")) + ((? string? x) + `("\n" ,x "\n")) + ((? list? x) + `("\n" ,@x "\n"))) + extension-configs))))))))) + +(define apache-httpd-service-type + (service-type (name 'apache-httpd) + (extensions + (list (service-extension shepherd-root-service-type + apache-httpd-shepherd-services) + (service-extension activation-service-type + apache-httpd-activation) + (service-extension account-service-type + (const %apache-httpd-accounts)))) + (compose concatenate) + (extend apache-httpd-process-extensions) + (default-value + (apache-httpd-configuration)))) + (define-record-type* nginx-server-configuration make-nginx-server-configuration nginx-server-configuration? diff --git a/gnu/tests/web.scm b/gnu/tests/web.scm index b84f072ac..1f4ab697c 100644 --- a/gnu/tests/web.scm +++ b/gnu/tests/web.scm @@ -28,7 +28,8 @@ #:use-module (gnu services networking) #:use-module (guix gexp) #:use-module (guix store) - #:export (%test-nginx + #:export (%test-apache-httpd + %test-nginx %test-php-fpm)) (define %index.html-contents @@ -44,6 +45,85 @@ (lambda (port) (display #$%index.html-contents port))))) +(define %apache-httpd-os + ;; Operating system under test. + (simple-operating-system + (dhcp-client-service) + (service apache-httpd-service-type + (apache-httpd-configuration + (config (apache-httpd-config-file + (listen '("8080")))))) + (simple-service 'make-http-root activation-service-type + %make-http-root))) + +(define* (run-apache-httpd-test #:optional (http-port 8080)) + "Run tests in %APACHE-HTTPD-OS, which has apache-httpd running and listening on +HTTP-PORT." + (define os + (marionette-operating-system + %apache-httpd-os + #:imported-modules '((gnu services herd) + (guix combinators)))) + + (define vm + (virtual-machine + (operating-system os) + (port-forwardings `((,http-port . 8080))))) + + (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 "apache-httpd") + + ;; Wait for apache-httpd to be up and running. + (test-assert "service running" + (marionette-eval + '(begin + (use-modules (gnu services herd)) + (match (start-service 'apache-httpd) + (#f #f) + (('service response-parts ...) + (match (assq-ref response-parts 'running) + ((pid) (number? pid)))))) + marionette)) + + ;; Retrieve the index.html file we put in /srv. + (test-equal "http-get" + '(200 #$%index.html-contents) + (let-values (((response text) + (http-get "http://localhost:8080/index.html" + #:decode-body? #t))) + (list (response-code response) text))) + + ;; There should be a log file in here. + (test-assert "log file" + (marionette-eval + '(file-exists? "/var/log/apache-httpd/error_log") + marionette)) + + (test-end) + (exit (= (test-runner-fail-count (test-runner-current)) 0))))) + + (gexp->derivation "apache-httpd-test" test)) + +(define %test-apache-httpd + (system-test + (name "apache-httpd") + (description "Connect to a running APACHE-HTTPD server.") + (value (run-apache-httpd-test)))) + (define %nginx-servers ;; Server blocks. (list (nginx-server-configuration -- 2.14.1