├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── stale.yml ├── 5.0 └── debian-10 │ ├── Dockerfile │ ├── docker-compose.yml │ ├── prebuildfs │ ├── opt │ │ └── bitnami │ │ │ ├── .bitnami_components.json │ │ │ ├── licenses │ │ │ └── licenses.txt │ │ │ └── scripts │ │ │ ├── libbitnami.sh │ │ │ ├── libcomponent.sh │ │ │ ├── libfile.sh │ │ │ ├── libfs.sh │ │ │ ├── libhook.sh │ │ │ ├── liblog.sh │ │ │ ├── libnet.sh │ │ │ ├── libos.sh │ │ │ ├── libpersistence.sh │ │ │ ├── libservice.sh │ │ │ ├── libvalidations.sh │ │ │ ├── libversion.sh │ │ │ └── libwebserver.sh │ └── usr │ │ └── sbin │ │ └── install_packages │ └── rootfs │ └── opt │ └── bitnami │ └── scripts │ ├── libredis.sh │ ├── librediscluster.sh │ ├── redis-cluster-env.sh │ └── redis-cluster │ ├── entrypoint.sh │ ├── postunpack.sh │ ├── run.sh │ └── setup.sh ├── 6.0 └── debian-10 │ ├── Dockerfile │ ├── docker-compose.yml │ ├── prebuildfs │ ├── opt │ │ └── bitnami │ │ │ ├── .bitnami_components.json │ │ │ ├── licenses │ │ │ └── licenses.txt │ │ │ └── scripts │ │ │ ├── libbitnami.sh │ │ │ ├── libcomponent.sh │ │ │ ├── libfile.sh │ │ │ ├── libfs.sh │ │ │ ├── libhook.sh │ │ │ ├── liblog.sh │ │ │ ├── libnet.sh │ │ │ ├── libos.sh │ │ │ ├── libpersistence.sh │ │ │ ├── libservice.sh │ │ │ ├── libvalidations.sh │ │ │ ├── libversion.sh │ │ │ └── libwebserver.sh │ └── usr │ │ └── sbin │ │ └── install_packages │ └── rootfs │ └── opt │ └── bitnami │ └── scripts │ ├── libredis.sh │ ├── librediscluster.sh │ ├── redis-cluster-env.sh │ └── redis-cluster │ ├── entrypoint.sh │ ├── postunpack.sh │ ├── run.sh │ └── setup.sh ├── 6.2 └── debian-10 │ ├── Dockerfile │ ├── docker-compose.yml │ ├── prebuildfs │ ├── opt │ │ └── bitnami │ │ │ ├── .bitnami_components.json │ │ │ ├── licenses │ │ │ └── licenses.txt │ │ │ └── scripts │ │ │ ├── libbitnami.sh │ │ │ ├── libcomponent.sh │ │ │ ├── libfile.sh │ │ │ ├── libfs.sh │ │ │ ├── libhook.sh │ │ │ ├── liblog.sh │ │ │ ├── libnet.sh │ │ │ ├── libos.sh │ │ │ ├── libpersistence.sh │ │ │ ├── libservice.sh │ │ │ ├── libvalidations.sh │ │ │ ├── libversion.sh │ │ │ └── libwebserver.sh │ └── usr │ │ └── sbin │ │ └── install_packages │ └── rootfs │ └── opt │ └── bitnami │ └── scripts │ ├── libredis.sh │ ├── librediscluster.sh │ ├── redis-cluster-env.sh │ └── redis-cluster │ ├── entrypoint.sh │ ├── postunpack.sh │ ├── run.sh │ └── setup.sh ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md └── docker-compose.yml /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 17 | 18 | **Description** 19 | 20 | 21 | 22 | **Steps to reproduce the issue:** 23 | 24 | 1. [First Step] 25 | 2. [Second Step] 26 | 3. [and so on...] 27 | 28 | **Describe the results you received:** 29 | 30 | 31 | 32 | **Describe the results you expected:** 33 | 34 | 35 | 36 | **Additional information you deem important (e.g. issue happens only occasionally):** 37 | 38 | 39 | 40 | **Version** 41 | 42 | - Output of `docker version`: 43 | 44 | ``` 45 | (paste your output here) 46 | ``` 47 | 48 | - Output of `docker info`: 49 | 50 | ``` 51 | (paste your output here) 52 | ``` 53 | 54 | - Output of `docker-compose version` (if applicable): 55 | 56 | ``` 57 | (paste your output here) 58 | ``` 59 | 60 | **Additional environment details (AWS, VirtualBox, Docker for MAC, physical, etc.):** 61 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 12 | 13 | **Description of the change** 14 | 15 | 16 | 17 | **Benefits** 18 | 19 | 20 | 21 | **Possible drawbacks** 22 | 23 | 24 | 25 | **Applicable issues** 26 | 27 | 28 | 29 | **Additional information** 30 | 31 | 33 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: 'Close stale issues and PRs' 2 | on: 3 | schedule: 4 | - cron: '0 1 * * *' 5 | 6 | jobs: 7 | stale: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/stale@v3 11 | with: 12 | repo-token: ${{ secrets.GITHUB_TOKEN }} 13 | stale-issue-message: 'This Issue has been automatically marked as "stale" because it has not had recent activity (for 15 days). It will be closed if no further activity occurs. Thanks for the feedback.' 14 | stale-pr-message: 'This Pull Request has been automatically marked as "stale" because it has not had recent activity (for 15 days). It will be closed if no further activity occurs. Thank you for your contribution.' 15 | close-issue-message: 'Due to the lack of activity in the last 5 days since it was marked as "stale", we proceed to close this Issue. Do not hesitate to reopen it later if necessary.' 16 | close-pr-message: 'Due to the lack of activity in the last 5 days since it was marked as "stale", we proceed to close this Pull Request. Do not hesitate to reopen it later if necessary.' 17 | days-before-stale: 15 18 | days-before-close: 5 19 | exempt-issue-labels: 'on-hold' 20 | exempt-pr-labels: 'on-hold' 21 | -------------------------------------------------------------------------------- /5.0/debian-10/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.io/bitnami/minideb:buster 2 | LABEL maintainer "Bitnami " 3 | 4 | ENV HOME="/" \ 5 | OS_ARCH="amd64" \ 6 | OS_FLAVOUR="debian-10" \ 7 | OS_NAME="linux" 8 | 9 | COPY prebuildfs / 10 | # Install required system packages and dependencies 11 | RUN install_packages acl ca-certificates curl gzip libc6 procps tar 12 | RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "redis" "5.0.14-3" --checksum fe8cf3f97927f5eaa014de917a02a511d8aaaed7c870c8bad6ee846c1d603a83 13 | RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "gosu" "1.14.0-0" --checksum 3e6fc37ca073b10a73a804d39c2f0c028947a1a596382a4f8ebe43dfbaa3a25e 14 | RUN chmod g+rwX /opt/bitnami 15 | 16 | COPY rootfs / 17 | RUN /opt/bitnami/scripts/redis-cluster/postunpack.sh 18 | ENV BITNAMI_APP_NAME="redis-cluster" \ 19 | BITNAMI_IMAGE_VERSION="5.0.14-debian-10-r17" \ 20 | PATH="/opt/bitnami/redis/bin:/opt/bitnami/common/bin:$PATH" 21 | 22 | EXPOSE 6379 23 | 24 | USER 1001 25 | ENTRYPOINT [ "/opt/bitnami/scripts/redis-cluster/entrypoint.sh" ] 26 | CMD [ "/opt/bitnami/scripts/redis-cluster/run.sh" ] 27 | -------------------------------------------------------------------------------- /5.0/debian-10/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | redis-node-0: 4 | image: docker.io/bitnami/redis-cluster:5.0 5 | volumes: 6 | - redis-cluster_data-0:/bitnami/redis/data 7 | environment: 8 | - 'REDIS_PASSWORD=bitnami' 9 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 10 | 11 | redis-node-1: 12 | image: docker.io/bitnami/redis-cluster:5.0 13 | volumes: 14 | - redis-cluster_data-1:/bitnami/redis/data 15 | environment: 16 | - 'REDIS_PASSWORD=bitnami' 17 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 18 | 19 | redis-node-2: 20 | image: docker.io/bitnami/redis-cluster:5.0 21 | volumes: 22 | - redis-cluster_data-2:/bitnami/redis/data 23 | environment: 24 | - 'REDIS_PASSWORD=bitnami' 25 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 26 | 27 | redis-node-3: 28 | image: docker.io/bitnami/redis-cluster:5.0 29 | volumes: 30 | - redis-cluster_data-3:/bitnami/redis/data 31 | environment: 32 | - 'REDIS_PASSWORD=bitnami' 33 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 34 | 35 | redis-node-4: 36 | image: docker.io/bitnami/redis-cluster:5.0 37 | volumes: 38 | - redis-cluster_data-4:/bitnami/redis/data 39 | environment: 40 | - 'REDIS_PASSWORD=bitnami' 41 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 42 | 43 | redis-node-5: 44 | image: docker.io/bitnami/redis-cluster:5.0 45 | volumes: 46 | - redis-cluster_data-5:/bitnami/redis/data 47 | depends_on: 48 | - redis-node-0 49 | - redis-node-1 50 | - redis-node-2 51 | - redis-node-3 52 | - redis-node-4 53 | environment: 54 | - 'REDIS_PASSWORD=bitnami' 55 | - 'REDISCLI_AUTH=bitnami' 56 | - 'REDIS_CLUSTER_REPLICAS=1' 57 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 58 | - 'REDIS_CLUSTER_CREATOR=yes' 59 | 60 | volumes: 61 | redis-cluster_data-0: 62 | driver: local 63 | redis-cluster_data-1: 64 | driver: local 65 | redis-cluster_data-2: 66 | driver: local 67 | redis-cluster_data-3: 68 | driver: local 69 | redis-cluster_data-4: 70 | driver: local 71 | redis-cluster_data-5: 72 | driver: local 73 | -------------------------------------------------------------------------------- /5.0/debian-10/prebuildfs/opt/bitnami/.bitnami_components.json: -------------------------------------------------------------------------------- 1 | { 2 | "gosu": { 3 | "arch": "amd64", 4 | "digest": "3e6fc37ca073b10a73a804d39c2f0c028947a1a596382a4f8ebe43dfbaa3a25e", 5 | "distro": "debian-10", 6 | "type": "NAMI", 7 | "version": "1.14.0-0" 8 | }, 9 | "redis": { 10 | "arch": "amd64", 11 | "digest": "fe8cf3f97927f5eaa014de917a02a511d8aaaed7c870c8bad6ee846c1d603a83", 12 | "distro": "debian-10", 13 | "type": "NAMI", 14 | "version": "5.0.14-3" 15 | } 16 | } -------------------------------------------------------------------------------- /5.0/debian-10/prebuildfs/opt/bitnami/licenses/licenses.txt: -------------------------------------------------------------------------------- 1 | Bitnami containers ship with software bundles. You can find the licenses under: 2 | /opt/bitnami/nami/COPYING 3 | /opt/bitnami/[name-of-bundle]/licenses/[bundle-version].txt 4 | -------------------------------------------------------------------------------- /5.0/debian-10/prebuildfs/opt/bitnami/scripts/libbitnami.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Bitnami custom library 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/liblog.sh 9 | 10 | # Constants 11 | BOLD='\033[1m' 12 | 13 | # Functions 14 | 15 | ######################## 16 | # Print the welcome page 17 | # Globals: 18 | # DISABLE_WELCOME_MESSAGE 19 | # BITNAMI_APP_NAME 20 | # Arguments: 21 | # None 22 | # Returns: 23 | # None 24 | ######################### 25 | print_welcome_page() { 26 | if [[ -z "${DISABLE_WELCOME_MESSAGE:-}" ]]; then 27 | if [[ -n "$BITNAMI_APP_NAME" ]]; then 28 | print_image_welcome_page 29 | fi 30 | fi 31 | } 32 | 33 | ######################## 34 | # Print the welcome page for a Bitnami Docker image 35 | # Globals: 36 | # BITNAMI_APP_NAME 37 | # Arguments: 38 | # None 39 | # Returns: 40 | # None 41 | ######################### 42 | print_image_welcome_page() { 43 | local github_url="https://github.com/bitnami/bitnami-docker-${BITNAMI_APP_NAME}" 44 | 45 | log "" 46 | log "${BOLD}Welcome to the Bitnami ${BITNAMI_APP_NAME} container${RESET}" 47 | log "Subscribe to project updates by watching ${BOLD}${github_url}${RESET}" 48 | log "Submit issues and feature requests at ${BOLD}${github_url}/issues${RESET}" 49 | log "" 50 | } 51 | 52 | -------------------------------------------------------------------------------- /5.0/debian-10/prebuildfs/opt/bitnami/scripts/libcomponent.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for managing Bitnami components 4 | 5 | # Constants 6 | CACHE_ROOT="/tmp/bitnami/pkg/cache" 7 | DOWNLOAD_URL="https://downloads.bitnami.com/files/stacksmith" 8 | 9 | # Functions 10 | 11 | ######################## 12 | # Download and unpack a Bitnami package 13 | # Globals: 14 | # OS_NAME 15 | # OS_ARCH 16 | # OS_FLAVOUR 17 | # Arguments: 18 | # $1 - component's name 19 | # $2 - component's version 20 | # Returns: 21 | # None 22 | ######################### 23 | component_unpack() { 24 | local name="${1:?name is required}" 25 | local version="${2:?version is required}" 26 | local base_name="${name}-${version}-${OS_NAME}-${OS_ARCH}-${OS_FLAVOUR}" 27 | local package_sha256="" 28 | local directory="/opt/bitnami" 29 | 30 | # Validate arguments 31 | shift 2 32 | while [ "$#" -gt 0 ]; do 33 | case "$1" in 34 | -c|--checksum) 35 | shift 36 | package_sha256="${1:?missing package checksum}" 37 | ;; 38 | *) 39 | echo "Invalid command line flag $1" >&2 40 | return 1 41 | ;; 42 | esac 43 | shift 44 | done 45 | 46 | echo "Downloading $base_name package" 47 | if [ -f "${CACHE_ROOT}/${base_name}.tar.gz" ]; then 48 | echo "${CACHE_ROOT}/${base_name}.tar.gz already exists, skipping download." 49 | cp "${CACHE_ROOT}/${base_name}.tar.gz" . 50 | rm "${CACHE_ROOT}/${base_name}.tar.gz" 51 | if [ -f "${CACHE_ROOT}/${base_name}.tar.gz.sha256" ]; then 52 | echo "Using the local sha256 from ${CACHE_ROOT}/${base_name}.tar.gz.sha256" 53 | package_sha256="$(< "${CACHE_ROOT}/${base_name}.tar.gz.sha256")" 54 | rm "${CACHE_ROOT}/${base_name}.tar.gz.sha256" 55 | fi 56 | else 57 | curl --remote-name --silent "${DOWNLOAD_URL}/${base_name}.tar.gz" 58 | fi 59 | if [ -n "$package_sha256" ]; then 60 | echo "Verifying package integrity" 61 | echo "$package_sha256 ${base_name}.tar.gz" | sha256sum --check - 62 | fi 63 | tar --directory "${directory}" --extract --gunzip --file "${base_name}.tar.gz" --no-same-owner --strip-components=2 "${base_name}/files/" 64 | rm "${base_name}.tar.gz" 65 | } 66 | -------------------------------------------------------------------------------- /5.0/debian-10/prebuildfs/opt/bitnami/scripts/libfile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for managing files 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/libos.sh 9 | 10 | # Functions 11 | 12 | ######################## 13 | # Replace a regex-matching string in a file 14 | # Arguments: 15 | # $1 - filename 16 | # $2 - match regex 17 | # $3 - substitute regex 18 | # $4 - use POSIX regex. Default: true 19 | # Returns: 20 | # None 21 | ######################### 22 | replace_in_file() { 23 | local filename="${1:?filename is required}" 24 | local match_regex="${2:?match regex is required}" 25 | local substitute_regex="${3:?substitute regex is required}" 26 | local posix_regex=${4:-true} 27 | 28 | local result 29 | 30 | # We should avoid using 'sed in-place' substitutions 31 | # 1) They are not compatible with files mounted from ConfigMap(s) 32 | # 2) We found incompatibility issues with Debian10 and "in-place" substitutions 33 | local -r del=$'\001' # Use a non-printable character as a 'sed' delimiter to avoid issues 34 | if [[ $posix_regex = true ]]; then 35 | result="$(sed -E "s${del}${match_regex}${del}${substitute_regex}${del}g" "$filename")" 36 | else 37 | result="$(sed "s${del}${match_regex}${del}${substitute_regex}${del}g" "$filename")" 38 | fi 39 | echo "$result" > "$filename" 40 | } 41 | 42 | ######################## 43 | # Replace a regex-matching multiline string in a file 44 | # Arguments: 45 | # $1 - filename 46 | # $2 - match regex 47 | # $3 - substitute regex 48 | # Returns: 49 | # None 50 | ######################### 51 | replace_in_file_multiline() { 52 | local filename="${1:?filename is required}" 53 | local match_regex="${2:?match regex is required}" 54 | local substitute_regex="${3:?substitute regex is required}" 55 | 56 | local result 57 | local -r del=$'\001' # Use a non-printable character as a 'sed' delimiter to avoid issues 58 | result="$(perl -pe "BEGIN{undef $/;} s${del}${match_regex}${del}${substitute_regex}${del}sg" "$filename")" 59 | echo "$result" > "$filename" 60 | } 61 | 62 | ######################## 63 | # Remove a line in a file based on a regex 64 | # Arguments: 65 | # $1 - filename 66 | # $2 - match regex 67 | # $3 - use POSIX regex. Default: true 68 | # Returns: 69 | # None 70 | ######################### 71 | remove_in_file() { 72 | local filename="${1:?filename is required}" 73 | local match_regex="${2:?match regex is required}" 74 | local posix_regex=${3:-true} 75 | local result 76 | 77 | # We should avoid using 'sed in-place' substitutions 78 | # 1) They are not compatible with files mounted from ConfigMap(s) 79 | # 2) We found incompatibility issues with Debian10 and "in-place" substitutions 80 | if [[ $posix_regex = true ]]; then 81 | result="$(sed -E "/$match_regex/d" "$filename")" 82 | else 83 | result="$(sed "/$match_regex/d" "$filename")" 84 | fi 85 | echo "$result" > "$filename" 86 | } 87 | 88 | ######################## 89 | # Appends text after the last line matching a pattern 90 | # Arguments: 91 | # $1 - file 92 | # $2 - match regex 93 | # $3 - contents to add 94 | # Returns: 95 | # None 96 | ######################### 97 | append_file_after_last_match() { 98 | local file="${1:?missing file}" 99 | local match_regex="${2:?missing pattern}" 100 | local value="${3:?missing value}" 101 | 102 | # We read the file in reverse, replace the first match (0,/pattern/s) and then reverse the results again 103 | result="$(tac "$file" | sed -E "0,/($match_regex)/s||${value}\n\1|" | tac)" 104 | echo "$result" > "$file" 105 | } 106 | 107 | ######################## 108 | # Wait until certain entry is present in a log file 109 | # Arguments: 110 | # $1 - entry to look for 111 | # $2 - log file 112 | # $3 - max retries. Default: 12 113 | # $4 - sleep between retries (in seconds). Default: 5 114 | # Returns: 115 | # Boolean 116 | ######################### 117 | wait_for_log_entry() { 118 | local -r entry="${1:-missing entry}" 119 | local -r log_file="${2:-missing log file}" 120 | local -r retries="${3:-12}" 121 | local -r interval_time="${4:-5}" 122 | local attempt=0 123 | 124 | check_log_file_for_entry() { 125 | if ! grep -qE "$entry" "$log_file"; then 126 | debug "Entry \"${entry}\" still not present in ${log_file} (attempt $((++attempt))/${retries})" 127 | return 1 128 | fi 129 | } 130 | debug "Checking that ${log_file} log file contains entry \"${entry}\"" 131 | if retry_while check_log_file_for_entry "$retries" "$interval_time"; then 132 | debug "Found entry \"${entry}\" in ${log_file}" 133 | true 134 | else 135 | error "Could not find entry \"${entry}\" in ${log_file} after ${retries} retries" 136 | debug_execute cat "$log_file" 137 | return 1 138 | fi 139 | } 140 | -------------------------------------------------------------------------------- /5.0/debian-10/prebuildfs/opt/bitnami/scripts/libfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for file system actions 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/liblog.sh 9 | 10 | # Functions 11 | 12 | ######################## 13 | # Ensure a file/directory is owned (user and group) but the given user 14 | # Arguments: 15 | # $1 - filepath 16 | # $2 - owner 17 | # Returns: 18 | # None 19 | ######################### 20 | owned_by() { 21 | local path="${1:?path is missing}" 22 | local owner="${2:?owner is missing}" 23 | 24 | chown "$owner":"$owner" "$path" 25 | } 26 | 27 | ######################## 28 | # Ensure a directory exists and, optionally, is owned by the given user 29 | # Arguments: 30 | # $1 - directory 31 | # $2 - owner 32 | # Returns: 33 | # None 34 | ######################### 35 | ensure_dir_exists() { 36 | local dir="${1:?directory is missing}" 37 | local owner="${2:-}" 38 | 39 | mkdir -p "${dir}" 40 | if [[ -n $owner ]]; then 41 | owned_by "$dir" "$owner" 42 | fi 43 | } 44 | 45 | ######################## 46 | # Checks whether a directory is empty or not 47 | # arguments: 48 | # $1 - directory 49 | # returns: 50 | # boolean 51 | ######################### 52 | is_dir_empty() { 53 | local dir="${1:?missing directory}" 54 | 55 | if [[ ! -e "$dir" ]] || [[ -z "$(ls -A "$dir")" ]]; then 56 | true 57 | else 58 | false 59 | fi 60 | } 61 | 62 | ######################## 63 | # Checks whether a mounted directory is empty or not 64 | # arguments: 65 | # $1 - directory 66 | # returns: 67 | # boolean 68 | ######################### 69 | is_mounted_dir_empty() { 70 | local dir="${1:?missing directory}" 71 | 72 | if is_dir_empty "$dir" || find "$dir" -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" -exec false {} +; then 73 | true 74 | else 75 | false 76 | fi 77 | } 78 | 79 | ######################## 80 | # Checks whether a file can be written to or not 81 | # arguments: 82 | # $1 - file 83 | # returns: 84 | # boolean 85 | ######################### 86 | is_file_writable() { 87 | local file="${1:?missing file}" 88 | local dir 89 | dir="$(dirname "$file")" 90 | 91 | if [[ ( -f "$file" && -w "$file" ) || ( ! -f "$file" && -d "$dir" && -w "$dir" ) ]]; then 92 | true 93 | else 94 | false 95 | fi 96 | } 97 | 98 | ######################## 99 | # Relativize a path 100 | # arguments: 101 | # $1 - path 102 | # $2 - base 103 | # returns: 104 | # None 105 | ######################### 106 | relativize() { 107 | local -r path="${1:?missing path}" 108 | local -r base="${2:?missing base}" 109 | pushd "$base" >/dev/null || exit 110 | realpath -q --no-symlinks --relative-base="$base" "$path" | sed -e 's|^/$|.|' -e 's|^/||' 111 | popd >/dev/null || exit 112 | } 113 | 114 | ######################## 115 | # Configure permisions and ownership recursively 116 | # Globals: 117 | # None 118 | # Arguments: 119 | # $1 - paths (as a string). 120 | # Flags: 121 | # -f|--file-mode - mode for directories. 122 | # -d|--dir-mode - mode for files. 123 | # -u|--user - user 124 | # -g|--group - group 125 | # Returns: 126 | # None 127 | ######################### 128 | configure_permissions_ownership() { 129 | local -r paths="${1:?paths is missing}" 130 | local dir_mode="" 131 | local file_mode="" 132 | local user="" 133 | local group="" 134 | 135 | # Validate arguments 136 | shift 1 137 | while [ "$#" -gt 0 ]; do 138 | case "$1" in 139 | -f|--file-mode) 140 | shift 141 | file_mode="${1:?missing mode for files}" 142 | ;; 143 | -d|--dir-mode) 144 | shift 145 | dir_mode="${1:?missing mode for directories}" 146 | ;; 147 | -u|--user) 148 | shift 149 | user="${1:?missing user}" 150 | ;; 151 | -g|--group) 152 | shift 153 | group="${1:?missing group}" 154 | ;; 155 | *) 156 | echo "Invalid command line flag $1" >&2 157 | return 1 158 | ;; 159 | esac 160 | shift 161 | done 162 | 163 | read -r -a filepaths <<< "$paths" 164 | for p in "${filepaths[@]}"; do 165 | if [[ -e "$p" ]]; then 166 | if [[ -n $dir_mode ]]; then 167 | find -L "$p" -type d -exec chmod "$dir_mode" {} \; 168 | fi 169 | if [[ -n $file_mode ]]; then 170 | find -L "$p" -type f -exec chmod "$file_mode" {} \; 171 | fi 172 | if [[ -n $user ]] && [[ -n $group ]]; then 173 | chown -LR "$user":"$group" "$p" 174 | elif [[ -n $user ]] && [[ -z $group ]]; then 175 | chown -LR "$user" "$p" 176 | elif [[ -z $user ]] && [[ -n $group ]]; then 177 | chgrp -LR "$group" "$p" 178 | fi 179 | else 180 | stderr_print "$p does not exist" 181 | fi 182 | done 183 | } 184 | -------------------------------------------------------------------------------- /5.0/debian-10/prebuildfs/opt/bitnami/scripts/libhook.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library to use for scripts expected to be used as Kubernetes lifecycle hooks 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load generic libraries 8 | . /opt/bitnami/scripts/liblog.sh 9 | . /opt/bitnami/scripts/libos.sh 10 | 11 | # Override functions that log to stdout/stderr of the current process, so they print to process 1 12 | for function_to_override in stderr_print debug_execute; do 13 | # Output is sent to output of process 1 and thus end up in the container log 14 | # The hook output in general isn't saved 15 | eval "$(declare -f "$function_to_override") >/proc/1/fd/1 2>/proc/1/fd/2" 16 | done 17 | -------------------------------------------------------------------------------- /5.0/debian-10/prebuildfs/opt/bitnami/scripts/liblog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for logging functions 4 | 5 | # Constants 6 | RESET='\033[0m' 7 | RED='\033[38;5;1m' 8 | GREEN='\033[38;5;2m' 9 | YELLOW='\033[38;5;3m' 10 | MAGENTA='\033[38;5;5m' 11 | CYAN='\033[38;5;6m' 12 | 13 | # Functions 14 | 15 | ######################## 16 | # Print to STDERR 17 | # Arguments: 18 | # Message to print 19 | # Returns: 20 | # None 21 | ######################### 22 | stderr_print() { 23 | # 'is_boolean_yes' is defined in libvalidations.sh, but depends on this file so we cannot source it 24 | local bool="${BITNAMI_QUIET:-false}" 25 | # comparison is performed without regard to the case of alphabetic characters 26 | shopt -s nocasematch 27 | if ! [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then 28 | printf "%b\\n" "${*}" >&2 29 | fi 30 | } 31 | 32 | ######################## 33 | # Log message 34 | # Arguments: 35 | # Message to log 36 | # Returns: 37 | # None 38 | ######################### 39 | log() { 40 | stderr_print "${CYAN}${MODULE:-} ${MAGENTA}$(date "+%T.%2N ")${RESET}${*}" 41 | } 42 | ######################## 43 | # Log an 'info' message 44 | # Arguments: 45 | # Message to log 46 | # Returns: 47 | # None 48 | ######################### 49 | info() { 50 | log "${GREEN}INFO ${RESET} ==> ${*}" 51 | } 52 | ######################## 53 | # Log message 54 | # Arguments: 55 | # Message to log 56 | # Returns: 57 | # None 58 | ######################### 59 | warn() { 60 | log "${YELLOW}WARN ${RESET} ==> ${*}" 61 | } 62 | ######################## 63 | # Log an 'error' message 64 | # Arguments: 65 | # Message to log 66 | # Returns: 67 | # None 68 | ######################### 69 | error() { 70 | log "${RED}ERROR${RESET} ==> ${*}" 71 | } 72 | ######################## 73 | # Log a 'debug' message 74 | # Globals: 75 | # BITNAMI_DEBUG 76 | # Arguments: 77 | # None 78 | # Returns: 79 | # None 80 | ######################### 81 | debug() { 82 | # 'is_boolean_yes' is defined in libvalidations.sh, but depends on this file so we cannot source it 83 | local bool="${BITNAMI_DEBUG:-false}" 84 | # comparison is performed without regard to the case of alphabetic characters 85 | shopt -s nocasematch 86 | if [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then 87 | log "${MAGENTA}DEBUG${RESET} ==> ${*}" 88 | fi 89 | } 90 | 91 | ######################## 92 | # Indent a string 93 | # Arguments: 94 | # $1 - string 95 | # $2 - number of indentation characters (default: 4) 96 | # $3 - indentation character (default: " ") 97 | # Returns: 98 | # None 99 | ######################### 100 | indent() { 101 | local string="${1:-}" 102 | local num="${2:?missing num}" 103 | local char="${3:-" "}" 104 | # Build the indentation unit string 105 | local indent_unit="" 106 | for ((i = 0; i < num; i++)); do 107 | indent_unit="${indent_unit}${char}" 108 | done 109 | # shellcheck disable=SC2001 110 | # Complex regex, see https://github.com/koalaman/shellcheck/wiki/SC2001#exceptions 111 | echo "$string" | sed "s/^/${indent_unit}/" 112 | } 113 | -------------------------------------------------------------------------------- /5.0/debian-10/prebuildfs/opt/bitnami/scripts/libnet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for network functions 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/liblog.sh 9 | 10 | # Functions 11 | 12 | ######################## 13 | # Resolve IP address for a host/domain (i.e. DNS lookup) 14 | # Arguments: 15 | # $1 - Hostname to resolve 16 | # $2 - IP address version (v4, v6), leave empty for resolving to any version 17 | # Returns: 18 | # IP 19 | ######################### 20 | dns_lookup() { 21 | local host="${1:?host is missing}" 22 | local ip_version="${2:-}" 23 | getent "ahosts${ip_version}" "$host" | awk '/STREAM/ {print $1 }' | head -n 1 24 | } 25 | 26 | ######################### 27 | # Wait for a hostname and return the IP 28 | # Arguments: 29 | # $1 - hostname 30 | # $2 - number of retries 31 | # $3 - seconds to wait between retries 32 | # Returns: 33 | # - IP address that corresponds to the hostname 34 | ######################### 35 | wait_for_dns_lookup() { 36 | local hostname="${1:?hostname is missing}" 37 | local retries="${2:-5}" 38 | local seconds="${3:-1}" 39 | check_host() { 40 | if [[ $(dns_lookup "$hostname") == "" ]]; then 41 | false 42 | else 43 | true 44 | fi 45 | } 46 | # Wait for the host to be ready 47 | retry_while "check_host ${hostname}" "$retries" "$seconds" 48 | dns_lookup "$hostname" 49 | } 50 | 51 | ######################## 52 | # Get machine's IP 53 | # Arguments: 54 | # None 55 | # Returns: 56 | # Machine IP 57 | ######################### 58 | get_machine_ip() { 59 | local -a ip_addresses 60 | local hostname 61 | hostname="$(hostname)" 62 | read -r -a ip_addresses <<< "$(dns_lookup "$hostname" | xargs echo)" 63 | if [[ "${#ip_addresses[@]}" -gt 1 ]]; then 64 | warn "Found more than one IP address associated to hostname ${hostname}: ${ip_addresses[*]}, will use ${ip_addresses[0]}" 65 | elif [[ "${#ip_addresses[@]}" -lt 1 ]]; then 66 | error "Could not find any IP address associated to hostname ${hostname}" 67 | exit 1 68 | fi 69 | echo "${ip_addresses[0]}" 70 | } 71 | 72 | ######################## 73 | # Check if the provided argument is a resolved hostname 74 | # Arguments: 75 | # $1 - Value to check 76 | # Returns: 77 | # Boolean 78 | ######################### 79 | is_hostname_resolved() { 80 | local -r host="${1:?missing value}" 81 | if [[ -n "$(dns_lookup "$host")" ]]; then 82 | true 83 | else 84 | false 85 | fi 86 | } 87 | 88 | ######################## 89 | # Parse URL 90 | # Globals: 91 | # None 92 | # Arguments: 93 | # $1 - uri - String 94 | # $2 - component to obtain. Valid options (scheme, authority, userinfo, host, port, path, query or fragment) - String 95 | # Returns: 96 | # String 97 | parse_uri() { 98 | local uri="${1:?uri is missing}" 99 | local component="${2:?component is missing}" 100 | 101 | # Solution based on https://tools.ietf.org/html/rfc3986#appendix-B with 102 | # additional sub-expressions to split authority into userinfo, host and port 103 | # Credits to Patryk Obara (see https://stackoverflow.com/a/45977232/6694969) 104 | local -r URI_REGEX='^(([^:/?#]+):)?(//((([^@/?#]+)@)?([^:/?#]+)(:([0-9]+))?))?(/([^?#]*))?(\?([^#]*))?(#(.*))?' 105 | # || | ||| | | | | | | | | | 106 | # |2 scheme | ||6 userinfo 7 host | 9 port | 11 rpath | 13 query | 15 fragment 107 | # 1 scheme: | |5 userinfo@ 8 :... 10 path 12 ?... 14 #... 108 | # | 4 authority 109 | # 3 //... 110 | local index=0 111 | case "$component" in 112 | scheme) 113 | index=2 114 | ;; 115 | authority) 116 | index=4 117 | ;; 118 | userinfo) 119 | index=6 120 | ;; 121 | host) 122 | index=7 123 | ;; 124 | port) 125 | index=9 126 | ;; 127 | path) 128 | index=10 129 | ;; 130 | query) 131 | index=13 132 | ;; 133 | fragment) 134 | index=14 135 | ;; 136 | *) 137 | stderr_print "unrecognized component $component" 138 | return 1 139 | ;; 140 | esac 141 | [[ "$uri" =~ $URI_REGEX ]] && echo "${BASH_REMATCH[${index}]}" 142 | } 143 | 144 | ######################## 145 | # Wait for a HTTP connection to succeed 146 | # Globals: 147 | # * 148 | # Arguments: 149 | # $1 - URL to wait for 150 | # $2 - Maximum amount of retries (optional) 151 | # $3 - Time between retries (optional) 152 | # Returns: 153 | # true if the HTTP connection succeeded, false otherwise 154 | ######################### 155 | wait_for_http_connection() { 156 | local url="${1:?missing url}" 157 | local retries="${2:-}" 158 | local sleep_time="${3:-}" 159 | if ! retry_while "debug_execute curl --silent ${url}" "$retries" "$sleep_time"; then 160 | error "Could not connect to ${url}" 161 | return 1 162 | fi 163 | } 164 | -------------------------------------------------------------------------------- /5.0/debian-10/prebuildfs/opt/bitnami/scripts/libpersistence.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Bitnami persistence library 4 | # Used for bringing persistence capabilities to applications that don't have clear separation of data and logic 5 | 6 | # shellcheck disable=SC1091 7 | 8 | # Load Generic Libraries 9 | . /opt/bitnami/scripts/libfs.sh 10 | . /opt/bitnami/scripts/libos.sh 11 | . /opt/bitnami/scripts/liblog.sh 12 | . /opt/bitnami/scripts/libversion.sh 13 | 14 | # Functions 15 | 16 | ######################## 17 | # Persist an application directory 18 | # Globals: 19 | # BITNAMI_ROOT_DIR 20 | # BITNAMI_VOLUME_DIR 21 | # Arguments: 22 | # $1 - App folder name 23 | # $2 - List of app files to persist 24 | # Returns: 25 | # true if all steps succeeded, false otherwise 26 | ######################### 27 | persist_app() { 28 | local -r app="${1:?missing app}" 29 | local -a files_to_restore 30 | read -r -a files_to_persist <<< "$(tr ',;:' ' ' <<< "$2")" 31 | local -r install_dir="${BITNAMI_ROOT_DIR}/${app}" 32 | local -r persist_dir="${BITNAMI_VOLUME_DIR}/${app}" 33 | # Persist the individual files 34 | if [[ "${#files_to_persist[@]}" -le 0 ]]; then 35 | warn "No files are configured to be persisted" 36 | return 37 | fi 38 | pushd "$install_dir" >/dev/null || exit 39 | local file_to_persist_relative file_to_persist_destination file_to_persist_destination_folder 40 | local -r tmp_file="/tmp/perms.acl" 41 | for file_to_persist in "${files_to_persist[@]}"; do 42 | if [[ ! -f "$file_to_persist" && ! -d "$file_to_persist" ]]; then 43 | error "Cannot persist '${file_to_persist}' because it does not exist" 44 | return 1 45 | fi 46 | file_to_persist_relative="$(relativize "$file_to_persist" "$install_dir")" 47 | file_to_persist_destination="${persist_dir}/${file_to_persist_relative}" 48 | file_to_persist_destination_folder="$(dirname "$file_to_persist_destination")" 49 | # Get original permissions for existing files, which will be applied later 50 | # Exclude the root directory with 'sed', to avoid issues when copying the entirety of it to a volume 51 | getfacl -R "$file_to_persist_relative" | sed -E '/# file: (\..+|[^.])/,$!d' > "$tmp_file" 52 | # Copy directories to the volume 53 | ensure_dir_exists "$file_to_persist_destination_folder" 54 | cp -Lr --preserve=links "$file_to_persist_relative" "$file_to_persist_destination_folder" 55 | # Restore permissions 56 | pushd "$persist_dir" >/dev/null || exit 57 | if am_i_root; then 58 | setfacl --restore="$tmp_file" 59 | else 60 | # When running as non-root, don't change ownership 61 | setfacl --restore=<(grep -E -v '^# (owner|group):' "$tmp_file") 62 | fi 63 | popd >/dev/null || exit 64 | done 65 | popd >/dev/null || exit 66 | rm -f "$tmp_file" 67 | # Install the persisted files into the installation directory, via symlinks 68 | restore_persisted_app "$@" 69 | } 70 | 71 | ######################## 72 | # Restore a persisted application directory 73 | # Globals: 74 | # BITNAMI_ROOT_DIR 75 | # BITNAMI_VOLUME_DIR 76 | # FORCE_MAJOR_UPGRADE 77 | # Arguments: 78 | # $1 - App folder name 79 | # $2 - List of app files to restore 80 | # Returns: 81 | # true if all steps succeeded, false otherwise 82 | ######################### 83 | restore_persisted_app() { 84 | local -r app="${1:?missing app}" 85 | local -a files_to_restore 86 | read -r -a files_to_restore <<< "$(tr ',;:' ' ' <<< "$2")" 87 | local -r install_dir="${BITNAMI_ROOT_DIR}/${app}" 88 | local -r persist_dir="${BITNAMI_VOLUME_DIR}/${app}" 89 | # Restore the individual persisted files 90 | if [[ "${#files_to_restore[@]}" -le 0 ]]; then 91 | warn "No persisted files are configured to be restored" 92 | return 93 | fi 94 | local file_to_restore_relative file_to_restore_origin file_to_restore_destination 95 | for file_to_restore in "${files_to_restore[@]}"; do 96 | file_to_restore_relative="$(relativize "$file_to_restore" "$install_dir")" 97 | # We use 'realpath --no-symlinks' to ensure that the case of '.' is covered and the directory is removed 98 | file_to_restore_origin="$(realpath --no-symlinks "${install_dir}/${file_to_restore_relative}")" 99 | file_to_restore_destination="$(realpath --no-symlinks "${persist_dir}/${file_to_restore_relative}")" 100 | rm -rf "$file_to_restore_origin" 101 | ln -sfn "$file_to_restore_destination" "$file_to_restore_origin" 102 | done 103 | } 104 | 105 | ######################## 106 | # Check if an application directory was already persisted 107 | # Globals: 108 | # BITNAMI_VOLUME_DIR 109 | # Arguments: 110 | # $1 - App folder name 111 | # Returns: 112 | # true if all steps succeeded, false otherwise 113 | ######################### 114 | is_app_initialized() { 115 | local -r app="${1:?missing app}" 116 | local -r persist_dir="${BITNAMI_VOLUME_DIR}/${app}" 117 | if ! is_mounted_dir_empty "$persist_dir"; then 118 | true 119 | else 120 | false 121 | fi 122 | } 123 | -------------------------------------------------------------------------------- /5.0/debian-10/prebuildfs/opt/bitnami/scripts/libservice.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for managing services 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/libvalidations.sh 9 | . /opt/bitnami/scripts/liblog.sh 10 | 11 | # Functions 12 | 13 | ######################## 14 | # Read the provided pid file and returns a PID 15 | # Arguments: 16 | # $1 - Pid file 17 | # Returns: 18 | # PID 19 | ######################### 20 | get_pid_from_file() { 21 | local pid_file="${1:?pid file is missing}" 22 | 23 | if [[ -f "$pid_file" ]]; then 24 | if [[ -n "$(< "$pid_file")" ]] && [[ "$(< "$pid_file")" -gt 0 ]]; then 25 | echo "$(< "$pid_file")" 26 | fi 27 | fi 28 | } 29 | 30 | ######################## 31 | # Check if a provided PID corresponds to a running service 32 | # Arguments: 33 | # $1 - PID 34 | # Returns: 35 | # Boolean 36 | ######################### 37 | is_service_running() { 38 | local pid="${1:?pid is missing}" 39 | 40 | kill -0 "$pid" 2>/dev/null 41 | } 42 | 43 | ######################## 44 | # Stop a service by sending a termination signal to its pid 45 | # Arguments: 46 | # $1 - Pid file 47 | # $2 - Signal number (optional) 48 | # Returns: 49 | # None 50 | ######################### 51 | stop_service_using_pid() { 52 | local pid_file="${1:?pid file is missing}" 53 | local signal="${2:-}" 54 | local pid 55 | 56 | pid="$(get_pid_from_file "$pid_file")" 57 | [[ -z "$pid" ]] || ! is_service_running "$pid" && return 58 | 59 | if [[ -n "$signal" ]]; then 60 | kill "-${signal}" "$pid" 61 | else 62 | kill "$pid" 63 | fi 64 | 65 | local counter=10 66 | while [[ "$counter" -ne 0 ]] && is_service_running "$pid"; do 67 | sleep 1 68 | counter=$((counter - 1)) 69 | done 70 | } 71 | 72 | ######################## 73 | # Start cron daemon 74 | # Arguments: 75 | # None 76 | # Returns: 77 | # true if started correctly, false otherwise 78 | ######################### 79 | cron_start() { 80 | if [[ -x "/usr/sbin/cron" ]]; then 81 | /usr/sbin/cron 82 | elif [[ -x "/usr/sbin/crond" ]]; then 83 | /usr/sbin/crond 84 | else 85 | false 86 | fi 87 | } 88 | 89 | ######################## 90 | # Generate a cron configuration file for a given service 91 | # Arguments: 92 | # $1 - Service name 93 | # $2 - Command 94 | # Flags: 95 | # --run-as - User to run as (default: root) 96 | # --schedule - Cron schedule configuration (default: * * * * *) 97 | # Returns: 98 | # None 99 | ######################### 100 | generate_cron_conf() { 101 | local service_name="${1:?service name is missing}" 102 | local cmd="${2:?command is missing}" 103 | local run_as="root" 104 | local schedule="* * * * *" 105 | local clean="true" 106 | 107 | local clean="true" 108 | 109 | # Parse optional CLI flags 110 | shift 2 111 | while [[ "$#" -gt 0 ]]; do 112 | case "$1" in 113 | --run-as) 114 | shift 115 | run_as="$1" 116 | ;; 117 | --schedule) 118 | shift 119 | schedule="$1" 120 | ;; 121 | --no-clean) 122 | clean="false" 123 | ;; 124 | *) 125 | echo "Invalid command line flag ${1}" >&2 126 | return 1 127 | ;; 128 | esac 129 | shift 130 | done 131 | 132 | mkdir -p /etc/cron.d 133 | if "$clean"; then 134 | echo "${schedule} ${run_as} ${cmd}" > /etc/cron.d/"$service_name" 135 | else 136 | echo "${schedule} ${run_as} ${cmd}" >> /etc/cron.d/"$service_name" 137 | fi 138 | } 139 | 140 | ######################## 141 | # Remove a cron configuration file for a given service 142 | # Arguments: 143 | # $1 - Service name 144 | # Returns: 145 | # None 146 | ######################### 147 | remove_cron_conf() { 148 | local service_name="${1:?service name is missing}" 149 | local cron_conf_dir="/etc/monit/conf.d" 150 | rm -f "${cron_conf_dir}/${service_name}" 151 | } 152 | 153 | ######################## 154 | # Generate a monit configuration file for a given service 155 | # Arguments: 156 | # $1 - Service name 157 | # $2 - Pid file 158 | # $3 - Start command 159 | # $4 - Stop command 160 | # Flags: 161 | # --disable - Whether to disable the monit configuration 162 | # Returns: 163 | # None 164 | ######################### 165 | generate_monit_conf() { 166 | local service_name="${1:?service name is missing}" 167 | local pid_file="${2:?pid file is missing}" 168 | local start_command="${3:?start command is missing}" 169 | local stop_command="${4:?stop command is missing}" 170 | local monit_conf_dir="/etc/monit/conf.d" 171 | local disabled="no" 172 | 173 | # Parse optional CLI flags 174 | shift 4 175 | while [[ "$#" -gt 0 ]]; do 176 | case "$1" in 177 | --disable) 178 | disabled="yes" 179 | ;; 180 | *) 181 | echo "Invalid command line flag ${1}" >&2 182 | return 1 183 | ;; 184 | esac 185 | shift 186 | done 187 | 188 | is_boolean_yes "$disabled" && conf_suffix=".disabled" 189 | mkdir -p "$monit_conf_dir" 190 | cat >"${monit_conf_dir}/${service_name}.conf${conf_suffix:-}" <&2 242 | return 1 243 | ;; 244 | esac 245 | shift 246 | done 247 | 248 | mkdir -p "$logrotate_conf_dir" 249 | cat <"${logrotate_conf_dir}/${service_name}" 250 | ${log_path} { 251 | ${period} 252 | rotate ${rotations} 253 | dateext 254 | compress 255 | copytruncate 256 | missingok 257 | $(indent "$extra" 2) 258 | } 259 | EOF 260 | } 261 | 262 | ######################## 263 | # Remove a logrotate configuration file 264 | # Arguments: 265 | # $1 - Service name 266 | # Returns: 267 | # None 268 | ######################### 269 | remove_logrotate_conf() { 270 | local service_name="${1:?service name is missing}" 271 | local logrotate_conf_dir="/etc/logrotate.d" 272 | rm -f "${logrotate_conf_dir}/${service_name}" 273 | } 274 | -------------------------------------------------------------------------------- /5.0/debian-10/prebuildfs/opt/bitnami/scripts/libvalidations.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Validation functions library 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/liblog.sh 9 | 10 | # Functions 11 | 12 | ######################## 13 | # Check if the provided argument is an integer 14 | # Arguments: 15 | # $1 - Value to check 16 | # Returns: 17 | # Boolean 18 | ######################### 19 | is_int() { 20 | local -r int="${1:?missing value}" 21 | if [[ "$int" =~ ^-?[0-9]+ ]]; then 22 | true 23 | else 24 | false 25 | fi 26 | } 27 | 28 | ######################## 29 | # Check if the provided argument is a positive integer 30 | # Arguments: 31 | # $1 - Value to check 32 | # Returns: 33 | # Boolean 34 | ######################### 35 | is_positive_int() { 36 | local -r int="${1:?missing value}" 37 | if is_int "$int" && (( "${int}" >= 0 )); then 38 | true 39 | else 40 | false 41 | fi 42 | } 43 | 44 | ######################## 45 | # Check if the provided argument is a boolean or is the string 'yes/true' 46 | # Arguments: 47 | # $1 - Value to check 48 | # Returns: 49 | # Boolean 50 | ######################### 51 | is_boolean_yes() { 52 | local -r bool="${1:-}" 53 | # comparison is performed without regard to the case of alphabetic characters 54 | shopt -s nocasematch 55 | if [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then 56 | true 57 | else 58 | false 59 | fi 60 | } 61 | 62 | ######################## 63 | # Check if the provided argument is a boolean yes/no value 64 | # Arguments: 65 | # $1 - Value to check 66 | # Returns: 67 | # Boolean 68 | ######################### 69 | is_yes_no_value() { 70 | local -r bool="${1:-}" 71 | if [[ "$bool" =~ ^(yes|no)$ ]]; then 72 | true 73 | else 74 | false 75 | fi 76 | } 77 | 78 | ######################## 79 | # Check if the provided argument is a boolean true/false value 80 | # Arguments: 81 | # $1 - Value to check 82 | # Returns: 83 | # Boolean 84 | ######################### 85 | is_true_false_value() { 86 | local -r bool="${1:-}" 87 | if [[ "$bool" =~ ^(true|false)$ ]]; then 88 | true 89 | else 90 | false 91 | fi 92 | } 93 | 94 | ######################## 95 | # Check if the provided argument is a boolean 1/0 value 96 | # Arguments: 97 | # $1 - Value to check 98 | # Returns: 99 | # Boolean 100 | ######################### 101 | is_1_0_value() { 102 | local -r bool="${1:-}" 103 | if [[ "$bool" =~ ^[10]$ ]]; then 104 | true 105 | else 106 | false 107 | fi 108 | } 109 | 110 | ######################## 111 | # Check if the provided argument is an empty string or not defined 112 | # Arguments: 113 | # $1 - Value to check 114 | # Returns: 115 | # Boolean 116 | ######################### 117 | is_empty_value() { 118 | local -r val="${1:-}" 119 | if [[ -z "$val" ]]; then 120 | true 121 | else 122 | false 123 | fi 124 | } 125 | 126 | ######################## 127 | # Validate if the provided argument is a valid port 128 | # Arguments: 129 | # $1 - Port to validate 130 | # Returns: 131 | # Boolean and error message 132 | ######################### 133 | validate_port() { 134 | local value 135 | local unprivileged=0 136 | 137 | # Parse flags 138 | while [[ "$#" -gt 0 ]]; do 139 | case "$1" in 140 | -unprivileged) 141 | unprivileged=1 142 | ;; 143 | --) 144 | shift 145 | break 146 | ;; 147 | -*) 148 | stderr_print "unrecognized flag $1" 149 | return 1 150 | ;; 151 | *) 152 | break 153 | ;; 154 | esac 155 | shift 156 | done 157 | 158 | if [[ "$#" -gt 1 ]]; then 159 | echo "too many arguments provided" 160 | return 2 161 | elif [[ "$#" -eq 0 ]]; then 162 | stderr_print "missing port argument" 163 | return 1 164 | else 165 | value=$1 166 | fi 167 | 168 | if [[ -z "$value" ]]; then 169 | echo "the value is empty" 170 | return 1 171 | else 172 | if ! is_int "$value"; then 173 | echo "value is not an integer" 174 | return 2 175 | elif [[ "$value" -lt 0 ]]; then 176 | echo "negative value provided" 177 | return 2 178 | elif [[ "$value" -gt 65535 ]]; then 179 | echo "requested port is greater than 65535" 180 | return 2 181 | elif [[ "$unprivileged" = 1 && "$value" -lt 1024 ]]; then 182 | echo "privileged port requested" 183 | return 3 184 | fi 185 | fi 186 | } 187 | 188 | ######################## 189 | # Validate if the provided argument is a valid IPv4 address 190 | # Arguments: 191 | # $1 - IP to validate 192 | # Returns: 193 | # Boolean 194 | ######################### 195 | validate_ipv4() { 196 | local ip="${1:?ip is missing}" 197 | local stat=1 198 | 199 | if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then 200 | read -r -a ip_array <<< "$(tr '.' ' ' <<< "$ip")" 201 | [[ ${ip_array[0]} -le 255 && ${ip_array[1]} -le 255 \ 202 | && ${ip_array[2]} -le 255 && ${ip_array[3]} -le 255 ]] 203 | stat=$? 204 | fi 205 | return $stat 206 | } 207 | 208 | ######################## 209 | # Validate a string format 210 | # Arguments: 211 | # $1 - String to validate 212 | # Returns: 213 | # Boolean 214 | ######################### 215 | validate_string() { 216 | local string 217 | local min_length=-1 218 | local max_length=-1 219 | 220 | # Parse flags 221 | while [ "$#" -gt 0 ]; do 222 | case "$1" in 223 | -min-length) 224 | shift 225 | min_length=${1:-} 226 | ;; 227 | -max-length) 228 | shift 229 | max_length=${1:-} 230 | ;; 231 | --) 232 | shift 233 | break 234 | ;; 235 | -*) 236 | stderr_print "unrecognized flag $1" 237 | return 1 238 | ;; 239 | *) 240 | break 241 | ;; 242 | esac 243 | shift 244 | done 245 | 246 | if [ "$#" -gt 1 ]; then 247 | stderr_print "too many arguments provided" 248 | return 2 249 | elif [ "$#" -eq 0 ]; then 250 | stderr_print "missing string" 251 | return 1 252 | else 253 | string=$1 254 | fi 255 | 256 | if [[ "$min_length" -ge 0 ]] && [[ "${#string}" -lt "$min_length" ]]; then 257 | echo "string length is less than $min_length" 258 | return 1 259 | fi 260 | if [[ "$max_length" -ge 0 ]] && [[ "${#string}" -gt "$max_length" ]]; then 261 | echo "string length is great than $max_length" 262 | return 1 263 | fi 264 | } 265 | -------------------------------------------------------------------------------- /5.0/debian-10/prebuildfs/opt/bitnami/scripts/libversion.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for managing versions strings 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/liblog.sh 9 | 10 | # Functions 11 | ######################## 12 | # Gets semantic version 13 | # Arguments: 14 | # $1 - version: string to extract major.minor.patch 15 | # $2 - section: 1 to extract major, 2 to extract minor, 3 to extract patch 16 | # Returns: 17 | # array with the major, minor and release 18 | ######################### 19 | get_sematic_version () { 20 | local version="${1:?version is required}" 21 | local section="${2:?section is required}" 22 | local -a version_sections 23 | 24 | #Regex to parse versions: x.y.z 25 | local -r regex='([0-9]+)(\.([0-9]+)(\.([0-9]+))?)?' 26 | 27 | if [[ "$version" =~ $regex ]]; then 28 | local i=1 29 | local j=1 30 | local n=${#BASH_REMATCH[*]} 31 | 32 | while [[ $i -lt $n ]]; do 33 | if [[ -n "${BASH_REMATCH[$i]}" ]] && [[ "${BASH_REMATCH[$i]:0:1}" != '.' ]]; then 34 | version_sections[$j]=${BASH_REMATCH[$i]} 35 | ((j++)) 36 | fi 37 | ((i++)) 38 | done 39 | 40 | local number_regex='^[0-9]+$' 41 | if [[ "$section" =~ $number_regex ]] && (( section > 0 )) && (( section <= 3 )); then 42 | echo "${version_sections[$section]}" 43 | return 44 | else 45 | stderr_print "Section allowed values are: 1, 2, and 3" 46 | return 1 47 | fi 48 | fi 49 | } 50 | -------------------------------------------------------------------------------- /5.0/debian-10/prebuildfs/usr/sbin/install_packages: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | export DEBIAN_FRONTEND=noninteractive 5 | n=0 6 | max=2 7 | until [ $n -gt $max ]; do 8 | set +e 9 | ( 10 | apt-get update -qq && 11 | apt-get install -y --no-install-recommends "$@" 12 | ) 13 | CODE=$? 14 | set -e 15 | if [ $CODE -eq 0 ]; then 16 | break 17 | fi 18 | if [ $n -eq $max ]; then 19 | exit $CODE 20 | fi 21 | echo "apt failed, retrying" 22 | n=$(($n + 1)) 23 | done 24 | rm -r /var/lib/apt/lists /var/cache/apt/archives 25 | -------------------------------------------------------------------------------- /5.0/debian-10/rootfs/opt/bitnami/scripts/librediscluster.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Bitnami Redis Cluster library 4 | 5 | # shellcheck disable=SC1090,SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/libfile.sh 9 | . /opt/bitnami/scripts/libfs.sh 10 | . /opt/bitnami/scripts/liblog.sh 11 | . /opt/bitnami/scripts/libnet.sh 12 | . /opt/bitnami/scripts/libos.sh 13 | . /opt/bitnami/scripts/libservice.sh 14 | . /opt/bitnami/scripts/libvalidations.sh 15 | . /opt/bitnami/scripts/libredis.sh 16 | 17 | # Functions 18 | 19 | ######################## 20 | # Validate settings in REDIS_* env vars. 21 | # Globals: 22 | # REDIS_* 23 | # Arguments: 24 | # None 25 | # Returns: 26 | # None 27 | ######################### 28 | redis_cluster_validate() { 29 | debug "Validating settings in REDIS_* env vars.." 30 | local error_code=0 31 | 32 | # Auxiliary functions 33 | print_validation_error() { 34 | error "$1" 35 | error_code=1 36 | } 37 | 38 | empty_password_enabled_warn() { 39 | warn "You set the environment variable ALLOW_EMPTY_PASSWORD=${ALLOW_EMPTY_PASSWORD}. For safety reasons, do not use this flag in a production environment." 40 | } 41 | empty_password_error() { 42 | print_validation_error "The $1 environment variable is empty or not set. Set the environment variable ALLOW_EMPTY_PASSWORD=yes to allow the container to be started with blank passwords. This is recommended only for development." 43 | } 44 | 45 | if is_boolean_yes "$ALLOW_EMPTY_PASSWORD"; then 46 | empty_password_enabled_warn 47 | else 48 | [[ -z "$REDIS_PASSWORD" ]] && empty_password_error REDIS_PASSWORD 49 | fi 50 | 51 | if ! is_boolean_yes "$REDIS_CLUSTER_DYNAMIC_IPS"; then 52 | [[ -z "$REDIS_CLUSTER_ANNOUNCE_IP" ]] && print_validation_error "To provide external access you need to provide the REDIS_CLUSTER_ANNOUNCE_IP env var" 53 | fi 54 | 55 | [[ -z "$REDIS_NODES" ]] && print_validation_error "REDIS_NODES is required" 56 | 57 | if [[ -z "$REDIS_PORT_NUMBER" ]]; then 58 | print_validation_error "REDIS_PORT_NUMBER cannot be empty" 59 | fi 60 | 61 | if is_boolean_yes "$REDIS_CLUSTER_CREATOR"; then 62 | [[ -z "$REDIS_CLUSTER_REPLICAS" ]] && print_validation_error "To create the cluster you need to provide the number of replicas to the cluster creator" 63 | fi 64 | 65 | if ((REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP < 0)); then 66 | print_validation_error "REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP must be greater or equal to zero" 67 | fi 68 | 69 | [[ "$error_code" -eq 0 ]] || exit "$error_code" 70 | } 71 | 72 | ######################## 73 | # Redis specific configuration to override the default one 74 | # Globals: 75 | # REDIS_* 76 | # Arguments: 77 | # None 78 | # Returns: 79 | # None 80 | ######################### 81 | redis_cluster_override_conf() { 82 | # Redis configuration to override 83 | if ! is_boolean_yes "$REDIS_CLUSTER_DYNAMIC_IPS"; then 84 | redis_conf_set cluster-announce-ip "$REDIS_CLUSTER_ANNOUNCE_IP" 85 | fi 86 | if is_boolean_yes "$REDIS_CLUSTER_DYNAMIC_IPS"; then 87 | # Always set the announce-ip to avoid issues when using proxies and traffic restrictions. 88 | redis_conf_set cluster-announce-ip "$(get_machine_ip)" 89 | fi 90 | if is_boolean_yes "$REDIS_TLS_ENABLED"; then 91 | redis_conf_set tls-cluster yes 92 | redis_conf_set tls-replication yes 93 | fi 94 | } 95 | 96 | ######################## 97 | # Ensure Redis is initialized 98 | # Globals: 99 | # REDIS_* 100 | # Arguments: 101 | # None 102 | # Returns: 103 | # None 104 | ######################### 105 | redis_cluster_initialize() { 106 | redis_configure_default 107 | redis_cluster_override_conf 108 | } 109 | 110 | ######################## 111 | # Creates the Redis cluster 112 | # Globals: 113 | # REDIS_* 114 | # Arguments: 115 | # - $@ Array with the hostnames 116 | # Returns: 117 | # None 118 | ######################### 119 | redis_cluster_create() { 120 | local nodes=("$@") 121 | local sockets=() 122 | local wait_command 123 | local create_command 124 | 125 | for node in "${nodes[@]}"; do 126 | read -r -a host_and_port <<< "$(to_host_and_port "$node")" 127 | wait_command="redis-cli -h ${host_and_port[0]} -p ${host_and_port[1]} ping" 128 | if is_boolean_yes "$REDIS_TLS_ENABLED"; then 129 | wait_command="${wait_command:0:-5} --tls --cert ${REDIS_TLS_CERT_FILE} --key ${REDIS_TLS_KEY_FILE} --cacert ${REDIS_TLS_CA_FILE} ping" 130 | fi 131 | while [[ $($wait_command) != 'PONG' ]]; do 132 | echo "Node $node not ready, waiting for all the nodes to be ready..." 133 | sleep 1 134 | done 135 | done 136 | 137 | echo "Waiting ${REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP}s before querying node ip addresses" 138 | sleep "${REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP}" 139 | 140 | for node in "${nodes[@]}"; do 141 | read -r -a host_and_port <<< "$(to_host_and_port "$node")" 142 | sockets+=("$(wait_for_dns_lookup "${host_and_port[0]}" "${REDIS_CLUSTER_DNS_LOOKUP_RETRIES}" "${REDIS_CLUSTER_DNS_LOOKUP_SLEEP}"):${host_and_port[1]}") 143 | done 144 | 145 | create_command="redis-cli --cluster create ${sockets[*]} --cluster-replicas ${REDIS_CLUSTER_REPLICAS} --cluster-yes" 146 | if is_boolean_yes "$REDIS_TLS_ENABLED"; then 147 | create_command="${create_command} --tls --cert ${REDIS_TLS_CERT_FILE} --key ${REDIS_TLS_KEY_FILE} --cacert ${REDIS_TLS_CA_FILE}" 148 | fi 149 | yes yes | $create_command || true 150 | if redis_cluster_check "${sockets[0]}"; then 151 | echo "Cluster correctly created" 152 | else 153 | echo "The cluster was already created, the nodes should have recovered it" 154 | fi 155 | } 156 | 157 | ######################### 158 | ## Checks if the cluster state is correct. 159 | ## Params: 160 | ## - $1: node where to check the cluster state 161 | ######################### 162 | redis_cluster_check() { 163 | if is_boolean_yes "$REDIS_TLS_ENABLED"; then 164 | local -r check=$(redis-cli --tls --cert "${REDIS_TLS_CERT_FILE}" --key "${REDIS_TLS_KEY_FILE}" --cacert "${REDIS_TLS_CA_FILE}" --cluster check "$1") 165 | else 166 | local -r check=$(redis-cli --cluster check "$1") 167 | fi 168 | if [[ $check =~ "All 16384 slots covered" ]]; then 169 | true 170 | else 171 | false 172 | fi 173 | } 174 | 175 | ######################### 176 | ## Recovers the cluster when using dynamic IPs by changing them in the nodes.conf 177 | # Globals: 178 | # REDIS_* 179 | # Arguments: 180 | # None 181 | # Returns: 182 | # None 183 | ######################### 184 | redis_cluster_update_ips() { 185 | read -ra nodes <<< "$(tr ',;' ' ' <<< "${REDIS_NODES}")" 186 | 187 | declare -A host_2_ip_array # Array to map hosts and IPs 188 | # Update the IPs when a number of nodes > quorum change their IPs 189 | if [[ ! -f "${REDIS_DATA_DIR}/nodes.sh" ]]; then 190 | # It is the first initialization so store the nodes 191 | for node in "${nodes[@]}"; do 192 | ip=$(wait_for_dns_lookup "$node" "$REDIS_DNS_RETRIES" 5) 193 | host_2_ip_array["$node"]="$ip" 194 | done 195 | echo "Storing map with hostnames and IPs" 196 | declare -p host_2_ip_array >"${REDIS_DATA_DIR}/nodes.sh" 197 | else 198 | # The cluster was already started 199 | . "${REDIS_DATA_DIR}/nodes.sh" 200 | # Update the IPs in the nodes.conf 201 | for node in "${nodes[@]}"; do 202 | newIP=$(wait_for_dns_lookup "$node" "$REDIS_DNS_RETRIES" 5) 203 | # The node can be new if we are updating the cluster, so catch the unbound variable error 204 | if [[ ${host_2_ip_array[$node]+true} ]]; then 205 | echo "Changing old IP ${host_2_ip_array[$node]} by the new one ${newIP}" 206 | nodesFile=$(sed "s/ ${host_2_ip_array[$node]}:/ $newIP:/g" "${REDIS_DATA_DIR}/nodes.conf") 207 | echo "$nodesFile" >"${REDIS_DATA_DIR}/nodes.conf" 208 | fi 209 | host_2_ip_array["$node"]="$newIP" 210 | done 211 | declare -p host_2_ip_array >"${REDIS_DATA_DIR}/nodes.sh" 212 | fi 213 | } 214 | 215 | ######################### 216 | ## Assigns a port to the host if one is not set using redis defaults 217 | # Globals: 218 | # REDIS_* 219 | # Arguments: 220 | # $1 - redis host or redis host and port 221 | # Returns: 222 | # - 2 element Array of host and port 223 | ######################### 224 | to_host_and_port() { 225 | local host="${1:?host is required}" 226 | read -r -a host_and_port <<< "$(echo "$host" | tr ":" " ")" 227 | 228 | if [ "${#host_and_port[*]}" -eq "1" ]; then 229 | if is_boolean_yes "$REDIS_TLS_ENABLED"; then 230 | host_and_port=("${host_and_port[0]}" "${REDIS_TLS_PORT}") 231 | else 232 | host_and_port=("${host_and_port[0]}" "${REDIS_PORT_NUMBER}") 233 | fi 234 | fi 235 | 236 | echo "${host_and_port[*]}" 237 | } 238 | -------------------------------------------------------------------------------- /5.0/debian-10/rootfs/opt/bitnami/scripts/redis-cluster-env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Environment configuration for redis-cluster 4 | 5 | # The values for all environment variables will be set in the below order of precedence 6 | # 1. Custom environment variables defined below after Bitnami defaults 7 | # 2. Constants defined in this file (environment variables with no default), i.e. BITNAMI_ROOT_DIR 8 | # 3. Environment variables overridden via external files using *_FILE variables (see below) 9 | # 4. Environment variables set externally (i.e. current Bash context/Dockerfile/userdata) 10 | 11 | # Load logging library 12 | . /opt/bitnami/scripts/liblog.sh 13 | 14 | export BITNAMI_ROOT_DIR="/opt/bitnami" 15 | export BITNAMI_VOLUME_DIR="/bitnami" 16 | 17 | # Logging configuration 18 | export MODULE="${MODULE:-redis-cluster}" 19 | export BITNAMI_DEBUG="${BITNAMI_DEBUG:-false}" 20 | 21 | # By setting an environment variable matching *_FILE to a file path, the prefixed environment 22 | # variable will be overridden with the value specified in that file 23 | redis_cluster_env_vars=( 24 | REDIS_DATA_DIR 25 | REDIS_DISABLE_COMMANDS 26 | REDIS_DATABASE 27 | REDIS_AOF_ENABLED 28 | REDIS_MASTER_HOST 29 | REDIS_MASTER_PORT_NUMBER 30 | REDIS_PORT_NUMBER 31 | REDIS_ALLOW_REMOTE_CONNECTIONS 32 | REDIS_REPLICATION_MODE 33 | REDIS_REPLICA_IP 34 | REDIS_REPLICA_PORT 35 | REDIS_EXTRA_FLAGS 36 | ALLOW_EMPTY_PASSWORD 37 | REDIS_PASSWORD 38 | REDIS_MASTER_PASSWORD 39 | REDIS_TLS_ENABLED 40 | REDIS_TLS_PORT_NUMBER 41 | REDIS_TLS_CERT_FILE 42 | REDIS_TLS_KEY_FILE 43 | REDIS_TLS_CA_FILE 44 | REDIS_TLS_DH_PARAMS_FILE 45 | REDIS_TLS_AUTH_CLIENTS 46 | REDIS_CLUSTER_CREATOR 47 | REDIS_CLUSTER_REPLICAS 48 | REDIS_CLUSTER_DYNAMIC_IPS 49 | REDIS_CLUSTER_ANNOUNCE_IP 50 | REDIS_DNS_RETRIES 51 | REDIS_NODES 52 | REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP 53 | REDIS_CLUSTER_DNS_LOOKUP_RETRIES 54 | REDIS_CLUSTER_DNS_LOOKUP_SLEEP 55 | REDIS_TLS_PORT 56 | ) 57 | for env_var in "${redis_cluster_env_vars[@]}"; do 58 | file_env_var="${env_var}_FILE" 59 | if [[ -n "${!file_env_var:-}" ]]; then 60 | if [[ -r "${!file_env_var:-}" ]]; then 61 | export "${env_var}=$(< "${!file_env_var}")" 62 | unset "${file_env_var}" 63 | else 64 | warn "Skipping export of '${env_var}'. '${!file_env_var:-}' is not readable." 65 | fi 66 | fi 67 | done 68 | unset redis_cluster_env_vars 69 | 70 | # Paths 71 | export REDIS_VOLUME_DIR="/bitnami/redis" 72 | export REDIS_BASE_DIR="${BITNAMI_ROOT_DIR}/redis" 73 | export REDIS_CONF_DIR="${REDIS_BASE_DIR}/etc" 74 | export REDIS_DATA_DIR="${REDIS_DATA_DIR:-${REDIS_VOLUME_DIR}/data}" 75 | export REDIS_MOUNTED_CONF_DIR="${REDIS_BASE_DIR}/mounted-etc" 76 | export REDIS_CONF_FILE="${REDIS_CONF_DIR}/redis.conf" 77 | export REDIS_LOG_DIR="${REDIS_BASE_DIR}/logs" 78 | export REDIS_LOG_FILE="${REDIS_LOG_DIR}/redis.log" 79 | export REDIS_TMP_DIR="${REDIS_BASE_DIR}/tmp" 80 | export REDIS_PID_FILE="${REDIS_TMP_DIR}/redis.pid" 81 | export REDIS_BIN_DIR="${REDIS_BASE_DIR}/bin" 82 | export PATH="${REDIS_BIN_DIR}:${BITNAMI_ROOT_DIR}/common/bin:${PATH}" 83 | 84 | # System users (when running with a privileged user) 85 | export REDIS_DAEMON_USER="redis" 86 | export REDIS_DAEMON_GROUP="redis" 87 | 88 | # Redis settings 89 | export REDIS_DISABLE_COMMANDS="${REDIS_DISABLE_COMMANDS:-}" 90 | export REDIS_DATABASE="${REDIS_DATABASE:-redis}" 91 | export REDIS_AOF_ENABLED="${REDIS_AOF_ENABLED:-yes}" 92 | export REDIS_MASTER_HOST="${REDIS_MASTER_HOST:-}" 93 | export REDIS_MASTER_PORT_NUMBER="${REDIS_MASTER_PORT_NUMBER:-6379}" 94 | export REDIS_DEFAULT_PORT_NUMBER="6379" # only used at build time 95 | export REDIS_PORT_NUMBER="${REDIS_PORT_NUMBER:-$REDIS_DEFAULT_PORT_NUMBER}" 96 | export REDIS_ALLOW_REMOTE_CONNECTIONS="${REDIS_ALLOW_REMOTE_CONNECTIONS:-yes}" 97 | export REDIS_REPLICATION_MODE="${REDIS_REPLICATION_MODE:-}" 98 | export REDIS_REPLICA_IP="${REDIS_REPLICA_IP:-}" 99 | export REDIS_REPLICA_PORT="${REDIS_REPLICA_PORT:-}" 100 | export REDIS_EXTRA_FLAGS="${REDIS_EXTRA_FLAGS:-}" 101 | export ALLOW_EMPTY_PASSWORD="${ALLOW_EMPTY_PASSWORD:-no}" 102 | export REDIS_PASSWORD="${REDIS_PASSWORD:-}" 103 | export REDIS_MASTER_PASSWORD="${REDIS_MASTER_PASSWORD:-}" 104 | 105 | # TLS settings 106 | export REDIS_TLS_ENABLED="${REDIS_TLS_ENABLED:-no}" 107 | REDIS_TLS_PORT_NUMBER="${REDIS_TLS_PORT_NUMBER:-"${REDIS_TLS_PORT:-}"}" 108 | export REDIS_TLS_PORT_NUMBER="${REDIS_TLS_PORT_NUMBER:-6379}" 109 | export REDIS_TLS_CERT_FILE="${REDIS_TLS_CERT_FILE:-}" 110 | export REDIS_TLS_KEY_FILE="${REDIS_TLS_KEY_FILE:-}" 111 | export REDIS_TLS_CA_FILE="${REDIS_TLS_CA_FILE:-}" 112 | export REDIS_TLS_DH_PARAMS_FILE="${REDIS_TLS_DH_PARAMS_FILE:-}" 113 | export REDIS_TLS_AUTH_CLIENTS="${REDIS_TLS_AUTH_CLIENTS:-yes}" 114 | 115 | # Redis Cluster settings 116 | export REDIS_CLUSTER_CREATOR="${REDIS_CLUSTER_CREATOR:-no}" 117 | export REDIS_CLUSTER_REPLICAS="${REDIS_CLUSTER_REPLICAS:-1}" 118 | export REDIS_CLUSTER_DYNAMIC_IPS="${REDIS_CLUSTER_DYNAMIC_IPS:-yes}" 119 | export REDIS_CLUSTER_ANNOUNCE_IP="${REDIS_CLUSTER_ANNOUNCE_IP:-}" 120 | export REDIS_DNS_RETRIES="${REDIS_DNS_RETRIES:-120}" 121 | export REDIS_NODES="${REDIS_NODES:-}" 122 | export REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP="${REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP:-0}" 123 | export REDIS_CLUSTER_DNS_LOOKUP_RETRIES="${REDIS_CLUSTER_DNS_LOOKUP_RETRIES:-1}" 124 | export REDIS_CLUSTER_DNS_LOOKUP_SLEEP="${REDIS_CLUSTER_DNS_LOOKUP_SLEEP:-1}" 125 | 126 | # Custom environment variables may be defined below 127 | -------------------------------------------------------------------------------- /5.0/debian-10/rootfs/opt/bitnami/scripts/redis-cluster/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # shellcheck disable=SC1091 4 | 5 | set -o errexit 6 | set -o nounset 7 | set -o pipefail 8 | # set -o xtrace # Uncomment this line for debugging purpose 9 | 10 | # Load Redis environment variables 11 | . /opt/bitnami/scripts/redis-cluster-env.sh 12 | 13 | # Load libraries 14 | . /opt/bitnami/scripts/libbitnami.sh 15 | . /opt/bitnami/scripts/librediscluster.sh 16 | 17 | print_welcome_page 18 | 19 | if [[ "$*" = *"/run.sh"* ]]; then 20 | info "** Starting Redis setup **" 21 | /opt/bitnami/scripts/redis-cluster/setup.sh 22 | info "** Redis setup finished! **" 23 | fi 24 | 25 | echo "" 26 | exec "$@" 27 | -------------------------------------------------------------------------------- /5.0/debian-10/rootfs/opt/bitnami/scripts/redis-cluster/postunpack.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # shellcheck disable=SC1091 4 | 5 | set -o errexit 6 | set -o nounset 7 | set -o pipefail 8 | # set -o xtrace # Uncomment this line for debugging purpose 9 | 10 | # Load Redis environment variables 11 | . /opt/bitnami/scripts/redis-cluster-env.sh 12 | 13 | # Load libraries 14 | . /opt/bitnami/scripts/librediscluster.sh 15 | . /opt/bitnami/scripts/libfs.sh 16 | 17 | for dir in "$REDIS_VOLUME_DIR" "$REDIS_DATA_DIR" "$REDIS_BASE_DIR" "$REDIS_CONF_DIR"; do 18 | ensure_dir_exists "$dir" 19 | done 20 | 21 | cp "${REDIS_BASE_DIR}/etc/redis-default.conf" "$REDIS_CONF_FILE" 22 | 23 | info "Setting Redis config file..." 24 | redis_conf_set port "$REDIS_DEFAULT_PORT_NUMBER" 25 | redis_conf_set dir "$REDIS_DATA_DIR" 26 | redis_conf_set pidfile "$REDIS_PID_FILE" 27 | redis_conf_set daemonize no 28 | redis_conf_set cluster-enabled yes 29 | redis_conf_set cluster-config-file "${REDIS_DATA_DIR}/nodes.conf" 30 | 31 | chmod -R g+rwX "$REDIS_BASE_DIR" /bitnami/redis 32 | -------------------------------------------------------------------------------- /5.0/debian-10/rootfs/opt/bitnami/scripts/redis-cluster/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # shellcheck disable=SC1091 4 | 5 | set -o errexit 6 | set -o nounset 7 | set -o pipefail 8 | # set -o xtrace # Uncomment this line for debugging purpose 9 | 10 | # Enable job control 11 | # ref https://www.gnu.org/software/bash/manual/bash.html#The-Set-Builtin 12 | set -m 13 | 14 | # Load Redis environment variables 15 | . /opt/bitnami/scripts/redis-cluster-env.sh 16 | 17 | # Load libraries 18 | . /opt/bitnami/scripts/libos.sh 19 | . /opt/bitnami/scripts/librediscluster.sh 20 | 21 | read -ra nodes <<< "$(tr ',;' ' ' <<< "${REDIS_NODES}")" 22 | 23 | ARGS=("--port" "$REDIS_PORT_NUMBER") 24 | ARGS+=("--include" "${REDIS_BASE_DIR}/etc/redis.conf") 25 | 26 | if ! is_boolean_yes "$ALLOW_EMPTY_PASSWORD"; then 27 | ARGS+=("--requirepass" "$REDIS_PASSWORD") 28 | ARGS+=("--masterauth" "$REDIS_PASSWORD") 29 | else 30 | ARGS+=("--protected-mode" "no") 31 | fi 32 | 33 | ARGS+=("$@") 34 | 35 | if is_boolean_yes "$REDIS_CLUSTER_CREATOR" && ! [[ -f "${REDIS_DATA_DIR}/nodes.conf" ]]; then 36 | # Start Redis in background 37 | if am_i_root; then 38 | gosu "$REDIS_DAEMON_USER" redis-server "${ARGS[@]}" & 39 | else 40 | redis-server "${ARGS[@]}" & 41 | fi 42 | # Create the cluster 43 | redis_cluster_create "${nodes[@]}" 44 | # Bring redis process to foreground 45 | fg 46 | else 47 | if am_i_root; then 48 | exec gosu "$REDIS_DAEMON_USER" redis-server "${ARGS[@]}" 49 | else 50 | exec redis-server "${ARGS[@]}" 51 | fi 52 | fi 53 | -------------------------------------------------------------------------------- /5.0/debian-10/rootfs/opt/bitnami/scripts/redis-cluster/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # shellcheck disable=SC1091 4 | 5 | set -o errexit 6 | set -o nounset 7 | set -o pipefail 8 | # set -o xtrace # Uncomment this line for debugging purpose 9 | 10 | # Load Redis environment variables 11 | . /opt/bitnami/scripts/redis-cluster-env.sh 12 | 13 | # Load libraries 14 | . /opt/bitnami/scripts/libos.sh 15 | . /opt/bitnami/scripts/libfs.sh 16 | . /opt/bitnami/scripts/librediscluster.sh 17 | 18 | # Ensure Redis environment variables settings are valid 19 | redis_cluster_validate 20 | # Ensure Redis is stopped when this script ends 21 | trap "redis_stop" EXIT 22 | am_i_root && ensure_user_exists "$REDIS_DAEMON_USER" --group "$REDIS_DAEMON_GROUP" 23 | 24 | # Ensure Redis is initialized 25 | redis_cluster_initialize 26 | 27 | if is_boolean_yes "$REDIS_CLUSTER_DYNAMIC_IPS"; then 28 | redis_cluster_update_ips 29 | fi 30 | -------------------------------------------------------------------------------- /6.0/debian-10/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.io/bitnami/minideb:buster 2 | LABEL maintainer "Bitnami " 3 | 4 | ENV HOME="/" \ 5 | OS_ARCH="amd64" \ 6 | OS_FLAVOUR="debian-10" \ 7 | OS_NAME="linux" 8 | 9 | COPY prebuildfs / 10 | # Install required system packages and dependencies 11 | RUN install_packages acl ca-certificates curl gzip libc6 libssl1.1 procps tar 12 | RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "redis" "6.0.16-1" --checksum 2f1e2503cbd471c61f3819f7778db72654c95b1cc68792c65655ba658f491118 13 | RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "gosu" "1.14.0-0" --checksum 3e6fc37ca073b10a73a804d39c2f0c028947a1a596382a4f8ebe43dfbaa3a25e 14 | RUN chmod g+rwX /opt/bitnami 15 | 16 | COPY rootfs / 17 | RUN /opt/bitnami/scripts/redis-cluster/postunpack.sh 18 | ENV BITNAMI_APP_NAME="redis-cluster" \ 19 | BITNAMI_IMAGE_VERSION="6.0.16-debian-10-r16" \ 20 | PATH="/opt/bitnami/redis/bin:/opt/bitnami/common/bin:$PATH" 21 | 22 | EXPOSE 6379 23 | 24 | USER 1001 25 | ENTRYPOINT [ "/opt/bitnami/scripts/redis-cluster/entrypoint.sh" ] 26 | CMD [ "/opt/bitnami/scripts/redis-cluster/run.sh" ] 27 | -------------------------------------------------------------------------------- /6.0/debian-10/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | redis-node-0: 4 | image: docker.io/bitnami/redis-cluster:6.0 5 | volumes: 6 | - redis-cluster_data-0:/bitnami/redis/data 7 | environment: 8 | - 'REDIS_PASSWORD=bitnami' 9 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 10 | 11 | redis-node-1: 12 | image: docker.io/bitnami/redis-cluster:6.0 13 | volumes: 14 | - redis-cluster_data-1:/bitnami/redis/data 15 | environment: 16 | - 'REDIS_PASSWORD=bitnami' 17 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 18 | 19 | redis-node-2: 20 | image: docker.io/bitnami/redis-cluster:6.0 21 | volumes: 22 | - redis-cluster_data-2:/bitnami/redis/data 23 | environment: 24 | - 'REDIS_PASSWORD=bitnami' 25 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 26 | 27 | redis-node-3: 28 | image: docker.io/bitnami/redis-cluster:6.0 29 | volumes: 30 | - redis-cluster_data-3:/bitnami/redis/data 31 | environment: 32 | - 'REDIS_PASSWORD=bitnami' 33 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 34 | 35 | redis-node-4: 36 | image: docker.io/bitnami/redis-cluster:6.0 37 | volumes: 38 | - redis-cluster_data-4:/bitnami/redis/data 39 | environment: 40 | - 'REDIS_PASSWORD=bitnami' 41 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 42 | 43 | redis-node-5: 44 | image: docker.io/bitnami/redis-cluster:6.0 45 | volumes: 46 | - redis-cluster_data-5:/bitnami/redis/data 47 | depends_on: 48 | - redis-node-0 49 | - redis-node-1 50 | - redis-node-2 51 | - redis-node-3 52 | - redis-node-4 53 | environment: 54 | - 'REDIS_PASSWORD=bitnami' 55 | - 'REDISCLI_AUTH=bitnami' 56 | - 'REDIS_CLUSTER_REPLICAS=1' 57 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 58 | - 'REDIS_CLUSTER_CREATOR=yes' 59 | 60 | volumes: 61 | redis-cluster_data-0: 62 | driver: local 63 | redis-cluster_data-1: 64 | driver: local 65 | redis-cluster_data-2: 66 | driver: local 67 | redis-cluster_data-3: 68 | driver: local 69 | redis-cluster_data-4: 70 | driver: local 71 | redis-cluster_data-5: 72 | driver: local 73 | -------------------------------------------------------------------------------- /6.0/debian-10/prebuildfs/opt/bitnami/.bitnami_components.json: -------------------------------------------------------------------------------- 1 | { 2 | "gosu": { 3 | "arch": "amd64", 4 | "digest": "3e6fc37ca073b10a73a804d39c2f0c028947a1a596382a4f8ebe43dfbaa3a25e", 5 | "distro": "debian-10", 6 | "type": "NAMI", 7 | "version": "1.14.0-0" 8 | }, 9 | "redis": { 10 | "arch": "amd64", 11 | "digest": "2f1e2503cbd471c61f3819f7778db72654c95b1cc68792c65655ba658f491118", 12 | "distro": "debian-10", 13 | "type": "NAMI", 14 | "version": "6.0.16-1" 15 | } 16 | } -------------------------------------------------------------------------------- /6.0/debian-10/prebuildfs/opt/bitnami/licenses/licenses.txt: -------------------------------------------------------------------------------- 1 | Bitnami containers ship with software bundles. You can find the licenses under: 2 | /opt/bitnami/nami/COPYING 3 | /opt/bitnami/[name-of-bundle]/licenses/[bundle-version].txt 4 | -------------------------------------------------------------------------------- /6.0/debian-10/prebuildfs/opt/bitnami/scripts/libbitnami.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Bitnami custom library 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/liblog.sh 9 | 10 | # Constants 11 | BOLD='\033[1m' 12 | 13 | # Functions 14 | 15 | ######################## 16 | # Print the welcome page 17 | # Globals: 18 | # DISABLE_WELCOME_MESSAGE 19 | # BITNAMI_APP_NAME 20 | # Arguments: 21 | # None 22 | # Returns: 23 | # None 24 | ######################### 25 | print_welcome_page() { 26 | if [[ -z "${DISABLE_WELCOME_MESSAGE:-}" ]]; then 27 | if [[ -n "$BITNAMI_APP_NAME" ]]; then 28 | print_image_welcome_page 29 | fi 30 | fi 31 | } 32 | 33 | ######################## 34 | # Print the welcome page for a Bitnami Docker image 35 | # Globals: 36 | # BITNAMI_APP_NAME 37 | # Arguments: 38 | # None 39 | # Returns: 40 | # None 41 | ######################### 42 | print_image_welcome_page() { 43 | local github_url="https://github.com/bitnami/bitnami-docker-${BITNAMI_APP_NAME}" 44 | 45 | log "" 46 | log "${BOLD}Welcome to the Bitnami ${BITNAMI_APP_NAME} container${RESET}" 47 | log "Subscribe to project updates by watching ${BOLD}${github_url}${RESET}" 48 | log "Submit issues and feature requests at ${BOLD}${github_url}/issues${RESET}" 49 | log "" 50 | } 51 | 52 | -------------------------------------------------------------------------------- /6.0/debian-10/prebuildfs/opt/bitnami/scripts/libcomponent.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for managing Bitnami components 4 | 5 | # Constants 6 | CACHE_ROOT="/tmp/bitnami/pkg/cache" 7 | DOWNLOAD_URL="https://downloads.bitnami.com/files/stacksmith" 8 | 9 | # Functions 10 | 11 | ######################## 12 | # Download and unpack a Bitnami package 13 | # Globals: 14 | # OS_NAME 15 | # OS_ARCH 16 | # OS_FLAVOUR 17 | # Arguments: 18 | # $1 - component's name 19 | # $2 - component's version 20 | # Returns: 21 | # None 22 | ######################### 23 | component_unpack() { 24 | local name="${1:?name is required}" 25 | local version="${2:?version is required}" 26 | local base_name="${name}-${version}-${OS_NAME}-${OS_ARCH}-${OS_FLAVOUR}" 27 | local package_sha256="" 28 | local directory="/opt/bitnami" 29 | 30 | # Validate arguments 31 | shift 2 32 | while [ "$#" -gt 0 ]; do 33 | case "$1" in 34 | -c|--checksum) 35 | shift 36 | package_sha256="${1:?missing package checksum}" 37 | ;; 38 | *) 39 | echo "Invalid command line flag $1" >&2 40 | return 1 41 | ;; 42 | esac 43 | shift 44 | done 45 | 46 | echo "Downloading $base_name package" 47 | if [ -f "${CACHE_ROOT}/${base_name}.tar.gz" ]; then 48 | echo "${CACHE_ROOT}/${base_name}.tar.gz already exists, skipping download." 49 | cp "${CACHE_ROOT}/${base_name}.tar.gz" . 50 | rm "${CACHE_ROOT}/${base_name}.tar.gz" 51 | if [ -f "${CACHE_ROOT}/${base_name}.tar.gz.sha256" ]; then 52 | echo "Using the local sha256 from ${CACHE_ROOT}/${base_name}.tar.gz.sha256" 53 | package_sha256="$(< "${CACHE_ROOT}/${base_name}.tar.gz.sha256")" 54 | rm "${CACHE_ROOT}/${base_name}.tar.gz.sha256" 55 | fi 56 | else 57 | curl --remote-name --silent "${DOWNLOAD_URL}/${base_name}.tar.gz" 58 | fi 59 | if [ -n "$package_sha256" ]; then 60 | echo "Verifying package integrity" 61 | echo "$package_sha256 ${base_name}.tar.gz" | sha256sum --check - 62 | fi 63 | tar --directory "${directory}" --extract --gunzip --file "${base_name}.tar.gz" --no-same-owner --strip-components=2 "${base_name}/files/" 64 | rm "${base_name}.tar.gz" 65 | } 66 | -------------------------------------------------------------------------------- /6.0/debian-10/prebuildfs/opt/bitnami/scripts/libfile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for managing files 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/libos.sh 9 | 10 | # Functions 11 | 12 | ######################## 13 | # Replace a regex-matching string in a file 14 | # Arguments: 15 | # $1 - filename 16 | # $2 - match regex 17 | # $3 - substitute regex 18 | # $4 - use POSIX regex. Default: true 19 | # Returns: 20 | # None 21 | ######################### 22 | replace_in_file() { 23 | local filename="${1:?filename is required}" 24 | local match_regex="${2:?match regex is required}" 25 | local substitute_regex="${3:?substitute regex is required}" 26 | local posix_regex=${4:-true} 27 | 28 | local result 29 | 30 | # We should avoid using 'sed in-place' substitutions 31 | # 1) They are not compatible with files mounted from ConfigMap(s) 32 | # 2) We found incompatibility issues with Debian10 and "in-place" substitutions 33 | local -r del=$'\001' # Use a non-printable character as a 'sed' delimiter to avoid issues 34 | if [[ $posix_regex = true ]]; then 35 | result="$(sed -E "s${del}${match_regex}${del}${substitute_regex}${del}g" "$filename")" 36 | else 37 | result="$(sed "s${del}${match_regex}${del}${substitute_regex}${del}g" "$filename")" 38 | fi 39 | echo "$result" > "$filename" 40 | } 41 | 42 | ######################## 43 | # Replace a regex-matching multiline string in a file 44 | # Arguments: 45 | # $1 - filename 46 | # $2 - match regex 47 | # $3 - substitute regex 48 | # Returns: 49 | # None 50 | ######################### 51 | replace_in_file_multiline() { 52 | local filename="${1:?filename is required}" 53 | local match_regex="${2:?match regex is required}" 54 | local substitute_regex="${3:?substitute regex is required}" 55 | 56 | local result 57 | local -r del=$'\001' # Use a non-printable character as a 'sed' delimiter to avoid issues 58 | result="$(perl -pe "BEGIN{undef $/;} s${del}${match_regex}${del}${substitute_regex}${del}sg" "$filename")" 59 | echo "$result" > "$filename" 60 | } 61 | 62 | ######################## 63 | # Remove a line in a file based on a regex 64 | # Arguments: 65 | # $1 - filename 66 | # $2 - match regex 67 | # $3 - use POSIX regex. Default: true 68 | # Returns: 69 | # None 70 | ######################### 71 | remove_in_file() { 72 | local filename="${1:?filename is required}" 73 | local match_regex="${2:?match regex is required}" 74 | local posix_regex=${3:-true} 75 | local result 76 | 77 | # We should avoid using 'sed in-place' substitutions 78 | # 1) They are not compatible with files mounted from ConfigMap(s) 79 | # 2) We found incompatibility issues with Debian10 and "in-place" substitutions 80 | if [[ $posix_regex = true ]]; then 81 | result="$(sed -E "/$match_regex/d" "$filename")" 82 | else 83 | result="$(sed "/$match_regex/d" "$filename")" 84 | fi 85 | echo "$result" > "$filename" 86 | } 87 | 88 | ######################## 89 | # Appends text after the last line matching a pattern 90 | # Arguments: 91 | # $1 - file 92 | # $2 - match regex 93 | # $3 - contents to add 94 | # Returns: 95 | # None 96 | ######################### 97 | append_file_after_last_match() { 98 | local file="${1:?missing file}" 99 | local match_regex="${2:?missing pattern}" 100 | local value="${3:?missing value}" 101 | 102 | # We read the file in reverse, replace the first match (0,/pattern/s) and then reverse the results again 103 | result="$(tac "$file" | sed -E "0,/($match_regex)/s||${value}\n\1|" | tac)" 104 | echo "$result" > "$file" 105 | } 106 | 107 | ######################## 108 | # Wait until certain entry is present in a log file 109 | # Arguments: 110 | # $1 - entry to look for 111 | # $2 - log file 112 | # $3 - max retries. Default: 12 113 | # $4 - sleep between retries (in seconds). Default: 5 114 | # Returns: 115 | # Boolean 116 | ######################### 117 | wait_for_log_entry() { 118 | local -r entry="${1:-missing entry}" 119 | local -r log_file="${2:-missing log file}" 120 | local -r retries="${3:-12}" 121 | local -r interval_time="${4:-5}" 122 | local attempt=0 123 | 124 | check_log_file_for_entry() { 125 | if ! grep -qE "$entry" "$log_file"; then 126 | debug "Entry \"${entry}\" still not present in ${log_file} (attempt $((++attempt))/${retries})" 127 | return 1 128 | fi 129 | } 130 | debug "Checking that ${log_file} log file contains entry \"${entry}\"" 131 | if retry_while check_log_file_for_entry "$retries" "$interval_time"; then 132 | debug "Found entry \"${entry}\" in ${log_file}" 133 | true 134 | else 135 | error "Could not find entry \"${entry}\" in ${log_file} after ${retries} retries" 136 | debug_execute cat "$log_file" 137 | return 1 138 | fi 139 | } 140 | -------------------------------------------------------------------------------- /6.0/debian-10/prebuildfs/opt/bitnami/scripts/libfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for file system actions 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/liblog.sh 9 | 10 | # Functions 11 | 12 | ######################## 13 | # Ensure a file/directory is owned (user and group) but the given user 14 | # Arguments: 15 | # $1 - filepath 16 | # $2 - owner 17 | # Returns: 18 | # None 19 | ######################### 20 | owned_by() { 21 | local path="${1:?path is missing}" 22 | local owner="${2:?owner is missing}" 23 | 24 | chown "$owner":"$owner" "$path" 25 | } 26 | 27 | ######################## 28 | # Ensure a directory exists and, optionally, is owned by the given user 29 | # Arguments: 30 | # $1 - directory 31 | # $2 - owner 32 | # Returns: 33 | # None 34 | ######################### 35 | ensure_dir_exists() { 36 | local dir="${1:?directory is missing}" 37 | local owner="${2:-}" 38 | 39 | mkdir -p "${dir}" 40 | if [[ -n $owner ]]; then 41 | owned_by "$dir" "$owner" 42 | fi 43 | } 44 | 45 | ######################## 46 | # Checks whether a directory is empty or not 47 | # arguments: 48 | # $1 - directory 49 | # returns: 50 | # boolean 51 | ######################### 52 | is_dir_empty() { 53 | local dir="${1:?missing directory}" 54 | 55 | if [[ ! -e "$dir" ]] || [[ -z "$(ls -A "$dir")" ]]; then 56 | true 57 | else 58 | false 59 | fi 60 | } 61 | 62 | ######################## 63 | # Checks whether a mounted directory is empty or not 64 | # arguments: 65 | # $1 - directory 66 | # returns: 67 | # boolean 68 | ######################### 69 | is_mounted_dir_empty() { 70 | local dir="${1:?missing directory}" 71 | 72 | if is_dir_empty "$dir" || find "$dir" -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" -exec false {} +; then 73 | true 74 | else 75 | false 76 | fi 77 | } 78 | 79 | ######################## 80 | # Checks whether a file can be written to or not 81 | # arguments: 82 | # $1 - file 83 | # returns: 84 | # boolean 85 | ######################### 86 | is_file_writable() { 87 | local file="${1:?missing file}" 88 | local dir 89 | dir="$(dirname "$file")" 90 | 91 | if [[ ( -f "$file" && -w "$file" ) || ( ! -f "$file" && -d "$dir" && -w "$dir" ) ]]; then 92 | true 93 | else 94 | false 95 | fi 96 | } 97 | 98 | ######################## 99 | # Relativize a path 100 | # arguments: 101 | # $1 - path 102 | # $2 - base 103 | # returns: 104 | # None 105 | ######################### 106 | relativize() { 107 | local -r path="${1:?missing path}" 108 | local -r base="${2:?missing base}" 109 | pushd "$base" >/dev/null || exit 110 | realpath -q --no-symlinks --relative-base="$base" "$path" | sed -e 's|^/$|.|' -e 's|^/||' 111 | popd >/dev/null || exit 112 | } 113 | 114 | ######################## 115 | # Configure permisions and ownership recursively 116 | # Globals: 117 | # None 118 | # Arguments: 119 | # $1 - paths (as a string). 120 | # Flags: 121 | # -f|--file-mode - mode for directories. 122 | # -d|--dir-mode - mode for files. 123 | # -u|--user - user 124 | # -g|--group - group 125 | # Returns: 126 | # None 127 | ######################### 128 | configure_permissions_ownership() { 129 | local -r paths="${1:?paths is missing}" 130 | local dir_mode="" 131 | local file_mode="" 132 | local user="" 133 | local group="" 134 | 135 | # Validate arguments 136 | shift 1 137 | while [ "$#" -gt 0 ]; do 138 | case "$1" in 139 | -f|--file-mode) 140 | shift 141 | file_mode="${1:?missing mode for files}" 142 | ;; 143 | -d|--dir-mode) 144 | shift 145 | dir_mode="${1:?missing mode for directories}" 146 | ;; 147 | -u|--user) 148 | shift 149 | user="${1:?missing user}" 150 | ;; 151 | -g|--group) 152 | shift 153 | group="${1:?missing group}" 154 | ;; 155 | *) 156 | echo "Invalid command line flag $1" >&2 157 | return 1 158 | ;; 159 | esac 160 | shift 161 | done 162 | 163 | read -r -a filepaths <<< "$paths" 164 | for p in "${filepaths[@]}"; do 165 | if [[ -e "$p" ]]; then 166 | if [[ -n $dir_mode ]]; then 167 | find -L "$p" -type d -exec chmod "$dir_mode" {} \; 168 | fi 169 | if [[ -n $file_mode ]]; then 170 | find -L "$p" -type f -exec chmod "$file_mode" {} \; 171 | fi 172 | if [[ -n $user ]] && [[ -n $group ]]; then 173 | chown -LR "$user":"$group" "$p" 174 | elif [[ -n $user ]] && [[ -z $group ]]; then 175 | chown -LR "$user" "$p" 176 | elif [[ -z $user ]] && [[ -n $group ]]; then 177 | chgrp -LR "$group" "$p" 178 | fi 179 | else 180 | stderr_print "$p does not exist" 181 | fi 182 | done 183 | } 184 | -------------------------------------------------------------------------------- /6.0/debian-10/prebuildfs/opt/bitnami/scripts/libhook.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library to use for scripts expected to be used as Kubernetes lifecycle hooks 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load generic libraries 8 | . /opt/bitnami/scripts/liblog.sh 9 | . /opt/bitnami/scripts/libos.sh 10 | 11 | # Override functions that log to stdout/stderr of the current process, so they print to process 1 12 | for function_to_override in stderr_print debug_execute; do 13 | # Output is sent to output of process 1 and thus end up in the container log 14 | # The hook output in general isn't saved 15 | eval "$(declare -f "$function_to_override") >/proc/1/fd/1 2>/proc/1/fd/2" 16 | done 17 | -------------------------------------------------------------------------------- /6.0/debian-10/prebuildfs/opt/bitnami/scripts/liblog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for logging functions 4 | 5 | # Constants 6 | RESET='\033[0m' 7 | RED='\033[38;5;1m' 8 | GREEN='\033[38;5;2m' 9 | YELLOW='\033[38;5;3m' 10 | MAGENTA='\033[38;5;5m' 11 | CYAN='\033[38;5;6m' 12 | 13 | # Functions 14 | 15 | ######################## 16 | # Print to STDERR 17 | # Arguments: 18 | # Message to print 19 | # Returns: 20 | # None 21 | ######################### 22 | stderr_print() { 23 | # 'is_boolean_yes' is defined in libvalidations.sh, but depends on this file so we cannot source it 24 | local bool="${BITNAMI_QUIET:-false}" 25 | # comparison is performed without regard to the case of alphabetic characters 26 | shopt -s nocasematch 27 | if ! [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then 28 | printf "%b\\n" "${*}" >&2 29 | fi 30 | } 31 | 32 | ######################## 33 | # Log message 34 | # Arguments: 35 | # Message to log 36 | # Returns: 37 | # None 38 | ######################### 39 | log() { 40 | stderr_print "${CYAN}${MODULE:-} ${MAGENTA}$(date "+%T.%2N ")${RESET}${*}" 41 | } 42 | ######################## 43 | # Log an 'info' message 44 | # Arguments: 45 | # Message to log 46 | # Returns: 47 | # None 48 | ######################### 49 | info() { 50 | log "${GREEN}INFO ${RESET} ==> ${*}" 51 | } 52 | ######################## 53 | # Log message 54 | # Arguments: 55 | # Message to log 56 | # Returns: 57 | # None 58 | ######################### 59 | warn() { 60 | log "${YELLOW}WARN ${RESET} ==> ${*}" 61 | } 62 | ######################## 63 | # Log an 'error' message 64 | # Arguments: 65 | # Message to log 66 | # Returns: 67 | # None 68 | ######################### 69 | error() { 70 | log "${RED}ERROR${RESET} ==> ${*}" 71 | } 72 | ######################## 73 | # Log a 'debug' message 74 | # Globals: 75 | # BITNAMI_DEBUG 76 | # Arguments: 77 | # None 78 | # Returns: 79 | # None 80 | ######################### 81 | debug() { 82 | # 'is_boolean_yes' is defined in libvalidations.sh, but depends on this file so we cannot source it 83 | local bool="${BITNAMI_DEBUG:-false}" 84 | # comparison is performed without regard to the case of alphabetic characters 85 | shopt -s nocasematch 86 | if [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then 87 | log "${MAGENTA}DEBUG${RESET} ==> ${*}" 88 | fi 89 | } 90 | 91 | ######################## 92 | # Indent a string 93 | # Arguments: 94 | # $1 - string 95 | # $2 - number of indentation characters (default: 4) 96 | # $3 - indentation character (default: " ") 97 | # Returns: 98 | # None 99 | ######################### 100 | indent() { 101 | local string="${1:-}" 102 | local num="${2:?missing num}" 103 | local char="${3:-" "}" 104 | # Build the indentation unit string 105 | local indent_unit="" 106 | for ((i = 0; i < num; i++)); do 107 | indent_unit="${indent_unit}${char}" 108 | done 109 | # shellcheck disable=SC2001 110 | # Complex regex, see https://github.com/koalaman/shellcheck/wiki/SC2001#exceptions 111 | echo "$string" | sed "s/^/${indent_unit}/" 112 | } 113 | -------------------------------------------------------------------------------- /6.0/debian-10/prebuildfs/opt/bitnami/scripts/libnet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for network functions 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/liblog.sh 9 | 10 | # Functions 11 | 12 | ######################## 13 | # Resolve IP address for a host/domain (i.e. DNS lookup) 14 | # Arguments: 15 | # $1 - Hostname to resolve 16 | # $2 - IP address version (v4, v6), leave empty for resolving to any version 17 | # Returns: 18 | # IP 19 | ######################### 20 | dns_lookup() { 21 | local host="${1:?host is missing}" 22 | local ip_version="${2:-}" 23 | getent "ahosts${ip_version}" "$host" | awk '/STREAM/ {print $1 }' | head -n 1 24 | } 25 | 26 | ######################### 27 | # Wait for a hostname and return the IP 28 | # Arguments: 29 | # $1 - hostname 30 | # $2 - number of retries 31 | # $3 - seconds to wait between retries 32 | # Returns: 33 | # - IP address that corresponds to the hostname 34 | ######################### 35 | wait_for_dns_lookup() { 36 | local hostname="${1:?hostname is missing}" 37 | local retries="${2:-5}" 38 | local seconds="${3:-1}" 39 | check_host() { 40 | if [[ $(dns_lookup "$hostname") == "" ]]; then 41 | false 42 | else 43 | true 44 | fi 45 | } 46 | # Wait for the host to be ready 47 | retry_while "check_host ${hostname}" "$retries" "$seconds" 48 | dns_lookup "$hostname" 49 | } 50 | 51 | ######################## 52 | # Get machine's IP 53 | # Arguments: 54 | # None 55 | # Returns: 56 | # Machine IP 57 | ######################### 58 | get_machine_ip() { 59 | local -a ip_addresses 60 | local hostname 61 | hostname="$(hostname)" 62 | read -r -a ip_addresses <<< "$(dns_lookup "$hostname" | xargs echo)" 63 | if [[ "${#ip_addresses[@]}" -gt 1 ]]; then 64 | warn "Found more than one IP address associated to hostname ${hostname}: ${ip_addresses[*]}, will use ${ip_addresses[0]}" 65 | elif [[ "${#ip_addresses[@]}" -lt 1 ]]; then 66 | error "Could not find any IP address associated to hostname ${hostname}" 67 | exit 1 68 | fi 69 | echo "${ip_addresses[0]}" 70 | } 71 | 72 | ######################## 73 | # Check if the provided argument is a resolved hostname 74 | # Arguments: 75 | # $1 - Value to check 76 | # Returns: 77 | # Boolean 78 | ######################### 79 | is_hostname_resolved() { 80 | local -r host="${1:?missing value}" 81 | if [[ -n "$(dns_lookup "$host")" ]]; then 82 | true 83 | else 84 | false 85 | fi 86 | } 87 | 88 | ######################## 89 | # Parse URL 90 | # Globals: 91 | # None 92 | # Arguments: 93 | # $1 - uri - String 94 | # $2 - component to obtain. Valid options (scheme, authority, userinfo, host, port, path, query or fragment) - String 95 | # Returns: 96 | # String 97 | parse_uri() { 98 | local uri="${1:?uri is missing}" 99 | local component="${2:?component is missing}" 100 | 101 | # Solution based on https://tools.ietf.org/html/rfc3986#appendix-B with 102 | # additional sub-expressions to split authority into userinfo, host and port 103 | # Credits to Patryk Obara (see https://stackoverflow.com/a/45977232/6694969) 104 | local -r URI_REGEX='^(([^:/?#]+):)?(//((([^@/?#]+)@)?([^:/?#]+)(:([0-9]+))?))?(/([^?#]*))?(\?([^#]*))?(#(.*))?' 105 | # || | ||| | | | | | | | | | 106 | # |2 scheme | ||6 userinfo 7 host | 9 port | 11 rpath | 13 query | 15 fragment 107 | # 1 scheme: | |5 userinfo@ 8 :... 10 path 12 ?... 14 #... 108 | # | 4 authority 109 | # 3 //... 110 | local index=0 111 | case "$component" in 112 | scheme) 113 | index=2 114 | ;; 115 | authority) 116 | index=4 117 | ;; 118 | userinfo) 119 | index=6 120 | ;; 121 | host) 122 | index=7 123 | ;; 124 | port) 125 | index=9 126 | ;; 127 | path) 128 | index=10 129 | ;; 130 | query) 131 | index=13 132 | ;; 133 | fragment) 134 | index=14 135 | ;; 136 | *) 137 | stderr_print "unrecognized component $component" 138 | return 1 139 | ;; 140 | esac 141 | [[ "$uri" =~ $URI_REGEX ]] && echo "${BASH_REMATCH[${index}]}" 142 | } 143 | 144 | ######################## 145 | # Wait for a HTTP connection to succeed 146 | # Globals: 147 | # * 148 | # Arguments: 149 | # $1 - URL to wait for 150 | # $2 - Maximum amount of retries (optional) 151 | # $3 - Time between retries (optional) 152 | # Returns: 153 | # true if the HTTP connection succeeded, false otherwise 154 | ######################### 155 | wait_for_http_connection() { 156 | local url="${1:?missing url}" 157 | local retries="${2:-}" 158 | local sleep_time="${3:-}" 159 | if ! retry_while "debug_execute curl --silent ${url}" "$retries" "$sleep_time"; then 160 | error "Could not connect to ${url}" 161 | return 1 162 | fi 163 | } 164 | -------------------------------------------------------------------------------- /6.0/debian-10/prebuildfs/opt/bitnami/scripts/libpersistence.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Bitnami persistence library 4 | # Used for bringing persistence capabilities to applications that don't have clear separation of data and logic 5 | 6 | # shellcheck disable=SC1091 7 | 8 | # Load Generic Libraries 9 | . /opt/bitnami/scripts/libfs.sh 10 | . /opt/bitnami/scripts/libos.sh 11 | . /opt/bitnami/scripts/liblog.sh 12 | . /opt/bitnami/scripts/libversion.sh 13 | 14 | # Functions 15 | 16 | ######################## 17 | # Persist an application directory 18 | # Globals: 19 | # BITNAMI_ROOT_DIR 20 | # BITNAMI_VOLUME_DIR 21 | # Arguments: 22 | # $1 - App folder name 23 | # $2 - List of app files to persist 24 | # Returns: 25 | # true if all steps succeeded, false otherwise 26 | ######################### 27 | persist_app() { 28 | local -r app="${1:?missing app}" 29 | local -a files_to_restore 30 | read -r -a files_to_persist <<< "$(tr ',;:' ' ' <<< "$2")" 31 | local -r install_dir="${BITNAMI_ROOT_DIR}/${app}" 32 | local -r persist_dir="${BITNAMI_VOLUME_DIR}/${app}" 33 | # Persist the individual files 34 | if [[ "${#files_to_persist[@]}" -le 0 ]]; then 35 | warn "No files are configured to be persisted" 36 | return 37 | fi 38 | pushd "$install_dir" >/dev/null || exit 39 | local file_to_persist_relative file_to_persist_destination file_to_persist_destination_folder 40 | local -r tmp_file="/tmp/perms.acl" 41 | for file_to_persist in "${files_to_persist[@]}"; do 42 | if [[ ! -f "$file_to_persist" && ! -d "$file_to_persist" ]]; then 43 | error "Cannot persist '${file_to_persist}' because it does not exist" 44 | return 1 45 | fi 46 | file_to_persist_relative="$(relativize "$file_to_persist" "$install_dir")" 47 | file_to_persist_destination="${persist_dir}/${file_to_persist_relative}" 48 | file_to_persist_destination_folder="$(dirname "$file_to_persist_destination")" 49 | # Get original permissions for existing files, which will be applied later 50 | # Exclude the root directory with 'sed', to avoid issues when copying the entirety of it to a volume 51 | getfacl -R "$file_to_persist_relative" | sed -E '/# file: (\..+|[^.])/,$!d' > "$tmp_file" 52 | # Copy directories to the volume 53 | ensure_dir_exists "$file_to_persist_destination_folder" 54 | cp -Lr --preserve=links "$file_to_persist_relative" "$file_to_persist_destination_folder" 55 | # Restore permissions 56 | pushd "$persist_dir" >/dev/null || exit 57 | if am_i_root; then 58 | setfacl --restore="$tmp_file" 59 | else 60 | # When running as non-root, don't change ownership 61 | setfacl --restore=<(grep -E -v '^# (owner|group):' "$tmp_file") 62 | fi 63 | popd >/dev/null || exit 64 | done 65 | popd >/dev/null || exit 66 | rm -f "$tmp_file" 67 | # Install the persisted files into the installation directory, via symlinks 68 | restore_persisted_app "$@" 69 | } 70 | 71 | ######################## 72 | # Restore a persisted application directory 73 | # Globals: 74 | # BITNAMI_ROOT_DIR 75 | # BITNAMI_VOLUME_DIR 76 | # FORCE_MAJOR_UPGRADE 77 | # Arguments: 78 | # $1 - App folder name 79 | # $2 - List of app files to restore 80 | # Returns: 81 | # true if all steps succeeded, false otherwise 82 | ######################### 83 | restore_persisted_app() { 84 | local -r app="${1:?missing app}" 85 | local -a files_to_restore 86 | read -r -a files_to_restore <<< "$(tr ',;:' ' ' <<< "$2")" 87 | local -r install_dir="${BITNAMI_ROOT_DIR}/${app}" 88 | local -r persist_dir="${BITNAMI_VOLUME_DIR}/${app}" 89 | # Restore the individual persisted files 90 | if [[ "${#files_to_restore[@]}" -le 0 ]]; then 91 | warn "No persisted files are configured to be restored" 92 | return 93 | fi 94 | local file_to_restore_relative file_to_restore_origin file_to_restore_destination 95 | for file_to_restore in "${files_to_restore[@]}"; do 96 | file_to_restore_relative="$(relativize "$file_to_restore" "$install_dir")" 97 | # We use 'realpath --no-symlinks' to ensure that the case of '.' is covered and the directory is removed 98 | file_to_restore_origin="$(realpath --no-symlinks "${install_dir}/${file_to_restore_relative}")" 99 | file_to_restore_destination="$(realpath --no-symlinks "${persist_dir}/${file_to_restore_relative}")" 100 | rm -rf "$file_to_restore_origin" 101 | ln -sfn "$file_to_restore_destination" "$file_to_restore_origin" 102 | done 103 | } 104 | 105 | ######################## 106 | # Check if an application directory was already persisted 107 | # Globals: 108 | # BITNAMI_VOLUME_DIR 109 | # Arguments: 110 | # $1 - App folder name 111 | # Returns: 112 | # true if all steps succeeded, false otherwise 113 | ######################### 114 | is_app_initialized() { 115 | local -r app="${1:?missing app}" 116 | local -r persist_dir="${BITNAMI_VOLUME_DIR}/${app}" 117 | if ! is_mounted_dir_empty "$persist_dir"; then 118 | true 119 | else 120 | false 121 | fi 122 | } 123 | -------------------------------------------------------------------------------- /6.0/debian-10/prebuildfs/opt/bitnami/scripts/libservice.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for managing services 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/libvalidations.sh 9 | . /opt/bitnami/scripts/liblog.sh 10 | 11 | # Functions 12 | 13 | ######################## 14 | # Read the provided pid file and returns a PID 15 | # Arguments: 16 | # $1 - Pid file 17 | # Returns: 18 | # PID 19 | ######################### 20 | get_pid_from_file() { 21 | local pid_file="${1:?pid file is missing}" 22 | 23 | if [[ -f "$pid_file" ]]; then 24 | if [[ -n "$(< "$pid_file")" ]] && [[ "$(< "$pid_file")" -gt 0 ]]; then 25 | echo "$(< "$pid_file")" 26 | fi 27 | fi 28 | } 29 | 30 | ######################## 31 | # Check if a provided PID corresponds to a running service 32 | # Arguments: 33 | # $1 - PID 34 | # Returns: 35 | # Boolean 36 | ######################### 37 | is_service_running() { 38 | local pid="${1:?pid is missing}" 39 | 40 | kill -0 "$pid" 2>/dev/null 41 | } 42 | 43 | ######################## 44 | # Stop a service by sending a termination signal to its pid 45 | # Arguments: 46 | # $1 - Pid file 47 | # $2 - Signal number (optional) 48 | # Returns: 49 | # None 50 | ######################### 51 | stop_service_using_pid() { 52 | local pid_file="${1:?pid file is missing}" 53 | local signal="${2:-}" 54 | local pid 55 | 56 | pid="$(get_pid_from_file "$pid_file")" 57 | [[ -z "$pid" ]] || ! is_service_running "$pid" && return 58 | 59 | if [[ -n "$signal" ]]; then 60 | kill "-${signal}" "$pid" 61 | else 62 | kill "$pid" 63 | fi 64 | 65 | local counter=10 66 | while [[ "$counter" -ne 0 ]] && is_service_running "$pid"; do 67 | sleep 1 68 | counter=$((counter - 1)) 69 | done 70 | } 71 | 72 | ######################## 73 | # Start cron daemon 74 | # Arguments: 75 | # None 76 | # Returns: 77 | # true if started correctly, false otherwise 78 | ######################### 79 | cron_start() { 80 | if [[ -x "/usr/sbin/cron" ]]; then 81 | /usr/sbin/cron 82 | elif [[ -x "/usr/sbin/crond" ]]; then 83 | /usr/sbin/crond 84 | else 85 | false 86 | fi 87 | } 88 | 89 | ######################## 90 | # Generate a cron configuration file for a given service 91 | # Arguments: 92 | # $1 - Service name 93 | # $2 - Command 94 | # Flags: 95 | # --run-as - User to run as (default: root) 96 | # --schedule - Cron schedule configuration (default: * * * * *) 97 | # Returns: 98 | # None 99 | ######################### 100 | generate_cron_conf() { 101 | local service_name="${1:?service name is missing}" 102 | local cmd="${2:?command is missing}" 103 | local run_as="root" 104 | local schedule="* * * * *" 105 | local clean="true" 106 | 107 | local clean="true" 108 | 109 | # Parse optional CLI flags 110 | shift 2 111 | while [[ "$#" -gt 0 ]]; do 112 | case "$1" in 113 | --run-as) 114 | shift 115 | run_as="$1" 116 | ;; 117 | --schedule) 118 | shift 119 | schedule="$1" 120 | ;; 121 | --no-clean) 122 | clean="false" 123 | ;; 124 | *) 125 | echo "Invalid command line flag ${1}" >&2 126 | return 1 127 | ;; 128 | esac 129 | shift 130 | done 131 | 132 | mkdir -p /etc/cron.d 133 | if "$clean"; then 134 | echo "${schedule} ${run_as} ${cmd}" > /etc/cron.d/"$service_name" 135 | else 136 | echo "${schedule} ${run_as} ${cmd}" >> /etc/cron.d/"$service_name" 137 | fi 138 | } 139 | 140 | ######################## 141 | # Remove a cron configuration file for a given service 142 | # Arguments: 143 | # $1 - Service name 144 | # Returns: 145 | # None 146 | ######################### 147 | remove_cron_conf() { 148 | local service_name="${1:?service name is missing}" 149 | local cron_conf_dir="/etc/monit/conf.d" 150 | rm -f "${cron_conf_dir}/${service_name}" 151 | } 152 | 153 | ######################## 154 | # Generate a monit configuration file for a given service 155 | # Arguments: 156 | # $1 - Service name 157 | # $2 - Pid file 158 | # $3 - Start command 159 | # $4 - Stop command 160 | # Flags: 161 | # --disable - Whether to disable the monit configuration 162 | # Returns: 163 | # None 164 | ######################### 165 | generate_monit_conf() { 166 | local service_name="${1:?service name is missing}" 167 | local pid_file="${2:?pid file is missing}" 168 | local start_command="${3:?start command is missing}" 169 | local stop_command="${4:?stop command is missing}" 170 | local monit_conf_dir="/etc/monit/conf.d" 171 | local disabled="no" 172 | 173 | # Parse optional CLI flags 174 | shift 4 175 | while [[ "$#" -gt 0 ]]; do 176 | case "$1" in 177 | --disable) 178 | disabled="yes" 179 | ;; 180 | *) 181 | echo "Invalid command line flag ${1}" >&2 182 | return 1 183 | ;; 184 | esac 185 | shift 186 | done 187 | 188 | is_boolean_yes "$disabled" && conf_suffix=".disabled" 189 | mkdir -p "$monit_conf_dir" 190 | cat >"${monit_conf_dir}/${service_name}.conf${conf_suffix:-}" <&2 242 | return 1 243 | ;; 244 | esac 245 | shift 246 | done 247 | 248 | mkdir -p "$logrotate_conf_dir" 249 | cat <"${logrotate_conf_dir}/${service_name}" 250 | ${log_path} { 251 | ${period} 252 | rotate ${rotations} 253 | dateext 254 | compress 255 | copytruncate 256 | missingok 257 | $(indent "$extra" 2) 258 | } 259 | EOF 260 | } 261 | 262 | ######################## 263 | # Remove a logrotate configuration file 264 | # Arguments: 265 | # $1 - Service name 266 | # Returns: 267 | # None 268 | ######################### 269 | remove_logrotate_conf() { 270 | local service_name="${1:?service name is missing}" 271 | local logrotate_conf_dir="/etc/logrotate.d" 272 | rm -f "${logrotate_conf_dir}/${service_name}" 273 | } 274 | -------------------------------------------------------------------------------- /6.0/debian-10/prebuildfs/opt/bitnami/scripts/libvalidations.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Validation functions library 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/liblog.sh 9 | 10 | # Functions 11 | 12 | ######################## 13 | # Check if the provided argument is an integer 14 | # Arguments: 15 | # $1 - Value to check 16 | # Returns: 17 | # Boolean 18 | ######################### 19 | is_int() { 20 | local -r int="${1:?missing value}" 21 | if [[ "$int" =~ ^-?[0-9]+ ]]; then 22 | true 23 | else 24 | false 25 | fi 26 | } 27 | 28 | ######################## 29 | # Check if the provided argument is a positive integer 30 | # Arguments: 31 | # $1 - Value to check 32 | # Returns: 33 | # Boolean 34 | ######################### 35 | is_positive_int() { 36 | local -r int="${1:?missing value}" 37 | if is_int "$int" && (( "${int}" >= 0 )); then 38 | true 39 | else 40 | false 41 | fi 42 | } 43 | 44 | ######################## 45 | # Check if the provided argument is a boolean or is the string 'yes/true' 46 | # Arguments: 47 | # $1 - Value to check 48 | # Returns: 49 | # Boolean 50 | ######################### 51 | is_boolean_yes() { 52 | local -r bool="${1:-}" 53 | # comparison is performed without regard to the case of alphabetic characters 54 | shopt -s nocasematch 55 | if [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then 56 | true 57 | else 58 | false 59 | fi 60 | } 61 | 62 | ######################## 63 | # Check if the provided argument is a boolean yes/no value 64 | # Arguments: 65 | # $1 - Value to check 66 | # Returns: 67 | # Boolean 68 | ######################### 69 | is_yes_no_value() { 70 | local -r bool="${1:-}" 71 | if [[ "$bool" =~ ^(yes|no)$ ]]; then 72 | true 73 | else 74 | false 75 | fi 76 | } 77 | 78 | ######################## 79 | # Check if the provided argument is a boolean true/false value 80 | # Arguments: 81 | # $1 - Value to check 82 | # Returns: 83 | # Boolean 84 | ######################### 85 | is_true_false_value() { 86 | local -r bool="${1:-}" 87 | if [[ "$bool" =~ ^(true|false)$ ]]; then 88 | true 89 | else 90 | false 91 | fi 92 | } 93 | 94 | ######################## 95 | # Check if the provided argument is a boolean 1/0 value 96 | # Arguments: 97 | # $1 - Value to check 98 | # Returns: 99 | # Boolean 100 | ######################### 101 | is_1_0_value() { 102 | local -r bool="${1:-}" 103 | if [[ "$bool" =~ ^[10]$ ]]; then 104 | true 105 | else 106 | false 107 | fi 108 | } 109 | 110 | ######################## 111 | # Check if the provided argument is an empty string or not defined 112 | # Arguments: 113 | # $1 - Value to check 114 | # Returns: 115 | # Boolean 116 | ######################### 117 | is_empty_value() { 118 | local -r val="${1:-}" 119 | if [[ -z "$val" ]]; then 120 | true 121 | else 122 | false 123 | fi 124 | } 125 | 126 | ######################## 127 | # Validate if the provided argument is a valid port 128 | # Arguments: 129 | # $1 - Port to validate 130 | # Returns: 131 | # Boolean and error message 132 | ######################### 133 | validate_port() { 134 | local value 135 | local unprivileged=0 136 | 137 | # Parse flags 138 | while [[ "$#" -gt 0 ]]; do 139 | case "$1" in 140 | -unprivileged) 141 | unprivileged=1 142 | ;; 143 | --) 144 | shift 145 | break 146 | ;; 147 | -*) 148 | stderr_print "unrecognized flag $1" 149 | return 1 150 | ;; 151 | *) 152 | break 153 | ;; 154 | esac 155 | shift 156 | done 157 | 158 | if [[ "$#" -gt 1 ]]; then 159 | echo "too many arguments provided" 160 | return 2 161 | elif [[ "$#" -eq 0 ]]; then 162 | stderr_print "missing port argument" 163 | return 1 164 | else 165 | value=$1 166 | fi 167 | 168 | if [[ -z "$value" ]]; then 169 | echo "the value is empty" 170 | return 1 171 | else 172 | if ! is_int "$value"; then 173 | echo "value is not an integer" 174 | return 2 175 | elif [[ "$value" -lt 0 ]]; then 176 | echo "negative value provided" 177 | return 2 178 | elif [[ "$value" -gt 65535 ]]; then 179 | echo "requested port is greater than 65535" 180 | return 2 181 | elif [[ "$unprivileged" = 1 && "$value" -lt 1024 ]]; then 182 | echo "privileged port requested" 183 | return 3 184 | fi 185 | fi 186 | } 187 | 188 | ######################## 189 | # Validate if the provided argument is a valid IPv4 address 190 | # Arguments: 191 | # $1 - IP to validate 192 | # Returns: 193 | # Boolean 194 | ######################### 195 | validate_ipv4() { 196 | local ip="${1:?ip is missing}" 197 | local stat=1 198 | 199 | if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then 200 | read -r -a ip_array <<< "$(tr '.' ' ' <<< "$ip")" 201 | [[ ${ip_array[0]} -le 255 && ${ip_array[1]} -le 255 \ 202 | && ${ip_array[2]} -le 255 && ${ip_array[3]} -le 255 ]] 203 | stat=$? 204 | fi 205 | return $stat 206 | } 207 | 208 | ######################## 209 | # Validate a string format 210 | # Arguments: 211 | # $1 - String to validate 212 | # Returns: 213 | # Boolean 214 | ######################### 215 | validate_string() { 216 | local string 217 | local min_length=-1 218 | local max_length=-1 219 | 220 | # Parse flags 221 | while [ "$#" -gt 0 ]; do 222 | case "$1" in 223 | -min-length) 224 | shift 225 | min_length=${1:-} 226 | ;; 227 | -max-length) 228 | shift 229 | max_length=${1:-} 230 | ;; 231 | --) 232 | shift 233 | break 234 | ;; 235 | -*) 236 | stderr_print "unrecognized flag $1" 237 | return 1 238 | ;; 239 | *) 240 | break 241 | ;; 242 | esac 243 | shift 244 | done 245 | 246 | if [ "$#" -gt 1 ]; then 247 | stderr_print "too many arguments provided" 248 | return 2 249 | elif [ "$#" -eq 0 ]; then 250 | stderr_print "missing string" 251 | return 1 252 | else 253 | string=$1 254 | fi 255 | 256 | if [[ "$min_length" -ge 0 ]] && [[ "${#string}" -lt "$min_length" ]]; then 257 | echo "string length is less than $min_length" 258 | return 1 259 | fi 260 | if [[ "$max_length" -ge 0 ]] && [[ "${#string}" -gt "$max_length" ]]; then 261 | echo "string length is great than $max_length" 262 | return 1 263 | fi 264 | } 265 | -------------------------------------------------------------------------------- /6.0/debian-10/prebuildfs/opt/bitnami/scripts/libversion.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for managing versions strings 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/liblog.sh 9 | 10 | # Functions 11 | ######################## 12 | # Gets semantic version 13 | # Arguments: 14 | # $1 - version: string to extract major.minor.patch 15 | # $2 - section: 1 to extract major, 2 to extract minor, 3 to extract patch 16 | # Returns: 17 | # array with the major, minor and release 18 | ######################### 19 | get_sematic_version () { 20 | local version="${1:?version is required}" 21 | local section="${2:?section is required}" 22 | local -a version_sections 23 | 24 | #Regex to parse versions: x.y.z 25 | local -r regex='([0-9]+)(\.([0-9]+)(\.([0-9]+))?)?' 26 | 27 | if [[ "$version" =~ $regex ]]; then 28 | local i=1 29 | local j=1 30 | local n=${#BASH_REMATCH[*]} 31 | 32 | while [[ $i -lt $n ]]; do 33 | if [[ -n "${BASH_REMATCH[$i]}" ]] && [[ "${BASH_REMATCH[$i]:0:1}" != '.' ]]; then 34 | version_sections[$j]=${BASH_REMATCH[$i]} 35 | ((j++)) 36 | fi 37 | ((i++)) 38 | done 39 | 40 | local number_regex='^[0-9]+$' 41 | if [[ "$section" =~ $number_regex ]] && (( section > 0 )) && (( section <= 3 )); then 42 | echo "${version_sections[$section]}" 43 | return 44 | else 45 | stderr_print "Section allowed values are: 1, 2, and 3" 46 | return 1 47 | fi 48 | fi 49 | } 50 | -------------------------------------------------------------------------------- /6.0/debian-10/prebuildfs/usr/sbin/install_packages: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | export DEBIAN_FRONTEND=noninteractive 5 | n=0 6 | max=2 7 | until [ $n -gt $max ]; do 8 | set +e 9 | ( 10 | apt-get update -qq && 11 | apt-get install -y --no-install-recommends "$@" 12 | ) 13 | CODE=$? 14 | set -e 15 | if [ $CODE -eq 0 ]; then 16 | break 17 | fi 18 | if [ $n -eq $max ]; then 19 | exit $CODE 20 | fi 21 | echo "apt failed, retrying" 22 | n=$(($n + 1)) 23 | done 24 | rm -r /var/lib/apt/lists /var/cache/apt/archives 25 | -------------------------------------------------------------------------------- /6.0/debian-10/rootfs/opt/bitnami/scripts/librediscluster.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Bitnami Redis Cluster library 4 | 5 | # shellcheck disable=SC1090,SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/libfile.sh 9 | . /opt/bitnami/scripts/libfs.sh 10 | . /opt/bitnami/scripts/liblog.sh 11 | . /opt/bitnami/scripts/libnet.sh 12 | . /opt/bitnami/scripts/libos.sh 13 | . /opt/bitnami/scripts/libservice.sh 14 | . /opt/bitnami/scripts/libvalidations.sh 15 | . /opt/bitnami/scripts/libredis.sh 16 | 17 | # Functions 18 | 19 | ######################## 20 | # Validate settings in REDIS_* env vars. 21 | # Globals: 22 | # REDIS_* 23 | # Arguments: 24 | # None 25 | # Returns: 26 | # None 27 | ######################### 28 | redis_cluster_validate() { 29 | debug "Validating settings in REDIS_* env vars.." 30 | local error_code=0 31 | 32 | # Auxiliary functions 33 | print_validation_error() { 34 | error "$1" 35 | error_code=1 36 | } 37 | 38 | empty_password_enabled_warn() { 39 | warn "You set the environment variable ALLOW_EMPTY_PASSWORD=${ALLOW_EMPTY_PASSWORD}. For safety reasons, do not use this flag in a production environment." 40 | } 41 | empty_password_error() { 42 | print_validation_error "The $1 environment variable is empty or not set. Set the environment variable ALLOW_EMPTY_PASSWORD=yes to allow the container to be started with blank passwords. This is recommended only for development." 43 | } 44 | 45 | if is_boolean_yes "$ALLOW_EMPTY_PASSWORD"; then 46 | empty_password_enabled_warn 47 | else 48 | [[ -z "$REDIS_PASSWORD" ]] && empty_password_error REDIS_PASSWORD 49 | fi 50 | 51 | if ! is_boolean_yes "$REDIS_CLUSTER_DYNAMIC_IPS"; then 52 | [[ -z "$REDIS_CLUSTER_ANNOUNCE_IP" ]] && print_validation_error "To provide external access you need to provide the REDIS_CLUSTER_ANNOUNCE_IP env var" 53 | fi 54 | 55 | [[ -z "$REDIS_NODES" ]] && print_validation_error "REDIS_NODES is required" 56 | 57 | if [[ -z "$REDIS_PORT_NUMBER" ]]; then 58 | print_validation_error "REDIS_PORT_NUMBER cannot be empty" 59 | fi 60 | 61 | if is_boolean_yes "$REDIS_CLUSTER_CREATOR"; then 62 | [[ -z "$REDIS_CLUSTER_REPLICAS" ]] && print_validation_error "To create the cluster you need to provide the number of replicas to the cluster creator" 63 | fi 64 | 65 | if ((REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP < 0)); then 66 | print_validation_error "REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP must be greater or equal to zero" 67 | fi 68 | 69 | [[ "$error_code" -eq 0 ]] || exit "$error_code" 70 | } 71 | 72 | ######################## 73 | # Redis specific configuration to override the default one 74 | # Globals: 75 | # REDIS_* 76 | # Arguments: 77 | # None 78 | # Returns: 79 | # None 80 | ######################### 81 | redis_cluster_override_conf() { 82 | # Redis configuration to override 83 | if ! is_boolean_yes "$REDIS_CLUSTER_DYNAMIC_IPS"; then 84 | redis_conf_set cluster-announce-ip "$REDIS_CLUSTER_ANNOUNCE_IP" 85 | fi 86 | if is_boolean_yes "$REDIS_CLUSTER_DYNAMIC_IPS"; then 87 | # Always set the announce-ip to avoid issues when using proxies and traffic restrictions. 88 | redis_conf_set cluster-announce-ip "$(get_machine_ip)" 89 | fi 90 | if is_boolean_yes "$REDIS_TLS_ENABLED"; then 91 | redis_conf_set tls-cluster yes 92 | redis_conf_set tls-replication yes 93 | fi 94 | } 95 | 96 | ######################## 97 | # Ensure Redis is initialized 98 | # Globals: 99 | # REDIS_* 100 | # Arguments: 101 | # None 102 | # Returns: 103 | # None 104 | ######################### 105 | redis_cluster_initialize() { 106 | redis_configure_default 107 | redis_cluster_override_conf 108 | } 109 | 110 | ######################## 111 | # Creates the Redis cluster 112 | # Globals: 113 | # REDIS_* 114 | # Arguments: 115 | # - $@ Array with the hostnames 116 | # Returns: 117 | # None 118 | ######################### 119 | redis_cluster_create() { 120 | local nodes=("$@") 121 | local sockets=() 122 | local wait_command 123 | local create_command 124 | 125 | for node in "${nodes[@]}"; do 126 | read -r -a host_and_port <<< "$(to_host_and_port "$node")" 127 | wait_command="redis-cli -h ${host_and_port[0]} -p ${host_and_port[1]} ping" 128 | if is_boolean_yes "$REDIS_TLS_ENABLED"; then 129 | wait_command="${wait_command:0:-5} --tls --cert ${REDIS_TLS_CERT_FILE} --key ${REDIS_TLS_KEY_FILE} --cacert ${REDIS_TLS_CA_FILE} ping" 130 | fi 131 | while [[ $($wait_command) != 'PONG' ]]; do 132 | echo "Node $node not ready, waiting for all the nodes to be ready..." 133 | sleep 1 134 | done 135 | done 136 | 137 | echo "Waiting ${REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP}s before querying node ip addresses" 138 | sleep "${REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP}" 139 | 140 | for node in "${nodes[@]}"; do 141 | read -r -a host_and_port <<< "$(to_host_and_port "$node")" 142 | sockets+=("$(wait_for_dns_lookup "${host_and_port[0]}" "${REDIS_CLUSTER_DNS_LOOKUP_RETRIES}" "${REDIS_CLUSTER_DNS_LOOKUP_SLEEP}"):${host_and_port[1]}") 143 | done 144 | 145 | create_command="redis-cli --cluster create ${sockets[*]} --cluster-replicas ${REDIS_CLUSTER_REPLICAS} --cluster-yes" 146 | if is_boolean_yes "$REDIS_TLS_ENABLED"; then 147 | create_command="${create_command} --tls --cert ${REDIS_TLS_CERT_FILE} --key ${REDIS_TLS_KEY_FILE} --cacert ${REDIS_TLS_CA_FILE}" 148 | fi 149 | yes yes | $create_command || true 150 | if redis_cluster_check "${sockets[0]}"; then 151 | echo "Cluster correctly created" 152 | else 153 | echo "The cluster was already created, the nodes should have recovered it" 154 | fi 155 | } 156 | 157 | ######################### 158 | ## Checks if the cluster state is correct. 159 | ## Params: 160 | ## - $1: node where to check the cluster state 161 | ######################### 162 | redis_cluster_check() { 163 | if is_boolean_yes "$REDIS_TLS_ENABLED"; then 164 | local -r check=$(redis-cli --tls --cert "${REDIS_TLS_CERT_FILE}" --key "${REDIS_TLS_KEY_FILE}" --cacert "${REDIS_TLS_CA_FILE}" --cluster check "$1") 165 | else 166 | local -r check=$(redis-cli --cluster check "$1") 167 | fi 168 | if [[ $check =~ "All 16384 slots covered" ]]; then 169 | true 170 | else 171 | false 172 | fi 173 | } 174 | 175 | ######################### 176 | ## Recovers the cluster when using dynamic IPs by changing them in the nodes.conf 177 | # Globals: 178 | # REDIS_* 179 | # Arguments: 180 | # None 181 | # Returns: 182 | # None 183 | ######################### 184 | redis_cluster_update_ips() { 185 | read -ra nodes <<< "$(tr ',;' ' ' <<< "${REDIS_NODES}")" 186 | 187 | declare -A host_2_ip_array # Array to map hosts and IPs 188 | # Update the IPs when a number of nodes > quorum change their IPs 189 | if [[ ! -f "${REDIS_DATA_DIR}/nodes.sh" ]]; then 190 | # It is the first initialization so store the nodes 191 | for node in "${nodes[@]}"; do 192 | ip=$(wait_for_dns_lookup "$node" "$REDIS_DNS_RETRIES" 5) 193 | host_2_ip_array["$node"]="$ip" 194 | done 195 | echo "Storing map with hostnames and IPs" 196 | declare -p host_2_ip_array >"${REDIS_DATA_DIR}/nodes.sh" 197 | else 198 | # The cluster was already started 199 | . "${REDIS_DATA_DIR}/nodes.sh" 200 | # Update the IPs in the nodes.conf 201 | for node in "${nodes[@]}"; do 202 | newIP=$(wait_for_dns_lookup "$node" "$REDIS_DNS_RETRIES" 5) 203 | # The node can be new if we are updating the cluster, so catch the unbound variable error 204 | if [[ ${host_2_ip_array[$node]+true} ]]; then 205 | echo "Changing old IP ${host_2_ip_array[$node]} by the new one ${newIP}" 206 | nodesFile=$(sed "s/ ${host_2_ip_array[$node]}:/ $newIP:/g" "${REDIS_DATA_DIR}/nodes.conf") 207 | echo "$nodesFile" >"${REDIS_DATA_DIR}/nodes.conf" 208 | fi 209 | host_2_ip_array["$node"]="$newIP" 210 | done 211 | declare -p host_2_ip_array >"${REDIS_DATA_DIR}/nodes.sh" 212 | fi 213 | } 214 | 215 | ######################### 216 | ## Assigns a port to the host if one is not set using redis defaults 217 | # Globals: 218 | # REDIS_* 219 | # Arguments: 220 | # $1 - redis host or redis host and port 221 | # Returns: 222 | # - 2 element Array of host and port 223 | ######################### 224 | to_host_and_port() { 225 | local host="${1:?host is required}" 226 | read -r -a host_and_port <<< "$(echo "$host" | tr ":" " ")" 227 | 228 | if [ "${#host_and_port[*]}" -eq "1" ]; then 229 | if is_boolean_yes "$REDIS_TLS_ENABLED"; then 230 | host_and_port=("${host_and_port[0]}" "${REDIS_TLS_PORT}") 231 | else 232 | host_and_port=("${host_and_port[0]}" "${REDIS_PORT_NUMBER}") 233 | fi 234 | fi 235 | 236 | echo "${host_and_port[*]}" 237 | } 238 | -------------------------------------------------------------------------------- /6.0/debian-10/rootfs/opt/bitnami/scripts/redis-cluster-env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Environment configuration for redis-cluster 4 | 5 | # The values for all environment variables will be set in the below order of precedence 6 | # 1. Custom environment variables defined below after Bitnami defaults 7 | # 2. Constants defined in this file (environment variables with no default), i.e. BITNAMI_ROOT_DIR 8 | # 3. Environment variables overridden via external files using *_FILE variables (see below) 9 | # 4. Environment variables set externally (i.e. current Bash context/Dockerfile/userdata) 10 | 11 | # Load logging library 12 | . /opt/bitnami/scripts/liblog.sh 13 | 14 | export BITNAMI_ROOT_DIR="/opt/bitnami" 15 | export BITNAMI_VOLUME_DIR="/bitnami" 16 | 17 | # Logging configuration 18 | export MODULE="${MODULE:-redis-cluster}" 19 | export BITNAMI_DEBUG="${BITNAMI_DEBUG:-false}" 20 | 21 | # By setting an environment variable matching *_FILE to a file path, the prefixed environment 22 | # variable will be overridden with the value specified in that file 23 | redis_cluster_env_vars=( 24 | REDIS_DATA_DIR 25 | REDIS_DISABLE_COMMANDS 26 | REDIS_DATABASE 27 | REDIS_AOF_ENABLED 28 | REDIS_MASTER_HOST 29 | REDIS_MASTER_PORT_NUMBER 30 | REDIS_PORT_NUMBER 31 | REDIS_ALLOW_REMOTE_CONNECTIONS 32 | REDIS_REPLICATION_MODE 33 | REDIS_REPLICA_IP 34 | REDIS_REPLICA_PORT 35 | REDIS_EXTRA_FLAGS 36 | ALLOW_EMPTY_PASSWORD 37 | REDIS_PASSWORD 38 | REDIS_MASTER_PASSWORD 39 | REDIS_TLS_ENABLED 40 | REDIS_TLS_PORT_NUMBER 41 | REDIS_TLS_CERT_FILE 42 | REDIS_TLS_KEY_FILE 43 | REDIS_TLS_CA_FILE 44 | REDIS_TLS_DH_PARAMS_FILE 45 | REDIS_TLS_AUTH_CLIENTS 46 | REDIS_CLUSTER_CREATOR 47 | REDIS_CLUSTER_REPLICAS 48 | REDIS_CLUSTER_DYNAMIC_IPS 49 | REDIS_CLUSTER_ANNOUNCE_IP 50 | REDIS_DNS_RETRIES 51 | REDIS_NODES 52 | REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP 53 | REDIS_CLUSTER_DNS_LOOKUP_RETRIES 54 | REDIS_CLUSTER_DNS_LOOKUP_SLEEP 55 | REDIS_TLS_PORT 56 | ) 57 | for env_var in "${redis_cluster_env_vars[@]}"; do 58 | file_env_var="${env_var}_FILE" 59 | if [[ -n "${!file_env_var:-}" ]]; then 60 | if [[ -r "${!file_env_var:-}" ]]; then 61 | export "${env_var}=$(< "${!file_env_var}")" 62 | unset "${file_env_var}" 63 | else 64 | warn "Skipping export of '${env_var}'. '${!file_env_var:-}' is not readable." 65 | fi 66 | fi 67 | done 68 | unset redis_cluster_env_vars 69 | 70 | # Paths 71 | export REDIS_VOLUME_DIR="/bitnami/redis" 72 | export REDIS_BASE_DIR="${BITNAMI_ROOT_DIR}/redis" 73 | export REDIS_CONF_DIR="${REDIS_BASE_DIR}/etc" 74 | export REDIS_DATA_DIR="${REDIS_DATA_DIR:-${REDIS_VOLUME_DIR}/data}" 75 | export REDIS_MOUNTED_CONF_DIR="${REDIS_BASE_DIR}/mounted-etc" 76 | export REDIS_CONF_FILE="${REDIS_CONF_DIR}/redis.conf" 77 | export REDIS_LOG_DIR="${REDIS_BASE_DIR}/logs" 78 | export REDIS_LOG_FILE="${REDIS_LOG_DIR}/redis.log" 79 | export REDIS_TMP_DIR="${REDIS_BASE_DIR}/tmp" 80 | export REDIS_PID_FILE="${REDIS_TMP_DIR}/redis.pid" 81 | export REDIS_BIN_DIR="${REDIS_BASE_DIR}/bin" 82 | export PATH="${REDIS_BIN_DIR}:${BITNAMI_ROOT_DIR}/common/bin:${PATH}" 83 | 84 | # System users (when running with a privileged user) 85 | export REDIS_DAEMON_USER="redis" 86 | export REDIS_DAEMON_GROUP="redis" 87 | 88 | # Redis settings 89 | export REDIS_DISABLE_COMMANDS="${REDIS_DISABLE_COMMANDS:-}" 90 | export REDIS_DATABASE="${REDIS_DATABASE:-redis}" 91 | export REDIS_AOF_ENABLED="${REDIS_AOF_ENABLED:-yes}" 92 | export REDIS_MASTER_HOST="${REDIS_MASTER_HOST:-}" 93 | export REDIS_MASTER_PORT_NUMBER="${REDIS_MASTER_PORT_NUMBER:-6379}" 94 | export REDIS_DEFAULT_PORT_NUMBER="6379" # only used at build time 95 | export REDIS_PORT_NUMBER="${REDIS_PORT_NUMBER:-$REDIS_DEFAULT_PORT_NUMBER}" 96 | export REDIS_ALLOW_REMOTE_CONNECTIONS="${REDIS_ALLOW_REMOTE_CONNECTIONS:-yes}" 97 | export REDIS_REPLICATION_MODE="${REDIS_REPLICATION_MODE:-}" 98 | export REDIS_REPLICA_IP="${REDIS_REPLICA_IP:-}" 99 | export REDIS_REPLICA_PORT="${REDIS_REPLICA_PORT:-}" 100 | export REDIS_EXTRA_FLAGS="${REDIS_EXTRA_FLAGS:-}" 101 | export ALLOW_EMPTY_PASSWORD="${ALLOW_EMPTY_PASSWORD:-no}" 102 | export REDIS_PASSWORD="${REDIS_PASSWORD:-}" 103 | export REDIS_MASTER_PASSWORD="${REDIS_MASTER_PASSWORD:-}" 104 | 105 | # TLS settings 106 | export REDIS_TLS_ENABLED="${REDIS_TLS_ENABLED:-no}" 107 | REDIS_TLS_PORT_NUMBER="${REDIS_TLS_PORT_NUMBER:-"${REDIS_TLS_PORT:-}"}" 108 | export REDIS_TLS_PORT_NUMBER="${REDIS_TLS_PORT_NUMBER:-6379}" 109 | export REDIS_TLS_CERT_FILE="${REDIS_TLS_CERT_FILE:-}" 110 | export REDIS_TLS_KEY_FILE="${REDIS_TLS_KEY_FILE:-}" 111 | export REDIS_TLS_CA_FILE="${REDIS_TLS_CA_FILE:-}" 112 | export REDIS_TLS_DH_PARAMS_FILE="${REDIS_TLS_DH_PARAMS_FILE:-}" 113 | export REDIS_TLS_AUTH_CLIENTS="${REDIS_TLS_AUTH_CLIENTS:-yes}" 114 | 115 | # Redis Cluster settings 116 | export REDIS_CLUSTER_CREATOR="${REDIS_CLUSTER_CREATOR:-no}" 117 | export REDIS_CLUSTER_REPLICAS="${REDIS_CLUSTER_REPLICAS:-1}" 118 | export REDIS_CLUSTER_DYNAMIC_IPS="${REDIS_CLUSTER_DYNAMIC_IPS:-yes}" 119 | export REDIS_CLUSTER_ANNOUNCE_IP="${REDIS_CLUSTER_ANNOUNCE_IP:-}" 120 | export REDIS_DNS_RETRIES="${REDIS_DNS_RETRIES:-120}" 121 | export REDIS_NODES="${REDIS_NODES:-}" 122 | export REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP="${REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP:-0}" 123 | export REDIS_CLUSTER_DNS_LOOKUP_RETRIES="${REDIS_CLUSTER_DNS_LOOKUP_RETRIES:-1}" 124 | export REDIS_CLUSTER_DNS_LOOKUP_SLEEP="${REDIS_CLUSTER_DNS_LOOKUP_SLEEP:-1}" 125 | 126 | # Custom environment variables may be defined below 127 | -------------------------------------------------------------------------------- /6.0/debian-10/rootfs/opt/bitnami/scripts/redis-cluster/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # shellcheck disable=SC1091 4 | 5 | set -o errexit 6 | set -o nounset 7 | set -o pipefail 8 | # set -o xtrace # Uncomment this line for debugging purpose 9 | 10 | # Load Redis environment variables 11 | . /opt/bitnami/scripts/redis-cluster-env.sh 12 | 13 | # Load libraries 14 | . /opt/bitnami/scripts/libbitnami.sh 15 | . /opt/bitnami/scripts/librediscluster.sh 16 | 17 | print_welcome_page 18 | 19 | if [[ "$*" = *"/run.sh"* ]]; then 20 | info "** Starting Redis setup **" 21 | /opt/bitnami/scripts/redis-cluster/setup.sh 22 | info "** Redis setup finished! **" 23 | fi 24 | 25 | echo "" 26 | exec "$@" 27 | -------------------------------------------------------------------------------- /6.0/debian-10/rootfs/opt/bitnami/scripts/redis-cluster/postunpack.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # shellcheck disable=SC1091 4 | 5 | set -o errexit 6 | set -o nounset 7 | set -o pipefail 8 | # set -o xtrace # Uncomment this line for debugging purpose 9 | 10 | # Load Redis environment variables 11 | . /opt/bitnami/scripts/redis-cluster-env.sh 12 | 13 | # Load libraries 14 | . /opt/bitnami/scripts/librediscluster.sh 15 | . /opt/bitnami/scripts/libfs.sh 16 | 17 | for dir in "$REDIS_VOLUME_DIR" "$REDIS_DATA_DIR" "$REDIS_BASE_DIR" "$REDIS_CONF_DIR"; do 18 | ensure_dir_exists "$dir" 19 | done 20 | 21 | cp "${REDIS_BASE_DIR}/etc/redis-default.conf" "$REDIS_CONF_FILE" 22 | 23 | info "Setting Redis config file..." 24 | redis_conf_set port "$REDIS_DEFAULT_PORT_NUMBER" 25 | redis_conf_set dir "$REDIS_DATA_DIR" 26 | redis_conf_set pidfile "$REDIS_PID_FILE" 27 | redis_conf_set daemonize no 28 | redis_conf_set cluster-enabled yes 29 | redis_conf_set cluster-config-file "${REDIS_DATA_DIR}/nodes.conf" 30 | 31 | chmod -R g+rwX "$REDIS_BASE_DIR" /bitnami/redis 32 | -------------------------------------------------------------------------------- /6.0/debian-10/rootfs/opt/bitnami/scripts/redis-cluster/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # shellcheck disable=SC1091 4 | 5 | set -o errexit 6 | set -o nounset 7 | set -o pipefail 8 | # set -o xtrace # Uncomment this line for debugging purpose 9 | 10 | # Enable job control 11 | # ref https://www.gnu.org/software/bash/manual/bash.html#The-Set-Builtin 12 | set -m 13 | 14 | # Load Redis environment variables 15 | . /opt/bitnami/scripts/redis-cluster-env.sh 16 | 17 | # Load libraries 18 | . /opt/bitnami/scripts/libos.sh 19 | . /opt/bitnami/scripts/librediscluster.sh 20 | 21 | read -ra nodes <<< "$(tr ',;' ' ' <<< "${REDIS_NODES}")" 22 | 23 | ARGS=("--port" "$REDIS_PORT_NUMBER") 24 | ARGS+=("--include" "${REDIS_BASE_DIR}/etc/redis.conf") 25 | 26 | if ! is_boolean_yes "$ALLOW_EMPTY_PASSWORD"; then 27 | ARGS+=("--requirepass" "$REDIS_PASSWORD") 28 | ARGS+=("--masterauth" "$REDIS_PASSWORD") 29 | else 30 | ARGS+=("--protected-mode" "no") 31 | fi 32 | 33 | ARGS+=("$@") 34 | 35 | if is_boolean_yes "$REDIS_CLUSTER_CREATOR" && ! [[ -f "${REDIS_DATA_DIR}/nodes.conf" ]]; then 36 | # Start Redis in background 37 | if am_i_root; then 38 | gosu "$REDIS_DAEMON_USER" redis-server "${ARGS[@]}" & 39 | else 40 | redis-server "${ARGS[@]}" & 41 | fi 42 | # Create the cluster 43 | redis_cluster_create "${nodes[@]}" 44 | # Bring redis process to foreground 45 | fg 46 | else 47 | if am_i_root; then 48 | exec gosu "$REDIS_DAEMON_USER" redis-server "${ARGS[@]}" 49 | else 50 | exec redis-server "${ARGS[@]}" 51 | fi 52 | fi 53 | -------------------------------------------------------------------------------- /6.0/debian-10/rootfs/opt/bitnami/scripts/redis-cluster/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # shellcheck disable=SC1091 4 | 5 | set -o errexit 6 | set -o nounset 7 | set -o pipefail 8 | # set -o xtrace # Uncomment this line for debugging purpose 9 | 10 | # Load Redis environment variables 11 | . /opt/bitnami/scripts/redis-cluster-env.sh 12 | 13 | # Load libraries 14 | . /opt/bitnami/scripts/libos.sh 15 | . /opt/bitnami/scripts/libfs.sh 16 | . /opt/bitnami/scripts/librediscluster.sh 17 | 18 | # Ensure Redis environment variables settings are valid 19 | redis_cluster_validate 20 | # Ensure Redis is stopped when this script ends 21 | trap "redis_stop" EXIT 22 | am_i_root && ensure_user_exists "$REDIS_DAEMON_USER" --group "$REDIS_DAEMON_GROUP" 23 | 24 | # Ensure Redis is initialized 25 | redis_cluster_initialize 26 | 27 | if is_boolean_yes "$REDIS_CLUSTER_DYNAMIC_IPS"; then 28 | redis_cluster_update_ips 29 | fi 30 | -------------------------------------------------------------------------------- /6.2/debian-10/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.io/bitnami/minideb:buster 2 | LABEL maintainer "Bitnami " 3 | 4 | ENV HOME="/" \ 5 | OS_ARCH="amd64" \ 6 | OS_FLAVOUR="debian-10" \ 7 | OS_NAME="linux" 8 | 9 | COPY prebuildfs / 10 | # Install required system packages and dependencies 11 | RUN install_packages acl ca-certificates curl gzip libc6 libssl1.1 procps tar 12 | RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "redis" "6.2.6-1" --checksum 172caf7ebf69ba8105ec7f05150a7e341fdf117c9650cbcb9191919a523ada86 13 | RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "gosu" "1.14.0-0" --checksum 3e6fc37ca073b10a73a804d39c2f0c028947a1a596382a4f8ebe43dfbaa3a25e 14 | RUN chmod g+rwX /opt/bitnami 15 | 16 | COPY rootfs / 17 | RUN /opt/bitnami/scripts/redis-cluster/postunpack.sh 18 | ENV BITNAMI_APP_NAME="redis-cluster" \ 19 | BITNAMI_IMAGE_VERSION="6.2.6-debian-10-r15" \ 20 | PATH="/opt/bitnami/redis/bin:/opt/bitnami/common/bin:$PATH" 21 | 22 | EXPOSE 6379 23 | 24 | USER 1001 25 | ENTRYPOINT [ "/opt/bitnami/scripts/redis-cluster/entrypoint.sh" ] 26 | CMD [ "/opt/bitnami/scripts/redis-cluster/run.sh" ] 27 | -------------------------------------------------------------------------------- /6.2/debian-10/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | redis-node-0: 4 | image: docker.io/bitnami/redis-cluster:6.2 5 | volumes: 6 | - redis-cluster_data-0:/bitnami/redis/data 7 | environment: 8 | - 'REDIS_PASSWORD=bitnami' 9 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 10 | 11 | redis-node-1: 12 | image: docker.io/bitnami/redis-cluster:6.2 13 | volumes: 14 | - redis-cluster_data-1:/bitnami/redis/data 15 | environment: 16 | - 'REDIS_PASSWORD=bitnami' 17 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 18 | 19 | redis-node-2: 20 | image: docker.io/bitnami/redis-cluster:6.2 21 | volumes: 22 | - redis-cluster_data-2:/bitnami/redis/data 23 | environment: 24 | - 'REDIS_PASSWORD=bitnami' 25 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 26 | 27 | redis-node-3: 28 | image: docker.io/bitnami/redis-cluster:6.2 29 | volumes: 30 | - redis-cluster_data-3:/bitnami/redis/data 31 | environment: 32 | - 'REDIS_PASSWORD=bitnami' 33 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 34 | 35 | redis-node-4: 36 | image: docker.io/bitnami/redis-cluster:6.2 37 | volumes: 38 | - redis-cluster_data-4:/bitnami/redis/data 39 | environment: 40 | - 'REDIS_PASSWORD=bitnami' 41 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 42 | 43 | redis-node-5: 44 | image: docker.io/bitnami/redis-cluster:6.2 45 | volumes: 46 | - redis-cluster_data-5:/bitnami/redis/data 47 | depends_on: 48 | - redis-node-0 49 | - redis-node-1 50 | - redis-node-2 51 | - redis-node-3 52 | - redis-node-4 53 | environment: 54 | - 'REDIS_PASSWORD=bitnami' 55 | - 'REDISCLI_AUTH=bitnami' 56 | - 'REDIS_CLUSTER_REPLICAS=1' 57 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 58 | - 'REDIS_CLUSTER_CREATOR=yes' 59 | 60 | volumes: 61 | redis-cluster_data-0: 62 | driver: local 63 | redis-cluster_data-1: 64 | driver: local 65 | redis-cluster_data-2: 66 | driver: local 67 | redis-cluster_data-3: 68 | driver: local 69 | redis-cluster_data-4: 70 | driver: local 71 | redis-cluster_data-5: 72 | driver: local 73 | -------------------------------------------------------------------------------- /6.2/debian-10/prebuildfs/opt/bitnami/.bitnami_components.json: -------------------------------------------------------------------------------- 1 | { 2 | "gosu": { 3 | "arch": "amd64", 4 | "digest": "3e6fc37ca073b10a73a804d39c2f0c028947a1a596382a4f8ebe43dfbaa3a25e", 5 | "distro": "debian-10", 6 | "type": "NAMI", 7 | "version": "1.14.0-0" 8 | }, 9 | "redis": { 10 | "arch": "amd64", 11 | "digest": "172caf7ebf69ba8105ec7f05150a7e341fdf117c9650cbcb9191919a523ada86", 12 | "distro": "debian-10", 13 | "type": "NAMI", 14 | "version": "6.2.6-1" 15 | } 16 | } -------------------------------------------------------------------------------- /6.2/debian-10/prebuildfs/opt/bitnami/licenses/licenses.txt: -------------------------------------------------------------------------------- 1 | Bitnami containers ship with software bundles. You can find the licenses under: 2 | /opt/bitnami/nami/COPYING 3 | /opt/bitnami/[name-of-bundle]/licenses/[bundle-version].txt 4 | -------------------------------------------------------------------------------- /6.2/debian-10/prebuildfs/opt/bitnami/scripts/libbitnami.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Bitnami custom library 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/liblog.sh 9 | 10 | # Constants 11 | BOLD='\033[1m' 12 | 13 | # Functions 14 | 15 | ######################## 16 | # Print the welcome page 17 | # Globals: 18 | # DISABLE_WELCOME_MESSAGE 19 | # BITNAMI_APP_NAME 20 | # Arguments: 21 | # None 22 | # Returns: 23 | # None 24 | ######################### 25 | print_welcome_page() { 26 | if [[ -z "${DISABLE_WELCOME_MESSAGE:-}" ]]; then 27 | if [[ -n "$BITNAMI_APP_NAME" ]]; then 28 | print_image_welcome_page 29 | fi 30 | fi 31 | } 32 | 33 | ######################## 34 | # Print the welcome page for a Bitnami Docker image 35 | # Globals: 36 | # BITNAMI_APP_NAME 37 | # Arguments: 38 | # None 39 | # Returns: 40 | # None 41 | ######################### 42 | print_image_welcome_page() { 43 | local github_url="https://github.com/bitnami/bitnami-docker-${BITNAMI_APP_NAME}" 44 | 45 | log "" 46 | log "${BOLD}Welcome to the Bitnami ${BITNAMI_APP_NAME} container${RESET}" 47 | log "Subscribe to project updates by watching ${BOLD}${github_url}${RESET}" 48 | log "Submit issues and feature requests at ${BOLD}${github_url}/issues${RESET}" 49 | log "" 50 | } 51 | 52 | -------------------------------------------------------------------------------- /6.2/debian-10/prebuildfs/opt/bitnami/scripts/libcomponent.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for managing Bitnami components 4 | 5 | # Constants 6 | CACHE_ROOT="/tmp/bitnami/pkg/cache" 7 | DOWNLOAD_URL="https://downloads.bitnami.com/files/stacksmith" 8 | 9 | # Functions 10 | 11 | ######################## 12 | # Download and unpack a Bitnami package 13 | # Globals: 14 | # OS_NAME 15 | # OS_ARCH 16 | # OS_FLAVOUR 17 | # Arguments: 18 | # $1 - component's name 19 | # $2 - component's version 20 | # Returns: 21 | # None 22 | ######################### 23 | component_unpack() { 24 | local name="${1:?name is required}" 25 | local version="${2:?version is required}" 26 | local base_name="${name}-${version}-${OS_NAME}-${OS_ARCH}-${OS_FLAVOUR}" 27 | local package_sha256="" 28 | local directory="/opt/bitnami" 29 | 30 | # Validate arguments 31 | shift 2 32 | while [ "$#" -gt 0 ]; do 33 | case "$1" in 34 | -c|--checksum) 35 | shift 36 | package_sha256="${1:?missing package checksum}" 37 | ;; 38 | *) 39 | echo "Invalid command line flag $1" >&2 40 | return 1 41 | ;; 42 | esac 43 | shift 44 | done 45 | 46 | echo "Downloading $base_name package" 47 | if [ -f "${CACHE_ROOT}/${base_name}.tar.gz" ]; then 48 | echo "${CACHE_ROOT}/${base_name}.tar.gz already exists, skipping download." 49 | cp "${CACHE_ROOT}/${base_name}.tar.gz" . 50 | rm "${CACHE_ROOT}/${base_name}.tar.gz" 51 | if [ -f "${CACHE_ROOT}/${base_name}.tar.gz.sha256" ]; then 52 | echo "Using the local sha256 from ${CACHE_ROOT}/${base_name}.tar.gz.sha256" 53 | package_sha256="$(< "${CACHE_ROOT}/${base_name}.tar.gz.sha256")" 54 | rm "${CACHE_ROOT}/${base_name}.tar.gz.sha256" 55 | fi 56 | else 57 | curl --remote-name --silent "${DOWNLOAD_URL}/${base_name}.tar.gz" 58 | fi 59 | if [ -n "$package_sha256" ]; then 60 | echo "Verifying package integrity" 61 | echo "$package_sha256 ${base_name}.tar.gz" | sha256sum --check - 62 | fi 63 | tar --directory "${directory}" --extract --gunzip --file "${base_name}.tar.gz" --no-same-owner --strip-components=2 "${base_name}/files/" 64 | rm "${base_name}.tar.gz" 65 | } 66 | -------------------------------------------------------------------------------- /6.2/debian-10/prebuildfs/opt/bitnami/scripts/libfile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for managing files 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/libos.sh 9 | 10 | # Functions 11 | 12 | ######################## 13 | # Replace a regex-matching string in a file 14 | # Arguments: 15 | # $1 - filename 16 | # $2 - match regex 17 | # $3 - substitute regex 18 | # $4 - use POSIX regex. Default: true 19 | # Returns: 20 | # None 21 | ######################### 22 | replace_in_file() { 23 | local filename="${1:?filename is required}" 24 | local match_regex="${2:?match regex is required}" 25 | local substitute_regex="${3:?substitute regex is required}" 26 | local posix_regex=${4:-true} 27 | 28 | local result 29 | 30 | # We should avoid using 'sed in-place' substitutions 31 | # 1) They are not compatible with files mounted from ConfigMap(s) 32 | # 2) We found incompatibility issues with Debian10 and "in-place" substitutions 33 | local -r del=$'\001' # Use a non-printable character as a 'sed' delimiter to avoid issues 34 | if [[ $posix_regex = true ]]; then 35 | result="$(sed -E "s${del}${match_regex}${del}${substitute_regex}${del}g" "$filename")" 36 | else 37 | result="$(sed "s${del}${match_regex}${del}${substitute_regex}${del}g" "$filename")" 38 | fi 39 | echo "$result" > "$filename" 40 | } 41 | 42 | ######################## 43 | # Replace a regex-matching multiline string in a file 44 | # Arguments: 45 | # $1 - filename 46 | # $2 - match regex 47 | # $3 - substitute regex 48 | # Returns: 49 | # None 50 | ######################### 51 | replace_in_file_multiline() { 52 | local filename="${1:?filename is required}" 53 | local match_regex="${2:?match regex is required}" 54 | local substitute_regex="${3:?substitute regex is required}" 55 | 56 | local result 57 | local -r del=$'\001' # Use a non-printable character as a 'sed' delimiter to avoid issues 58 | result="$(perl -pe "BEGIN{undef $/;} s${del}${match_regex}${del}${substitute_regex}${del}sg" "$filename")" 59 | echo "$result" > "$filename" 60 | } 61 | 62 | ######################## 63 | # Remove a line in a file based on a regex 64 | # Arguments: 65 | # $1 - filename 66 | # $2 - match regex 67 | # $3 - use POSIX regex. Default: true 68 | # Returns: 69 | # None 70 | ######################### 71 | remove_in_file() { 72 | local filename="${1:?filename is required}" 73 | local match_regex="${2:?match regex is required}" 74 | local posix_regex=${3:-true} 75 | local result 76 | 77 | # We should avoid using 'sed in-place' substitutions 78 | # 1) They are not compatible with files mounted from ConfigMap(s) 79 | # 2) We found incompatibility issues with Debian10 and "in-place" substitutions 80 | if [[ $posix_regex = true ]]; then 81 | result="$(sed -E "/$match_regex/d" "$filename")" 82 | else 83 | result="$(sed "/$match_regex/d" "$filename")" 84 | fi 85 | echo "$result" > "$filename" 86 | } 87 | 88 | ######################## 89 | # Appends text after the last line matching a pattern 90 | # Arguments: 91 | # $1 - file 92 | # $2 - match regex 93 | # $3 - contents to add 94 | # Returns: 95 | # None 96 | ######################### 97 | append_file_after_last_match() { 98 | local file="${1:?missing file}" 99 | local match_regex="${2:?missing pattern}" 100 | local value="${3:?missing value}" 101 | 102 | # We read the file in reverse, replace the first match (0,/pattern/s) and then reverse the results again 103 | result="$(tac "$file" | sed -E "0,/($match_regex)/s||${value}\n\1|" | tac)" 104 | echo "$result" > "$file" 105 | } 106 | 107 | ######################## 108 | # Wait until certain entry is present in a log file 109 | # Arguments: 110 | # $1 - entry to look for 111 | # $2 - log file 112 | # $3 - max retries. Default: 12 113 | # $4 - sleep between retries (in seconds). Default: 5 114 | # Returns: 115 | # Boolean 116 | ######################### 117 | wait_for_log_entry() { 118 | local -r entry="${1:-missing entry}" 119 | local -r log_file="${2:-missing log file}" 120 | local -r retries="${3:-12}" 121 | local -r interval_time="${4:-5}" 122 | local attempt=0 123 | 124 | check_log_file_for_entry() { 125 | if ! grep -qE "$entry" "$log_file"; then 126 | debug "Entry \"${entry}\" still not present in ${log_file} (attempt $((++attempt))/${retries})" 127 | return 1 128 | fi 129 | } 130 | debug "Checking that ${log_file} log file contains entry \"${entry}\"" 131 | if retry_while check_log_file_for_entry "$retries" "$interval_time"; then 132 | debug "Found entry \"${entry}\" in ${log_file}" 133 | true 134 | else 135 | error "Could not find entry \"${entry}\" in ${log_file} after ${retries} retries" 136 | debug_execute cat "$log_file" 137 | return 1 138 | fi 139 | } 140 | -------------------------------------------------------------------------------- /6.2/debian-10/prebuildfs/opt/bitnami/scripts/libfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for file system actions 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/liblog.sh 9 | 10 | # Functions 11 | 12 | ######################## 13 | # Ensure a file/directory is owned (user and group) but the given user 14 | # Arguments: 15 | # $1 - filepath 16 | # $2 - owner 17 | # Returns: 18 | # None 19 | ######################### 20 | owned_by() { 21 | local path="${1:?path is missing}" 22 | local owner="${2:?owner is missing}" 23 | 24 | chown "$owner":"$owner" "$path" 25 | } 26 | 27 | ######################## 28 | # Ensure a directory exists and, optionally, is owned by the given user 29 | # Arguments: 30 | # $1 - directory 31 | # $2 - owner 32 | # Returns: 33 | # None 34 | ######################### 35 | ensure_dir_exists() { 36 | local dir="${1:?directory is missing}" 37 | local owner="${2:-}" 38 | 39 | mkdir -p "${dir}" 40 | if [[ -n $owner ]]; then 41 | owned_by "$dir" "$owner" 42 | fi 43 | } 44 | 45 | ######################## 46 | # Checks whether a directory is empty or not 47 | # arguments: 48 | # $1 - directory 49 | # returns: 50 | # boolean 51 | ######################### 52 | is_dir_empty() { 53 | local dir="${1:?missing directory}" 54 | 55 | if [[ ! -e "$dir" ]] || [[ -z "$(ls -A "$dir")" ]]; then 56 | true 57 | else 58 | false 59 | fi 60 | } 61 | 62 | ######################## 63 | # Checks whether a mounted directory is empty or not 64 | # arguments: 65 | # $1 - directory 66 | # returns: 67 | # boolean 68 | ######################### 69 | is_mounted_dir_empty() { 70 | local dir="${1:?missing directory}" 71 | 72 | if is_dir_empty "$dir" || find "$dir" -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" -exec false {} +; then 73 | true 74 | else 75 | false 76 | fi 77 | } 78 | 79 | ######################## 80 | # Checks whether a file can be written to or not 81 | # arguments: 82 | # $1 - file 83 | # returns: 84 | # boolean 85 | ######################### 86 | is_file_writable() { 87 | local file="${1:?missing file}" 88 | local dir 89 | dir="$(dirname "$file")" 90 | 91 | if [[ ( -f "$file" && -w "$file" ) || ( ! -f "$file" && -d "$dir" && -w "$dir" ) ]]; then 92 | true 93 | else 94 | false 95 | fi 96 | } 97 | 98 | ######################## 99 | # Relativize a path 100 | # arguments: 101 | # $1 - path 102 | # $2 - base 103 | # returns: 104 | # None 105 | ######################### 106 | relativize() { 107 | local -r path="${1:?missing path}" 108 | local -r base="${2:?missing base}" 109 | pushd "$base" >/dev/null || exit 110 | realpath -q --no-symlinks --relative-base="$base" "$path" | sed -e 's|^/$|.|' -e 's|^/||' 111 | popd >/dev/null || exit 112 | } 113 | 114 | ######################## 115 | # Configure permisions and ownership recursively 116 | # Globals: 117 | # None 118 | # Arguments: 119 | # $1 - paths (as a string). 120 | # Flags: 121 | # -f|--file-mode - mode for directories. 122 | # -d|--dir-mode - mode for files. 123 | # -u|--user - user 124 | # -g|--group - group 125 | # Returns: 126 | # None 127 | ######################### 128 | configure_permissions_ownership() { 129 | local -r paths="${1:?paths is missing}" 130 | local dir_mode="" 131 | local file_mode="" 132 | local user="" 133 | local group="" 134 | 135 | # Validate arguments 136 | shift 1 137 | while [ "$#" -gt 0 ]; do 138 | case "$1" in 139 | -f|--file-mode) 140 | shift 141 | file_mode="${1:?missing mode for files}" 142 | ;; 143 | -d|--dir-mode) 144 | shift 145 | dir_mode="${1:?missing mode for directories}" 146 | ;; 147 | -u|--user) 148 | shift 149 | user="${1:?missing user}" 150 | ;; 151 | -g|--group) 152 | shift 153 | group="${1:?missing group}" 154 | ;; 155 | *) 156 | echo "Invalid command line flag $1" >&2 157 | return 1 158 | ;; 159 | esac 160 | shift 161 | done 162 | 163 | read -r -a filepaths <<< "$paths" 164 | for p in "${filepaths[@]}"; do 165 | if [[ -e "$p" ]]; then 166 | if [[ -n $dir_mode ]]; then 167 | find -L "$p" -type d -exec chmod "$dir_mode" {} \; 168 | fi 169 | if [[ -n $file_mode ]]; then 170 | find -L "$p" -type f -exec chmod "$file_mode" {} \; 171 | fi 172 | if [[ -n $user ]] && [[ -n $group ]]; then 173 | chown -LR "$user":"$group" "$p" 174 | elif [[ -n $user ]] && [[ -z $group ]]; then 175 | chown -LR "$user" "$p" 176 | elif [[ -z $user ]] && [[ -n $group ]]; then 177 | chgrp -LR "$group" "$p" 178 | fi 179 | else 180 | stderr_print "$p does not exist" 181 | fi 182 | done 183 | } 184 | -------------------------------------------------------------------------------- /6.2/debian-10/prebuildfs/opt/bitnami/scripts/libhook.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library to use for scripts expected to be used as Kubernetes lifecycle hooks 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load generic libraries 8 | . /opt/bitnami/scripts/liblog.sh 9 | . /opt/bitnami/scripts/libos.sh 10 | 11 | # Override functions that log to stdout/stderr of the current process, so they print to process 1 12 | for function_to_override in stderr_print debug_execute; do 13 | # Output is sent to output of process 1 and thus end up in the container log 14 | # The hook output in general isn't saved 15 | eval "$(declare -f "$function_to_override") >/proc/1/fd/1 2>/proc/1/fd/2" 16 | done 17 | -------------------------------------------------------------------------------- /6.2/debian-10/prebuildfs/opt/bitnami/scripts/liblog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for logging functions 4 | 5 | # Constants 6 | RESET='\033[0m' 7 | RED='\033[38;5;1m' 8 | GREEN='\033[38;5;2m' 9 | YELLOW='\033[38;5;3m' 10 | MAGENTA='\033[38;5;5m' 11 | CYAN='\033[38;5;6m' 12 | 13 | # Functions 14 | 15 | ######################## 16 | # Print to STDERR 17 | # Arguments: 18 | # Message to print 19 | # Returns: 20 | # None 21 | ######################### 22 | stderr_print() { 23 | # 'is_boolean_yes' is defined in libvalidations.sh, but depends on this file so we cannot source it 24 | local bool="${BITNAMI_QUIET:-false}" 25 | # comparison is performed without regard to the case of alphabetic characters 26 | shopt -s nocasematch 27 | if ! [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then 28 | printf "%b\\n" "${*}" >&2 29 | fi 30 | } 31 | 32 | ######################## 33 | # Log message 34 | # Arguments: 35 | # Message to log 36 | # Returns: 37 | # None 38 | ######################### 39 | log() { 40 | stderr_print "${CYAN}${MODULE:-} ${MAGENTA}$(date "+%T.%2N ")${RESET}${*}" 41 | } 42 | ######################## 43 | # Log an 'info' message 44 | # Arguments: 45 | # Message to log 46 | # Returns: 47 | # None 48 | ######################### 49 | info() { 50 | log "${GREEN}INFO ${RESET} ==> ${*}" 51 | } 52 | ######################## 53 | # Log message 54 | # Arguments: 55 | # Message to log 56 | # Returns: 57 | # None 58 | ######################### 59 | warn() { 60 | log "${YELLOW}WARN ${RESET} ==> ${*}" 61 | } 62 | ######################## 63 | # Log an 'error' message 64 | # Arguments: 65 | # Message to log 66 | # Returns: 67 | # None 68 | ######################### 69 | error() { 70 | log "${RED}ERROR${RESET} ==> ${*}" 71 | } 72 | ######################## 73 | # Log a 'debug' message 74 | # Globals: 75 | # BITNAMI_DEBUG 76 | # Arguments: 77 | # None 78 | # Returns: 79 | # None 80 | ######################### 81 | debug() { 82 | # 'is_boolean_yes' is defined in libvalidations.sh, but depends on this file so we cannot source it 83 | local bool="${BITNAMI_DEBUG:-false}" 84 | # comparison is performed without regard to the case of alphabetic characters 85 | shopt -s nocasematch 86 | if [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then 87 | log "${MAGENTA}DEBUG${RESET} ==> ${*}" 88 | fi 89 | } 90 | 91 | ######################## 92 | # Indent a string 93 | # Arguments: 94 | # $1 - string 95 | # $2 - number of indentation characters (default: 4) 96 | # $3 - indentation character (default: " ") 97 | # Returns: 98 | # None 99 | ######################### 100 | indent() { 101 | local string="${1:-}" 102 | local num="${2:?missing num}" 103 | local char="${3:-" "}" 104 | # Build the indentation unit string 105 | local indent_unit="" 106 | for ((i = 0; i < num; i++)); do 107 | indent_unit="${indent_unit}${char}" 108 | done 109 | # shellcheck disable=SC2001 110 | # Complex regex, see https://github.com/koalaman/shellcheck/wiki/SC2001#exceptions 111 | echo "$string" | sed "s/^/${indent_unit}/" 112 | } 113 | -------------------------------------------------------------------------------- /6.2/debian-10/prebuildfs/opt/bitnami/scripts/libnet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for network functions 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/liblog.sh 9 | 10 | # Functions 11 | 12 | ######################## 13 | # Resolve IP address for a host/domain (i.e. DNS lookup) 14 | # Arguments: 15 | # $1 - Hostname to resolve 16 | # $2 - IP address version (v4, v6), leave empty for resolving to any version 17 | # Returns: 18 | # IP 19 | ######################### 20 | dns_lookup() { 21 | local host="${1:?host is missing}" 22 | local ip_version="${2:-}" 23 | getent "ahosts${ip_version}" "$host" | awk '/STREAM/ {print $1 }' | head -n 1 24 | } 25 | 26 | ######################### 27 | # Wait for a hostname and return the IP 28 | # Arguments: 29 | # $1 - hostname 30 | # $2 - number of retries 31 | # $3 - seconds to wait between retries 32 | # Returns: 33 | # - IP address that corresponds to the hostname 34 | ######################### 35 | wait_for_dns_lookup() { 36 | local hostname="${1:?hostname is missing}" 37 | local retries="${2:-5}" 38 | local seconds="${3:-1}" 39 | check_host() { 40 | if [[ $(dns_lookup "$hostname") == "" ]]; then 41 | false 42 | else 43 | true 44 | fi 45 | } 46 | # Wait for the host to be ready 47 | retry_while "check_host ${hostname}" "$retries" "$seconds" 48 | dns_lookup "$hostname" 49 | } 50 | 51 | ######################## 52 | # Get machine's IP 53 | # Arguments: 54 | # None 55 | # Returns: 56 | # Machine IP 57 | ######################### 58 | get_machine_ip() { 59 | local -a ip_addresses 60 | local hostname 61 | hostname="$(hostname)" 62 | read -r -a ip_addresses <<< "$(dns_lookup "$hostname" | xargs echo)" 63 | if [[ "${#ip_addresses[@]}" -gt 1 ]]; then 64 | warn "Found more than one IP address associated to hostname ${hostname}: ${ip_addresses[*]}, will use ${ip_addresses[0]}" 65 | elif [[ "${#ip_addresses[@]}" -lt 1 ]]; then 66 | error "Could not find any IP address associated to hostname ${hostname}" 67 | exit 1 68 | fi 69 | echo "${ip_addresses[0]}" 70 | } 71 | 72 | ######################## 73 | # Check if the provided argument is a resolved hostname 74 | # Arguments: 75 | # $1 - Value to check 76 | # Returns: 77 | # Boolean 78 | ######################### 79 | is_hostname_resolved() { 80 | local -r host="${1:?missing value}" 81 | if [[ -n "$(dns_lookup "$host")" ]]; then 82 | true 83 | else 84 | false 85 | fi 86 | } 87 | 88 | ######################## 89 | # Parse URL 90 | # Globals: 91 | # None 92 | # Arguments: 93 | # $1 - uri - String 94 | # $2 - component to obtain. Valid options (scheme, authority, userinfo, host, port, path, query or fragment) - String 95 | # Returns: 96 | # String 97 | parse_uri() { 98 | local uri="${1:?uri is missing}" 99 | local component="${2:?component is missing}" 100 | 101 | # Solution based on https://tools.ietf.org/html/rfc3986#appendix-B with 102 | # additional sub-expressions to split authority into userinfo, host and port 103 | # Credits to Patryk Obara (see https://stackoverflow.com/a/45977232/6694969) 104 | local -r URI_REGEX='^(([^:/?#]+):)?(//((([^@/?#]+)@)?([^:/?#]+)(:([0-9]+))?))?(/([^?#]*))?(\?([^#]*))?(#(.*))?' 105 | # || | ||| | | | | | | | | | 106 | # |2 scheme | ||6 userinfo 7 host | 9 port | 11 rpath | 13 query | 15 fragment 107 | # 1 scheme: | |5 userinfo@ 8 :... 10 path 12 ?... 14 #... 108 | # | 4 authority 109 | # 3 //... 110 | local index=0 111 | case "$component" in 112 | scheme) 113 | index=2 114 | ;; 115 | authority) 116 | index=4 117 | ;; 118 | userinfo) 119 | index=6 120 | ;; 121 | host) 122 | index=7 123 | ;; 124 | port) 125 | index=9 126 | ;; 127 | path) 128 | index=10 129 | ;; 130 | query) 131 | index=13 132 | ;; 133 | fragment) 134 | index=14 135 | ;; 136 | *) 137 | stderr_print "unrecognized component $component" 138 | return 1 139 | ;; 140 | esac 141 | [[ "$uri" =~ $URI_REGEX ]] && echo "${BASH_REMATCH[${index}]}" 142 | } 143 | 144 | ######################## 145 | # Wait for a HTTP connection to succeed 146 | # Globals: 147 | # * 148 | # Arguments: 149 | # $1 - URL to wait for 150 | # $2 - Maximum amount of retries (optional) 151 | # $3 - Time between retries (optional) 152 | # Returns: 153 | # true if the HTTP connection succeeded, false otherwise 154 | ######################### 155 | wait_for_http_connection() { 156 | local url="${1:?missing url}" 157 | local retries="${2:-}" 158 | local sleep_time="${3:-}" 159 | if ! retry_while "debug_execute curl --silent ${url}" "$retries" "$sleep_time"; then 160 | error "Could not connect to ${url}" 161 | return 1 162 | fi 163 | } 164 | -------------------------------------------------------------------------------- /6.2/debian-10/prebuildfs/opt/bitnami/scripts/libpersistence.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Bitnami persistence library 4 | # Used for bringing persistence capabilities to applications that don't have clear separation of data and logic 5 | 6 | # shellcheck disable=SC1091 7 | 8 | # Load Generic Libraries 9 | . /opt/bitnami/scripts/libfs.sh 10 | . /opt/bitnami/scripts/libos.sh 11 | . /opt/bitnami/scripts/liblog.sh 12 | . /opt/bitnami/scripts/libversion.sh 13 | 14 | # Functions 15 | 16 | ######################## 17 | # Persist an application directory 18 | # Globals: 19 | # BITNAMI_ROOT_DIR 20 | # BITNAMI_VOLUME_DIR 21 | # Arguments: 22 | # $1 - App folder name 23 | # $2 - List of app files to persist 24 | # Returns: 25 | # true if all steps succeeded, false otherwise 26 | ######################### 27 | persist_app() { 28 | local -r app="${1:?missing app}" 29 | local -a files_to_restore 30 | read -r -a files_to_persist <<< "$(tr ',;:' ' ' <<< "$2")" 31 | local -r install_dir="${BITNAMI_ROOT_DIR}/${app}" 32 | local -r persist_dir="${BITNAMI_VOLUME_DIR}/${app}" 33 | # Persist the individual files 34 | if [[ "${#files_to_persist[@]}" -le 0 ]]; then 35 | warn "No files are configured to be persisted" 36 | return 37 | fi 38 | pushd "$install_dir" >/dev/null || exit 39 | local file_to_persist_relative file_to_persist_destination file_to_persist_destination_folder 40 | local -r tmp_file="/tmp/perms.acl" 41 | for file_to_persist in "${files_to_persist[@]}"; do 42 | if [[ ! -f "$file_to_persist" && ! -d "$file_to_persist" ]]; then 43 | error "Cannot persist '${file_to_persist}' because it does not exist" 44 | return 1 45 | fi 46 | file_to_persist_relative="$(relativize "$file_to_persist" "$install_dir")" 47 | file_to_persist_destination="${persist_dir}/${file_to_persist_relative}" 48 | file_to_persist_destination_folder="$(dirname "$file_to_persist_destination")" 49 | # Get original permissions for existing files, which will be applied later 50 | # Exclude the root directory with 'sed', to avoid issues when copying the entirety of it to a volume 51 | getfacl -R "$file_to_persist_relative" | sed -E '/# file: (\..+|[^.])/,$!d' > "$tmp_file" 52 | # Copy directories to the volume 53 | ensure_dir_exists "$file_to_persist_destination_folder" 54 | cp -Lr --preserve=links "$file_to_persist_relative" "$file_to_persist_destination_folder" 55 | # Restore permissions 56 | pushd "$persist_dir" >/dev/null || exit 57 | if am_i_root; then 58 | setfacl --restore="$tmp_file" 59 | else 60 | # When running as non-root, don't change ownership 61 | setfacl --restore=<(grep -E -v '^# (owner|group):' "$tmp_file") 62 | fi 63 | popd >/dev/null || exit 64 | done 65 | popd >/dev/null || exit 66 | rm -f "$tmp_file" 67 | # Install the persisted files into the installation directory, via symlinks 68 | restore_persisted_app "$@" 69 | } 70 | 71 | ######################## 72 | # Restore a persisted application directory 73 | # Globals: 74 | # BITNAMI_ROOT_DIR 75 | # BITNAMI_VOLUME_DIR 76 | # FORCE_MAJOR_UPGRADE 77 | # Arguments: 78 | # $1 - App folder name 79 | # $2 - List of app files to restore 80 | # Returns: 81 | # true if all steps succeeded, false otherwise 82 | ######################### 83 | restore_persisted_app() { 84 | local -r app="${1:?missing app}" 85 | local -a files_to_restore 86 | read -r -a files_to_restore <<< "$(tr ',;:' ' ' <<< "$2")" 87 | local -r install_dir="${BITNAMI_ROOT_DIR}/${app}" 88 | local -r persist_dir="${BITNAMI_VOLUME_DIR}/${app}" 89 | # Restore the individual persisted files 90 | if [[ "${#files_to_restore[@]}" -le 0 ]]; then 91 | warn "No persisted files are configured to be restored" 92 | return 93 | fi 94 | local file_to_restore_relative file_to_restore_origin file_to_restore_destination 95 | for file_to_restore in "${files_to_restore[@]}"; do 96 | file_to_restore_relative="$(relativize "$file_to_restore" "$install_dir")" 97 | # We use 'realpath --no-symlinks' to ensure that the case of '.' is covered and the directory is removed 98 | file_to_restore_origin="$(realpath --no-symlinks "${install_dir}/${file_to_restore_relative}")" 99 | file_to_restore_destination="$(realpath --no-symlinks "${persist_dir}/${file_to_restore_relative}")" 100 | rm -rf "$file_to_restore_origin" 101 | ln -sfn "$file_to_restore_destination" "$file_to_restore_origin" 102 | done 103 | } 104 | 105 | ######################## 106 | # Check if an application directory was already persisted 107 | # Globals: 108 | # BITNAMI_VOLUME_DIR 109 | # Arguments: 110 | # $1 - App folder name 111 | # Returns: 112 | # true if all steps succeeded, false otherwise 113 | ######################### 114 | is_app_initialized() { 115 | local -r app="${1:?missing app}" 116 | local -r persist_dir="${BITNAMI_VOLUME_DIR}/${app}" 117 | if ! is_mounted_dir_empty "$persist_dir"; then 118 | true 119 | else 120 | false 121 | fi 122 | } 123 | -------------------------------------------------------------------------------- /6.2/debian-10/prebuildfs/opt/bitnami/scripts/libservice.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for managing services 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/libvalidations.sh 9 | . /opt/bitnami/scripts/liblog.sh 10 | 11 | # Functions 12 | 13 | ######################## 14 | # Read the provided pid file and returns a PID 15 | # Arguments: 16 | # $1 - Pid file 17 | # Returns: 18 | # PID 19 | ######################### 20 | get_pid_from_file() { 21 | local pid_file="${1:?pid file is missing}" 22 | 23 | if [[ -f "$pid_file" ]]; then 24 | if [[ -n "$(< "$pid_file")" ]] && [[ "$(< "$pid_file")" -gt 0 ]]; then 25 | echo "$(< "$pid_file")" 26 | fi 27 | fi 28 | } 29 | 30 | ######################## 31 | # Check if a provided PID corresponds to a running service 32 | # Arguments: 33 | # $1 - PID 34 | # Returns: 35 | # Boolean 36 | ######################### 37 | is_service_running() { 38 | local pid="${1:?pid is missing}" 39 | 40 | kill -0 "$pid" 2>/dev/null 41 | } 42 | 43 | ######################## 44 | # Stop a service by sending a termination signal to its pid 45 | # Arguments: 46 | # $1 - Pid file 47 | # $2 - Signal number (optional) 48 | # Returns: 49 | # None 50 | ######################### 51 | stop_service_using_pid() { 52 | local pid_file="${1:?pid file is missing}" 53 | local signal="${2:-}" 54 | local pid 55 | 56 | pid="$(get_pid_from_file "$pid_file")" 57 | [[ -z "$pid" ]] || ! is_service_running "$pid" && return 58 | 59 | if [[ -n "$signal" ]]; then 60 | kill "-${signal}" "$pid" 61 | else 62 | kill "$pid" 63 | fi 64 | 65 | local counter=10 66 | while [[ "$counter" -ne 0 ]] && is_service_running "$pid"; do 67 | sleep 1 68 | counter=$((counter - 1)) 69 | done 70 | } 71 | 72 | ######################## 73 | # Start cron daemon 74 | # Arguments: 75 | # None 76 | # Returns: 77 | # true if started correctly, false otherwise 78 | ######################### 79 | cron_start() { 80 | if [[ -x "/usr/sbin/cron" ]]; then 81 | /usr/sbin/cron 82 | elif [[ -x "/usr/sbin/crond" ]]; then 83 | /usr/sbin/crond 84 | else 85 | false 86 | fi 87 | } 88 | 89 | ######################## 90 | # Generate a cron configuration file for a given service 91 | # Arguments: 92 | # $1 - Service name 93 | # $2 - Command 94 | # Flags: 95 | # --run-as - User to run as (default: root) 96 | # --schedule - Cron schedule configuration (default: * * * * *) 97 | # Returns: 98 | # None 99 | ######################### 100 | generate_cron_conf() { 101 | local service_name="${1:?service name is missing}" 102 | local cmd="${2:?command is missing}" 103 | local run_as="root" 104 | local schedule="* * * * *" 105 | local clean="true" 106 | 107 | local clean="true" 108 | 109 | # Parse optional CLI flags 110 | shift 2 111 | while [[ "$#" -gt 0 ]]; do 112 | case "$1" in 113 | --run-as) 114 | shift 115 | run_as="$1" 116 | ;; 117 | --schedule) 118 | shift 119 | schedule="$1" 120 | ;; 121 | --no-clean) 122 | clean="false" 123 | ;; 124 | *) 125 | echo "Invalid command line flag ${1}" >&2 126 | return 1 127 | ;; 128 | esac 129 | shift 130 | done 131 | 132 | mkdir -p /etc/cron.d 133 | if "$clean"; then 134 | echo "${schedule} ${run_as} ${cmd}" > /etc/cron.d/"$service_name" 135 | else 136 | echo "${schedule} ${run_as} ${cmd}" >> /etc/cron.d/"$service_name" 137 | fi 138 | } 139 | 140 | ######################## 141 | # Remove a cron configuration file for a given service 142 | # Arguments: 143 | # $1 - Service name 144 | # Returns: 145 | # None 146 | ######################### 147 | remove_cron_conf() { 148 | local service_name="${1:?service name is missing}" 149 | local cron_conf_dir="/etc/monit/conf.d" 150 | rm -f "${cron_conf_dir}/${service_name}" 151 | } 152 | 153 | ######################## 154 | # Generate a monit configuration file for a given service 155 | # Arguments: 156 | # $1 - Service name 157 | # $2 - Pid file 158 | # $3 - Start command 159 | # $4 - Stop command 160 | # Flags: 161 | # --disable - Whether to disable the monit configuration 162 | # Returns: 163 | # None 164 | ######################### 165 | generate_monit_conf() { 166 | local service_name="${1:?service name is missing}" 167 | local pid_file="${2:?pid file is missing}" 168 | local start_command="${3:?start command is missing}" 169 | local stop_command="${4:?stop command is missing}" 170 | local monit_conf_dir="/etc/monit/conf.d" 171 | local disabled="no" 172 | 173 | # Parse optional CLI flags 174 | shift 4 175 | while [[ "$#" -gt 0 ]]; do 176 | case "$1" in 177 | --disable) 178 | disabled="yes" 179 | ;; 180 | *) 181 | echo "Invalid command line flag ${1}" >&2 182 | return 1 183 | ;; 184 | esac 185 | shift 186 | done 187 | 188 | is_boolean_yes "$disabled" && conf_suffix=".disabled" 189 | mkdir -p "$monit_conf_dir" 190 | cat >"${monit_conf_dir}/${service_name}.conf${conf_suffix:-}" <&2 242 | return 1 243 | ;; 244 | esac 245 | shift 246 | done 247 | 248 | mkdir -p "$logrotate_conf_dir" 249 | cat <"${logrotate_conf_dir}/${service_name}" 250 | ${log_path} { 251 | ${period} 252 | rotate ${rotations} 253 | dateext 254 | compress 255 | copytruncate 256 | missingok 257 | $(indent "$extra" 2) 258 | } 259 | EOF 260 | } 261 | 262 | ######################## 263 | # Remove a logrotate configuration file 264 | # Arguments: 265 | # $1 - Service name 266 | # Returns: 267 | # None 268 | ######################### 269 | remove_logrotate_conf() { 270 | local service_name="${1:?service name is missing}" 271 | local logrotate_conf_dir="/etc/logrotate.d" 272 | rm -f "${logrotate_conf_dir}/${service_name}" 273 | } 274 | -------------------------------------------------------------------------------- /6.2/debian-10/prebuildfs/opt/bitnami/scripts/libvalidations.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Validation functions library 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/liblog.sh 9 | 10 | # Functions 11 | 12 | ######################## 13 | # Check if the provided argument is an integer 14 | # Arguments: 15 | # $1 - Value to check 16 | # Returns: 17 | # Boolean 18 | ######################### 19 | is_int() { 20 | local -r int="${1:?missing value}" 21 | if [[ "$int" =~ ^-?[0-9]+ ]]; then 22 | true 23 | else 24 | false 25 | fi 26 | } 27 | 28 | ######################## 29 | # Check if the provided argument is a positive integer 30 | # Arguments: 31 | # $1 - Value to check 32 | # Returns: 33 | # Boolean 34 | ######################### 35 | is_positive_int() { 36 | local -r int="${1:?missing value}" 37 | if is_int "$int" && (( "${int}" >= 0 )); then 38 | true 39 | else 40 | false 41 | fi 42 | } 43 | 44 | ######################## 45 | # Check if the provided argument is a boolean or is the string 'yes/true' 46 | # Arguments: 47 | # $1 - Value to check 48 | # Returns: 49 | # Boolean 50 | ######################### 51 | is_boolean_yes() { 52 | local -r bool="${1:-}" 53 | # comparison is performed without regard to the case of alphabetic characters 54 | shopt -s nocasematch 55 | if [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then 56 | true 57 | else 58 | false 59 | fi 60 | } 61 | 62 | ######################## 63 | # Check if the provided argument is a boolean yes/no value 64 | # Arguments: 65 | # $1 - Value to check 66 | # Returns: 67 | # Boolean 68 | ######################### 69 | is_yes_no_value() { 70 | local -r bool="${1:-}" 71 | if [[ "$bool" =~ ^(yes|no)$ ]]; then 72 | true 73 | else 74 | false 75 | fi 76 | } 77 | 78 | ######################## 79 | # Check if the provided argument is a boolean true/false value 80 | # Arguments: 81 | # $1 - Value to check 82 | # Returns: 83 | # Boolean 84 | ######################### 85 | is_true_false_value() { 86 | local -r bool="${1:-}" 87 | if [[ "$bool" =~ ^(true|false)$ ]]; then 88 | true 89 | else 90 | false 91 | fi 92 | } 93 | 94 | ######################## 95 | # Check if the provided argument is a boolean 1/0 value 96 | # Arguments: 97 | # $1 - Value to check 98 | # Returns: 99 | # Boolean 100 | ######################### 101 | is_1_0_value() { 102 | local -r bool="${1:-}" 103 | if [[ "$bool" =~ ^[10]$ ]]; then 104 | true 105 | else 106 | false 107 | fi 108 | } 109 | 110 | ######################## 111 | # Check if the provided argument is an empty string or not defined 112 | # Arguments: 113 | # $1 - Value to check 114 | # Returns: 115 | # Boolean 116 | ######################### 117 | is_empty_value() { 118 | local -r val="${1:-}" 119 | if [[ -z "$val" ]]; then 120 | true 121 | else 122 | false 123 | fi 124 | } 125 | 126 | ######################## 127 | # Validate if the provided argument is a valid port 128 | # Arguments: 129 | # $1 - Port to validate 130 | # Returns: 131 | # Boolean and error message 132 | ######################### 133 | validate_port() { 134 | local value 135 | local unprivileged=0 136 | 137 | # Parse flags 138 | while [[ "$#" -gt 0 ]]; do 139 | case "$1" in 140 | -unprivileged) 141 | unprivileged=1 142 | ;; 143 | --) 144 | shift 145 | break 146 | ;; 147 | -*) 148 | stderr_print "unrecognized flag $1" 149 | return 1 150 | ;; 151 | *) 152 | break 153 | ;; 154 | esac 155 | shift 156 | done 157 | 158 | if [[ "$#" -gt 1 ]]; then 159 | echo "too many arguments provided" 160 | return 2 161 | elif [[ "$#" -eq 0 ]]; then 162 | stderr_print "missing port argument" 163 | return 1 164 | else 165 | value=$1 166 | fi 167 | 168 | if [[ -z "$value" ]]; then 169 | echo "the value is empty" 170 | return 1 171 | else 172 | if ! is_int "$value"; then 173 | echo "value is not an integer" 174 | return 2 175 | elif [[ "$value" -lt 0 ]]; then 176 | echo "negative value provided" 177 | return 2 178 | elif [[ "$value" -gt 65535 ]]; then 179 | echo "requested port is greater than 65535" 180 | return 2 181 | elif [[ "$unprivileged" = 1 && "$value" -lt 1024 ]]; then 182 | echo "privileged port requested" 183 | return 3 184 | fi 185 | fi 186 | } 187 | 188 | ######################## 189 | # Validate if the provided argument is a valid IPv4 address 190 | # Arguments: 191 | # $1 - IP to validate 192 | # Returns: 193 | # Boolean 194 | ######################### 195 | validate_ipv4() { 196 | local ip="${1:?ip is missing}" 197 | local stat=1 198 | 199 | if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then 200 | read -r -a ip_array <<< "$(tr '.' ' ' <<< "$ip")" 201 | [[ ${ip_array[0]} -le 255 && ${ip_array[1]} -le 255 \ 202 | && ${ip_array[2]} -le 255 && ${ip_array[3]} -le 255 ]] 203 | stat=$? 204 | fi 205 | return $stat 206 | } 207 | 208 | ######################## 209 | # Validate a string format 210 | # Arguments: 211 | # $1 - String to validate 212 | # Returns: 213 | # Boolean 214 | ######################### 215 | validate_string() { 216 | local string 217 | local min_length=-1 218 | local max_length=-1 219 | 220 | # Parse flags 221 | while [ "$#" -gt 0 ]; do 222 | case "$1" in 223 | -min-length) 224 | shift 225 | min_length=${1:-} 226 | ;; 227 | -max-length) 228 | shift 229 | max_length=${1:-} 230 | ;; 231 | --) 232 | shift 233 | break 234 | ;; 235 | -*) 236 | stderr_print "unrecognized flag $1" 237 | return 1 238 | ;; 239 | *) 240 | break 241 | ;; 242 | esac 243 | shift 244 | done 245 | 246 | if [ "$#" -gt 1 ]; then 247 | stderr_print "too many arguments provided" 248 | return 2 249 | elif [ "$#" -eq 0 ]; then 250 | stderr_print "missing string" 251 | return 1 252 | else 253 | string=$1 254 | fi 255 | 256 | if [[ "$min_length" -ge 0 ]] && [[ "${#string}" -lt "$min_length" ]]; then 257 | echo "string length is less than $min_length" 258 | return 1 259 | fi 260 | if [[ "$max_length" -ge 0 ]] && [[ "${#string}" -gt "$max_length" ]]; then 261 | echo "string length is great than $max_length" 262 | return 1 263 | fi 264 | } 265 | -------------------------------------------------------------------------------- /6.2/debian-10/prebuildfs/opt/bitnami/scripts/libversion.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Library for managing versions strings 4 | 5 | # shellcheck disable=SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/liblog.sh 9 | 10 | # Functions 11 | ######################## 12 | # Gets semantic version 13 | # Arguments: 14 | # $1 - version: string to extract major.minor.patch 15 | # $2 - section: 1 to extract major, 2 to extract minor, 3 to extract patch 16 | # Returns: 17 | # array with the major, minor and release 18 | ######################### 19 | get_sematic_version () { 20 | local version="${1:?version is required}" 21 | local section="${2:?section is required}" 22 | local -a version_sections 23 | 24 | #Regex to parse versions: x.y.z 25 | local -r regex='([0-9]+)(\.([0-9]+)(\.([0-9]+))?)?' 26 | 27 | if [[ "$version" =~ $regex ]]; then 28 | local i=1 29 | local j=1 30 | local n=${#BASH_REMATCH[*]} 31 | 32 | while [[ $i -lt $n ]]; do 33 | if [[ -n "${BASH_REMATCH[$i]}" ]] && [[ "${BASH_REMATCH[$i]:0:1}" != '.' ]]; then 34 | version_sections[$j]=${BASH_REMATCH[$i]} 35 | ((j++)) 36 | fi 37 | ((i++)) 38 | done 39 | 40 | local number_regex='^[0-9]+$' 41 | if [[ "$section" =~ $number_regex ]] && (( section > 0 )) && (( section <= 3 )); then 42 | echo "${version_sections[$section]}" 43 | return 44 | else 45 | stderr_print "Section allowed values are: 1, 2, and 3" 46 | return 1 47 | fi 48 | fi 49 | } 50 | -------------------------------------------------------------------------------- /6.2/debian-10/prebuildfs/usr/sbin/install_packages: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | export DEBIAN_FRONTEND=noninteractive 5 | n=0 6 | max=2 7 | until [ $n -gt $max ]; do 8 | set +e 9 | ( 10 | apt-get update -qq && 11 | apt-get install -y --no-install-recommends "$@" 12 | ) 13 | CODE=$? 14 | set -e 15 | if [ $CODE -eq 0 ]; then 16 | break 17 | fi 18 | if [ $n -eq $max ]; then 19 | exit $CODE 20 | fi 21 | echo "apt failed, retrying" 22 | n=$(($n + 1)) 23 | done 24 | rm -r /var/lib/apt/lists /var/cache/apt/archives 25 | -------------------------------------------------------------------------------- /6.2/debian-10/rootfs/opt/bitnami/scripts/librediscluster.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Bitnami Redis Cluster library 4 | 5 | # shellcheck disable=SC1090,SC1091 6 | 7 | # Load Generic Libraries 8 | . /opt/bitnami/scripts/libfile.sh 9 | . /opt/bitnami/scripts/libfs.sh 10 | . /opt/bitnami/scripts/liblog.sh 11 | . /opt/bitnami/scripts/libnet.sh 12 | . /opt/bitnami/scripts/libos.sh 13 | . /opt/bitnami/scripts/libservice.sh 14 | . /opt/bitnami/scripts/libvalidations.sh 15 | . /opt/bitnami/scripts/libredis.sh 16 | 17 | # Functions 18 | 19 | ######################## 20 | # Validate settings in REDIS_* env vars. 21 | # Globals: 22 | # REDIS_* 23 | # Arguments: 24 | # None 25 | # Returns: 26 | # None 27 | ######################### 28 | redis_cluster_validate() { 29 | debug "Validating settings in REDIS_* env vars.." 30 | local error_code=0 31 | 32 | # Auxiliary functions 33 | print_validation_error() { 34 | error "$1" 35 | error_code=1 36 | } 37 | 38 | empty_password_enabled_warn() { 39 | warn "You set the environment variable ALLOW_EMPTY_PASSWORD=${ALLOW_EMPTY_PASSWORD}. For safety reasons, do not use this flag in a production environment." 40 | } 41 | empty_password_error() { 42 | print_validation_error "The $1 environment variable is empty or not set. Set the environment variable ALLOW_EMPTY_PASSWORD=yes to allow the container to be started with blank passwords. This is recommended only for development." 43 | } 44 | 45 | if is_boolean_yes "$ALLOW_EMPTY_PASSWORD"; then 46 | empty_password_enabled_warn 47 | else 48 | [[ -z "$REDIS_PASSWORD" ]] && empty_password_error REDIS_PASSWORD 49 | fi 50 | 51 | if ! is_boolean_yes "$REDIS_CLUSTER_DYNAMIC_IPS"; then 52 | [[ -z "$REDIS_CLUSTER_ANNOUNCE_IP" ]] && print_validation_error "To provide external access you need to provide the REDIS_CLUSTER_ANNOUNCE_IP env var" 53 | fi 54 | 55 | [[ -z "$REDIS_NODES" ]] && print_validation_error "REDIS_NODES is required" 56 | 57 | if [[ -z "$REDIS_PORT_NUMBER" ]]; then 58 | print_validation_error "REDIS_PORT_NUMBER cannot be empty" 59 | fi 60 | 61 | if is_boolean_yes "$REDIS_CLUSTER_CREATOR"; then 62 | [[ -z "$REDIS_CLUSTER_REPLICAS" ]] && print_validation_error "To create the cluster you need to provide the number of replicas to the cluster creator" 63 | fi 64 | 65 | if ((REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP < 0)); then 66 | print_validation_error "REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP must be greater or equal to zero" 67 | fi 68 | 69 | [[ "$error_code" -eq 0 ]] || exit "$error_code" 70 | } 71 | 72 | ######################## 73 | # Redis specific configuration to override the default one 74 | # Globals: 75 | # REDIS_* 76 | # Arguments: 77 | # None 78 | # Returns: 79 | # None 80 | ######################### 81 | redis_cluster_override_conf() { 82 | # Redis configuration to override 83 | if ! is_boolean_yes "$REDIS_CLUSTER_DYNAMIC_IPS"; then 84 | redis_conf_set cluster-announce-ip "$REDIS_CLUSTER_ANNOUNCE_IP" 85 | fi 86 | if is_boolean_yes "$REDIS_CLUSTER_DYNAMIC_IPS"; then 87 | # Always set the announce-ip to avoid issues when using proxies and traffic restrictions. 88 | redis_conf_set cluster-announce-ip "$(get_machine_ip)" 89 | fi 90 | if is_boolean_yes "$REDIS_TLS_ENABLED"; then 91 | redis_conf_set tls-cluster yes 92 | redis_conf_set tls-replication yes 93 | fi 94 | } 95 | 96 | ######################## 97 | # Ensure Redis is initialized 98 | # Globals: 99 | # REDIS_* 100 | # Arguments: 101 | # None 102 | # Returns: 103 | # None 104 | ######################### 105 | redis_cluster_initialize() { 106 | redis_configure_default 107 | redis_cluster_override_conf 108 | } 109 | 110 | ######################## 111 | # Creates the Redis cluster 112 | # Globals: 113 | # REDIS_* 114 | # Arguments: 115 | # - $@ Array with the hostnames 116 | # Returns: 117 | # None 118 | ######################### 119 | redis_cluster_create() { 120 | local nodes=("$@") 121 | local sockets=() 122 | local wait_command 123 | local create_command 124 | 125 | for node in "${nodes[@]}"; do 126 | read -r -a host_and_port <<< "$(to_host_and_port "$node")" 127 | wait_command="redis-cli -h ${host_and_port[0]} -p ${host_and_port[1]} ping" 128 | if is_boolean_yes "$REDIS_TLS_ENABLED"; then 129 | wait_command="${wait_command:0:-5} --tls --cert ${REDIS_TLS_CERT_FILE} --key ${REDIS_TLS_KEY_FILE} --cacert ${REDIS_TLS_CA_FILE} ping" 130 | fi 131 | while [[ $($wait_command) != 'PONG' ]]; do 132 | echo "Node $node not ready, waiting for all the nodes to be ready..." 133 | sleep 1 134 | done 135 | done 136 | 137 | echo "Waiting ${REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP}s before querying node ip addresses" 138 | sleep "${REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP}" 139 | 140 | for node in "${nodes[@]}"; do 141 | read -r -a host_and_port <<< "$(to_host_and_port "$node")" 142 | sockets+=("$(wait_for_dns_lookup "${host_and_port[0]}" "${REDIS_CLUSTER_DNS_LOOKUP_RETRIES}" "${REDIS_CLUSTER_DNS_LOOKUP_SLEEP}"):${host_and_port[1]}") 143 | done 144 | 145 | create_command="redis-cli --cluster create ${sockets[*]} --cluster-replicas ${REDIS_CLUSTER_REPLICAS} --cluster-yes" 146 | if is_boolean_yes "$REDIS_TLS_ENABLED"; then 147 | create_command="${create_command} --tls --cert ${REDIS_TLS_CERT_FILE} --key ${REDIS_TLS_KEY_FILE} --cacert ${REDIS_TLS_CA_FILE}" 148 | fi 149 | yes yes | $create_command || true 150 | if redis_cluster_check "${sockets[0]}"; then 151 | echo "Cluster correctly created" 152 | else 153 | echo "The cluster was already created, the nodes should have recovered it" 154 | fi 155 | } 156 | 157 | ######################### 158 | ## Checks if the cluster state is correct. 159 | ## Params: 160 | ## - $1: node where to check the cluster state 161 | ######################### 162 | redis_cluster_check() { 163 | if is_boolean_yes "$REDIS_TLS_ENABLED"; then 164 | local -r check=$(redis-cli --tls --cert "${REDIS_TLS_CERT_FILE}" --key "${REDIS_TLS_KEY_FILE}" --cacert "${REDIS_TLS_CA_FILE}" --cluster check "$1") 165 | else 166 | local -r check=$(redis-cli --cluster check "$1") 167 | fi 168 | if [[ $check =~ "All 16384 slots covered" ]]; then 169 | true 170 | else 171 | false 172 | fi 173 | } 174 | 175 | ######################### 176 | ## Recovers the cluster when using dynamic IPs by changing them in the nodes.conf 177 | # Globals: 178 | # REDIS_* 179 | # Arguments: 180 | # None 181 | # Returns: 182 | # None 183 | ######################### 184 | redis_cluster_update_ips() { 185 | read -ra nodes <<< "$(tr ',;' ' ' <<< "${REDIS_NODES}")" 186 | 187 | declare -A host_2_ip_array # Array to map hosts and IPs 188 | # Update the IPs when a number of nodes > quorum change their IPs 189 | if [[ ! -f "${REDIS_DATA_DIR}/nodes.sh" ]]; then 190 | # It is the first initialization so store the nodes 191 | for node in "${nodes[@]}"; do 192 | ip=$(wait_for_dns_lookup "$node" "$REDIS_DNS_RETRIES" 5) 193 | host_2_ip_array["$node"]="$ip" 194 | done 195 | echo "Storing map with hostnames and IPs" 196 | declare -p host_2_ip_array >"${REDIS_DATA_DIR}/nodes.sh" 197 | else 198 | # The cluster was already started 199 | . "${REDIS_DATA_DIR}/nodes.sh" 200 | # Update the IPs in the nodes.conf 201 | for node in "${nodes[@]}"; do 202 | newIP=$(wait_for_dns_lookup "$node" "$REDIS_DNS_RETRIES" 5) 203 | # The node can be new if we are updating the cluster, so catch the unbound variable error 204 | if [[ ${host_2_ip_array[$node]+true} ]]; then 205 | echo "Changing old IP ${host_2_ip_array[$node]} by the new one ${newIP}" 206 | nodesFile=$(sed "s/ ${host_2_ip_array[$node]}:/ $newIP:/g" "${REDIS_DATA_DIR}/nodes.conf") 207 | echo "$nodesFile" >"${REDIS_DATA_DIR}/nodes.conf" 208 | fi 209 | host_2_ip_array["$node"]="$newIP" 210 | done 211 | declare -p host_2_ip_array >"${REDIS_DATA_DIR}/nodes.sh" 212 | fi 213 | } 214 | 215 | ######################### 216 | ## Assigns a port to the host if one is not set using redis defaults 217 | # Globals: 218 | # REDIS_* 219 | # Arguments: 220 | # $1 - redis host or redis host and port 221 | # Returns: 222 | # - 2 element Array of host and port 223 | ######################### 224 | to_host_and_port() { 225 | local host="${1:?host is required}" 226 | read -r -a host_and_port <<< "$(echo "$host" | tr ":" " ")" 227 | 228 | if [ "${#host_and_port[*]}" -eq "1" ]; then 229 | if is_boolean_yes "$REDIS_TLS_ENABLED"; then 230 | host_and_port=("${host_and_port[0]}" "${REDIS_TLS_PORT}") 231 | else 232 | host_and_port=("${host_and_port[0]}" "${REDIS_PORT_NUMBER}") 233 | fi 234 | fi 235 | 236 | echo "${host_and_port[*]}" 237 | } 238 | -------------------------------------------------------------------------------- /6.2/debian-10/rootfs/opt/bitnami/scripts/redis-cluster-env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Environment configuration for redis-cluster 4 | 5 | # The values for all environment variables will be set in the below order of precedence 6 | # 1. Custom environment variables defined below after Bitnami defaults 7 | # 2. Constants defined in this file (environment variables with no default), i.e. BITNAMI_ROOT_DIR 8 | # 3. Environment variables overridden via external files using *_FILE variables (see below) 9 | # 4. Environment variables set externally (i.e. current Bash context/Dockerfile/userdata) 10 | 11 | # Load logging library 12 | . /opt/bitnami/scripts/liblog.sh 13 | 14 | export BITNAMI_ROOT_DIR="/opt/bitnami" 15 | export BITNAMI_VOLUME_DIR="/bitnami" 16 | 17 | # Logging configuration 18 | export MODULE="${MODULE:-redis-cluster}" 19 | export BITNAMI_DEBUG="${BITNAMI_DEBUG:-false}" 20 | 21 | # By setting an environment variable matching *_FILE to a file path, the prefixed environment 22 | # variable will be overridden with the value specified in that file 23 | redis_cluster_env_vars=( 24 | REDIS_DATA_DIR 25 | REDIS_DISABLE_COMMANDS 26 | REDIS_DATABASE 27 | REDIS_AOF_ENABLED 28 | REDIS_MASTER_HOST 29 | REDIS_MASTER_PORT_NUMBER 30 | REDIS_PORT_NUMBER 31 | REDIS_ALLOW_REMOTE_CONNECTIONS 32 | REDIS_REPLICATION_MODE 33 | REDIS_REPLICA_IP 34 | REDIS_REPLICA_PORT 35 | REDIS_EXTRA_FLAGS 36 | ALLOW_EMPTY_PASSWORD 37 | REDIS_PASSWORD 38 | REDIS_MASTER_PASSWORD 39 | REDIS_TLS_ENABLED 40 | REDIS_TLS_PORT_NUMBER 41 | REDIS_TLS_CERT_FILE 42 | REDIS_TLS_KEY_FILE 43 | REDIS_TLS_CA_FILE 44 | REDIS_TLS_DH_PARAMS_FILE 45 | REDIS_TLS_AUTH_CLIENTS 46 | REDIS_CLUSTER_CREATOR 47 | REDIS_CLUSTER_REPLICAS 48 | REDIS_CLUSTER_DYNAMIC_IPS 49 | REDIS_CLUSTER_ANNOUNCE_IP 50 | REDIS_DNS_RETRIES 51 | REDIS_NODES 52 | REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP 53 | REDIS_CLUSTER_DNS_LOOKUP_RETRIES 54 | REDIS_CLUSTER_DNS_LOOKUP_SLEEP 55 | REDIS_TLS_PORT 56 | ) 57 | for env_var in "${redis_cluster_env_vars[@]}"; do 58 | file_env_var="${env_var}_FILE" 59 | if [[ -n "${!file_env_var:-}" ]]; then 60 | if [[ -r "${!file_env_var:-}" ]]; then 61 | export "${env_var}=$(< "${!file_env_var}")" 62 | unset "${file_env_var}" 63 | else 64 | warn "Skipping export of '${env_var}'. '${!file_env_var:-}' is not readable." 65 | fi 66 | fi 67 | done 68 | unset redis_cluster_env_vars 69 | 70 | # Paths 71 | export REDIS_VOLUME_DIR="/bitnami/redis" 72 | export REDIS_BASE_DIR="${BITNAMI_ROOT_DIR}/redis" 73 | export REDIS_CONF_DIR="${REDIS_BASE_DIR}/etc" 74 | export REDIS_DATA_DIR="${REDIS_DATA_DIR:-${REDIS_VOLUME_DIR}/data}" 75 | export REDIS_MOUNTED_CONF_DIR="${REDIS_BASE_DIR}/mounted-etc" 76 | export REDIS_CONF_FILE="${REDIS_CONF_DIR}/redis.conf" 77 | export REDIS_LOG_DIR="${REDIS_BASE_DIR}/logs" 78 | export REDIS_LOG_FILE="${REDIS_LOG_DIR}/redis.log" 79 | export REDIS_TMP_DIR="${REDIS_BASE_DIR}/tmp" 80 | export REDIS_PID_FILE="${REDIS_TMP_DIR}/redis.pid" 81 | export REDIS_BIN_DIR="${REDIS_BASE_DIR}/bin" 82 | export PATH="${REDIS_BIN_DIR}:${BITNAMI_ROOT_DIR}/common/bin:${PATH}" 83 | 84 | # System users (when running with a privileged user) 85 | export REDIS_DAEMON_USER="redis" 86 | export REDIS_DAEMON_GROUP="redis" 87 | 88 | # Redis settings 89 | export REDIS_DISABLE_COMMANDS="${REDIS_DISABLE_COMMANDS:-}" 90 | export REDIS_DATABASE="${REDIS_DATABASE:-redis}" 91 | export REDIS_AOF_ENABLED="${REDIS_AOF_ENABLED:-yes}" 92 | export REDIS_MASTER_HOST="${REDIS_MASTER_HOST:-}" 93 | export REDIS_MASTER_PORT_NUMBER="${REDIS_MASTER_PORT_NUMBER:-6379}" 94 | export REDIS_DEFAULT_PORT_NUMBER="6379" # only used at build time 95 | export REDIS_PORT_NUMBER="${REDIS_PORT_NUMBER:-$REDIS_DEFAULT_PORT_NUMBER}" 96 | export REDIS_ALLOW_REMOTE_CONNECTIONS="${REDIS_ALLOW_REMOTE_CONNECTIONS:-yes}" 97 | export REDIS_REPLICATION_MODE="${REDIS_REPLICATION_MODE:-}" 98 | export REDIS_REPLICA_IP="${REDIS_REPLICA_IP:-}" 99 | export REDIS_REPLICA_PORT="${REDIS_REPLICA_PORT:-}" 100 | export REDIS_EXTRA_FLAGS="${REDIS_EXTRA_FLAGS:-}" 101 | export ALLOW_EMPTY_PASSWORD="${ALLOW_EMPTY_PASSWORD:-no}" 102 | export REDIS_PASSWORD="${REDIS_PASSWORD:-}" 103 | export REDIS_MASTER_PASSWORD="${REDIS_MASTER_PASSWORD:-}" 104 | 105 | # TLS settings 106 | export REDIS_TLS_ENABLED="${REDIS_TLS_ENABLED:-no}" 107 | REDIS_TLS_PORT_NUMBER="${REDIS_TLS_PORT_NUMBER:-"${REDIS_TLS_PORT:-}"}" 108 | export REDIS_TLS_PORT_NUMBER="${REDIS_TLS_PORT_NUMBER:-6379}" 109 | export REDIS_TLS_CERT_FILE="${REDIS_TLS_CERT_FILE:-}" 110 | export REDIS_TLS_KEY_FILE="${REDIS_TLS_KEY_FILE:-}" 111 | export REDIS_TLS_CA_FILE="${REDIS_TLS_CA_FILE:-}" 112 | export REDIS_TLS_DH_PARAMS_FILE="${REDIS_TLS_DH_PARAMS_FILE:-}" 113 | export REDIS_TLS_AUTH_CLIENTS="${REDIS_TLS_AUTH_CLIENTS:-yes}" 114 | 115 | # Redis Cluster settings 116 | export REDIS_CLUSTER_CREATOR="${REDIS_CLUSTER_CREATOR:-no}" 117 | export REDIS_CLUSTER_REPLICAS="${REDIS_CLUSTER_REPLICAS:-1}" 118 | export REDIS_CLUSTER_DYNAMIC_IPS="${REDIS_CLUSTER_DYNAMIC_IPS:-yes}" 119 | export REDIS_CLUSTER_ANNOUNCE_IP="${REDIS_CLUSTER_ANNOUNCE_IP:-}" 120 | export REDIS_DNS_RETRIES="${REDIS_DNS_RETRIES:-120}" 121 | export REDIS_NODES="${REDIS_NODES:-}" 122 | export REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP="${REDIS_CLUSTER_SLEEP_BEFORE_DNS_LOOKUP:-0}" 123 | export REDIS_CLUSTER_DNS_LOOKUP_RETRIES="${REDIS_CLUSTER_DNS_LOOKUP_RETRIES:-1}" 124 | export REDIS_CLUSTER_DNS_LOOKUP_SLEEP="${REDIS_CLUSTER_DNS_LOOKUP_SLEEP:-1}" 125 | 126 | # Custom environment variables may be defined below 127 | -------------------------------------------------------------------------------- /6.2/debian-10/rootfs/opt/bitnami/scripts/redis-cluster/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # shellcheck disable=SC1091 4 | 5 | set -o errexit 6 | set -o nounset 7 | set -o pipefail 8 | # set -o xtrace # Uncomment this line for debugging purpose 9 | 10 | # Load Redis environment variables 11 | . /opt/bitnami/scripts/redis-cluster-env.sh 12 | 13 | # Load libraries 14 | . /opt/bitnami/scripts/libbitnami.sh 15 | . /opt/bitnami/scripts/librediscluster.sh 16 | 17 | print_welcome_page 18 | 19 | if [[ "$*" = *"/run.sh"* ]]; then 20 | info "** Starting Redis setup **" 21 | /opt/bitnami/scripts/redis-cluster/setup.sh 22 | info "** Redis setup finished! **" 23 | fi 24 | 25 | echo "" 26 | exec "$@" 27 | -------------------------------------------------------------------------------- /6.2/debian-10/rootfs/opt/bitnami/scripts/redis-cluster/postunpack.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # shellcheck disable=SC1091 4 | 5 | set -o errexit 6 | set -o nounset 7 | set -o pipefail 8 | # set -o xtrace # Uncomment this line for debugging purpose 9 | 10 | # Load Redis environment variables 11 | . /opt/bitnami/scripts/redis-cluster-env.sh 12 | 13 | # Load libraries 14 | . /opt/bitnami/scripts/librediscluster.sh 15 | . /opt/bitnami/scripts/libfs.sh 16 | 17 | for dir in "$REDIS_VOLUME_DIR" "$REDIS_DATA_DIR" "$REDIS_BASE_DIR" "$REDIS_CONF_DIR"; do 18 | ensure_dir_exists "$dir" 19 | done 20 | 21 | cp "${REDIS_BASE_DIR}/etc/redis-default.conf" "$REDIS_CONF_FILE" 22 | 23 | info "Setting Redis config file..." 24 | redis_conf_set port "$REDIS_DEFAULT_PORT_NUMBER" 25 | redis_conf_set dir "$REDIS_DATA_DIR" 26 | redis_conf_set pidfile "$REDIS_PID_FILE" 27 | redis_conf_set daemonize no 28 | redis_conf_set cluster-enabled yes 29 | redis_conf_set cluster-config-file "${REDIS_DATA_DIR}/nodes.conf" 30 | 31 | chmod -R g+rwX "$REDIS_BASE_DIR" /bitnami/redis 32 | -------------------------------------------------------------------------------- /6.2/debian-10/rootfs/opt/bitnami/scripts/redis-cluster/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # shellcheck disable=SC1091 4 | 5 | set -o errexit 6 | set -o nounset 7 | set -o pipefail 8 | # set -o xtrace # Uncomment this line for debugging purpose 9 | 10 | # Enable job control 11 | # ref https://www.gnu.org/software/bash/manual/bash.html#The-Set-Builtin 12 | set -m 13 | 14 | # Load Redis environment variables 15 | . /opt/bitnami/scripts/redis-cluster-env.sh 16 | 17 | # Load libraries 18 | . /opt/bitnami/scripts/libos.sh 19 | . /opt/bitnami/scripts/librediscluster.sh 20 | 21 | read -ra nodes <<< "$(tr ',;' ' ' <<< "${REDIS_NODES}")" 22 | 23 | ARGS=("--port" "$REDIS_PORT_NUMBER") 24 | ARGS+=("--include" "${REDIS_BASE_DIR}/etc/redis.conf") 25 | 26 | if ! is_boolean_yes "$ALLOW_EMPTY_PASSWORD"; then 27 | ARGS+=("--requirepass" "$REDIS_PASSWORD") 28 | ARGS+=("--masterauth" "$REDIS_PASSWORD") 29 | else 30 | ARGS+=("--protected-mode" "no") 31 | fi 32 | 33 | ARGS+=("$@") 34 | 35 | if is_boolean_yes "$REDIS_CLUSTER_CREATOR" && ! [[ -f "${REDIS_DATA_DIR}/nodes.conf" ]]; then 36 | # Start Redis in background 37 | if am_i_root; then 38 | gosu "$REDIS_DAEMON_USER" redis-server "${ARGS[@]}" & 39 | else 40 | redis-server "${ARGS[@]}" & 41 | fi 42 | # Create the cluster 43 | redis_cluster_create "${nodes[@]}" 44 | # Bring redis process to foreground 45 | fg 46 | else 47 | if am_i_root; then 48 | exec gosu "$REDIS_DAEMON_USER" redis-server "${ARGS[@]}" 49 | else 50 | exec redis-server "${ARGS[@]}" 51 | fi 52 | fi 53 | -------------------------------------------------------------------------------- /6.2/debian-10/rootfs/opt/bitnami/scripts/redis-cluster/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # shellcheck disable=SC1091 4 | 5 | set -o errexit 6 | set -o nounset 7 | set -o pipefail 8 | # set -o xtrace # Uncomment this line for debugging purpose 9 | 10 | # Load Redis environment variables 11 | . /opt/bitnami/scripts/redis-cluster-env.sh 12 | 13 | # Load libraries 14 | . /opt/bitnami/scripts/libos.sh 15 | . /opt/bitnami/scripts/libfs.sh 16 | . /opt/bitnami/scripts/librediscluster.sh 17 | 18 | # Ensure Redis environment variables settings are valid 19 | redis_cluster_validate 20 | # Ensure Redis is stopped when this script ends 21 | trap "redis_stop" EXIT 22 | am_i_root && ensure_user_exists "$REDIS_DAEMON_USER" --group "$REDIS_DAEMON_GROUP" 23 | 24 | # Ensure Redis is initialized 25 | redis_cluster_initialize 26 | 27 | if is_boolean_yes "$REDIS_CLUSTER_DYNAMIC_IPS"; then 28 | redis_cluster_update_ips 29 | fi 30 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities. 4 | 5 | Communication through any of Bitnami's channels (GitHub, mailing lists, Twitter, and so on) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. 6 | 7 | We promise to extend courtesy and respect to everyone involved in this project, regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to this project to do the same. 8 | 9 | If any member of the community violates this code of conduct, the maintainers of this project may take action, including removing issues, comments, and PRs or blocking accounts, as deemed appropriate. 10 | 11 | If you are subjected to or witness unacceptable behavior, or have any other concerns, please communicate with us. 12 | 13 | If you have suggestions to improve this Code of Conduct, please submit an issue or PR. 14 | 15 | **Attribution** 16 | 17 | This Code of Conduct is adapted from the Angular project available at this page: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md 18 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Contributions are welcome via GitHub Pull Requests. This document outlines the process to help get your contribution accepted. 4 | 5 | Any type of contribution is welcome: new features, bug fixes, documentation improvements, etc. 6 | 7 | ## How to Contribute 8 | 9 | 1. Fork this repository, develop, and test your changes. 10 | 2. Submit a pull request. 11 | 12 | ### Requirements 13 | 14 | When submitting a PR make sure that: 15 | - It must pass CI jobs for linting and test the changes (if any). 16 | - It must follow [container best practices](https://engineering.bitnami.com/articles/best-practices-writing-a-dockerfile.html). 17 | - The title of the PR is clear enough. 18 | - If necessary, add information to the repository's `README.md`. 19 | 20 | ### PR Approval and Release Process 21 | 22 | 1. Changes are manually reviewed by Bitnami team members usually within a business day. 23 | 2. Once the changes are accepted, the PR is tested (if needed) into the Bitnami CI pipeline, the container is deployed and tested (verification and functional tests) using docker-compose and Helm (if there is an associated Helm Chart). 24 | 3. The PR is merged by the reviewer(s) in the GitHub `master` branch. 25 | 4. Then our CI/CD system is going to push the container image to the different registries including the recently merged changes. 26 | 27 | ***NOTE***: Please note that, in terms of time, may be a slight difference between the appearance of the code in GitHub and the image with the changes in the different registries. 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-2021 Bitnami 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | redis-node-0: 4 | image: docker.io/bitnami/redis-cluster:6.2 5 | volumes: 6 | - redis-cluster_data-0:/bitnami/redis/data 7 | environment: 8 | - 'REDIS_PASSWORD=bitnami' 9 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 10 | 11 | redis-node-1: 12 | image: docker.io/bitnami/redis-cluster:6.2 13 | volumes: 14 | - redis-cluster_data-1:/bitnami/redis/data 15 | environment: 16 | - 'REDIS_PASSWORD=bitnami' 17 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 18 | 19 | redis-node-2: 20 | image: docker.io/bitnami/redis-cluster:6.2 21 | volumes: 22 | - redis-cluster_data-2:/bitnami/redis/data 23 | environment: 24 | - 'REDIS_PASSWORD=bitnami' 25 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 26 | 27 | redis-node-3: 28 | image: docker.io/bitnami/redis-cluster:6.2 29 | volumes: 30 | - redis-cluster_data-3:/bitnami/redis/data 31 | environment: 32 | - 'REDIS_PASSWORD=bitnami' 33 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 34 | 35 | redis-node-4: 36 | image: docker.io/bitnami/redis-cluster:6.2 37 | volumes: 38 | - redis-cluster_data-4:/bitnami/redis/data 39 | environment: 40 | - 'REDIS_PASSWORD=bitnami' 41 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 42 | 43 | redis-node-5: 44 | image: docker.io/bitnami/redis-cluster:6.2 45 | volumes: 46 | - redis-cluster_data-5:/bitnami/redis/data 47 | depends_on: 48 | - redis-node-0 49 | - redis-node-1 50 | - redis-node-2 51 | - redis-node-3 52 | - redis-node-4 53 | environment: 54 | - 'REDIS_PASSWORD=bitnami' 55 | - 'REDISCLI_AUTH=bitnami' 56 | - 'REDIS_CLUSTER_REPLICAS=1' 57 | - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' 58 | - 'REDIS_CLUSTER_CREATOR=yes' 59 | 60 | volumes: 61 | redis-cluster_data-0: 62 | driver: local 63 | redis-cluster_data-1: 64 | driver: local 65 | redis-cluster_data-2: 66 | driver: local 67 | redis-cluster_data-3: 68 | driver: local 69 | redis-cluster_data-4: 70 | driver: local 71 | redis-cluster_data-5: 72 | driver: local 73 | --------------------------------------------------------------------------------