mirror of
https://github.com/containrrr/watchtower.git
synced 2024-12-12 09:04:17 +02:00
1c59200565
Load authentication credentials for available credential stores in order of preference: 1. Environment variables REPO_USER, REPO_PASS 2. Docker config files Request image pull with authentication header. Wait until pull request is complete before exiting function.
154 lines
3.0 KiB
Go
154 lines
3.0 KiB
Go
package main // import "github.com/CenturyLinkLabs/watchtower"
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/signal"
|
|
"sync"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/CenturyLinkLabs/watchtower/actions"
|
|
"github.com/CenturyLinkLabs/watchtower/container"
|
|
log "github.com/Sirupsen/logrus"
|
|
"github.com/urfave/cli"
|
|
)
|
|
|
|
var (
|
|
wg sync.WaitGroup
|
|
client container.Client
|
|
pollInterval time.Duration
|
|
cleanup bool
|
|
)
|
|
|
|
func init() {
|
|
log.SetLevel(log.InfoLevel)
|
|
}
|
|
|
|
func main() {
|
|
app := cli.NewApp()
|
|
app.Name = "watchtower"
|
|
app.Usage = "Automatically update running Docker containers"
|
|
app.Before = before
|
|
app.Action = start
|
|
app.Flags = []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "host, H",
|
|
Usage: "daemon socket to connect to",
|
|
Value: "unix:///var/run/docker.sock",
|
|
EnvVar: "DOCKER_HOST",
|
|
},
|
|
cli.IntFlag{
|
|
Name: "interval, i",
|
|
Usage: "poll interval (in seconds)",
|
|
Value: 300,
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "no-pull",
|
|
Usage: "do not pull new images",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "cleanup",
|
|
Usage: "remove old images after updating",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "tlsverify",
|
|
Usage: "use TLS and verify the remote",
|
|
EnvVar: "DOCKER_TLS_VERIFY",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "debug",
|
|
Usage: "enable debug mode with verbose logging",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "apiversion",
|
|
Usage: "the version of the docker api",
|
|
EnvVar: "DOCKER_API_VERSION",
|
|
},
|
|
}
|
|
|
|
if err := app.Run(os.Args); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func before(c *cli.Context) error {
|
|
if c.GlobalBool("debug") {
|
|
log.SetLevel(log.DebugLevel)
|
|
}
|
|
|
|
pollInterval = time.Duration(c.Int("interval")) * time.Second
|
|
cleanup = c.GlobalBool("cleanup")
|
|
|
|
// configure environment vars for client
|
|
err := envConfig(c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
client = container.NewClient(!c.GlobalBool("no-pull"))
|
|
|
|
handleSignals()
|
|
return nil
|
|
}
|
|
|
|
func start(c *cli.Context) {
|
|
names := c.Args()
|
|
|
|
if err := actions.CheckPrereqs(client, cleanup); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
for {
|
|
wg.Add(1)
|
|
if err := actions.Update(client, names, cleanup); err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
wg.Done()
|
|
|
|
time.Sleep(pollInterval)
|
|
}
|
|
}
|
|
|
|
func handleSignals() {
|
|
// Graceful shut-down on SIGINT/SIGTERM
|
|
c := make(chan os.Signal, 1)
|
|
signal.Notify(c, os.Interrupt)
|
|
signal.Notify(c, syscall.SIGTERM)
|
|
|
|
go func() {
|
|
<-c
|
|
wg.Wait()
|
|
os.Exit(1)
|
|
}()
|
|
}
|
|
|
|
func setEnvOptStr(env string, opt string) error {
|
|
if opt != "" && opt != os.Getenv(env) {
|
|
err := os.Setenv(env, opt)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func setEnvOptBool(env string, opt bool) error {
|
|
if opt == true {
|
|
return setEnvOptStr(env, "1")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// envConfig translates the command-line options into environment variables
|
|
// that will initialize the api client
|
|
func envConfig(c *cli.Context) error {
|
|
var err error
|
|
|
|
err = setEnvOptStr("DOCKER_HOST", c.GlobalString("host"))
|
|
err = setEnvOptBool("DOCKER_TLS_VERIFY", c.GlobalBool("tlsverify"))
|
|
err = setEnvOptStr("DOCKER_API_VERSION", c.GlobalString("apiversion"))
|
|
|
|
return err
|
|
}
|