mirroring without sausages

(or at least without showing the making of said sausages)
redis
gitolite tester 2012-03-27 22:06:43 +05:30 committed by Sitaram Chamarty
parent b78466b164
commit 25bb1c00db
6 changed files with 1047 additions and 0 deletions

View File

@ -0,0 +1,212 @@
package Gitolite::Triggers::Mirroring;
use Gitolite::Rc;
use Gitolite::Common;
use Gitolite::Conf::Load;
use strict;
use warnings;
my $git_commands = "git-upload-pack|git-receive-pack|git-upload-archive";
my $hn = $rc{HOSTNAME};
# ----------------------------------------------------------------------
sub input {
return unless $ARGV[0] =~ /^server-(\S+)$/;
# note: we treat %rc as our own internal "poor man's %ENV"
$rc{FROM_SERVER} = $1;
trace(3, "from_server: $1");
if ( $ENV{SSH_ORIGINAL_COMMAND} =~ /^USER=(\S+) SOC=(git-receive-pack '(\S+)')$/ ) {
# my ($user, $newsoc, $repo) = ($1, $2, $3);
$ENV{SSH_ORIGINAL_COMMAND} = $2;
@ARGV = ($1);
$rc{REDIRECTED_PUSH} = 1;
trace(3, "redirected_push for user $1");
} else {
# master -> slave push, no access checks needed
$ENV{GL_BYPASS_ACCESS_CHECKS} = 1;
}
}
# ----------------------------------------------------------------------
my ($mode, $master, %slaves, %trusted_slaves);
sub pre_git {
return unless $hn;
# nothing, and I mean NOTHING, happens if HOSTNAME is not set
trace(1, "pre_git() on $hn");
my ($repo, $user, $aa) = @_[1, 2, 3];
my $sender = $rc{FROM_SERVER} || '';
$user = '' if $sender and not exists $rc{REDIRECTED_PUSH};
# ------------------------------------------------------------------
# now you know the repo, get its mirroring details
details($repo);
# we don't deal with any reads. Note that for pre-git this check must
# happen *after* getting details, to give mode() a chance to die on "known
# unknown" repos (repos that are in the config, but mirror settings
# exclude this host from both the master and slave lists)
return if $aa eq 'R';
trace(1, "mirror", "pre_git", $repo, "user=$user", "sender=$sender", "mode=$mode",
($rc{REDIRECTED_PUSH} ? ("redirected") : ()));
# ------------------------------------------------------------------
# case 1: we're master or slave, normal user pushing to us
if ($user and not $rc{REDIRECTED_PUSH}) {
trace(3, "case 1, user push");
return if $mode eq 'local' or $mode eq 'master';
if ($trusted_slaves{$hn}) {
trace(3, "redirecting to $master");
trace(1, "redirect to $master");
exec("ssh", $master, "USER=$user", "SOC=$ENV{SSH_ORIGINAL_COMMAND}");
} else {
_die "$hn: pushing '$repo' to slave '$hn' not allowed";
}
}
# ------------------------------------------------------------------
# case 2: we're slave, master pushing to us
if ($sender and not $rc{REDIRECTED_PUSH}) {
trace(3, "case 2, master push");
_die "$hn: '$repo' is local" if $mode eq 'local';
_die "$hn: '$repo' is native" if $mode eq 'master';
_die "$hn: '$sender' is not the master for '$repo'" if $master ne $sender;
return;
}
# ------------------------------------------------------------------
# case 3: we're master, slave sending a redirected push to us
if ($sender and $rc{REDIRECTED_PUSH}) {
trace(3, "case 2, slave redirect");
_die "$hn: '$repo' is local" if $mode eq 'local';
_die "$hn: '$repo' is not native" if $mode eq 'slave';
_die "$hn: '$sender' is not a valid slave for '$repo'" if not $slaves{$sender};
_die "$hn: redirection not allowed from '$sender'" if not $trusted_slaves{$sender};
return;
}
_die "$hn: should not reach this line";
}
# ----------------------------------------------------------------------
sub post_git {
return unless $hn;
# nothing, and I mean NOTHING, happens if HOSTNAME is not set
trace(1, "post_git() on $hn");
my ($repo, $user, $aa) = @_[1, 2, 3];
# we don't deal with any reads
return if $aa eq 'R';
my $sender = $rc{FROM_SERVER} || '';
$user = '' if $sender;
# ------------------------------------------------------------------
# now you know the repo, get its mirroring details
details($repo);
trace(1, "mirror", "post_git", $repo, "user=$user", "sender=$sender", "mode=$mode",
($rc{REDIRECTED_PUSH} ? ("redirected") : ()));
# ------------------------------------------------------------------
# case 1: we're master or slave, normal user pushing to us
if ($user and not $rc{REDIRECTED_PUSH}) {
trace(3, "case 1, user push");
return if $mode eq 'local';
# slave was eliminated earlier anyway, so that leaves 'master'
# find all slaves and push to each of them
push_to_slaves($repo);
return;
}
# ------------------------------------------------------------------
# case 2: we're slave, master pushing to us
if ($sender and not $rc{REDIRECTED_PUSH}) {
trace(3, "case 2, master push");
# nothing to do
return;
}
# ------------------------------------------------------------------
# case 3: we're master, slave sending a redirected push to us
if ($sender and $rc{REDIRECTED_PUSH}) {
trace(3, "case 2, slave redirect");
# find all slaves and push to each of them
push_to_slaves($repo);
return;
}
}
{
my $lastrepo = '';
sub details {
my $repo = shift;
return if $lastrepo eq $repo;
$master = master($repo);
%slaves = slaves($repo);
$mode = mode($repo);
%trusted_slaves = trusted_slaves($repo);
trace(3, $master, $mode, join(",", sort keys %slaves), join(",", sort keys %trusted_slaves) );
}
sub master {
return option(+shift, 'mirror.master');
}
sub slaves {
my $ref = git_config(+shift, "^gitolite-options\\.mirror\\.slaves.*");
my %out = map { $_ => 1 } map { split } values %$ref;
return %out;
}
sub trusted_slaves {
my $ref = git_config(+shift, "^gitolite-options\\.mirror\\.redirectOK.*");
# the list of trusted slaves (where we accept redirected pushes from)
# is either explicitly given...
my @out = map { split } values %$ref;
my %out = map { $_ => 1 } @out;
# ...or it's all the slaves mentioned if the list is just a "all"
%out = %slaves if (@out == 1 and $out[0] eq 'all');
return %out;
}
sub mode {
my $repo = shift;
return 'local' if not $hn;
return 'master' if $master eq $hn;
return 'slave' if $slaves{$hn};
return 'local' if not $master and not %slaves;
_die "$hn: '$repo' is mirrored but not here";
}
}
sub push_to_slaves {
my $repo = shift;
my $u = $ENV{GL_USER};
delete $ENV{GL_USER}; # why? see src/commands/mirror
for my $s (sort keys %slaves) {
system("gitolite mirror push $s $repo &");
}
$ENV{GL_USER} = $u;
}
1;

69
src/commands/mirror Executable file
View File

@ -0,0 +1,69 @@
#!/usr/bin/perl
use strict;
use warnings;
my $tid;
BEGIN {
$tid = $ENV{GL_TID} || 0;
delete $ENV{GL_TID};
}
use lib $ENV{GL_BINDIR};
use Gitolite::Rc;
use Gitolite::Common;
use Gitolite::Conf::Load;
=for usage
Usage 1: gitolite mirror push <slave> <repo>
Usage 2: ssh git@master-server mirror push <slave> <repo>
Forces a push of one repo to one slave.
Usage 1 is directly on the master server. Nothing is checked; if the slave
accepts it, the push happens, even if the slave is not in any slaves
option. This is how you do delayed or lagged pushes to servers that do not
need real-time updates or have bandwidth/connectivity issues.
Usage 2 can be initiated by *any* user who has *any* gitolite access to the
master server, but it checks that the slave is in one of the slaves options
before doing the push.
=cut
usage() if not @ARGV or $ARGV[0] eq '-h';
_die "HOSTNAME not set" if not $rc{HOSTNAME};
my ($cmd, $host, $repo) = @ARGV;
usage() if not $repo;
if ($cmd eq 'push') {
valid_slave($host, $repo) if exists $ENV{GL_USER};
# will die if host not in slaves for repo
trace(1, "TID=$tid host=$host repo=$repo", "gitolite mirror push started");
_chdir($rc{GL_REPO_BASE});
_chdir("$repo.git");
my $errors = 0;
for (`git push --mirror $host:$repo 2>&1`) {
print STDERR "$_" if -t STDERR or exists $ENV{GL_USER};
chomp;
if (/FATAL/) {
$errors++;
gl_log('mirror', $_);
} else {
trace(1, "mirror: $_");
}
}
exit $errors;
}
sub valid_slave {
my ($host, $repo) = @_;
_die "invalid repo '$repo'" unless $repo =~ $REPONAME_PATT;
my $ref = git_config($repo, "^gitolite-options\\.mirror\\.slaves.*");
my %list = map { $_ => 1 } map { split } values %$ref;
_die "'$host' not a valid slave for '$repo'" unless $list{$host};
}

