Compare commits
No commits in common. "rawhide" and "f30" have entirely different histories.
20 changed files with 1479 additions and 1 deletions
0
.gitignore
vendored
Normal file
0
.gitignore
vendored
Normal file
49
Dockerfile
Normal file
49
Dockerfile
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
FROM registry.fedoraproject.org/fedora:rawhide
|
||||||
|
LABEL MAINTAINER SoftwareCollections.org <sclorg@redhat.com>
|
||||||
|
|
||||||
|
ENV NAME=mongodb \
|
||||||
|
VERSION=0 \
|
||||||
|
RELEASE=1 \
|
||||||
|
ARCH=x86_64
|
||||||
|
|
||||||
|
LABEL com.redhat.component="$NAME" \
|
||||||
|
name="$FGC/$NAME" \
|
||||||
|
version="$VERSION" \
|
||||||
|
release="$RELEASE.$DISTTAG" \
|
||||||
|
architecture="$ARCH" \
|
||||||
|
usage="docker run -d -e MONGODB_ADMIN_PASSWORD=my_pass $FGC/$NAME" \
|
||||||
|
help="help.1"
|
||||||
|
|
||||||
|
LABEL io.k8s.description="MongoDB is a scalable, high-performance, open source NoSQL database." \
|
||||||
|
io.k8s.display-name="MongoDB 3.4" \
|
||||||
|
io.openshift.expose-services="27017:mongodb" \
|
||||||
|
io.openshift.tags="database,mongodb"
|
||||||
|
|
||||||
|
ENV MONGODB_VERSION=3.4 \
|
||||||
|
# Set paths to avoid hard-coding them in scripts.
|
||||||
|
HOME=/var/lib/mongodb \
|
||||||
|
CONTAINER_SCRIPTS_PATH=/usr/share/container-scripts/mongodb
|
||||||
|
|
||||||
|
EXPOSE 27017
|
||||||
|
|
||||||
|
ENTRYPOINT ["container-entrypoint"]
|
||||||
|
CMD ["run-mongod"]
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
ADD root /
|
||||||
|
|
||||||
|
|
||||||
|
# Container setup
|
||||||
|
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
|
||||||
1
README.md
Symbolic link
1
README.md
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
root/usr/share/container-scripts/mongodb/README.md
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
The repository is available in https://github.com/sclorg organization. Images are pushed to quay.io/fedora organization from the upstream repo.
|
|
||||||
153
root/help.1
Normal file
153
root/help.1
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
.\"t
|
||||||
|
.\" WARNING: Do not edit this file manually, it is generated from README.md automatically.
|
||||||
|
.\"
|
||||||
|
.\"t
|
||||||
|
.\" Automatically generated by Pandoc 1.16.0.2
|
||||||
|
.\"
|
||||||
|
.TH "MONGODB\-32\-RHEL7" "1" "February 22, 2017" "Container Image Pages" ""
|
||||||
|
.hy
|
||||||
|
.SH MongoDB Docker image
|
||||||
|
.PP
|
||||||
|
This repository contains Dockerfiles for MongoDB images for general
|
||||||
|
usage and OpenShift.
|
||||||
|
Users can choose between RHEL and CentOS based images.
|
||||||
|
.SS Environment variables
|
||||||
|
.PP
|
||||||
|
The image recognizes the following environment variables that you can
|
||||||
|
set during initialization by passing \f[C]\-e\ VAR=VALUE\f[] to the
|
||||||
|
Docker run command.
|
||||||
|
.PP
|
||||||
|
.TS
|
||||||
|
tab(@);
|
||||||
|
l l.
|
||||||
|
T{
|
||||||
|
Variable name
|
||||||
|
T}@T{
|
||||||
|
Description
|
||||||
|
T}
|
||||||
|
_
|
||||||
|
T{
|
||||||
|
\f[C]MONGODB_USER\f[]
|
||||||
|
T}@T{
|
||||||
|
User name for MONGODB account to be created
|
||||||
|
T}
|
||||||
|
T{
|
||||||
|
\f[C]MONGODB_PASSWORD\f[]
|
||||||
|
T}@T{
|
||||||
|
Password for the user account
|
||||||
|
T}
|
||||||
|
T{
|
||||||
|
\f[C]MONGODB_DATABASE\f[]
|
||||||
|
T}@T{
|
||||||
|
Database name
|
||||||
|
T}
|
||||||
|
T{
|
||||||
|
\f[C]MONGODB_ADMIN_PASSWORD\f[]
|
||||||
|
T}@T{
|
||||||
|
Password for the admin user
|
||||||
|
T}
|
||||||
|
.TE
|
||||||
|
.PP
|
||||||
|
The following environment variables influence the MongoDB configuration
|
||||||
|
file.
|
||||||
|
They are all optional.
|
||||||
|
.PP
|
||||||
|
.TS
|
||||||
|
tab(@);
|
||||||
|
lw(13.6n) lw(45.8n) lw(10.5n).
|
||||||
|
T{
|
||||||
|
Variable name
|
||||||
|
T}@T{
|
||||||
|
Description
|
||||||
|
T}@T{
|
||||||
|
Default
|
||||||
|
T}
|
||||||
|
_
|
||||||
|
T{
|
||||||
|
\f[C]MONGODB_QUIET\f[]
|
||||||
|
T}@T{
|
||||||
|
Runs MongoDB in a quiet mode that attempts to limit the amount of
|
||||||
|
output.
|
||||||
|
T}@T{
|
||||||
|
true
|
||||||
|
T}
|
||||||
|
.TE
|
||||||
|
.PP
|
||||||
|
You can also set the following mount points by passing the
|
||||||
|
\f[C]\-v\ /host:/container\f[] flag to Docker.
|
||||||
|
.PP
|
||||||
|
.TS
|
||||||
|
tab(@);
|
||||||
|
l l.
|
||||||
|
T{
|
||||||
|
Volume mount point
|
||||||
|
T}@T{
|
||||||
|
Description
|
||||||
|
T}
|
||||||
|
_
|
||||||
|
T{
|
||||||
|
\f[C]/var/lib/mongodb/data\f[]
|
||||||
|
T}@T{
|
||||||
|
MongoDB data directory
|
||||||
|
T}
|
||||||
|
.TE
|
||||||
|
.PP
|
||||||
|
\f[B]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.\f[]
|
||||||
|
.SS Usage
|
||||||
|
.PP
|
||||||
|
For this, we will assume that you are using the
|
||||||
|
\f[C]centos/mongodb\-32\-centos7\f[] image.
|
||||||
|
If you want to set only the mandatory environment variables and store
|
||||||
|
the database in the \f[C]/home/user/database\f[] directory on the host
|
||||||
|
filesystem, execute the following command:
|
||||||
|
.IP
|
||||||
|
.nf
|
||||||
|
\f[C]
|
||||||
|
$\ docker\ run\ \-d\ \-e\ MONGODB_USER=<user>\ \-e\ MONGODB_PASSWORD=<password>\ \-e\ MONGODB_DATABASE=<database>\ \-e\ MONGODB_ADMIN_PASSWORD=<admin_password>\ \-v\ /home/user/database:/var/lib/mongodb/data\ centos/mongodb\-32\-centos7
|
||||||
|
\f[]
|
||||||
|
.fi
|
||||||
|
.PP
|
||||||
|
If you are initializing the database and it\[aq]s the first time you are
|
||||||
|
using the specified shared volume, the database will be created with two
|
||||||
|
users: \f[C]admin\f[] and \f[C]MONGODB_USER\f[].
|
||||||
|
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.
|
||||||
|
.SS Custom configuration file
|
||||||
|
.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
|
||||||
|
\f[C]/etc/mongod.conf\f[].
|
||||||
|
For example to use configuration file stored in \f[C]/home/user\f[]
|
||||||
|
directory use this option for \f[C]docker\ run\f[] command:
|
||||||
|
\f[C]\-v\ /home/user/mongod.conf:/etc/mongod.conf:Z\f[].
|
||||||
|
.PP
|
||||||
|
\f[B]Notice: Custom config file does not affect name of replica set. It
|
||||||
|
has to be set in \f[C]MONGODB_REPLICA_NAME\f[] environment variable.\f[]
|
||||||
|
.SS MongoDB admin user
|
||||||
|
.PP
|
||||||
|
The admin user name is set to \f[C]admin\f[] and you have to to specify
|
||||||
|
the password by setting the \f[C]MONGODB_ADMIN_PASSWORD\f[] environment
|
||||||
|
variable.
|
||||||
|
This process is done upon database initialization.
|
||||||
|
.SS Changing passwords
|
||||||
|
.PP
|
||||||
|
Since passwords are part of the image configuration, the only supported
|
||||||
|
method to change passwords for the database user (\f[C]MONGODB_USER\f[])
|
||||||
|
and admin user is by changing the environment variables
|
||||||
|
\f[C]MONGODB_PASSWORD\f[] and \f[C]MONGODB_ADMIN_PASSWORD\f[],
|
||||||
|
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.
|
||||||
|
.SH AUTHORS
|
||||||
|
Red Hat.
|
||||||
92
root/usr/bin/cgroup-limits
Executable file
92
root/usr/bin/cgroup-limits
Executable file
|
|
@ -0,0 +1,92 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
"""
|
||||||
|
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))
|
||||||
2
root/usr/bin/container-entrypoint
Executable file
2
root/usr/bin/container-entrypoint
Executable file
|
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/bash
|
||||||
|
exec "$@"
|
||||||
57
root/usr/bin/run-mongod
Executable file
57
root/usr/bin/run-mongod
Executable file
|
|
@ -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
|
||||||
1
root/usr/bin/run-mongod-pet
Symbolic link
1
root/usr/bin/run-mongod-pet
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
run-mongod-replication
|
||||||
55
root/usr/bin/run-mongod-replication
Executable file
55
root/usr/bin/run-mongod-replication
Executable file
|
|
@ -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
|
||||||
6
root/usr/libexec/fix-permissions
Executable file
6
root/usr/libexec/fix-permissions
Executable file
|
|
@ -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 {} +
|
||||||
90
root/usr/share/container-scripts/mongodb/README.md
Normal file
90
root/usr/share/container-scripts/mongodb/README.md
Normal file
|
|
@ -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=<user> -e MONGODB_PASSWORD=<password> -e MONGODB_DATABASE=<database> -e MONGODB_ADMIN_PASSWORD=<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.
|
||||||
|
|
||||||
259
root/usr/share/container-scripts/mongodb/common.sh
Normal file
259
root/usr/share/container-scripts/mongodb/common.sh
Normal file
|
|
@ -0,0 +1,259 @@
|
||||||
|
#!/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
|
||||||
|
echo >&2 "Cannot get address of replica set: no nodes are listed in service"
|
||||||
|
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=$(python3 -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')" "$*"
|
||||||
|
}
|
||||||
111
root/usr/share/container-scripts/mongodb/init-replset.sh
Executable file
111
root/usr/share/container-scripts/mongodb/init-replset.sh
Executable file
|
|
@ -0,0 +1,111 @@
|
||||||
|
#!/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)"
|
||||||
|
|
||||||
|
# Outputs available endpoints (hostnames) to stdout.
|
||||||
|
# This also includes hostname of the current pod.
|
||||||
|
#
|
||||||
|
# Uses the following global variables:
|
||||||
|
# - MONGODB_SERVICE_NAME (optional, defaults to 'mongodb')
|
||||||
|
function find_endpoints() {
|
||||||
|
local service_name="${MONGODB_SERVICE_NAME:-mongodb}"
|
||||||
|
|
||||||
|
# Extract host names from lines like this: "10 33 0 mongodb-2.mongodb.myproject.svc.cluster.local."
|
||||||
|
dig "${service_name}" SRV +search +short | cut -d' ' -f4 | rev | cut -c2- | rev
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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 ..."
|
||||||
|
|
||||||
|
# TODO: replace this with a call to `replset_addr` from common.sh, once it returns host names.
|
||||||
|
local endpoints
|
||||||
|
endpoints="$(find_endpoints | paste -s -d,)"
|
||||||
|
|
||||||
|
if [ -z "${endpoints}" ]; then
|
||||||
|
info "ERROR: couldn't add host to replica set!"
|
||||||
|
info "CAUSE: DNS lookup for '${MONGODB_SERVICE_NAME:-mongodb}' returned no results."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local replset_addr
|
||||||
|
replset_addr="${MONGODB_REPLICA_NAME}/${endpoints}"
|
||||||
|
|
||||||
|
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
|
||||||
|
|
@ -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
|
||||||
3
root/usr/share/container-scripts/mongodb/scl_enable
Normal file
3
root/usr/share/container-scripts/mongodb/scl_enable
Normal file
|
|
@ -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}
|
||||||
61
root/usr/share/container-scripts/mongodb/test-functions.sh
Normal file
61
root/usr/share/container-scripts/mongodb/test-functions.sh
Normal file
|
|
@ -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}"
|
||||||
|
}
|
||||||
0
sources
Normal file
0
sources
Normal file
423
test/run
Executable file
423
test/run
Executable file
|
|
@ -0,0 +1,423 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Test the MongoDB image.
|
||||||
|
#
|
||||||
|
# IMAGE_NAME specifies a name of the candidate image used for testing.
|
||||||
|
# The image has to be available before this script is executed.
|
||||||
|
#
|
||||||
|
|
||||||
|
set -exo nounset
|
||||||
|
shopt -s nullglob
|
||||||
|
|
||||||
|
IMAGE_NAME=${IMAGE_NAME-centos/mongodb-32-centos7-candidate}
|
||||||
|
|
||||||
|
CIDFILE_DIR=$(mktemp --suffix=mongodb_test_cidfiles -d)
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
for cidfile in $CIDFILE_DIR/* ; do
|
||||||
|
CONTAINER=$(cat $cidfile)
|
||||||
|
|
||||||
|
echo "Stopping and removing container $CONTAINER..."
|
||||||
|
docker stop $CONTAINER
|
||||||
|
docker rm $CONTAINER
|
||||||
|
rm $cidfile
|
||||||
|
echo "Done."
|
||||||
|
done
|
||||||
|
rmdir $CIDFILE_DIR
|
||||||
|
}
|
||||||
|
trap cleanup EXIT SIGINT
|
||||||
|
|
||||||
|
function get_cid() {
|
||||||
|
local id="$1" ; shift || return 1
|
||||||
|
echo -n $(cat "$CIDFILE_DIR/$id")
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_container_ip() {
|
||||||
|
local id="$1" ; shift
|
||||||
|
docker inspect --format='{{.NetworkSettings.IPAddress}}' $(get_cid "$id")
|
||||||
|
}
|
||||||
|
|
||||||
|
function mongo_cmd() {
|
||||||
|
docker run --rm $IMAGE_NAME mongo "$DB" --host $CONTAINER_IP -u "$USER" -p"$PASS" --eval "${@}"
|
||||||
|
}
|
||||||
|
|
||||||
|
function mongo_admin_cmd() {
|
||||||
|
docker run --rm $IMAGE_NAME mongo admin --host $CONTAINER_IP -u admin -p"$ADMIN_PASS" --eval "${@}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Make sure the invocation of docker run fails.
|
||||||
|
function assert_container_creation_fails() {
|
||||||
|
|
||||||
|
# Time the docker run command. It should fail. If it doesn't fail,
|
||||||
|
# container will keep running so we kill it with SIGKILL to make sure
|
||||||
|
# timeout returns a non-zero value.
|
||||||
|
set +e
|
||||||
|
timeout -s 9 --preserve-status 10s docker run --rm "$@" $IMAGE_NAME
|
||||||
|
ret=$?
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Timeout will exit with a high number.
|
||||||
|
if [ $ret -gt 30 ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_container_creation_tests() {
|
||||||
|
echo " Testing wrong user variables usage"
|
||||||
|
|
||||||
|
assert_container_creation_fails -e MONGODB_USER=user -e MONGODB_PASSWORD=pass
|
||||||
|
assert_container_creation_fails -e MONGODB_DATABASE=db -e MONGODB_PASSWORD=pass
|
||||||
|
assert_container_creation_fails -e MONGODB_DATABASE=db -e MONGODB_USER=user
|
||||||
|
assert_container_creation_fails -e MONGODB_USER=user -e MONGODB_DATABASE=db -e MONGODB_PASSWORD=pass
|
||||||
|
|
||||||
|
assert_container_creation_fails -e MONGODB_ADMIN_PASSWORD=Pass -e MONGODB_USER=user
|
||||||
|
assert_container_creation_fails -e MONGODB_ADMIN_PASSWORD=Pass -e MONGODB_PASSWORD=pass
|
||||||
|
assert_container_creation_fails -e MONGODB_ADMIN_PASSWORD=Pass -e MONGODB_DATABASE=db
|
||||||
|
|
||||||
|
echo " Success!"
|
||||||
|
echo " Testing good user variables usage"
|
||||||
|
assert_container_creation_fails -e MONGODB_ADMIN_PASSWORD=Pass || [ $? -eq 1 ]
|
||||||
|
assert_container_creation_fails -e MONGODB_ADMIN_PASSWORD=Pass -e MONGODB_USER=user -e MONGODB_DATABASE=db -e MONGODB_PASSWORD=pass || [ $? -eq 1 ]
|
||||||
|
echo " Success!"
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_connection() {
|
||||||
|
local name=$1 ; shift
|
||||||
|
CONTAINER_IP=$(get_container_ip $name)
|
||||||
|
echo " Testing MongoDB connection to $CONTAINER_IP..."
|
||||||
|
local max_attempts=20
|
||||||
|
local sleep_time=2
|
||||||
|
for i in $(seq $max_attempts); do
|
||||||
|
echo " Trying to connect..."
|
||||||
|
set +e
|
||||||
|
mongo_cmd "db.getSiblingDB('test_database');"
|
||||||
|
status=$?
|
||||||
|
set -e
|
||||||
|
if [ $status -eq 0 ]; then
|
||||||
|
echo " Success!"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sleep $sleep_time
|
||||||
|
done
|
||||||
|
echo " Giving up: Failed to connect. Logs:"
|
||||||
|
docker logs $(get_cid $name)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
test_scl_usage() {
|
||||||
|
local name="$1"
|
||||||
|
local run_cmd="$2"
|
||||||
|
local expected="$3"
|
||||||
|
|
||||||
|
echo " Testing the image SCL enable"
|
||||||
|
out=$(docker run --rm ${IMAGE_NAME} /bin/bash -c "${run_cmd}")
|
||||||
|
if ! echo "${out}" | grep -q "${expected}"; then
|
||||||
|
echo "ERROR[/bin/bash -c "${run_cmd}"] Expected '${expected}', got '${out}'"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
out=$(docker exec $(get_cid $name) /bin/bash -c "${run_cmd}" 2>&1)
|
||||||
|
if ! echo "${out}" | grep -q "${expected}"; then
|
||||||
|
echo "ERROR[exec /bin/bash -c "${run_cmd}"] Expected '${expected}', got '${out}'"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
out=$(docker exec $(get_cid $name) /bin/sh -ic "${run_cmd}" 2>&1)
|
||||||
|
if ! echo "${out}" | grep -q "${expected}"; then
|
||||||
|
echo "ERROR[exec /bin/sh -ic "${run_cmd}"] Expected '${expected}', got '${out}'"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_mongo() {
|
||||||
|
echo " Testing MongoDB"
|
||||||
|
if [ -v ADMIN_PASS ]; then
|
||||||
|
echo " Testing Admin user privileges"
|
||||||
|
mongo_admin_cmd "db=db.getSiblingDB('${DB}');db.dropUser('${USER}');"
|
||||||
|
mongo_admin_cmd "db=db.getSiblingDB('${DB}');db.createUser({user:'${USER}',pwd:'${PASS}',roles:['readWrite','userAdmin','dbAdmin']});"
|
||||||
|
mongo_admin_cmd "db=db.getSiblingDB('${DB}');db.testData.insert({x:0});"
|
||||||
|
mongo_cmd "db.createUser({user:'test_user2',pwd:'test_password2',roles:['readWrite']});"
|
||||||
|
fi
|
||||||
|
echo " Testing user privileges"
|
||||||
|
mongo_cmd "db.testData.insert({ y : 1 });"
|
||||||
|
mongo_cmd "db.testData.insert({ z : 2 });"
|
||||||
|
mongo_cmd "db.testData.find().forEach(printjson);"
|
||||||
|
mongo_cmd "db.testData.count();"
|
||||||
|
mongo_cmd "db.testData.drop();"
|
||||||
|
mongo_cmd "db.dropDatabase();"
|
||||||
|
echo " Success!"
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_config_option() {
|
||||||
|
local env_var=$1 ; shift
|
||||||
|
local env_val=$1 ; shift
|
||||||
|
local config_part=$1 ; shift
|
||||||
|
|
||||||
|
local name="configuration_${env_var}"
|
||||||
|
|
||||||
|
# If $value is a string, it needs to be in simple quotes ''.
|
||||||
|
DOCKER_ARGS="
|
||||||
|
-e MONGODB_DATABASE=db
|
||||||
|
-e MONGODB_USER=user
|
||||||
|
-e MONGODB_PASSWORD=password
|
||||||
|
-e MONGODB_ADMIN_PASSWORD=adminPassword
|
||||||
|
-e $env_var=${env_val}
|
||||||
|
"
|
||||||
|
create_container ${name} ${DOCKER_ARGS}
|
||||||
|
|
||||||
|
# need to set these because `mongo_cmd` relies on global variables
|
||||||
|
USER=user
|
||||||
|
PASS=password
|
||||||
|
DB=db
|
||||||
|
|
||||||
|
test_connection ${name}
|
||||||
|
|
||||||
|
# If nothing is found, grep returns 1 and test fails.
|
||||||
|
docker exec $(get_cid $name) bash -c "cat /etc/mongod.conf" | grep -q "${config_part}"
|
||||||
|
|
||||||
|
docker stop $(get_cid ${name})
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_configuration_tests() {
|
||||||
|
echo " Testing image configuration settings"
|
||||||
|
test_config_option MONGODB_QUIET true "quiet: true"
|
||||||
|
echo " Success!"
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_for_cid() {
|
||||||
|
local max_attempts=10
|
||||||
|
local sleep_time=1
|
||||||
|
local attempt=1
|
||||||
|
local result=1
|
||||||
|
while [ $attempt -le $max_attempts ]; do
|
||||||
|
[ -f $cid_file ] && [ -s $cid_file ] && break
|
||||||
|
echo "Waiting for container start..."
|
||||||
|
attempt=$(( $attempt + 1 ))
|
||||||
|
sleep $sleep_time
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function create_container() {
|
||||||
|
local name=$1 ; shift
|
||||||
|
local cargs=${CONTAINER_ARGS:-}
|
||||||
|
cid_file="$CIDFILE_DIR/$name"
|
||||||
|
# create container with a cidfile in a directory for cleanup
|
||||||
|
docker run --cidfile $cid_file -d $cargs "$@" $IMAGE_NAME
|
||||||
|
echo "Created container $(cat $cid_file)"
|
||||||
|
wait_for_cid
|
||||||
|
}
|
||||||
|
|
||||||
|
function assert_login_access() {
|
||||||
|
local USER=$1 ; shift
|
||||||
|
local PASS=$1 ; shift
|
||||||
|
local success=$1 ; shift
|
||||||
|
|
||||||
|
if mongo_cmd 'db.version()' ; then
|
||||||
|
if $success ; then
|
||||||
|
echo " $USER($PASS) access granted as expected"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if ! $success ; then
|
||||||
|
echo " $USER($PASS) access denied as expected"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo " $USER($PASS) login assertion failed"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_tests() {
|
||||||
|
local name=$1 ; shift
|
||||||
|
envs="-e MONGODB_USER=$USER -e MONGODB_PASSWORD=$PASS -e MONGODB_DATABASE=$DB"
|
||||||
|
if [ -v ADMIN_PASS ]; then
|
||||||
|
envs="$envs -e MONGODB_ADMIN_PASSWORD=$ADMIN_PASS"
|
||||||
|
fi
|
||||||
|
create_container $name $envs
|
||||||
|
CONTAINER_IP=$(get_container_ip $name)
|
||||||
|
test_connection $name
|
||||||
|
echo " Testing scl usage"
|
||||||
|
test_scl_usage $name 'mongo --version' '3.2'
|
||||||
|
test_mongo $name
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_change_password_test() {
|
||||||
|
local name="change_password"
|
||||||
|
|
||||||
|
local database='db'
|
||||||
|
local user='user'
|
||||||
|
local password='password'
|
||||||
|
local admin_password='adminPassword'
|
||||||
|
|
||||||
|
local volume_dir
|
||||||
|
volume_dir=`mktemp -d --tmpdir mongodb-testdata.XXXXX`
|
||||||
|
chmod a+rwx ${volume_dir}
|
||||||
|
|
||||||
|
DOCKER_ARGS="
|
||||||
|
-e MONGODB_DATABASE=${database}
|
||||||
|
-e MONGODB_USER=${user}
|
||||||
|
-e MONGODB_PASSWORD=${password}
|
||||||
|
-e MONGODB_ADMIN_PASSWORD=${admin_password}
|
||||||
|
-v ${volume_dir}:/var/lib/mongodb/data:Z
|
||||||
|
"
|
||||||
|
create_container ${name} ${DOCKER_ARGS}
|
||||||
|
|
||||||
|
# need to set these because `mongo_cmd` relies on global variables
|
||||||
|
USER=${user}
|
||||||
|
PASS=${password}
|
||||||
|
DB=${database}
|
||||||
|
|
||||||
|
# need this to wait for the container to start up
|
||||||
|
CONTAINER_IP=$(get_container_ip ${name})
|
||||||
|
test_connection ${name}
|
||||||
|
|
||||||
|
echo " Testing login"
|
||||||
|
|
||||||
|
assert_login_access ${user} ${password} true
|
||||||
|
DB='admin' assert_login_access 'admin' ${admin_password} true
|
||||||
|
|
||||||
|
echo " Changing passwords"
|
||||||
|
|
||||||
|
docker stop $(get_cid ${name})
|
||||||
|
DOCKER_ARGS="
|
||||||
|
-e MONGODB_DATABASE=${database}
|
||||||
|
-e MONGODB_USER=${user}
|
||||||
|
-e MONGODB_PASSWORD=NEW_${password}
|
||||||
|
-e MONGODB_ADMIN_PASSWORD=NEW_${admin_password}
|
||||||
|
-v ${volume_dir}:/var/lib/mongodb/data:Z
|
||||||
|
"
|
||||||
|
create_container "${name}_NEW" ${DOCKER_ARGS}
|
||||||
|
|
||||||
|
# need to set this because `mongo_cmd` relies on global variables
|
||||||
|
PASS="NEW_${password}"
|
||||||
|
|
||||||
|
# need this to wait for the container to start up
|
||||||
|
CONTAINER_IP=$(get_container_ip "${name}_NEW")
|
||||||
|
test_connection "${name}_NEW"
|
||||||
|
|
||||||
|
echo " Testing login with new passwords"
|
||||||
|
|
||||||
|
assert_login_access ${user} "NEW_${password}" true
|
||||||
|
assert_login_access ${user} ${password} false
|
||||||
|
|
||||||
|
DB='admin' assert_login_access 'admin' "NEW_${admin_password}" true
|
||||||
|
DB='admin' assert_login_access 'admin' ${admin_password} false
|
||||||
|
|
||||||
|
# need to remove volume_dir with sudo because of permissions of files written
|
||||||
|
# by the Docker container
|
||||||
|
sudo rm -rf ${volume_dir}
|
||||||
|
|
||||||
|
echo " Success!"
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_mount_config_test() {
|
||||||
|
local name="mount_config"
|
||||||
|
echo " Testing config file mount"
|
||||||
|
local database='db'
|
||||||
|
local user='user'
|
||||||
|
local password='password'
|
||||||
|
local admin_password='adminPassword'
|
||||||
|
|
||||||
|
local volume_dir
|
||||||
|
volume_dir=`mktemp -d --tmpdir mongodb-testdata.XXXXX`
|
||||||
|
chmod a+rwx ${volume_dir}
|
||||||
|
config_file=$volume_dir/mongod.conf
|
||||||
|
echo "dbpath=/var/lib/mongodb/dbpath
|
||||||
|
unixSocketPrefix = /var/lib/mongodb" > $config_file
|
||||||
|
chmod a+r ${config_file}
|
||||||
|
|
||||||
|
DOCKER_ARGS="
|
||||||
|
-e MONGODB_DATABASE=${database}
|
||||||
|
-e MONGODB_USER=${user}
|
||||||
|
-e MONGODB_PASSWORD=${password}
|
||||||
|
-e MONGODB_ADMIN_PASSWORD=${admin_password}
|
||||||
|
-v ${config_file}:/etc/mongod.conf:Z
|
||||||
|
-v ${volume_dir}:/var/lib/mongodb/dbpath:Z
|
||||||
|
"
|
||||||
|
create_container ${name} ${DOCKER_ARGS}
|
||||||
|
|
||||||
|
# need to set these because `mongo_cmd` relies on global variables
|
||||||
|
USER=${user}
|
||||||
|
PASS=${password}
|
||||||
|
DB=${database}
|
||||||
|
|
||||||
|
# need this to wait for the container to start up
|
||||||
|
CONTAINER_IP=$(get_container_ip ${name})
|
||||||
|
echo " Testing mongod is running"
|
||||||
|
test_connection ${name}
|
||||||
|
echo " Testing config file works"
|
||||||
|
docker exec $(get_cid ${name}) bash -c "test -S /var/lib/mongodb/mongodb-27017.sock"
|
||||||
|
|
||||||
|
# need to remove volume_dir with sudo because of permissions of files written
|
||||||
|
# by the Docker container
|
||||||
|
sudo rm -rf ${volume_dir}
|
||||||
|
|
||||||
|
echo " Success!"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_doc_test() {
|
||||||
|
local tmpdir=$(mktemp -d)
|
||||||
|
local f
|
||||||
|
echo " Testing documentation in the container image"
|
||||||
|
# Extract the help files from the container
|
||||||
|
for f in /usr/share/container-scripts/mongodb/README.md help.1 ; do
|
||||||
|
docker run --rm ${IMAGE_NAME} /bin/bash -c "cat /${f}" >${tmpdir}/$(basename ${f})
|
||||||
|
# Check whether the files include some important information
|
||||||
|
for term in MONGODB_ADMIN_PASSWORD volume ; do
|
||||||
|
if ! cat ${tmpdir}/$(basename ${f}) | grep -q -e "${term}" ; then
|
||||||
|
echo "ERROR: File /${f} does not include '${term}'."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
# Check whether the files use the correct format
|
||||||
|
if ! file ${tmpdir}/help.1 | grep -q roff ; then
|
||||||
|
echo "ERROR: /help.1 is not in troff or groff format"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo " Success!"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
run_WT_cache_test() {
|
||||||
|
local name="WT_cache_size"
|
||||||
|
echo " Testing setting of WT cache size"
|
||||||
|
local database='db'
|
||||||
|
local user='user'
|
||||||
|
local password='password'
|
||||||
|
local admin_password='adminPassword'
|
||||||
|
|
||||||
|
DOCKER_ARGS="
|
||||||
|
-e MONGODB_DATABASE=${database}
|
||||||
|
-e MONGODB_USER=${user}
|
||||||
|
-e MONGODB_PASSWORD=${password}
|
||||||
|
-e MONGODB_ADMIN_PASSWORD=${admin_password}
|
||||||
|
"
|
||||||
|
# need to set these because `mongo_cmd` relies on global variables
|
||||||
|
USER=${user}
|
||||||
|
PASS=${password}
|
||||||
|
DB=${database}
|
||||||
|
ADMIN_PASS=${admin_password}
|
||||||
|
|
||||||
|
# minimum is 1G
|
||||||
|
create_container "${name}_200M" ${DOCKER_ARGS} -m 200M
|
||||||
|
test_connection ${name}_200M
|
||||||
|
mongo_admin_cmd "if (db.serverStatus()['wiredTiger']['cache']['maximum bytes configured'] == Math.pow(2,30)){quit(0)}; quit(1)"
|
||||||
|
# if greater that 1G, use 60% of (RAM - 1G)
|
||||||
|
create_container "${name}_6G" ${DOCKER_ARGS} -m 6G
|
||||||
|
test_connection ${name}_6G
|
||||||
|
mongo_admin_cmd "if (db.serverStatus()['wiredTiger']['cache']['maximum bytes configured'] == 3*Math.pow(2,30)){quit(0)}; quit(1)"
|
||||||
|
|
||||||
|
echo " Success!"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Tests.
|
||||||
|
run_container_creation_tests
|
||||||
|
run_configuration_tests
|
||||||
|
USER="user1" PASS="pass1" DB="test_db" ADMIN_PASS="r00t" run_tests admin
|
||||||
|
# Test with random uid in container
|
||||||
|
CONTAINER_ARGS="-u 12345" USER="user1" PASS="pass1" DB="test_db" ADMIN_PASS="r00t" run_tests admin_altuid
|
||||||
|
run_change_password_test
|
||||||
|
run_mount_config_test
|
||||||
|
run_doc_test
|
||||||
|
run_WT_cache_test
|
||||||
88
test/run-openshift
Executable file
88
test/run-openshift
Executable file
|
|
@ -0,0 +1,88 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Test the MongoDB image in OpenShift.
|
||||||
|
#
|
||||||
|
# IMAGE_NAME specifies a name of the candidate image used for testing.
|
||||||
|
# The image has to be available before this script is executed.
|
||||||
|
#
|
||||||
|
|
||||||
|
set -exo nounset
|
||||||
|
|
||||||
|
function prepare_oc_client() {
|
||||||
|
# Prepare oc command
|
||||||
|
if [[ ! -d ../openshift-client/ ]]; then
|
||||||
|
OC_RELEASE=$(curl -s https://api.github.com/repos/openshift/origin/releases | grep "browser_download_url" | grep "openshift-origin-client" | grep "linux-64bit" | sort | tail -n 1 | sed -e 's|"browser_download_url": ||' | tr -d ' "')
|
||||||
|
|
||||||
|
curl -L ${OC_RELEASE} | tar xz
|
||||||
|
mv ./openshift-origin-client-tools-* ../openshift-client
|
||||||
|
fi
|
||||||
|
export PATH=${PATH}:`pwd`/../openshift-client/
|
||||||
|
}
|
||||||
|
prepare_oc_client
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
echo "Stopping and removing OpenShift cluster..."
|
||||||
|
oc delete project --all
|
||||||
|
oc cluster down
|
||||||
|
}
|
||||||
|
trap cleanup EXIT SIGINT
|
||||||
|
|
||||||
|
function print_logs() {
|
||||||
|
oc get all
|
||||||
|
while read pod_info; do
|
||||||
|
pod=$(echo ${pod_info} | tr -s ' ' | cut -f1 -d' ')
|
||||||
|
echo "INFO: printing logs for pod ${pod}"
|
||||||
|
oc logs ${pod}
|
||||||
|
done < <(oc get pods --no-headers=true)
|
||||||
|
}
|
||||||
|
trap print_logs ERR
|
||||||
|
|
||||||
|
# Start OpenShift cluster
|
||||||
|
[ -d openshift.pv ] || mkdir openshift.pv
|
||||||
|
oc cluster up --host-pv-dir=$(pwd)/openshift.pv
|
||||||
|
|
||||||
|
# Prepare image - add tag different than :latest
|
||||||
|
# With :latest default imagePullPolicy is Always
|
||||||
|
# https://docs.openshift.com/enterprise/3.2/dev_guide/managing_images.html#image-pull-policy
|
||||||
|
docker tag ${IMAGE_NAME} ${IMAGE_NAME}:test-openshift
|
||||||
|
IMAGE_NAME=${IMAGE_NAME}:test-openshift
|
||||||
|
|
||||||
|
#
|
||||||
|
# General functions
|
||||||
|
#
|
||||||
|
|
||||||
|
# wait_for_ready_pods wait till number of pods with label get ready
|
||||||
|
function wait_for_ready_pods() {
|
||||||
|
local label="$1"
|
||||||
|
local count="$2"
|
||||||
|
for i in $(seq 30); do
|
||||||
|
if [[ "$(oc get pods --no-headers=true -l${label} | grep "1/1" | wc -l)" -eq ${count} ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo "Waiting for ${count} ready pods labeled with '${label}'..."
|
||||||
|
sleep 20
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Deploy MongoDB clustered application
|
||||||
|
USER=user
|
||||||
|
PASS=pass
|
||||||
|
ADMIN_PASS=adminPass
|
||||||
|
DB=db
|
||||||
|
|
||||||
|
oc new-project petset-example
|
||||||
|
oc new-app --file=../examples/petset/mongodb-petset-persistent.yaml -p MONGODB_USER=${USER} -p MONGODB_PASSWORD=${PASS} -p MONGODB_DATABASE=${DB} -p MONGODB_ADMIN_PASSWORD=${ADMIN_PASS} -p MONGODB_IMAGE=${IMAGE_NAME} -p VOLUME_CAPACITY=500M
|
||||||
|
|
||||||
|
wait_for_ready_pods "app=mongodb-petset-replication" 3
|
||||||
|
wait_for_ready_pods "openshift.io/deployer-pod-for.name" 0
|
||||||
|
|
||||||
|
host="rs0/$(oc get endpoints mongodb --no-headers | tr -s ' ' | cut -f2 -d' ')"
|
||||||
|
|
||||||
|
docker exec origin kubectl run --attach --restart=Never mongodb-test --image ${IMAGE_NAME} --env="MONGODB_ADMIN_PASSWORD=${ADMIN_PASS}" --command -- bash -c "set -x
|
||||||
|
. /usr/share/container-scripts/mongodb/common.sh
|
||||||
|
. /usr/share/container-scripts/mongodb/test-functions.sh
|
||||||
|
wait_for_mongo_up '${host}'
|
||||||
|
wait_replicaset_members '${host}' 3
|
||||||
|
insert_and_wait_for_replication '${host}' '{a:5, b:10}'"
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue