The repository is available in https://github.com/sclorg organization. Images are pushed to quay.io/fedora organization from the upstream repo.
This commit is contained in:
parent
6d9e58bd56
commit
896bb65993
20 changed files with 1 additions and 1479 deletions
0
.gitignore
vendored
0
.gitignore
vendored
49
Dockerfile
49
Dockerfile
|
|
@ -1,49 +0,0 @@
|
|||
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 +0,0 @@
|
|||
root/usr/share/container-scripts/mongodb/README.md
|
||||
1
dead.package
Normal file
1
dead.package
Normal file
|
|
@ -0,0 +1 @@
|
|||
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
153
root/help.1
|
|
@ -1,153 +0,0 @@
|
|||
.\"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.
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
#!/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))
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
#!/bin/bash
|
||||
exec "$@"
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
#!/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 +0,0 @@
|
|||
run-mongod-replication
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
#!/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
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
#!/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 {} +
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
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.
|
||||
|
||||
|
|
@ -1,259 +0,0 @@
|
|||
#!/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')" "$*"
|
||||
}
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
#!/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
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
##
|
||||
## 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
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
# This will make scl collection binaries work out of box.
|
||||
unset BASH_ENV PROMPT_COMMAND ENV
|
||||
source scl_source enable ${ENABLED_COLLECTIONS}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
#!/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
0
sources
423
test/run
423
test/run
|
|
@ -1,423 +0,0 @@
|
|||
#!/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
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
#!/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