commit
012d0bfbf0
|
|
@ -14,10 +14,6 @@
|
||||||
|
|
||||||
FROM {ARG_FROM}
|
FROM {ARG_FROM}
|
||||||
|
|
||||||
MAINTAINER Tim Hockin <thockin@google.com>
|
|
||||||
|
|
||||||
ADD bin/{ARG_OS}_{ARG_ARCH}/{ARG_BIN} /{ARG_BIN}
|
|
||||||
|
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get -y install \
|
&& apt-get -y install \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
|
|
@ -28,6 +24,8 @@ RUN apt-get update \
|
||||||
|
|
||||||
RUN echo "git-sync:x:65533:65533::/tmp:/sbin/nologin" >> /etc/passwd
|
RUN echo "git-sync:x:65533:65533::/tmp:/sbin/nologin" >> /etc/passwd
|
||||||
|
|
||||||
|
ADD bin/{ARG_OS}_{ARG_ARCH}/{ARG_BIN} /{ARG_BIN}
|
||||||
|
|
||||||
WORKDIR /tmp
|
WORKDIR /tmp
|
||||||
USER git-sync:nogroup
|
USER git-sync:nogroup
|
||||||
ENTRYPOINT ["/{ARG_BIN}"]
|
ENTRYPOINT ["/{ARG_BIN}"]
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import (
|
||||||
"github.com/go-logr/glogr"
|
"github.com/go-logr/glogr"
|
||||||
"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"
|
||||||
|
"k8s.io/git-sync/pkg/pid1"
|
||||||
"k8s.io/git-sync/pkg/version"
|
"k8s.io/git-sync/pkg/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -187,6 +188,20 @@ func envDuration(key string, def time.Duration) time.Duration {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// In case we come up as pid 1, act as init.
|
||||||
|
if os.Getpid() == 1 {
|
||||||
|
fmt.Fprintf(os.Stderr, "INFO: detected pid 1, running init handler\n")
|
||||||
|
err := pid1.ReRun()
|
||||||
|
if err == nil {
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
if exerr, ok := err.(*exec.ExitError); ok {
|
||||||
|
os.Exit(exerr.ExitCode())
|
||||||
|
}
|
||||||
|
fmt.Fprintf(os.Stderr, "ERROR: unhandled pid1 error: %v\n", err)
|
||||||
|
os.Exit(127)
|
||||||
|
}
|
||||||
|
|
||||||
setFlagDefaults()
|
setFlagDefaults()
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
@ -201,15 +216,18 @@ func main() {
|
||||||
flag.Usage()
|
flag.Usage()
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if *flDest == "" {
|
if *flDest == "" {
|
||||||
parts := strings.Split(strings.Trim(*flRepo, "/"), "/")
|
parts := strings.Split(strings.Trim(*flRepo, "/"), "/")
|
||||||
*flDest = parts[len(parts)-1]
|
*flDest = parts[len(parts)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(*flDest, "/") {
|
if strings.Contains(*flDest, "/") {
|
||||||
fmt.Fprintf(os.Stderr, "ERROR: --dest must be a bare name\n")
|
fmt.Fprintf(os.Stderr, "ERROR: --dest must be a bare name\n")
|
||||||
flag.Usage()
|
flag.Usage()
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := exec.LookPath(*flGitCmd); err != nil {
|
if _, err := exec.LookPath(*flGitCmd); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "ERROR: git executable %q not found: %v\n", *flGitCmd, err)
|
fmt.Fprintf(os.Stderr, "ERROR: git executable %q not found: %v\n", *flGitCmd, err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
package pid1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReRun converts the current process into a bare-bones init, runs the current
|
||||||
|
// commandline as a child process, and waits for it to complete. The new child
|
||||||
|
// process shares stdin/stdout/stderr with the parent. When the child exits,
|
||||||
|
// this will return the same value as exec.Command.Run(). If there is an error
|
||||||
|
// in reaping children that this can not handle, it will panic.
|
||||||
|
func ReRun() error {
|
||||||
|
bin, err := os.Readlink("/proc/self/exe")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cmd := exec.Command(bin, os.Args[1:]...)
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
if err := cmd.Start(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
go runInit(cmd.Process.Pid)
|
||||||
|
return cmd.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// runInit runs a bare-bones init process. This will never return. In case of
|
||||||
|
// truly unknown errors it will panic.
|
||||||
|
func runInit(pid int) {
|
||||||
|
sigs := make(chan os.Signal, 8)
|
||||||
|
signal.Notify(sigs)
|
||||||
|
for sig := range sigs {
|
||||||
|
if sig == syscall.SIGCHLD {
|
||||||
|
sigchld()
|
||||||
|
} else {
|
||||||
|
// Pass it on to the real process.
|
||||||
|
syscall.Kill(pid, sig.(syscall.Signal))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sigchld handles a SIGCHLD.
|
||||||
|
func sigchld() {
|
||||||
|
// Loop to handle multiple child processes.
|
||||||
|
for {
|
||||||
|
var status syscall.WaitStatus
|
||||||
|
pid, err := syscall.Wait4(-1, &status, syscall.WNOHANG, nil)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to wait4(): %v\n", err))
|
||||||
|
}
|
||||||
|
if pid <= 0 {
|
||||||
|
// No more children to reap.
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// Must have found one, see if there are more.
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue