#!/usr/bin/env bash # This script was generated # Modifying it manually is not recommended check_bash_version() { if [ ! "${BASH_VERSINFO:-0}" -ge 4 ]; then echo "Bash version 4 or greater is required (got ${BASH_VERSINFO}), please update your bash version!" exit 1 fi } check_bash_version # :command.master_script # :command.version_command version_command() { echo "$version" } # :command.usage rcstack_usage() { if [[ -n $long_usage ]]; then printf "rcstack\n" echo printf " CLI for installing and managing RhodeCode Cluster Stack \nSupport:\n https://community.rhodecode.com\nDocs: https://docs.rhodecode.com/rcstack\n" echo else printf "rcstack - CLI for installing and managing RhodeCode Cluster Stack \nSupport: https://community.rhodecode.com\nDocs: https://docs.rhodecode.com/rcstack\n" echo fi printf "%s\n" "Usage:" printf " rcstack [OPTIONS] COMMAND\n" printf " rcstack [COMMAND] --help | -h\n" printf " rcstack --version | -v\n" echo # :command.usage_commands printf "%s\n" "Commands:" printf " %s Print instructions to get started with rhodecode docker stack\n" "get-started " printf " %s Bootstrap this machine, check docker version and install rhodecode-network\n" "init " printf " %s Update rcstack and it's docker definitions\n" "self-update " echo printf "%s\n" "Stack Commands:" printf " %s Run one of available cluster stacks, run stack -h for more details\n" "stack " printf " %s Show stack status\n" "stack-status " printf " %s Upgrade a stack, run stack-upgrade -h for more details\n" "stack-upgrade" printf " %s run monitoring on stack items\n" "stack-monitor" echo printf "%s\n" "CLI Commands:" printf " %s Various CLI tools, run cli -h for more details\n" "cli " echo printf "%s\n" "Backup Commands:" printf " %s Backup Database\n" "backup-db " printf " %s Backup RhodeCode storage\n" "backup-data " echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_flags # :flag.usage printf " %s\n" "--debug" printf " Enable debug and detailed output. Add --debug right after ./rcstack command.\n E.g. ./rcstack --debug COMMAND\n" echo # :flag.usage printf " %s\n" "--no-init-check" printf " Skip check for ./rcstack init call\n" echo # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo printf " %s\n" "--version, -v" printf " Show version number\n" echo # :command.usage_environment_variables printf "%s\n" "Environment Variables:" # :environment_variable.usage printf " %s\n" "RCC_CONFIG" printf " default config file for rcstack\n" printf " Default: .rcstack.ini\n" echo # :environment_variable.usage printf " %s\n" "AUTH_TOKEN" printf " Set your RhodeCode AUTH Token\n" echo # :environment_variable.usage printf " %s\n" "RC_STACK_ROUTER_EXT" printf "\n" printf " Default: .custom/docker-compose-router.override.yaml\n" echo # :environment_variable.usage printf " %s\n" "RC_STACK_METRICS_EXT" printf "\n" printf " Default: .custom/docker-compose-metrics.override.yaml\n" echo # :environment_variable.usage printf " %s\n" "RC_STACK_SERVICES_EXT" printf "\n" printf " Default: .custom/docker-compose-services.override.yaml\n" echo # :environment_variable.usage printf " %s\n" "RC_STACK_RHODECODE_EXT" printf "\n" printf " Default: .custom/docker-compose-apps.override.yaml\n" echo # :command.footer printf "RhodeCode Inc 2023\n\n" echo fi } # :command.usage rcstack_get_started_usage() { if [[ -n $long_usage ]]; then printf "rcstack get-started - Print instructions to get started with rhodecode docker stack\n" echo else printf "rcstack get-started - Print instructions to get started with rhodecode docker stack\n" echo fi printf "%s\n" "Usage:" printf " rcstack get-started\n" printf " rcstack get-started --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo fi } # :command.usage rcstack_init_usage() { if [[ -n $long_usage ]]; then printf "rcstack init - Bootstrap this machine, check docker version and install rhodecode-network\n" echo else printf "rcstack init - Bootstrap this machine, check docker version and install rhodecode-network\n" echo fi printf "%s\n" "Usage:" printf " rcstack init [OPTIONS]\n" printf " rcstack init --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_flags # :flag.usage printf " %s\n" "--arg-rc-edition ARG_RC_EDITION" printf " specify rc_edition [ee|ce] for setup\n" echo # :flag.usage printf " %s\n" "--arg-hostname ARG_HOSTNAME" printf " specify hostname [hostname.example.com] for setup\n" echo # :flag.usage printf " %s\n" "--arg-use-ssl ARG_USE_SSL" printf " specify use_ssl [y|n] for setup\n" echo # :flag.usage printf " %s\n" "--arg-admin-email ARG_ADMIN_EMAIL" printf " specify admin_email [foo@example.com] for setup\n" echo # :flag.usage printf " %s\n" "--arg-admin-user ARG_ADMIN_USER" printf " specify admin_user [admin] for setup\n" echo # :flag.usage printf " %s\n" "--arg-admin-pass ARG_ADMIN_PASS" printf " specify admin_pass [secretpassword] for setup\n" echo # :flag.usage printf " %s\n" "--arg-license-token ARG_ADMIN_TOKEN" printf " specify license_token [abcd-abcd-abcd-abcd] for setup\n" echo # :flag.usage printf " %s\n" "--no-prompt" printf " Don't use interactive prompt to ask setup questions. Use defaults instead\n" echo # :flag.usage printf " %s\n" "--force, -f" printf " Overwrite existing files\n" echo # :flag.usage printf " %s\n" "--stage STAGE (repeatable)" printf " specify one or more stages to run\n" echo # :flag.usage printf " %s\n" "--docker-revision DOCKER_REVISION" printf " revision to fetch new docker definitions.\n" printf " Default: stable\n" echo # :flag.usage printf " %s\n" "--install-docker INSTALL_DOCKER" printf " answer [y]es or [n]o to question to install docker\n" echo # :flag.usage printf " %s\n" "--server-url SERVER_URL" printf " Specify RhodeCode server location where the rcstack archive should be\n downloaded from\n" printf " Default: https://dls.rhodecode.com/get_archive\n" echo # :flag.usage printf " %s\n" "--auth-token AUTH_TOKEN" printf " Optionally specify AUTH TOKEN to obtain sources\n" echo # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_examples printf "%s\n" "Examples:" printf " - ./rcstack init\n - ./rcstack init --force\n # non-interactive mode to say yes to install docker question [n] always does\n not install docker\n - ./rcstack init --install-docker=y\n # non-interactive mode to answer setup questions use --help to check all\n --arg-NAME options\n - ./rcstack init --install-docker=y --arg-hostname=docker-dev --arg-use-ssl=n\n --arg-rc-edition=ee\n" echo fi } # :command.usage rcstack_self_update_usage() { if [[ -n $long_usage ]]; then printf "rcstack self-update - Update rcstack and it's docker definitions\n" echo else printf "rcstack self-update - Update rcstack and it's docker definitions\n" echo fi printf "%s\n" "Usage:" printf " rcstack self-update [OPTIONS]\n" printf " rcstack self-update --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_flags # :flag.usage printf " %s\n" "--force" printf " Ignore same-version skip check. Runs same logic as there would be new\n version available\n" echo # :flag.usage printf " %s\n" "--update-docker-image UPDATE_DOCKER_IMAGE" printf " answer [y]es or [n]o to question to set docker image from installer stored\n version.\n" echo # :flag.usage printf " %s\n" "--cli-revision CLI_REVISION" printf " commit or branch to fetch new rcstack cli tool.\n" printf " Default: stable\n" echo # :flag.usage printf " %s\n" "--docker-revision DOCKER_REVISION" printf " commit or branch to fetch new docker definitions.\n" printf " Default: stable\n" echo # :flag.usage printf " %s\n" "--server-url SERVER_URL" printf " Specify RhodeCode server location where the rcstack archive should be\n downloaded from\n" printf " Default: https://dls.rhodecode.com/get_archive\n" echo # :flag.usage printf " %s\n" "--auth-token AUTH_TOKEN" printf " Optionally specify AUTH TOKEN to obtain sources\n" echo # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_examples printf "%s\n" "Examples:" printf " # simply to update it to a new version\n - ./rccstack self-update \n \n # to fetch dev branch and install it\n - ./rccstack self-update --cli-revision=master --docker-revision=master\n \n # In case rcstack breaks, you can re-download the stack script using curl\n curl -L -s -o rcstack https://dls.rhodecode.com/get/stable && chmod +x rcstack\n" echo fi } # :command.usage rcstack_stack_usage() { if [[ -n $long_usage ]]; then printf "rcstack stack - Run one of available cluster stacks, run stack -h for more details\n" echo else printf "rcstack stack - Run one of available cluster stacks, run stack -h for more details\n" echo fi printf "%s\n" "Usage:" printf " rcstack stack [OPTIONS] COMMAND\n" printf " rcstack stack [COMMAND] --help | -h\n" echo # :command.usage_commands printf "%s\n" "Commands:" printf " %s execute commands for the router stack\n" "router " printf " %s execute commands for the router stack\n" "metrics " printf " %s execute commands for the router stack\n" "services " printf " %s execute commands for the router stack\n" "rhodecode" printf " %s execute commands for all stacks in order\n" "all " echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_flags # :flag.usage printf " %s\n" "--env-file-path ENV_FILE_PATH" printf " Set custom env file\n" printf " Default: $PWD/.custom/.runtime.env\n" echo # :flag.usage printf " %s\n" "--stack-prefix STACK_PREFIX" printf " Set custom stack prefix, e.g rc_cluster_apps_ci\n" echo # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_examples printf "%s\n" "Examples:" printf " # running stack (example for router stack)\n - ./rcstack stack router up # run router stack with output to stdout\n - ./rcstack stack router up --detach # run router stack detached\n - ./rcstack stack router down # stop whole router stack\n - ./rcstack stack router restart # restart the stack\n - ./rcstack stack router ps # check status of router stack\n \n # logs, use logs -f to follow/tail --until 1h to limit for last time\n - ./rcstack stack services logs -f database\n \n # scale a single stack service[s] to more replicas (horizontally), use\n overrides files to permanently set scale\n - ./rcstack stack rhodecode up --detach --no-recreate --scale rhodecode=2\n --scale vcsserver=2\n \n # run router stack with your overrides compose file\n - ./rcstack stack router -f docker-overrides.yaml up -d\n \n # run command in the stack image\n - ./rcstack stack rhodecode run rhodecode bash\n" echo fi } # :command.usage rcstack_stack_router_usage() { if [[ -n $long_usage ]]; then printf "rcstack stack router - execute commands for the router stack\n" echo else printf "rcstack stack router - execute commands for the router stack\n" echo fi printf "%s\n" "Usage:" printf " rcstack stack router [SERVICES PARAMS...]\n" printf " rcstack stack router --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_args printf "%s\n" "Arguments:" echo " SERVICES PARAMS..." printf " Additional arguments or flags for services command\n" echo fi } # :command.usage rcstack_stack_metrics_usage() { if [[ -n $long_usage ]]; then printf "rcstack stack metrics - execute commands for the router stack\n" echo else printf "rcstack stack metrics - execute commands for the router stack\n" echo fi printf "%s\n" "Usage:" printf " rcstack stack metrics [SERVICES PARAMS...]\n" printf " rcstack stack metrics --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_args printf "%s\n" "Arguments:" echo " SERVICES PARAMS..." printf " Additional arguments or flags for services command\n" echo fi } # :command.usage rcstack_stack_services_usage() { if [[ -n $long_usage ]]; then printf "rcstack stack services - execute commands for the router stack\n" echo else printf "rcstack stack services - execute commands for the router stack\n" echo fi printf "%s\n" "Usage:" printf " rcstack stack services [SERVICES PARAMS...]\n" printf " rcstack stack services --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_args printf "%s\n" "Arguments:" echo " SERVICES PARAMS..." printf " Additional arguments or flags for services command\n" echo fi } # :command.usage rcstack_stack_rhodecode_usage() { if [[ -n $long_usage ]]; then printf "rcstack stack rhodecode - execute commands for the router stack\n" echo else printf "rcstack stack rhodecode - execute commands for the router stack\n" echo fi printf "%s\n" "Usage:" printf " rcstack stack rhodecode [SERVICES PARAMS...]\n" printf " rcstack stack rhodecode --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_args printf "%s\n" "Arguments:" echo " SERVICES PARAMS..." printf " Additional arguments or flags for services command\n" echo fi } # :command.usage rcstack_stack_all_usage() { if [[ -n $long_usage ]]; then printf "rcstack stack all - execute commands for all stacks in order\n" echo else printf "rcstack stack all - execute commands for all stacks in order\n" echo fi printf "%s\n" "Usage:" printf " rcstack stack all [SERVICES PARAMS...]\n" printf " rcstack stack all --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_args printf "%s\n" "Arguments:" echo " SERVICES PARAMS..." printf " Additional arguments or flags for services command\n" echo fi } # :command.usage rcstack_stack_status_usage() { if [[ -n $long_usage ]]; then printf "rcstack stack-status - Show stack status\n" echo else printf "rcstack stack-status - Show stack status\n" echo fi printf "Alias: status\n" echo printf "%s\n" "Usage:" printf " rcstack stack-status [OPTIONS]\n" printf " rcstack stack-status --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_flags # :flag.usage printf " %s\n" "--detailed" printf " Display a detailed format\n" echo # :flag.usage printf " %s\n" "--configs" printf " Display a detailed info about configuration files\n" echo # :flag.usage printf " %s\n" "-v" printf " Verbose output for details on the stack\n" echo # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo fi } # :command.usage rcstack_stack_upgrade_usage() { if [[ -n $long_usage ]]; then printf "rcstack stack-upgrade - Upgrade a stack, run stack-upgrade -h for more details\n" echo else printf "rcstack stack-upgrade - Upgrade a stack, run stack-upgrade -h for more details\n" echo fi printf "%s\n" "Usage:" printf " rcstack stack-upgrade [OPTIONS] COMMAND\n" printf " rcstack stack-upgrade [COMMAND] --help | -h\n" echo # :command.usage_commands printf "%s\n" "Commands:" printf " %s upgrade the router stack\n" "router " printf " %s upgrade the services stack\n" "services " printf " %s upgrade the metrics stack\n" "metrics " printf " %s upgrade the rhodecode stack\n" "rhodecode" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_flags # :flag.usage printf " %s\n" "--stack-prefix STACK_PREFIX" printf " Set custom stack prefix, e.g rc_cluster_apps_ci\n" echo # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_examples printf "%s\n" "Examples:" printf " # Upgrading stack\n - ./rcstack stack-upgrade router\n \n # RhodeCode stack upgrades with 0 downtime using container rotation\n - ./rcstack stack-upgrade rhodecode\n \n # RhodeCode stack upgrades with fast container restart recycle, might cause\n slight downtime\n - ./rcstack stack-upgrade rhodecode --stop-wait=10 --docker-stop-wait=5\n" echo fi } # :command.usage rcstack_stack_upgrade_router_usage() { if [[ -n $long_usage ]]; then printf "rcstack stack-upgrade router - upgrade the router stack\n" echo else printf "rcstack stack-upgrade router - upgrade the router stack\n" echo fi printf "%s\n" "Usage:" printf " rcstack stack-upgrade router\n" printf " rcstack stack-upgrade router --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo fi } # :command.usage rcstack_stack_upgrade_services_usage() { if [[ -n $long_usage ]]; then printf "rcstack stack-upgrade services - upgrade the services stack\n" echo else printf "rcstack stack-upgrade services - upgrade the services stack\n" echo fi printf "%s\n" "Usage:" printf " rcstack stack-upgrade services\n" printf " rcstack stack-upgrade services --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo fi } # :command.usage rcstack_stack_upgrade_metrics_usage() { if [[ -n $long_usage ]]; then printf "rcstack stack-upgrade metrics - upgrade the metrics stack\n" echo else printf "rcstack stack-upgrade metrics - upgrade the metrics stack\n" echo fi printf "%s\n" "Usage:" printf " rcstack stack-upgrade metrics\n" printf " rcstack stack-upgrade metrics --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo fi } # :command.usage rcstack_stack_upgrade_rhodecode_usage() { if [[ -n $long_usage ]]; then printf "rcstack stack-upgrade rhodecode - upgrade the rhodecode stack\n" echo else printf "rcstack stack-upgrade rhodecode - upgrade the rhodecode stack\n" echo fi printf "%s\n" "Usage:" printf " rcstack stack-upgrade rhodecode [OPTIONS]\n" printf " rcstack stack-upgrade rhodecode --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_flags # :flag.usage printf " %s\n" "--stop-wait STOP_WAIT" printf " Number of seconds to wait for stopping old containers, use low value to\n quickly restart and recycle containers\n" printf " Default: 120\n" echo # :flag.usage printf " %s\n" "--docker-stop-wait DOCKER_STOP_WAIT" printf " Number of seconds to pass to docker stop command that will wait for\n container to gracefully stop\n" printf " Default: 3600\n" echo # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo fi } # :command.usage rcstack_stack_monitor_usage() { if [[ -n $long_usage ]]; then printf "rcstack stack-monitor - run monitoring on stack items\n" echo else printf "rcstack stack-monitor - run monitoring on stack items\n" echo fi printf "%s\n" "Usage:" printf " rcstack stack-monitor COMMAND\n" printf " rcstack stack-monitor [COMMAND] --help | -h\n" echo # :command.usage_commands printf "%s\n" "Stack Commands:" printf " %s monitor stack containers that are unhealthy and restart them\n" "restart-unhealthy" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo fi } # :command.usage rcstack_stack_monitor_restart_unhealthy_usage() { if [[ -n $long_usage ]]; then printf "rcstack stack-monitor restart-unhealthy - monitor stack containers that are unhealthy and restart them\n" echo else printf "rcstack stack-monitor restart-unhealthy - monitor stack containers that are unhealthy and restart them\n" echo fi printf "%s\n" "Usage:" printf " rcstack stack-monitor restart-unhealthy [OPTIONS]\n" printf " rcstack stack-monitor restart-unhealthy --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_flags # :flag.usage printf " %s\n" "--loop LOOP" printf " run in a loop to monitor continuously every N seconds\n" printf " Default: 0\n" echo # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_examples printf "%s\n" "Examples:" printf " # check and restart for unhealthy containers\n ./rcstack stack-monitor restart-unhealthy\n \n # check and restart for unhealthy containers, and continue in a loop every 5\n minutes (300s)\n ./rcstack stack-monitor restart-unhealthy --loop=300\n \n # run this script in background with logs\n nohup ./rcstack stack-monitor restart-unhealthy --loop=300 >\n unhealthy-checks.log &\n" echo fi } # :command.usage rcstack_cli_usage() { if [[ -n $long_usage ]]; then printf "rcstack cli - Various CLI tools, run cli -h for more details\n" echo else printf "rcstack cli - Various CLI tools, run cli -h for more details\n" echo fi printf "%s\n" "Usage:" printf " rcstack cli COMMAND\n" printf " rcstack cli [COMMAND] --help | -h\n" echo # :command.usage_commands printf "%s\n" "Commands:" printf " %s run a custom command on top of docker image from RhodeCode\n" "cmd " printf " %s ishell attached to running RhodeCode instance\n" "ishell " printf " %s print out stored docker image version\n" "image-info " printf " %s set version to .runtime.env file\n" "set-runtime-image " printf " %s get current docker info\n" "docker-info " printf " %s force upgrade docker\n" "docker-upgrade " printf " %s CLI for Redis\n" "redis " printf " %s CLI with Database connection\n" "db " printf " %s CLI to run db upgrade\n" "db-upgrade " printf " %s CLI for repository storage. Exposes a basic image with mounted data and repositories volumes or attach to currently running containers storage\n" "storage " printf " %s attach to running instance of RhodeCode, by default it attaches to rhodecode main web app\n" "attach " printf " %s set current setup to either CE (Community) or EE (Enterprise) type\n" "set-edition " printf " %s reconfigure the vcsserver.ini file\n" "configure-vcsserver" printf " %s reconfigure the rhodecode.ini file\n" "configure-rhodecode" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo fi } # :command.usage rcstack_cli_cmd_usage() { if [[ -n $long_usage ]]; then printf "rcstack cli cmd - run a custom command on top of docker image from RhodeCode\n" echo else printf "rcstack cli cmd - run a custom command on top of docker image from RhodeCode\n" echo fi printf "%s\n" "Usage:" printf " rcstack cli cmd [OPTIONS] [CALL ARGUMENTS...]\n" printf " rcstack cli cmd --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_flags # :flag.usage printf " %s\n" "--no-tty" printf " when running docker command don't attach to TTY. Useful for running a script\n out of shell context, e.g crontab\n" echo # :flag.usage printf " %s\n" "--user" printf " User to run the command as, e.g root / rhodecode\n" echo # :flag.usage printf " %s\n" "--env-file-path ENV_FILE_PATH" printf " Set custom env file\n" printf " Default: $PWD/.custom/.runtime.env\n" echo # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_args printf "%s\n" "Arguments:" echo " CALL ARGUMENTS..." printf " call arguments\n" echo fi } # :command.usage rcstack_cli_ishell_usage() { if [[ -n $long_usage ]]; then printf "rcstack cli ishell - ishell attached to running RhodeCode instance\n" echo else printf "rcstack cli ishell - ishell attached to running RhodeCode instance\n" echo fi printf "%s\n" "Usage:" printf " rcstack cli ishell [OPTIONS]\n" printf " rcstack cli ishell --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_flags # :flag.usage printf " %s\n" "--no-tty" printf " when running docker command don't attach to TTY. Useful for running a script\n out of shell context, e.g crontab\n" echo # :flag.usage printf " %s\n" "--user" printf " User to run the command as, e.g root / rhodecode\n" echo # :flag.usage printf " %s\n" "--env-file-path ENV_FILE_PATH" printf " Set custom env file\n" printf " Default: $PWD/.custom/.runtime.env\n" echo # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo fi } # :command.usage rcstack_cli_image_info_usage() { if [[ -n $long_usage ]]; then printf "rcstack cli image-info - print out stored docker image version\n" echo else printf "rcstack cli image-info - print out stored docker image version\n" echo fi printf "%s\n" "Usage:" printf " rcstack cli image-info [OPTIONS]\n" printf " rcstack cli image-info --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_flags # :flag.usage printf " %s\n" "--verbose" printf " rich output about image\n" echo # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo fi } # :command.usage rcstack_cli_set_runtime_image_usage() { if [[ -n $long_usage ]]; then printf "rcstack cli set-runtime-image - set version to .runtime.env file\n" echo else printf "rcstack cli set-runtime-image - set version to .runtime.env file\n" echo fi printf "%s\n" "Usage:" printf " rcstack cli set-runtime-image VERSION\n" printf " rcstack cli set-runtime-image --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_args printf "%s\n" "Arguments:" # :argument.usage printf " %s\n" "VERSION" printf " Version of docker image to set e.g '5.0.0'\n" echo fi } # :command.usage rcstack_cli_docker_info_usage() { if [[ -n $long_usage ]]; then printf "rcstack cli docker-info - get current docker info\n" echo else printf "rcstack cli docker-info - get current docker info\n" echo fi printf "%s\n" "Usage:" printf " rcstack cli docker-info [OPTIONS]\n" printf " rcstack cli docker-info --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_flags # :flag.usage printf " %s\n" "--verbose" printf " rich output about docker\n" echo # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo fi } # :command.usage rcstack_cli_docker_upgrade_usage() { if [[ -n $long_usage ]]; then printf "rcstack cli docker-upgrade - force upgrade docker\n" echo else printf "rcstack cli docker-upgrade - force upgrade docker\n" echo fi printf "%s\n" "Usage:" printf " rcstack cli docker-upgrade [OPTIONS]\n" printf " rcstack cli docker-upgrade --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_flags # :flag.usage printf " %s\n" "--compose" printf " run an upgrade of docker compose to latest version\n" echo # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo fi } # :command.usage rcstack_cli_redis_usage() { if [[ -n $long_usage ]]; then printf "rcstack cli redis - CLI for Redis\n" echo else printf "rcstack cli redis - CLI for Redis\n" echo fi printf "%s\n" "Usage:" printf " rcstack cli redis [OPTIONS]\n" printf " rcstack cli redis --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_flags # :flag.usage printf " %s\n" "--no-tty" printf " when running docker command don't attach to TTY. Useful for running a script\n out of shell context, e.g crontab\n" echo # :flag.usage printf " %s\n" "--user" printf " User to run the command as, e.g root / rhodecode\n" echo # :flag.usage printf " %s\n" "--env-file-path ENV_FILE_PATH" printf " Set custom env file\n" printf " Default: $PWD/.custom/.runtime.env\n" echo # :flag.usage printf " %s\n" "--db DB" printf " select Redis db, defaults 0\n" printf " Default: 0\n" echo # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_examples printf "%s\n" "Examples:" printf " # run the redis CLI\n - ./rcstack cli redis\n # run a command without TTY\n - echo 'KEYS *' | ./rcstack cli redis --no-tty\n" echo fi } # :command.usage rcstack_cli_db_usage() { if [[ -n $long_usage ]]; then printf "rcstack cli db - CLI with Database connection\n" echo else printf "rcstack cli db - CLI with Database connection\n" echo fi printf "%s\n" "Usage:" printf " rcstack cli db [OPTIONS]\n" printf " rcstack cli db --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_flags # :flag.usage printf " %s\n" "--no-tty" printf " when running docker command don't attach to TTY. Useful for running a script\n out of shell context, e.g crontab\n" echo # :flag.usage printf " %s\n" "--user" printf " User to run the command as, e.g root / rhodecode\n" echo # :flag.usage printf " %s\n" "--env-file-path ENV_FILE_PATH" printf " Set custom env file\n" printf " Default: $PWD/.custom/.runtime.env\n" echo # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_examples printf "%s\n" "Examples:" printf " # restore backup\n - \i /var/rc-data-dump/your_dump.sql\n" echo fi } # :command.usage rcstack_cli_db_upgrade_usage() { if [[ -n $long_usage ]]; then printf "rcstack cli db-upgrade - CLI to run db upgrade\n" echo else printf "rcstack cli db-upgrade - CLI to run db upgrade\n" echo fi printf "%s\n" "Usage:" printf " rcstack cli db-upgrade\n" printf " rcstack cli db-upgrade --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo fi } # :command.usage rcstack_cli_storage_usage() { if [[ -n $long_usage ]]; then printf "rcstack cli storage - CLI for repository storage. Exposes a basic image with mounted data and repositories volumes or attach to currently running containers storage\n" echo else printf "rcstack cli storage - CLI for repository storage. Exposes a basic image with mounted data and repositories volumes or attach to currently running containers storage\n" echo fi printf "%s\n" "Usage:" printf " rcstack cli storage [OPTIONS]\n" printf " rcstack cli storage --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_flags # :flag.usage printf " %s\n" "--no-tty" printf " when running docker command don't attach to TTY. Useful for running a script\n out of shell context, e.g crontab\n" echo # :flag.usage printf " %s\n" "--attached ATTACHED" printf " attach to storage of already running vcsserver container instead\n" echo # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo fi } # :command.usage rcstack_cli_attach_usage() { if [[ -n $long_usage ]]; then printf "rcstack cli attach - attach to running instance of RhodeCode, by default it attaches to rhodecode main web app\n" echo else printf "rcstack cli attach - attach to running instance of RhodeCode, by default it attaches to rhodecode main web app\n" echo fi printf "%s\n" "Usage:" printf " rcstack cli attach [OPTIONS]\n" printf " rcstack cli attach --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_flags # :flag.usage printf " %s\n" "--no-tty" printf " when running docker command don't attach to TTY. Useful for running a script\n out of shell context, e.g crontab\n" echo # :flag.usage printf " %s\n" "--instance-type INSTANCE_TYPE" printf " type of instance to attach to\n" printf " Default: rhodecode\n" echo # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_examples printf "%s\n" "Examples:" printf " ./rcstack cli attach --instance-type sshd\n ./rcstack cli attach --instance-type vcsserver\n ./rcstack cli attach --instance-type celery\n ./rcstack cli attach --instance-type celery-beat\n" echo fi } # :command.usage rcstack_cli_set_edition_usage() { if [[ -n $long_usage ]]; then printf "rcstack cli set-edition - set current setup to either CE (Community) or EE (Enterprise) type\n" echo else printf "rcstack cli set-edition - set current setup to either CE (Community) or EE (Enterprise) type\n" echo fi printf "%s\n" "Usage:" printf " rcstack cli set-edition EDITION_TYPE\n" printf " rcstack cli set-edition --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_args printf "%s\n" "Arguments:" # :argument.usage printf " %s\n" "EDITION_TYPE" printf " pick type CE or EE\n" printf " Allowed: ce, ee\n" echo # :command.usage_examples printf "%s\n" "Examples:" printf " ./rcstack set-edition ce\n" printf " ./rcstack set-edition ee\n" echo fi } # :command.usage rcstack_cli_configure_vcsserver_usage() { if [[ -n $long_usage ]]; then printf "rcstack cli configure-vcsserver - reconfigure the vcsserver.ini file\n" echo else printf "rcstack cli configure-vcsserver - reconfigure the vcsserver.ini file\n" echo fi printf "%s\n" "Usage:" printf " rcstack cli configure-vcsserver INI_PATH\n" printf " rcstack cli configure-vcsserver --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_args printf "%s\n" "Arguments:" # :argument.usage printf " %s\n" "INI_PATH" printf " Path to vcsserver.ini to reconfigure\n" echo # :command.usage_examples printf "%s\n" "Examples:" printf " ./rcstack cli configure-vcs config/_shared/vcsserver.ini\n" echo fi } # :command.usage rcstack_cli_configure_rhodecode_usage() { if [[ -n $long_usage ]]; then printf "rcstack cli configure-rhodecode - reconfigure the rhodecode.ini file\n" echo else printf "rcstack cli configure-rhodecode - reconfigure the rhodecode.ini file\n" echo fi printf "%s\n" "Usage:" printf " rcstack cli configure-rhodecode INI_PATH\n" printf " rcstack cli configure-rhodecode --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_args printf "%s\n" "Arguments:" # :argument.usage printf " %s\n" "INI_PATH" printf " Path to rhodecode.ini to reconfigure\n" echo # :command.usage_examples printf "%s\n" "Examples:" printf " ./rcstack cli configure-rhodecode config/_shared/rhodecode.ini\n" echo fi } # :command.usage rcstack_backup_db_usage() { if [[ -n $long_usage ]]; then printf "rcstack backup-db - Backup Database\n" echo else printf "rcstack backup-db - Backup Database\n" echo fi printf "%s\n" "Usage:" printf " rcstack backup-db DESTINATION\n" printf " rcstack backup-db --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_args printf "%s\n" "Arguments:" # :argument.usage printf " %s\n" "DESTINATION" printf " Destination directory to store backup archive\n" echo # :command.usage_examples printf "%s\n" "Examples:" printf " # make backup gz compressed from container DB\n - ./rcstack backup-db /home/my-db-backup\n \n # restore backup\n - gunzip your_dump.sql.gz\n - ./rcstack cli db\n - \i /var/rc-data-dump/your_dump.sql\n" echo fi } # :command.usage rcstack_backup_data_usage() { if [[ -n $long_usage ]]; then printf "rcstack backup-data - Backup RhodeCode storage\n" echo else printf "rcstack backup-data - Backup RhodeCode storage\n" echo fi printf "%s\n" "Usage:" printf " rcstack backup-data DESTINATION\n" printf " rcstack backup-data --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo # :command.usage_args printf "%s\n" "Arguments:" # :argument.usage printf " %s\n" "DESTINATION" printf " Destination directory to store backup archive\n" echo # :command.usage_examples printf "%s\n" "Examples:" printf " # make backup gz compressed for rhodecode containers, and all volumes\n - ./rcstack backup-data /home/my-data-backup\n" echo fi } # :command.usage rcstack__completions_usage() { if [[ -n $long_usage ]]; then printf "rcstack _completions - Generate completions\n" echo else printf "rcstack _completions - Generate completions\n" echo fi printf "%s\n" "Usage:" printf " rcstack _completions\n" printf " rcstack _completions --help | -h\n" echo # :command.long_usage if [[ -n $long_usage ]]; then printf "%s\n" "Options:" # :command.usage_fixed_flags printf " %s\n" "--help, -h" printf " Show this help\n" echo fi } # :command.normalize_input normalize_input() { local arg flags while [[ $# -gt 0 ]]; do arg="$1" if [[ $arg =~ ^(--[a-zA-Z0-9_\-]+)=(.+)$ ]]; then input+=("${BASH_REMATCH[1]}") input+=("${BASH_REMATCH[2]}") elif [[ $arg =~ ^(-[a-zA-Z0-9])=(.+)$ ]]; then input+=("${BASH_REMATCH[1]}") input+=("${BASH_REMATCH[2]}") elif [[ $arg =~ ^-([a-zA-Z0-9][a-zA-Z0-9]+)$ ]]; then flags="${BASH_REMATCH[1]}" for ((i = 0; i < ${#flags}; i++)); do input+=("-${flags:i:1}") done else input+=("$arg") fi shift done } # :command.inspect_args inspect_args() { if ((${#args[@]})); then readarray -t sorted_keys < <(printf '%s\n' "${!args[@]}" | sort) echo args: for k in "${sorted_keys[@]}"; do echo "- \${args[$k]} = ${args[$k]}"; done else echo args: none fi if ((${#other_args[@]})); then echo echo other_args: echo "- \${other_args[*]} = ${other_args[*]}" for i in "${!other_args[@]}"; do echo "- \${other_args[$i]} = ${other_args[$i]}" done fi if ((${#deps[@]})); then readarray -t sorted_keys < <(printf '%s\n' "${!deps[@]}" | sort) echo echo deps: for k in "${sorted_keys[@]}"; do echo "- \${deps[$k]} = ${deps[$k]}"; done fi } # :command.user_lib # src/lib/check_bootstrap.sh check_bootstrap() { # Avoid destroying bootstrapping by simple start/stop for stage_name in $BOOTSTRAP_STAGES; do if ! config_has_key $stage_name ; then echo "$(yellow WARNING:) Bootstrap key $stage_name not found in config file $CONFIG_FILE!" echo "$(yellow NOTICE:) Run this first: ./$RC_SCRIPT_NAME init" exit fi done } # src/lib/colors.sh print_in_color() { local color="$1" shift if [[ -z ${NO_COLOR+x} ]]; then printf "$color%b\e[0m\n" "$*" else printf "%b\n" "$*" fi } red() { print_in_color "\e[31m" "$*"; } green() { print_in_color "\e[32m" "$*"; } yellow() { print_in_color "\e[33m" "$*"; } blue() { print_in_color "\e[34m" "$*"; } magenta() { print_in_color "\e[35m" "$*"; } cyan() { print_in_color "\e[36m" "$*"; } bold() { print_in_color "\e[1m" "$*"; } underlined() { print_in_color "\e[4m" "$*"; } red_bold() { print_in_color "\e[1;31m" "$*"; } green_bold() { print_in_color "\e[1;32m" "$*"; } yellow_bold() { print_in_color "\e[1;33m" "$*"; } blue_bold() { print_in_color "\e[1;34m" "$*"; } magenta_bold() { print_in_color "\e[1;35m" "$*"; } cyan_bold() { print_in_color "\e[1;36m" "$*"; } red_underlined() { print_in_color "\e[4;31m" "$*"; } green_underlined() { print_in_color "\e[4;32m" "$*"; } yellow_underlined() { print_in_color "\e[4;33m" "$*"; } blue_underlined() { print_in_color "\e[4;34m" "$*"; } magenta_underlined() { print_in_color "\e[4;35m" "$*"; } cyan_underlined() { print_in_color "\e[4;36m" "$*"; } # src/lib/config.sh config_show() { config_load ini_show } config_get() { local key="$1" local default_value="$2" config_load echo "${ini["$key"]:-$default_value}" } config_set() { local key="$1" shift local value="$*" config_load ini["$key"]="$value" config_save } config_del() { local key="$1" config_load unset "ini[$key]" config_save } config_keys() { config_load ini_keys } config_has_key() { [[ $(config_get "$1") ]] } config_reload() { declare -g config_loaded=false config_load } config_load() { [[ "$config_loaded" == "true" ]] && return declare -g CONFIG_FILE=${CONFIG_FILE:=config.ini} declare -g config_loaded=true [[ -f "$CONFIG_FILE" ]] || touch "$CONFIG_FILE" ini_load "$CONFIG_FILE" } config_save() { ini_save "$CONFIG_FILE" } # src/lib/dotenv.sh __dotenv= __dotenv_file= __dotenv_cmd=.env .env() { REPLY=() [[ $__dotenv_file || ${1-} == -* ]] || .env.--file .env || return if declare -F -- ".env.${1-}" >/dev/null; then .env."$@"; return ; fi .env --help >&2; return 64 } .env.-f() { .env.--file "$@"; } .env.get() { .env::arg "get requires a key" "$@" && [[ "$__dotenv" =~ ^(.*(^|$'\n'))([ ]*)"$1="(.*)$ ]] && REPLY=${BASH_REMATCH[4]%%$'\n'*} && REPLY=${REPLY%"${REPLY##*[![:space:]]}"} } .env.get_or_error() { .env.get "$@" || { echo "$(red ERROR required key $@ not set in $RUNTIME_ENV file)"; exit 1; } } .env.parse() { local line key while IFS= read -r line; do line=${line#"${line%%[![:space:]]*}"} # trim leading whitespace line=${line%"${line##*[![:space:]]}"} # trim trailing whitespace if [[ ! "$line" || "$line" == '#'* ]]; then continue ; fi if (($#)); then for key; do if [[ $key == "${line%%=*}" ]]; then REPLY+=("$line"); break; fi done else REPLY+=("$line") fi done <<<"$__dotenv" ((${#REPLY[@]})) } .env.export() { ! .env.parse "$@" || export "${REPLY[@]}"; } .env.set() { .env::file load || return ; local key saved=$__dotenv while (($#)); do key=${1#+}; key=${key%%=*} if .env.get "$key"; then REPLY=() if [[ $1 == +* ]]; then shift; continue # skip if already found elif [[ $1 == *=* ]]; then __dotenv=${BASH_REMATCH[1]}${BASH_REMATCH[3]}$1$'\n'${BASH_REMATCH[4]#*$'\n'} else __dotenv=${BASH_REMATCH[1]}${BASH_REMATCH[4]#*$'\n'} continue # delete all occurrences fi elif [[ $1 == *=* ]]; then __dotenv+="${1#+}"$'\n' fi shift done [[ $__dotenv == "$saved" ]] || .env::file save } .env.puts() { echo "${1-}">>"$__dotenv_file" && __dotenv+="$1"$'\n'; } .env.generate() { .env::arg "key required for generate" "$@" || return .env.get "$1" && return || REPLY=$("${@:2}") || return .env::one "generate: ouptut of '${*:2}' has more than one line" "$REPLY" || return .env.puts "$1=$REPLY" } .env.--file() { .env::arg "filename required for --file" "$@" || return __dotenv_file=$1; .env::file load || return (($#<2)) || .env "${@:2}" } .env::arg() { [[ "${2-}" ]] || { echo "$__dotenv_cmd: $1" >&2; return 64; }; } .env::one() { [[ "$2" != *$'\n'* ]] || .env::arg "$1"; } .env::file() { local REPLY=$__dotenv_file case "$1" in load) __dotenv=; ! [[ -f "$REPLY" ]] || __dotenv="$(<"$REPLY")"$'\n' || return ;; save) if [[ -L "$REPLY" ]] && declare -F -- realpath.resolved >/dev/null; then realpath.resolved "$REPLY" fi { [[ ! -f "$REPLY" ]] || cp -p "$REPLY" "$REPLY.bak"; } && printf %s "$__dotenv" >"$REPLY.bak" && mv "$REPLY.bak" "$REPLY" esac } # #__dotenv() { # set -eu # __dotenv_cmd=${0##*/} # .env.export() { .env.parse "$@" || return 0; printf 'export %q\n' "${REPLY[@]}"; REPLY=(); } # .env "$@" || return $? # ${REPLY[@]+printf '%s\n' "${REPLY[@]}"} #} #if [[ $0 == "${BASH_SOURCE-}" ]]; then __dotenv "$@"; exit; fi # src/lib/get_docker_definitions.sh get_docker_definitions() { SOURCE_DIR=$PWD RHODECODE_DOCKER_HASH=$1 FULL_MODE=$2 DEBUG=$3 final_archive_url="$SERVER_URL/$RHODECODE_DOCKER_HASH.tgz" extracted_archive_dir="rhodecode-enterprise-docker-id-bacb-sub-0-archive-all" # download sources echo "bootstrap_definitions: download rhodecode docker definitions from: $final_archive_url" echo "" if [ $DEBUG ]; then echo "bootstrap_definitions: downloading: $SERVER_URL/$RHODECODE_DOCKER_HASH.tgz" curl --header "X-Rc-Auth-Token: $AUTH_TOKEN" -L $final_archive_url | tar -xz -C $SOURCE_DIR echo "extracted archive to $SOURCE_DIR" echo "bootstrap_definitions: running CP $SOURCE_DIR/$extracted_archive_dir/* $SOURCE_DIR" cp_backup_verbose $SOURCE_DIR/$extracted_archive_dir/* $SOURCE_DIR echo "bootstrap_definitions: removing $SOURCE_DIR/$extracted_archive_dir" rm -r $SOURCE_DIR/$extracted_archive_dir else curl -s --header "X-Rc-Auth-Token: $AUTH_TOKEN" -L $final_archive_url | tar -xz -C $SOURCE_DIR cp_backup $SOURCE_DIR/$extracted_archive_dir/* $SOURCE_DIR rm -r $SOURCE_DIR/$extracted_archive_dir fi echo "$(green bootstrap_definitions: docker definitions extracted to $SOURCE_DIR)" # cleanup of backup files, just good to have, ignore any warnings # NOTE: Disabled for backward compat #find "$SOURCE_DIR" -nowarn -ignore_readdir_race -iname "*.~*~" -delete 2> /dev/null # some cleanup of things we don't need in cli if [[ ! $FULL_MODE ]]; then rm dev-tools rm -r scripts/dev-tools rm -r entrypoints.d fi } # src/lib/ini.sh ini_load() { declare -gA ini local ini_file="$1" local section="" local key="" local value="" local section_regex="^\[(.+)\]" local key_regex="^([^ =]+) *= *(.*) *$" local comment_regex="^;" while IFS= read -r line; do if [[ $line =~ $comment_regex ]]; then continue elif [[ $line =~ $section_regex ]]; then section="${BASH_REMATCH[1]}." elif [[ $line =~ $key_regex ]]; then key="${BASH_REMATCH[1]}" value="${BASH_REMATCH[2]}" ini["${section}${key}"]="$value" fi done <"$ini_file" } ini_save() { declare -gA ini local ini_file="$1" local current_section="" local has_free_keys=false rm -f "$ini_file" for key in $(ini_keys); do [[ $key == *.* ]] && continue has_free_keys=true value="${ini[$key]}" echo "$key = $value" >>"$ini_file" done [[ "${has_free_keys}" == "true" ]] && echo >>"$ini_file" for key in $(ini_keys); do [[ $key == *.* ]] || continue value="${ini[$key]}" IFS="." read -r section_name key_name <<<"$key" if [[ "$current_section" != "$section_name" ]]; then [[ $current_section ]] && echo >>"$ini_file" echo "[$section_name]" >>"$ini_file" current_section="$section_name" fi echo "$key_name = $value" >>"$ini_file" done } ini_show() { declare -gA ini for key in $(ini_keys); do echo "$key = ${ini[$key]}" done } ini_keys() { declare -gA ini local keys=("${!ini[@]}") for a in "${keys[@]}"; do echo "$a"; done | sort } # src/lib/reconfigure_ini.sh sed_replace() { if [[ $ini_path == "" ]]; then echo "ERROR: missing 'ini_path' variable" fi sed_func "$1" "$2" "$ini_path" } sed_safe_path() { echo $((echo $1|sed -r 's/([\$\.\*\/\[\\^])/\\\1/g'|sed 's/[]]/\[]]/g')>&1) } config_vcsserver_ini() { #host/port sed_replace '^#?host = .*' 'host = 0\.0\.0\.0' sed_replace '^#?port = .*' 'port = 10010' # workers adjustment sed_replace '^#?workers = .*' 'workers = 1' sed_replace '^#?memory_max_usage = .*' 'memory_max_usage = 2147483648' sed_replace '^#?core\.binary_dir = .*' 'core.binary_dir = \/usr\/local\/bin\/rhodecode_bin\/vcs_bin' sed_replace '^#?rc_cache\.repo_object\.expiration_time = .*' '#rc_cache.repo_object.expiration_time = 2592000' sed_replace '^#?rc_cache\.repo_object\.backend = dogpile\.cache\.rc\.redis_msgpack' 'rc_cache.repo_object.backend = dogpile.cache.rc.redis_msgpack' sed_replace '^#?rc_cache\.repo_object\.arguments\.socket_timeout = .*' 'rc_cache.repo_object.arguments.socket_timeout = 30' sed_replace '^#?rc_cache\.repo_object\.arguments\.db = .*' 'rc_cache.repo_object.arguments.db = 5' sed_replace '^#?rc_cache\.repo_object\.arguments\.port = .*' 'rc_cache.repo_object.arguments.port = 6379' sed_replace '^#?rc_cache\.repo_object\.arguments\.host = .*' 'rc_cache.repo_object.arguments.host = redis' sed_replace '^#?rc_cache\.repo_object\.arguments\.redis_expiration_time = .*' 'rc_cache.repo_object.arguments.redis_expiration_time = 3592000' sed_replace '^#?cache_dir = .*' 'cache_dir = \/var\/opt\/rhodecode_data' sed_replace '^#?formatter = .*' 'formatter = json' #statsd enable sed_replace '^#?statsd.enabled = .*' 'statsd.enabled = true' sed_replace '^#?statsd.statsd_host = .*' 'statsd.statsd_host = statsd-exporter' sed_replace '^#?statsd.statsd_port = .*' 'statsd.statsd_port = 9125' } config_rhodecode_ini() { #host/port sed_replace '^#?host = .*' 'host = 0\.0\.0\.0' sed_replace '^#?port = .*' 'port = 10020' # workers adjustment sed_replace '^#?workers = .*' 'workers = 1' sed_replace '^#?memory_max_usage = .*' 'memory_max_usage = 2147483648' # email sed_replace '^#?email_prefix = .*' 'email_prefix = [RhodeCode]' sed_replace '^#?app_email_from = .*' "app_email_from = rhodecode-noreply@$RC_HOSTNAME" sed_replace '^#?smtp_server = .*' 'smtp_server = localhost' # app-instance-uuid sed_replace '^app_instance_uuid = .*' "app_instance_uuid = $RC_APP_INSTANCE_UUID" # app base sed_replace '^app\.base_url = .*' "app\.base_url = $RC_APP_BASE_URL" # set license_token sed_replace '^#?license_token =.*' "license_token = $RC_LICENSE_TOKEN" # set Edition sed_replace '^use = egg:rhodecode-enterprise.*' "use = egg:rhodecode-enterprise-$RC_EDITION" # enable celery sed_replace '^#?use_celery = .*' 'use_celery = true' # DB sed_replace '^sqlalchemy\.db1\.url =.*' "sqlalchemy\.db1\.url = $RC_SQLALCHEMY_DB1_URL" #CHANNELSTREAM WS_URL sed_replace '^#?channelstream\.ws_url =.*' "channelstream\.ws_url = $RC_CHANNELSTREAM_WS_URL" # set cache dir sed_replace '^#?cache_dir = .*' 'cache_dir = \/var\/opt\/rhodecode_data' # set archive cache dir sed_replace '^#?archive_cache_dir = .*' 'archive_cache_dir = \/var\/opt\/rhodecode_data\/tarballcache' # set file_store path sed_replace '^#?file_store\.storage_path = .*' 'file_store.storage_path = \/var\/opt\/rhodecode_data\/file_store' # cleanup rabbitmq example entry sed_replace '^#celery\.broker_url = amqp.*' '' sed_replace '^#?celery\.broker_url = .*' 'celery\.broker_url = redis:\/\/redis:6379\/8' # switch beaker sessions to Redis based sed_replace '^#?beaker.session.type = file.*' '#beaker.session.type = file' sed_replace '^#?beaker.session.data_dir = .*' '#beaker.session.data_dir = \/tmp\/data\/sessions' # enable redis db2 sed_replace '^#?beaker\.session\.type = ext:redis' 'beaker.session.type = ext:redis' sed_replace '^#?beaker\.session\.url = redis:\/\/127.0.0.1:6379\/2' 'beaker.session.url = redis:\/\/redis:6379\/2' # sed_replace '^#?beaker.session.type = ext:database.*' 'beaker.session.type = ext:database' # sed_replace '^#?beaker.session.sa.url = postgresql.*' 'beaker.session.sa.url = postgresql://{{rhodecode_db_username}}:{{rhodecode_db_password}}@localhost/{{rhodecode_db_name}}' # hooks reconfigure for auto-bind to host sed_replace '^#?vcs.hooks.host = .*' 'vcs.hooks.host = \*' sed_replace '^#?vcs.server = .*' 'vcs.server = vcsserver:10010' # enable SVN sed_replace '^#?svn.proxy.generate_config = .*' 'svn.proxy.generate_config = true' # enable SSH sed_replace '^#?ssh.generate_authorized_keyfile = .*' 'ssh.generate_authorized_keyfile = true' #statsd enable sed_replace '^#?statsd.enabled = .*' 'statsd.enabled = true' sed_replace '^#?statsd.statsd_host = .*' 'statsd.statsd_host = statsd-exporter' sed_replace '^#?statsd.statsd_port = .*' 'statsd.statsd_port = 9125' # the wrapper_cmd sed_replace '^#?ssh.wrapper_cmd = .*' 'ssh.wrapper_cmd = \/usr\/local\/bin\/rhodecode_bin\/bin\/rc-ssh-wrapper' sed_replace '^#?api_access_controllers_whitelist = .*' 'api_access_controllers_whitelist = RepoFilesView:repo_archivefile, RepoFilesView:repo_file_raw' # # set search to elasticsearch # # enabled modules for Whoosh we remove, we have duplicates there.. # '^search.module = .*' '' # '^search.location = .*' '' # # '^#?search.module = .*' 'search.module = rc_elasticsearch' # '^#?search.location = .*' 'search.location = http://localhost:9200' # '^#?search.es_version = .*' 'search.es_version = 6' # enable Chat sed_replace '^#?chat.enabled = .*' 'chat.enabled = true' # logging sed_replace '^#?formatter = .*' 'formatter = json' } # src/lib/send_completions.sh # src/lib/utils.sh generate_md5() { local input_string="$1" if command -v md5 &> /dev/null; then echo -n "$input_string" | md5 elif command -v md5sum &> /dev/null; then echo -n "$input_string" | md5sum | awk '{print $1}' else echo "Error: Neither md5 nor md5sum command is available. Please make sure this is installed in your system" return 1 fi } random_str() { len=$1 random_generate=$(generate_md5 $RANDOM | head -c $len) echo "$random_generate" } # function to copy files with --backup=numbered option detect_cp_backup () { cp -r -f --update --backup=numbered "$@" 2>/dev/null if [ $? -eq 0 ]; then # if exit status is 0, --backup=numbered worked and return true return 0 else # if exit status is not 0, --backup=numbered didn't work and return false return 1 fi } # function that acts like cp cp_backup () { cp -r -f "$@" } cp_backup_verbose () { cp -r -f -v "$@" } # version_gte checks if the version specified in $VERSION is at least the given # SemVer (Maj.Minor[.Patch]), or CalVer (YY.MM) version.It returns 0 (success) # if $VERSION is either unset (=latest) or newer or equal than the specified # version, or returns 1 (fail) otherwise. # # examples: # # VERSION=23.0 # version_gte 23.0 // 0 (success) # version_gte 20.10 // 0 (success) # version_gte 19.03 // 0 (success) # version_gte 21.10 // 1 (fail) version_gte() { if [ -z "$VERSION" ]; then return 0 fi eval version_compare "$VERSION" "$1" } # version_compare compares two version strings (either SemVer (Major.Minor.Path), # or CalVer (YY.MM) version strings. It returns 0 (success) if version A is newer # or equal than version B, or 1 (fail) otherwise. Patch releases and pre-release # (-alpha/-beta) are not taken into account # # examples: # # version_compare 23.0.0 20.10 // 0 (success) # version_compare 23.0 20.10 // 0 (success) # version_compare 20.10 19.03 // 0 (success) # version_compare 20.10 20.10 // 0 (success) # version_compare 19.03 20.10 // 1 (fail) version_compare() ( set +x yy_a="$(echo "$1" | cut -d'.' -f1)" yy_b="$(echo "$2" | cut -d'.' -f1)" if [ "$yy_a" -lt "$yy_b" ]; then return 1 fi if [ "$yy_a" -gt "$yy_b" ]; then return 0 fi mm_a="$(echo "$1" | cut -d'.' -f2)" mm_b="$(echo "$2" | cut -d'.' -f2)" # trim leading zeros to accommodate CalVer mm_a="${mm_a#0}" mm_b="${mm_b#0}" if [ "${mm_a:-0}" -lt "${mm_b:-0}" ]; then return 1 fi return 0 ) # consistent sed function # example sed_func x y file.txt sed_func() { if [[ $DEBUG ]]; then echo echo "sed -i .replaced -E \"s/$1/$2/\" $in_file" echo "pat1: $1" echo "pat2: $2" fi in_file=$3 sed -i.replaced -E "s/$1/$2/" $in_file } # create a slug from a name slugify() { local input="$1" local slug # Convert to lowercase slug="${input,,}" # Replace slashes with underscores slug="${slug//\//_}" # Replace spaces with hyphens slug="${slug// /_}" # Remove characters that are not letters, numbers, or hyphens, or underscores slug="${slug//[^a-zA-Z0-9-_]/}" echo "$slug" } check_os() { echo `uname -s` } check_macos_memory() { echo $(($(memory_pressure | head -n 1 | awk '{ print $4 }') / 1024 / 1024 / 1024)) } check_linux_memory() { mem=`free -m --si | awk ' /Mem:/ {print $2}'` if [ "$mem" -ge 990 -a "$mem" -lt 1000 ]; then echo 1 else echo `free -g --si | awk ' /Mem:/ {print $2} '` fi } # src/lib/validate_stack_exists.sh validate_stack_exists() { err="" invalid="1" for item in $VALID_SERVICES do if [ "$1" == "$item" ]; then invalid="" break fi done if [[ -n $invalid ]]; then err="command '$1' not in list of $VALID_SERVICES" fi echo $err } # src/lib/validations/validate_dir_exists.sh validate_dir_exists() { [[ -d "$1" ]] || echo "must be an existing directory" } # src/lib/validations/validate_file_exists.sh validate_file_exists() { [[ -f "$1" ]] || echo "must be an existing file" } # src/lib/validations/validate_integer.sh validate_integer() { [[ "$1" =~ ^[0-9]+$ ]] || echo "must be an integer" } # src/lib/validations/validate_not_empty.sh validate_not_empty() { [[ -z "$1" ]] && echo "must not be empty" } # :command.command_functions # :command.function rcstack_get_started_command() { # src/get_started_command.sh get_started_full } # :command.function rcstack_init_command() { # src/init_command.sh DEBUG=${args[--debug]} force=${args[--force]} docker_revision=${args[--docker-revision]} install_docker=${args[--install-docker]} no_prompt=${args[--no-prompt]} eval "stages_from_cli=(${args[--stage]})" # CLI passed args / defaults if [[ -z ${args['--arg-rc-edition']} ]]; then # set default args['--arg-rc-edition']="ee" else # mark we used flag and don't ask in prompts args['__arg_rc_edition']=1 fi if [[ -z ${args['--arg-accept-eula']} ]]; then # set default args['--arg-accept-eula']="yes" else # mark we used flag and don't ask in prompts args['__arg_accept_eula']=1 fi if [[ -z ${args['--arg-hostname']} ]]; then # set default args['--arg-hostname']="rhodecode.local" else # mark we used flag and don't ask in prompts args['__arg_hostname']=1 fi if [[ -z ${args['--arg-use-ssl']} ]]; then # set default args['--arg-use-ssl']="n" else # mark we used flag and don't ask in prompts args['__arg_use_ssl']=1 fi if [[ -z ${args['--arg-admin-email']} ]]; then # set default args['--arg-admin-email']="admin@${args['--arg-hostname']}" else # mark we used flag and don't ask in prompts args['__arg_admin_email']=1 fi if [[ -z ${args['--arg-admin-user']} ]]; then # set default args['--arg-admin-user']="admin" else # mark we used flag and don't ask in prompts args['__arg_admin_user']=1 fi if [[ -z ${args['--arg-admin-pass']} ]]; then # set default args['--arg-admin-pass']="secret4" else # mark we used flag and don't ask in prompts args['__arg_admin_pass']=1 fi if [[ -z ${args['--arg-license-token']} ]]; then # set default args['--arg-license-token']="$(random_str 4)"-"$(random_str 4)"-"$(random_str 4)"-"$(random_str 4)" else # mark we used flag and don't ask in prompts args['__arg_license_token']=1 fi if [[ -z ${args['--arg-log-formatter']} ]]; then # set default args['--arg-log-formatter']="json" else # mark we used flag and don't ask in prompts args['__arg_log_formatter']=1 fi arg_rc_edition=${args[--arg-rc-edition]} arg_accept_eula=${args[--arg-accept-eula]} arg_hostname=${args[--arg-hostname]} arg_use_ssl=${args[--arg-use-ssl]} arg_admin_email=${args[--arg-admin-email]} arg_admin_user=${args[--arg-admin-user]} arg_admin_pass=${args[--arg-admin-pass]} arg_license_token=${args[--arg-license-token]} arg_log_formatter=${args[--arg-log-formatter]} ask_user_for_config() { local config_done="n" echo "Starting interactive setup..." echo "" while [[ "$config_done" == "n" ]] # config loop start do # edition to install if [ ! -z "$arg_rc_edition" ] && [ -z ${args['__arg_rc_edition']} ] then read -p "Select 'ee' to use Enterprise edition or type 'ce' to use Community free edition: rhodecode-[$arg_rc_edition]: " new_value if [ ! -z "$new_value" ] then arg_rc_edition="$new_value" fi fi if [ ! -z "$arg_accept_eula" ] && [ -z ${args['__arg_accept_eula']} ] then if [[ $arg_rc_edition == "ee" ]]; then #EE EULA read -p "Do you accept RhodeCode EULA (see: https://docs.rhodecode.com/rcstack/eula/ee.txt) accept: 'yes' deny: 'no' ? [$arg_accept_eula]: " new_value else #CE EULA read -p "Do you accept RhodeCode EULA (see: https://docs.rhodecode.com/rcstack/eula/ce.txt) accept: 'yes' deny: 'no' ? [$arg_accept_eula]: " new_value fi if [ ! -z "$new_value" ] then arg_accept_eula="$new_value" fi if [[ $arg_accept_eula != "yes" ]]; then echo "$(red please accept EULA by typing yes, no installation is possible without accepted EULA)" exit fi fi # ask for license-token IF edition is ee if [[ $arg_rc_edition == "ee" ]]; then if [ ! -z "$arg_license_token" ] && [ -z ${args['__arg_license_token']} ] then read -p "enter a valid license-token or use pre-generated one [$arg_license_token]: " new_value if [ ! -z "$new_value" ] then arg_license_token="$new_value" fi fi fi # hostname if [ ! -z "$arg_hostname" ] && [ -z ${args['__arg_hostname']} ] then read -p "Enter a valid hostname for RhodeCode Stack? [$arg_hostname]: " new_value if [ ! -z "$new_value" ] then arg_hostname="$new_value" fi if [[ $arg_hostname =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] then echo echo "$(red IP addresses are unsupported and will not work. Please provide a DNS hostname)" echo arg_hostname="rc-docker.local" fi fi # use SSL if [ ! -z "$arg_use_ssl" ] && [ -z ${args['__arg_use_ssl']} ] then read -p "Do you want to enable SSL/HTTPS now (can be changed later) 'y' for yes 'n' for no? [$arg_use_ssl]: " new_value if [ ! -z "$new_value" ] then arg_use_ssl="$new_value" fi fi # admin email if [ ! -z "$arg_admin_email" ] && [ -z ${args['__arg_admin_email']} ] then read -p "Enter first super-admin email? [$arg_admin_email]: " new_value if [ ! -z "$new_value" ] then arg_admin_email="$new_value" fi fi # admin user if [ ! -z "$arg_admin_user" ] && [ -z ${args['__arg_admin_user']} ] then read -p "Enter first super-admin account name? [$arg_admin_user]: " new_value if [ ! -z "$new_value" ] then arg_admin_user="$new_value" fi fi # admin password if [ ! -z "$arg_admin_pass" ] && [ -z ${args['__arg_admin_pass']} ] then read -p "Enter first super-admin account password? [$arg_admin_pass]: " new_value if [ ! -z "$new_value" ] then arg_admin_pass="$new_value" fi fi echo -e "\nDoes this look right?\n" echo "RhodeCode Edition : rhodecode-$arg_rc_edition" echo "License Token : $arg_license_token" echo "Hostname : $arg_hostname" echo "Use SSL : $arg_use_ssl" echo "Email : $arg_admin_email" echo "Admin user : $arg_admin_user" echo "Admin password : $arg_admin_pass" echo "" read -p "ENTER to continue, 'n' to try again, Ctrl+C to exit: " config_done # config loop end done } check_docker() { (which docker || which docker.io) &>/dev/null } bootstrap_docker_install() { # systemctl enable docker on debian echo "bootstrap_docker_install: trying to check and configure docker" failMsg="Failed to find docker on your PATH" if ! check_docker; then if [[ $install_docker == "n" ]]; then echo "$(red $failMsg, exiting without docker install)" fi echo "$(yellow $failMsg, trying docker install)" if [[ $install_docker == "y" ]]; then echo "continuing with automated docker installation from https://get.docker.com/ " else read -p "Enter to install Docker directly from https://get.docker.com/ or Ctrl+C to exit and install it manually" fi curl -fsSL https://get.docker.com -o install-docker.sh sh install-docker.sh rm install-docker.sh if ! check_docker; then echo "$failMsg" echo "Docker install failed. Quitting." exit 1 fi docker --version fi } bootstrap_docker_commons() { echo 'bootstrap_docker_commons: running docker commands.' echo "bootstrap_docker_commons: creating volume 'rc_datavolume'" docker volume create --label keep=1 --name=rc_datavolume echo "bootstrap_docker_commons (rc_datavolume): done" echo "" echo "bootstrap_docker_commons: creating volume 'rc_reposvolume'" docker volume create --label keep=1 --name=rc_reposvolume echo "bootstrap_docker_commons (rc_reposvolume): done" echo "" echo "bootstrap_docker_commons: creating network 'rhodecode_network'" docker network inspect rhodecode_network >/dev/null 2>&1 || docker network create rhodecode_network echo "bootstrap_docker_commons (rhodecode_network): done" echo "" echo "bootstrap_docker_commons: creating loki logging" loki_driver=$(docker plugin ls --format {{.Name}} --filter enabled=true | grep loki || echo "") if [[ $loki_driver == "" ]]; then docker plugin install grafana/loki-docker-driver:latest --alias loki --grant-all-permissions else echo "bootstrap_docker_commons: loki driver already exists" fi } config_init() { loc_config_file=${CONFIG_FILE:=config.ini} [[ -f "$loc_config_file" ]] || touch "$loc_config_file" } bootstrap_config() { shared_key=$(random_str 32) shared_key_md5=$(generate_md5 $shared_key | head -c 32) db_key=$(random_str 32) if [[ ! $no_prompt ]]; then ask_user_for_config fi # setup args license_token=$arg_license_token log_formatter=$arg_log_formatter base_domain=$arg_hostname rc_edition=$arg_rc_edition is_https=0 if [[ $arg_use_ssl == "y" ]]; then is_https=1; fi DB_USER='rhodecode' DB_NAME='rhodecode' if [[ ! -f "$CONFIG_FILE" ]]; then echo "init new config at: $CONFIG_FILE" config_init else echo "re-using existing config at: $CONFIG_FILE" fi CUSTOM_DIR_PATH=$PWD/.custom mkdir -p "$CUSTOM_DIR_PATH" BOOTSTRAP_TMPL=$PWD/templates/runtime.env.tmpl BOOTSTRAP_RUNTIME_ENV=$PWD/.custom/.runtime.env # TODO: Pick version ver=0_edge INI_TARGET=$PWD/config/_shared RHODECODE_INI_TMPL=$PWD/templates/ini/$ver/rhodecode.ini VCSSERVER_INI_TMPL=$PWD/templates/ini/$ver/vcsserver.ini # break if we didn't use force and definitions exist if [[ -f $BOOTSTRAP_RUNTIME_ENV && ! $force ]]; then echo "$(yellow bootstrap_config: $BOOTSTRAP_RUNTIME_ENV file exists, not adding any configuration. Use --force to create it anyway)" return fi if [[ -f $BOOTSTRAP_RUNTIME_ENV ]]; then echo "$(yellow $BOOTSTRAP_RUNTIME_ENV file exists, are you sure to force re-create it?)" while true; do read -p "Would you like to continue with overriding file? [yn] " yn case $yn in [Yy]*) break ;; [Nn]*) exit ;; *) echo "Please answer y or n." ;; esac done fi echo "bootstrap_config: init runtime env config at: $BOOTSTRAP_RUNTIME_ENV" # Make runtime file echo "## BOOTSTRAP GENERATED $(date) ##" > $BOOTSTRAP_RUNTIME_ENV echo "" >> $BOOTSTRAP_RUNTIME_ENV cat $BOOTSTRAP_TMPL >> $BOOTSTRAP_RUNTIME_ENV # Make .ini files cp -v $RHODECODE_INI_TMPL $INI_TARGET cp -v $VCSSERVER_INI_TMPL $INI_TARGET # init env generator with env file .env --file "$BOOTSTRAP_RUNTIME_ENV" .env set RC_EDITION=$rc_edition .env set DB_PASSWORD=$db_key .env set RHODECODE_USER_EMAIL=$arg_admin_email .env set RHODECODE_USER_NAME=$arg_admin_user .env set RHODECODE_USER_PASS=$arg_admin_pass .env set RC_ENCRYPTED_SECRET=$shared_key rc_db1="postgresql://$DB_USER:$db_key@database/$DB_NAME" .env set RC_DB_URL="$rc_db1" .env set RC_SQLALCHEMY_DB1_URL="$rc_db1" .env set RC_LICENSE_TOKEN=$license_token .env set RC_HOSTNAME=$base_domain if [[ $is_https == 1 ]]; then app_base_url=https://$base_domain else app_base_url=http://$base_domain fi .env set RC_APP_BASE_URL=$app_base_url .env set RC_LOKI_AUTH=loki-auth:$shared_key@ .env puts '' .env puts '# Log formatter option' .env set RC_LOGGING_FORMATTER=$log_formatter .env set RC_USE_CELERY=true .env puts '' .env puts '# Channelstream config' .env set RC_CHANNELSTREAM_SERVER=channelstream:8000 if [[ $is_https == 1 ]]; then rc_channelstream_url="wss://$base_domain/_channelstream" else rc_channelstream_url="ws://$base_domain/_channelstream" fi .env set RC_CHANNELSTREAM_WS_URL=$rc_channelstream_url .env set CHANNELSTREAM_ALLOW_POSTING_FROM=0.0.0.0 .env puts '' .env puts '# Channelstream secrets' .env set CHANNELSTREAM_SECRET=$shared_key .env set RC_CHANNELSTREAM_SECRET=$shared_key .env puts '' .env puts '# Channelstream admin' .env set CHANNELSTREAM_ADMIN_SECRET=$shared_key .env set RC_CHANNELSTREAM_ADMIN_SECRET=$shared_key .env puts '' .env puts '# SSH PORT' .env set RC_SSH_PORT=9022 ini_path=$INI_TARGET/vcsserver.ini config_vcsserver_ini ini_path=$INI_TARGET/rhodecode.ini RC_EDITION=$rc_edition RC_LICENSE_TOKEN=$license_token RC_HOSTNAME=$(sed_safe_path $base_domain) RC_APP_BASE_URL=$(sed_safe_path $app_base_url) RC_SQLALCHEMY_DB1_URL=$(sed_safe_path $rc_db1) RC_CHANNELSTREAM_WS_URL=$(sed_safe_path $rc_channelstream_url) config_rhodecode_ini touch $BOOTSTRAP_RUNTIME_ENV } bootstrap_definitions() { # This is needed for bootstrap_definitions AUTH_TOKEN=${args[--auth-token]} SERVER_URL=${args[--server-url]} DEFINITIONS_EXIST="" CHECK_FILES="\ docker-compose-services.yaml \ docker-compose-apps.yaml \ docker-compose-metrics.yaml \ docker-compose-router.yaml \ " for check_file in $CHECK_FILES; do if [[ -f "$check_file" ]]; then DEFINITIONS_EXIST="1" fi done # break if we didn't use force and definitions exist if [[ -n $DEFINITIONS_EXIST && ! $force ]]; then echo "$(yellow bootstrap_definitions: skipping docker defs creation, existing files found. Use --force to create them anyway)" return fi if [[ -n $DEFINITIONS_EXIST ]]; then echo "$(yellow docker definitions exists, are you sure to force re-create them?)" while true; do read -p "Would you like to continue with overriding files? [yn] " yn case $yn in [Yy]*) break ;; [Nn]*) exit ;; *) echo "Please answer y or n." ;; esac done fi FULL_MODE=1 # This expects the $AUTH_TOKEN and $SERVER_URL be present get_docker_definitions $docker_revision $FULL_MODE $DEBUG } bootstrap_overrides() { templates=$YAML_TEMPLATES target_dir=$PWD/.custom for o_file in $templates; do target_file=$target_dir/$o_file if [[ ! -f "$target_file" ]]; then echo "copy override file $o_file" cp -v $PWD/templates/$o_file $target_file else echo "file $target_file existing, skipping..." fi done mkdir -p $target_dir/traefik_custom cp -r $PWD/config/traefik/* $target_dir/traefik_custom/ echo "$(green bootstrap_overrides: overrides extracted to $target_dir)" # save our loki auth using md5 encryption so the auth works OOTB echo "loki-auth:$shared_key_md5" >> $target_dir/traefik_custom/dynamic/.htpasswd # change our templates and adjust using enable SSH if [[ $arg_use_ssl == "y" ]]; then echo "enabling SSL on .override.yaml templates" metrics_replace() { metrics_tmpl=$target_dir/docker-compose-metrics.override.yaml sed_func "$1" "$2" "$metrics_tmpl" } metrics_replace '# # Enable http\+https' ' # Enable http\+https' metrics_replace '# - "traefik.http.routers.grafana.entrypoints=http,https"' ' - "traefik.http.routers.grafana.entrypoints=http,https"' services_replace() { services_tmpl=$target_dir/docker-compose-services.override.yaml sed_func "$1" "$2" "$services_tmpl" } services_replace '# # Enable http\+https' ' # Enable http\+https' services_replace '# - "traefik.http.routers.channelstream.entrypoints=http,https"' ' - "traefik.http.routers.channelstream.entrypoints=http,https"' services_replace '# - "traefik.http.routers.nginx-statics.entrypoints=http,https"' ' - "traefik.http.routers.nginx-statics.entrypoints=http,https"' apps_replace() { apps_tmpl=$target_dir/docker-compose-apps.override.yaml sed_func "$1" "$2" "$apps_tmpl" } apps_replace '# # Enable http\+https' ' # Enable http\+https' apps_replace '# - "traefik.http.routers.rhodecode.entrypoints=http,https"' ' - "traefik.http.routers.rhodecode.entrypoints=http,https"' fi } cur_date=$(date '+%Y-%m-%d %H:%M:%S') # Init the config ! if [[ ! -f "$CONFIG_FILE" ]]; then echo "config: init new config at: $CONFIG_FILE" config_init else echo "config: re-using present config at: $CONFIG_FILE" fi run_stages=$BOOTSTRAP_STAGES if [ ! ${#stages_from_cli[@]} -eq 0 ]; then echo "Using custom stages to run init command..." run_stages=${stages_from_cli[@]} fi for stage_name in $run_stages; do stage_func=$(get_stage_function $stage_name) if ! config_has_key $stage_name ; then echo "$(green \* bootstrap: \'$stage_name\' stage not found\; running now... )" $stage_func config_set "$stage_name" $cur_date else if [ $force ]; then echo "$(green \* bootstrap: \'$stage_name\' is present!\; FORCE running now... )" $stage_func $force config_set "$stage_name" $cur_date else echo "$(yellow \* bootstrap: \'$stage_name\' stage already present, use --force to run it again)" fi fi done echo "" echo "~~~~ $(green Bootstrap completed) ~~~~" get_started } # :command.function rcstack_self_update_command() { # src/self_update_command.sh check_bootstrap FORCE=${args[--force]} DEBUG=${args[--debug]} # This is needed for bootstrap_definitions AUTH_TOKEN=${args[--auth-token]} SERVER_URL=${args[--server-url]} update_docker_image=${args[--update-docker-image]} rcstack_channel=${args[--cli-revision]} docker_channel=${args[--docker-revision]} FETCH_FROM=https://dls.rhodecode.com/get/$rcstack_channel FINAL_TARGET=$PWD/scripts/rcstack/rcstack DL_TARGET=$PWD/scripts/rcstack/rcstack.tmp #ensure we have this dir ! mkdir -p $PWD/scripts/rcstack .env --file $RUNTIME_ENV .env get_or_error RC_VERSION ENV_VER=$REPLY echo "self-update: downloading new $RC_SCRIPT_NAME script from $FETCH_FROM" if [[ $FORCE ]]; then echo "$(yellow self-update: --force used, doing forced update)" fi if [[ $DEBUG ]]; then echo "running: curl -L -ss --fail -o $DL_TARGET $FETCH_FROM" fi curl -L -ss --fail -o $DL_TARGET $FETCH_FROM chmod +x $DL_TARGET version_old=0 rc_version_old=0 # check if we have OLD file, in case we don't just set versions to 0 if [[ -f "$FINAL_TARGET" ]]; then version_old=$($FINAL_TARGET --version) rc_version_old=$($FINAL_TARGET cli image-info) fi version_dl=$($DL_TARGET --version) rc_version_dl=$($DL_TARGET cli image-info) echo "self-update: $RC_SCRIPT_NAME version downloaded: $version_dl" if [[ $DEBUG ]]; then echo "DEBUG: old-script ver: $version_old" echo "DEBUG: new-script ver: $version_dl" echo "DEBUG: " echo "DEBUG: .runtime.env set version $ENV_VER" echo "DEBUG: " echo "DEBUG: old-script: RC VERSION: $rc_version_old" echo "DEBUG: new-script: RC VERSION: $rc_version_dl" fi if [[ $version_old == "$version_dl" ]]; then if [[ $FORCE ]]; then echo "$(yellow self-update: downloaded version is the same as current version $version_dl, continue with --force...)" else echo "self-update: downloaded version is the same as current version $version_dl, exiting..." exit fi fi docker_image_update() { echo "$(green self-update: saving new RC_VERSION=$rc_version_dl to runtime.env file)" echo "currently .runtime.env file uses image: $ENV_VER" if [[ $update_docker_image == "y" ]]; then echo "continuing with automated forced installer version saved into .runtime.env" .env set RC_VERSION=$rc_version_dl else while true; do read -p "self-update: Would you like to continue with setting RC_VERSION=$rc_version_dl into .runtime.env file? [yn] " yn case $yn in [Yy]*) .env set RC_VERSION=$rc_version_dl echo "self-update: new version set into config" break ;; [Nn]*) break ;; *) echo "Please answer y or n." ;; esac done fi } if [[ $rc_version_old == "$rc_version_dl" ]]; then echo "self-update: docker image defined by RC_VERSION=$rc_version_dl seems to be up-to date" if [[ $FORCE ]]; then echo "$(yellow self-update: continue with --force...)" docker_image_update fi else docker_image_update fi echo "self-update: updating cli $RC_SCRIPT_NAME script to new version: $version_dl" if [[ -f "$FINAL_TARGET" ]]; then rm $FINAL_TARGET && mv -v $DL_TARGET $FINAL_TARGET else mv -v $DL_TARGET $FINAL_TARGET fi echo "$(green self-update: updating docker definitions to $docker_channel)" FULL_MODE=1 # This expects the $AUTH_TOKEN and $SERVER_URL be present get_docker_definitions $docker_channel $FULL_MODE $DEBUG echo "$(green self-update: successfully update to $version_dl)" exit } # :command.function rcstack_stack_router_command() { # src/stack_router_command.sh check_bootstrap DEBUG=${args[--debug]} ENV_FILE=${args[--env-file-path]} if [[ ! -f $RC_STACK_ROUTER_EXT ]]; then RC_STACK_ROUTER_EXT="" else RC_STACK_ROUTER_EXT="-f $RC_STACK_ROUTER_EXT" fi CMD_ROUTER="\ RC_ENV_FILE=$ENV_FILE docker compose \ --env-file $ENV_FILE \ $ENV_EXPAND \ -p rc_cluster_router \ -f docker-compose-base.yaml \ -f docker-compose-router.yaml $RC_STACK_ROUTER_EXT" if [[ $DEBUG ]]; then echo "---" echo "stacks docker: $RC_STACK_ROUTER_EXT_LCL" echo "running command: ${CMD_ROUTER}" echo "ARGS: ${other_args[*]}" echo "---" fi eval "${CMD_ROUTER} ${other_args[*]}" } # :command.function rcstack_stack_metrics_command() { # src/stack_metrics_command.sh check_bootstrap DEBUG=${args[--debug]} ENV_FILE=${args[--env-file-path]} if [[ ! -f $RC_STACK_METRICS_EXT ]]; then RC_STACK_METRICS_EXT_LCL="" else RC_STACK_METRICS_EXT_LCL="-f $RC_STACK_METRICS_EXT" fi CMD_METRICS="\ RC_ENV_FILE=$ENV_FILE docker compose \ --env-file $ENV_FILE \ $ENV_EXPAND \ -p rc_cluster_metrics \ -f docker-compose-base.yaml \ -f docker-compose-metrics.yaml $RC_STACK_METRICS_EXT_LCL" if [[ $DEBUG ]]; then echo "---" echo "stacks docker: $RC_STACK_METRICS_EXT_LCL" echo "running command: ${CMD_METRICS}" echo "ARGS: ${other_args[*]}" echo "---" fi eval "${CMD_METRICS} ${other_args[*]}" } # :command.function rcstack_stack_services_command() { # src/stack_services_command.sh check_bootstrap DEBUG=${args[--debug]} ENV_FILE=${args[--env-file-path]} if [[ ! -f $RC_STACK_SERVICES_EXT ]]; then RC_STACK_SERVICES_EXT_LCL="" else RC_STACK_SERVICES_EXT_LCL="-f $RC_STACK_SERVICES_EXT" fi RC_STACK_PROFILES="--profile database --profile redis --profile elasticsearch --profile channelstream" CMD_SERVICES="\ RC_ENV_FILE=$ENV_FILE docker compose \ --env-file $ENV_FILE \ $ENV_EXPAND \ $RC_STACK_PROFILES \ --project-name rc_cluster_services \ -f docker-compose-base.yaml \ -f docker-compose-services.yaml $RC_STACK_SERVICES_EXT_LCL" if [[ $DEBUG ]]; then echo "---" echo "stacks docker: $RC_STACK_SERVICES_EXT_LCL" echo "running command: ${CMD_SERVICES}" echo "ARGS: ${other_args[*]}" echo "---" fi eval "${CMD_SERVICES} ${other_args[*]}" } # :command.function rcstack_stack_rhodecode_command() { # src/stack_rhodecode_command.sh check_bootstrap DEBUG=${args[--debug]} ENV_FILE=${args[--env-file-path]} stack_prefix=${args[--stack-prefix]} if [[ $stack_prefix == "" ]]; then stack_prefix="rc_cluster_apps" fi if [[ ! -f $RC_STACK_RHODECODE_EXT ]]; then RC_STACK_RHODECODE_EXT_LCL="" else RC_STACK_RHODECODE_EXT_LCL="-f $RC_STACK_RHODECODE_EXT" fi CMD_RHODECODE="\ RC_ENV_FILE=$ENV_FILE docker compose \ --env-file $ENV_FILE \ $ENV_EXPAND \ -p $stack_prefix \ -f docker-compose-base.yaml \ -f docker-compose-apps.yaml $RC_STACK_RHODECODE_EXT_LCL" sub_cmd=${other_args[0]} if [[ $sub_cmd == "up" ]]; then declare -a final_args=( "$sub_cmd" "--no-color" "--no-build" "${other_args[@]:1}" ) else declare -a final_args=( "$sub_cmd" "${other_args[@]:1}" ) fi if [[ $DEBUG ]]; then echo "---" echo "stacks docker: $RC_STACK_RHODECODE_EXT_LCL" echo "running command: ${CMD_RHODECODE}" echo "ARGS: ${final_args[*]}" echo "---" fi eval "${CMD_RHODECODE} ${final_args[*]}" } # :command.function rcstack_stack_all_command() { # src/stack_all_command.sh check_bootstrap DEBUG=${args[--debug]} stack_lst=$VALID_SERVICES for stack in $stack_lst; do ./$RC_SCRIPT_NAME stack $stack ${other_args[*]} done } # :command.function rcstack_stack_status_command() { # src/stack_status_command.sh check_bootstrap DEBUG=${args[--debug]} DETAILED=${args[--detailed]} CONFIGS=${args[--configs]} VERBOSE=${args[-v]} .env --file $RUNTIME_ENV .env get_or_error RC_APP_BASE_URL RC_APP_BASE_URL=$REPLY .env get_or_error RC_VERSION RC_VERSION=$REPLY .env get_or_error RC_SSH_PORT RC_SSH_PORT=$REPLY .env get_or_error RC_EDITION RC_EDITION=$REPLY .env get_or_error RC_LICENSE_TOKEN RC_LICENSE_TOKEN=$REPLY if [[ $DEBUG ]]; then echo "---" ps_cmd=$(docker ps --filter=name=rc_cluster --format="{{.ID}}") for service in $ps_cmd; do servicename=`docker inspect --format '{{ .Name }}' $service` servicename=${servicename:1} echo $servicename docker inspect $service --format='{{.State.Status}}: {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' echo "" done echo "---" fi echo "Running hostname: $RC_APP_BASE_URL" if [[ $VERBOSE ]]; then printf "SSH Port: $RC_SSH_PORT\n" printf "Edition: $RC_EDITION:$RC_VERSION\n" printf "License: $RC_LICENSE_TOKEN\n" printf "\n" fi if [[ $CONFIGS ]]; then printf "rcstack:\n" printf " config (in-host): $RUNTIME_ENV\n" printf "RhodeCode:\n" printf " ini (in-host): $rhodecode_default_config_path\n" printf " volumes (in-container):\n" printf " repo-store: /var/opt/rhodecode_repo_store\n" printf " data-store: /var/opt/rhodecode_data\n" printf "VCSServer:\n" printf " ini (in-host): $vcsserver_default_config_path\n" printf " volumes (in-container):\n" printf " repo-store: /var/opt/rhodecode_repo_store\n" printf " data-store: /var/opt/rhodecode_data\n" printf "Traefik (router):\n" printf " ssl-certs definitions: .custom/traefik_custom/dynamic/traefik_dynamic_custom.yaml\n" printf " ssl-certs dir: .custom/traefik_custom/dynamic/certs/\n" fi if [[ $DETAILED ]]; then ps_cmd=$(docker ps --filter=name=rc_cluster --format="{{.ID}}") for service in $ps_cmd; do servicename=`docker inspect --format '{{ .Name }}' $service` servicename=${servicename:1} printf "CONTAINER:\\t$servicename\n" printf "LOGS:\\t\\tdocker logs --tail=100 $service\n" docker ps --filter=name=$servicename --format="ID:\\t\\t{{.ID}}\nIMAGE:\\t\\t{{.Image}}\nSTATUS:\\t\\t{{.Status}}\nPORTS:\\t\\t{{.Ports}}\n" echo "" done else docker ps --filter=name=rc_cluster --format "table {{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}" | (read -r; printf "%s\n" "$REPLY"; sort -k 2 ) fi } # :command.function rcstack_stack_upgrade_router_command() { # src/stack_upgrade_router_command.sh echo "Upgrading this stack with:" echo "./$RC_SCRIPT_NAME stack router up --force-recreate --detach" echo "" echo "NOTE: To reclaim space occupied by old images, run:" echo "docker image prune -f" ./$RC_SCRIPT_NAME stack router up --force-recreate --detach } # :command.function rcstack_stack_upgrade_services_command() { # src/stack_upgrade_services_command.sh echo "Upgrading this stack with:" echo "./$RC_SCRIPT_NAME stack services up --force-recreate --detach" echo "" echo "NOTE: To reclaim space occupied by old images, run:" echo "docker image prune -f" ./$RC_SCRIPT_NAME stack services up --force-recreate --detach } # :command.function rcstack_stack_upgrade_metrics_command() { # src/stack_upgrade_metrics_command.sh echo "To upgrading this stack with:" echo "./$RC_SCRIPT_NAME stack metrics up --force-recreate --detach" echo "" echo "NOTE: To reclaim space occupied by old images, run:" echo "docker image prune -f" ./$RC_SCRIPT_NAME stack metrics up --force-recreate --detach } # :command.function rcstack_stack_upgrade_rhodecode_command() { # src/stack_upgrade_rhodecode_command.sh check_bootstrap stop_wait=${args[--stop-wait]} docker_stop_wait=${args[--docker-stop-wait]} stack_prefix=${args[--stack-prefix]} if [[ $stack_prefix == "" ]]; then stack_prefix="rc_cluster_apps" fi # search docker IDs for current service .env --file $RUNTIME_ENV .env get_or_error RC_VERSION RC_VERSION=$REPLY .env get_or_error RC_EDITION RC_EDITION=$REPLY echo "Pulling new image: rhodecode/rhodecode-${RC_EDITION}:${RC_VERSION}" echo "WARNING: about to start downloading the RhodeCode base image" echo "This process may take anywhere between a few minutes to an hour, depending on your network speed" echo "running: docker pull -q rhodecode/rhodecode-${RC_EDITION}:${RC_VERSION}" eval "docker pull -q rhodecode/rhodecode-${RC_EDITION}:${RC_VERSION}" have_tty=1 # Set a dummy terminal type if none set [[ -z "$TERM" ]] && export have_tty=0 [[ ! -t 1 ]] && export have_tty=0 set_cursor() { if [[ $have_tty == 1 ]]; then tput $1 fi } stop_containers() { target_container=$1 docker_stop_wait=$2 stop_wait=$3 target_containers_pat="$stack_prefix-$target_container-*" # array with OLD containers local -a old_docker_ids readarray -t old_docker_ids < <(docker ps --filter name="$target_containers_pat" -q) scale=${#old_docker_ids[@]} scale_2=$(( scale * 2 )) echo "" echo "Found $scale old container[s] for $target_container" echo "Old container-ids:" "${old_docker_ids[@]}" echo "" if [[ $scale == "0" ]]; then echo "No previous services found, doing a regular start for $target_container" ./$RC_SCRIPT_NAME stack rhodecode up $target_container --detach return else echo "Scaling to 2x ($scale_2 total) containers for $target_container" ./$RC_SCRIPT_NAME stack rhodecode up $target_container --no-recreate --detach --scale $target_container=$scale_2 fi # array with ALL new containers local -a scaled_docker_ids readarray -t scaled_docker_ids < <(docker ps --filter name="$target_containers_pat" -q) echo "Scaling completed, running $scale_2 services for upgrade purpose..." echo "new docker-ids:" "${scaled_docker_ids[@]}" # calculate just NEW containers declare -A new_container_check # Mark elements of the first initial docker for docker_id in "${old_docker_ids[@]}"; do new_container_check[$docker_id]=1 done local new_docker_ids_str new_docker_ids_str="" # Check if elements of the second array are not in the first for n_docker_id in "${scaled_docker_ids[@]}"; do # if $docker_id in new services is empty in the last array we ADD it :) if [[ -z ${new_container_check[$n_docker_id]} ]]; then new_docker_ids_str+=" $n_docker_id " fi done echo "Stopping $scale old $target_container containers " echo "killing docker-ids:" "${old_docker_ids[@]}" spin='⠾⠽⠻⠟⠯⠷' charwidth=1 # wait the required stop-wait time #HC: docker inspect --format='{{.Name}}: {{json .ContainerId .State.Health.Status}}' local i i=$(($stop_wait * 10)) local status status='' # cursor invisible set_cursor civis while true s=$((i / 10)) do i=$(($i-1)) if [[ $i -lt 1 ]]; then break fi if [[ "$(($i % 10))" == 0 ]]; then is_at_sec=1 else is_at_sec=0 fi local new_docker_ids_status_cnt if [[ $is_at_sec == 1 ]]; then new_docker_ids_status_cnt=$(docker inspect --format='{{.State.Health.Status}}' $new_docker_ids_str | grep -c "healthy" || echo "") if [[ $new_docker_ids_status_cnt -eq $scale ]]; then echo "All $target_container are in HEALTHY state; stopping old ones now" echo "" break fi fi k=$(((k + $charwidth) % ${#spin})) if [[ $have_tty == 1 ]]; then printf "%s stopping $scale old containers once they are in HEALTHY state, or in $s s..." "${spin:$k:$charwidth}" printf "\r" else if [[ $is_at_sec == 1 ]]; then echo "stopping $scale old containers once they are in HEALTHY state, or in $s s..." fi fi sleep .1 done set_cursor cnorm for container in "${old_docker_ids[@]}" do echo "now running container $container stop with --time $docker_stop_wait" docker stop --time "$docker_stop_wait" "$container" > /dev/null docker rm "$container" > /dev/null echo "Stopped $container" done } # VCSSERVER Containers stop_containers "vcsserver" $docker_stop_wait $stop_wait # RHODECODE Containers stop_containers "rhodecode" $docker_stop_wait $stop_wait # SSHD Containers stop_containers "sshd" $docker_stop_wait $stop_wait # SVN Containers stop_containers "svn" $docker_stop_wait $stop_wait ./$RC_SCRIPT_NAME stack rhodecode up celery --force-recreate --detach ./$RC_SCRIPT_NAME stack rhodecode up celery-beat --force-recreate --detach echo "Upgrade to rhodecode/rhodecode-${RC_EDITION}:${RC_VERSION} completed" exit } # :command.function rcstack_stack_monitor_restart_unhealthy_command() { # src/stack_monitor_restart_unhealthy_command.sh check_bootstrap DEBUG=${args[--debug]} loop=${args[--loop]} get_unhealthy() { unhealthy=$(docker ps --filter health=unhealthy --filter label=autoheal=true --format "{{.ID}}") if [[ $unhealthy == "" ]]; then echo "$(green stack-monitor: no unhealthy containers found)" else echo "$(yellow stack-monitor: found unhealthy containers $unhealthy)" fi for container in $unhealthy do docker stats --no-stream --format '{{.ID}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}' $container echo "stack-monitor: restart $container" docker restart --time=10 $container done } if [[ ! $loop == "0" ]]; then while true do date_formatted=$(date) echo "stack-monitor: loop-run every $loop seconds..., $date_formatted" # loop run NO_COLOR=1 get_unhealthy echo "Next execution in $loop s..." && \ sleep $loop echo "" done else # one time run get_unhealthy fi exit } # :command.function rcstack_cli_cmd_command() { # src/cli_cmd_command.sh check_bootstrap if [[ -z ${args['--user']} ]]; then # set default, user if the flag is not used args['--user']='root' fi DEBUG=${args[--debug]} RUN_WITHOUT_TTY=${args[--no-tty]} ENV_FILE=${args[--env-file-path]} EXEC_USER=${args[--user]} INTERACTIVE_FLAGS="--interactive --tty" if [[ $RUN_WITHOUT_TTY ]]; then INTERACTIVE_FLAGS="--interactive" fi proj_name=rc_cluster_apps # use vcsserver here because it won't do any extra logic like rhodecode image does instance_type=vcsserver if [ ${#other_args[@]} -eq 0 ]; then other_args[${#other_args[@]}]="echo 'please provide a valid cmd arg...'" fi printf "*Volumes*:\n" printf " attaching $PWD/config/_shared \t\tunder: /vol/confvolume\n" printf "\n" #printf "attaching rc_reposvolume \t\tunder: /vol/repovolume\n" #printf "attaching \$PWD/.custom/storage \t\tunder: /vol/backupvolume\n" CMD_EXEC="\ RC_ENV_FILE=$ENV_FILE docker compose \ --env-file $ENV_FILE \ $ENV_EXPAND \ --project-name $proj_name \ -f docker-compose-base.yaml \ -f docker-compose-apps.yaml \ run \ --user $EXEC_USER \ --rm \ $INTERACTIVE_FLAGS \ --volume=$PWD/config/_shared:/vol/confvolume \ --workdir=/vol/confvolume \ $instance_type" if [[ $DEBUG ]]; then echo $CMD_EXEC echo ${other_args[*]} fi eval "${CMD_EXEC} ${other_args[*]}" } # :command.function rcstack_cli_ishell_command() { # src/cli_ishell_command.sh check_bootstrap if [[ -z ${args['--user']} ]]; then # set default, user if the flag is not used args['--user']='rhodecode' fi DEBUG=${args[--debug]} RUN_WITHOUT_TTY=${args[--no-tty]} ENV_FILE=${args[--env-file-path]} EXEC_USER=${args[--user]} INTERACTIVE_FLAGS="--interactive --tty" if [[ $RUN_WITHOUT_TTY ]]; then INTERACTIVE_FLAGS="--interactive" fi proj_name=rc_cluster_apps instance_type=rhodecode docker_id=$(docker ps --filter name=$proj_name-$instance_type -q | head -n1) if [[ $docker_id == "" ]]; then echo "$(yellow cannot find docker instance \($proj_name-$instance_type\) for command execution. Please make sure it is running.)" exit 1 fi index_num=$(docker inspect "$docker_id" --format '{{ index .Config.Labels "com.docker.compose.container-number" }}') if [[ -z "$index_num" ]] then index_num="0" fi RC_STACK_PROFILES="--profile database --profile redis --profile elasticsearch --profile channelstream" CMD_EXEC="\ RC_ENV_FILE=$ENV_FILE docker compose \ --env-file $ENV_FILE \ $ENV_EXPAND \ $RC_STACK_PROFILES \ --project-name $proj_name \ -f docker-compose-base.yaml \ -f docker-compose-apps.yaml \ exec \ --index $index_num \ --user $EXEC_USER \ $INTERACTIVE_FLAGS \ $instance_type \ /usr/local/bin/rhodecode_bin/bin/rc-ishell \ /etc/rhodecode/conf/rhodecode.ini" if [[ $DEBUG ]]; then echo $CMD_EXEC echo ${other_args[*]} fi eval "${CMD_EXEC}" } # :command.function rcstack_cli_image_info_command() { # src/cli_image_info_command.sh verbose=${args[--verbose]} if [[ $verbose ]]; then ver="unknown" if [[ -f $RUNTIME_ENV ]]; then .env --file $RUNTIME_ENV .env get_or_error RC_VERSION ver=$REPLY fi echo "Image stored version: $rc_image_ver" echo "Image from runtime: $ver" echo "runtime-file=$RUNTIME_ENV" echo "RC_VERSION=$ver" else echo $rc_image_ver fi } # :command.function rcstack_cli_set_runtime_image_command() { # src/cli_set_runtime_image_command.sh set_ver=${args[version]} .env --file $RUNTIME_ENV echo "setting runtime version to $set_ver into $RUNTIME_ENV" .env set RC_VERSION=$set_ver echo "New version set to $set_ver" } # :command.function rcstack_cli_docker_info_command() { # src/cli_docker_info_command.sh verbose=${args[--verbose]} docker --version docker compose version if [[ $verbose ]]; then echo "-- DETAILED DOCKER INFO --" docker version fi } # :command.function rcstack_cli_docker_upgrade_command() { # src/cli_docker_upgrade_command.sh DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} DOCKER_CLI_PLUGINS=$DOCKER_CONFIG/cli-plugins upgrade_compose=${args[--compose]} compose_script_name="install-docker.sh" curl -fsSL https://get.docker.com -o "$compose_script_name" # sh install-docker.sh --version 23.0 sh "$compose_script_name" rm -rf "$compose_script_name" if [[ $upgrade_compose ]]; then os_type=$(check_os) if [ "$os_type" != "Linux" ]; then echo "$(red compose upgrade is only available for Linux architecture, got \'$os_type\' instead)" exit fi # just ensure we have this dir mkdir -p "$DOCKER_CLI_PLUGINS" if [[ -f "$DOCKER_CLI_PLUGINS/docker-compose" ]]; then echo "found docker-compose at $DOCKER_CLI_PLUGINS, removing it now..." rm -rf "$DOCKER_CLI_PLUGINS/docker-compose" fi NEW_COMPOSE_VERSION=$(curl --silent https://api.github.com/repos/docker/compose/releases/latest | grep -Po '"tag_name": "\K.*\d') echo "new compose version $NEW_COMPOSE_VERSION to be installed in $DOCKER_CLI_PLUGINS" curl -fsSL https://github.com/docker/compose/releases/download/$NEW_COMPOSE_VERSION/docker-compose-linux-x86_64 -o $DOCKER_CLI_PLUGINS/docker-compose chmod +x $DOCKER_CLI_PLUGINS/docker-compose echo "updated compose to $NEW_COMPOSE_VERSION" fi } # :command.function rcstack_cli_redis_command() { # src/cli_redis_command.sh check_bootstrap if [[ -z ${args['--user']} ]]; then # set default, user if the flag is not used args['--user']='root' fi DEBUG=${args[--debug]} RUN_WITHOUT_TTY=${args[--no-tty]} ENV_FILE=${args[--env-file-path]} EXEC_USER=${args[--user]} db_num=${args[--db]} INTERACTIVE_FLAGS="--interactive --tty" if [[ $RUN_WITHOUT_TTY ]]; then INTERACTIVE_FLAGS="--interactive" fi proj_name=rc_cluster_services instance_type=redis docker_id=$(docker ps --filter name=$proj_name-$instance_type -q | head -n1) if [[ $docker_id == "" ]]; then echo "$(yellow cannot find docker instance \($proj_name-$instance_type\) for command execution. Please make sure it is running.)" exit 1 fi index_num=$(docker inspect "$docker_id" --format '{{ index .Config.Labels "com.docker.compose.container-number" }}') if [[ -z "$index_num" ]] then index_num="0" fi RC_STACK_PROFILES="--profile database --profile redis --profile elasticsearch --profile channelstream" CMD_EXEC="\ RC_ENV_FILE=$ENV_FILE docker compose \ --env-file $ENV_FILE \ $ENV_EXPAND \ $RC_STACK_PROFILES \ --project-name $proj_name \ -f docker-compose-base.yaml \ -f docker-compose-services.yaml \ exec \ --user $EXEC_USER \ $INTERACTIVE_FLAGS \ $instance_type \ /bin/bash -c 'redis-cli -n $db_num'" if [[ $DEBUG ]]; then echo $CMD_EXEC echo ${other_args[*]} fi eval "${CMD_EXEC}" } # :command.function rcstack_cli_db_command() { # src/cli_db_command.sh check_bootstrap if [[ -z ${args['--user']} ]]; then # set default, user if the flag is not used args['--user']='root' fi DEBUG=${args[--debug]} RUN_WITHOUT_TTY=${args[--no-tty]} ENV_FILE=${args[--env-file-path]} EXEC_USER=${args[--user]} INTERACTIVE_FLAGS="--interactive --tty" if [[ $RUN_WITHOUT_TTY ]]; then INTERACTIVE_FLAGS="--interactive" fi .env --file $ENV_FILE .env get_or_error DB_PASSWORD DB_PASSWORD=$REPLY .env get_or_error DB_NAME DB_NAME=$REPLY .env get_or_error DB_USER DB_USER=$REPLY proj_name=rc_cluster_services instance_type=database docker_id=$(docker ps --filter name=$proj_name-$instance_type -q | head -n1) if [[ $docker_id == "" ]]; then echo "$(yellow cannot find docker instance \($proj_name-$instance_type\) for command execution. Please make sure it is running.)" exit 1 fi index_num=$(docker inspect "$docker_id" --format '{{ index .Config.Labels "com.docker.compose.container-number" }}') if [[ -z "$index_num" ]] then index_num="0" fi RC_STACK_PROFILES="--profile database --profile redis --profile elasticsearch --profile channelstream" CMD_EXEC="\ RC_ENV_FILE=$ENV_FILE docker compose \ --env-file $ENV_FILE \ $ENV_EXPAND \ $RC_STACK_PROFILES \ --project-name $proj_name \ -f docker-compose-base.yaml \ -f docker-compose-services.yaml \ exec \ --user $EXEC_USER \ $INTERACTIVE_FLAGS \ $instance_type \ /bin/bash -c 'PGPASSWORD=$DB_PASSWORD psql --username=$DB_USER --dbname=$DB_NAME'" if [[ $DEBUG ]]; then echo $CMD_EXEC echo ${other_args[*]} fi printf "*Volumes*:\n" printf " attaching pg_data under: /var/lib/postgresql/data\n" printf " attaching \$PWD/.custom/db_dump under: /var/rc-data-dump\n" printf "\n" printf "*Restore dump*:\n" printf " \i /var/rc-data-dump/your_dump.sql\n" printf "\n" eval "${CMD_EXEC}" } # :command.function rcstack_cli_db_upgrade_command() { # src/cli_db_upgrade_command.sh check_bootstrap DEBUG=${args[--debug]} target_container=rc_cluster_services-database-* docker_id=$(docker ps --filter name=$target_container -q | head -n1) if [[ $DEBUG ]]; then echo "container id: $docker_id, based on $target_container filter" docker ps fi if [ "$docker_id" == "" ]; then MSG="Cannot find container ID with name $target_container" echo "$(red $MSG)" exit 1 fi if [[ $DEBUG ]]; then echo "./$RC_SCRIPT_NAME stack rhodecode exec rhodecode /usr/local/bin/rhodecode_bin/bin/rc-upgrade-db /etc/rhodecode/conf/rhodecode.ini --force-yes" fi ./$RC_SCRIPT_NAME stack rhodecode exec rhodecode /usr/local/bin/rhodecode_bin/bin/rc-upgrade-db /etc/rhodecode/conf/rhodecode.ini --force-yes } # :command.function rcstack_cli_storage_command() { # src/cli_storage_command.sh check_bootstrap DEBUG=${args[--debug]} RUN_WITHOUT_TTY=${args[--no-tty]} INTERACTIVE_FLAGS="--interactive --tty" if [[ $RUN_WITHOUT_TTY ]]; then INTERACTIVE_FLAGS="--interactive" fi ENV_FILE=${args[--env-file-path]} ATTACHED=${args[--attached]} if [[ $DEBUG ]]; then echo "rc_datavolume inspection..." docker volume inspect rc_datavolume echo "rc_reposvolume inspection..." docker volume inspect rc_reposvolume fi # #if [[ $DEBUG ]]; then # echo "image id: $image_id, based on $target_container filter" # docker image ls # echo "---" #fi # rename a volume #docker volume create --name #docker run --rm -it -v :/from -v :/to alpine ash -c "cd /from ; cp -av . /to" #docker volume rm if [[ $ATTACHED ]]; then printf "Starting with attached mode to vcsserver !" printf "present rc_datavolume \t\tunder: /var/opt/rhodecode_data\n" printf "present rc_reposvolume \t\tunder: /var/opt/rhodecode_repo_store\n" printf "present confvolume \t\tunder: /etc/rhodecode/conf\n" match_name=rc_cluster_apps-vcsserver docker_id=$(docker ps --filter name=$match_name -q | head -n1) if [[ $docker_id == "" ]]; then echo "$(yellow cannot find instance to attach by name *$match_name*)" exit 1 fi docker exec \ $INTERACTIVE_FLAGS \ --workdir /var/opt $docker_id bash else printf "attaching rc_datavolume \t\tunder: /vol/datavolume\n" printf "attaching rc_reposvolume \t\tunder: /vol/repovolume\n" printf "attaching \$PWD/.custom/storage \t\tunder: /vol/backupvolume\n" docker run --rm \ $INTERACTIVE_FLAGS \ --volume $PWD/.custom/storage:/vol/backupvolume \ --volume rc_datavolume:/vol/datavolume \ --volume rc_reposvolume:/vol/repovolume \ --workdir="/vol" \ $BASE_OPS_IMAGE \ /bin/bash fi } # :command.function rcstack_cli_attach_command() { # src/cli_attach_command.sh check_bootstrap RUN_WITHOUT_TTY=${args[--no-tty]} INTERACTIVE_FLAGS="--interactive --tty" if [[ $RUN_WITHOUT_TTY ]]; then INTERACTIVE_FLAGS="--interactive" fi instance_type=${args[--instance-type]} match_name=rc_cluster_apps-$instance_type docker_id=$(docker ps --filter name=$match_name -q | head -n1) if [[ $docker_id == "" ]]; then echo "$(yellow cannot find instance to attach by name *$match_name*)" exit 1 fi docker exec \ $INTERACTIVE_FLAGS \ $docker_id bash } # :command.function rcstack_cli_set_edition_command() { # src/cli_set_edition_command.sh INI_TARGET=$PWD/config/_shared BOOTSTRAP_RUNTIME_ENV=$PWD/.custom/.runtime.env RC_EDITION=${args[edition_type]} ini_path=$INI_TARGET/rhodecode.ini echo "Setting current installation as rhodecode-$RC_EDITION type" echo "configure $ini_path" sed_replace '^use = egg:rhodecode-enterprise.*' "use = egg:rhodecode-enterprise-$RC_EDITION" echo "" echo "configure $BOOTSTRAP_RUNTIME_ENV" .env --file "$BOOTSTRAP_RUNTIME_ENV" .env set RC_EDITION=$RC_EDITION echo "Configuration done, run " echo "./$RC_SCRIPT_NAME stack-upgrade rhodecode" } # :command.function rcstack_cli_configure_vcsserver_command() { # src/cli_configure_vcsserver_command.sh ini_path=${args[ini_path]} DEBUG=${args[--debug]} config_vcsserver_ini echo echo "reconfigure of $ini_path completed" } # :command.function rcstack_cli_configure_rhodecode_command() { # src/cli_configure_rhodecode_command.sh ini_path=${args[ini_path]} DEBUG=${args[--debug]} # read generated secrets etc from our .env file .env --file $RUNTIME_ENV .env get RC_LICENSE_TOKEN RC_LICENSE_TOKEN=$REPLY .env get RC_EDITION RC_EDITION=$REPLY .env get RC_HOSTNAME RC_HOSTNAME=$(sed_safe_path $REPLY) .env get RC_APP_BASE_URL RC_APP_BASE_URL=$(sed_safe_path $REPLY) .env get RC_SQLALCHEMY_DB1_URL RC_SQLALCHEMY_DB1_URL=$(sed_safe_path $REPLY) .env get RC_CHANNELSTREAM_WS_URL RC_CHANNELSTREAM_WS_URL=$(sed_safe_path $REPLY) # $ini_path needs to be defined! config_rhodecode_ini echo echo "reconfigure of $ini_path completed" } # :command.function rcstack_backup_db_command() { # src/backup_db_command.sh check_bootstrap DEBUG=${args[--debug]} DESTINATION=${args[destination]} echo "$(green_bold Creating backup of rcstack database)" backup_date=$(date +%Y-%m-%d) backup_name_prefix=rc_db_dump target_container=rc_cluster_services-database-* docker_id=$(docker ps --filter name=$target_container -q | head -n1) if [[ $DEBUG ]]; then echo "container id: $docker_id, based on $target_container filter" docker ps echo "---" fi if [ "$docker_id" == "" ]; then MSG="Cannot find container ID with name $target_container" echo "$(red $MSG)" exit 1 fi .env --file $RUNTIME_ENV .env get_or_error DB_PASSWORD DB_PASSWORD=$REPLY .env get_or_error DB_NAME DB_NAME=$REPLY .env get_or_error DB_USER DB_USER=$REPLY destination_dir=$DESTINATION spacer="_" backup_name="$backup_name_prefix$spacer$backup_date.sql.gz" if [[ $DEBUG ]]; then echo "docker exec -e PGPASSWORD=$DB_PASSWORD $docker_id /bin/bash -c 'mkdir -p /var/rc-data-dump && pg_dump --inserts -U $DB_USER -h 127.0.0.1 --dbname=$DB_NAME | gzip > /var/rc-data-dump/$backup_name'" echo "dump placed in /var/rc-data-dump/$backup_name" echo "run docker cp $docker_id:/var/rc-data-dump/$backup_name $PWD to copy the file into your host machine" fi set -euo pipefail docker exec -e PGPASSWORD=$DB_PASSWORD $docker_id /bin/bash -c "pg_dump --inserts -U $DB_USER -h 127.0.0.1 --dbname=$DB_NAME | gzip > /var/rc-data-dump/$backup_name" docker cp $docker_id:/var/rc-data-dump/$backup_name $destination_dir echo "$(green Backup created in: \'$destination_dir\')" ls -la $destination_dir | grep $backup_name_prefix } # :command.function rcstack_backup_data_command() { # src/backup_data_command.sh check_bootstrap DEBUG=${args[--debug]} DESTINATION=${args[destination]} echo "$(green_bold Creating backup of rcstack volumes)" backup_date=$(date +%Y-%m-%d) backup_name_prefix=rc_data_dump target_container=rc_cluster_apps-rhodecode-* docker_id=$(docker ps --filter name=$target_container -q | head -n1) if [[ $DEBUG ]]; then echo "container id: $docker_id, based on $target_container filter" docker ps echo "---" fi if [ "$docker_id" == "" ]; then MSG="Cannot find container ID with name $target_container" echo "$(red $MSG)" exit 1 fi set -euo pipefail echo "$(green_bold Following volumes will be backed-up:)" volumes=$(docker inspect --format "{{ range .Mounts }}{{ println .Destination }}{{ end }}" $docker_id) destination_dir=$DESTINATION spacer="_" for vol in $volumes; do echo "Volume: $vol" vol_name=$(slugify $vol) backup_slug="$backup_name_prefix$spacer$vol_name$spacer$backup_date" docker run --rm -v $destination_dir:/backup --volumes-from "$docker_id" $BASE_OPS_IMAGE tar -czvf /backup/$backup_slug.tar.gz "$vol" done echo "$(green Backup created in: \'$destination_dir\')" ls -la $destination_dir | grep $backup_name_prefix #docker-volume-restore-compressed() { # destination_dir=$1 # container=$2 # # docker run --rm -v $destination_dir:/backup --volumes-from "$container" debian:jessie tar -xzvf /backup/backup.tar.gz "${@:3}" # echo "Double checking files..." # docker run --rm -v $destination_dir:/backup --volumes-from "$container" debian:jessie ls -lh "${@:2}" #} } # :command.function rcstack__completions_command() { # src/_completions_command.sh send_completions } # :command.parse_requirements parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --version | -v) version_command exit ;; --help | -h) long_usage=yes rcstack_usage exit ;; # :flag.case --debug) # :flag.case_no_arg args['--debug']=1 shift ;; # :flag.case --no-init-check) # :flag.case_no_arg args['--no-init-check']=1 shift ;; *) break ;; esac done # :command.environment_variables_filter # :command.environment_variables_default export RCC_CONFIG="${RCC_CONFIG:-.rcstack.ini}" export RC_STACK_ROUTER_EXT="${RC_STACK_ROUTER_EXT:-.custom/docker-compose-router.override.yaml}" export RC_STACK_METRICS_EXT="${RC_STACK_METRICS_EXT:-.custom/docker-compose-metrics.override.yaml}" export RC_STACK_SERVICES_EXT="${RC_STACK_SERVICES_EXT:-.custom/docker-compose-services.override.yaml}" export RC_STACK_RHODECODE_EXT="${RC_STACK_RHODECODE_EXT:-.custom/docker-compose-apps.override.yaml}" # :command.command_filter action=${1:-} case $action in -*) ;; get-started) action="get-started" shift rcstack_get_started_parse_requirements "$@" shift $# ;; init) action="init" shift rcstack_init_parse_requirements "$@" shift $# ;; self-update) action="self-update" shift rcstack_self_update_parse_requirements "$@" shift $# ;; stack) action="stack" shift rcstack_stack_parse_requirements "$@" shift $# ;; stack-status | status) action="stack-status" shift rcstack_stack_status_parse_requirements "$@" shift $# ;; stack-upgrade) action="stack-upgrade" shift rcstack_stack_upgrade_parse_requirements "$@" shift $# ;; stack-monitor) action="stack-monitor" shift rcstack_stack_monitor_parse_requirements "$@" shift $# ;; cli) action="cli" shift rcstack_cli_parse_requirements "$@" shift $# ;; backup-db) action="backup-db" shift rcstack_backup_db_parse_requirements "$@" shift $# ;; backup-data) action="backup-data" shift rcstack_backup_data_parse_requirements "$@" shift $# ;; _completions) action="_completions" shift rcstack__completions_parse_requirements "$@" shift $# ;; # :command.command_fallback "") rcstack_usage >&2 exit 1 ;; *) printf "invalid command: %s\n" "$action" >&2 exit 1 ;; esac # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done } # :command.parse_requirements rcstack_get_started_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_get_started_usage exit ;; *) break ;; esac done # :command.command_filter action="get-started" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done } # :command.parse_requirements rcstack_init_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_init_usage exit ;; *) break ;; esac done # :command.dependencies_filter if command -v curl >/dev/null 2>&1; then deps['curl']="$(command -v curl | head -n1)" else printf "missing dependency: curl\n" >&2 exit 1 fi if command -v tar >/dev/null 2>&1; then deps['tar']="$(command -v tar | head -n1)" else printf "missing dependency: tar\n" >&2 exit 1 fi if command -v find >/dev/null 2>&1; then deps['find']="$(command -v find | head -n1)" else printf "missing dependency: find\n" >&2 exit 1 fi # :command.command_filter action="init" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in # :flag.case --arg-rc-edition) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--arg-rc-edition']="$2" shift shift else printf "%s\n" "--arg-rc-edition requires an argument: --arg-rc-edition ARG_RC_EDITION" >&2 exit 1 fi ;; # :flag.case --arg-hostname) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--arg-hostname']="$2" shift shift else printf "%s\n" "--arg-hostname requires an argument: --arg-hostname ARG_HOSTNAME" >&2 exit 1 fi ;; # :flag.case --arg-use-ssl) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--arg-use-ssl']="$2" shift shift else printf "%s\n" "--arg-use-ssl requires an argument: --arg-use-ssl ARG_USE_SSL" >&2 exit 1 fi ;; # :flag.case --arg-admin-email) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--arg-admin-email']="$2" shift shift else printf "%s\n" "--arg-admin-email requires an argument: --arg-admin-email ARG_ADMIN_EMAIL" >&2 exit 1 fi ;; # :flag.case --arg-admin-user) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--arg-admin-user']="$2" shift shift else printf "%s\n" "--arg-admin-user requires an argument: --arg-admin-user ARG_ADMIN_USER" >&2 exit 1 fi ;; # :flag.case --arg-admin-pass) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--arg-admin-pass']="$2" shift shift else printf "%s\n" "--arg-admin-pass requires an argument: --arg-admin-pass ARG_ADMIN_PASS" >&2 exit 1 fi ;; # :flag.case --arg-license-token) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--arg-license-token']="$2" shift shift else printf "%s\n" "--arg-license-token requires an argument: --arg-license-token ARG_ADMIN_TOKEN" >&2 exit 1 fi ;; # :flag.case --no-prompt) # :flag.case_no_arg args['--no-prompt']=1 shift ;; # :flag.case --force | -f) # :flag.case_no_arg args['--force']=1 shift ;; # :flag.case --stage) # :flag.case_arg if [[ -n ${2+x} ]]; then if [[ -z ${args['--stage']+x} ]]; then args['--stage']="\"$2\"" else args['--stage']="${args[--stage]} \"$2\"" fi shift shift else printf "%s\n" "--stage requires an argument: --stage STAGE" >&2 exit 1 fi ;; # :flag.case --docker-revision) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--docker-revision']="$2" shift shift else printf "%s\n" "--docker-revision requires an argument: --docker-revision DOCKER_REVISION" >&2 exit 1 fi ;; # :flag.case --install-docker) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--install-docker']="$2" shift shift else printf "%s\n" "--install-docker requires an argument: --install-docker INSTALL_DOCKER" >&2 exit 1 fi ;; # :flag.case --server-url) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--server-url']="$2" shift shift else printf "%s\n" "--server-url requires an argument: --server-url SERVER_URL" >&2 exit 1 fi ;; # :flag.case --auth-token) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--auth-token']="$2" shift shift else printf "%s\n" "--auth-token requires an argument: --auth-token AUTH_TOKEN" >&2 exit 1 fi ;; -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done # :command.default_assignments [[ -n ${args['--docker-revision']:-} ]] || args['--docker-revision']="stable" [[ -n ${args['--server-url']:-} ]] || args['--server-url']="https://dls.rhodecode.com/get_archive" } # :command.parse_requirements rcstack_self_update_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_self_update_usage exit ;; *) break ;; esac done # :command.dependencies_filter if command -v curl >/dev/null 2>&1; then deps['curl']="$(command -v curl | head -n1)" else printf "missing dependency: curl\n" >&2 exit 1 fi if command -v tar >/dev/null 2>&1; then deps['tar']="$(command -v tar | head -n1)" else printf "missing dependency: tar\n" >&2 exit 1 fi # :command.command_filter action="self-update" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in # :flag.case --force) # :flag.case_no_arg args['--force']=1 shift ;; # :flag.case --update-docker-image) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--update-docker-image']="$2" shift shift else printf "%s\n" "--update-docker-image requires an argument: --update-docker-image UPDATE_DOCKER_IMAGE" >&2 exit 1 fi ;; # :flag.case --cli-revision) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--cli-revision']="$2" shift shift else printf "%s\n" "--cli-revision requires an argument: --cli-revision CLI_REVISION" >&2 exit 1 fi ;; # :flag.case --docker-revision) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--docker-revision']="$2" shift shift else printf "%s\n" "--docker-revision requires an argument: --docker-revision DOCKER_REVISION" >&2 exit 1 fi ;; # :flag.case --server-url) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--server-url']="$2" shift shift else printf "%s\n" "--server-url requires an argument: --server-url SERVER_URL" >&2 exit 1 fi ;; # :flag.case --auth-token) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--auth-token']="$2" shift shift else printf "%s\n" "--auth-token requires an argument: --auth-token AUTH_TOKEN" >&2 exit 1 fi ;; -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done # :command.default_assignments [[ -n ${args['--cli-revision']:-} ]] || args['--cli-revision']="stable" [[ -n ${args['--docker-revision']:-} ]] || args['--docker-revision']="stable" [[ -n ${args['--server-url']:-} ]] || args['--server-url']="https://dls.rhodecode.com/get_archive" } # :command.parse_requirements rcstack_stack_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_stack_usage exit ;; # :flag.case --env-file-path) # :flag.case_arg if [[ -n ${2+x} ]]; then # :flag.validations if [[ -n $(validate_file_exists "$2") ]]; then printf "validation error in %s:\n%s\n" "--env-file-path ENV_FILE_PATH" "$(validate_file_exists "$2")" >&2 exit 1 fi args['--env-file-path']="$2" shift shift else printf "%s\n" "--env-file-path requires an argument: --env-file-path ENV_FILE_PATH" >&2 exit 1 fi ;; # :flag.case --stack-prefix) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--stack-prefix']="$2" shift shift else printf "%s\n" "--stack-prefix requires an argument: --stack-prefix STACK_PREFIX" >&2 exit 1 fi ;; *) break ;; esac done # :command.command_filter action=${1:-} case $action in -*) ;; router) action="router" shift rcstack_stack_router_parse_requirements "$@" shift $# ;; metrics) action="metrics" shift rcstack_stack_metrics_parse_requirements "$@" shift $# ;; services) action="services" shift rcstack_stack_services_parse_requirements "$@" shift $# ;; rhodecode) action="rhodecode" shift rcstack_stack_rhodecode_parse_requirements "$@" shift $# ;; all) action="all" shift rcstack_stack_all_parse_requirements "$@" shift $# ;; # :command.command_fallback "") rcstack_stack_usage >&2 exit 1 ;; *) printf "invalid command: %s\n" "$action" >&2 exit 1 ;; esac # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done # :command.default_assignments [[ -n ${args['--env-file-path']:-} ]] || args['--env-file-path']="$PWD/.custom/.runtime.env" } # :command.parse_requirements rcstack_stack_router_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_stack_router_usage exit ;; *) break ;; esac done # :command.command_filter action="stack router" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in --) shift other_args+=("$@") break ;; -?*) other_args+=("$1") shift ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_catch_all other_args+=("$1") shift ;; esac done } # :command.parse_requirements rcstack_stack_metrics_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_stack_metrics_usage exit ;; *) break ;; esac done # :command.command_filter action="stack metrics" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in --) shift other_args+=("$@") break ;; -?*) other_args+=("$1") shift ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_catch_all other_args+=("$1") shift ;; esac done } # :command.parse_requirements rcstack_stack_services_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_stack_services_usage exit ;; *) break ;; esac done # :command.command_filter action="stack services" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in --) shift other_args+=("$@") break ;; -?*) other_args+=("$1") shift ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_catch_all other_args+=("$1") shift ;; esac done } # :command.parse_requirements rcstack_stack_rhodecode_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_stack_rhodecode_usage exit ;; *) break ;; esac done # :command.command_filter action="stack rhodecode" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in --) shift other_args+=("$@") break ;; -?*) other_args+=("$1") shift ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_catch_all other_args+=("$1") shift ;; esac done } # :command.parse_requirements rcstack_stack_all_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_stack_all_usage exit ;; *) break ;; esac done # :command.command_filter action="stack all" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in --) shift other_args+=("$@") break ;; -?*) other_args+=("$1") shift ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_catch_all other_args+=("$1") shift ;; esac done } # :command.parse_requirements rcstack_stack_status_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_stack_status_usage exit ;; *) break ;; esac done # :command.command_filter action="stack-status" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in # :flag.case --detailed) # :flag.case_no_arg args['--detailed']=1 shift ;; # :flag.case --configs) # :flag.case_no_arg args['--configs']=1 shift ;; # :flag.case -v) # :flag.case_no_arg args['-v']=1 shift ;; -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done } # :command.parse_requirements rcstack_stack_upgrade_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_stack_upgrade_usage exit ;; # :flag.case --stack-prefix) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--stack-prefix']="$2" shift shift else printf "%s\n" "--stack-prefix requires an argument: --stack-prefix STACK_PREFIX" >&2 exit 1 fi ;; *) break ;; esac done # :command.command_filter action=${1:-} case $action in -*) ;; router) action="router" shift rcstack_stack_upgrade_router_parse_requirements "$@" shift $# ;; services) action="services" shift rcstack_stack_upgrade_services_parse_requirements "$@" shift $# ;; metrics) action="metrics" shift rcstack_stack_upgrade_metrics_parse_requirements "$@" shift $# ;; rhodecode) action="rhodecode" shift rcstack_stack_upgrade_rhodecode_parse_requirements "$@" shift $# ;; # :command.command_fallback "") rcstack_stack_upgrade_usage >&2 exit 1 ;; *) printf "invalid command: %s\n" "$action" >&2 exit 1 ;; esac # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done } # :command.parse_requirements rcstack_stack_upgrade_router_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_stack_upgrade_router_usage exit ;; *) break ;; esac done # :command.command_filter action="stack-upgrade router" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done } # :command.parse_requirements rcstack_stack_upgrade_services_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_stack_upgrade_services_usage exit ;; *) break ;; esac done # :command.command_filter action="stack-upgrade services" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done } # :command.parse_requirements rcstack_stack_upgrade_metrics_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_stack_upgrade_metrics_usage exit ;; *) break ;; esac done # :command.command_filter action="stack-upgrade metrics" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done } # :command.parse_requirements rcstack_stack_upgrade_rhodecode_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_stack_upgrade_rhodecode_usage exit ;; *) break ;; esac done # :command.command_filter action="stack-upgrade rhodecode" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in # :flag.case --stop-wait) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--stop-wait']="$2" shift shift else printf "%s\n" "--stop-wait requires an argument: --stop-wait STOP_WAIT" >&2 exit 1 fi ;; # :flag.case --docker-stop-wait) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--docker-stop-wait']="$2" shift shift else printf "%s\n" "--docker-stop-wait requires an argument: --docker-stop-wait DOCKER_STOP_WAIT" >&2 exit 1 fi ;; -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done # :command.default_assignments [[ -n ${args['--stop-wait']:-} ]] || args['--stop-wait']="120" [[ -n ${args['--docker-stop-wait']:-} ]] || args['--docker-stop-wait']="3600" } # :command.parse_requirements rcstack_stack_monitor_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_stack_monitor_usage exit ;; *) break ;; esac done # :command.command_filter action=${1:-} case $action in -*) ;; restart-unhealthy) action="restart-unhealthy" shift rcstack_stack_monitor_restart_unhealthy_parse_requirements "$@" shift $# ;; # :command.command_fallback "") rcstack_stack_monitor_usage >&2 exit 1 ;; *) printf "invalid command: %s\n" "$action" >&2 exit 1 ;; esac # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done } # :command.parse_requirements rcstack_stack_monitor_restart_unhealthy_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_stack_monitor_restart_unhealthy_usage exit ;; *) break ;; esac done # :command.command_filter action="stack-monitor restart-unhealthy" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in # :flag.case --loop) # :flag.case_arg if [[ -n ${2+x} ]]; then # :flag.validations if [[ -n $(validate_integer "$2") ]]; then printf "validation error in %s:\n%s\n" "--loop LOOP" "$(validate_integer "$2")" >&2 exit 1 fi args['--loop']="$2" shift shift else printf "%s\n" "--loop requires an argument: --loop LOOP" >&2 exit 1 fi ;; -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done # :command.default_assignments [[ -n ${args['--loop']:-} ]] || args['--loop']="0" } # :command.parse_requirements rcstack_cli_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_cli_usage exit ;; *) break ;; esac done # :command.command_filter action=${1:-} case $action in -*) ;; cmd) action="cmd" shift rcstack_cli_cmd_parse_requirements "$@" shift $# ;; ishell) action="ishell" shift rcstack_cli_ishell_parse_requirements "$@" shift $# ;; image-info) action="image-info" shift rcstack_cli_image_info_parse_requirements "$@" shift $# ;; set-runtime-image) action="set-runtime-image" shift rcstack_cli_set_runtime_image_parse_requirements "$@" shift $# ;; docker-info) action="docker-info" shift rcstack_cli_docker_info_parse_requirements "$@" shift $# ;; docker-upgrade) action="docker-upgrade" shift rcstack_cli_docker_upgrade_parse_requirements "$@" shift $# ;; redis) action="redis" shift rcstack_cli_redis_parse_requirements "$@" shift $# ;; db) action="db" shift rcstack_cli_db_parse_requirements "$@" shift $# ;; db-upgrade) action="db-upgrade" shift rcstack_cli_db_upgrade_parse_requirements "$@" shift $# ;; storage) action="storage" shift rcstack_cli_storage_parse_requirements "$@" shift $# ;; attach) action="attach" shift rcstack_cli_attach_parse_requirements "$@" shift $# ;; set-edition) action="set-edition" shift rcstack_cli_set_edition_parse_requirements "$@" shift $# ;; configure-vcsserver) action="configure-vcsserver" shift rcstack_cli_configure_vcsserver_parse_requirements "$@" shift $# ;; configure-rhodecode) action="configure-rhodecode" shift rcstack_cli_configure_rhodecode_parse_requirements "$@" shift $# ;; # :command.command_fallback "") rcstack_cli_usage >&2 exit 1 ;; *) printf "invalid command: %s\n" "$action" >&2 exit 1 ;; esac # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done } # :command.parse_requirements rcstack_cli_cmd_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_cli_cmd_usage exit ;; *) break ;; esac done # :command.command_filter action="cli cmd" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in # :flag.case --no-tty) # :flag.case_no_arg args['--no-tty']=1 shift ;; # :flag.case --user) # :flag.case_no_arg args['--user']=1 shift ;; # :flag.case --env-file-path) # :flag.case_arg if [[ -n ${2+x} ]]; then # :flag.validations if [[ -n $(validate_file_exists "$2") ]]; then printf "validation error in %s:\n%s\n" "--env-file-path ENV_FILE_PATH" "$(validate_file_exists "$2")" >&2 exit 1 fi args['--env-file-path']="$2" shift shift else printf "%s\n" "--env-file-path requires an argument: --env-file-path ENV_FILE_PATH" >&2 exit 1 fi ;; --) shift other_args+=("$@") break ;; -?*) other_args+=("$1") shift ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_catch_all other_args+=("$1") shift ;; esac done # :command.default_assignments [[ -n ${args['--env-file-path']:-} ]] || args['--env-file-path']="$PWD/.custom/.runtime.env" } # :command.parse_requirements rcstack_cli_ishell_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_cli_ishell_usage exit ;; *) break ;; esac done # :command.command_filter action="cli ishell" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in # :flag.case --no-tty) # :flag.case_no_arg args['--no-tty']=1 shift ;; # :flag.case --user) # :flag.case_no_arg args['--user']=1 shift ;; # :flag.case --env-file-path) # :flag.case_arg if [[ -n ${2+x} ]]; then # :flag.validations if [[ -n $(validate_file_exists "$2") ]]; then printf "validation error in %s:\n%s\n" "--env-file-path ENV_FILE_PATH" "$(validate_file_exists "$2")" >&2 exit 1 fi args['--env-file-path']="$2" shift shift else printf "%s\n" "--env-file-path requires an argument: --env-file-path ENV_FILE_PATH" >&2 exit 1 fi ;; -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done # :command.default_assignments [[ -n ${args['--env-file-path']:-} ]] || args['--env-file-path']="$PWD/.custom/.runtime.env" } # :command.parse_requirements rcstack_cli_image_info_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_cli_image_info_usage exit ;; *) break ;; esac done # :command.command_filter action="cli image-info" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in # :flag.case --verbose) # :flag.case_no_arg args['--verbose']=1 shift ;; -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done } # :command.parse_requirements rcstack_cli_set_runtime_image_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_cli_set_runtime_image_usage exit ;; *) break ;; esac done # :command.command_filter action="cli set-runtime-image" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple if [[ -z ${args['version']+x} ]]; then args['version']=$1 shift else printf "invalid argument: %s\n" "$key" >&2 exit 1 fi ;; esac done # :command.required_args_filter if [[ -z ${args['version']+x} ]]; then printf "missing required argument: VERSION\nusage: rcstack cli set-runtime-image VERSION\n" >&2 exit 1 fi } # :command.parse_requirements rcstack_cli_docker_info_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_cli_docker_info_usage exit ;; *) break ;; esac done # :command.command_filter action="cli docker-info" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in # :flag.case --verbose) # :flag.case_no_arg args['--verbose']=1 shift ;; -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done } # :command.parse_requirements rcstack_cli_docker_upgrade_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_cli_docker_upgrade_usage exit ;; *) break ;; esac done # :command.command_filter action="cli docker-upgrade" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in # :flag.case --compose) # :flag.case_no_arg args['--compose']=1 shift ;; -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done } # :command.parse_requirements rcstack_cli_redis_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_cli_redis_usage exit ;; *) break ;; esac done # :command.command_filter action="cli redis" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in # :flag.case --no-tty) # :flag.case_no_arg args['--no-tty']=1 shift ;; # :flag.case --user) # :flag.case_no_arg args['--user']=1 shift ;; # :flag.case --env-file-path) # :flag.case_arg if [[ -n ${2+x} ]]; then # :flag.validations if [[ -n $(validate_file_exists "$2") ]]; then printf "validation error in %s:\n%s\n" "--env-file-path ENV_FILE_PATH" "$(validate_file_exists "$2")" >&2 exit 1 fi args['--env-file-path']="$2" shift shift else printf "%s\n" "--env-file-path requires an argument: --env-file-path ENV_FILE_PATH" >&2 exit 1 fi ;; # :flag.case --db) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--db']="$2" shift shift else printf "%s\n" "--db requires an argument: --db DB" >&2 exit 1 fi ;; -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done # :command.default_assignments [[ -n ${args['--env-file-path']:-} ]] || args['--env-file-path']="$PWD/.custom/.runtime.env" [[ -n ${args['--db']:-} ]] || args['--db']="0" } # :command.parse_requirements rcstack_cli_db_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_cli_db_usage exit ;; *) break ;; esac done # :command.command_filter action="cli db" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in # :flag.case --no-tty) # :flag.case_no_arg args['--no-tty']=1 shift ;; # :flag.case --user) # :flag.case_no_arg args['--user']=1 shift ;; # :flag.case --env-file-path) # :flag.case_arg if [[ -n ${2+x} ]]; then # :flag.validations if [[ -n $(validate_file_exists "$2") ]]; then printf "validation error in %s:\n%s\n" "--env-file-path ENV_FILE_PATH" "$(validate_file_exists "$2")" >&2 exit 1 fi args['--env-file-path']="$2" shift shift else printf "%s\n" "--env-file-path requires an argument: --env-file-path ENV_FILE_PATH" >&2 exit 1 fi ;; -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done # :command.default_assignments [[ -n ${args['--env-file-path']:-} ]] || args['--env-file-path']="$PWD/.custom/.runtime.env" } # :command.parse_requirements rcstack_cli_db_upgrade_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_cli_db_upgrade_usage exit ;; *) break ;; esac done # :command.command_filter action="cli db-upgrade" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done } # :command.parse_requirements rcstack_cli_storage_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_cli_storage_usage exit ;; *) break ;; esac done # :command.command_filter action="cli storage" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in # :flag.case --no-tty) # :flag.case_no_arg args['--no-tty']=1 shift ;; # :flag.case --attached) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--attached']="$2" shift shift else printf "%s\n" "--attached requires an argument: --attached ATTACHED" >&2 exit 1 fi ;; -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done } # :command.parse_requirements rcstack_cli_attach_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_cli_attach_usage exit ;; *) break ;; esac done # :command.command_filter action="cli attach" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in # :flag.case --no-tty) # :flag.case_no_arg args['--no-tty']=1 shift ;; # :flag.case --instance-type) # :flag.case_arg if [[ -n ${2+x} ]]; then args['--instance-type']="$2" shift shift else printf "%s\n" "--instance-type requires an argument: --instance-type INSTANCE_TYPE" >&2 exit 1 fi ;; -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done # :command.default_assignments [[ -n ${args['--instance-type']:-} ]] || args['--instance-type']="rhodecode" } # :command.parse_requirements rcstack_cli_set_edition_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_cli_set_edition_usage exit ;; *) break ;; esac done # :command.command_filter action="cli set-edition" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple if [[ -z ${args['edition_type']+x} ]]; then args['edition_type']=$1 shift else printf "invalid argument: %s\n" "$key" >&2 exit 1 fi ;; esac done # :command.required_args_filter if [[ -z ${args['edition_type']+x} ]]; then printf "missing required argument: EDITION_TYPE\nusage: rcstack cli set-edition EDITION_TYPE\n" >&2 exit 1 fi # :command.whitelist_filter if [[ -n ${args['edition_type']} ]] && [[ ! ${args['edition_type']} =~ ^(ce|ee)$ ]]; then printf "%s\n" "edition_type must be one of: ce, ee" >&2 exit 1 fi } # :command.parse_requirements rcstack_cli_configure_vcsserver_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_cli_configure_vcsserver_usage exit ;; *) break ;; esac done # :command.command_filter action="cli configure-vcsserver" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple if [[ -z ${args['ini_path']+x} ]]; then # :argument.validations if [[ -n $(validate_file_exists "$1") ]]; then printf "validation error in %s:\n%s\n" "INI_PATH" "$(validate_file_exists "$1")" >&2 exit 1 fi args['ini_path']=$1 shift else printf "invalid argument: %s\n" "$key" >&2 exit 1 fi ;; esac done # :command.required_args_filter if [[ -z ${args['ini_path']+x} ]]; then printf "missing required argument: INI_PATH\nusage: rcstack cli configure-vcsserver INI_PATH\n" >&2 exit 1 fi } # :command.parse_requirements rcstack_cli_configure_rhodecode_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_cli_configure_rhodecode_usage exit ;; *) break ;; esac done # :command.command_filter action="cli configure-rhodecode" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple if [[ -z ${args['ini_path']+x} ]]; then # :argument.validations if [[ -n $(validate_file_exists "$1") ]]; then printf "validation error in %s:\n%s\n" "INI_PATH" "$(validate_file_exists "$1")" >&2 exit 1 fi args['ini_path']=$1 shift else printf "invalid argument: %s\n" "$key" >&2 exit 1 fi ;; esac done # :command.required_args_filter if [[ -z ${args['ini_path']+x} ]]; then printf "missing required argument: INI_PATH\nusage: rcstack cli configure-rhodecode INI_PATH\n" >&2 exit 1 fi } # :command.parse_requirements rcstack_backup_db_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_backup_db_usage exit ;; *) break ;; esac done # :command.dependencies_filter if command -v tar >/dev/null 2>&1; then deps['tar']="$(command -v tar | head -n1)" else printf "missing dependency: tar\n" >&2 exit 1 fi if command -v gzip >/dev/null 2>&1; then deps['gzip']="$(command -v gzip | head -n1)" else printf "missing dependency: gzip\n" >&2 exit 1 fi # :command.command_filter action="backup-db" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple if [[ -z ${args['destination']+x} ]]; then # :argument.validations if [[ -n $(validate_dir_exists "$1") ]]; then printf "validation error in %s:\n%s\n" "DESTINATION" "$(validate_dir_exists "$1")" >&2 exit 1 fi args['destination']=$1 shift else printf "invalid argument: %s\n" "$key" >&2 exit 1 fi ;; esac done # :command.required_args_filter if [[ -z ${args['destination']+x} ]]; then printf "missing required argument: DESTINATION\nusage: rcstack backup-db DESTINATION\n" >&2 exit 1 fi } # :command.parse_requirements rcstack_backup_data_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack_backup_data_usage exit ;; *) break ;; esac done # :command.dependencies_filter if command -v tar >/dev/null 2>&1; then deps['tar']="$(command -v tar | head -n1)" else printf "missing dependency: tar\n" >&2 exit 1 fi if command -v gzip >/dev/null 2>&1; then deps['gzip']="$(command -v gzip | head -n1)" else printf "missing dependency: gzip\n" >&2 exit 1 fi # :command.command_filter action="backup-data" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple if [[ -z ${args['destination']+x} ]]; then # :argument.validations if [[ -n $(validate_dir_exists "$1") ]]; then printf "validation error in %s:\n%s\n" "DESTINATION" "$(validate_dir_exists "$1")" >&2 exit 1 fi args['destination']=$1 shift else printf "invalid argument: %s\n" "$key" >&2 exit 1 fi ;; esac done # :command.required_args_filter if [[ -z ${args['destination']+x} ]]; then printf "missing required argument: DESTINATION\nusage: rcstack backup-data DESTINATION\n" >&2 exit 1 fi } # :command.parse_requirements rcstack__completions_parse_requirements() { # :command.fixed_flags_filter while [[ $# -gt 0 ]]; do case "${1:-}" in --help | -h) long_usage=yes rcstack__completions_usage exit ;; *) break ;; esac done # :command.command_filter action="_completions" # :command.parse_requirements_while while [[ $# -gt 0 ]]; do key="$1" case "$key" in -?*) printf "invalid option: %s\n" "$key" >&2 exit 1 ;; *) # :command.parse_requirements_case # :command.parse_requirements_case_simple printf "invalid argument: %s\n" "$key" >&2 exit 1 ;; esac done } # :command.initialize initialize() { version="5.8.0" long_usage='' set -e # :command.environment_variables_default export RCC_CONFIG="${RCC_CONFIG:-.rcstack.ini}" export RC_STACK_ROUTER_EXT="${RC_STACK_ROUTER_EXT:-.custom/docker-compose-router.override.yaml}" export RC_STACK_METRICS_EXT="${RC_STACK_METRICS_EXT:-.custom/docker-compose-metrics.override.yaml}" export RC_STACK_SERVICES_EXT="${RC_STACK_SERVICES_EXT:-.custom/docker-compose-services.override.yaml}" export RC_STACK_RHODECODE_EXT="${RC_STACK_RHODECODE_EXT:-.custom/docker-compose-apps.override.yaml}" # src/initialize.sh rc_image_ver=4.28.0 rhodecode_default_config_path=config/_shared/rhodecode.ini vcsserver_default_config_path=config/_shared/vcsserver.ini RC_STACK_ROUTER_VER=1.0.0 RC_STACK_SERVICES_VER=1.0.0 RC_STACK_RHODECODE_VER=1.0.0 RC_STACK_METRICS_VER=1.0.0 RC_SCRIPT_NAME=rcstack # bootstrap file is a config file at the same time CONFIG_FILE=${RCC_CONFIG:=.rcstack.ini} # runtime env file RUNTIME_ENV=$PWD/.custom/.runtime.env # STACK_LIST VALID_SERVICES="router metrics services rhodecode" DOCKER_DEFS_WORK_DIR="docker_defs" # stage key, saved in .rcstack.ini : stage func to execute BOOTSTRAP_STAGES="\ bootstrap_v1_docker_install \ bootstrap_v1_docker_commons \ bootstrap_v1_definitions \ bootstrap_v1_config \ bootstrap_v1_overrides \ " YAML_TEMPLATES="\ docker-compose-apps.override.yaml docker-compose-metrics.override.yaml docker-compose-router.override.yaml docker-compose-services.override.yaml runtime.env.tmpl " BASE_OPS_IMAGE="ubuntu:22.04" get_stage_function() { stage_name=$1 case $stage_name in bootstrap_v1_docker_install) stage_func=bootstrap_docker_install ;; bootstrap_v1_docker_commons) stage_func=bootstrap_docker_commons ;; bootstrap_v1_definitions) stage_func=bootstrap_definitions ;; bootstrap_v1_config) stage_func=bootstrap_config ;; bootstrap_v1_overrides) stage_func=bootstrap_overrides ;; *) echo "can't find function for stage $stage_name" exit 1 esac echo $stage_func } #echo "1 ----" #echo $RC_STACK_SERVICES_EXT #echo $RC_STACK_METRICS_EXT #echo "1 -----" #echo '2 ----' #grep -v -e '^#' "$ENV_FILE" | xargs -I {} echo \'{}\' #echo '2 ----' #expose env vars from ./rcstack config #if [[ -f $ENV_FILE ]]; then # eval $(grep -v -e '^#' "$ENV_FILE" | xargs -I {} echo export \'{}\') #fi #ENV_EXPAND="" #for k in $(config_keys); do # k_upper=${k^^} # env_entry="-e $k_upper='$(config_get "$k")' " # ENV_EXPAND+=$env_entry; # #echo $env_expand #done # #echo "3 ----" #echo $RC_STACK_SERVICES_EXT #echo $RC_STACK_METRICS_EXT #echo $RC_STACK_RHODECODE_EXT #echo "3 -----" #env | grep RC_ docker_ping_host() { PING_HOST="$1" docker run --network rhodecode_network --rm alpine ping "$PING_HOST" } get_started() { echo "" echo "To start using RhodeCode run the following stacks using './$RC_SCRIPT_NAME stack [STACK_NAME]'" echo "Check './$RC_SCRIPT_NAME stack --help' for more examples and options" echo "$(green_bold IMPORTANT): init command generates some secrets/config inside $RUNTIME_ENV file." echo "Check and adjust those settings if needed." echo "" echo "$(bold Run the stacks in following order):" echo "$(bold [NOTE]): Instead of running stacks independent, one can use shorthand to run all stacks in order (detached with -d)" echo "./$RC_SCRIPT_NAME stack all up -d" echo "" echo "$(green_bold 1\) router [Mandatory]): run the edge router to control stack traffic / domain access and optionally SSL termination" echo "IMPORTANT: router binds to some common ports 80, 443, SSH (9022), Loki (3100) if those are not available, please adjust them" echo "To configure this stack before running check: $RC_STACK_ROUTER_EXT" echo "" echo "./$RC_SCRIPT_NAME stack router up --detach" echo "" echo "$(green_bold 2\) services [Mandatory]): run the services, like database, redis, channelstream etc..." echo "IMPORTANT: if you like to run your own database, or redis please adjust before running" echo "To configure this stack before running check: $RC_STACK_SERVICES_EXT" echo "" echo "./$RC_SCRIPT_NAME stack services up --detach" echo "" echo "$(green_bold 3\) rhodecode [Mandatory]): run the rhodecode app stack" echo "To configure this stack before running check: $RC_STACK_RHODECODE_EXT" echo "" echo "./$RC_SCRIPT_NAME stack rhodecode up --detach" echo "" echo "$(yellow_bold 4\) metrics [Optional]): run the monitoring stack, this includes grafana/prometheus logging/metrics system" echo "To configure this stack before running check: $RC_STACK_METRICS_EXT" echo "" echo "./$RC_SCRIPT_NAME stack metrics up --detach" echo "" echo "$(bold [Status]): check services run status, ports etc.." echo "./$RC_SCRIPT_NAME status -v --configs" echo "" echo "$(bold [Logs]): check service logs" echo "./$RC_SCRIPT_NAME stack [STACK_NAME] logs" } get_started_full() { echo "$(blue_bold [~~~~ GET STARTED ~~~~~])" echo "$(green_bold Having problems / need help? Reach out to us here:) https://community.rhodecode.com" echo "" echo "./$RC_SCRIPT_NAME is a CLI based installer/manager for RhodeCode Cluster Stack" echo "./$RC_SCRIPT_NAME -h is your friend, in case of doubt, check examples and usage options with -h / --help flag" echo "" echo "$(yellow_bold [First time run])" echo "run './$RC_SCRIPT_NAME init' to setup docker and download required installer files." echo "./$RC_SCRIPT_NAME can install Docker for you, or install it manually before running init command" get_started } } # :command.run run() { declare -A args=() declare -A deps=() declare -a other_args=() declare -a input=() normalize_input "$@" parse_requirements "${input[@]}" case "$action" in "get-started") rcstack_get_started_command ;; "init") rcstack_init_command ;; "self-update") rcstack_self_update_command ;; "stack") rcstack_stack_command ;; "stack router") rcstack_stack_router_command ;; "stack metrics") rcstack_stack_metrics_command ;; "stack services") rcstack_stack_services_command ;; "stack rhodecode") rcstack_stack_rhodecode_command ;; "stack all") rcstack_stack_all_command ;; "stack-status") rcstack_stack_status_command ;; "stack-upgrade") rcstack_stack_upgrade_command ;; "stack-upgrade router") rcstack_stack_upgrade_router_command ;; "stack-upgrade services") rcstack_stack_upgrade_services_command ;; "stack-upgrade metrics") rcstack_stack_upgrade_metrics_command ;; "stack-upgrade rhodecode") rcstack_stack_upgrade_rhodecode_command ;; "stack-monitor") rcstack_stack_monitor_command ;; "stack-monitor restart-unhealthy") rcstack_stack_monitor_restart_unhealthy_command ;; "cli") rcstack_cli_command ;; "cli cmd") rcstack_cli_cmd_command ;; "cli ishell") rcstack_cli_ishell_command ;; "cli image-info") rcstack_cli_image_info_command ;; "cli set-runtime-image") rcstack_cli_set_runtime_image_command ;; "cli docker-info") rcstack_cli_docker_info_command ;; "cli docker-upgrade") rcstack_cli_docker_upgrade_command ;; "cli redis") rcstack_cli_redis_command ;; "cli db") rcstack_cli_db_command ;; "cli db-upgrade") rcstack_cli_db_upgrade_command ;; "cli storage") rcstack_cli_storage_command ;; "cli attach") rcstack_cli_attach_command ;; "cli set-edition") rcstack_cli_set_edition_command ;; "cli configure-vcsserver") rcstack_cli_configure_vcsserver_command ;; "cli configure-rhodecode") rcstack_cli_configure_rhodecode_command ;; "backup-db") rcstack_backup_db_command ;; "backup-data") rcstack_backup_data_command ;; "_completions") rcstack__completions_command ;; esac } initialize run "$@"