Skip to content

Commit

Permalink
add global flag to define download directory for remote configuration…
Browse files Browse the repository at this point in the history
… (oci & git)

Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
  • Loading branch information
glours committed Feb 3, 2025
1 parent 4db5fcd commit ee59ba3
Showing 5 changed files with 92 additions and 22 deletions.
23 changes: 21 additions & 2 deletions cmd/compose/compose.go
Original file line number Diff line number Diff line change
@@ -150,6 +150,7 @@ type ProjectOptions struct {
Progress string
Offline bool
All bool
DownloadDir string
}

// ProjectFunc does stuff within a types.Project
@@ -226,7 +227,9 @@ func (o *ProjectOptions) addProjectFlags(f *pflag.FlagSet) {
f.BoolVar(&o.Compatibility, "compatibility", false, "Run compose in backward compatibility mode")
f.StringVar(&o.Progress, "progress", string(buildkit.AutoMode), fmt.Sprintf(`Set type of progress output (%s)`, strings.Join(printerModes, ", ")))
f.BoolVar(&o.All, "all-resources", false, "Include all resources, even those not used by services")
f.StringVar(&o.DownloadDir, "download-dir", "", "Directory to store OCI or GIT Compose configurations")
_ = f.MarkHidden("workdir")
_ = f.MarkHidden("download-dir")
}

// get default value for a command line flag that is set by a coma-separated value in environment variable
@@ -372,8 +375,8 @@ func (o *ProjectOptions) remoteLoaders(dockerCli command.Cli) []loader.ResourceL
if o.Offline {
return nil
}
git := remote.NewGitRemoteLoader(o.Offline)
oci := remote.NewOCIRemoteLoader(dockerCli, o.Offline)
git := remote.NewGitRemoteLoader(o.Offline, o.DownloadDir)
oci := remote.NewOCIRemoteLoader(dockerCli, o.Offline, o.DownloadDir)
return []loader.ResourceLoader{git, oci}
}

@@ -537,6 +540,22 @@ func RootCommand(dockerCli command.Cli, backend Backend) *cobra.Command { //noli
}
}

if opts.DownloadDir != "" {
if len(opts.ConfigPaths) == 0 {
return fmt.Errorf("cannot use --download-dir without --file using oci:// or git:// prefix")
}
remoteResources := false
for _, file := range opts.ConfigPaths {
if strings.HasPrefix(file, "oci://") || strings.HasPrefix(file, "git://") {
remoteResources = true
break
}
}
if !remoteResources {
return fmt.Errorf("cannot use --download-dir without --file using oci:// or git:// prefix")
}
}

composeCmd := cmd
for {
if composeCmd.Name() == PluginName {
9 changes: 9 additions & 0 deletions docs/reference/docker_compose.yaml
Original file line number Diff line number Diff line change
@@ -102,6 +102,15 @@ options:
experimentalcli: false
kubernetes: false
swarm: false
- option: download-dir
value_type: string
description: Directory to store OCI or GIT Compose configurations
deprecated: false
hidden: true
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: dry-run
value_type: bool
default_value: "false"
20 changes: 20 additions & 0 deletions internal/paths/paths.go
Original file line number Diff line number Diff line change
@@ -118,3 +118,23 @@ func EncompassingPaths(paths []string) []string {
}
return result
}

func GetAbsPath(path string) (string, error) {
if filepath.IsAbs(path) {
return path, nil
}

if strings.HasPrefix(path, "~") {
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Join(home, path[1:]), nil
}

wd, err := os.Getwd()
if err != nil {
return "", err
}
return filepath.Join(wd, path), nil
}
30 changes: 21 additions & 9 deletions pkg/remote/git.go
Original file line number Diff line number Diff line change
@@ -25,6 +25,8 @@ import (
"regexp"
"strconv"

"github.com/docker/compose/v2/internal/paths"

"github.com/compose-spec/compose-go/v2/cli"
"github.com/compose-spec/compose-go/v2/loader"
"github.com/compose-spec/compose-go/v2/types"
@@ -45,16 +47,18 @@ func gitRemoteLoaderEnabled() (bool, error) {
return false, nil
}

func NewGitRemoteLoader(offline bool) loader.ResourceLoader {
func NewGitRemoteLoader(offline bool, downloadDirectory string) loader.ResourceLoader {
return gitRemoteLoader{
offline: offline,
known: map[string]string{},
offline: offline,
known: map[string]string{},
downloadDirectory: downloadDirectory,
}
}

type gitRemoteLoader struct {
offline bool
known map[string]string
offline bool
known map[string]string
downloadDirectory string
}

func (g gitRemoteLoader) Accept(path string) bool {
@@ -89,12 +93,20 @@ func (g gitRemoteLoader) Load(ctx context.Context, path string) (string, error)
return "", err
}

cache, err := cacheDir()
if err != nil {
return "", fmt.Errorf("initializing remote resource cache: %w", err)
if local == "" {
cache, err := cacheDir()
if err != nil {
return "", fmt.Errorf("initializing remote resource cache: %w", err)
}
local = cache
} else {
local, err = paths.GetAbsPath(g.downloadDirectory)
if err != nil {
return "", err
}
}

local = filepath.Join(cache, ref.Commit)
local = filepath.Join(local, ref.Commit)
if _, err := os.Stat(local); os.IsNotExist(err) {
if g.offline {
return "", nil
32 changes: 21 additions & 11 deletions pkg/remote/oci.go
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@ import (
"github.com/docker/buildx/util/imagetools"
"github.com/docker/cli/cli/command"
"github.com/docker/compose/v2/internal/ocipush"
"github.com/docker/compose/v2/internal/paths"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
)

@@ -47,18 +48,20 @@ func ociRemoteLoaderEnabled() (bool, error) {
return false, nil
}

func NewOCIRemoteLoader(dockerCli command.Cli, offline bool) loader.ResourceLoader {
func NewOCIRemoteLoader(dockerCli command.Cli, offline bool, downloadDirectory string) loader.ResourceLoader {
return ociRemoteLoader{
dockerCli: dockerCli,
offline: offline,
known: map[string]string{},
dockerCli: dockerCli,
offline: offline,
downloadDirectory: downloadDirectory,
known: map[string]string{},
}
}

type ociRemoteLoader struct {
dockerCli command.Cli
offline bool
known map[string]string
dockerCli command.Cli
offline bool
known map[string]string
downloadDirectory string
}

const prefix = "oci://"
@@ -98,12 +101,19 @@ func (g ociRemoteLoader) Load(ctx context.Context, path string) (string, error)
return "", err
}

cache, err := cacheDir()
if err != nil {
return "", fmt.Errorf("initializing remote resource cache: %w", err)
if local == "" {
cache, err := cacheDir()
if err != nil {
return "", fmt.Errorf("initializing remote resource cache: %w", err)
}
local = filepath.Join(cache, descriptor.Digest.Hex())
} else {
local, err = paths.GetAbsPath(g.downloadDirectory)
if err != nil {
return "", err
}
}

local = filepath.Join(cache, descriptor.Digest.Hex())
composeFile := filepath.Join(local, "compose.yaml")
if _, err = os.Stat(local); os.IsNotExist(err) {
var manifest v1.Manifest

0 comments on commit ee59ba3

Please sign in to comment.