435
t/mirror-test Executable file
View File

@ -0,0 +1,435 @@
#!/usr/bin/perl
use strict;
use warnings;
# you need 3 disposable userids: sam, frodo, gollum. Then the test user (say
# "g3") needs to be able to sudo into them. Put this in /etc/sudoers:
# g3 ALL = (sam,frodo,gollum) NOPASSWD: ALL
$ENV{TSH_ERREXIT} = 1;
# this is hardcoded; change it if needed
use lib "src";
use Gitolite::Test;
use Cwd;
my $workdir = getcwd();
my $h = $ENV{HOME};
my ($t, $t2); # temp vars
# basic tests
# ----------------------------------------------------------------------
try "plan 152";
## try "DEF POK = !/DENIED/; !/failed to push/";
## confreset;confadd '
## ';
## try "ADMIN_PUSH set1; !/FATAL/" or die text();
# ----------------------------------------------------------------------
# switch keys
sub swk {
my $h = $ENV{HOME};
my $k = shift;
system("cp $h/.ssh/$k $h/.ssh/id_rsa");
system("cp $h/.ssh/$k.pub $h/.ssh/id_rsa.pub");
}
sub all {
try "F " . join(" ", @_);
try "S " . join(" ", @_);
try "G " . join(" ", @_);
}
try "
DEF F = sudo -u frodo -i
DEF S = sudo -u sam -i
DEF G = sudo -u gollum -i
";
my $bd = `gitolite query-rc -n GL_BINDIR`;
try "
$bd/../t/mirror-test-setup.sh; ok or die mirror setup shell script failed
/hello server-frodo, this is frodo/
/hello server-sam, this is frodo/
/hello server-gollum, this is frodo/
/hello server-frodo, this is sam/
/hello server-sam, this is sam/
/hello server-gollum, this is sam/
/hello server-frodo, this is gollum/
/hello server-sam, this is gollum/
/hello server-gollum, this is gollum/
/hello admin, this is frodo/
/Initialized empty .*/gitolite-admin.git/
/Initialized empty .*/r1.git/
/Initialized empty .*/r2.git/
/Initialized empty .*/testing.git/
/Initialized empty .*/gitolite-admin.git/
/Initialized empty .*/r1.git/
/Initialized empty .*/r2.git/
/Initialized empty .*/testing.git/
/Initialized empty .*/gitolite-admin.git/
/Initialized empty .*/r1.git/
/Initialized empty .*/r2.git/
/Initialized empty .*/testing.git/
";
# ----------------------------------------------------------------------
# SECTION 1: gitolite-admin shenanigans
# push to frodo and see sam and gollum change
try "
git clone frodo\@localhost:gitolite-admin fga
ok; /Cloning into 'fga'.../
cd fga; ok
cp $h/.ssh/u?.pub keydir; ok
git add keydir; ok
git commit -m 6keys; ok
git push; ok
/To frodo\@localhost:gitolite-admin/
/master -> master/
git rev-parse HEAD
";
chomp($t = text());
try "
git ls-remote sam\@localhost:gitolite-admin
ok; /$t/
git ls-remote gollum\@localhost:gitolite-admin
ok; /$t/
";
try "
cd ..
";
# push to sam and see frodo and gollum change
try "
git clone sam\@localhost:gitolite-admin sga
ok; /Cloning into 'sga'.../
cd sga; ok
empty; ok
git push; ok
/To sam\@localhost:gitolite-admin/
/master -> master/
git rev-parse HEAD
";
chomp($t = text());
try "
git ls-remote frodo\@localhost:gitolite-admin
ok; /$t/
git ls-remote gollum\@localhost:gitolite-admin
ok; /$t/
";
try "
cd ..
";
# push to gollum and fail at gollum
try "
git clone gollum\@localhost:gitolite-admin gga
ok; /Cloning into 'gga'.../
cd gga; ok
empty; ok
git push; !ok
!/To gollum\@localhost:gitolite-admin/
!/master -> master/
/gollum: pushing 'gitolite-admin' to slave 'gollum' not allowed/
git rev-parse HEAD
";
chomp($t2 = text());
try "
git ls-remote frodo\@localhost:gitolite-admin
ok; /$t/; !/$t2/
git ls-remote sam\@localhost:gitolite-admin
ok; /$t/; !/$t2/
git ls-remote gollum\@localhost:gitolite-admin
ok; /$t/; !/$t2/
";
# fake out the gollum failure to continue the redirected push and fail at frodo
try "
sudo -u gollum -i gitolite git-config -r gitolite-admin .
ok
/redirectOK.*sam/
!/redirectOK.*gollum/
sudo -u gollum -i bash -c 'echo repo gitolite-admin > junk'
sudo -u gollum -i bash -c 'echo option mirror.redirectOK-1 = gollum >> junk'
sudo -u gollum -i bash -c 'cat junk >> .gitolite/conf/gitolite.conf'
sudo -u gollum -i gitolite compile
sudo -u gollum -i gitolite git-config -r gitolite-admin .
ok
/redirectOK.*sam/
/redirectOK.*gollum/
git push; !ok
/frodo: redirection not allowed from 'gollum'/
!/To gollum\@localhost:gitolite-admin/
!/master -> master/
";
# reset gollum via frodo
try "
cd ..
rm -rf fga
git clone frodo\@localhost:gitolite-admin fga
ok; /Cloning into 'fga'.../
cd fga; ok
empty; ok
git push; ok
/To frodo\@localhost:gitolite-admin/
/master -> master/
sudo -u gollum -i gitolite git-config -r gitolite-admin .
ok
/redirectOK.*sam/
!/redirectOK.*gollum/
git rev-parse HEAD
";
chomp($t = text());
try "
git ls-remote sam\@localhost:gitolite-admin
ok; /$t/
git ls-remote gollum\@localhost:gitolite-admin
ok; /$t/
";
# ----------------------------------------------------------------------
# user repo shenanigans
# for a recap of the perms see t/mirror-test-setup.sh
try "
cd ..
pwd
/tmp/tsh_tempdir/ or die not in the right place
" or die;
swk('u1');
# u1 sam r1, R ok, W ok
try "
rm -rf fga sga gga
git clone sam\@localhost:r1 sr1
/Cloning into 'sr1'.../
/warning: You appear to have cloned an empty repository/
cd sr1
empty
git push origin master
/new branch/; /master -> master/
git rev-parse HEAD
";
chomp($t = text());
# u1 sam r1, W mirrors to frodo but not gollum
try "
git ls-remote sam\@localhost:r1
/$t/
git ls-remote frodo\@localhost:r1
/$t/
git ls-remote gollum\@localhost:r1
/gollum: 'r1' is mirrored but not here/
";
swk("u2");
try "
empty
git rev-parse HEAD
";
chomp($t2 = text());
# u2 sam r2 W ok, mirrors to all
try "
git push sam\@localhost:r2 master
/new branch/; /master -> master/
/master -> master/
git ls-remote frodo\@localhost:r2
!/$t/
/$t2/
git ls-remote gollum\@localhost:r2
!/$t/
/$t2/
";
swk("u1");
# u1 gollum r1 -- "known unknown" :-)
# u1 frodo r1 R ok, W not ok
# u1 sam r1 R ok, W ok
try "
cd ..
rm -rf sr1
git clone gollum\@localhost:r1 fr1
/gollum: 'r1' is mirrored but not here/
git clone frodo\@localhost:r1 fr1; ok
cd fr1
empty
git push
/frodo: pushing 'r1' to slave 'frodo' not allowed/
cd ..
git clone sam\@localhost:r1 sr1; ok
cd sr1
empty
git push; ok
/master -> master/
git rev-parse HEAD
";
chomp($t = text());
# u1 sam r1 W mirrored to frodo but not gollum
try "
git ls-remote sam\@localhost:r1
/$t/
git ls-remote frodo\@localhost:r1
/$t/
git ls-remote gollum\@localhost:r1
/gollum: 'r1' is mirrored but not here/
git reset --hard HEAD^; ok
tc a
git push; !ok
/rejected/
/failed to push/
git push -f
/\\+ .......\\.\\.\\........ master -> master .forced update/
";
swk("u2");
# u2 frodo r1 R ok, W not allowed (no redirectOK)
# u2 frodo r2 W ok
try "
cd ..
rm -rf fr1 sr1
git clone frodo\@localhost:r1 fr1; ok
cd fr1
tc b
git push
/frodo: pushing 'r1' to slave 'frodo' not allowed/
cd ..
git clone frodo\@localhost:r2 fr2; ok
cd fr2
tc c
git push
/master -> master/
git rev-parse HEAD
";
chomp($t = text());
# u2 frodo r2 W mirrors to sam and gollum
try "
git ls-remote sam\@localhost:r2
/$t/
git ls-remote gollum\@localhost:r2
/$t/
git reset --hard HEAD^; ok
tc d
git push
/rejected/
/failed to push/
git push -f
/\\+ .......\\.\\.\\........ master -> master .forced update/
cd ..
rm -rf fr1 fr2
";
swk("u3");
# u3 frodo r2 R ok W ok
try "
git clone frodo\@localhost:r2 fr2; ok
cd fr2
tc e
git push; ok
git rev-parse HEAD
";
chomp($t = text());
# u3 frodo r2 W mirrors to sam and gollum
try "
git ls-remote sam\@localhost:r2
/$t/
git ls-remote gollum\@localhost:r2
/$t/
git reset --hard HEAD^; ok
tc f
git push
/rejected/
/failed to push/
sleep 10
git push -f
/\\+ refs/heads/master r2 u3 DENIED by fallthru/
/hook declined/
/rejected/
";
# ----------------------------------------------------------------------
# all those vague edge cases where the two servers have totally wrong ideas
# about each other
swk('u1');
try "sudo -u frodo -i ls .gitolite/logs";
chomp($t = text());
my $lfn = ".gitolite/logs/$t";
try "
ssh sam\@localhost mirror push frodo lfrodo; !ok
/FATAL: frodo: 'lfrodo' is local/
ssh sam\@localhost mirror push frodo mboth; !ok
/FATAL: frodo: 'mboth' is native/
ssh sam\@localhost mirror push frodo mnotsam; !ok
/FATAL: frodo: 'sam' is not the master for 'mnotsam'/
cd ..
git clone sam\@localhost:lfrodo2 lfrodo2; ok
cd lfrodo2
empty
git push origin master; !ok
/FATAL: frodo: 'lfrodo2' is local/
cd ..
git clone sam\@localhost:nnfrodo nnfrodo; ok
cd nnfrodo
empty
git push origin master; !ok
/FATAL: frodo: 'nnfrodo' is not native/
cd ..
git clone sam\@localhost:nvsfrodo nvsfrodo; ok
cd nvsfrodo
empty
git push origin master; !ok
/FATAL: frodo: 'sam' is not a valid slave for 'nvsfrodo'/
";

127
t/mirror-test-rc Normal file
View File

@ -0,0 +1,127 @@
# configuration variables for gitolite
# This file is in perl syntax. But you do NOT need to know perl to edit it --
# just mind the commas, use single quotes unless you know what you're doing,
# and make sure the brackets and braces stay matched up!
# (Tip: perl allows a comma after the last item in a list also!)
%RC = (
HOSTNAME => '%HOSTNAME',
UMASK => 0077,
GIT_CONFIG_KEYS => '',
# comment out if you don't need all the extra detail in the logfile
LOG_EXTRA => 1,
# settings used by external programs; uncomment and change as needed. You
# can add your own variables for use in your own external programs; take a
# look at the cpu-time and desc commands for perl and shell samples.
# used by the cpu-time command
# DISPLAY_CPU_TIME => 1,
# CPU_TIME_WARN_LIMIT => 0.1,
# used by the desc command
# WRITER_CAN_UPDATE_DESC => 1,
# used by the info command
# SITE_INFO => 'Please see http://blahblah/gitolite for more help',
# add more roles (like MANAGER, TESTER, ...) here.
# WARNING: if you make changes to this hash, you MUST run 'gitolite
# compile' afterward, and possibly also 'gitolite trigger POST_COMPILE'
ROLES =>
{
READERS => 1,
WRITERS => 1,
},
# uncomment (and change) this if you wish
# DEFAULT_ROLE_PERMS => 'READERS @all',
# comment out or uncomment as needed
# these are available to remote users
COMMANDS =>
{
'help' => 1,
'info' => 1,
'desc' => 1,
'perms' => 1,
'mirror' => 1,
'writable' => 1,
},
# comment out or uncomment as needed
# these will run in sequence during the conf file parse
SYNTACTIC_SUGAR =>
[
# 'continuation-lines',
],
# comment out or uncomment as needed
# these will run in sequence to modify the input (arguments and environment)
INPUT =>
[
'Mirroring::input',
],
# comment out or uncomment as needed
# these will run in sequence just after the first access check is done
ACCESS_1 =>
[
],
# comment out or uncomment as needed
# these will run in sequence at the start, before a git operation has started
PRE_GIT =>
[
# if you use this, make this the first item in the list
# 'renice 10',
'Mirroring::pre_git',
# see docs ("list of non-core programs shipped") for details
# 'partial-copy',
],
# comment out or uncomment as needed
# these will run in sequence just after the second access check is done
ACCESS_2 =>
[
],
# comment out or uncomment as needed
# these will run in sequence at the end, after a git operation has ended
POST_GIT =>
[
# if you use this, make this the last item in the list
# 'cpu-time',
'Mirroring::post_git',
],
# comment out or uncomment as needed
# these will run in sequence after a new wild repo is created
POST_CREATE =>
[
'post-compile/update-git-configs',
'post-compile/update-gitweb-access-list',
'post-compile/update-git-daemon-access-list',
],
# comment out or uncomment as needed
# these will run in sequence after post-update
POST_COMPILE =>
[
'post-compile/ssh-authkeys',
'post-compile/update-git-configs',
'post-compile/update-gitweb-access-list',
'post-compile/update-git-daemon-access-list',
],
);
# ------------------------------------------------------------------------------
# per perl rules, this should be the last line in such a file:
1;
# Local variables:
# mode: perl
# End:
# vim: set syn=perl:

