diff --git a/components/blobserve/cmd/run.go b/components/blobserve/cmd/run.go index becf216597a161..b24bf8b19993d3 100644 --- a/components/blobserve/cmd/run.go +++ b/components/blobserve/cmd/run.go @@ -5,11 +5,13 @@ package cmd import ( + "context" "fmt" "net/http" "os" "os/signal" "path/filepath" + "sync" "syscall" "time" @@ -28,6 +30,7 @@ import ( "github.com/gitpod-io/gitpod/common-go/kubernetes" "github.com/gitpod-io/gitpod/common-go/log" "github.com/gitpod-io/gitpod/common-go/pprof" + "github.com/gitpod-io/gitpod/common-go/watch" ) var jsonLog bool @@ -44,30 +47,21 @@ var runCmd = &cobra.Command{ log.WithError(err).WithField("filename", args[0]).Fatal("cannot load config") } - var dockerCfg *configfile.ConfigFile + var ( + dockerCfg *configfile.ConfigFile + dockerCfgMu sync.RWMutex + ) if cfg.AuthCfg != "" { - authCfg := cfg.AuthCfg - if tproot := os.Getenv("TELEPRESENCE_ROOT"); tproot != "" { - authCfg = filepath.Join(tproot, authCfg) - } - fr, err := os.OpenFile(authCfg, os.O_RDONLY, 0) - if err != nil { - log.WithError(err).Fatal("cannot read docker auth config") - } - - dockerCfg = configfile.New(authCfg) - err = dockerCfg.LoadFromReader(fr) - fr.Close() - if err != nil { - log.WithError(err).Fatal("cannot read docker config") - } - log.WithField("fn", authCfg).Info("using authentication for backing registries") + dockerCfg = loadDockerCfg(cfg.AuthCfg) } reg := prometheus.NewRegistry() resolverProvider := func() remotes.Resolver { var resolverOpts docker.ResolverOptions + + dockerCfgMu.RLock() + defer dockerCfgMu.RUnlock() if dockerCfg != nil { resolverOpts.Hosts = docker.ConfigureDefaultRegistries( docker.WithAuthorizer(authorizerFromDockerConfig(dockerCfg)), @@ -136,6 +130,19 @@ var runCmd = &cobra.Command{ }() } + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + err = watch.File(ctx, cfg.AuthCfg, func() { + dockerCfgMu.Lock() + defer dockerCfgMu.Unlock() + + dockerCfg = loadDockerCfg(cfg.AuthCfg) + }) + if err != nil { + log.WithError(err).Fatal("cannot start watch of Docker auth configuration file") + } + log.Info("🏪 blobserve is up and running") sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) @@ -147,6 +154,26 @@ func init() { rootCmd.AddCommand(runCmd) } +func loadDockerCfg(fn string) *configfile.ConfigFile { + if tproot := os.Getenv("TELEPRESENCE_ROOT"); tproot != "" { + fn = filepath.Join(tproot, fn) + } + fr, err := os.OpenFile(fn, os.O_RDONLY, 0) + if err != nil { + log.WithError(err).Fatal("cannot read docker auth config") + } + + dockerCfg := configfile.New(fn) + err = dockerCfg.LoadFromReader(fr) + fr.Close() + if err != nil { + log.WithError(err).Fatal("cannot read docker config") + } + log.WithField("fn", fn).Info("using authentication for backing registries") + + return dockerCfg +} + // FromDockerConfig turns docker client config into docker registry hosts func authorizerFromDockerConfig(cfg *configfile.ConfigFile) docker.Authorizer { return docker.NewDockerAuthorizer(docker.WithAuthCreds(func(host string) (user, pass string, err error) { diff --git a/components/blobserve/go.mod b/components/blobserve/go.mod index 6766429c038669..45d7f5604e4bf3 100644 --- a/components/blobserve/go.mod +++ b/components/blobserve/go.mod @@ -26,6 +26,7 @@ require ( github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/docker/docker-credential-helpers v0.6.4 // indirect github.com/felixge/httpsnoop v1.0.1 // indirect + github.com/fsnotify/fsnotify v1.4.9 // indirect github.com/gitpod-io/gitpod/registry-facade/api v0.0.0-00010101000000-000000000000 // indirect github.com/go-logr/logr v1.2.2 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect