adding dummy files and templates to run tests
This commit is contained in:
parent
35e45e4945
commit
f2b6b13b62
15 changed files with 839 additions and 0 deletions
29
Dockerfile
Normal file
29
Dockerfile
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
FROM registry.fedoraproject.org/fedora:26
|
||||
|
||||
ENV NAME=mongodb ARCH=x86_64
|
||||
LABEL MAINTAINER "Matus Kocka" <mkocka@redhat.com>
|
||||
LABEL summary="MongoDB is a scalable, high-performance, open source NoSQL database."
|
||||
|
||||
EXPOSE 27017
|
||||
|
||||
RUN INSTALL_PKGS="bind-utils gettext iproute rsync tar findutils python3 mongodb mongodb-server mongo-tools" && \
|
||||
dnf install -y --setopt=tsflags=nodocs $INSTALL_PKGS && \
|
||||
rpm -V $INSTALL_PKGS && \
|
||||
dnf clean all
|
||||
|
||||
ADD files /
|
||||
|
||||
ENTRYPOINT ["container-entrypoint"]
|
||||
CMD ["run-mongod"]
|
||||
|
||||
# Container setup from scl
|
||||
RUN : > /etc/mongod.conf && \
|
||||
mkdir -p ${HOME}/data && \
|
||||
# Set owner 'mongodb:0' and 'g+rw(x)' permission - to avoid problems running container with arbitrary UID
|
||||
/usr/libexec/fix-permissions /etc/mongod.conf ${CONTAINER_SCRIPTS_PATH}/mongodb.conf.template \
|
||||
${HOME}
|
||||
|
||||
VOLUME ["/var/lib/mongodb/data"]
|
||||
|
||||
USER 184
|
||||
|
||||
15
Makefile
Normal file
15
Makefile
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
IMAGE_NAME = mongodb
|
||||
|
||||
MODULEMDURL=file://mongodb.yaml
|
||||
|
||||
default: run
|
||||
|
||||
build:
|
||||
docker build --tag=$(IMAGE_NAME) .
|
||||
|
||||
run: build
|
||||
docker run -d $(IMAGE_NAME)
|
||||
|
||||
test: build
|
||||
cd tests; MODULE=docker MODULEMD=$(MODULEMDURL) URL="docker=$(IMAGE_NAME)" make all
|
||||
cd tests; MODULE=rpm MODULEMD=$(MODULEMDURL) URL="docker=$(IMAGE_NAME)" make all
|
||||
92
files/usr/bin/cgroup-limits
Executable file
92
files/usr/bin/cgroup-limits
Executable file
|
|
@ -0,0 +1,92 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
"""
|
||||
Script for parsing cgroup information
|
||||
|
||||
This script will read some limits from the cgroup system and parse
|
||||
them, printing out "VARIABLE=VALUE" on each line for every limit that is
|
||||
successfully read. Output of this script can be directly fed into
|
||||
bash's export command. Recommended usage from a bash script:
|
||||
|
||||
set -o errexit
|
||||
export_vars=$(cgroup-limits) ; export $export_vars
|
||||
|
||||
Variables currently supported:
|
||||
MAX_MEMORY_LIMIT_IN_BYTES
|
||||
Maximum possible limit MEMORY_LIMIT_IN_BYTES can have. This is
|
||||
currently constant value of 9223372036854775807.
|
||||
MEMORY_LIMIT_IN_BYTES
|
||||
Maximum amount of user memory in bytes. If this value is set
|
||||
to the same value as MAX_MEMORY_LIMIT_IN_BYTES, it means that
|
||||
there is no limit set. The value is taken from
|
||||
/sys/fs/cgroup/memory/memory.limit_in_bytes
|
||||
NUMBER_OF_CORES
|
||||
Number of detected CPU cores that can be used. This value is
|
||||
calculated from /sys/fs/cgroup/cpuset/cpuset.cpus
|
||||
NO_MEMORY_LIMIT
|
||||
Set to "true" if MEMORY_LIMIT_IN_BYTES is so high that the caller
|
||||
can act as if no memory limit was set. Undefined otherwise.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
|
||||
|
||||
def _read_file(path):
|
||||
try:
|
||||
with open(path, 'r') as f:
|
||||
return f.read().strip()
|
||||
except IOError:
|
||||
return None
|
||||
|
||||
|
||||
def get_memory_limit():
|
||||
"""
|
||||
Read memory limit, in bytes.
|
||||
"""
|
||||
|
||||
limit = _read_file('/sys/fs/cgroup/memory/memory.limit_in_bytes')
|
||||
if limit is None or not limit.isdigit():
|
||||
print("Warning: Can't detect memory limit from cgroups",
|
||||
file=sys.stderr)
|
||||
return None
|
||||
return int(limit)
|
||||
|
||||
|
||||
def get_number_of_cores():
|
||||
"""
|
||||
Read number of CPU cores.
|
||||
"""
|
||||
|
||||
core_count = 0
|
||||
|
||||
line = _read_file('/sys/fs/cgroup/cpuset/cpuset.cpus')
|
||||
if line is None:
|
||||
print("Warning: Can't detect number of CPU cores from cgroups",
|
||||
file=sys.stderr)
|
||||
return None
|
||||
|
||||
for group in line.split(','):
|
||||
core_ids = list(map(int, group.split('-')))
|
||||
if len(core_ids) == 2:
|
||||
core_count += core_ids[1] - core_ids[0] + 1
|
||||
else:
|
||||
core_count += 1
|
||||
|
||||
return core_count
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
env_vars = {
|
||||
"MAX_MEMORY_LIMIT_IN_BYTES": 9223372036854775807,
|
||||
"MEMORY_LIMIT_IN_BYTES": get_memory_limit(),
|
||||
"NUMBER_OF_CORES": get_number_of_cores()
|
||||
}
|
||||
|
||||
env_vars = {k: v for k, v in env_vars.items() if v is not None}
|
||||
|
||||
if env_vars.get("MEMORY_LIMIT_IN_BYTES", 0) >= 92233720368547:
|
||||
env_vars["NO_MEMORY_LIMIT"] = "true"
|
||||
|
||||
for key, value in env_vars.items():
|
||||
print("{0}={1}".format(key, value))
|
||||
2
files/usr/bin/container-entrypoint
Executable file
2
files/usr/bin/container-entrypoint
Executable file
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/bash
|
||||
exec "$@"
|
||||
57
files/usr/bin/run-mongod
Executable file
57
files/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
|
||||
55
files/usr/bin/run-mongod-pet
Executable file
55
files/usr/bin/run-mongod-pet
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
|
||||
55
files/usr/bin/run-mongod-replication
Executable file
55
files/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
files/usr/libexec/fix-permissions
Executable file
6
files/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
files/usr/share/container-scripts/mongodb/README.md
Normal file
90
files/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.
|
||||
|
||||
260
files/usr/share/container-scripts/mongodb/common.sh
Normal file
260
files/usr/share/container-scripts/mongodb/common.sh
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
# Data directory where MongoDB database files live. The data subdirectory is here
|
||||
# because mongodb.conf lives in /var/lib/mongodb/ and we don't want a volume to
|
||||
# override it.
|
||||
export MONGODB_DATADIR=/var/lib/mongodb/data
|
||||
export CONTAINER_PORT=27017
|
||||
# Configuration settings.
|
||||
export MONGODB_QUIET=${MONGODB_QUIET:-true}
|
||||
|
||||
MONGODB_CONFIG_PATH=/etc/mongod.conf
|
||||
MONGODB_KEYFILE_PATH="${HOME}/keyfile"
|
||||
|
||||
# Constants used for waiting
|
||||
readonly MAX_ATTEMPTS=60
|
||||
readonly SLEEP_TIME=1
|
||||
|
||||
# wait_for_mongo_up waits until the mongo server accepts incomming connections
|
||||
function wait_for_mongo_up() {
|
||||
_wait_for_mongo 1 "$@"
|
||||
}
|
||||
|
||||
# wait_for_mongo_down waits until the mongo server is down
|
||||
function wait_for_mongo_down() {
|
||||
_wait_for_mongo 0 "$@"
|
||||
}
|
||||
|
||||
# wait_for_mongo waits until the mongo server is up/down
|
||||
# $1 - 0 or 1 - to specify for what to wait (0 - down, 1 - up)
|
||||
# $2 - host where to connect (localhost by default)
|
||||
function _wait_for_mongo() {
|
||||
local operation=${1:-1}
|
||||
local message="up"
|
||||
if [[ ${operation} -eq 0 ]]; then
|
||||
message="down"
|
||||
fi
|
||||
|
||||
local mongo_cmd="mongo admin --host ${2:-localhost} "
|
||||
|
||||
local i
|
||||
for i in $(seq $MAX_ATTEMPTS); do
|
||||
echo "=> ${2:-} Waiting for MongoDB daemon ${message}"
|
||||
if ([[ ${operation} -eq 1 ]] && ${mongo_cmd} --eval "quit()" &>/dev/null) || ([[ ${operation} -eq 0 ]] && ! ${mongo_cmd} --eval "quit()" &>/dev/null); then
|
||||
echo "=> MongoDB daemon is ${message}"
|
||||
return 0
|
||||
fi
|
||||
sleep ${SLEEP_TIME}
|
||||
done
|
||||
echo "=> Giving up: MongoDB daemon is not ${message}!"
|
||||
return 1
|
||||
}
|
||||
|
||||
# endpoints returns list of IP addresses with other instances of MongoDB
|
||||
# To get list of endpoints, you need to have headless Service named 'mongodb'.
|
||||
# NOTE: This won't work with standalone Docker container.
|
||||
function endpoints() {
|
||||
service_name=${MONGODB_SERVICE_NAME:-mongodb}
|
||||
dig ${service_name} A +search +short 2>/dev/null
|
||||
}
|
||||
|
||||
# replset_addr return the address of the current replSet
|
||||
function replset_addr() {
|
||||
local current_endpoints
|
||||
current_endpoints="$(endpoints)"
|
||||
if [ -z "${current_endpoints}" ]; then
|
||||
info "Cannot get address of replica set: no nodes are listed in service!"
|
||||
info "CAUSE: DNS lookup for '${MONGODB_SERVICE_NAME:-mongodb}' returned no results."
|
||||
return 1
|
||||
fi
|
||||
echo "${MONGODB_REPLICA_NAME}/${current_endpoints//[[:space:]]/,}"
|
||||
}
|
||||
|
||||
# mongo_create_admin creates the MongoDB admin user with password: MONGODB_ADMIN_PASSWORD
|
||||
# $1 - login parameters for mongo (optional)
|
||||
# $2 - host where to connect (localhost by default)
|
||||
function mongo_create_admin() {
|
||||
if [[ -z "${MONGODB_ADMIN_PASSWORD:-}" ]]; then
|
||||
echo >&2 "=> MONGODB_ADMIN_PASSWORD is not set. Authentication can not be set up."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set admin password
|
||||
local js_command="db.createUser({user: 'admin', pwd: '${MONGODB_ADMIN_PASSWORD}', roles: ['dbAdminAnyDatabase', 'userAdminAnyDatabase' , 'readWriteAnyDatabase','clusterAdmin' ]});"
|
||||
if ! mongo admin ${1:-} --host ${2:-"localhost"} --eval "${js_command}"; then
|
||||
echo >&2 "=> Failed to create MongoDB admin user."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# mongo_create_user creates the MongoDB database user: MONGODB_USER,
|
||||
# with password: MONGDOB_PASSWORD, inside database: MONGODB_DATABASE
|
||||
# $1 - login parameters for mongo (optional)
|
||||
# $2 - host where to connect (localhost by default)
|
||||
function mongo_create_user() {
|
||||
# Ensure input variables exists
|
||||
if [[ -z "${MONGODB_USER:-}" ]]; then
|
||||
echo >&2 "=> MONGODB_USER is not set. Failed to create MongoDB user"
|
||||
exit 1
|
||||
fi
|
||||
if [[ -z "${MONGODB_PASSWORD:-}" ]]; then
|
||||
echo "=> MONGODB_PASSWORD is not set. Failed to create MongoDB user: ${MONGODB_USER}"
|
||||
exit >&2 1
|
||||
fi
|
||||
if [[ -z "${MONGODB_DATABASE:-}" ]]; then
|
||||
echo >&2 "=> MONGODB_DATABASE is not set. Failed to create MongoDB user: ${MONGODB_USER}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create database user
|
||||
local js_command="db.getSiblingDB('${MONGODB_DATABASE}').createUser({user: '${MONGODB_USER}', pwd: '${MONGODB_PASSWORD}', roles: [ 'readWrite' ]});"
|
||||
if ! mongo admin ${1:-} --host ${2:-"localhost"} --eval "${js_command}"; then
|
||||
echo >&2 "=> Failed to create MongoDB user: ${MONGODB_USER}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# mongo_reset_user sets the MongoDB MONGODB_USER's password to match MONGODB_PASSWORD
|
||||
function mongo_reset_user() {
|
||||
if [[ -n "${MONGODB_USER:-}" && -n "${MONGODB_PASSWORD:-}" && -n "${MONGODB_DATABASE:-}" ]]; then
|
||||
local js_command="db.changeUserPassword('${MONGODB_USER}', '${MONGODB_PASSWORD}')"
|
||||
if ! mongo ${MONGODB_DATABASE} --eval "${js_command}"; then
|
||||
echo >&2 "=> Failed to reset password of MongoDB user: ${MONGODB_USER}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# mongo_reset_admin sets the MongoDB admin password to match MONGODB_ADMIN_PASSWORD
|
||||
function mongo_reset_admin() {
|
||||
if [[ -n "${MONGODB_ADMIN_PASSWORD:-}" ]]; then
|
||||
local js_command="db.changeUserPassword('admin', '${MONGODB_ADMIN_PASSWORD}')"
|
||||
if ! mongo admin --eval "${js_command}"; then
|
||||
echo >&2 "=> Failed to reset password of MongoDB user: ${MONGODB_USER}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# setup_keyfile fixes the bug in mounting the Kubernetes 'Secret' volume that
|
||||
# mounts the secret files with 'too open' permissions.
|
||||
# add --keyFile argument to mongo_common_args
|
||||
function setup_keyfile() {
|
||||
# If user specify keyFile in config file do not use generated keyFile
|
||||
if grep -q "^\s*keyFile" ${MONGODB_CONFIG_PATH}; then
|
||||
exit 0
|
||||
fi
|
||||
if [ -z "${MONGODB_KEYFILE_VALUE-}" ]; then
|
||||
echo >&2 "ERROR: You have to provide the 'keyfile' value in MONGODB_KEYFILE_VALUE"
|
||||
exit 1
|
||||
fi
|
||||
local keyfile_dir
|
||||
keyfile_dir="$(dirname "$MONGODB_KEYFILE_PATH")"
|
||||
if [ ! -w "$keyfile_dir" ]; then
|
||||
echo >&2 "ERROR: Couldn't create ${MONGODB_KEYFILE_PATH}"
|
||||
echo >&2 "CAUSE: current user doesn't have permissions for writing to ${keyfile_dir} directory"
|
||||
echo >&2 "DETAILS: current user id = $(id -u), user groups: $(id -G)"
|
||||
echo >&2 "DETAILS: directory permissions: $(stat -c '%A owned by %u:%g' "${keyfile_dir}")"
|
||||
exit 1
|
||||
fi
|
||||
echo ${MONGODB_KEYFILE_VALUE} > ${MONGODB_KEYFILE_PATH}
|
||||
chmod 0600 ${MONGODB_KEYFILE_PATH}
|
||||
mongo_common_args+=" --keyFile ${MONGODB_KEYFILE_PATH}"
|
||||
}
|
||||
|
||||
# setup_default_datadir checks permissions of mounded directory into default
|
||||
# data directory MONGODB_DATADIR
|
||||
function setup_default_datadir() {
|
||||
if [ ! -w "$MONGODB_DATADIR" ]; then
|
||||
echo >&2 "ERROR: Couldn't write into ${MONGODB_DATADIR}"
|
||||
echo >&2 "CAUSE: current user doesn't have permissions for writing to ${MONGODB_DATADIR} directory"
|
||||
echo >&2 "DETAILS: current user id = $(id -u), user groups: $(id -G)"
|
||||
echo >&2 "DETAILS: directory permissions: $(stat -c '%A owned by %u:%g, SELinux: %C' "${MONGODB_DATADIR}")"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# setup_wiredtiger_cache checks amount of available RAM (it has to use cgroups in container)
|
||||
# and if there are any memory restrictions set storage.wiredTiger.engineConfig.cacheSizeGB
|
||||
# in MONGODB_CONFIG_PATH to upstream default size
|
||||
# it is intended to update mongodb.conf.template, with custom config file it might create conflict
|
||||
function setup_wiredtiger_cache() {
|
||||
local config_file
|
||||
config_file=${1:-$MONGODB_CONFIG_PATH}
|
||||
|
||||
declare $(cgroup-limits)
|
||||
if [[ ! -v MEMORY_LIMIT_IN_BYTES || "${NO_MEMORY_LIMIT:-}" == "true" ]]; then
|
||||
return 0;
|
||||
fi
|
||||
|
||||
cache_size=$(python -c "min=1; limit=int(($MEMORY_LIMIT_IN_BYTES / pow(2,30) - 1) * 0.6); print( min if limit < min else limit)")
|
||||
echo "storage.wiredTiger.engineConfig.cacheSizeGB: ${cache_size}" >> ${config_file}
|
||||
|
||||
info "wiredTiger cacheSizeGB set to ${cache_size}"
|
||||
}
|
||||
|
||||
# check_env_vars checks environmental variables
|
||||
# if variables to create non-admin user are provided, sets CREATE_USER=1
|
||||
# if REPLICATION variable is set, checks also replication variables
|
||||
function check_env_vars() {
|
||||
local readonly database_regex='^[^/\. "$]*$'
|
||||
|
||||
[[ -v MONGODB_ADMIN_PASSWORD ]] || usage "MONGODB_ADMIN_PASSWORD has to be set."
|
||||
|
||||
if [[ -v MONGODB_USER || -v MONGODB_PASSWORD || -v MONGODB_DATABASE ]]; then
|
||||
[[ -v MONGODB_USER && -v MONGODB_PASSWORD && -v MONGODB_DATABASE ]] || usage "You have to set all or none of variables: MONGODB_USER, MONGODB_PASSWORD, MONGODB_DATABASE"
|
||||
|
||||
[[ "${MONGODB_DATABASE}" =~ $database_regex ]] || usage "Database name must match regex: $database_regex"
|
||||
[ ${#MONGODB_DATABASE} -le 63 ] || usage "Database name too long (maximum 63 characters)"
|
||||
|
||||
export CREATE_USER=1
|
||||
fi
|
||||
|
||||
if [[ -v REPLICATION ]]; then
|
||||
[[ -v MONGODB_KEYFILE_VALUE && -v MONGODB_REPLICA_NAME ]] || usage "MONGODB_KEYFILE_VALUE and MONGODB_REPLICA_NAME have to be set"
|
||||
fi
|
||||
}
|
||||
|
||||
# usage prints info about required enviromental variables
|
||||
# if $1 is passed, prints error message containing $1
|
||||
# if REPLICATION variable is set, prints also info about replication variables
|
||||
function usage() {
|
||||
if [ $# == 1 ]; then
|
||||
echo >&2 "error: $1"
|
||||
fi
|
||||
|
||||
echo "
|
||||
You must specify the following environment variables:
|
||||
MONGODB_ADMIN_PASSWORD
|
||||
Optionally you can provide settings for a user with 'readWrite' role:
|
||||
(Note you MUST specify all three of these settings)
|
||||
MONGODB_USER
|
||||
MONGODB_PASSWORD
|
||||
MONGODB_DATABASE
|
||||
Optional settings:
|
||||
MONGODB_QUIET (default: true)"
|
||||
|
||||
if [[ -v REPLICATION ]]; then
|
||||
echo "
|
||||
For replication you must also specify the following environment variables:
|
||||
MONGODB_KEYFILE_VALUE
|
||||
MONGODB_REPLICA_NAME
|
||||
Optional settings:
|
||||
MONGODB_SERVICE_NAME (default: mongodb)
|
||||
"
|
||||
fi
|
||||
echo "
|
||||
For more information see /usr/share/container-scripts/mongodb/README.md
|
||||
within the container or visit https://github.com/sclorgk/mongodb-container/."
|
||||
|
||||
exit 1
|
||||
}
|
||||
|
||||
# info prints a message prefixed by date and time.
|
||||
function info() {
|
||||
printf "=> [%s] %s\n" "$(date +'%a %b %d %T')" "$*"
|
||||
}
|
||||
86
files/usr/share/container-scripts/mongodb/init-replset.sh
Executable file
86
files/usr/share/container-scripts/mongodb/init-replset.sh
Executable file
|
|
@ -0,0 +1,86 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
source "${CONTAINER_SCRIPTS_PATH}/common.sh"
|
||||
|
||||
# This is a full hostname that will be added to replica set
|
||||
# (for example, "replica-2.mongodb.myproject.svc.cluster.local")
|
||||
readonly MEMBER_HOST="$(hostname -f)"
|
||||
|
||||
# Initializes the replica set configuration.
|
||||
#
|
||||
# Arguments:
|
||||
# - $1: host address[:port]
|
||||
#
|
||||
# Uses the following global variables:
|
||||
# - MONGODB_REPLICA_NAME
|
||||
# - MONGODB_ADMIN_PASSWORD
|
||||
function initiate() {
|
||||
local host="$1"
|
||||
|
||||
local config="{_id: '${MONGODB_REPLICA_NAME}', members: [{_id: 0, host: '${host}'}]}"
|
||||
|
||||
info "Initiating MongoDB replica using: ${config}"
|
||||
mongo --eval "quit(rs.initiate(${config}).ok ? 0 : 1)" --quiet
|
||||
|
||||
info "Waiting for PRIMARY status ..."
|
||||
mongo --eval "while (!rs.isMaster().ismaster) { sleep(100); }" --quiet
|
||||
|
||||
info "Creating MongoDB users ..."
|
||||
mongo_create_admin
|
||||
[[ -v CREATE_USER ]] && mongo_create_user "-u admin -p ${MONGODB_ADMIN_PASSWORD}"
|
||||
|
||||
info "Successfully initialized replica set"
|
||||
}
|
||||
|
||||
# Adds a host to the replica set configuration.
|
||||
#
|
||||
# Arguments:
|
||||
# - $1: host address[:port]
|
||||
#
|
||||
# Global variables:
|
||||
# - MONGODB_REPLICA_NAME
|
||||
# - MONGODB_ADMIN_PASSWORD
|
||||
function add_member() {
|
||||
local host="$1"
|
||||
info "Adding ${host} to replica set ..."
|
||||
|
||||
if ! mongo admin -u admin -p "${MONGODB_ADMIN_PASSWORD}" --host "$(replset_addr)" --eval "while (!rs.add('${host}').ok) { sleep(100); }" --quiet; then
|
||||
info "ERROR: couldn't add host to replica set!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
info "Waiting for PRIMARY/SECONDARY status ..."
|
||||
mongo --eval "while (!rs.isMaster().ismaster && !rs.isMaster().secondary) { sleep(100); }" --quiet
|
||||
|
||||
info "Successfully joined replica set"
|
||||
}
|
||||
|
||||
info "Waiting for local MongoDB to accept connections ..."
|
||||
wait_for_mongo_up &>/dev/null
|
||||
|
||||
if [[ $(mongo --eval 'db.isMaster().setName' --quiet) == "${MONGODB_REPLICA_NAME}" ]]; then
|
||||
info "Replica set '${MONGODB_REPLICA_NAME}' already exists, skipping initialization"
|
||||
>/tmp/initialized
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# StatefulSet pods are named with a predictable name, following the pattern:
|
||||
# $(statefulset name)-$(zero-based index)
|
||||
# MEMBER_ID is computed by removing the prefix matching "*-", i.e.:
|
||||
# "mongodb-0" -> "0"
|
||||
# "mongodb-1" -> "1"
|
||||
# "mongodb-2" -> "2"
|
||||
readonly MEMBER_ID="${HOSTNAME##*-}"
|
||||
|
||||
# Initialize replica set only if we're the first member
|
||||
if [ "${MEMBER_ID}" = '0' ]; then
|
||||
initiate "${MEMBER_HOST}"
|
||||
else
|
||||
add_member "${MEMBER_HOST}"
|
||||
fi
|
||||
|
||||
>/tmp/initialized
|
||||
|
|
@ -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
files/usr/share/container-scripts/mongodb/scl_enable
Normal file
3
files/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
files/usr/share/container-scripts/mongodb/test-functions.sh
Normal file
61
files/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
help.md
Normal file
0
help.md
Normal file
Loading…
Add table
Add a link
Reference in a new issue