blob: 3a066ce86713da8135149838f2215ad3577d21e1 [file] [log] [blame]
#!/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"