6.0.2-2-debian-10-r53 release
This commit is contained in:
parent
2812088f2a
commit
bbedd5361b
|
|
@ -1,33 +1,31 @@
|
|||
FROM docker.io/bitnami/minideb:buster
|
||||
LABEL maintainer "Bitnami <containers@bitnami.com>"
|
||||
|
||||
ENV PATH="/opt/bitnami/ruby/bin:/opt/bitnami/node/bin:/opt/bitnami/mysql/bin:/opt/bitnami/git/bin:/opt/bitnami/common/bin:/opt/bitnami/rails/bin:/opt/bitnami/nami/bin:$PATH"
|
||||
ENV OS_ARCH="amd64" \
|
||||
OS_FLAVOUR="debian-10" \
|
||||
OS_NAME="linux"
|
||||
|
||||
COPY prebuildfs /
|
||||
# Install required system packages and dependencies
|
||||
RUN install_packages build-essential ca-certificates curl default-libmysqlclient-dev dirmngr ghostscript gnupg imagemagick libaudit1 libbz2-1.0 libc6 libcap-ng0 libcom-err2 libcurl4 libffi6 libgcc1 libgcrypt20 libgmp-dev libgmp10 libgnutls30 libgpg-error0 libgssapi-krb5-2 libhogweed4 libidn2-0 libjemalloc2 libk5crypto3 libkeyutils1 libkrb5-3 libkrb5support0 libldap-2.4-2 liblzma5 libncurses6 libncursesw6 libnettle6 libnghttp2-14 libp11-kit0 libpam0g libpq5 libpsl5 libreadline-dev libreadline7 librtmp1 libsasl2-2 libsqlite3-0 libssh2-1 libssl1.1 libstdc++6 libtasn1-6 libtinfo6 libunistring2 libxml2-dev libxslt1-dev netcat-traditional procps sudo unzip zlib1g zlib1g-dev
|
||||
RUN /build/bitnami-user.sh
|
||||
RUN /build/install-nami.sh
|
||||
RUN bitnami-pkg install ruby-2.6.6-0 --checksum ecadce77e40822926c69f76cc11437954dd068793548c3f0a21007f9c4fafed3
|
||||
RUN bitnami-pkg install node-10.20.1-3 --checksum 1d2031e972d160623b392dee30f51b950b31afb39fc4ae8c4579de55d05db976
|
||||
RUN bitnami-pkg install mysql-client-10.3.22-1 --checksum e9fa94f574c87d15f0b6aba7cff1c06f70c0e69c1c442378c9961fc148fa68ef
|
||||
RUN bitnami-pkg install git-2.26.2-0 --checksum 7d970d7f29ec3ab0ef4c9c699c686ab1b4d95f8371be90cbce07c26b9f4386e7
|
||||
RUN bitnami-pkg install tini-0.19.0-0 --checksum 9a8ae20be31a518f042fcec359f2cf35bfdb4e2a56f2fa8ff9ef2ecaf45da80c
|
||||
RUN bitnami-pkg install rails-6.0.2-2-0 --checksum 41ccec09430919e973a2dc1f51b2cee430b02a55986c0e564667d6277d9dfb8d
|
||||
RUN bitnami-pkg install gosu-1.12.0-0 --checksum 582d501eeb6b338a24f417fededbf14295903d6be55c52d66c52e616c81bcd8c
|
||||
RUN install_packages build-essential ca-certificates curl ghostscript git gzip imagemagick libbz2-1.0 libc6 libcom-err2 libcurl4 libffi6 libgcc1 libgcrypt20 libgmp-dev libgmp10 libgnutls30 libgpg-error0 libgssapi-krb5-2 libhogweed4 libidn2-0 libk5crypto3 libkeyutils1 libkrb5-3 libkrb5support0 libldap-2.4-2 liblzma5 libmariadb3 libncurses6 libncursesw6 libnettle6 libnghttp2-14 libp11-kit0 libpq5 libpsl5 libreadline7 librtmp1 libsasl2-2 libsqlite3-0 libsqlite3-dev libssh2-1 libssl-dev libssl1.1 libstdc++6 libtasn1-6 libtinfo6 libunistring2 libxml2-dev libxslt1-dev netcat pkg-config procps sudo tar unzip wget zlib1g zlib1g-dev
|
||||
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "ruby" "2.6.6-0" --checksum ecadce77e40822926c69f76cc11437954dd068793548c3f0a21007f9c4fafed3
|
||||
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "node" "10.20.1-3" --checksum 1d2031e972d160623b392dee30f51b950b31afb39fc4ae8c4579de55d05db976
|
||||
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "git" "2.26.2-0" --checksum 7d970d7f29ec3ab0ef4c9c699c686ab1b4d95f8371be90cbce07c26b9f4386e7
|
||||
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "rails" "6.0.2-2-1" --checksum 1714b81cc06343fece1d3ca3272ad3fbc1f1cd571363d508f74fb9b793bde460
|
||||
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "gosu" "1.12.0-0" --checksum 582d501eeb6b338a24f417fededbf14295903d6be55c52d66c52e616c81bcd8c
|
||||
RUN apt-get update && apt-get upgrade -y && \
|
||||
rm -r /var/lib/apt/lists /var/cache/apt/archives
|
||||
RUN mkdir /app && chown bitnami:bitnami /app
|
||||
RUN /build/bitnami-user.sh
|
||||
|
||||
COPY rootfs /
|
||||
RUN /opt/bitnami/scripts/rails/postunpack.sh
|
||||
ENV BITNAMI_APP_NAME="rails" \
|
||||
BITNAMI_IMAGE_VERSION="6.0.2-2-debian-10-r52" \
|
||||
BUNDLE_BUILD__SASSC="--disable-march-tune-native" \
|
||||
RAILS_ENV="development"
|
||||
BITNAMI_IMAGE_VERSION="6.0.2-2-debian-10-r53" \
|
||||
PATH="/opt/bitnami/ruby/bin:/opt/bitnami/node/bin:/opt/bitnami/git/bin:/opt/bitnami/common/bin:$PATH"
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
WORKDIR /app
|
||||
USER bitnami
|
||||
ENTRYPOINT [ "/app-entrypoint.sh" ]
|
||||
ENTRYPOINT [ "/opt/bitnami/scripts/rails/entrypoint.sh" ]
|
||||
CMD [ "bundle", "exec", "rails", "server", "-b", "0.0.0.0", "-p", "3000" ]
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
version: '2'
|
||||
services:
|
||||
mariadb:
|
||||
image: 'bitnami/mariadb:10.3'
|
||||
image: 'docker.io/bitnami/mariadb:10.3-debian-10'
|
||||
environment:
|
||||
- ALLOW_EMPTY_PASSWORD=yes
|
||||
|
||||
myapp:
|
||||
tty: true # Enables debugging capabilities when attached to this container.
|
||||
image: bitnami/rails:6
|
||||
image: docker.io/bitnami/rails:6-debian-10
|
||||
environment:
|
||||
- DATABASE_HOST=mariadb
|
||||
- DATABASE_NAME=my_app_development
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
curl --silent -L https://nami-prod.s3.amazonaws.com/tools/nami/releases/nami-1.0.0-1-linux-x64.tar.gz > /tmp/nami-linux-x64.tar.gz
|
||||
echo "80488279b056d5e9c183fe34097c5f496715ab16a602afcc9f78d59f15139a16 /tmp/nami-linux-x64.tar.gz" | sha256sum --check
|
||||
mkdir -p /opt/bitnami/nami /opt/bitnami/licenses
|
||||
tar xzf /tmp/nami-linux-x64.tar.gz --strip 1 -C /opt/bitnami/nami && rm /tmp/nami-linux-x64.tar.gz
|
||||
curl --silent -L https://raw.githubusercontent.com/bitnami/nami/master/COPYING > /opt/bitnami/licenses/nami-1.0.0-1.txt
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
[[ ${BASH_DEBUG:-false} = true ]] && set -x
|
||||
|
||||
# Constants
|
||||
MODULE="$(basename "$0")"
|
||||
BITNAMI_PREFIX=/opt/bitnami
|
||||
|
||||
# Color Palette
|
||||
RESET='\033[0m'
|
||||
BOLD='\033[1m'
|
||||
|
||||
## Foreground
|
||||
BLACK='\033[38;5;0m'
|
||||
RED='\033[38;5;1m'
|
||||
GREEN='\033[38;5;2m'
|
||||
YELLOW='\033[38;5;3m'
|
||||
BLUE='\033[38;5;4m'
|
||||
MAGENTA='\033[38;5;5m'
|
||||
CYAN='\033[38;5;6m'
|
||||
WHITE='\033[38;5;7m'
|
||||
|
||||
## Background
|
||||
ON_BLACK='\033[48;5;0m'
|
||||
ON_RED='\033[48;5;1m'
|
||||
ON_GREEN='\033[48;5;2m'
|
||||
ON_YELLOW='\033[48;5;3m'
|
||||
ON_BLUE='\033[48;5;4m'
|
||||
ON_MAGENTA='\033[48;5;5m'
|
||||
ON_CYAN='\033[48;5;6m'
|
||||
ON_WHITE='\033[48;5;7m'
|
||||
|
||||
# Functions
|
||||
|
||||
########################
|
||||
# Print to STDERR
|
||||
# Arguments:
|
||||
# Message to print
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
stderr_print() {
|
||||
printf "%b\\n" "${*}" >&2
|
||||
}
|
||||
|
||||
########################
|
||||
# Log message
|
||||
# Arguments:
|
||||
# Message to log
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
log() {
|
||||
stderr_print "${NAMI_DEBUG:+${CYAN}${MODULE:-} ${MAGENTA}$(date "+%T.%2N ")}${RESET}${*}"
|
||||
}
|
||||
########################
|
||||
# Log an 'info' message
|
||||
# Arguments:
|
||||
# Message to log
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
info() {
|
||||
log "${GREEN}INFO ${RESET} ==> ${*}"
|
||||
}
|
||||
########################
|
||||
# Log message
|
||||
# Arguments:
|
||||
# Message to log
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
warn() {
|
||||
log "${YELLOW}WARN ${RESET} ==> ${*}"
|
||||
}
|
||||
########################
|
||||
# Log an 'error' message
|
||||
# Arguments:
|
||||
# Message to log
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
error() {
|
||||
log "${RED}ERROR${RESET} ==> ${*}"
|
||||
}
|
||||
########################
|
||||
# Print the welcome page
|
||||
# Globals:
|
||||
# DISABLE_WELCOME_MESSAGE
|
||||
# BITNAMI_APP_NAME
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
print_welcome_page() {
|
||||
if [[ -z "${DISABLE_WELCOME_MESSAGE:-}" ]]; then
|
||||
if [[ -n "$BITNAMI_APP_NAME" ]]; then
|
||||
print_image_welcome_page
|
||||
fi
|
||||
fi
|
||||
}
|
||||
########################
|
||||
# Print the welcome page for a Bitnami Docker image
|
||||
# Globals:
|
||||
# BITNAMI_APP_NAME
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
print_image_welcome_page() {
|
||||
local github_url="https://github.com/bitnami/bitnami-docker-${BITNAMI_APP_NAME}"
|
||||
|
||||
log ""
|
||||
log "${BOLD}Welcome to the Bitnami ${BITNAMI_APP_NAME} container${RESET}"
|
||||
log "Subscribe to project updates by watching ${BOLD}${github_url}${RESET}"
|
||||
log "Submit issues and feature requests at ${BOLD}${github_url}/issues${RESET}"
|
||||
log ""
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
. /opt/bitnami/base/functions
|
||||
|
||||
########################
|
||||
# Helper function to initialize a single nami module
|
||||
# Arguments:
|
||||
# Module to initialize
|
||||
# Returns:
|
||||
# None
|
||||
# Description:
|
||||
# Initialize an unpacked nami module with the `nami initialize` command.
|
||||
# Command arguments can be specified as function argumnts after the module name.
|
||||
# `--log-level trace` flag is added to the command if `NAMI_DEBUG` env variable exists.
|
||||
# The log level can be overriden using the `NAMI_LOG_LEVEL` env variable.
|
||||
#########################
|
||||
nami_initialize_one() {
|
||||
local module="${1:?module not specified}"
|
||||
if nami inspect $module | grep -q '"lifecycle": "unpacked"'; then
|
||||
local inputs=
|
||||
if [[ -f "/${module}-inputs.json" ]]; then
|
||||
inputs="--inputs-file=/${module}-inputs.json"
|
||||
fi
|
||||
nami ${NAMI_DEBUG:+--log-level ${NAMI_LOG_LEVEL:-trace}} initialize $module $inputs "${@:2}"
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Helper function to initialize one or more nami modules
|
||||
# Arguments:
|
||||
# Module to initialize
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
nami_initialize() {
|
||||
local module="${1:?module not specified}"
|
||||
for module in "${@}"; do
|
||||
nami_initialize_one $module
|
||||
done
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Bitnami custom library
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
|
||||
# Load Generic Libraries
|
||||
. /opt/bitnami/scripts/liblog.sh
|
||||
|
||||
# Constants
|
||||
BOLD='\033[1m'
|
||||
|
||||
# Functions
|
||||
|
||||
########################
|
||||
# Print the welcome page
|
||||
# Globals:
|
||||
# DISABLE_WELCOME_MESSAGE
|
||||
# BITNAMI_APP_NAME
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
print_welcome_page() {
|
||||
if [[ -z "${DISABLE_WELCOME_MESSAGE:-}" ]]; then
|
||||
if [[ -n "$BITNAMI_APP_NAME" ]]; then
|
||||
print_image_welcome_page
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Print the welcome page for a Bitnami Docker image
|
||||
# Globals:
|
||||
# BITNAMI_APP_NAME
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
print_image_welcome_page() {
|
||||
local github_url="https://github.com/bitnami/bitnami-docker-${BITNAMI_APP_NAME}"
|
||||
|
||||
log ""
|
||||
log "${BOLD}Welcome to the Bitnami ${BITNAMI_APP_NAME} container${RESET}"
|
||||
log "Subscribe to project updates by watching ${BOLD}${github_url}${RESET}"
|
||||
log "Submit issues and feature requests at ${BOLD}${github_url}/issues${RESET}"
|
||||
log ""
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Library for managing Bitnami components
|
||||
|
||||
# Constants
|
||||
CACHE_ROOT="/tmp/bitnami/pkg/cache"
|
||||
DOWNLOAD_URL="https://downloads.bitnami.com/files/stacksmith"
|
||||
|
||||
# Functions
|
||||
|
||||
########################
|
||||
# Download and unpack a Bitnami package
|
||||
# Globals:
|
||||
# OS_NAME
|
||||
# OS_ARCH
|
||||
# OS_FLAVOUR
|
||||
# Arguments:
|
||||
# $1 - component's name
|
||||
# $2 - component's version
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
component_unpack() {
|
||||
local name="${1:?name is required}"
|
||||
local version="${2:?version is required}"
|
||||
local base_name="${name}-${version}-${OS_NAME}-${OS_ARCH}-${OS_FLAVOUR}"
|
||||
local package_sha256=""
|
||||
|
||||
# Validate arguments
|
||||
shift 2
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
-c|--checksum)
|
||||
shift
|
||||
package_sha256="${1:?missing package checksum}"
|
||||
;;
|
||||
*)
|
||||
echo "Invalid command line flag $1" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
echo "Downloading $base_name package"
|
||||
if [ -f "${CACHE_ROOT}/${base_name}.tar.gz" ]; then
|
||||
echo "${CACHE_ROOT}/${base_name}.tar.gz already exists, skipping download."
|
||||
cp "${CACHE_ROOT}/${base_name}.tar.gz" .
|
||||
rm "${CACHE_ROOT}/${base_name}.tar.gz"
|
||||
if [ -f "${CACHE_ROOT}/${base_name}.tar.gz.sha256" ]; then
|
||||
echo "Using the local sha256 from ${CACHE_ROOT}/${base_name}.tar.gz.sha256"
|
||||
package_sha256="$(< "${CACHE_ROOT}/${base_name}.tar.gz.sha256")"
|
||||
rm "${CACHE_ROOT}/${base_name}.tar.gz.sha256"
|
||||
fi
|
||||
else
|
||||
curl --remote-name --silent "${DOWNLOAD_URL}/${base_name}.tar.gz"
|
||||
fi
|
||||
if [ -n "$package_sha256" ]; then
|
||||
echo "Verifying package integrity"
|
||||
echo "$package_sha256 ${base_name}.tar.gz" | sha256sum --check -
|
||||
fi
|
||||
tar --directory /opt/bitnami --extract --gunzip --file "${base_name}.tar.gz" --no-same-owner --strip-components=2 "${base_name}/files/"
|
||||
rm "${base_name}.tar.gz"
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Library for managing files
|
||||
|
||||
# Functions
|
||||
|
||||
########################
|
||||
# Replace a regex in a file
|
||||
# Arguments:
|
||||
# $1 - filename
|
||||
# $2 - match regex
|
||||
# $3 - substitute regex
|
||||
# $4 - use POSIX regex. Default: true
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
replace_in_file() {
|
||||
local filename="${1:?filename is required}"
|
||||
local match_regex="${2:?match regex is required}"
|
||||
local substitute_regex="${3:?substitute regex is required}"
|
||||
local posix_regex=${4:-true}
|
||||
|
||||
local result
|
||||
|
||||
# We should avoid using 'sed in-place' substitutions
|
||||
# 1) They are not compatible with files mounted from ConfigMap(s)
|
||||
# 2) We found incompatibility issues with Debian10 and "in-place" substitutions
|
||||
if [[ $posix_regex = true ]]; then
|
||||
result="$(sed -E "s@$match_regex@$substitute_regex@g" "$filename")"
|
||||
else
|
||||
result="$(sed "s@$match_regex@$substitute_regex@g" "$filename")"
|
||||
fi
|
||||
echo "$result" > "$filename"
|
||||
}
|
||||
|
||||
########################
|
||||
# Remove a line in a file based on a regex
|
||||
# Arguments:
|
||||
# $1 - filename
|
||||
# $2 - match regex
|
||||
# $3 - use POSIX regex. Default: true
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
remove_in_file() {
|
||||
local filename="${1:?filename is required}"
|
||||
local match_regex="${2:?match regex is required}"
|
||||
local posix_regex=${3:-true}
|
||||
local result
|
||||
|
||||
# We should avoid using 'sed in-place' substitutions
|
||||
# 1) They are not compatible with files mounted from ConfigMap(s)
|
||||
# 2) We found incompatibility issues with Debian10 and "in-place" substitutions
|
||||
if [[ $posix_regex = true ]]; then
|
||||
result="$(sed -E "/$match_regex/d" "$filename")"
|
||||
else
|
||||
result="$(sed "/$match_regex/d" "$filename")"
|
||||
fi
|
||||
echo "$result" > "$filename"
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Library for file system actions
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
|
||||
# Load Generic Libraries
|
||||
. /opt/bitnami/scripts/liblog.sh
|
||||
|
||||
# Functions
|
||||
|
||||
########################
|
||||
# Ensure a file/directory is owned (user and group) but the given user
|
||||
# Arguments:
|
||||
# $1 - filepath
|
||||
# $2 - owner
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
owned_by() {
|
||||
local path="${1:?path is missing}"
|
||||
local owner="${2:?owner is missing}"
|
||||
|
||||
chown "$owner":"$owner" "$path"
|
||||
}
|
||||
|
||||
########################
|
||||
# Ensure a directory exists and, optionally, is owned by the given user
|
||||
# Arguments:
|
||||
# $1 - directory
|
||||
# $2 - owner
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
ensure_dir_exists() {
|
||||
local dir="${1:?directory is missing}"
|
||||
local owner="${2:-}"
|
||||
|
||||
mkdir -p "${dir}"
|
||||
if [[ -n $owner ]]; then
|
||||
owned_by "$dir" "$owner"
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Checks whether a directory is empty or not
|
||||
# Arguments:
|
||||
# $1 - directory
|
||||
# Returns:
|
||||
# Boolean
|
||||
#########################
|
||||
is_dir_empty() {
|
||||
local dir="${1:?missing directory}"
|
||||
|
||||
if [[ ! -e "$dir" ]] || [[ -z "$(ls -A "$dir")" ]]; then
|
||||
true
|
||||
else
|
||||
false
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Configure permisions and ownership recursively
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# $1 - paths (as a string).
|
||||
# Flags:
|
||||
# -f|--file-mode - mode for directories.
|
||||
# -d|--dir-mode - mode for files.
|
||||
# -u|--user - user
|
||||
# -g|--group - group
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
configure_permissions_ownership() {
|
||||
local -r paths="${1:?paths is missing}"
|
||||
local dir_mode=""
|
||||
local file_mode=""
|
||||
local user=""
|
||||
local group=""
|
||||
|
||||
# Validate arguments
|
||||
shift 1
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
-f|--file-mode)
|
||||
shift
|
||||
file_mode="${1:?missing mode for files}"
|
||||
;;
|
||||
-d|--dir-mode)
|
||||
shift
|
||||
dir_mode="${1:?missing mode for directories}"
|
||||
;;
|
||||
-u|--user)
|
||||
shift
|
||||
user="${1:?missing user}"
|
||||
;;
|
||||
-g|--group)
|
||||
shift
|
||||
group="${1:?missing group}"
|
||||
;;
|
||||
*)
|
||||
echo "Invalid command line flag $1" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
read -r -a filepaths <<< "$paths"
|
||||
for p in "${filepaths[@]}"; do
|
||||
if [[ -e "$p" ]]; then
|
||||
if [[ -n $dir_mode ]]; then
|
||||
find -L "$p" -type d -exec chmod "$dir_mode" {} \;
|
||||
fi
|
||||
if [[ -n $file_mode ]]; then
|
||||
find -L "$p" -type f -exec chmod "$file_mode" {} \;
|
||||
fi
|
||||
if [[ -n $user ]] && [[ -n $group ]]; then
|
||||
chown -LR "$user":"$group" "$p"
|
||||
elif [[ -n $user ]] && [[ -z $group ]]; then
|
||||
chown -LR "$user" "$p"
|
||||
elif [[ -z $user ]] && [[ -n $group ]]; then
|
||||
chgrp -LR "$group" "$p"
|
||||
fi
|
||||
else
|
||||
stderr_print "$p does not exist"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Library for logging functions
|
||||
|
||||
# Constants
|
||||
RESET='\033[0m'
|
||||
RED='\033[38;5;1m'
|
||||
GREEN='\033[38;5;2m'
|
||||
YELLOW='\033[38;5;3m'
|
||||
MAGENTA='\033[38;5;5m'
|
||||
CYAN='\033[38;5;6m'
|
||||
|
||||
# Functions
|
||||
|
||||
########################
|
||||
# Print to STDERR
|
||||
# Arguments:
|
||||
# Message to print
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
stderr_print() {
|
||||
# 'is_boolean_yes' is defined in libvalidations.sh, but depends on this file so we cannot source it
|
||||
local -r bool="${BITNAMI_QUIET:-false}"
|
||||
# comparison is performed without regard to the case of alphabetic characters
|
||||
shopt -s nocasematch
|
||||
if ! [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then
|
||||
printf "%b\\n" "${*}" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Log message
|
||||
# Arguments:
|
||||
# Message to log
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
log() {
|
||||
stderr_print "${CYAN}${MODULE:-} ${MAGENTA}$(date "+%T.%2N ")${RESET}${*}"
|
||||
}
|
||||
########################
|
||||
# Log an 'info' message
|
||||
# Arguments:
|
||||
# Message to log
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
info() {
|
||||
log "${GREEN}INFO ${RESET} ==> ${*}"
|
||||
}
|
||||
########################
|
||||
# Log message
|
||||
# Arguments:
|
||||
# Message to log
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
warn() {
|
||||
log "${YELLOW}WARN ${RESET} ==> ${*}"
|
||||
}
|
||||
########################
|
||||
# Log an 'error' message
|
||||
# Arguments:
|
||||
# Message to log
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
error() {
|
||||
log "${RED}ERROR${RESET} ==> ${*}"
|
||||
}
|
||||
########################
|
||||
# Log a 'debug' message
|
||||
# Globals:
|
||||
# BITNAMI_DEBUG
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
debug() {
|
||||
# 'is_boolean_yes' is defined in libvalidations.sh, but depends on this file so we cannot source it
|
||||
local -r bool="${BITNAMI_DEBUG:-false}"
|
||||
# comparison is performed without regard to the case of alphabetic characters
|
||||
shopt -s nocasematch
|
||||
if [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then
|
||||
log "${MAGENTA}DEBUG${RESET} ==> ${*}"
|
||||
fi
|
||||
}
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Library for network functions
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
|
||||
# Load Generic Libraries
|
||||
. /opt/bitnami/scripts/liblog.sh
|
||||
|
||||
# Functions
|
||||
|
||||
########################
|
||||
# Resolve dns
|
||||
# Arguments:
|
||||
# $1 - Hostname to resolve
|
||||
# Returns:
|
||||
# IP
|
||||
#########################
|
||||
dns_lookup() {
|
||||
local host="${1:?host is missing}"
|
||||
getent ahosts "$host" | awk '/STREAM/ {print $1 }'
|
||||
}
|
||||
|
||||
#########################
|
||||
## Wait for a hostname and return the IP
|
||||
# Arguments:
|
||||
# $1 - hostname
|
||||
# $2 - number of retries
|
||||
# $3 - seconds to wait between retries
|
||||
# Returns:
|
||||
# - IP address that corresponds to the hostname
|
||||
#########################
|
||||
wait_for_dns_lookup() {
|
||||
local hostname="${1:?hostname is missing}"
|
||||
local retries="${2:-5}"
|
||||
local seconds="${3:-1}"
|
||||
check_host() {
|
||||
if [[ $(dns_lookup "$hostname") == "" ]]; then
|
||||
false
|
||||
else
|
||||
true
|
||||
fi
|
||||
}
|
||||
# Wait 10 minutes for the host to be ready
|
||||
retry_while "check_host ${hostname}" "$retries" "$seconds"
|
||||
dns_lookup "$hostname"
|
||||
}
|
||||
|
||||
########################
|
||||
# Get machine's IP
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# Machine IP
|
||||
#########################
|
||||
get_machine_ip() {
|
||||
dns_lookup "$(hostname)"
|
||||
}
|
||||
|
||||
########################
|
||||
# Check if the provided argument is a resolved hostname
|
||||
# Arguments:
|
||||
# $1 - Value to check
|
||||
# Returns:
|
||||
# Boolean
|
||||
#########################
|
||||
is_hostname_resolved() {
|
||||
local -r host="${1:?missing value}"
|
||||
if [[ -n "$(dns_lookup "$host")" ]]; then
|
||||
true
|
||||
else
|
||||
false
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Parse URL
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# $1 - uri - String
|
||||
# $2 - component to obtain. Valid options (scheme, authority, userinfo, host, port, path, query or fragment) - String
|
||||
# Returns:
|
||||
# String
|
||||
parse_uri() {
|
||||
local uri="${1:?uri is missing}"
|
||||
local component="${2:?component is missing}"
|
||||
|
||||
# Solution based on https://tools.ietf.org/html/rfc3986#appendix-B with
|
||||
# additional sub-expressions to split authority into userinfo, host and port
|
||||
# Credits to Patryk Obara (see https://stackoverflow.com/a/45977232/6694969)
|
||||
local -r URI_REGEX='^(([^:/?#]+):)?(//((([^@/?#]+)@)?([^:/?#]+)(:([0-9]+))?))?(/([^?#]*))?(\?([^#]*))?(#(.*))?'
|
||||
# || | ||| | | | | | | | | |
|
||||
# |2 scheme | ||6 userinfo 7 host | 9 port | 11 rpath | 13 query | 15 fragment
|
||||
# 1 scheme: | |5 userinfo@ 8 :... 10 path 12 ?... 14 #...
|
||||
# | 4 authority
|
||||
# 3 //...
|
||||
local index=0
|
||||
case "$component" in
|
||||
scheme)
|
||||
index=2
|
||||
;;
|
||||
authority)
|
||||
index=4
|
||||
;;
|
||||
userinfo)
|
||||
index=6
|
||||
;;
|
||||
host)
|
||||
index=7
|
||||
;;
|
||||
port)
|
||||
index=9
|
||||
;;
|
||||
path)
|
||||
index=10
|
||||
;;
|
||||
query)
|
||||
index=13
|
||||
;;
|
||||
fragment)
|
||||
index=14
|
||||
;;
|
||||
*)
|
||||
stderr_print "unrecognized component $component"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
[[ "$uri" =~ $URI_REGEX ]] && echo "${BASH_REMATCH[${index}]}"
|
||||
}
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Library for operating system actions
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
|
||||
# Load Generic Libraries
|
||||
. /opt/bitnami/scripts/liblog.sh
|
||||
|
||||
# Functions
|
||||
|
||||
########################
|
||||
# Check if an user exists in the system
|
||||
# Arguments:
|
||||
# $1 - user
|
||||
# Returns:
|
||||
# Boolean
|
||||
#########################
|
||||
user_exists() {
|
||||
local user="${1:?user is missing}"
|
||||
id "$user" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
########################
|
||||
# Check if a group exists in the system
|
||||
# Arguments:
|
||||
# $1 - group
|
||||
# Returns:
|
||||
# Boolean
|
||||
#########################
|
||||
group_exists() {
|
||||
local group="${1:?group is missing}"
|
||||
getent group "$group" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
########################
|
||||
# Create a group in the system if it does not exist already
|
||||
# Arguments:
|
||||
# $1 - group
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
ensure_group_exists() {
|
||||
local group="${1:?group is missing}"
|
||||
|
||||
if ! group_exists "$group"; then
|
||||
groupadd "$group" >/dev/null 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Create an user in the system if it does not exist already
|
||||
# Arguments:
|
||||
# $1 - user
|
||||
# $2 - group
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
ensure_user_exists() {
|
||||
local user="${1:?user is missing}"
|
||||
local group="${2:-}"
|
||||
|
||||
if ! user_exists "$user"; then
|
||||
useradd "$user" >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
if [[ -n "$group" ]]; then
|
||||
ensure_group_exists "$group"
|
||||
usermod -a -G "$group" "$user" >/dev/null 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Check if the script is currently running as root
|
||||
# Arguments:
|
||||
# $1 - user
|
||||
# $2 - group
|
||||
# Returns:
|
||||
# Boolean
|
||||
#########################
|
||||
am_i_root() {
|
||||
if [[ "$(id -u)" = "0" ]]; then
|
||||
true
|
||||
else
|
||||
false
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Get total memory available
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# Memory in bytes
|
||||
#########################
|
||||
get_total_memory() {
|
||||
echo $(($(grep MemTotal /proc/meminfo | awk '{print $2}') / 1024))
|
||||
}
|
||||
|
||||
########################
|
||||
# Get machine size depending on specified memory
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# $1 - memory size (optional)
|
||||
# Returns:
|
||||
# Detected instance size
|
||||
#########################
|
||||
get_machine_size() {
|
||||
local memory="${1:-}"
|
||||
if [[ -z "$memory" ]]; then
|
||||
debug "Memory was not specified, detecting available memory automatically"
|
||||
memory="$(get_total_memory)"
|
||||
fi
|
||||
sanitized_memory=$(convert_to_mb "$memory")
|
||||
if [[ "$sanitized_memory" -gt 26000 ]]; then
|
||||
echo 2xlarge
|
||||
elif [[ "$sanitized_memory" -gt 13000 ]]; then
|
||||
echo xlarge
|
||||
elif [[ "$sanitized_memory" -gt 6000 ]]; then
|
||||
echo large
|
||||
elif [[ "$sanitized_memory" -gt 3000 ]]; then
|
||||
echo medium
|
||||
elif [[ "$sanitized_memory" -gt 1500 ]]; then
|
||||
echo small
|
||||
else
|
||||
echo micro
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Get machine size depending on specified memory
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# $1 - memory size (optional)
|
||||
# Returns:
|
||||
# Detected instance size
|
||||
#########################
|
||||
get_supported_machine_sizes() {
|
||||
echo micro small medium large xlarge 2xlarge
|
||||
}
|
||||
|
||||
########################
|
||||
# Convert memory size from string to amount of megabytes (i.e. 2G -> 2048)
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# $1 - memory size
|
||||
# Returns:
|
||||
# Result of the conversion
|
||||
#########################
|
||||
convert_to_mb() {
|
||||
local amount="${1:-}"
|
||||
if [[ $amount =~ ^([0-9]+)(M|G) ]]; then
|
||||
size="${BASH_REMATCH[1]}"
|
||||
unit="${BASH_REMATCH[2]}"
|
||||
if [[ "$unit" = "G" ]]; then
|
||||
amount="$((size * 1024))"
|
||||
else
|
||||
amount="$size"
|
||||
fi
|
||||
fi
|
||||
echo "$amount"
|
||||
}
|
||||
|
||||
|
||||
#########################
|
||||
# Redirects output to /dev/null if debug mode is disabled
|
||||
# Globals:
|
||||
# BITNAMI_DEBUG
|
||||
# Arguments:
|
||||
# $@ - Command to execute
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
debug_execute() {
|
||||
if ${BITNAMI_DEBUG:-false}; then
|
||||
"$@"
|
||||
else
|
||||
"$@" >/dev/null 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Retries a command a given number of times
|
||||
# Arguments:
|
||||
# $1 - cmd (as a string)
|
||||
# $2 - max retries. Default: 12
|
||||
# $3 - sleep between retries (in seconds). Default: 5
|
||||
# Returns:
|
||||
# Boolean
|
||||
#########################
|
||||
retry_while() {
|
||||
local cmd="${1:?cmd is missing}"
|
||||
local retries="${2:-12}"
|
||||
local sleep_time="${3:-5}"
|
||||
local return_value=1
|
||||
|
||||
read -r -a command <<< "$cmd"
|
||||
for ((i = 1 ; i <= retries ; i+=1 )); do
|
||||
"${command[@]}" && return_value=0 && break
|
||||
sleep "$sleep_time"
|
||||
done
|
||||
return $return_value
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Library for managing services
|
||||
|
||||
# Functions
|
||||
|
||||
########################
|
||||
# Read the provided pid file and returns a PID
|
||||
# Arguments:
|
||||
# $1 - Pid file
|
||||
# Returns:
|
||||
# PID
|
||||
#########################
|
||||
get_pid_from_file() {
|
||||
local pid_file="${1:?pid file is missing}"
|
||||
|
||||
if [[ -f "$pid_file" ]]; then
|
||||
if [[ -n "$(< "$pid_file")" ]] && [[ "$(< "$pid_file")" -gt 0 ]]; then
|
||||
echo "$(< "$pid_file")"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Check if a provided PID corresponds to a running service
|
||||
# Arguments:
|
||||
# $1 - PID
|
||||
# Returns:
|
||||
# Boolean
|
||||
#########################
|
||||
is_service_running() {
|
||||
local pid="${1:?pid is missing}"
|
||||
|
||||
kill -0 "$pid" 2>/dev/null
|
||||
}
|
||||
|
||||
########################
|
||||
# Stop a service by sending a termination signal to its pid
|
||||
# Arguments:
|
||||
# $1 - Pid file
|
||||
# $2 - Signal number (optional)
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
stop_service_using_pid() {
|
||||
local pid_file="${1:?pid file is missing}"
|
||||
local signal="${2:-}"
|
||||
local pid
|
||||
|
||||
pid="$(get_pid_from_file "$pid_file")"
|
||||
[[ -z "$pid" ]] || ! is_service_running "$pid" && return
|
||||
|
||||
if [[ -n "$signal" ]]; then
|
||||
kill "-${signal}" "$pid"
|
||||
else
|
||||
kill "$pid"
|
||||
fi
|
||||
|
||||
local counter=10
|
||||
while [[ "$counter" -ne 0 ]] && is_service_running "$pid"; do
|
||||
sleep 1
|
||||
counter=$((counter - 1))
|
||||
done
|
||||
}
|
||||
|
||||
########################
|
||||
# Generate a monit configuration file for a given service
|
||||
# Arguments:
|
||||
# $1 - Service name
|
||||
# $2 - Pid file
|
||||
# $3 - Start command
|
||||
# $4 - Stop command
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
generate_monit_conf() {
|
||||
local -r service_name="${1:?service name is missing}"
|
||||
local -r pid_file="${2:?pid file is missing}"
|
||||
local -r start_command="${3:?start command is missing}"
|
||||
local -r stop_command="${4:?stop command is missing}"
|
||||
local -r monit_conf_dir="/etc/monit/conf.d"
|
||||
|
||||
mkdir -p "$monit_conf_dir"
|
||||
cat >"${monit_conf_dir}/${service_name}.conf" <<EOF
|
||||
check process ${service_name}
|
||||
with pidfile "${pid_file}"
|
||||
start program = "${start_command}" with timeout 90 seconds
|
||||
stop program = "${stop_command}" with timeout 90 seconds
|
||||
EOF
|
||||
}
|
||||
|
||||
########################
|
||||
# Generate a logrotate configuration file
|
||||
# Arguments:
|
||||
# $1 - Log path
|
||||
# $2 - Period
|
||||
# $3 - Number of rotations to store
|
||||
# $4 - Extra options (Optional)
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
generate_logrotate_conf() {
|
||||
local -r service_name="${1:?service name is missing}"
|
||||
local -r log_path="${2:?log path is missing}"
|
||||
local -r period="${3:-weekly}"
|
||||
local -r rotations="${4:-150}"
|
||||
local -r extra_options="${5:-}"
|
||||
local -r logrotate_conf_dir="/etc/logrotate.d"
|
||||
|
||||
mkdir -p "$logrotate_conf_dir"
|
||||
cat >"${logrotate_conf_dir}/${service_name}" <<EOF
|
||||
${log_path} {
|
||||
${period}
|
||||
rotate ${rotations}
|
||||
dateext
|
||||
compress
|
||||
copytruncate
|
||||
missingok
|
||||
${extra_options}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
|
@ -0,0 +1,248 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Validation functions library
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
|
||||
# Load Generic Libraries
|
||||
. /opt/bitnami/scripts/liblog.sh
|
||||
|
||||
# Functions
|
||||
|
||||
########################
|
||||
# Check if the provided argument is an integer
|
||||
# Arguments:
|
||||
# $1 - Value to check
|
||||
# Returns:
|
||||
# Boolean
|
||||
#########################
|
||||
is_int() {
|
||||
local -r int="${1:?missing value}"
|
||||
if [[ "$int" =~ ^-?[0-9]+ ]]; then
|
||||
true
|
||||
else
|
||||
false
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Check if the provided argument is a positive integer
|
||||
# Arguments:
|
||||
# $1 - Value to check
|
||||
# Returns:
|
||||
# Boolean
|
||||
#########################
|
||||
is_positive_int() {
|
||||
local -r int="${1:?missing value}"
|
||||
if is_int "$int" && (( "${int}" >= 0 )); then
|
||||
true
|
||||
else
|
||||
false
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Check if the provided argument is a boolean or is the string 'yes/true'
|
||||
# Arguments:
|
||||
# $1 - Value to check
|
||||
# Returns:
|
||||
# Boolean
|
||||
#########################
|
||||
is_boolean_yes() {
|
||||
local -r bool="${1:-}"
|
||||
# comparison is performed without regard to the case of alphabetic characters
|
||||
shopt -s nocasematch
|
||||
if [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then
|
||||
true
|
||||
else
|
||||
false
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Check if the provided argument is a boolean yes/no value
|
||||
# Arguments:
|
||||
# $1 - Value to check
|
||||
# Returns:
|
||||
# Boolean
|
||||
#########################
|
||||
is_yes_no_value() {
|
||||
local -r bool="${1:-}"
|
||||
if [[ "$bool" =~ ^(yes|no)$ ]]; then
|
||||
true
|
||||
else
|
||||
false
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Check if the provided argument is a boolean true/false value
|
||||
# Arguments:
|
||||
# $1 - Value to check
|
||||
# Returns:
|
||||
# Boolean
|
||||
#########################
|
||||
is_true_false_value() {
|
||||
local -r bool="${1:-}"
|
||||
if [[ "$bool" =~ ^(true|false)$ ]]; then
|
||||
true
|
||||
else
|
||||
false
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Check if the provided argument is an empty string or not defined
|
||||
# Arguments:
|
||||
# $1 - Value to check
|
||||
# Returns:
|
||||
# Boolean
|
||||
#########################
|
||||
is_empty_value() {
|
||||
local -r val="${1:-}"
|
||||
if [[ -z "$val" ]]; then
|
||||
true
|
||||
else
|
||||
false
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Validate if the provided argument is a valid port
|
||||
# Arguments:
|
||||
# $1 - Port to validate
|
||||
# Returns:
|
||||
# Boolean and error message
|
||||
#########################
|
||||
validate_port() {
|
||||
local value
|
||||
local unprivileged=0
|
||||
|
||||
# Parse flags
|
||||
while [[ "$#" -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-unprivileged)
|
||||
unprivileged=1
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-*)
|
||||
stderr_print "unrecognized flag $1"
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [[ "$#" -gt 1 ]]; then
|
||||
echo "too many arguments provided"
|
||||
return 2
|
||||
elif [[ "$#" -eq 0 ]]; then
|
||||
stderr_print "missing port argument"
|
||||
return 1
|
||||
else
|
||||
value=$1
|
||||
fi
|
||||
|
||||
if [[ -z "$value" ]]; then
|
||||
echo "the value is empty"
|
||||
return 1
|
||||
else
|
||||
if ! is_int "$value"; then
|
||||
echo "value is not an integer"
|
||||
return 2
|
||||
elif [[ "$value" -lt 0 ]]; then
|
||||
echo "negative value provided"
|
||||
return 2
|
||||
elif [[ "$value" -gt 65535 ]]; then
|
||||
echo "requested port is greater than 65535"
|
||||
return 2
|
||||
elif [[ "$unprivileged" = 1 && "$value" -lt 1024 ]]; then
|
||||
echo "privileged port requested"
|
||||
return 3
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Validate if the provided argument is a valid IPv4 address
|
||||
# Arguments:
|
||||
# $1 - IP to validate
|
||||
# Returns:
|
||||
# Boolean
|
||||
#########################
|
||||
validate_ipv4() {
|
||||
local ip="${1:?ip is missing}"
|
||||
local stat=1
|
||||
|
||||
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
|
||||
read -r -a ip_array <<< "$(tr '.' ' ' <<< "$ip")"
|
||||
[[ ${ip_array[0]} -le 255 && ${ip_array[1]} -le 255 \
|
||||
&& ${ip_array[2]} -le 255 && ${ip_array[3]} -le 255 ]]
|
||||
stat=$?
|
||||
fi
|
||||
return $stat
|
||||
}
|
||||
|
||||
########################
|
||||
# Validate a string format
|
||||
# Arguments:
|
||||
# $1 - String to validate
|
||||
# Returns:
|
||||
# Boolean
|
||||
#########################
|
||||
validate_string() {
|
||||
local string
|
||||
local min_length=-1
|
||||
local max_length=-1
|
||||
|
||||
# Parse flags
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
-min-length)
|
||||
shift
|
||||
min_length=${1:-}
|
||||
;;
|
||||
-max-length)
|
||||
shift
|
||||
max_length=${1:-}
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-*)
|
||||
stderr_print "unrecognized flag $1"
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ "$#" -gt 1 ]; then
|
||||
stderr_print "too many arguments provided"
|
||||
return 2
|
||||
elif [ "$#" -eq 0 ]; then
|
||||
stderr_print "missing string"
|
||||
return 1
|
||||
else
|
||||
string=$1
|
||||
fi
|
||||
|
||||
if [[ "$min_length" -ge 0 ]] && [[ "${#string}" -lt "$min_length" ]]; then
|
||||
echo "string length is less than $min_length"
|
||||
return 1
|
||||
fi
|
||||
if [[ "$max_length" -ge 0 ]] && [[ "${#string}" -gt "$max_length" ]]; then
|
||||
echo "string length is great than $max_length"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Library for managing versions strings
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
|
||||
# Load Generic Libraries
|
||||
. /opt/bitnami/scripts/liblog.sh
|
||||
|
||||
# Functions
|
||||
########################
|
||||
# Gets semantic version
|
||||
# Arguments:
|
||||
# $1 - version: string to extract major.minor.patch
|
||||
# $2 - section: 1 to extract major, 2 to extract minor, 3 to extract patch
|
||||
# Returns:
|
||||
# array with the major, minor and release
|
||||
#########################
|
||||
get_sematic_version () {
|
||||
local version="${1:?version is required}"
|
||||
local section="${2:?section is required}"
|
||||
local -a version_sections
|
||||
|
||||
#Regex to parse versions: x.y.z
|
||||
local -r regex='([0-9]+)(\.([0-9]+)(\.([0-9]+))?)?'
|
||||
|
||||
if [[ "$version" =~ $regex ]]; then
|
||||
local i=1
|
||||
local j=1
|
||||
local n=${#BASH_REMATCH[*]}
|
||||
|
||||
while [[ $i -lt $n ]]; do
|
||||
if [[ -n "${BASH_REMATCH[$i]}" ]] && [[ "${BASH_REMATCH[$i]:0:1}" != '.' ]]; then
|
||||
version_sections[$j]=${BASH_REMATCH[$i]}
|
||||
((j++))
|
||||
fi
|
||||
((i++))
|
||||
done
|
||||
|
||||
local number_regex='^[0-9]+$'
|
||||
if [[ "$section" =~ $number_regex ]] && (( $section > 0 )) && (( $section <= 3 )); then
|
||||
echo "${version_sections[$section]}"
|
||||
return
|
||||
else
|
||||
stderr_print "Section allowed values are: 1, 2, and 3"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
|
@ -1,211 +0,0 @@
|
|||
#!/bin/bash -e
|
||||
. /opt/bitnami/base/functions
|
||||
|
||||
print_usage() {
|
||||
log "Usage: bitnami-pkg <COMMAND> <PACKAGE>-<VERSION> [OPTIONS] -- [ARGS]"
|
||||
log ""
|
||||
log "Download and install Bitnami packages"
|
||||
log ""
|
||||
log "Commands:"
|
||||
log " install Download and install a package."
|
||||
log " unpack Download and unpack a package."
|
||||
log ""
|
||||
log "Options:"
|
||||
log " -b, --bucket Package release bucket (default: stacksmith)."
|
||||
log " -c, --checksum SHA256 verification checksum."
|
||||
log " -h, --help Show this help message and exit."
|
||||
log ""
|
||||
log "If the package is already available in the /tmp/bitnami/pkg/cache/"
|
||||
log "directory, the download will be skipped. If there is a corresponding"
|
||||
log "file of the same name post-fixed with .sha256 in the directory,"
|
||||
log "that sha will be used instead of the --checksum option."
|
||||
log ""
|
||||
log "Examples:"
|
||||
log " - Unpack package"
|
||||
log " \$ bitnami-pkg unpack nginx-1.9.10-0"
|
||||
log ""
|
||||
log " - Verify and Install package"
|
||||
log " \$ bitnami-pkg install nginx-1.9.10-0 --checksum 15565d06b18c2e3710fc08e579ddb3d0e39aa663264a0f7404f0743cb4cdb58d"
|
||||
log ""
|
||||
log " - Install package with arguments"
|
||||
log " \$ bitnami-pkg install mariadb-10.1.11-0 -- --password bitnami"
|
||||
log ""
|
||||
log " - Install package from testing"
|
||||
log " \$ bitnami-pkg install mariadb-10.1.11-0 --bucket testing"
|
||||
log ""
|
||||
}
|
||||
|
||||
identify_distro() {
|
||||
distro="${IMAGE_OS:-unknown}"
|
||||
if [ "${distro}" == "unknown" -a -f /etc/os-release ]; then
|
||||
distro="$(grep "^ID=" /etc/os-release | cut -d'=' -f2 | cut -d'"' -f2)-$(grep "^VERSION_ID=" /etc/os-release | cut -d'=' -f2 | cut -d'"' -f2 | cut -d'.' -f1)"
|
||||
fi
|
||||
echo "$distro"
|
||||
}
|
||||
|
||||
identify_arch() {
|
||||
local arch=$(uname -m)
|
||||
|
||||
case "${arch}" in
|
||||
ppc64le)
|
||||
;; # no-op
|
||||
x86_64)
|
||||
case $(identify_distro) in
|
||||
debian-*)
|
||||
arch=amd64
|
||||
;;
|
||||
ol-*)
|
||||
arch=x86_64
|
||||
;;
|
||||
centos-*)
|
||||
arch=x86_64
|
||||
;;
|
||||
rhel-*)
|
||||
arch=x86_64
|
||||
;;
|
||||
photon-*)
|
||||
arch=x86_64
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
arch="unknown"
|
||||
;;
|
||||
esac
|
||||
echo $arch
|
||||
}
|
||||
|
||||
# break up command line for easy parsing and check legal options
|
||||
ARGS=$(getopt -o b:c:h -l "bucket:,checksum:,help" -n "bitnami-pkg" -- "$@")
|
||||
if [ $? -ne 0 ];
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
eval set -- "$ARGS";
|
||||
while true; do
|
||||
case "$1" in
|
||||
-b|--bucket)
|
||||
shift
|
||||
if [ -n "$1" ]; then
|
||||
RELEASE_BUCKET=$1
|
||||
shift
|
||||
fi
|
||||
;;
|
||||
-c|--checksum)
|
||||
shift
|
||||
if [ -n "$1" ]; then
|
||||
PACKAGE_SHA256=$1
|
||||
shift
|
||||
fi
|
||||
;;
|
||||
-h|--help)
|
||||
print_usage
|
||||
exit 0
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# weed out unrecognized commands
|
||||
case "$1" in
|
||||
install|unpack) ;;
|
||||
*)
|
||||
error "Unrecognized command: $1"
|
||||
print_usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# install/unpack command need to be supplied a package name
|
||||
if [ $# -lt 2 ]; then
|
||||
print_usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
INSTALL_ROOT=/tmp/bitnami/pkg/install
|
||||
CACHE_ROOT=/tmp/bitnami/pkg/cache
|
||||
|
||||
PACKAGE="$2-linux-$(identify_arch)-$(identify_distro)"
|
||||
PACKAGE_ARGS=${@:3}
|
||||
PACKAGE_NAME=$(echo $PACKAGE | sed 's/-[0-9].*//')
|
||||
RELEASE_BUCKET=${RELEASE_BUCKET:-stacksmith}
|
||||
|
||||
mkdir -p $INSTALL_ROOT
|
||||
cd $INSTALL_ROOT
|
||||
|
||||
info "Downloading $PACKAGE package"
|
||||
if [ -f $CACHE_ROOT/$PACKAGE.tar.gz ]; then
|
||||
info "$CACHE_ROOT/$PACKAGE.tar.gz already exists, skipping download."
|
||||
cp $CACHE_ROOT/$PACKAGE.tar.gz .
|
||||
if [ -f $CACHE_ROOT/$PACKAGE.tar.gz.sha256 ]; then
|
||||
info "Using the local sha256 from $CACHE_ROOT/$PACKAGE.tar.gz.sha256"
|
||||
PACKAGE_SHA256=$(cat $CACHE_ROOT/$PACKAGE.tar.gz.sha256)
|
||||
fi
|
||||
else
|
||||
# display cURL progress bar when a tty is attached
|
||||
if tty -s; then
|
||||
CURL_ARGS="-#"
|
||||
else
|
||||
CURL_ARGS="-sS"
|
||||
fi
|
||||
if ! curl $CURL_ARGS -LOf "https://downloads.bitnami.com/files/$RELEASE_BUCKET/$PACKAGE.tar.gz"; then
|
||||
warn "Package name '$PACKAGE' does not exist, will try '${PACKAGE%-$(identify_distro)}'..."
|
||||
if curl $CURL_ARGS -LOf "https://downloads.bitnami.com/files/$RELEASE_BUCKET/${PACKAGE%-$(identify_distro)}.tar.gz"; then
|
||||
PACKAGE="${PACKAGE%-$(identify_distro)}"
|
||||
else
|
||||
error "Could not find the requested package..."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! tar tzf $PACKAGE.tar.gz >/dev/null 2>&1; then
|
||||
error "Invalid or corrupt '$PACKAGE' package."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$PACKAGE_SHA256" ]; then
|
||||
info "Verifying package integrity"
|
||||
echo "$PACKAGE_SHA256 $PACKAGE.tar.gz" | sha256sum -c -
|
||||
fi
|
||||
|
||||
# If the tarball has too many files, it can trigger a bug
|
||||
# in overlayfs when using tar. Install bsdtar in the container image
|
||||
# to workaround it. As the overhead is too big (~40 MB), it is not added by
|
||||
# default. Source: https://github.com/coreos/bugs/issues/1095
|
||||
if which bsdtar >/dev/null 2>&1; then
|
||||
bsdtar -xf $PACKAGE.tar.gz
|
||||
else
|
||||
tar xzf $PACKAGE.tar.gz
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
install) info "Installing $PACKAGE" ;;
|
||||
unpack) info "Unpacking $PACKAGE" ;;
|
||||
esac
|
||||
|
||||
nami $1 $PACKAGE $PACKAGE_ARGS
|
||||
rm -rf $INSTALL_ROOT
|
||||
|
||||
if [ "$BITNAMI_PKG_EXTRA_DIRS" ]; then
|
||||
info "Creating extra directories"
|
||||
for i in ${BITNAMI_PKG_EXTRA_DIRS}; do
|
||||
mkdir -p $i
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$BITNAMI_PKG_CHMOD" ]; then
|
||||
DIRS="/.nami /bitnami $BITNAMI_PKG_EXTRA_DIRS"
|
||||
if ! [[ $PACKAGE_NAME =~ .*-client ]]; then
|
||||
mkdir -p /bitnami/$PACKAGE_NAME
|
||||
fi
|
||||
# We need to be in $HOME in order to nami inspect works
|
||||
cd $HOME
|
||||
DIRS+=" $(nami inspect $PACKAGE_NAME | grep -e '"installdir"' | cut -f4 -d\")"
|
||||
info "Fixing permissions: chmod $BITNAMI_PKG_CHMOD $DIRS"
|
||||
chmod $BITNAMI_PKG_CHMOD $DIRS
|
||||
fi
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
set -u
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
n=0
|
||||
max=2
|
||||
until [ $n -gt $max ]; do
|
||||
set +e
|
||||
(
|
||||
apt-get update -qq &&
|
||||
apt-get install -y --no-install-recommends "$@"
|
||||
)
|
||||
CODE=$?
|
||||
set -e
|
||||
if [ $CODE -eq 0 ]; then
|
||||
break
|
||||
fi
|
||||
if [ $n -eq $max ]; then
|
||||
exit $CODE
|
||||
fi
|
||||
echo "apt failed, retrying"
|
||||
n=$(($n + 1))
|
||||
done
|
||||
rm -r /var/lib/apt/lists /var/cache/apt/archives
|
||||
|
|
@ -1,143 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
# set -o xtrace
|
||||
|
||||
# Load libraries
|
||||
# shellcheck disable=SC1091
|
||||
. /opt/bitnami/base/functions
|
||||
|
||||
# Constants
|
||||
INIT_SEM=/tmp/initialized.sem
|
||||
|
||||
# Functions
|
||||
|
||||
########################
|
||||
# Replace a regex in a file
|
||||
# Arguments:
|
||||
# $1 - filename
|
||||
# $2 - match regex
|
||||
# $3 - substitute regex
|
||||
# $4 - regex modifier
|
||||
# Returns: none
|
||||
#########################
|
||||
replace_in_file() {
|
||||
local filename="${1:?filename is required}"
|
||||
local match_regex="${2:?match regex is required}"
|
||||
local substitute_regex="${3:?substitute regex is required}"
|
||||
local regex_modifier="${4:-}"
|
||||
local result
|
||||
|
||||
# We should avoid using 'sed in-place' substitutions
|
||||
# 1) They are not compatible with files mounted from ConfigMap(s)
|
||||
# 2) We found incompatibility issues with Debian10 and "in-place" substitutions
|
||||
result="$(sed "${regex_modifier}s@${match_regex}@${substitute_regex}@g" "$filename")"
|
||||
echo "$result" > "$filename"
|
||||
}
|
||||
|
||||
########################
|
||||
# Ensure gems are up to date
|
||||
# Arguments: none
|
||||
# Returns: boolean
|
||||
#########################
|
||||
gems_up_to_date() {
|
||||
bundle check 1> /dev/null
|
||||
}
|
||||
|
||||
########################
|
||||
# Wait for database to be ready
|
||||
# Globals:
|
||||
# DATABASE_HOST
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns: none
|
||||
#########################
|
||||
wait_for_db() {
|
||||
local db_host="${DATABASE_HOST:-mariadb}"
|
||||
local db_address
|
||||
db_address="$(getent hosts "$db_host" | awk '{ print $1 }')"
|
||||
counter=0
|
||||
log "Connecting to MariaDB at $db_address"
|
||||
while ! nc -z "$db_host" 3306; do
|
||||
counter=$((counter+1))
|
||||
if [ $counter == 30 ]; then
|
||||
log "Error: Couldn't connect to MariaDB."
|
||||
exit 1
|
||||
fi
|
||||
log "Trying to connect to mariadb at $db_address. Attempt $counter."
|
||||
sleep 5
|
||||
done
|
||||
}
|
||||
|
||||
print_welcome_page
|
||||
|
||||
if [[ "$1" = "bundle" ]] && [[ "$2" = "exec" ]]; then
|
||||
if [[ -f /app/config.ru ]]; then
|
||||
log "Rails project found. Skipping creation..."
|
||||
else
|
||||
log "Creating new Rails project..."
|
||||
rails new . --skip-bundle --database mysql
|
||||
# Add mini_racer
|
||||
replace_in_file "Gemfile" "# gem 'mini_racer'" "gem 'mini_racer'"
|
||||
# TODO: substitution using 'yq' once they support anchors
|
||||
# Related issue: https://github.com/mikefarah/yq/issues/178
|
||||
# E.g: yq w -i /app/config/database.yml default.host '<%= ENV.fetch("DATABASE_HOST") { mariadb } %>'
|
||||
# E.g: yq w -i /app/config/database.yml development.database '<%= ENV.fetch("DATABASE_NAME") { mariadb } %>'
|
||||
log "Setting default host to \`${DATABASE_HOST:-mariadb}\`..."
|
||||
replace_in_file "/app/config/database.yml" "host:.*$" "host: <%= ENV.fetch(\"DATABASE_HOST\", \"mariadb\") %>"
|
||||
log "Setting development database to \`${DATABASE_NAME:-my_app_development}\`..."
|
||||
replace_in_file "/app/config/database.yml" "database:.*$" "database: <%= ENV.fetch(\"DATABASE_NAME\", \"my_app_development\") %>" "1,/test:/ "
|
||||
fi
|
||||
|
||||
if ! gems_up_to_date; then
|
||||
log "Installing/Updating Rails dependencies (gems)..."
|
||||
bundle install
|
||||
log "Gems updated!!"
|
||||
fi
|
||||
|
||||
if [[ -z $SKIP_DB_WAIT ]]; then
|
||||
wait_for_db
|
||||
fi
|
||||
|
||||
if [[ -f $INIT_SEM ]]; then
|
||||
echo "#########################################################################"
|
||||
echo " "
|
||||
echo " App initialization skipped:"
|
||||
echo " Delete the file $INIT_SEM and restart the container to reinitialize"
|
||||
echo " You can alternatively run specific commands using docker-compose exec"
|
||||
echo " e.g docker-compose exec rails bundle exec rails db:migrate"
|
||||
echo " "
|
||||
echo "#########################################################################"
|
||||
else
|
||||
if [[ -z $SKIP_DB_SETUP ]]; then
|
||||
log "Configuring the database..."
|
||||
while ! bundle exec rails db:create; do
|
||||
counter=$((counter+1))
|
||||
if [ $counter == 30 ]; then
|
||||
log "Error: db:create failed"
|
||||
exit 1
|
||||
fi
|
||||
log "Trying to execute db:create. Attempt $counter."
|
||||
sleep 5
|
||||
done
|
||||
fi
|
||||
log "Initialization finished!!!"
|
||||
touch $INIT_SEM
|
||||
fi
|
||||
|
||||
if [[ -z $SKIP_DB_SETUP ]]; then
|
||||
log "Applying database migrations (db:migrate)..."
|
||||
while ! bundle exec rails db:migrate; do
|
||||
counter=$((counter+1))
|
||||
if [ $counter == 30 ]; then
|
||||
log "Error: db:migrate failed"
|
||||
exit 1
|
||||
fi
|
||||
log "Trying to execute db:migrate. Attempt $counter."
|
||||
sleep 5
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
exec tini -- "$@"
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Bitnami Rails library
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
|
||||
# Load Generic Libraries
|
||||
. /opt/bitnami/scripts/libfs.sh
|
||||
. /opt/bitnami/scripts/liblog.sh
|
||||
. /opt/bitnami/scripts/libos.sh
|
||||
. /opt/bitnami/scripts/libvalidations.sh
|
||||
. /opt/bitnami/scripts/libservice.sh
|
||||
|
||||
########################
|
||||
# Load global variables used on Rails configuration.
|
||||
# Globals:
|
||||
# RAILS_ENV
|
||||
# SKIP_DB_SETUP
|
||||
# SKIP_DB_WAIT
|
||||
# RETRY_ATTEMPTS
|
||||
# PATH
|
||||
# DATABASE_HOST
|
||||
# DATABASE_NAME
|
||||
# DATABASE_TYPE
|
||||
# DATABASE_PORT_NUMBER
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# Series of exports to be used as 'eval' arguments
|
||||
#########################
|
||||
rails_env() {
|
||||
cat <<"EOF"
|
||||
RAILS_ENV="${RAILS_ENV:-development}"
|
||||
SKIP_DB_SETUP="${SKIP_DB_SETUP:-no}"
|
||||
SKIP_DB_WAIT="${SKIP_DB_WAIT:-no}"
|
||||
RETRY_ATTEMPTS="${RETRY_ATTEMPTS:-30}"
|
||||
PATH="/opt/bitnami/ruby/bin:/opt/bitnami/mysql/bin:/opt/bitnami/node/bin:/opt/bitnami/git/bin:${PATH}"
|
||||
|
||||
# Database configuration
|
||||
DATABASE_HOST="${DATABASE_HOST:-mariadb}"
|
||||
DATABASE_TYPE="${DATABASE_TYPE:-mysql}"
|
||||
DATABASE_NAME="${DATABASE_NAME:-my_app_development}"
|
||||
DATABASE_PORT_NUMBER="${DATABASE_PORT_NUMBER:-3306}"
|
||||
EOF
|
||||
}
|
||||
|
||||
########################
|
||||
# Validate settings in DATABASE_* env vars
|
||||
# Globals:
|
||||
# SKIP_DB_SETUP
|
||||
# SKIP_DB_WAIT
|
||||
# RETRY_ATTEMPTS
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
rails_validate() {
|
||||
debug "Validating settings in DATABASE_* environment variables..."
|
||||
local error_code=0
|
||||
|
||||
# Auxiliary functions
|
||||
print_validation_error() {
|
||||
error "$1"
|
||||
error_code=1
|
||||
}
|
||||
|
||||
check_yes_no_value() {
|
||||
if ! is_yes_no_value "${!1}" && ! is_true_false_value "${!1}"; then
|
||||
print_validation_error "The allowed values for $1 are [yes, no]"
|
||||
fi
|
||||
}
|
||||
|
||||
check_positive_value() {
|
||||
if ! is_positive_int "${!1}"; then
|
||||
print_validation_error "The variable $1 must be positive integer"
|
||||
fi
|
||||
}
|
||||
|
||||
check_yes_no_value SKIP_DB_SETUP
|
||||
check_yes_no_value SKIP_DB_WAIT
|
||||
check_positive_value RETRY_ATTEMPTS
|
||||
|
||||
[[ "$error_code" -eq 0 ]] || exit "$error_code"
|
||||
}
|
||||
|
||||
########################
|
||||
# Ensure the Rails app is initialized
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
rails_initialize() {
|
||||
# Initialize Rails project
|
||||
if [[ -f "config.ru" ]]; then
|
||||
info "Rails project found, skipping creation"
|
||||
info "Installing dependencies"
|
||||
bundle install
|
||||
else
|
||||
info "Creating new Rails project"
|
||||
rails new "." --database "$DATABASE_TYPE"
|
||||
# Set up database configuration
|
||||
local database_path="$DATABASE_NAME"
|
||||
[[ "$DATABASE_TYPE" = "sqlite3" ]] && database_path="db/${DATABASE_NAME}.sqlite3"
|
||||
info "Configuring database host to ${DATABASE_HOST}"
|
||||
replace_in_file "config/database.yml" "host:.*$" "host: ${DATABASE_HOST}"
|
||||
info "Configuring database name to ${DATABASE_NAME}"
|
||||
replace_in_file "config/database.yml" "database:.*$" "database: ${database_path}" "1,/test:/ "
|
||||
fi
|
||||
|
||||
# Wait for database and initialize
|
||||
is_boolean_yes "$SKIP_DB_WAIT" || wait_for_db
|
||||
is_boolean_yes "$SKIP_DB_SETUP" || initialize_db
|
||||
}
|
||||
|
||||
########################
|
||||
# Replace a regex in a file
|
||||
# Arguments:
|
||||
# $1 - filename
|
||||
# $2 - match regex
|
||||
# $3 - substitute regex
|
||||
# $4 - regex modifier
|
||||
# Returns: none
|
||||
#########################
|
||||
replace_in_file() {
|
||||
local filename="${1:?filename is required}"
|
||||
local match_regex="${2:?match regex is required}"
|
||||
local substitute_regex="${3:?substitute regex is required}"
|
||||
local regex_modifier="${4:-}"
|
||||
local result
|
||||
|
||||
# We should avoid using 'sed in-place' substitutions
|
||||
# 1) They are not compatible with files mounted from ConfigMap(s)
|
||||
# 2) We found incompatibility issues with Debian10 and "in-place" substitutions
|
||||
result="$(sed "${regex_modifier}s@${match_regex}@${substitute_regex}@g" "$filename")"
|
||||
echo "$result" > "$filename"
|
||||
}
|
||||
|
||||
########################
|
||||
# Wait for database to be ready
|
||||
# Globals:
|
||||
# RETRY_ATTEMPTS
|
||||
# DATABASE_HOST
|
||||
# DATABASE_TYPE
|
||||
# DATABASE_PORT_NUMBER
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
wait_for_db() {
|
||||
[[ "$DATABASE_TYPE" = "sqlite3" ]] && return
|
||||
info "Connecting to the database at ${DATABASE_HOST} (type: ${DATABASE_TYPE})"
|
||||
if ! retry_while "nc -z ${DATABASE_HOST} ${DATABASE_PORT_NUMBER}" "$RETRY_ATTEMPTS"; then
|
||||
error "Failed to connect to the database at ${DATABASE_HOST}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Initialize database
|
||||
# Globals:
|
||||
# RETRY_ATTEMPTS
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
initialize_db() {
|
||||
# The db:prepare command performs db:create, db:migrate and db:seed only when needed
|
||||
# If the database already exists, only db:migrate is run
|
||||
info "Initializing database (db:prepare)"
|
||||
if ! retry_while "bundle exec rails db:prepare" "$RETRY_ATTEMPTS"; then
|
||||
error "Failed to create database"
|
||||
return 1
|
||||
fi
|
||||
info "Database was successfully initialized"
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#!/bin/bash
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
#set -o xtrace
|
||||
|
||||
# Load libraries
|
||||
. /opt/bitnami/scripts/librails.sh
|
||||
. /opt/bitnami/scripts/libbitnami.sh
|
||||
. /opt/bitnami/scripts/liblog.sh
|
||||
|
||||
# Load Rails environment
|
||||
eval "$(rails_env)"
|
||||
|
||||
print_welcome_page
|
||||
|
||||
if [[ "$*" == "bundle exec "* ]]; then
|
||||
info "** Running Rails setup **"
|
||||
/opt/bitnami/scripts/rails/setup.sh
|
||||
info "** Rails setup finished! **"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
exec "$@"
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#!/bin/bash
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
# set -o xtrace # Uncomment this line for debugging purpose
|
||||
|
||||
# Load libraries
|
||||
. /opt/bitnami/scripts/librails.sh
|
||||
. /opt/bitnami/scripts/libfs.sh
|
||||
. /opt/bitnami/scripts/liblog.sh
|
||||
|
||||
# Load Rails environment
|
||||
eval "$(rails_env)"
|
||||
|
||||
info "Granting non-root permissions to /app directory"
|
||||
mkdir -p /app
|
||||
chown -R bitnami:bitnami /app
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#!/bin/bash
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
# set -o xtrace # Uncomment this line for debugging purpose
|
||||
|
||||
# Load libraries
|
||||
. /opt/bitnami/scripts/librails.sh
|
||||
|
||||
# Load Rails environment
|
||||
eval "$(rails_env)"
|
||||
|
||||
# Ensure environment variables for the Rails app are valid
|
||||
rails_validate
|
||||
|
||||
# Ensure Rails app is initialized
|
||||
rails_initialize
|
||||
|
|
@ -28,7 +28,7 @@ $ docker-compose up
|
|||
Learn more about the Bitnami tagging policy and the difference between rolling tags and immutable tags [in our documentation page](https://docs.bitnami.com/tutorials/understand-rolling-tags-containers/).
|
||||
|
||||
|
||||
* [`6-debian-10`, `6.0.2-2-debian-10-r52`, `6`, `6.0.2-2`, `latest` (6/debian-10/Dockerfile)](https://github.com/bitnami/bitnami-docker-rails/blob/6.0.2-2-debian-10-r52/6/debian-10/Dockerfile)
|
||||
* [`6-debian-10`, `6.0.2-2-debian-10-r53`, `6`, `6.0.2-2`, `latest` (6/debian-10/Dockerfile)](https://github.com/bitnami/bitnami-docker-rails/blob/6.0.2-2-debian-10-r53/6/debian-10/Dockerfile)
|
||||
|
||||
Subscribe to project updates by watching the [bitnami/rails GitHub repo](https://github.com/bitnami/bitnami-docker-rails).
|
||||
|
||||
|
|
@ -184,6 +184,12 @@ $ docker-compose restart myapp
|
|||
|
||||
When the `myapp` service container is restarted, it will install all the missing gems before starting the WEBrick Rails application server.
|
||||
|
||||
# Notable Changes
|
||||
|
||||
## 6.0.2-2-debian-10-r52
|
||||
|
||||
- Decrease the size of the container. The configuration logic is now based on Bash scripts in the `rootfs/` folder.
|
||||
|
||||
# Contributing
|
||||
|
||||
We'd love for you to contribute to this container. You can request new features by creating an [issue](https://github.com/bitnami/bitnami-docker-rails/issues), or submit a [pull request](https://github.com/bitnami/bitnami-docker-rails/pulls) with your contribution.
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
version: '2'
|
||||
services:
|
||||
mariadb:
|
||||
image: 'bitnami/mariadb:10.3'
|
||||
image: 'docker.io/bitnami/mariadb:10.3-debian-10'
|
||||
environment:
|
||||
- ALLOW_EMPTY_PASSWORD=yes
|
||||
|
||||
myapp:
|
||||
tty: true # Enables debugging capabilities when attached to this container.
|
||||
image: bitnami/rails:6
|
||||
image: docker.io/bitnami/rails:6-debian-10
|
||||
environment:
|
||||
- DATABASE_HOST=mariadb
|
||||
- DATABASE_NAME=my_app_development
|
||||
|
|
|
|||
Loading…
Reference in New Issue