193
t/mirror-test-setup.sh Executable file
View File

@ -0,0 +1,193 @@
#!/bin/bash
set -e
hosts="frodo sam gollum"
mainhost=frodo
# setup software
bd=`gitolite query-rc -n GL_BINDIR`
rm -rf /tmp/g3/src
cp -a $bd /tmp/g3/src
chmod -R go+rX /tmp/g3
# setup symlinks in frodo, sam, and gollum's accounts
for h in $hosts
do
sudo -u $h -i bash -c "rm -rf *.pub bin .ssh projects.list repositories .gitolite .gitolite.rc"
done
[ "$1" = "clear" ] && exit
cd /tmp/g3
[ -d keys ] || {
mkdir keys
cd keys
for h in $hosts
do
ssh-keygen -N '' -q -f server-$h -C $h
chmod go+r /tmp/g3/keys/server-$h
done
cp $bd/../t/mirror-test-ssh-config ssh-config
}
for h in $hosts
do
sudo -u $h -i bash -c "mkdir -p bin; ln -sf /tmp/g3/src/gitolite bin; mkdir -p .ssh; chmod 0700 .ssh"
sudo -u $h -i cp /tmp/g3/keys/ssh-config .ssh/config
sudo -u $h -i cp /tmp/g3/keys/server-$h .ssh/id_rsa
sudo -u $h -i cp /tmp/g3/keys/server-$h.pub .ssh/id_rsa.pub
sudo -u $h -i chmod go-rwx .ssh/id_rsa .ssh/config
done
# add all pubkeys to all servers
for h in $hosts
do
sudo -u $h -i gitolite setup -a admin
for j in $hosts
do
sudo -u $h -i gitolite setup -pk /tmp/g3/keys/server-$j.pub
echo sudo _u $j _i ssh $h@localhost info
sudo -u $j -i ssh -o StrictHostKeyChecking=no $h@localhost info
done
echo ----
done
# now copy our admin key to the main host
cd;cd .ssh
cp admin id_rsa; cp admin.pub id_rsa.pub
cp admin.pub /tmp/g3/keys; chmod go+r /tmp/g3/keys/admin.pub
sudo -u $mainhost -i gitolite setup -pk /tmp/g3/keys/admin.pub
ssh $mainhost@localhost info
lines="
repo gitolite-admin
option mirror.master = frodo
option mirror.slaves-1 = sam gollum
option mirror.redirectOK = sam
repo r1
RW+ = u1
RW = u2
R = u3
option mirror.master = sam
option mirror.slaves-1 = frodo
repo r2
RW+ = u2
RW = u3
R = u4
option mirror.master = sam
option mirror.slaves-1 = frodo gollum
option mirror.redirectOK = all
include \"%HOSTNAME.conf\"
"
lines2="
repo l-%HOSTNAME
RW = u1
"
# for each server, set the HOSTNAME to the rc, add the mirror options to the
# conf file, and compile
for h in $hosts
do
cat $bd/../t/mirror-test-rc | perl -pe "s/%HOSTNAME/$h/" > /tmp/g3/temp
sudo -u $h -i cp /tmp/g3/temp .gitolite.rc
echo "$lines" | sudo -u $h -i sh -c 'cat >> .gitolite/conf/gitolite.conf'
echo "$lines2" | sudo -u $h -i sh -c "cat >> .gitolite/conf/$h.conf"
sudo -u $h -i gitolite setup
done
# goes on frodo
lines="
# local to frodo but sam thinks frodo is a slave
repo lfrodo
RW = u1
# both think they're master
repo mboth
RW = u1
option mirror.master = frodo
option mirror.slaves = sam
# frodo thinks someone else is the master but sam thinks he is
repo mnotsam
RW = u1
option mirror.master = merry
option mirror.slaves = frodo
# local to frodo but sam thinks frodo is a master and redirect is OK
repo lfrodo2
RW = u1
# non-native to frodo but sam thinks frodo is master
repo nnfrodo
RW = u1
option mirror.master = gollum
option mirror.slaves = frodo
option mirror.redirectOK = all
# sam is not a valid slave to send stuff to frodo
repo nvsfrodo
RW = u1
option mirror.master = frodo
option mirror.slaves = gollum
option mirror.redirectOK = all
"
echo "$lines" | sudo -u frodo -i sh -c "cat >> .gitolite/conf/frodo.conf"
# goes on sam
lines="
# local to frodo but sam thinks frodo is a slave
repo lfrodo
RW = u1
option mirror.master = sam
option mirror.slaves = frodo
# both think they're master
repo mboth
RW = u1
option mirror.master = sam
option mirror.slaves = frodo
# frodo thinks someone else is the master but sam thinks he is
repo mnotsam
RW = u1
option mirror.master = sam
option mirror.slaves = frodo
# local to frodo but sam thinks frodo is a master and redirect is OK
repo lfrodo2
RW = u1
option mirror.master = frodo
option mirror.slaves = sam
option mirror.redirectOK = all
# non-native to frodo but sam thinks frodo is master
repo nnfrodo
RW = u1
option mirror.master = frodo
option mirror.slaves = sam
option mirror.redirectOK = all
# sam is not a valid slave to send stuff to frodo
repo nvsfrodo
RW = u1
option mirror.master = frodo
option mirror.slaves = sam
option mirror.redirectOK = all
"
echo "$lines" | sudo -u sam -i sh -c "cat >> .gitolite/conf/sam.conf"
for h in $hosts
do
sudo -u $h -i gitolite setup
done
# that ends the setup phase
echo ======================================================================

11
t/mirror-test-ssh-config Normal file
View File

@ -0,0 +1,11 @@
host frodo
user frodo
hostname localhost
host sam
user sam
hostname localhost
host gollum
user gollum
hostname localhost