Add cli option sync-on-signal to trigger git-sync with a signal. (#664)
Operation: git-sync --repo https://github.com/kubernetes/kubernetes --sync-on-signal SIGHUP git-sync --repo https://github.com/kubernetes/kubernetes --sync-on-signal HUP git-sync --repo https://github.com/kubernetes/kubernetes --sync-on-signal 1 Signals can be sent to docker containers with cmd: docker kill -signal SIGHUP <Container ID>
This commit is contained in:
parent
f7ff396716
commit
2b3f1bcdd7
|
|
@ -35,11 +35,13 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
"k8s.io/git-sync/pkg/cmd"
|
"k8s.io/git-sync/pkg/cmd"
|
||||||
"k8s.io/git-sync/pkg/hook"
|
"k8s.io/git-sync/pkg/hook"
|
||||||
"k8s.io/git-sync/pkg/logging"
|
"k8s.io/git-sync/pkg/logging"
|
||||||
|
|
@ -77,6 +79,8 @@ var flSyncTimeout = pflag.Duration("sync-timeout", envDuration("GIT_SYNC_SYNC_TI
|
||||||
"the total time allowed for one complete sync, must be >= 10ms; --timeout overrides this")
|
"the total time allowed for one complete sync, must be >= 10ms; --timeout overrides this")
|
||||||
var flOneTime = pflag.Bool("one-time", envBool("GIT_SYNC_ONE_TIME", false),
|
var flOneTime = pflag.Bool("one-time", envBool("GIT_SYNC_ONE_TIME", false),
|
||||||
"exit after the first sync")
|
"exit after the first sync")
|
||||||
|
var flSyncOnSignal = pflag.String("sync-on-signal", envString("GIT_SYNC_SYNC_ON_SIGNAL", ""),
|
||||||
|
"sync on receipt of the specified signal (e.g. SIGHUP)")
|
||||||
var flMaxFailures = pflag.Int("max-failures", envInt("GIT_SYNC_MAX_FAILURES", 0),
|
var flMaxFailures = pflag.Int("max-failures", envInt("GIT_SYNC_MAX_FAILURES", 0),
|
||||||
"the number of consecutive failures allowed before aborting (the first sync must succeed, -1 will retry forever")
|
"the number of consecutive failures allowed before aborting (the first sync must succeed, -1 will retry forever")
|
||||||
var flChmod = pflag.Int("change-permissions", envInt("GIT_SYNC_PERMISSIONS", 0),
|
var flChmod = pflag.Int("change-permissions", envInt("GIT_SYNC_PERMISSIONS", 0),
|
||||||
|
|
@ -397,6 +401,24 @@ func main() {
|
||||||
handleConfigError(log, true, "ERROR: --period must be at least 10ms")
|
handleConfigError(log, true, "ERROR: --period must be at least 10ms")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var syncSig syscall.Signal
|
||||||
|
if *flSyncOnSignal != "" {
|
||||||
|
if num, err := strconv.ParseInt(*flSyncOnSignal, 0, 0); err == nil {
|
||||||
|
// sync-on-signal value is a number
|
||||||
|
syncSig = syscall.Signal(num)
|
||||||
|
} else {
|
||||||
|
// sync-on-signal value is a name
|
||||||
|
syncSig = unix.SignalNum(*flSyncOnSignal)
|
||||||
|
if syncSig == 0 {
|
||||||
|
// last resort - maybe they said "HUP", meaning "SIGHUP"
|
||||||
|
syncSig = unix.SignalNum("SIG" + *flSyncOnSignal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if syncSig == 0 {
|
||||||
|
handleConfigError(log, true, "ERROR: --sync-on-signal must be a valid signal name or number")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if *flTimeout != 0 {
|
if *flTimeout != 0 {
|
||||||
// Back-compat
|
// Back-compat
|
||||||
*flSyncTimeout = time.Duration(*flTimeout) * time.Second
|
*flSyncTimeout = time.Duration(*flTimeout) * time.Second
|
||||||
|
|
@ -670,6 +692,13 @@ func main() {
|
||||||
go exechookRunner.Run(context.Background())
|
go exechookRunner.Run(context.Background())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup signal notify channel
|
||||||
|
sigChan := make(chan os.Signal, 1)
|
||||||
|
if syncSig != 0 {
|
||||||
|
log.V(2).Info("installing signal handler", "signal", unix.SignalName(syncSig))
|
||||||
|
signal.Notify(sigChan, syncSig)
|
||||||
|
}
|
||||||
|
|
||||||
// Craft a function that can be called to refresh credentials when needed.
|
// Craft a function that can be called to refresh credentials when needed.
|
||||||
refreshCreds := func(ctx context.Context) error {
|
refreshCreds := func(ctx context.Context) error {
|
||||||
// These should all be mutually-exclusive configs.
|
// These should all be mutually-exclusive configs.
|
||||||
|
|
@ -772,7 +801,16 @@ func main() {
|
||||||
|
|
||||||
log.V(1).Info("next sync", "waitTime", flPeriod.String())
|
log.V(1).Info("next sync", "waitTime", flPeriod.String())
|
||||||
cancel()
|
cancel()
|
||||||
time.Sleep(*flPeriod)
|
|
||||||
|
// Sleep until the next sync. If syncSig is set then the sleep may
|
||||||
|
// be interrupted by that signal.
|
||||||
|
t := time.NewTimer(*flPeriod)
|
||||||
|
select {
|
||||||
|
case <-t.C:
|
||||||
|
case <-sigChan:
|
||||||
|
log.V(2).Info("caught signal", "signal", unix.SignalName(syncSig))
|
||||||
|
t.Stop()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2139,6 +2177,13 @@ OPTIONS
|
||||||
The git submodule behavior: one of "recursive", "shallow", or
|
The git submodule behavior: one of "recursive", "shallow", or
|
||||||
"off". If not specified, this defaults to "recursive".
|
"off". If not specified, this defaults to "recursive".
|
||||||
|
|
||||||
|
--sync-on-signal <string>, $GIT_SYNC_SYNC_ON_SIGNAL
|
||||||
|
Indicates that a sync attempt should occur upon receipt of the
|
||||||
|
specified signal name (e.g. SIGHUP) or number (e.g. 1). If a sync
|
||||||
|
is already in progress, another sync will be triggered as soon as
|
||||||
|
the current one completes. If not specified, signals will not
|
||||||
|
trigger syncs.
|
||||||
|
|
||||||
--sync-timeout <duration>, $GIT_SYNC_SYNC_TIMEOUT
|
--sync-timeout <duration>, $GIT_SYNC_SYNC_TIMEOUT
|
||||||
The total time allowed for one complete sync. This must be at least
|
The total time allowed for one complete sync. This must be at least
|
||||||
10ms. This flag obsoletes --timeout, but if --timeout is specified,
|
10ms. This flag obsoletes --timeout, but if --timeout is specified,
|
||||||
|
|
|
||||||
110
test_e2e.sh
110
test_e2e.sh
|
|
@ -126,6 +126,14 @@ function docker_kill() {
|
||||||
docker kill "$1" >/dev/null
|
docker kill "$1" >/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function docker_signal() {
|
||||||
|
if [[ -z "$1" || -z "$2" ]]; then
|
||||||
|
echo "usage: $0 <id> <signal>"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
docker kill "--signal=$2" "$1" >/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
# E2E_TAG is the tag used for docker builds. This is needed because docker
|
# E2E_TAG is the tag used for docker builds. This is needed because docker
|
||||||
# tags are system-global, but one might have multiple repos checked out.
|
# tags are system-global, but one might have multiple repos checked out.
|
||||||
E2E_TAG=$(git rev-parse --show-toplevel | sed 's|/|_|g')
|
E2E_TAG=$(git rev-parse --show-toplevel | sed 's|/|_|g')
|
||||||
|
|
@ -1111,6 +1119,108 @@ function e2e::sync_slow_git_long_timeout() {
|
||||||
assert_metric_eq "${METRIC_GOOD_SYNC_COUNT}" 2
|
assert_metric_eq "${METRIC_GOOD_SYNC_COUNT}" 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##############################################
|
||||||
|
# Test sync-on-signal with SIGHUP
|
||||||
|
##############################################
|
||||||
|
function e2e::sync_on_signal_sighup() {
|
||||||
|
# First sync
|
||||||
|
echo "$FUNCNAME 1" > "$REPO"/file
|
||||||
|
git -C "$REPO" commit -qam "$FUNCNAME 1"
|
||||||
|
|
||||||
|
GIT_SYNC \
|
||||||
|
--period=100s \
|
||||||
|
--sync-on-signal="SIGHUP" \
|
||||||
|
--repo="file://$REPO" \
|
||||||
|
--branch="$MAIN_BRANCH" \
|
||||||
|
--rev=HEAD \
|
||||||
|
--root="$ROOT" \
|
||||||
|
--link="link" \
|
||||||
|
>> "$1" 2>&1 &
|
||||||
|
wait_for_sync 3
|
||||||
|
assert_link_exists "$ROOT"/link
|
||||||
|
assert_file_exists "$ROOT"/link/file
|
||||||
|
assert_file_eq "$ROOT"/link/file "$FUNCNAME 1"
|
||||||
|
|
||||||
|
# Move HEAD forward
|
||||||
|
echo "$FUNCNAME 2" > "$REPO"/file
|
||||||
|
git -C "$REPO" commit -qam "$FUNCNAME 2"
|
||||||
|
# Send signal (note --period is 100s, signal should trigger sync)
|
||||||
|
CTR=$(docker ps --filter label="git-sync-e2e=$RUNID" --format="{{.ID}}")
|
||||||
|
docker_signal "$CTR" SIGHUP
|
||||||
|
wait_for_sync 3
|
||||||
|
assert_link_exists "$ROOT"/link
|
||||||
|
assert_file_exists "$ROOT"/link/file
|
||||||
|
assert_file_eq "$ROOT"/link/file "$FUNCNAME 2"
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################################
|
||||||
|
# Test sync-on-signal with HUP
|
||||||
|
##############################################
|
||||||
|
function e2e::sync_on_signal_hup() {
|
||||||
|
# First sync
|
||||||
|
echo "$FUNCNAME 1" > "$REPO"/file
|
||||||
|
git -C "$REPO" commit -qam "$FUNCNAME 1"
|
||||||
|
|
||||||
|
GIT_SYNC \
|
||||||
|
--period=100s \
|
||||||
|
--sync-on-signal="HUP" \
|
||||||
|
--repo="file://$REPO" \
|
||||||
|
--branch="$MAIN_BRANCH" \
|
||||||
|
--rev=HEAD \
|
||||||
|
--root="$ROOT" \
|
||||||
|
--link="link" \
|
||||||
|
>> "$1" 2>&1 &
|
||||||
|
wait_for_sync 3
|
||||||
|
assert_link_exists "$ROOT"/link
|
||||||
|
assert_file_exists "$ROOT"/link/file
|
||||||
|
assert_file_eq "$ROOT"/link/file "$FUNCNAME 1"
|
||||||
|
|
||||||
|
# Move HEAD forward
|
||||||
|
echo "$FUNCNAME 2" > "$REPO"/file
|
||||||
|
git -C "$REPO" commit -qam "$FUNCNAME 2"
|
||||||
|
# Send signal (note --period is 100s, signal should trigger sync)
|
||||||
|
CTR=$(docker ps --filter label="git-sync-e2e=$RUNID" --format="{{.ID}}")
|
||||||
|
docker_signal "$CTR" SIGHUP
|
||||||
|
wait_for_sync 3
|
||||||
|
assert_link_exists "$ROOT"/link
|
||||||
|
assert_file_exists "$ROOT"/link/file
|
||||||
|
assert_file_eq "$ROOT"/link/file "$FUNCNAME 2"
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################################
|
||||||
|
# Test sync-on-signal with 1 (SIGHUP)
|
||||||
|
##############################################
|
||||||
|
function e2e::sync_on_signal_1() {
|
||||||
|
# First sync
|
||||||
|
echo "$FUNCNAME 1" > "$REPO"/file
|
||||||
|
git -C "$REPO" commit -qam "$FUNCNAME 1"
|
||||||
|
|
||||||
|
GIT_SYNC \
|
||||||
|
--period=100s \
|
||||||
|
--sync-on-signal=1 \
|
||||||
|
--repo="file://$REPO" \
|
||||||
|
--branch="$MAIN_BRANCH" \
|
||||||
|
--rev=HEAD \
|
||||||
|
--root="$ROOT" \
|
||||||
|
--link="link" \
|
||||||
|
>> "$1" 2>&1 &
|
||||||
|
wait_for_sync 3
|
||||||
|
assert_link_exists "$ROOT"/link
|
||||||
|
assert_file_exists "$ROOT"/link/file
|
||||||
|
assert_file_eq "$ROOT"/link/file "$FUNCNAME 1"
|
||||||
|
|
||||||
|
# Move HEAD forward
|
||||||
|
echo "$FUNCNAME 2" > "$REPO"/file
|
||||||
|
git -C "$REPO" commit -qam "$FUNCNAME 2"
|
||||||
|
# Send signal (note --period is 100s, signal should trigger sync)
|
||||||
|
CTR=$(docker ps --filter label="git-sync-e2e=$RUNID" --format="{{.ID}}")
|
||||||
|
docker_signal "$CTR" SIGHUP
|
||||||
|
wait_for_sync 3
|
||||||
|
assert_link_exists "$ROOT"/link
|
||||||
|
assert_file_exists "$ROOT"/link/file
|
||||||
|
assert_file_eq "$ROOT"/link/file "$FUNCNAME 2"
|
||||||
|
}
|
||||||
|
|
||||||
##############################################
|
##############################################
|
||||||
# Test depth syncing
|
# Test depth syncing
|
||||||
##############################################
|
##############################################
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue