-
Notifications
You must be signed in to change notification settings - Fork 1.3k
blobserve: dynamically reload Docker auth config #15442
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we really fail blobserve or keep using previous credentials? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It depends on how earlier we want to catch the problem. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jenting it is just a question, feel free to merge |
||
} | ||
|
||
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) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(nit) wonder whether mutex really needed or capturing local reference can be enough