| #!/bin/bash |
| # |
| # scheme.sh - gerrit |
| # |
| # Copyright 2019 Luigi Santivetti <luigi.santivetti@gmail.com> |
| |
| # Permission is hereby granted, free of charge, to any person obtaining a |
| # copy of this software and associated documentation files (the "Software"), |
| # to deal in the Software without restriction, including without limitation |
| # the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| # and/or sell copies of the Software, and to permit persons to whom the |
| # Software is furnished to do so, subject to the following conditions: |
| |
| # The above copyright notice and this permission notice (including the next |
| # paragraph) shall be included in all copies or substantial portions of the |
| # Software. |
| |
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| # ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
| # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| |
| declare -r entrypoint_bang_t="\ |
| #!/bin/bash -e |
| |
| if [ \"\${1}\" = \"init\" ]; then |
| echo \"Initializing Gerrit site ...\" |
| |
| # NOTE: This is the real in-container init that actually matters |
| # for properly start using Gerrit Code Review. |
| |
| java -jar /var/gerrit/bin/gerrit.war init --batch \\ |
| --no-auto-start --install-all-plugins -d /var/gerrit |
| java -jar /var/gerrit/bin/gerrit.war reindex -d /var/gerrit |
| git config -f /var/gerrit/etc/gerrit.config \\ |
| --add container.javaOptions \"${_GERRIT_JAVA_URANDOM_}\" |
| fi |
| |
| git config -f /var/gerrit/etc/gerrit.config \\ |
| gerrit.canonicalWebUrl \"\${CANONICAL_WEB_URL:-http://\$HOSTNAME}\" |
| git config -f /var/gerrit/etc/gerrit.config \\ |
| httpd.listenUrl \"\${LISTEN_URL:-proxy-http://\$HOSTNAME}\" |
| |
| sleep 1 |
| |
| if [ \"\${1}\" != \"init\" ]; then |
| echo \"Running Gerrit ...\" |
| /var/gerrit/bin/gerrit.sh run |
| fi" |
| |
| if [ "$gerrit_has_https" -eq 1 ]; then |
| declare -r config_t_has_secure_store="\ |
| secureStoreClass = ${_GERRIT_SECURE_STORE_}" |
| declare -r config_t_has_keystore="\ |
| sslKeyStore = ${_GERRIT_KEYSTORE_}" |
| declare -r config_t_has_secure_config="\ |
| [secureConfig] |
| cipher = ${_GERRIT_SECURE_CIPHER_} |
| passwordLength = 256" |
| else |
| declare -r config_t_has_secure_store="" |
| declare -r config_t_has_keystore="" |
| declare -r config_t_has_secure_config="" |
| fi |
| |
| declare -r config_t="\ |
| [gerrit] |
| basePath = git |
| canonicalWebUrl = ${_GERRIT_CANON_URL_} |
| ${config_t_has_secure_store} |
| |
| [index] |
| type = LUCENE |
| |
| [auth] |
| type = http |
| gitBasicAuth = true |
| gitBasicAuthPolicy = HTTP |
| |
| [sendemail] |
| smtpServer = localhost |
| |
| [sshd] |
| listenAddress = *:${_GERRIT_SSH_PORT_} |
| |
| [httpd] |
| listenUrl = ${_GERRIT_LISTEN_URL_} |
| ${config_t_has_keystore} |
| |
| [cache] |
| directory = cache |
| |
| [container] |
| user = ${_GERRIT_USER_CON_} |
| |
| [receive] |
| enableSignedPush = false |
| |
| ${config_t_has_secure_config}" |
| |
| # secure.config isn't part of the instance create/update process, however |
| # it must be defined in mod_more_files in the first place. |
| declare -r secure_t="$(cat $secure_f 2>/dev/null | grep -E -- "^[^#]" 2>/dev/null)" |
| |
| declare -r dockerfile_t="\ |
| FROM ubuntu:16.04 |
| MAINTAINER Gerrit Code Review Community |
| |
| # Add Gerrit packages repository |
| RUN echo \"deb mirror://mirrorlist.gerritforge.com/bionic gerrit contrib\" \\ |
| > /etc/apt/sources.list.d/GerritForge.list |
| RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 847005AE619067D5 |
| |
| RUN apt-get update |
| RUN apt-key update |
| RUN apt-get -y install sudo |
| |
| # Needed by Gerrit 3.0 ?! |
| RUN apt-get -y install gnupg2 |
| |
| ${_GERRIT_APT_GET_INSTALL_NMAP_} |
| ${_GERRIT_APT_GET_INSTALL_PING_} |
| |
| # Install OpenJDK and Gerrit in two subsequent transactions |
| # (pre-trans Gerrit script needs to have access to the Java command) |
| RUN apt-get -y install openjdk-8-jdk |
| |
| # Add entrypoint |
| ADD entrypoint.sh / |
| RUN chmod +x /entrypoint.sh |
| |
| # Init Gerrit |
| RUN apt-get -y install gerrit=${_GERRIT_APT_GET_PACKAGE_} && \\ |
| /entrypoint.sh init && \\ |
| rm -f /var/gerrit/etc/{ssh,secure}* && \\ |
| rm -Rf /var/gerrit/{static,index,logs,data,index,cache,git,db,tmp}/* && \\ |
| chown -R gerrit:gerrit /var/gerrit |
| |
| # Debian 9 fails with 'USER gerrit' |
| USER ${_GERRIT_USER_CON_} |
| |
| # Define environment |
| ENV CANONICAL_WEB_URL= |
| ENV LISTEN_URL= |
| |
| # Allow incoming traffic |
| EXPOSE ${_GERRIT_PROXY_PORT_} ${_GERRIT_SSH_PORT_} |
| |
| VOLUME [\"/var/gerrit/git\", \"/var/gerrit/index\", \\ |
| \"/var/gerrit/cache\", \"/var/gerrit/db\", \"/var/gerrit/etc\"] |
| |
| # Start Gerrit |
| ENTRYPOINT /entrypoint.sh" |
| |
| declare -r gerrit_cli_bang_t="\ |
| #!/bin/bash |
| |
| if (return 0 2>/dev/null); then |
| echo \"You must run this script\" >&2 |
| return 1 |
| fi |
| |
| function __help |
| { |
| if [ -n \"\$1\" ]; then |
| echo \"error: unknown option: \$1\" >&2 |
| echo \"------------------------\">&2 |
| fi |
| |
| cat <<EOF; exit 0 |
| `printf \"\\033[1m%s\\033[0m\\n\" \"NAME\"` |
| |
| \${BASH_SOURCE[0]} - Gerrit bash CLI for ${host_name} |
| |
| `printf \"\\033[1m%s\\033[0m\\n\" \"USAGE\"` |
| |
| \$ [ ENVIRONMENT ... ] \${BASH_SOURCE[0]} [ OPTION ARG ] ARGS |
| |
| `printf \"\\033[1m%s\\033[0m\\n\" \"ENVIRONMENT\"` |
| |
| SSH_PORT ssh port Gerrit listens on, default: ${_GERRIT_SSH_PORT_} |
| SSH_USER registered Gerrit user, default: NULL |
| SSH_HOST host where Gerrit runs, default: ${host_name} |
| |
| User, port and host passed on the command line take precedence over |
| those defined in the environment |
| |
| `printf \"\\033[1m%s\\033[0m\\n\" \"OPTION\"` |
| |
| -p ssh port |
| -h ssh host |
| -u ssh user |
| -a action to perform |
| |
| Available actions: |
| |
| import <src path> <dst path> |
| import in Gerrit all bare repositories found in src, if it |
| doesn't exist yet and if it's a valid src |
| dry-import <src path> <dst path> |
| create an empty project in Gerrit for each bare repository |
| found in src, if doesn't exist yet and if it's a valid src |
| list <flags> |
| list Gerrit projects with additional flags |
| listall - |
| list all Gerrit projects |
| flushall - |
| flush all Gerrit project caches |
| delete <project name> |
| delete named project and related data from Gerrit |
| create <flags> <project name> |
| create named project with additional flags |
| create-permission <project name> |
| create permission project, for access control only |
| cli <$@> |
| any valid list of arguments |
| |
| `printf \"\\033[1m%s\\033[0m\\n\" \"EXAMPLES\"` |
| |
| \$ \${BASH_SOURCE[0]} -u linus -a import \"old_site_path\" \"new_site_path\" |
| \$ SSH_PORT=1234 SSH_USER=linus \${BASH_SOURCE[0]} -a listall |
| |
| \$ export SSH_USER=linus |
| \$ \${BASH_SOURCE[0]} -a create \"wheel\" |
| |
| `printf \"\\033[1m%s\\033[0m\\n\" \"END\"` |
| EOF |
| } |
| |
| function set_environment |
| { |
| local SSH_PORT=\${1:-\$SSH_PORT} |
| declare -gr SSH_PORT=\${SSH_PORT:-$_GERRIT_SSH_PORT_} |
| |
| local SSH_USER=\${2:-\$SSH_USER} |
| declare -gr SSH_USER=\${SSH_USER:-} |
| |
| local SSH_HOST=\${3:-\$SSH_HOST} |
| declare -gr SSH_HOST=\${SSH_HOST:-$host_name} |
| } |
| |
| function gerrit_ssh |
| { |
| ssh -p \$SSH_PORT \$SSH_USER@\$SSH_HOST \${@} |
| } |
| |
| function gerrit_cli |
| { |
| gerrit_ssh \"gerrit \${@}\" |
| } |
| |
| function gerrit_create_project |
| { |
| gerrit_cli create-project \${@} |
| } |
| |
| function gerrit_list_projects |
| { |
| gerrit_cli ls-projects \${@} |
| } |
| |
| function gerrit_delete_project |
| { |
| local -r flags=\"--yes-really-delete\" |
| |
| echo >&2 \"warning: to force deletion run:\" |
| echo >&2 \" ssh -p \$SSH_PORT \$SSH_USER@\$SSH_HOST delete-project delete \$flags --force \$1\" |
| gerrit_ssh delete-project delete \$flags \${@} |
| } |
| |
| function gerrit_flush_all_caches |
| { |
| local -r flags=\"flush-caches --all\" |
| |
| gerrit_cli \$flags |
| } |
| |
| function glp_all_projects |
| { |
| local -r flags=\"--all --type all\" |
| |
| gerrit_list_projects \$flags |
| } |
| |
| function gcp_permission_only |
| { |
| local -r flags=\"--permissions-only --empty-commit\" |
| local -r project_name=\"\$1\" |
| |
| gerrit_create_project \$flags \$project_name |
| } |
| |
| function gcp_import_is_valid_src_repo |
| { |
| local -r git_path=\"\$1\" |
| |
| if ! (echo \"\${git_path}\" | grep -qE -- \".+\\.git\$\"); then |
| echo \"error: \$(basename \"\$git_path\"): invalid name\" >&2 |
| return 1 |
| fi |
| |
| if ! (GIT_DIR=\$git_path git rev-parse --is-bare-repository &>/dev/null); then |
| echo \"error: \$(basename \"\$git_path\"): not bare\" >&2 |
| return 1 |
| fi |
| } |
| |
| function gcp_import_project |
| { |
| local -r repo_name=\"\${1%.git}\" |
| local -r repo=\"\$1\" |
| local -r src=\"\$2\" |
| local -r dst=\"\$3\" |
| local -r dry=\"\$4\" |
| |
| # List of projects to explicitly skip |
| local -ar skiplist=( |
| All-Projects |
| All-Users |
| ) |
| |
| if printf \"%s\n\" \"\${skiplist[@]}\" | grep -qFx -- \"\$repo_name\"; then |
| echo \"warning: \$repo_name: flagged out\" >&2 |
| return 1 |
| fi |
| |
| if ! gerrit_create_project \$repo_name; then |
| echo \"error: \$repo_name: create failed\" >&2 |
| return 1 |
| fi |
| |
| if [ ! -d \"\$src/\$repo\" ]; then |
| echo \"error: \$repo: repo source not found\" >&2 |
| return 1 |
| fi |
| |
| if [ ! -d \"\$dst/\$repo\" ]; then |
| echo \"error: \$repo: destination not found\" >&2 |
| return 1 |
| fi |
| |
| if [ \"\$dry\" != \"true\" ]; then |
| if ! sudo -E cp -ar \$src/\$repo/* \$dst/\$repo; then |
| echo \"error: \$repo: copy failed\" >&2 |
| return 1 |
| fi |
| |
| if ! gerrit_flush_all_caches; then |
| echo \"warning: \$project_name: flush cache\" >&2 |
| fi |
| fi |
| } |
| |
| function gcp_import_repo_list |
| { |
| # Do this once and avoid multiple ssh access |
| local -ar exist_proj_list=( \$(glp_all_projects) ) |
| local -a valid_repo_list |
| # Arguments order matters |
| local -r dry=\"\$1\"; shift |
| local -r src=\"\$1\"; shift |
| local -r dst=\"\$1\"; shift |
| local proj repo ret act |
| |
| for repo in \${@}; do |
| if printf \"%s\n\" \"\${exist_proj_list[@]}\" | \\ |
| grep -qFx -- \"\${repo%.git}\"; then |
| echo \"warning: \${repo%.git}: already exists\" >&2 |
| continue |
| fi |
| gcp_import_is_valid_src_repo \"\$src/\$repo\" || continue |
| valid_repo_list+=( \"\$repo\" ) |
| done |
| |
| if [ \"\${#valid_repo_list[@]}\" -gt 0 ]; then |
| [ \"\$dry\" = \"true\" ] && act=\"dry-copy\" || act=\"copy\" |
| echo \"info: attempt to \$act\" >&2 |
| echo >&2 |
| echo \" * from \$src\" >&2 |
| echo \" * to \$dst\" >&2 |
| echo >&2 |
| cat -n <(printf \"%s\\\n\" \"\${valid_repo_list[@]}\") >&2 |
| echo >&2 |
| echo \"info: press any key to continue, [CTRL^C] to cancel\" |
| echo >&2 |
| read -s -n 1 |
| |
| for repo in \${valid_repo_list[@]}; do |
| gcp_import_project \$repo \$src \$dst \$dry && ret=\"done\" || ret=\"skip\" |
| printf \"%s: %s\n\" \"\$ret\" \"\$repo\" >&2 |
| done |
| else |
| echo \"warning: nothing to do\" >&2 |
| fi |
| } |
| |
| # @1 : path to find bare git repositories from |
| # @2 : path copy repositories into |
| # @desc : import any bare repository found in \$1 into \$2 |
| function gcp_import_copy_from_into |
| { |
| local -r regex=\".+/.+[^/]\\.git\$\" |
| local -r src=\"\$(realpath -q \"\$1\")\" |
| local -r dst=\"\$(realpath -q \"\$2\")\" |
| local -r dry=\"\$3\" |
| local flags |
| |
| # Flag order matters |
| flags=\"-type d\" |
| flags+=\" -regex \$regex\" |
| |
| local -ar list=\$(find \"\$src\" \$flags 2>/dev/null) |
| |
| gcp_import_repo_list \$dry \$src \$dst \${list[@]//\$src\\//} |
| } |
| |
| function __do_import |
| { |
| if [ -z \"\$1\" ] || [ ! -d \"\$1\" ]; then |
| echo \"error: invalid source path\" >&2 |
| exit 1 |
| fi |
| |
| if [ -z \"\$2\" ] || [ ! -d \"\$2\" ]; then |
| echo \"error: invalid target path\" >&2 |
| exit 1 |
| fi |
| |
| gcp_import_copy_from_into \$1 \$2 \"false\" |
| } |
| |
| function __do_dry_import |
| { |
| if [ -z \"\$1\" ] || [ ! -d \"\$1\" ]; then |
| echo \"error: invalid source path\" >&2 |
| exit 1 |
| fi |
| |
| if [ -z \"\$2\" ] || [ ! -d \"\$2\" ]; then |
| echo \"error: invalid target path\" >&2 |
| exit 1 |
| fi |
| |
| gcp_import_copy_from_into \$1 \$2 \"true\" |
| } |
| |
| function __do_cli |
| { |
| gerrit_cli \${@} |
| } |
| |
| function __do_flushall |
| { |
| gerrit_flush_all_caches |
| } |
| |
| function __do_list |
| { |
| gerrit_list_projects \$@ |
| } |
| |
| function __do_listall |
| { |
| glp_all_projects |
| } |
| |
| function __do_delete |
| { |
| gerrit_delete_project \$@ |
| } |
| |
| function __do_create |
| { |
| gerrit_create_project \$@ |
| } |
| |
| function __do_cpermi |
| { |
| gcp_permission_only \$@ |
| } |
| |
| function __do_unknown |
| { |
| if [ \"\$1\" != help ]; then |
| echo \"error: unknown action: \$1\" >&2 |
| echo >&2 |
| fi |
| __help |
| } |
| |
| while getopts \":hp:s:u:a:\" OPTION; do |
| case \"\$OPTION\" in |
| p ) declare -rg port=\"\$OPTARG\" ;; |
| s ) declare -rg host=\"\$OPTARG\" ;; |
| u ) declare -rg user=\"\$OPTARG\" ;; |
| a ) declare -rg __do=\"\$OPTARG\" ;; |
| \\? ) __help \$OPTARG ;; |
| esac |
| done |
| |
| if ! set_environment \"\$port\" \"\$user\" \"\$host\"; then |
| echo \"error: user must be set, try ? or -a help\" |
| exit 1 |
| fi |
| |
| shift \$((OPTIND - 1)) |
| |
| case \"\$__do\" in |
| import ) __do_import \$@ ;; |
| dry-import ) __do_dry_import \$@ ;; |
| list ) __do_list \$@ ;; |
| listall ) __do_listall ;; |
| flushall ) __do_flushall ;; |
| delete ) __do_delete \$@ ;; |
| create ) __do_create \$@ ;; |
| create-permission ) __do_cpermi \$@ ;; |
| cli ) __do_cli \$@ ;; |
| * ) __do_unknown \$__do ;; |
| esac" |