~ruther/guix-local

5266ff719e274056cb3e2b9740183f0063177255 — Christopher Baines 8 years ago 6bbbca9
services: Add MongoDB.

* gnu/services/databases.scm (%default-mongodb-configuration-file,
  %mongodb-accounts, mongodb-service-type): New variables.
  (<mongodb-configuration>): New record type.
  (mongodb-activation, mongodb-shepherd-service): New procedures.
* gnu/tests/databases.scm (%test-mongodb): New variable.
* doc/guix.texi (Database Services): Add MongoDB documentation.
3 files changed, 200 insertions(+), 1 deletions(-)

M doc/guix.texi
M gnu/services/databases.scm
M gnu/tests/databases.scm
M doc/guix.texi => doc/guix.texi +26 -0
@@ 12120,6 12120,32 @@ Additional command line options to pass to @code{memcached}.
@end table
@end deftp

@defvr {Scheme Variable} mongodb-service-type
This is the service type for @uref{https://www.mongodb.com/, MongoDB}.
The value for the service type is a @code{mongodb-configuration} object.
@end defvr

@example
(service mongodb-service-type)
@end example

@deftp {Data Type} mongodb-configuration
Data type representing the configuration of mongodb.

@table @asis
@item @code{mongodb} (default: @code{mongodb})
The MongoDB package to use.

@item @code{config-file} (default: @code{%default-mongodb-configuration-file})
The configuration file for MongoDB.

@item @code{data-directory} (default: @code{"/var/lib/mongodb"})
This value is used to create the directory, so that it exists and is
owned by the mongodb user.  It should match the data-directory which
MongoDB is configured to use through the configuration file.
@end table
@end deftp

@defvr {Scheme Variable} redis-service-type
This is the service type for the @uref{https://redis.io/, Redis}
key/value store, whose value is a @code{redis-configuration} object.

M gnu/services/databases.scm => gnu/services/databases.scm +89 -0
@@ 44,6 44,14 @@
            memcached-configuration-udp-port
            memcached-configuration-additional-options

            <mongodb-configuration>
            mongodb-configuration
            mongodb-configuration?
            mongodb-configuration-mongodb
            mongodb-configuration-config-file
            mongodb-configuration-data-directory
            mongodb-service-type

            mysql-service
            mysql-service-type
            mysql-configuration


@@ 264,6 272,87 @@ and stores the database cluster in @var{data-directory}."


;;;
;;; MongoDB
;;;

(define %default-mongodb-configuration-file
  (plain-file
   "mongodb.yaml"
   "# GNU Guix: MongoDB default configuration file
processManagement:
  pidFilePath: /var/run/mongodb/pid
storage:
  dbPath: /var/lib/mongodb
"))


(define-record-type* <mongodb-configuration>
  mongodb-configuration make-mongodb-configuration
  mongodb-configuration?
  (mongodb             mongodb-configuration-mongodb
                       (default mongodb))
  (config-file         mongodb-configuration-config-file
                       (default %default-mongodb-configuration-file))
  (data-directory      mongodb-configuration-data-directory
                       (default "/var/lib/mongodb")))

(define %mongodb-accounts
  (list (user-group (name "mongodb") (system? #t))
        (user-account
         (name "mongodb")
         (group "mongodb")
         (system? #t)
         (comment "Mongodb server user")
         (home-directory "/var/lib/mongodb")
         (shell (file-append shadow "/sbin/nologin")))))

(define mongodb-activation
  (match-lambda
    (($ <mongodb-configuration> mongodb config-file data-directory)
     #~(begin
         (use-modules (guix build utils))
         (let ((user (getpwnam "mongodb")))
           (for-each
            (lambda (directory)
              (mkdir-p directory)
              (chown directory
                     (passwd:uid user) (passwd:gid user)))
            '("/var/run/mongodb" #$data-directory)))))))

(define mongodb-shepherd-service
  (match-lambda
    (($ <mongodb-configuration> mongodb config-file data-directory)
     (shepherd-service
      (provision '(mongodb))
      (documentation "Run the Mongodb daemon.")
      (requirement '(user-processes loopback))
      (start #~(make-forkexec-constructor
                `(,(string-append #$mongodb "/bin/mongod")
                  "--config"
                  ,#$config-file)
                #:user "mongodb"
                #:group "mongodb"
                #:pid-file "/var/run/mongodb/pid"
                #:log-file "/var/log/mongodb.log"))
      (stop #~(make-kill-destructor))))))

(define mongodb-service-type
  (service-type
   (name 'mongodb)
   (description "Run the MongoDB document database server.")
   (extensions
    (list (service-extension shepherd-root-service-type
                             (compose list
                                      mongodb-shepherd-service))
          (service-extension activation-service-type
                             mongodb-activation)
          (service-extension account-service-type
                             (const %mongodb-accounts))))
   (default-value
     (mongodb-configuration))))


;;;
;;; MySQL.
;;;


M gnu/tests/databases.scm => gnu/tests/databases.scm +85 -1
@@ 25,9 25,11 @@
  #:use-module (gnu services)
  #:use-module (gnu services databases)
  #:use-module (gnu services networking)
  #:use-module (gnu packages databases)
  #:use-module (guix gexp)
  #:use-module (guix store)
  #:export (%test-memcached))
  #:export (%test-memcached
            %test-mongodb))

(define %memcached-os
  (simple-operating-system


@@ 121,3 123,85 @@
   (name "memcached")
   (description "Connect to a running MEMCACHED server.")
   (value (run-memcached-test))))

(define %mongodb-os
  (operating-system
    (inherit
     (simple-operating-system
      (dhcp-client-service)
      (service mongodb-service-type)))
    (packages (cons* mongodb
                     %base-packages))))

(define* (run-mongodb-test #:optional (port 27017))
  "Run tests in %MONGODB-OS, forwarding PORT."
  (define os
    (marionette-operating-system
     %mongodb-os
     #:imported-modules '((gnu services herd)
                          (guix combinators))))

  (define vm
    (virtual-machine
     (operating-system os)
     (memory-size 1024)
     (disk-image-size (* 1024 (expt 2 20)))
     (port-forwardings `((27017 . ,port)))))

  (define test
    (with-imported-modules '((gnu build marionette))
      #~(begin
          (use-modules (srfi srfi-11) (srfi srfi-64)
                       (gnu build marionette)
                       (ice-9 popen)
                       (ice-9 rdelim))

          (define marionette
            (make-marionette (list #$vm)))

          (mkdir #$output)
          (chdir #$output)

          (test-begin "mongodb")

          (test-assert "service running"
            (marionette-eval
             '(begin
                (use-modules (gnu services herd))
                (match (start-service 'mongodb)
                  (#f #f)
                  (('service response-parts ...)
                   (match (assq-ref response-parts 'running)
                     ((pid) (number? pid))))))
             marionette))

          (test-eq "test insert"
            0
            (system* (string-append #$mongodb "/bin/mongo")
                     "test"
                     "--eval"
                     "db.testCollection.insert({data: 'test-data'})"))

          (test-equal "test find"
            "test-data"
            (let* ((port (open-pipe*
                          OPEN_READ
                          (string-append #$mongodb "/bin/mongo")
                          "test"
                          "--quiet"
                          "--eval"
                          "db.testCollection.findOne().data"))
                   (output (read-line port))
                   (status (close-pipe port)))
              output))

          (test-end)
          (exit (= (test-runner-fail-count (test-runner-current)) 0)))))

  (gexp->derivation "mongodb-test" test))

(define %test-mongodb
  (system-test
   (name "mongodb")
   (description "Connect to a running MONGODB server.")
   (value (run-mongodb-test))))