Skip to content

Commit 5fa7ffe

Browse files
committed
feat!: introduce client interface, refactor packages
1 parent 127c1cd commit 5fa7ffe

22 files changed

Lines changed: 303 additions & 211 deletions

examples/podman/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ func main() {
1313
if err != nil {
1414
panic(err)
1515
}
16-
isPodman, err := cli.IsPodman(context.Background())
16+
isPodman, err := cli.SystemIsPodman(context.Background())
1717
if err != nil {
1818
panic(err)
1919
}
@@ -43,7 +43,7 @@ func main() {
4343
}
4444
defer cli.NetworkRemove(context.Background(), netResp.ID)
4545

46-
hostIP, err := cli.HostIPFromContainers(context.Background(), &netResp.ID)
46+
hostIP, err := cli.SystemHostIPFromContainers(context.Background(), &netResp.ID)
4747
if err != nil {
4848
panic(err)
4949
}

examples/pull/main.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ import (
1515

1616
func main() {
1717
logger := zap.Must(zap.NewDevelopment()).Sugar()
18-
authProvider, err := auth.NewDefaultProvider()
18+
authProvider, err := auth.NewDefaultAuthProvider()
1919
if err != nil {
2020
panic(err)
2121
}
22-
override := auth.NewOverridingProvider(
22+
override := auth.NewOverridingAuthProvider(
2323
authProvider, map[string]registry.AuthConfig{},
2424
auth.WithSugaredLogger(logger.With(zap.String("component", "auth-provider"))),
2525
).WithOverride("quay.io", registry.AuthConfig{})
@@ -51,7 +51,7 @@ func main() {
5151
logger.Infof("%02d [%s]: %s", idx, l.Id(), l.Status())
5252
}
5353
}
54-
digest, err := cli.ImagePull(context.Background(), ref, image.PullOptions{})
54+
digest, err := cli.ImagePullSimple(context.Background(), ref, image.PullOptions{})
5555
if err != nil {
5656
panic(err)
5757
}

pkg/api/client.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package api
2+
3+
import (
4+
"context"
5+
"io"
6+
"net"
7+
"net/http"
8+
9+
"github.com/distribution/reference"
10+
"github.com/docker/docker/api/types/build"
11+
"github.com/docker/docker/api/types/image"
12+
"github.com/docker/docker/client"
13+
v1 "github.com/google/go-containerregistry/pkg/v1"
14+
"github.com/opencontainers/go-digest"
15+
"github.com/silenium-dev/docker-wrapper/pkg/client/provider"
16+
"github.com/silenium-dev/docker-wrapper/pkg/client/pull/events"
17+
"github.com/silenium-dev/docker-wrapper/pkg/client/pull/state"
18+
"github.com/silenium-dev/docker-wrapper/pkg/client/stream"
19+
"go.uber.org/zap"
20+
)
21+
22+
type ClientBase interface {
23+
AuthProvider() provider.AuthProvider
24+
Logger() *zap.SugaredLogger
25+
Close() error
26+
RequestAuthenticate(req *http.Request, ref reference.Named) error
27+
}
28+
29+
type ImageClient interface {
30+
ImageBuild(
31+
ctx context.Context, buildContext io.Reader, opts build.ImageBuildOptions,
32+
) (build.ImageBuildResponse, error)
33+
ImagePullWithEvents(ctx context.Context, ref reference.Named, options image.PullOptions) (
34+
v1.Hash, *v1.Manifest, chan events.PullEvent, error,
35+
)
36+
ImagePullWithState(ctx context.Context, ref reference.Named, options image.PullOptions) (
37+
v1.Hash, *v1.Manifest, chan state.Pull, error,
38+
)
39+
ImagePullSimple(ctx context.Context, ref reference.Named, options image.PullOptions) (digest.Digest, error)
40+
ImageGetManifest(ctx context.Context, ref reference.Named, platform *v1.Platform) (v1.Hash, *v1.Manifest, error)
41+
}
42+
43+
type ContainerClient interface {
44+
StreamLogs(ctx context.Context, id string, follow bool) (*stream.MultiplexedStream, error)
45+
}
46+
47+
type SystemClient interface {
48+
SystemHostIPFromContainers(ctx context.Context, netId *string) (net.IP, error)
49+
SystemIsPodman(ctx context.Context) (bool, error)
50+
SystemDefaultPlatform(ctx context.Context) (*v1.Platform, error)
51+
}
52+
53+
type ClientWrapper interface {
54+
client.APIClient
55+
ClientBase
56+
ImageClient
57+
ContainerClient
58+
SystemClient
59+
}

pkg/client/base.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package client
2+
3+
import (
4+
"github.com/silenium-dev/docker-wrapper/pkg/client/provider"
5+
"go.uber.org/zap"
6+
)
7+
8+
func (c *Client) Close() error {
9+
return c.Client.Close()
10+
}
11+
12+
func (c *Client) AuthProvider() provider.AuthProvider {
13+
return c.authProvider
14+
}
15+
16+
func (c *Client) Logger() *zap.SugaredLogger {
17+
return c.logger
18+
}

pkg/client/build.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ package client
22

33
import (
44
"context"
5-
"github.com/docker/docker/api/types"
65
"io"
76
"maps"
7+
8+
"github.com/docker/docker/api/types/build"
89
)
910

10-
func (c *Client) ImageBuild(ctx context.Context, buildContext io.Reader, opts types.ImageBuildOptions) (types.ImageBuildResponse, error) {
11+
func (c *Client) ImageBuild(
12+
ctx context.Context, buildContext io.Reader, opts build.ImageBuildOptions,
13+
) (build.ImageBuildResponse, error) {
1114
authConfigs := c.authProvider.AuthConfigs()
1215
maps.Copy(authConfigs, opts.AuthConfigs)
1316
opts.AuthConfigs = authConfigs

pkg/client/client.go

Lines changed: 4 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,23 @@ package client
22

33
import (
44
"net"
5-
"net/http"
6-
"slices"
75
"sync"
86

97
"github.com/docker/docker/client"
10-
"github.com/silenium-dev/docker-wrapper/pkg/client/auth"
11-
"github.com/silenium-dev/docker-wrapper/pkg/client/image"
8+
"github.com/silenium-dev/docker-wrapper/pkg/client/provider"
129
"go.uber.org/zap"
1310
)
1411

1512
type Client struct {
1613
*client.Client
1714
dockerOpts []client.Opt
18-
authProvider auth.Provider
19-
imageProvider image.Provider
15+
authProvider provider.AuthProvider
16+
imageProvider provider.ImageProvider
2017
logger *zap.SugaredLogger
2118
hostFromContainerAddr net.IP
2219
hostFromContainerMutex sync.RWMutex
2320
}
2421

25-
type Opt func(*Client) error
26-
2722
func NewWithOpts(opts ...Opt) (*Client, error) {
2823
c := &Client{}
2924
for _, opt := range opts {
@@ -37,7 +32,7 @@ func NewWithOpts(opts ...Opt) (*Client, error) {
3732
c.logger = zap.Must(zap.NewDevelopment()).Sugar()
3833
}
3934
if c.imageProvider == nil {
40-
c.imageProvider = image.DefaultProvider()
35+
c.imageProvider = provider.DefaultImageProvider()
4136
}
4237

4338
cli, err := client.NewClientWithOpts(c.dockerOpts...)
@@ -47,67 +42,3 @@ func NewWithOpts(opts ...Opt) (*Client, error) {
4742
c.Client = cli
4843
return c, nil
4944
}
50-
51-
func (c *Client) Close() error {
52-
return c.Client.Close()
53-
}
54-
55-
func (c *Client) AuthProvider() auth.Provider {
56-
return c.authProvider
57-
}
58-
59-
func (c *Client) Logger() *zap.SugaredLogger {
60-
return c.logger
61-
}
62-
63-
func WithVersionNegotiation(c *Client) error {
64-
c.dockerOpts = append(c.dockerOpts, client.WithAPIVersionNegotiation())
65-
return nil
66-
}
67-
68-
func WithAuthProvider(authProvider auth.Provider) Opt {
69-
return func(c *Client) error {
70-
c.authProvider = authProvider
71-
return nil
72-
}
73-
}
74-
75-
func WithSugaredLogger(logger *zap.SugaredLogger) Opt {
76-
return func(c *Client) error {
77-
c.logger = logger
78-
return nil
79-
}
80-
}
81-
82-
func WithLogger(logger *zap.Logger) Opt {
83-
return func(c *Client) error {
84-
c.logger = logger.Sugar()
85-
return nil
86-
}
87-
}
88-
89-
func WithImageProvider(imageProvider image.Provider) Opt {
90-
return func(c *Client) error {
91-
c.imageProvider = imageProvider
92-
return nil
93-
}
94-
}
95-
96-
func WithDockerOpts(opts ...client.Opt) Opt {
97-
return func(c *Client) error {
98-
c.dockerOpts = slices.Concat(c.dockerOpts, opts)
99-
return nil
100-
}
101-
}
102-
103-
func WithHTTPClient(httpClient *http.Client) Opt {
104-
return func(c *Client) error {
105-
c.dockerOpts = append(c.dockerOpts, client.WithHTTPClient(httpClient))
106-
return nil
107-
}
108-
}
109-
110-
func FromEnv(c *Client) error {
111-
c.dockerOpts = append(c.dockerOpts, client.FromEnv)
112-
return nil
113-
}

pkg/client/client_opts.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package client
2+
3+
import (
4+
"net/http"
5+
"slices"
6+
7+
"github.com/docker/docker/client"
8+
"github.com/silenium-dev/docker-wrapper/pkg/client/provider"
9+
"go.uber.org/zap"
10+
)
11+
12+
type Opt func(*Client) error
13+
14+
func WithVersionNegotiation(c *Client) error {
15+
c.dockerOpts = append(c.dockerOpts, client.WithAPIVersionNegotiation())
16+
return nil
17+
}
18+
19+
func WithAuthProvider(authProvider provider.AuthProvider) Opt {
20+
return func(c *Client) error {
21+
c.authProvider = authProvider
22+
return nil
23+
}
24+
}
25+
26+
func WithSugaredLogger(logger *zap.SugaredLogger) Opt {
27+
return func(c *Client) error {
28+
c.logger = logger
29+
return nil
30+
}
31+
}
32+
33+
func WithLogger(logger *zap.Logger) Opt {
34+
return func(c *Client) error {
35+
c.logger = logger.Sugar()
36+
return nil
37+
}
38+
}
39+
40+
func WithImageProvider(imageProvider provider.ImageProvider) Opt {
41+
return func(c *Client) error {
42+
c.imageProvider = imageProvider
43+
return nil
44+
}
45+
}
46+
47+
func WithDockerOpts(opts ...client.Opt) Opt {
48+
return func(c *Client) error {
49+
c.dockerOpts = slices.Concat(c.dockerOpts, opts)
50+
return nil
51+
}
52+
}
53+
54+
func WithHTTPClient(httpClient *http.Client) Opt {
55+
return func(c *Client) error {
56+
c.dockerOpts = append(c.dockerOpts, client.WithHTTPClient(httpClient))
57+
return nil
58+
}
59+
}
60+
61+
func FromEnv(c *Client) error {
62+
c.dockerOpts = append(c.dockerOpts, client.FromEnv)
63+
return nil
64+
}

pkg/client/image_info.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package client
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/distribution/reference"
8+
"github.com/google/go-containerregistry/pkg/name"
9+
v1 "github.com/google/go-containerregistry/pkg/v1"
10+
"github.com/google/go-containerregistry/pkg/v1/remote"
11+
)
12+
13+
func (c *Client) ImageGetManifest(ctx context.Context, ref reference.Named, platform *v1.Platform) (
14+
v1.Hash, *v1.Manifest, error,
15+
) {
16+
var err error
17+
if platform == nil {
18+
platform, err = c.SystemDefaultPlatform(ctx)
19+
if err != nil {
20+
return v1.Hash{}, nil, err
21+
}
22+
}
23+
opts := []remote.Option{
24+
remote.WithAuthFromKeychain(c.authProvider),
25+
remote.WithContext(ctx),
26+
remote.WithPlatform(*platform),
27+
}
28+
29+
nameRef, err := name.ParseReference(ref.String())
30+
if err != nil {
31+
return v1.Hash{}, nil, err
32+
}
33+
34+
img, err := remote.Image(nameRef, opts...)
35+
if err != nil {
36+
return v1.Hash{}, nil, fmt.Errorf("failed to get image manifest: %w", err)
37+
}
38+
manifest, err := img.Manifest()
39+
if err != nil {
40+
return v1.Hash{}, nil, err
41+
}
42+
id, err := img.ConfigName()
43+
if err != nil {
44+
return v1.Hash{}, nil, err
45+
}
46+
47+
return id, manifest, nil
48+
}

0 commit comments

Comments
 (0)