Skip to content

Commit c239351

Browse files
committed
feat: add overriding auth provider for adding custom auth on top of another provider, add option for user-defined logger
1 parent 1361c56 commit c239351

File tree

9 files changed

+137
-27
lines changed

9 files changed

+137
-27
lines changed

examples/pull/main.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,36 @@ package main
22

33
import (
44
"context"
5-
"fmt"
65
"github.com/distribution/reference"
6+
"github.com/docker/docker/api/types/registry"
77
client2 "github.com/docker/docker/client"
88
"github.com/silenium-dev/docker-wrapper/pkg/client"
99
"github.com/silenium-dev/docker-wrapper/pkg/client/auth"
10+
"go.uber.org/zap"
1011
"time"
1112
)
1213

1314
func main() {
15+
logger := zap.Must(zap.NewDevelopment()).Sugar()
1416
authProvider, err := auth.NewDefaultProvider()
1517
if err != nil {
1618
panic(err)
1719
}
20+
override := auth.NewOverridingProvider(
21+
authProvider, map[string]registry.AuthConfig{},
22+
auth.WithSugaredLogger(logger.With(zap.String("component", "auth-provider"))),
23+
).WithOverride("quay.io", registry.AuthConfig{})
1824
cli, err := client.NewWithOpts(
19-
client.WithAuthProvider(authProvider),
25+
client.WithAuthProvider(override),
2026
client.FromEnv,
2127
client.WithDockerOpts(client2.WithTimeout(time.Hour*1)),
28+
client.WithSugaredLogger(logger.With(zap.String("component", "docker-client"))),
2229
)
2330
if err != nil {
2431
panic(err)
2532
}
26-
//ref, err := reference.ParseDockerRef("quay.io/prometheus/node-exporter@sha256:a25fbdaa3e4d03e0d735fd03f231e9a48332ecf40ca209b2f103b1f970d1cde0")
27-
ref, err := reference.ParseDockerRef("localstack/localstack:latest")
33+
ref, err := reference.ParseDockerRef("quay.io/prometheus/prometheus:latest")
34+
//ref, err := reference.ParseDockerRef("localstack/localstack:latest")
2835
if err != nil {
2936
panic(err)
3037
}
@@ -34,14 +41,14 @@ func main() {
3441
}
3542
for state := range stateChan {
3643
print("\033[2J")
37-
fmt.Printf("%s\n", state.Status())
44+
logger.Infof("%s", state.Status())
3845
for idx, l := range state.Layers() {
39-
fmt.Printf("%02d [%s]: %s\n", idx, l.Id(), l.Status())
46+
logger.Infof("%02d [%s]: %s", idx, l.Id(), l.Status())
4047
}
4148
}
4249
digest, err := cli.Pull(context.Background(), ref)
4350
if err != nil {
4451
panic(err)
4552
}
46-
fmt.Printf("Digest: %s\n", digest)
53+
logger.Infof("Digest: %s\n", digest)
4754
}

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
github.com/docker/docker v25.0.10+incompatible
1010
github.com/docker/go-units v0.5.0
1111
github.com/opencontainers/go-digest v1.0.0
12+
go.uber.org/zap v1.27.0
1213
)
1314

