Skip to content

Commit

Permalink
add opts to image extractor and move back config to internal
Browse files Browse the repository at this point in the history
  • Loading branch information
crazy-max committed May 5, 2024
1 parent 91fc39e commit 151a654
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 53 deletions.
2 changes: 1 addition & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (

"github.com/alecthomas/kong"
"github.com/crazy-max/undock/internal/app"
"github.com/crazy-max/undock/internal/config"
"github.com/crazy-max/undock/internal/logging"
"github.com/crazy-max/undock/pkg/config"
"github.com/rs/zerolog/log"
)

Expand Down
31 changes: 12 additions & 19 deletions internal/app/undock.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ package app
import (
"context"
"os"
"path/filepath"
"strings"

"github.com/containerd/containerd/platforms"
"github.com/crazy-max/undock/pkg/config"
"github.com/crazy-max/undock/internal/config"
ximage "github.com/crazy-max/undock/pkg/extractor/image"
"github.com/crazy-max/undock/pkg/image"
specs "github.com/opencontainers/image-spec/specs-go/v1"
Expand All @@ -24,22 +23,6 @@ type Undock struct {

// New creates new undock instance
func New(meta config.Meta, cli config.Cli) (*Undock, error) {
datadir := cli.CacheDir
if len(datadir) == 0 {
datadir = os.Getenv("XDG_DATA_HOME")
if len(datadir) == 0 {
home := os.Getenv("HOME")
if len(home) == 0 {
return nil, errors.New("neither XDG_DATA_HOME nor HOME was set non-empty")
}
datadir = filepath.Join(home, ".local", "share")
}
}
cli.CacheDir = filepath.Join(datadir, "undock", "cache")
if err := os.MkdirAll(cli.CacheDir, 0700); err != nil {
return nil, errors.Wrapf(err, "failed to create cache directory %q", cli.CacheDir)
}

platform := platforms.DefaultSpec()
if len(cli.Platform) > 0 {
var err error
Expand Down Expand Up @@ -73,7 +56,17 @@ func (c *Undock) Start() error {
return errors.Errorf("unsupported source %q", c.cli.Source)
}

xcli, err := ximage.New(c.ctx, c.meta, c.cli, c.platform)
xcli, err := ximage.New(c.ctx, ximage.Options{
Source: c.cli.Source,
Dist: c.cli.Dist,
Platform: c.platform,
All: c.cli.All,
Includes: c.cli.Includes,
Insecure: c.cli.Insecure,
Wrap: c.cli.Wrap,
CacheDir: c.cli.CacheDir,
UserAgent: c.meta.UserAgent,
})
if err != nil {
return err
}
Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion internal/logging/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"os"
"time"

"github.com/crazy-max/undock/pkg/config"
"github.com/crazy-max/undock/internal/config"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/rs/zerolog/pkgerrors"
Expand Down
18 changes: 9 additions & 9 deletions pkg/extractor/image/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func (c *Client) cacheSource(src string) ([]byte, string, error) {
}
}

srcCtx, err := c.srcCtx(&dockerAuth, c.cli.Insecure)
srcCtx, err := c.srcCtx(&dockerAuth, c.opts.RegistryInsecure)
if err != nil {
return nil, "", errors.Wrap(err, "cannot create source context")
}
Expand Down Expand Up @@ -71,7 +71,7 @@ func (c *Client) cacheSource(src string) ([]byte, string, error) {
cacheDigest = srcObj.Scheme() + "-" + hex.EncodeToString(srcHash.Sum(nil))
}

cachedir := filepath.Join(c.cli.CacheDir, cacheDigest)
cachedir := filepath.Join(c.opts.CacheDir, cacheDigest)
c.logger.Info().Msgf("Computed cache digest %s", cacheDigest)

dstRef, err := alltransports.ParseImageName(fmt.Sprintf("oci:%s", cachedir))
Expand All @@ -84,7 +84,7 @@ func (c *Client) cacheSource(src string) ([]byte, string, error) {
}

imageSelection := copy.CopySystemImage
if c.cli.All {
if c.opts.All {
imageSelection = copy.CopyAllImages
}

Expand All @@ -110,19 +110,19 @@ func (c *Client) srcCtx(auth *types.DockerAuthConfig, insecure bool) (*types.Sys
DockerAuthConfig: auth,
DockerDaemonInsecureSkipTLSVerify: insecure,
DockerInsecureSkipTLSVerify: types.NewOptionalBool(insecure),
DockerRegistryUserAgent: c.meta.UserAgent,
OSChoice: c.platform.OS,
ArchitectureChoice: c.platform.Architecture,
VariantChoice: c.platform.Variant,
BlobInfoCacheDir: filepath.Join(c.cli.CacheDir, "blobs"),
DockerRegistryUserAgent: c.opts.RegistryUserAgent,
OSChoice: c.opts.Platform.OS,
ArchitectureChoice: c.opts.Platform.Architecture,
VariantChoice: c.opts.Platform.Variant,
BlobInfoCacheDir: filepath.Join(c.opts.CacheDir, "blobs"),
}
return sysCtx, nil
}

func (c *Client) dstCtx(_ string) (*types.SystemContext, error) {
return &types.SystemContext{
DirForceDecompress: true,
BlobInfoCacheDir: filepath.Join(c.cli.CacheDir, "blobs"),
BlobInfoCacheDir: filepath.Join(c.opts.CacheDir, "blobs"),
}, nil
}

Expand Down
85 changes: 62 additions & 23 deletions pkg/extractor/image/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import (
"fmt"
"os"
"path"
"path/filepath"
"strings"

"github.com/containerd/containerd/platforms"
"github.com/containers/image/v5/manifest"
"github.com/crazy-max/undock/pkg/config"
"github.com/crazy-max/undock/pkg/extractor"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
Expand All @@ -21,22 +21,61 @@ import (
// Client represents an active image extractor object
type Client struct {
*extractor.Client
ctx context.Context
meta config.Meta
cli config.Cli
platform specs.Platform
logger zerolog.Logger
ctx context.Context
opts Options
logger zerolog.Logger
}

// Options represents image extractor options
type Options struct {
// Source image reference
Source string
// Platform to enforce for Source image
Platform specs.Platform
// Includes a subset of files/dirs from the Source image
Includes []string
// All extracts all architectures if Source image is a manifest list
All bool

// Dist folder
Dist string
// Wrap merges output in Dist folder for a manifest list
Wrap bool

// RegistryInsecure allows contacting the registry or docker daemon over
// HTTP, or HTTPS with failed TLS verification
RegistryInsecure bool
// RegistryUserAgent is the User-Agent string to send to the registry
RegistryUserAgent string

// CacheDir is the directory where the cache is stored
CacheDir string
}

// New creates new image extractor instance
func New(ctx context.Context, meta config.Meta, cli config.Cli, platform specs.Platform) (*extractor.Client, error) {
func New(ctx context.Context, opts Options) (*extractor.Client, error) {
datadir := opts.CacheDir
if len(datadir) == 0 {
datadir = os.Getenv("XDG_DATA_HOME")
if len(datadir) == 0 {
home := os.Getenv("HOME")
if len(home) == 0 {
return nil, errors.New("neither XDG_DATA_HOME nor HOME was set non-empty")
}
datadir = filepath.Join(home, ".local", "share")
}
}

opts.CacheDir = filepath.Join(datadir, "undock", "cache")
if err := os.MkdirAll(opts.CacheDir, 0700); err != nil {
return nil, errors.Wrapf(err, "failed to create cache directory %q", opts.CacheDir)
}

return &extractor.Client{
Handler: &Client{
ctx: ctx,
meta: meta,
cli: cli,
platform: platform,
logger: log.With().Str("src", cli.Source).Logger(),
ctx: ctx,
opts: opts,
logger: log.With().Str("src", opts.Source).Logger(),
},
}, nil
}
Expand All @@ -50,7 +89,7 @@ func (c *Client) Type() string {
func (c *Client) Extract() error {
c.logger.Info().Msg("Extracting source")

manblob, cachedir, err := c.cacheSource(c.cli.Source)
manblob, cachedir, err := c.cacheSource(c.opts.Source)
if err != nil {
return errors.Wrap(err, "cannot cache source")
}
Expand All @@ -69,7 +108,7 @@ func (c *Client) Extract() error {
return errors.Wrap(err, "cannot create OCI manifest instance from blob")
}
mans = append(mans, manifestEntry{
platform: c.platform,
platform: c.opts.Platform,
manifest: man,
})
} else if mtype == specs.MediaTypeImageIndex {
Expand All @@ -94,29 +133,29 @@ func (c *Client) Extract() error {
}

eg, _ := errgroup.WithContext(c.ctx)
for _, mane := range mans {
func(mane manifestEntry) {
for _, me := range mans {
func(me manifestEntry) {
eg.Go(func() error {
dest := c.cli.Dist
if !c.cli.Wrap && len(mans) > 1 {
dest = path.Join(c.cli.Dist, fmt.Sprintf("%s_%s%s", mane.platform.OS, mane.platform.Architecture, mane.platform.Variant))
dest := c.opts.Dist
if !c.opts.Wrap && len(mans) > 1 {
dest = path.Join(c.opts.Dist, fmt.Sprintf("%s_%s%s", me.platform.OS, me.platform.Architecture, me.platform.Variant))
}
for _, layer := range mane.manifest.LayerInfos() {
for _, layer := range me.manifest.LayerInfos() {
sublogger := c.logger.With().
Str("platform", platforms.Format(mane.platform)).
Str("platform", platforms.Format(me.platform)).
Str("media-type", layer.MediaType).
Str("blob", layer.Digest.String()).Logger()
if err = extractor.ExtractBlob(path.Join(cachedir, "blobs", layer.Digest.Algorithm().String(), layer.Digest.Hex()), dest, extractor.ExtractBlobOpts{
Context: c.ctx,
Logger: sublogger,
Includes: c.cli.Includes,
Includes: c.opts.Includes,
}); err != nil {
return err
}
}
return nil
})
}(mane)
}(me)
}

return eg.Wait()
Expand Down

0 comments on commit 151a654

Please sign in to comment.