From c4e5ae2f3bdd5ed50eee144ddc72e611fa458397 Mon Sep 17 00:00:00 2001 From: mkocka Date: Thu, 8 Jun 2017 11:23:11 +0200 Subject: [PATCH] updating master according to f26 --- Dockerfile | 45 ++- mongodb.yaml | 11 +- root/help.1 | 120 ++++++++ root/help.md | 92 +++++++ tests/Dockerfile | 32 +++ tests/README.md | 22 ++ tests/config.yaml | 2 +- tests/db.py | 95 +++++++ tests/files/usr/bin/cgroup-limits | 92 +++++++ tests/files/usr/bin/container-entrypoint | 2 + tests/files/usr/bin/run-mongod | 57 ++++ tests/files/usr/bin/run-mongod-pet | 55 ++++ tests/files/usr/bin/run-mongod-replication | 55 ++++ tests/files/usr/libexec/fix-permissions | 6 + .../share/container-scripts/mongodb/README.md | 90 ++++++ .../share/container-scripts/mongodb/common.sh | 260 ++++++++++++++++++ .../container-scripts/mongodb/init-replset.sh | 86 ++++++ .../mongodb/mongodb.conf.template | 28 ++ .../container-scripts/mongodb/scl_enable | 3 + .../mongodb/test-functions.sh | 61 ++++ tests/help.md | 0 tests/mongodb.yaml | 59 ++++ tests/rpmvalidator.py | 56 ++++ tests/sanity.py | 61 ++++ tests/sanity1.pyc | Bin 0 -> 938 bytes tests/sources | 0 26 files changed, 1373 insertions(+), 17 deletions(-) create mode 100644 root/help.1 create mode 100644 root/help.md create mode 100644 tests/Dockerfile create mode 100644 tests/README.md create mode 100644 tests/db.py create mode 100755 tests/files/usr/bin/cgroup-limits create mode 100755 tests/files/usr/bin/container-entrypoint create mode 100755 tests/files/usr/bin/run-mongod create mode 100755 tests/files/usr/bin/run-mongod-pet create mode 100755 tests/files/usr/bin/run-mongod-replication create mode 100755 tests/files/usr/libexec/fix-permissions create mode 100644 tests/files/usr/share/container-scripts/mongodb/README.md create mode 100644 tests/files/usr/share/container-scripts/mongodb/common.sh create mode 100755 tests/files/usr/share/container-scripts/mongodb/init-replset.sh create mode 100644 tests/files/usr/share/container-scripts/mongodb/mongodb.conf.template create mode 100644 tests/files/usr/share/container-scripts/mongodb/scl_enable create mode 100644 tests/files/usr/share/container-scripts/mongodb/test-functions.sh create mode 100644 tests/help.md create mode 100644 tests/mongodb.yaml create mode 100644 tests/rpmvalidator.py create mode 100644 tests/sanity.py create mode 100644 tests/sanity1.pyc create mode 100644 tests/sources diff --git a/Dockerfile b/Dockerfile index 25c6a96..197a15f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,26 +1,49 @@ -FROM registry.fedoraproject.org/fedora:26 +FROM baseruntime/baseruntime:latest + +ENV NAME=mongodb \ + ARCH=x86_64 \ + VERSION=0 \ + RELEASE=1 \ + MONGODB_VERSION="3.4.3" -ENV NAME=mongodb ARCH=x86_64 LABEL MAINTAINER "Matus Kocka" -LABEL summary="MongoDB is a scalable, high-performance, open source NoSQL database." +LABEL summary="MongoDB, NoSQL database." \ + name="$FGC/$NAME" \ + version="$VERSION" \ + release="$RELEASE.$DISTTAG" \ + architecture="$ARCH" \ + description="MongoDB is a scalable, high-performance, open source NoSQL database." \ + vendor="Fedora Project" \ + com.redhat.component="$NAME" \ + usage="docker run -e MONGODB_USER= -e MONGODB_PASSWORD= -e MONGODB_DATABASE= -e MONGODB_ADMIN_PASSWORD= -p 27017:27017 mongodb" \ + org.fedoraproject.component="mongodb" \ + authoritative-source-url="registry.fedoraproject.org" \ + io.k8s.description="MongoDB is a scalable, high-performance, open source NoSQL database." \ + io.k8s.display-name="MongoDB 3.4.3" \ + io.openshift.tags="mongodb, db, database, nosql" \ + io.openshift.expose-services="27017" -RUN INSTALL_PKGS="bind-utils gettext iproute rsync tar findutils python3 mongodb mongodb-server mongo-tools" && \ - dnf install -y --setopt=tsflags=nodocs $INSTALL_PKGS && \ - rpm -V $INSTALL_PKGS && \ - dnf clean all +#removed mongo-tools from $INSTALL_PKGS -ENV MONGODB_VERSION=3.2 \ - # Set paths to avoid hard-coding them in scripts. - HOME=/var/lib/mongodb \ +RUN INSTALL_PKGS="bind-utils gettext iproute rsync tar findutils python3" && \ + microdnf --nodocs install -y mongodb mongodb-server && \ + microdnf --nodocs install -y $INSTALL_PKGS && \ + microdnf clean all + +# Set paths to avoid hard-coding them in scripts. +ENV HOME=/var/lib/mongodb \ CONTAINER_SCRIPTS_PATH=/usr/share/container-scripts/mongodb ADD files / +# Add help file +COPY root / + EXPOSE 27017 CMD ["/usr/bin/run-mongod"] -# Container setup from scl +# Container setup from scl RUN : > /etc/mongod.conf && \ mkdir -p ${HOME}/data && \ # Set owner 'mongodb:0' and 'g+rw(x)' permission - to avoid problems running container with arbitrary UID diff --git a/mongodb.yaml b/mongodb.yaml index 7359346..79d8fc2 100644 --- a/mongodb.yaml +++ b/mongodb.yaml @@ -18,10 +18,8 @@ data: module: [ AGPLv3 and zlib and ASL 2.0 ] dependencies: buildrequires: -# base-runtime: f26 bootstrap: f26 common-build-dependencies: f26 - shared-userspace: f26 perl: f26 requires: base-runtime: f26 @@ -35,9 +33,11 @@ data: default: rpms: - mongodb + - mongodb-server api: rpms: - mongodb + - mongodb-server components: rpms: mongodb: @@ -57,6 +57,7 @@ data: ref: f26 buildorder: 7 mozjs45: -                rationale: MongoDB dependency. -                ref: f26  -                buildorder: 1 + rationale: MongoDB dependency. + ref: f26 + buildorder: 1 + diff --git a/root/help.1 b/root/help.1 new file mode 100644 index 0000000..3d2effb --- /dev/null +++ b/root/help.1 @@ -0,0 +1,120 @@ +.TH "mongodb" "1" "" "Rado Pitonak \" "DATE 25.05.2017" "" + + +.SH NAME +.PP +mongodb \- scalable, high\-performance, open source NoSQL database. + + +.SH USAGE +.PP +To pull the MongoDB container use: + +.PP +.RS + +.nf + docker pull modularitycontainers/mongodb + +.fi +.RE + +.PP +If you want to set only the mandatory environment variables and store the database +in the \fB\fC/home/user/database\fR directory on the host filesystem, execute the following command: + +.PP +.RS + +.nf + docker run \-d \-e MONGODB\_USER= \-e MONGODB\_PASSWORD= \-e MONGODB\_DATABASE= \-e MONGODB\_ADMIN\_PASSWORD= \-v /home/user/database:/var/lib/mongodb/data modularitycontainers/mongodb + +.fi +.RE + +.PP +If you are initializing the database and it's the first time you are using the +specified shared volume, the database will be created with two users: \fB\fCadmin\fR and \fB\fCMONGODB\_USER\fR. After that the MongoDB daemon +will be started. If you are re\-attaching the volume to another container, the +creation of the database user and admin user will be skipped and only the +MongoDB daemon will be started. + + +.SH ENVIROMENT VARIABLES +.PP +The image recognizes the following environment variables that you can set during +initialization by passing \fB\fC\-e VAR=VALUE\fR to the Docker run command. + +.PP +\fB\fCMONGODB\_ADMIN\_PASSWORD\fR + Password for the admin user + +.PP +Optionally you can provide settings for user with 'readWrite' role. + +.PP +\fB\fCMONGODB\_USER\fR + User name for MONGODB account to be created +\fB\fCMONGODB\_PASSWORD\fR +.br + Password for the user account +.br +\fB\fCMONGODB\_DATABASE\fR +.br + Database name + +.PP +The following environment variables influence the MongoDB configuration file. They are all optional. + +.PP +\fB\fCMONGODB\_QUIET\fR +.br + Runs MongoDB in a quiet mode that attempts to limit the amount of output. + Default: true + + +.SH VOLUMES +.PP +You can also set the following mount points by passing the \fB\fC\-v /host:/container\fR flag to Docker. + +.PP +\fB\fCVolume mount point\fR + \fB\fC/var/lib/mongodb/data\fR\- MongoDB data directory + +.PP +\fBNotice: When mouting a directory from the host into the container, ensure that the mounted +directory has the appropriate permissions and that the owner and group of the directory +matches the user UID or name which is running inside the container.\fP + + +.SH CONFIGURATION +.PP +It is allowed to use custom configuration file for mongod server. Providing a custom configuration file supercedes the individual configuration environment variable values. + +.PP +To use custom configuration file in container it has to be mounted into \fB\fC/etc/mongod.conf\fR. For example to use configuration file stored in \fB\fC/home/user\fR directory use this option for \fB\fCdocker run\fR command: \fB\fC\-v /home/user/mongod.conf:/etc/mongod.conf:Z\fR. + +.PP +\fBNotice: Custom config file does not affect name of replica set. It has to be set in \fB\fCMONGODB\_REPLICA\_NAME\fR environment variable.\fP + + +.SH ADMIN USER +.PP +The admin user name is set to \fB\fCadmin\fR and you have to to specify the password by +setting the \fB\fCMONGODB\_ADMIN\_PASSWORD\fR environment variable. This process is done +upon database initialization. + + +.SH CHANGING PASSWORD +.PP +Since passwords are part of the image configuration, the only supported method +to change passwords for the database user (\fB\fCMONGODB\_USER\fR) and admin user is by +changing the environment variables \fB\fCMONGODB\_PASSWORD\fR and +\fB\fCMONGODB\_ADMIN\_PASSWORD\fR, respectively. + +.PP +Changing database passwords directly in MongoDB will cause a mismatch between +the values stored in the variables and the actual passwords. Whenever a database +container starts it will reset the passwords to the values stored in the +environment variables. + diff --git a/root/help.md b/root/help.md new file mode 100644 index 0000000..b67ee22 --- /dev/null +++ b/root/help.md @@ -0,0 +1,92 @@ +% mongodb(1) +% Rado Pitonak \ +% DATE 25.05.2017 + +# NAME + +mongodb - scalable, high-performance, open source NoSQL database. + + +# USAGE + +To pull the MongoDB container use: + + ``` + docker pull modularitycontainers/mongodb + ``` + +If you want to set only the mandatory environment variables and store the database +in the `/home/user/database` directory on the host filesystem, execute the following command: + + + ``` + docker run -d -e MONGODB_USER= -e MONGODB_PASSWORD= -e MONGODB_DATABASE= -e MONGODB_ADMIN_PASSWORD= -v /home/user/database:/var/lib/mongodb/data modularitycontainers/mongodb + ``` + + +If you are initializing the database and it's the first time you are using the +specified shared volume, the database will be created with two users: `admin` and `MONGODB_USER`. After that the MongoDB daemon +will be started. If you are re-attaching the volume to another container, the +creation of the database user and admin user will be skipped and only the +MongoDB daemon will be started. + +# ENVIROMENT VARIABLES + +The image recognizes the following environment variables that you can set during +initialization by passing `-e VAR=VALUE` to the Docker run command. + +`MONGODB_ADMIN_PASSWORD` + Password for the admin user + +Optionally you can provide settings for user with 'readWrite' role. + +`MONGODB_USER` + User name for MONGODB account to be created +`MONGODB_PASSWORD` + Password for the user account +`MONGODB_DATABASE` + Database name + + +The following environment variables influence the MongoDB configuration file. They are all optional. + +`MONGODB_QUIET` + Runs MongoDB in a quiet mode that attempts to limit the amount of output. + Default: true + +# VOLUMES + +You can also set the following mount points by passing the `-v /host:/container` flag to Docker. + +`Volume mount point` + `/var/lib/mongodb/data`- MongoDB data directory + +**Notice: When mouting a directory from the host into the container, ensure that the mounted +directory has the appropriate permissions and that the owner and group of the directory +matches the user UID or name which is running inside the container.** + +# CONFIGURATION + +It is allowed to use custom configuration file for mongod server. Providing a custom configuration file supercedes the individual configuration environment variable values. + +To use custom configuration file in container it has to be mounted into `/etc/mongod.conf`. For example to use configuration file stored in `/home/user` directory use this option for `docker run` command: `-v /home/user/mongod.conf:/etc/mongod.conf:Z`. + +**Notice: Custom config file does not affect name of replica set. It has to be set in `MONGODB_REPLICA_NAME` environment variable.** + +# ADMIN USER + +The admin user name is set to `admin` and you have to to specify the password by +setting the `MONGODB_ADMIN_PASSWORD` environment variable. This process is done +upon database initialization. + +# CHANGING PASSWORD + +Since passwords are part of the image configuration, the only supported method +to change passwords for the database user (`MONGODB_USER`) and admin user is by +changing the environment variables `MONGODB_PASSWORD` and +`MONGODB_ADMIN_PASSWORD`, respectively. + +Changing database passwords directly in MongoDB will cause a mismatch between +the values stored in the variables and the actual passwords. Whenever a database +container starts it will reset the passwords to the values stored in the +environment variables. diff --git a/tests/Dockerfile b/tests/Dockerfile new file mode 100644 index 0000000..25c6a96 --- /dev/null +++ b/tests/Dockerfile @@ -0,0 +1,32 @@ +FROM registry.fedoraproject.org/fedora:26 + +ENV NAME=mongodb ARCH=x86_64 +LABEL MAINTAINER "Matus Kocka" +LABEL summary="MongoDB is a scalable, high-performance, open source NoSQL database." + +RUN INSTALL_PKGS="bind-utils gettext iproute rsync tar findutils python3 mongodb mongodb-server mongo-tools" && \ + dnf install -y --setopt=tsflags=nodocs $INSTALL_PKGS && \ + rpm -V $INSTALL_PKGS && \ + dnf clean all + +ENV MONGODB_VERSION=3.2 \ + # Set paths to avoid hard-coding them in scripts. + HOME=/var/lib/mongodb \ + CONTAINER_SCRIPTS_PATH=/usr/share/container-scripts/mongodb + +ADD files / + +EXPOSE 27017 + +CMD ["/usr/bin/run-mongod"] + +# Container setup from scl +RUN : > /etc/mongod.conf && \ + mkdir -p ${HOME}/data && \ + # Set owner 'mongodb:0' and 'g+rw(x)' permission - to avoid problems running container with arbitrary UID + /usr/libexec/fix-permissions /etc/mongod.conf ${CONTAINER_SCRIPTS_PATH}/mongodb.conf.template \ + ${HOME} + +VOLUME ["/var/lib/mongodb/data"] + +USER 184 diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..938ce2d --- /dev/null +++ b/tests/README.md @@ -0,0 +1,22 @@ +mongodb dependencies +==================== + +build dependencies calculated by brt_dep_solver +----------------------------------------------- +asio +boost +gcc +gperftools +icu +libstemmer +python-pymongo +scons +snappy +valgrind +yaml-cpp +yaml-cpp03 + +runtime dependencies calculated by brt_dep_solver +------------------------------------------------- +boost +yaml-cpp diff --git a/tests/config.yaml b/tests/config.yaml index f4c9002..c56cae4 100644 --- a/tests/config.yaml +++ b/tests/config.yaml @@ -22,7 +22,7 @@ testdependecies: - mongodb module: docker: - start: "docker run -d -e MONGODB_USER=user -e MONGODB_PASSWORD=pas -e MONGODB_DATABASE=db -e MONGODB_ADMIN_PASSWORD=admin -p 27017:27017" + start: "docker run -it -e MONGODB_USER=user -e MONGODB_PASSWORD=pas -e MONGODB_DATABASE=db -e MONGODB_ADMIN_PASSWORD=admin -p 27017:27017" labels: description: "MongoDB is a scalable, high-performance, open source NoSQL database." io.k8s.description: "MongoDB is a scalable, high-performance, open source NoSQL database." diff --git a/tests/db.py b/tests/db.py new file mode 100644 index 0000000..170a98c --- /dev/null +++ b/tests/db.py @@ -0,0 +1,95 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# This Modularity Testing Framework helps you to write tests for modules +# Copyright (C) 2017 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# he Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Authors: Rado Pitonak +# + +from avocado import main +from avocado.core import exceptions +from moduleframework import module_framework +import time + + +class DBCheck(module_framework.AvocadoTest): + """ + :avocado: enable + """ + + MONGO_CMD = 'mongo "$MONGODB_DATABASE" -u "$MONGODB_USER" -p "$MONGODB_PASSWORD"' + + # authentication options for admin user + # https://docs.mongodb.com/manual/reference/program/mongo/#mongo-shell-authentication-options + MONGO_ADMIN_CMD = 'mongo "$MONGODB_DATABASE" -u "admin" -p "$MONGODB_ADMIN_PASSWORD" --authenticationDatabase admin --authenticationMechanism SCRAM-SHA-1' + + def testConnectToDB(self): + """ + Test connection to database + """ + + query = "db.getSiblingDB('test_database');" + + self.start() + time.sleep(3) + + self.run('{} --eval "{}"'.format(self.MONGO_CMD, query)) + + def testUserPrivileges(self): + """ + Testing user privileges. + """ + + self.start() + time.sleep(3) + + # mongo db queries stored in dictionary, written in order which they are called + queries = {"insert1": "db.testData.insert({ y : 1 });", + "insert2": "db.testData.insert({ z : 2 });", + "print_json": "db.testData.find().forEach(printjson);", + "count": "db.testData.count();", + "data_drop": "db.testData.drop();", + "db_drop": "db.dropDatabase();"} + + self.run('{} --eval "{}"'.format(self.MONGO_CMD, queries["insert1"])) + self.run('{} --eval "{}"'.format(self.MONGO_CMD, queries["insert2"])) + self.run('{} --eval "{}"'.format(self.MONGO_CMD, queries["print_json"])) + self.run('{} --eval "{}"'.format(self.MONGO_CMD, queries["count"])) + self.run('{} --eval "{}"'.format(self.MONGO_CMD, queries["data_drop"])) + self.run('{} --eval "{}"'.format(self.MONGO_CMD, queries["db_drop"])) + + def testAdminPrivileges(self): + """ + Testing privileges for admin user + """ + self.start() + time.sleep(3) + + # mongo db queries stored in dictionary, written in order which they are called + queries = {"dropUser": "db=db.getSiblingDB('${MONGODB_DATABASE}');db.dropUser('${MONGODB_USER}');", + "createUser1": "db=db.getSiblingDB('${MONGODB_DATABASE}'); db.createUser({user:'${MONGODB_USER}',pwd:'${MONGODB_PASSWORD}',roles:['readWrite','userAdmin','dbAdmin']});", + "insert": "db=db.getSiblingDB('${MONGODB_DATABASE}');db.testData.insert({x:0});", + "createUser2": "db.createUser({user:'test_user2',pwd:'test_password2',roles:['readWrite']});"} + + self.run('{} --eval "{}"'.format(self.MONGO_ADMIN_CMD, queries["dropUser"])) + self.run('{} --eval "{}"'.format(self.MONGO_ADMIN_CMD, queries["createUser1"])) + self.run('{} --eval "{}"'.format(self.MONGO_ADMIN_CMD, queries["insert"])) + self.run('{} --eval "{}"'.format(self.MONGO_CMD, queries["createUser2"])) + +if __name__ == '__main__': + main() diff --git a/tests/files/usr/bin/cgroup-limits b/tests/files/usr/bin/cgroup-limits new file mode 100755 index 0000000..b9d4edc --- /dev/null +++ b/tests/files/usr/bin/cgroup-limits @@ -0,0 +1,92 @@ +#!/usr/bin/python + +""" +Script for parsing cgroup information + +This script will read some limits from the cgroup system and parse +them, printing out "VARIABLE=VALUE" on each line for every limit that is +successfully read. Output of this script can be directly fed into +bash's export command. Recommended usage from a bash script: + + set -o errexit + export_vars=$(cgroup-limits) ; export $export_vars + +Variables currently supported: + MAX_MEMORY_LIMIT_IN_BYTES + Maximum possible limit MEMORY_LIMIT_IN_BYTES can have. This is + currently constant value of 9223372036854775807. + MEMORY_LIMIT_IN_BYTES + Maximum amount of user memory in bytes. If this value is set + to the same value as MAX_MEMORY_LIMIT_IN_BYTES, it means that + there is no limit set. The value is taken from + /sys/fs/cgroup/memory/memory.limit_in_bytes + NUMBER_OF_CORES + Number of detected CPU cores that can be used. This value is + calculated from /sys/fs/cgroup/cpuset/cpuset.cpus + NO_MEMORY_LIMIT + Set to "true" if MEMORY_LIMIT_IN_BYTES is so high that the caller + can act as if no memory limit was set. Undefined otherwise. +""" + +from __future__ import print_function +import sys + + +def _read_file(path): + try: + with open(path, 'r') as f: + return f.read().strip() + except IOError: + return None + + +def get_memory_limit(): + """ + Read memory limit, in bytes. + """ + + limit = _read_file('/sys/fs/cgroup/memory/memory.limit_in_bytes') + if limit is None or not limit.isdigit(): + print("Warning: Can't detect memory limit from cgroups", + file=sys.stderr) + return None + return int(limit) + + +def get_number_of_cores(): + """ + Read number of CPU cores. + """ + + core_count = 0 + + line = _read_file('/sys/fs/cgroup/cpuset/cpuset.cpus') + if line is None: + print("Warning: Can't detect number of CPU cores from cgroups", + file=sys.stderr) + return None + + for group in line.split(','): + core_ids = list(map(int, group.split('-'))) + if len(core_ids) == 2: + core_count += core_ids[1] - core_ids[0] + 1 + else: + core_count += 1 + + return core_count + + +if __name__ == "__main__": + env_vars = { + "MAX_MEMORY_LIMIT_IN_BYTES": 9223372036854775807, + "MEMORY_LIMIT_IN_BYTES": get_memory_limit(), + "NUMBER_OF_CORES": get_number_of_cores() + } + + env_vars = {k: v for k, v in env_vars.items() if v is not None} + + if env_vars.get("MEMORY_LIMIT_IN_BYTES", 0) >= 92233720368547: + env_vars["NO_MEMORY_LIMIT"] = "true" + + for key, value in env_vars.items(): + print("{0}={1}".format(key, value)) diff --git a/tests/files/usr/bin/container-entrypoint b/tests/files/usr/bin/container-entrypoint new file mode 100755 index 0000000..9d8ad4d --- /dev/null +++ b/tests/files/usr/bin/container-entrypoint @@ -0,0 +1,2 @@ +#!/bin/bash +exec "$@" diff --git a/tests/files/usr/bin/run-mongod b/tests/files/usr/bin/run-mongod new file mode 100755 index 0000000..e273e48 --- /dev/null +++ b/tests/files/usr/bin/run-mongod @@ -0,0 +1,57 @@ +#!/bin/bash + +set -o errexit +set -o nounset +set -o pipefail + +source ${CONTAINER_SCRIPTS_PATH}/common.sh + +function cleanup() { + echo "=> Shutting down MongoDB server ..." + pkill -INT mongod || : + wait_for_mongo_down + exit 0 +} + +trap 'cleanup' SIGINT SIGTERM + +check_env_vars + +setup_wiredtiger_cache ${CONTAINER_SCRIPTS_PATH}/mongodb.conf.template + +# If user provides own config file use it and do not generate new one +if [ ! -s $MONGODB_CONFIG_PATH ]; then + # Generate config file for MongoDB + envsubst < ${CONTAINER_SCRIPTS_PATH}/mongodb.conf.template > $MONGODB_CONFIG_PATH +fi + +mongo_common_args="-f $MONGODB_CONFIG_PATH" + +setup_default_datadir + +# Must bring up MongoDB on localhost only until it has an admin password set. +mongod $mongo_common_args --bind_ip 127.0.0.1 & +wait_for_mongo_up +js_command="db.system.users.count({'user':'admin', 'db':'admin'})" +if [ "$(mongo admin --quiet --eval "$js_command")" == "1" ]; then + echo "=> Admin user is already created. Resetting password ..." + mongo_reset_admin +else + mongo_create_admin +fi +if [[ -v CREATE_USER ]]; then + js_command="db.system.users.count({'user':'${MONGODB_USER}', 'db':'${MONGODB_DATABASE}'})" + if [ "$(mongo admin --quiet --eval "$js_command")" == "1" ]; then + echo "=> MONGODB_USER user is already created. Resetting password ..." + mongo_reset_user + else + mongo_create_user + fi +fi +# Restart the MongoDB daemon to bind on all interfaces +mongod $mongo_common_args --shutdown +wait_for_mongo_down + +# Make sure env variables don't propagate to mongod process. +unset MONGODB_USER MONGODB_PASSWORD MONGODB_DATABASE MONGODB_ADMIN_PASSWORD +exec mongod $mongo_common_args --auth diff --git a/tests/files/usr/bin/run-mongod-pet b/tests/files/usr/bin/run-mongod-pet new file mode 100755 index 0000000..fb803e1 --- /dev/null +++ b/tests/files/usr/bin/run-mongod-pet @@ -0,0 +1,55 @@ +#!/bin/bash +# +# Run mongod in a StatefulSet-based replica set. See +# https://github.com/sclorg/mongodb-container/blob/master/examples/petset/README.md +# for a description of how this is intended to work. +# +# Note: +# - It does not attempt to remove the host from the replica set configuration +# when it is terminating. That is by design, because, in a StatefulSet, when a +# pod/container terminates and is restarted by OpenShift, it will always have +# the same hostname. Removing hosts from the configuration affects replica set +# elections and can impact the replica set stability. + +set -o errexit +set -o nounset +set -o pipefail + +source ${CONTAINER_SCRIPTS_PATH}/common.sh + +function cleanup() { + echo "=> Shutting down MongoDB server ..." + pkill -INT mongod || : + wait_for_mongo_down + exit 0 +} + +trap 'cleanup' SIGINT SIGTERM + +REPLICATION=1 check_env_vars + +setup_wiredtiger_cache ${CONTAINER_SCRIPTS_PATH}/mongodb.conf.template + +# If user provides own config file use it and do not generate new one +if [ ! -s "${MONGODB_CONFIG_PATH}" ]; then + # Generate config file for MongoDB + envsubst < "${CONTAINER_SCRIPTS_PATH}/mongodb.conf.template" > "${MONGODB_CONFIG_PATH}" +fi + +mongo_common_args="-f ${MONGODB_CONFIG_PATH}" + +# Attention: setup_keyfile may modify value of mongo_common_args! +setup_keyfile +setup_default_datadir + +${CONTAINER_SCRIPTS_PATH}/init-replset.sh & + +# TODO: capture exit code of `init-petset-replset.sh` and exit with an error if +# the initialization failed, so that the container will be restarted and the +# user can gain more visibility that there is a problem in a way other than just +# inspecting log messages. + +# Make sure env variables don't propagate to mongod process. +unset MONGODB_USER MONGODB_PASSWORD MONGODB_DATABASE MONGODB_ADMIN_PASSWORD +mongod ${mongo_common_args} --replSet "${MONGODB_REPLICA_NAME}" & +wait diff --git a/tests/files/usr/bin/run-mongod-replication b/tests/files/usr/bin/run-mongod-replication new file mode 100755 index 0000000..fb803e1 --- /dev/null +++ b/tests/files/usr/bin/run-mongod-replication @@ -0,0 +1,55 @@ +#!/bin/bash +# +# Run mongod in a StatefulSet-based replica set. See +# https://github.com/sclorg/mongodb-container/blob/master/examples/petset/README.md +# for a description of how this is intended to work. +# +# Note: +# - It does not attempt to remove the host from the replica set configuration +# when it is terminating. That is by design, because, in a StatefulSet, when a +# pod/container terminates and is restarted by OpenShift, it will always have +# the same hostname. Removing hosts from the configuration affects replica set +# elections and can impact the replica set stability. + +set -o errexit +set -o nounset +set -o pipefail + +source ${CONTAINER_SCRIPTS_PATH}/common.sh + +function cleanup() { + echo "=> Shutting down MongoDB server ..." + pkill -INT mongod || : + wait_for_mongo_down + exit 0 +} + +trap 'cleanup' SIGINT SIGTERM + +REPLICATION=1 check_env_vars + +setup_wiredtiger_cache ${CONTAINER_SCRIPTS_PATH}/mongodb.conf.template + +# If user provides own config file use it and do not generate new one +if [ ! -s "${MONGODB_CONFIG_PATH}" ]; then + # Generate config file for MongoDB + envsubst < "${CONTAINER_SCRIPTS_PATH}/mongodb.conf.template" > "${MONGODB_CONFIG_PATH}" +fi + +mongo_common_args="-f ${MONGODB_CONFIG_PATH}" + +# Attention: setup_keyfile may modify value of mongo_common_args! +setup_keyfile +setup_default_datadir + +${CONTAINER_SCRIPTS_PATH}/init-replset.sh & + +# TODO: capture exit code of `init-petset-replset.sh` and exit with an error if +# the initialization failed, so that the container will be restarted and the +# user can gain more visibility that there is a problem in a way other than just +# inspecting log messages. + +# Make sure env variables don't propagate to mongod process. +unset MONGODB_USER MONGODB_PASSWORD MONGODB_DATABASE MONGODB_ADMIN_PASSWORD +mongod ${mongo_common_args} --replSet "${MONGODB_REPLICA_NAME}" & +wait diff --git a/tests/files/usr/libexec/fix-permissions b/tests/files/usr/libexec/fix-permissions new file mode 100755 index 0000000..6ad8d03 --- /dev/null +++ b/tests/files/usr/libexec/fix-permissions @@ -0,0 +1,6 @@ +#!/bin/sh +# Fix permissions on the given directory to allow group read/write of +# regular files and execute of directories. +find $@ -exec chown mongodb:0 {} \; +find $@ -exec chmod g+rw {} \; +find $@ -type d -exec chmod g+x {} + diff --git a/tests/files/usr/share/container-scripts/mongodb/README.md b/tests/files/usr/share/container-scripts/mongodb/README.md new file mode 100644 index 0000000..28b8988 --- /dev/null +++ b/tests/files/usr/share/container-scripts/mongodb/README.md @@ -0,0 +1,90 @@ +MongoDB Docker image +==================== + +This repository contains Dockerfiles for MongoDB images for general usage and OpenShift. +Users can choose between RHEL and CentOS based images. + +Environment variables +--------------------------------- + +The image recognizes the following environment variables that you can set during +initialization by passing `-e VAR=VALUE` to the Docker run command. + +| Variable name | Description | +| :------------------------ | ----------------------------------------- | +| `MONGODB_ADMIN_PASSWORD` | Password for the admin user | + +Optionally you can provide settings for user with 'readWrite' role. + +| Variable name | Description | +| :------------------------ | ----------------------------------------- | +| `MONGODB_USER` | User name for MONGODB account to be created | +| `MONGODB_PASSWORD` | Password for the user account | +| `MONGODB_DATABASE` | Database name | + + +The following environment variables influence the MongoDB configuration file. They are all optional. + +| Variable name | Description | Default +| :-------------------- | ------------------------------------------------------------------------- | ---------------- +| `MONGODB_QUIET` | Runs MongoDB in a quiet mode that attempts to limit the amount of output. | true + + +You can also set the following mount points by passing the `-v /host:/container` flag to Docker. + +| Volume mount point | Description | +| :-------------------------- | ---------------------- | +| `/var/lib/mongodb/data` | MongoDB data directory | + +**Notice: When mouting a directory from the host into the container, ensure that the mounted +directory has the appropriate permissions and that the owner and group of the directory +matches the user UID or name which is running inside the container.** + + +Usage +--------------------------------- + +For this, we will assume that you are using the `centos/mongodb-32-centos7` image. +If you want to set only the mandatory environment variables and store the database +in the `/home/user/database` directory on the host filesystem, execute the following command: + +``` +$ docker run -d -e MONGODB_USER= -e MONGODB_PASSWORD= -e MONGODB_DATABASE= -e MONGODB_ADMIN_PASSWORD= -v /home/user/database:/var/lib/mongodb/data centos/mongodb-32-centos7 +``` + +If you are initializing the database and it's the first time you are using the +specified shared volume, the database will be created with two users: `admin` and `MONGODB_USER`. After that the MongoDB daemon +will be started. If you are re-attaching the volume to another container, the +creation of the database user and admin user will be skipped and only the +MongoDB daemon will be started. + +Custom configuration file +--------------------------------- + +It is allowed to use custom configuration file for mongod server. Providing a custom configuration file supercedes the individual configuration environment variable values. + +To use custom configuration file in container it has to be mounted into `/etc/mongod.conf`. For example to use configuration file stored in `/home/user` directory use this option for `docker run` command: `-v /home/user/mongod.conf:/etc/mongod.conf:Z`. + +**Notice: Custom config file does not affect name of replica set. It has to be set in `MONGODB_REPLICA_NAME` environment variable.** + +MongoDB admin user +--------------------------------- + +The admin user name is set to `admin` and you have to to specify the password by +setting the `MONGODB_ADMIN_PASSWORD` environment variable. This process is done +upon database initialization. + + +Changing passwords +------------------ + +Since passwords are part of the image configuration, the only supported method +to change passwords for the database user (`MONGODB_USER`) and admin user is by +changing the environment variables `MONGODB_PASSWORD` and +`MONGODB_ADMIN_PASSWORD`, respectively. + +Changing database passwords directly in MongoDB will cause a mismatch between +the values stored in the variables and the actual passwords. Whenever a database +container starts it will reset the passwords to the values stored in the +environment variables. + diff --git a/tests/files/usr/share/container-scripts/mongodb/common.sh b/tests/files/usr/share/container-scripts/mongodb/common.sh new file mode 100644 index 0000000..c6dcfc2 --- /dev/null +++ b/tests/files/usr/share/container-scripts/mongodb/common.sh @@ -0,0 +1,260 @@ +#!/bin/bash + +set -o errexit +set -o nounset +set -o pipefail + +# Data directory where MongoDB database files live. The data subdirectory is here +# because mongodb.conf lives in /var/lib/mongodb/ and we don't want a volume to +# override it. +export MONGODB_DATADIR=/var/lib/mongodb/data +export CONTAINER_PORT=27017 +# Configuration settings. +export MONGODB_QUIET=${MONGODB_QUIET:-true} + +MONGODB_CONFIG_PATH=/etc/mongod.conf +MONGODB_KEYFILE_PATH="${HOME}/keyfile" + +# Constants used for waiting +readonly MAX_ATTEMPTS=60 +readonly SLEEP_TIME=1 + +# wait_for_mongo_up waits until the mongo server accepts incomming connections +function wait_for_mongo_up() { + _wait_for_mongo 1 "$@" +} + +# wait_for_mongo_down waits until the mongo server is down +function wait_for_mongo_down() { + _wait_for_mongo 0 "$@" +} + +# wait_for_mongo waits until the mongo server is up/down +# $1 - 0 or 1 - to specify for what to wait (0 - down, 1 - up) +# $2 - host where to connect (localhost by default) +function _wait_for_mongo() { + local operation=${1:-1} + local message="up" + if [[ ${operation} -eq 0 ]]; then + message="down" + fi + + local mongo_cmd="mongo admin --host ${2:-localhost} " + + local i + for i in $(seq $MAX_ATTEMPTS); do + echo "=> ${2:-} Waiting for MongoDB daemon ${message}" + if ([[ ${operation} -eq 1 ]] && ${mongo_cmd} --eval "quit()" &>/dev/null) || ([[ ${operation} -eq 0 ]] && ! ${mongo_cmd} --eval "quit()" &>/dev/null); then + echo "=> MongoDB daemon is ${message}" + return 0 + fi + sleep ${SLEEP_TIME} + done + echo "=> Giving up: MongoDB daemon is not ${message}!" + return 1 +} + +# endpoints returns list of IP addresses with other instances of MongoDB +# To get list of endpoints, you need to have headless Service named 'mongodb'. +# NOTE: This won't work with standalone Docker container. +function endpoints() { + service_name=${MONGODB_SERVICE_NAME:-mongodb} + dig ${service_name} A +search +short 2>/dev/null +} + +# replset_addr return the address of the current replSet +function replset_addr() { + local current_endpoints + current_endpoints="$(endpoints)" + if [ -z "${current_endpoints}" ]; then + info "Cannot get address of replica set: no nodes are listed in service!" + info "CAUSE: DNS lookup for '${MONGODB_SERVICE_NAME:-mongodb}' returned no results." + return 1 + fi + echo "${MONGODB_REPLICA_NAME}/${current_endpoints//[[:space:]]/,}" +} + +# mongo_create_admin creates the MongoDB admin user with password: MONGODB_ADMIN_PASSWORD +# $1 - login parameters for mongo (optional) +# $2 - host where to connect (localhost by default) +function mongo_create_admin() { + if [[ -z "${MONGODB_ADMIN_PASSWORD:-}" ]]; then + echo >&2 "=> MONGODB_ADMIN_PASSWORD is not set. Authentication can not be set up." + exit 1 + fi + + # Set admin password + local js_command="db.createUser({user: 'admin', pwd: '${MONGODB_ADMIN_PASSWORD}', roles: ['dbAdminAnyDatabase', 'userAdminAnyDatabase' , 'readWriteAnyDatabase','clusterAdmin' ]});" + if ! mongo admin ${1:-} --host ${2:-"localhost"} --eval "${js_command}"; then + echo >&2 "=> Failed to create MongoDB admin user." + exit 1 + fi +} + +# mongo_create_user creates the MongoDB database user: MONGODB_USER, +# with password: MONGDOB_PASSWORD, inside database: MONGODB_DATABASE +# $1 - login parameters for mongo (optional) +# $2 - host where to connect (localhost by default) +function mongo_create_user() { + # Ensure input variables exists + if [[ -z "${MONGODB_USER:-}" ]]; then + echo >&2 "=> MONGODB_USER is not set. Failed to create MongoDB user" + exit 1 + fi + if [[ -z "${MONGODB_PASSWORD:-}" ]]; then + echo "=> MONGODB_PASSWORD is not set. Failed to create MongoDB user: ${MONGODB_USER}" + exit >&2 1 + fi + if [[ -z "${MONGODB_DATABASE:-}" ]]; then + echo >&2 "=> MONGODB_DATABASE is not set. Failed to create MongoDB user: ${MONGODB_USER}" + exit 1 + fi + + # Create database user + local js_command="db.getSiblingDB('${MONGODB_DATABASE}').createUser({user: '${MONGODB_USER}', pwd: '${MONGODB_PASSWORD}', roles: [ 'readWrite' ]});" + if ! mongo admin ${1:-} --host ${2:-"localhost"} --eval "${js_command}"; then + echo >&2 "=> Failed to create MongoDB user: ${MONGODB_USER}" + exit 1 + fi +} + +# mongo_reset_user sets the MongoDB MONGODB_USER's password to match MONGODB_PASSWORD +function mongo_reset_user() { + if [[ -n "${MONGODB_USER:-}" && -n "${MONGODB_PASSWORD:-}" && -n "${MONGODB_DATABASE:-}" ]]; then + local js_command="db.changeUserPassword('${MONGODB_USER}', '${MONGODB_PASSWORD}')" + if ! mongo ${MONGODB_DATABASE} --eval "${js_command}"; then + echo >&2 "=> Failed to reset password of MongoDB user: ${MONGODB_USER}" + exit 1 + fi + fi +} + +# mongo_reset_admin sets the MongoDB admin password to match MONGODB_ADMIN_PASSWORD +function mongo_reset_admin() { + if [[ -n "${MONGODB_ADMIN_PASSWORD:-}" ]]; then + local js_command="db.changeUserPassword('admin', '${MONGODB_ADMIN_PASSWORD}')" + if ! mongo admin --eval "${js_command}"; then + echo >&2 "=> Failed to reset password of MongoDB user: ${MONGODB_USER}" + exit 1 + fi + fi +} + +# setup_keyfile fixes the bug in mounting the Kubernetes 'Secret' volume that +# mounts the secret files with 'too open' permissions. +# add --keyFile argument to mongo_common_args +function setup_keyfile() { + # If user specify keyFile in config file do not use generated keyFile + if grep -q "^\s*keyFile" ${MONGODB_CONFIG_PATH}; then + exit 0 + fi + if [ -z "${MONGODB_KEYFILE_VALUE-}" ]; then + echo >&2 "ERROR: You have to provide the 'keyfile' value in MONGODB_KEYFILE_VALUE" + exit 1 + fi + local keyfile_dir + keyfile_dir="$(dirname "$MONGODB_KEYFILE_PATH")" + if [ ! -w "$keyfile_dir" ]; then + echo >&2 "ERROR: Couldn't create ${MONGODB_KEYFILE_PATH}" + echo >&2 "CAUSE: current user doesn't have permissions for writing to ${keyfile_dir} directory" + echo >&2 "DETAILS: current user id = $(id -u), user groups: $(id -G)" + echo >&2 "DETAILS: directory permissions: $(stat -c '%A owned by %u:%g' "${keyfile_dir}")" + exit 1 + fi + echo ${MONGODB_KEYFILE_VALUE} > ${MONGODB_KEYFILE_PATH} + chmod 0600 ${MONGODB_KEYFILE_PATH} + mongo_common_args+=" --keyFile ${MONGODB_KEYFILE_PATH}" +} + +# setup_default_datadir checks permissions of mounded directory into default +# data directory MONGODB_DATADIR +function setup_default_datadir() { + if [ ! -w "$MONGODB_DATADIR" ]; then + echo >&2 "ERROR: Couldn't write into ${MONGODB_DATADIR}" + echo >&2 "CAUSE: current user doesn't have permissions for writing to ${MONGODB_DATADIR} directory" + echo >&2 "DETAILS: current user id = $(id -u), user groups: $(id -G)" + echo >&2 "DETAILS: directory permissions: $(stat -c '%A owned by %u:%g, SELinux: %C' "${MONGODB_DATADIR}")" + exit 1 + fi +} + +# setup_wiredtiger_cache checks amount of available RAM (it has to use cgroups in container) +# and if there are any memory restrictions set storage.wiredTiger.engineConfig.cacheSizeGB +# in MONGODB_CONFIG_PATH to upstream default size +# it is intended to update mongodb.conf.template, with custom config file it might create conflict +function setup_wiredtiger_cache() { + local config_file + config_file=${1:-$MONGODB_CONFIG_PATH} + + declare $(cgroup-limits) + if [[ ! -v MEMORY_LIMIT_IN_BYTES || "${NO_MEMORY_LIMIT:-}" == "true" ]]; then + return 0; + fi + + cache_size=$(python -c "min=1; limit=int(($MEMORY_LIMIT_IN_BYTES / pow(2,30) - 1) * 0.6); print( min if limit < min else limit)") + echo "storage.wiredTiger.engineConfig.cacheSizeGB: ${cache_size}" >> ${config_file} + + info "wiredTiger cacheSizeGB set to ${cache_size}" +} + +# check_env_vars checks environmental variables +# if variables to create non-admin user are provided, sets CREATE_USER=1 +# if REPLICATION variable is set, checks also replication variables +function check_env_vars() { + local readonly database_regex='^[^/\. "$]*$' + + [[ -v MONGODB_ADMIN_PASSWORD ]] || usage "MONGODB_ADMIN_PASSWORD has to be set." + + if [[ -v MONGODB_USER || -v MONGODB_PASSWORD || -v MONGODB_DATABASE ]]; then + [[ -v MONGODB_USER && -v MONGODB_PASSWORD && -v MONGODB_DATABASE ]] || usage "You have to set all or none of variables: MONGODB_USER, MONGODB_PASSWORD, MONGODB_DATABASE" + + [[ "${MONGODB_DATABASE}" =~ $database_regex ]] || usage "Database name must match regex: $database_regex" + [ ${#MONGODB_DATABASE} -le 63 ] || usage "Database name too long (maximum 63 characters)" + + export CREATE_USER=1 + fi + + if [[ -v REPLICATION ]]; then + [[ -v MONGODB_KEYFILE_VALUE && -v MONGODB_REPLICA_NAME ]] || usage "MONGODB_KEYFILE_VALUE and MONGODB_REPLICA_NAME have to be set" + fi +} + +# usage prints info about required enviromental variables +# if $1 is passed, prints error message containing $1 +# if REPLICATION variable is set, prints also info about replication variables +function usage() { + if [ $# == 1 ]; then + echo >&2 "error: $1" + fi + + echo " +You must specify the following environment variables: + MONGODB_ADMIN_PASSWORD +Optionally you can provide settings for a user with 'readWrite' role: +(Note you MUST specify all three of these settings) + MONGODB_USER + MONGODB_PASSWORD + MONGODB_DATABASE +Optional settings: + MONGODB_QUIET (default: true)" + + if [[ -v REPLICATION ]]; then + echo " +For replication you must also specify the following environment variables: + MONGODB_KEYFILE_VALUE + MONGODB_REPLICA_NAME +Optional settings: + MONGODB_SERVICE_NAME (default: mongodb) +" + fi + echo " +For more information see /usr/share/container-scripts/mongodb/README.md +within the container or visit https://github.com/sclorgk/mongodb-container/." + + exit 1 +} + +# info prints a message prefixed by date and time. +function info() { + printf "=> [%s] %s\n" "$(date +'%a %b %d %T')" "$*" +} diff --git a/tests/files/usr/share/container-scripts/mongodb/init-replset.sh b/tests/files/usr/share/container-scripts/mongodb/init-replset.sh new file mode 100755 index 0000000..dd7f2de --- /dev/null +++ b/tests/files/usr/share/container-scripts/mongodb/init-replset.sh @@ -0,0 +1,86 @@ +#!/bin/bash + +set -o errexit +set -o nounset +set -o pipefail + +source "${CONTAINER_SCRIPTS_PATH}/common.sh" + +# This is a full hostname that will be added to replica set +# (for example, "replica-2.mongodb.myproject.svc.cluster.local") +readonly MEMBER_HOST="$(hostname -f)" + +# Initializes the replica set configuration. +# +# Arguments: +# - $1: host address[:port] +# +# Uses the following global variables: +# - MONGODB_REPLICA_NAME +# - MONGODB_ADMIN_PASSWORD +function initiate() { + local host="$1" + + local config="{_id: '${MONGODB_REPLICA_NAME}', members: [{_id: 0, host: '${host}'}]}" + + info "Initiating MongoDB replica using: ${config}" + mongo --eval "quit(rs.initiate(${config}).ok ? 0 : 1)" --quiet + + info "Waiting for PRIMARY status ..." + mongo --eval "while (!rs.isMaster().ismaster) { sleep(100); }" --quiet + + info "Creating MongoDB users ..." + mongo_create_admin + [[ -v CREATE_USER ]] && mongo_create_user "-u admin -p ${MONGODB_ADMIN_PASSWORD}" + + info "Successfully initialized replica set" +} + +# Adds a host to the replica set configuration. +# +# Arguments: +# - $1: host address[:port] +# +# Global variables: +# - MONGODB_REPLICA_NAME +# - MONGODB_ADMIN_PASSWORD +function add_member() { + local host="$1" + info "Adding ${host} to replica set ..." + + if ! mongo admin -u admin -p "${MONGODB_ADMIN_PASSWORD}" --host "$(replset_addr)" --eval "while (!rs.add('${host}').ok) { sleep(100); }" --quiet; then + info "ERROR: couldn't add host to replica set!" + return 1 + fi + + info "Waiting for PRIMARY/SECONDARY status ..." + mongo --eval "while (!rs.isMaster().ismaster && !rs.isMaster().secondary) { sleep(100); }" --quiet + + info "Successfully joined replica set" +} + +info "Waiting for local MongoDB to accept connections ..." +wait_for_mongo_up &>/dev/null + +if [[ $(mongo --eval 'db.isMaster().setName' --quiet) == "${MONGODB_REPLICA_NAME}" ]]; then + info "Replica set '${MONGODB_REPLICA_NAME}' already exists, skipping initialization" + >/tmp/initialized + exit 0 +fi + +# StatefulSet pods are named with a predictable name, following the pattern: +# $(statefulset name)-$(zero-based index) +# MEMBER_ID is computed by removing the prefix matching "*-", i.e.: +# "mongodb-0" -> "0" +# "mongodb-1" -> "1" +# "mongodb-2" -> "2" +readonly MEMBER_ID="${HOSTNAME##*-}" + +# Initialize replica set only if we're the first member +if [ "${MEMBER_ID}" = '0' ]; then + initiate "${MEMBER_HOST}" +else + add_member "${MEMBER_HOST}" +fi + +>/tmp/initialized diff --git a/tests/files/usr/share/container-scripts/mongodb/mongodb.conf.template b/tests/files/usr/share/container-scripts/mongodb/mongodb.conf.template new file mode 100644 index 0000000..e33ea21 --- /dev/null +++ b/tests/files/usr/share/container-scripts/mongodb/mongodb.conf.template @@ -0,0 +1,28 @@ +## +## For list of options visit: +## https://docs.mongodb.org/manual/reference/configuration-options/ +## + +# systemLog Options - How to do logging +systemLog: + # Runs the mongod in a quiet mode that attempts to limit the amount of output + quiet: ${MONGODB_QUIET} + + +# net Options - Network interfaces settings +net: + # Specify port number (27017 by default) + port: ${CONTAINER_PORT} + + +# storage Options - How and Where to store data +storage: + # Directory for datafiles (defaults to /data/db/) + dbPath: ${MONGODB_DATADIR} + + +# replication Options - Configures replication +replication: + # Specifies a maximum size in megabytes for the replication operation log (i.e. the oplog, + # 5% of disk space by default) + oplogSizeMB: 64 diff --git a/tests/files/usr/share/container-scripts/mongodb/scl_enable b/tests/files/usr/share/container-scripts/mongodb/scl_enable new file mode 100644 index 0000000..5a25432 --- /dev/null +++ b/tests/files/usr/share/container-scripts/mongodb/scl_enable @@ -0,0 +1,3 @@ +# This will make scl collection binaries work out of box. +unset BASH_ENV PROMPT_COMMAND ENV +source scl_source enable ${ENABLED_COLLECTIONS} diff --git a/tests/files/usr/share/container-scripts/mongodb/test-functions.sh b/tests/files/usr/share/container-scripts/mongodb/test-functions.sh new file mode 100644 index 0000000..50ac0a0 --- /dev/null +++ b/tests/files/usr/share/container-scripts/mongodb/test-functions.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +set -o errexit +set -o nounset +set -o pipefail + +# insert_and_wait_for_replication insert data in host and wait all replset members +# applied recent oplog entry +function insert_and_wait_for_replication() { + local host + host=$1 + local data + data=$2 + + # Storing document into replset and wait replication to finish + local script + script="db.getSiblingDB('test_db').data.insert(${data}); + for (var i = 0; i < 60; i++) { + var status=rs.status(); + var optime=status.members[0].optime; + var ok=true; + for(var j=1; j < status.members.length; j++) { + if(tojson(optime) != tojson(status.members[j].optime)) { + ok=false; + } + }; + if(ok == true) { + print('INFO: All members of replicaset are synchronized'); + quit(0); + } + sleep(1000); + } + print('ERROR: Members of replicaset are not synchronized'); + printjson(rs.status()); + quit(1);" + + mongo admin --host "${host}" -u admin -p "${MONGODB_ADMIN_PASSWORD}" --eval "${script}" +} + +# wait_replicaset_members waits till replset has specified number of members +function wait_replicaset_members() { + local host + host=$1 + local count + count=$2 + + local script + script="for (var i = 0; i < 60; i++) { + var ret = rs.status().members.length; + if (ret == ${count}) { + print('INFO: Replicaset has expected number of members'); + quit(0); + } + sleep(1000); + } + print('ERROR: Wrong count of members in replicaset'); + printjson(rs.status()); + quit(1);" + + mongo admin --host "${host}" -u admin -p "${MONGODB_ADMIN_PASSWORD}" --eval "${script}" +} diff --git a/tests/help.md b/tests/help.md new file mode 100644 index 0000000..e69de29 diff --git a/tests/mongodb.yaml b/tests/mongodb.yaml new file mode 100644 index 0000000..10f7a88 --- /dev/null +++ b/tests/mongodb.yaml @@ -0,0 +1,59 @@ +document: modulemd +version: 1 +data: + summary: MongoDB Module + description: Mongo from humongous is a high-performance, open source, schema-free + document-oriented database. MongoDB is written in C++ and offers the following features. + Collection oriented storage, easy storage of object/JSON-style data. + Dynamic queries. + Full index support, including on inner objects and embedded arrays. + Query profiling. + Replication and fail-over support. + Efficient storage of binary data including large objects (e.g. photos and videos). + Auto-sharding for cloud-level scalability (currently in early alpha). + Commercial Support Available. + A key goal of MongoDB is to bridge the gap between key/value stores (which are fast and highly scalable) + and traditional RDBMS systems (which are deep in functionality). + license: + module: [ AGPLv3 and zlib and ASL 2.0 ] + dependencies: + buildrequires: +# base-runtime: f26 + bootstrap: f26 + common-build-dependencies: f26 + shared-userspace: f26 + perl: f26 + requires: + base-runtime: f26 + perl: f26 + shared-userspace: f26 + references: + community: https://fedoraproject.org/wiki/Modularity + documentation: https://fedoraproject.org/wiki/Fedora_Packaging_Guidelines_for_Modules + tracker: https://taiga.fedorainfracloud.org/project/modularity + profiles: + default: + rpms: + - mongodb + api: + rpms: + - mongodb + components: + rpms: + mongodb: + rationale: MongoDB package. + ref: f26 + buildorder: 10 + python-pymongo: + rationale: MongoDB dependecy. + ref: f26 + buildorder: 8 + yaml-cpp: + rationale: MongoDB dependency. + ref: f26 + buildorder: 9 + asio: + rationale: MongoDB dependency. + ref: f26 + buildorder: 7 + diff --git a/tests/rpmvalidator.py b/tests/rpmvalidator.py new file mode 100644 index 0000000..8dc7541 --- /dev/null +++ b/tests/rpmvalidator.py @@ -0,0 +1,56 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# This Modularity Testing Framework helps you to write tests for modules +# Copyright (C) 2017 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# he Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Authors: Jan Scotka +# + +from avocado import main +from moduleframework import module_framework + + +class ExampleRpmValidation(module_framework.AvocadoTest): + """ + :avocado: enable + """ + fhs_base_paths = [ + '/bin', + '/boot', + '/dev', + '/etc', + '/home', + '/lib', + '/lib64', + '/media', + '/mnt', + '/opt', + '/proc', + '/root', + '/run', + '/sbin', + '/sys', + '/srv', + '/tmp', + '/usr/bin' + ] + + def testPaths(self): + self.start() + for directory in self.fhs_base_paths: + self.run("test -d %s" % directory) diff --git a/tests/sanity.py b/tests/sanity.py new file mode 100644 index 0000000..139e407 --- /dev/null +++ b/tests/sanity.py @@ -0,0 +1,61 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# This Modularity Testing Framework helps you to write tests for modules +# Copyright (C) 2017 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# he Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Authors: Rado Pitonak +# + +from avocado import main +from avocado.core import exceptions +from moduleframework import module_framework + + +class SanityCheck(module_framework.AvocadoTest): + """ + :avocado: enable + """ + + def test1(self): + """ + Simple sanity test + """ + + self.start() + self.run("ls / | grep bin") + + def test2MongoVersion(self): + """ + Check if MongoDB is installed in correct version + """ + + mongo_version = "3.4.3" + self.start() + self.run("mongod --version | grep " + mongo_version) + + def test3ServiceRunning(self): + """ + Check if MongoDB is running + """ + + self.start() + self.run('ls /proc/*/exe -alh | grep mongod') + + +if __name__ == '__main__': + main() diff --git a/tests/sanity1.pyc b/tests/sanity1.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2dfbdb557d9489fd0f19a890965dc6570a97f085 GIT binary patch literal 938 zcmb_aO>fgc5PfSWZV9dEr66&#dh(?;;lQCq2xyTw_2BeCeOYbnP3rh#gLmAfQaPo6 zfZxg$DQMPF`2k={tDV`=oA=&~|7(Br^J4QY!}jw5d<0;x0pvg~PyuOw_fQGc9#Rj2 z-+WX)>H*S09}iFsQ3pr^hhR8!FX`HjxX@skV&{me36F%*yr7L$71 z{SiogB$LSFg4X~>VHk#|>egf`H>aU))U?trnK2O8F~M`Le+S?JSU5d`Z-PN{59DDj z#1G+~eLM&(2JF$gcWV+c#-)Afgfw##9v|ylRfR`-RZ#fm?1=W+m3d=YEiEbPZ1EdF zG-QYPu%ucd_O9)kuf~$|?W*lGJqMty)h&Jb-l@vPjJpMLT3xl()r?pXjU%49JM3Ek z@r|i;lFUBXKC4RN4g~ zWus~>rJJdg+X+f1Ldx7^QYJjbzg+%>P{QlW+hf`5zz@9W8B1km)?}sb-P=w&VZLsM xwuzI>v^sGM$%1;aPurF_*VyP!{ia-LORnSpA@BTp-#7ih{4E=}Cl2`c{{V;j%{Kr5 literal 0 HcmV?d00001 diff --git a/tests/sources b/tests/sources new file mode 100644 index 0000000..e69de29