1415
require (
@@ -29,6 +30,7 @@ require (
2930
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 // indirect
3031
go.opentelemetry.io/otel/metric v1.37.0 // indirect
3132
go.opentelemetry.io/otel/trace v1.37.0 // indirect
33+
go.uber.org/multierr v1.11.0 // indirect
3234
golang.org/x/sys v0.34.0 // indirect
3335
golang.org/x/time v0.12.0 // indirect
3436
gotest.tools/v3 v3.5.2 // indirect

go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mx
7575
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
7676
go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os=
7777
go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo=
78+
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
79+
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
80+
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
81+
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
82+
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
83+
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
7884
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
7985
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
8086
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=

pkg/client/auth/api.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package auth
2+
3+
import (
4+
"github.com/distribution/reference"
5+
"github.com/docker/docker/api/types/registry"
6+
"go.uber.org/zap"
7+
)
8+
9+
type Provider interface {
10+
AuthConfig(ref reference.Named) registry.AuthConfig
11+
}
12+
13+
type ProviderConfig struct {
14+
Logger *zap.SugaredLogger
15+
}
16+
17+
type Opt func(config *ProviderConfig)
18+
19+
func WithLogger(logger *zap.Logger) Opt {
20+
return func(config *ProviderConfig) {
21+
config.Logger = logger.Sugar()
22+
}
23+
}
24+
25+
func WithSugaredLogger(logger *zap.SugaredLogger) Opt {
26+
return func(config *ProviderConfig) {
27+
config.Logger = logger
28+
}
29+
}
30+
31+
func renderConfig(opts []Opt) *ProviderConfig {
32+
config := &ProviderConfig{}
33+
for _, opt := range opts {
34+
opt(config)
35+
}
36+
if config.Logger == nil {
37+
config.Logger = zap.Must(zap.NewDevelopment()).Sugar()
38+
}
39+
return config
40+
}

pkg/client/auth/default.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,35 @@ import (
77
"github.com/cpuguy83/dockercfg"
88
"github.com/distribution/reference"
99
"github.com/docker/docker/api/types/registry"
10-
"log"
1110
"os"
1211
)
1312

1413
type DefaultAuthProvider struct {
1514
authConfigs map[string]*registry.AuthConfig
15+
config *ProviderConfig
1616
}
1717

1818
func (d *DefaultAuthProvider) AuthConfig(ref reference.Named) registry.AuthConfig {
1919
domain := reference.Domain(ref)
2020
if ac, ok := d.authConfigs[domain]; ok {
21-
log.Printf("using auth config for %s", domain)
21+
d.config.Logger.Debugf("using auth config for %s", domain)
2222
return *ac
2323
}
24-
log.Printf("no auth config for %s", domain)
24+
d.config.Logger.Debugf("no auth config for %s", domain)
2525
return registry.AuthConfig{}
2626
}
2727

28-
func NewDefaultProvider() (*DefaultAuthProvider, error) {
28+
func NewDefaultProvider(opts ...Opt) (*DefaultAuthProvider, error) {
29+
config := renderConfig(opts)
30+
2931
authConfigs := map[string]*registry.AuthConfig{}
3032

3133
cfg, err := dockercfg.LoadDefaultConfig()
3234
if err != nil && !errors.Is(err, os.ErrNotExist) {
33-
log.Printf("failed to load docker config: %v", err)
35+
config.Logger.Errorf("failed to load docker config: %v", err)
3436
return nil, err
3537
} else if errors.Is(err, os.ErrNotExist) {
36-
log.Printf("docker config not found, using empty config")
37-
return &DefaultAuthProvider{authConfigs}, nil
38+
return &DefaultAuthProvider{authConfigs, config}, nil
3839
}
3940

4041
for k, v := range cfg.AuthConfigs {
@@ -50,7 +51,7 @@ func NewDefaultProvider() (*DefaultAuthProvider, error) {
5051
if ac.Username == "" && ac.Password == "" {
5152
err := getCredentials(k, &cfg, ac)
5253
if err != nil {
53-
log.Printf("failed to get credentials for registry %s: %v", k, err)
54+
config.Logger.Errorf("failed to get credentials for registry %s: %v", k, err)
5455
continue
5556
}
5657
}
@@ -63,10 +64,10 @@ func NewDefaultProvider() (*DefaultAuthProvider, error) {
6364
for k := range cfg.CredentialHelpers {
6465
err := getCredentials(k, &cfg, authConfigs[k])
6566
if err != nil {
66-
log.Printf("failed to get credentials for registry %s: %v", k, err)
67+
config.Logger.Errorf("failed to get credentials for registry %s: %v", k, err)
6768
}
6869
}
69-
return &DefaultAuthProvider{authConfigs}, nil
70+
return &DefaultAuthProvider{authConfigs, config}, nil
7071
}
7172

7273
func getCredentials(registryHost string, cfg *dockercfg.Config, ac *registry.AuthConfig) error {

pkg/client/auth/overriding.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package auth
2+
3+
import (
4+
"github.com/distribution/reference"
5+
"github.com/docker/docker/api/types/registry"
6+
"maps"
7+
)
8+
9+
type OverridingAuthProvider struct {
10+
source Provider
11+
overrides map[string]registry.AuthConfig
12+
config *ProviderConfig
13+
}
14+
15+
func NewOverridingProvider(
16+
source Provider, overrides map[string]registry.AuthConfig, opts ...Opt,
17+
) *OverridingAuthProvider {
18+
config := renderConfig(opts)
19+
return &OverridingAuthProvider{source, overrides, config}
20+
}
21+
22+
func (o *OverridingAuthProvider) WithOverride(domain string, ac registry.AuthConfig) *OverridingAuthProvider {
23+
overrides := maps.Clone(o.overrides)
24+
overrides[domain] = ac
25+
return NewOverridingProvider(o.source, overrides)
26+
}
27+
28+
func (o *OverridingAuthProvider) AuthConfig(ref reference.Named) registry.AuthConfig {
29+
if ac, ok := o.overrides[reference.Domain(ref)]; ok {
30+
o.config.Logger.Debugf("using override for %s", reference.Domain(ref))
31+
return ac
32+
}
33+
o.config.Logger.Debugf("no override present for %s", reference.Domain(ref))
34+
return o.source.AuthConfig(ref)
35+
}

pkg/client/client.go

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
package client
22

33
import (
4-
"github.com/distribution/reference"
5-
"github.com/docker/docker/api/types/registry"
64
"github.com/docker/docker/client"
5+
"github.com/silenium-dev/docker-wrapper/pkg/client/auth"
6+
"go.uber.org/zap"
77
"slices"
88
)
99

10-
type AuthProvider interface {
11-
AuthConfig(named reference.Named) registry.AuthConfig
12-
}
13-
1410
type Client struct {
1511
*client.Client
1612
dockerOpts []client.Opt
17-
authProvider AuthProvider
13+
authProvider auth.Provider
14+
logger *zap.SugaredLogger
1815
}
1916

2017
type Opt func(*Client) error
@@ -27,6 +24,11 @@ func NewWithOpts(opts ...Opt) (*Client, error) {
2724
return nil, err
2825
}
2926
}
27+
28+
if c.logger == nil {
29+
c.logger = zap.Must(zap.NewDevelopment()).Sugar()
30+
}
31+
3032
cli, err := client.NewClientWithOpts(c.dockerOpts...)
3133
if err != nil {
3234
return nil, err
@@ -39,13 +41,27 @@ func (c *Client) Close() error {
3941
return c.Client.Close()
4042
}
4143

42-
func WithAuthProvider(authProvider AuthProvider) Opt {
44+
func WithAuthProvider(authProvider auth.Provider) Opt {
4345
return func(c *Client) error {
4446
c.authProvider = authProvider
4547
return nil
4648
}
4749
}
4850

51+
func WithSugaredLogger(logger *zap.SugaredLogger) Opt {
52+
return func(c *Client) error {
53+
c.logger = logger
54+
return nil
55+
}
56+
}
57+
58+
func WithLogger(logger *zap.Logger) Opt {
59+
return func(c *Client) error {
60+
c.logger = logger.Sugar()
61+
return nil
62+
}
63+
}
64+
4965
func WithDockerOpts(opts ...client.Opt) Opt {
5066
return func(c *Client) error {
5167
c.dockerOpts = slices.Concat(c.dockerOpts, opts)

pkg/client/pull.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ func (c *Client) PullWithEvents(ctx context.Context, ref reference.Named) (chan
2424
var encodedAuth string
2525
var err error
2626
if c.authProvider != nil {
27+
c.logger.Debugf("using configured auth provider")
2728
encodedAuth, err = registry.EncodeAuthConfig(c.authProvider.AuthConfig(ref))
2829
if err != nil {
2930
return nil, err
@@ -44,8 +45,9 @@ func (c *Client) Pull(ctx context.Context, ref reference.Named) (digest.Digest,
4445

4546
var digestEvent *events.Digest
4647
for event := range eventChan {
47-
if _, ok := event.(*events.Digest); digestEvent == nil && ok {
48-
digestEvent = event.(*events.Digest)
48+
if ev, ok := event.(*events.Digest); digestEvent == nil && ok {
49+
c.logger.Debugf("received digest event: %s", ev.String())
50+
digestEvent = ev
4951
}
5052
}
5153
if digestEvent == nil {

pkg/logging/logger.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package logging

0 commit comments

Comments
 (0)