From 589d4e4cf52defaca4b0207609a276cfbdb44431 Mon Sep 17 00:00:00 2001 From: Justin Chadwell Date: Mon, 3 Apr 2023 10:23:59 +0100 Subject: [PATCH 1/2] build: use buildkit's gitutil package to detect remote files BuildKit's gitutil package behaves slightly differently than moby's urlutil, so we should rely on BuildKit's gitutil when detecting URLs to avoid cases of accidentally producing invalid build requests that can confuse users. Signed-off-by: Justin Chadwell --- bake/bake.go | 7 +------ build/build.go | 6 ++---- build/utils.go | 12 ++++++++++++ commands/build.go | 6 +++--- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/bake/bake.go b/bake/bake.go index fc8b9337..c8ec628b 100644 --- a/bake/bake.go +++ b/bake/bake.go @@ -18,7 +18,6 @@ import ( "github.com/docker/buildx/util/buildflags" "github.com/docker/buildx/util/platformutil" "github.com/docker/cli/cli/config" - "github.com/docker/docker/builder/remotecontext/urlutil" hcl "github.com/hashicorp/hcl/v2" "github.com/moby/buildkit/client/llb" "github.com/moby/buildkit/session/auth/authprovider" @@ -884,7 +883,7 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) { dockerfilePath = *t.Dockerfile } - if !isRemoteResource(contextPath) && !path.IsAbs(dockerfilePath) { + if !build.IsRemoteURL(contextPath) && !path.IsAbs(dockerfilePath) { dockerfilePath = path.Join(contextPath, dockerfilePath) } @@ -1040,10 +1039,6 @@ func removeDupes(s []string) []string { return s[:i] } -func isRemoteResource(str string) bool { - return urlutil.IsGitURL(str) || urlutil.IsURL(str) -} - func parseOutputType(str string) string { csvReader := csv.NewReader(strings.NewReader(str)) fields, err := csvReader.Read() diff --git a/build/build.go b/build/build.go index e86c350b..86095371 100644 --- a/build/build.go +++ b/build/build.go @@ -1278,7 +1278,6 @@ func LoadInputs(ctx context.Context, d driver.Driver, inp Inputs, pw progress.Wr target.LocalDirs["context"] = inp.ContextPath } } - case isLocalDir(inp.ContextPath): target.LocalDirs["context"] = inp.ContextPath switch inp.DockerfilePath { @@ -1290,8 +1289,7 @@ func LoadInputs(ctx context.Context, d driver.Driver, inp Inputs, pw progress.Wr dockerfileDir = filepath.Dir(inp.DockerfilePath) dockerfileName = filepath.Base(inp.DockerfilePath) } - - case urlutil.IsGitURL(inp.ContextPath), urlutil.IsURL(inp.ContextPath): + case IsRemoteURL(inp.ContextPath): if inp.DockerfilePath == "-" { dockerfileReader = inp.InStream } @@ -1346,7 +1344,7 @@ func LoadInputs(ctx context.Context, d driver.Driver, inp Inputs, pw progress.Wr continue } - if urlutil.IsGitURL(v.Path) || urlutil.IsURL(v.Path) || strings.HasPrefix(v.Path, "docker-image://") || strings.HasPrefix(v.Path, "target:") { + if IsRemoteURL(v.Path) || strings.HasPrefix(v.Path, "docker-image://") || strings.HasPrefix(v.Path, "target:") { target.FrontendAttrs["context:"+k] = v.Path continue } diff --git a/build/utils.go b/build/utils.go index 58a9a2cd..03a85ca4 100644 --- a/build/utils.go +++ b/build/utils.go @@ -8,6 +8,8 @@ import ( "strings" "github.com/docker/cli/opts" + "github.com/docker/docker/builder/remotecontext/urlutil" + "github.com/moby/buildkit/util/gitutil" "github.com/pkg/errors" ) @@ -20,6 +22,16 @@ const ( mobyHostGatewayName = "host-gateway" ) +func IsRemoteURL(c string) bool { + if urlutil.IsURL(c) { + return true + } + if _, err := gitutil.ParseGitRef(c); err == nil { + return true + } + return false +} + func isLocalDir(c string) bool { st, err := os.Stat(c) return err == nil && st.IsDir() diff --git a/commands/build.go b/commands/build.go index 51532f57..06eeb526 100644 --- a/commands/build.go +++ b/commands/build.go @@ -14,6 +14,7 @@ import ( "strings" "github.com/containerd/console" + "github.com/docker/buildx/build" "github.com/docker/buildx/controller" cbuild "github.com/docker/buildx/controller/build" "github.com/docker/buildx/controller/control" @@ -29,7 +30,6 @@ import ( "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" dockeropts "github.com/docker/cli/opts" - "github.com/docker/docker/builder/remotecontext/urlutil" "github.com/docker/docker/pkg/ioutils" "github.com/moby/buildkit/client" "github.com/moby/buildkit/exporter/containerimage/exptypes" @@ -670,7 +670,7 @@ func dockerUlimitToControllerUlimit(u *dockeropts.UlimitOpt) *controllerapi.Ulim // and replaces them to absolute paths. func resolvePaths(options *controllerapi.BuildOptions) (_ *controllerapi.BuildOptions, err error) { if options.ContextPath != "" && options.ContextPath != "-" { - if !urlutil.IsGitURL(options.ContextPath) && !urlutil.IsURL(options.ContextPath) { + if !build.IsRemoteURL(options.ContextPath) { options.ContextPath, err = filepath.Abs(options.ContextPath) if err != nil { return nil, err @@ -685,7 +685,7 @@ func resolvePaths(options *controllerapi.BuildOptions) (_ *controllerapi.BuildOp } var contexts map[string]string for k, v := range options.NamedContexts { - if urlutil.IsGitURL(v) || urlutil.IsURL(v) || strings.HasPrefix(v, "docker-image://") { + if build.IsRemoteURL(v) || strings.HasPrefix(v, "docker-image://") { // url prefix, this is a remote path } else if strings.HasPrefix(v, "oci-layout://") { // oci layout prefix, this is a local path From 87a120e8e30d7dbca9830a80e73ce76590c909ff Mon Sep 17 00:00:00 2001 From: Justin Chadwell Date: Mon, 3 Apr 2023 10:48:31 +0100 Subject: [PATCH 2/2] bake: use build.IsRemoteURL Signed-off-by: Justin Chadwell --- bake/bake.go | 8 ++++---- bake/remote.go | 10 ---------- commands/bake.go | 4 ++-- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/bake/bake.go b/bake/bake.go index c8ec628b..c5ec48af 100644 --- a/bake/bake.go +++ b/bake/bake.go @@ -789,7 +789,7 @@ func updateContext(t *build.Inputs, inp *Input) { if strings.HasPrefix(v.Path, "cwd://") || strings.HasPrefix(v.Path, "target:") || strings.HasPrefix(v.Path, "docker-image:") { continue } - if IsRemoteURL(v.Path) { + if build.IsRemoteURL(v.Path) { continue } st := llb.Scratch().File(llb.Copy(*inp.State, v.Path, "/"), llb.WithCustomNamef("set context %s to %s", k, v.Path)) @@ -803,7 +803,7 @@ func updateContext(t *build.Inputs, inp *Input) { if strings.HasPrefix(t.ContextPath, "cwd://") { return } - if IsRemoteURL(t.ContextPath) { + if build.IsRemoteURL(t.ContextPath) { return } st := llb.Scratch().File(llb.Copy(*inp.State, t.ContextPath, "/"), llb.WithCustomNamef("set context to %s", t.ContextPath)) @@ -839,7 +839,7 @@ func validateContextsEntitlements(t build.Inputs, inp *Input) error { } func checkPath(p string) error { - if IsRemoteURL(p) || strings.HasPrefix(p, "target:") || strings.HasPrefix(p, "docker-image:") { + if build.IsRemoteURL(p) || strings.HasPrefix(p, "target:") || strings.HasPrefix(p, "docker-image:") { return nil } p, err := filepath.EvalSymlinks(p) @@ -875,7 +875,7 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) { if t.Context != nil { contextPath = *t.Context } - if !strings.HasPrefix(contextPath, "cwd://") && !IsRemoteURL(contextPath) { + if !strings.HasPrefix(contextPath, "cwd://") && !build.IsRemoteURL(contextPath) { contextPath = path.Clean(contextPath) } dockerfilePath := "Dockerfile" diff --git a/bake/remote.go b/bake/remote.go index 939957d0..4574eb7d 100644 --- a/bake/remote.go +++ b/bake/remote.go @@ -83,16 +83,6 @@ func ReadRemoteFiles(ctx context.Context, nodes []builder.Node, url string, name return files, inp, nil } -func IsRemoteURL(url string) bool { - if _, _, ok := detectHTTPContext(url); ok { - return true - } - if _, ok := detectGitContext(url); ok { - return true - } - return false -} - func detectHTTPContext(url string) (*llb.State, string, bool) { if httpPrefix.MatchString(url) { httpContext := llb.HTTP(url, llb.Filename("context"), llb.WithCustomName("[internal] load remote build context")) diff --git a/commands/bake.go b/commands/bake.go index 9c49327e..f66e20c9 100644 --- a/commands/bake.go +++ b/commands/bake.go @@ -47,11 +47,11 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions, cFlags com cmdContext := "cwd://" if len(targets) > 0 { - if bake.IsRemoteURL(targets[0]) { + if build.IsRemoteURL(targets[0]) { url = targets[0] targets = targets[1:] if len(targets) > 0 { - if bake.IsRemoteURL(targets[0]) { + if build.IsRemoteURL(targets[0]) { cmdContext = targets[0] targets = targets[1:] }