فهرست منبع

clean up implementation of path resolving

Alexander Belanger 4 سال پیش
والد
کامیت
1803bfa105
4فایلهای تغییر یافته به همراه108 افزوده شده و 50 حذف شده
  1. 69 11
      cli/cmd/deploy/build.go
  2. 1 1
      cli/cmd/deploy/create.go
  3. 16 22
      cli/cmd/deploy/deploy.go
  4. 22 16
      cli/cmd/docker/builder.go

+ 69 - 11
cli/cmd/deploy/build.go

@@ -2,7 +2,9 @@ package deploy
 
 import (
 	"fmt"
+	"os"
 	"path/filepath"
+	"strings"
 
 	"github.com/porter-dev/porter/cli/cmd/api"
 	"github.com/porter-dev/porter/cli/cmd/docker"
@@ -20,24 +22,34 @@ type BuildAgent struct {
 }
 
 // BuildDocker uses the local Docker daemon to build the image
-func (b *BuildAgent) BuildDocker(dockerAgent *docker.Agent, buildCtx, tag string) error {
-	opts := &docker.BuildOpts{
-		ImageRepo:    b.imageRepo,
-		Tag:          tag,
-		BuildContext: buildCtx,
-		Env:          b.env,
-	}
-
-	// use the absolute path to the dockerfile
-	localDockerfileAbs, err := filepath.Abs(b.LocalDockerfile)
+func (b *BuildAgent) BuildDocker(
+	dockerAgent *docker.Agent,
+	basePath,
+	buildCtx,
+	dockerfilePath,
+	tag string,
+) error {
+	buildCtx, dockerfilePath, isDockerfileInCtx, err := ResolveDockerPaths(
+		basePath,
+		buildCtx,
+		dockerfilePath,
+	)
 
 	if err != nil {
 		return err
 	}
 
+	opts := &docker.BuildOpts{
+		ImageRepo:         b.imageRepo,
+		Tag:               tag,
+		BuildContext:      buildCtx,
+		Env:               b.env,
+		DockerfilePath:    dockerfilePath,
+		IsDockerfileInCtx: isDockerfileInCtx,
+	}
+
 	return dockerAgent.BuildLocal(
 		opts,
-		localDockerfileAbs,
 	)
 }
 
@@ -80,3 +92,49 @@ func (b *BuildAgent) BuildPack(dockerAgent *docker.Agent, dst, tag string) error
 		fmt.Sprintf("%s:%s", b.imageRepo, tag),
 	)
 }
+
+// ResolveDockerPaths returns a path to the dockerfile that is either relative or absolute, and a path
+// to the build context that is absolute.
+//
+// The return value will be relative if the dockerfile exists within the build context, absolute
+// otherwise. The second return value is true if the dockerfile exists within the build context,
+// false otherwise.
+func ResolveDockerPaths(
+	basePath string,
+	buildContextPath string,
+	dockerfilePath string,
+) (
+	resBuildCtxPath string,
+	resDockerfilePath string,
+	isDockerfileRelative bool,
+	err error,
+) {
+	resBuildCtxPath, err = filepath.Abs(buildContextPath)
+	resDockerfilePath = dockerfilePath
+
+	// determine if the given dockerfile path is relative
+	if !filepath.IsAbs(dockerfilePath) {
+		// if path is relative, join basepath with path
+		resDockerfilePath = filepath.Join(basePath, dockerfilePath)
+	}
+
+	// compare the path to the dockerfile with the build context
+	pathComp, err := filepath.Rel(resBuildCtxPath, resDockerfilePath)
+
+	if err != nil {
+		return "", "", false, err
+	}
+
+	if !strings.HasPrefix(pathComp, ".."+string(os.PathSeparator)) {
+		// return the relative path to the dockerfile
+		return resBuildCtxPath, pathComp, true, nil
+	}
+
+	resDockerfilePath, err = filepath.Abs(resDockerfilePath)
+
+	if err != nil {
+		return "", "", false, err
+	}
+
+	return resBuildCtxPath, resDockerfilePath, false, nil
+}

+ 1 - 1
cli/cmd/deploy/create.go

@@ -279,7 +279,7 @@ func (c *CreateAgent) CreateFromDocker(
 	}
 
 	if opts.Method == DeployBuildTypeDocker {
-		err = buildAgent.BuildDocker(agent, opts.LocalPath, "latest")
+		err = buildAgent.BuildDocker(agent, opts.LocalPath, ".", opts.LocalDockerfile, "latest")
 	} else {
 		err = buildAgent.BuildPack(agent, opts.LocalPath, "latest")
 	}

+ 16 - 22
cli/cmd/deploy/deploy.go

@@ -193,8 +193,8 @@ func (d *DeployAgent) WriteBuildEnv(fileDest string) error {
 // buildpack or docker.
 func (d *DeployAgent) Build() error {
 	// if build is not local, fetch remote source
-	var dst string
-	var buildCtx string
+	var basePath string
+	buildCtx := d.opts.LocalPath
 	var err error
 
 	if !d.opts.Local {
@@ -209,25 +209,22 @@ func (d *DeployAgent) Build() error {
 		}
 
 		// download the repository from remote source into a temp directory
-		dst, err = d.downloadRepoToDir(zipResp.URLString)
+		basePath, err = d.downloadRepoToDir(zipResp.URLString)
+
+		if err != nil {
+			return err
+		}
 
 		if d.tag == "" {
 			shortRef := fmt.Sprintf("%.7s", zipResp.LatestCommitSHA)
 			d.tag = shortRef
 		}
+	} else {
+		basePath, err = filepath.Abs(".")
 
 		if err != nil {
 			return err
 		}
-
-		// if the local path is set it must be a relative path, so create a filepath with the dst
-		// and the relative path
-		if d.opts.LocalPath != "" {
-			buildCtx = filepath.Join(dst, d.opts.LocalPath)
-		}
-	} else {
-		dst = filepath.Dir(d.opts.LocalPath)
-		buildCtx = filepath.Dir(d.opts.LocalPath)
 	}
 
 	if d.tag == "" {
@@ -255,16 +252,13 @@ func (d *DeployAgent) Build() error {
 	}
 
 	if d.opts.Method == DeployBuildTypeDocker {
-		var dockerfilePath string
-
-		// if the dockerfile path is set it must also be a relative path
-		if !d.opts.Local && d.dockerfilePath != "" {
-			dockerfilePath = filepath.Join(dst, d.dockerfilePath)
-		}
-
-		buildAgent.SharedOpts.LocalDockerfile = dockerfilePath
-
-		return buildAgent.BuildDocker(d.agent, buildCtx, d.tag)
+		return buildAgent.BuildDocker(
+			d.agent,
+			basePath,
+			buildCtx,
+			d.dockerfilePath,
+			d.tag,
+		)
 	}
 
 	return buildAgent.BuildPack(d.agent, buildCtx, d.tag)

+ 22 - 16
cli/cmd/docker/builder.go

@@ -19,33 +19,39 @@ import (
 )
 
 type BuildOpts struct {
-	ImageRepo    string
-	Tag          string
-	BuildContext string
-	Env          map[string]string
+	ImageRepo         string
+	Tag               string
+	BuildContext      string
+	DockerfilePath    string
+	IsDockerfileInCtx bool
+
+	Env map[string]string
 }
 
 // BuildLocal
-func (a *Agent) BuildLocal(opts *BuildOpts, dockerfilePath string) error {
-	tarBuildContext, err := archive.TarWithOptions(opts.BuildContext, &archive.TarOptions{})
+func (a *Agent) BuildLocal(opts *BuildOpts) error {
+	dockerfilePath := opts.DockerfilePath
+	tar, err := archive.TarWithOptions(opts.BuildContext, &archive.TarOptions{})
 
 	if err != nil {
 		return err
 	}
 
-	dockerfileCtx, err := os.Open(dockerfilePath)
+	if !opts.IsDockerfileInCtx {
+		dockerfileCtx, err := os.Open(dockerfilePath)
 
-	if err != nil {
-		return errors.Errorf("unable to open Dockerfile: %v", err)
-	}
+		if err != nil {
+			return errors.Errorf("unable to open Dockerfile: %v", err)
+		}
 
-	defer dockerfileCtx.Close()
+		defer dockerfileCtx.Close()
 
-	// add the dockerfile to the build context
-	tar, relPath, err := AddDockerfileToBuildContext(dockerfileCtx, tarBuildContext)
+		// add the dockerfile to the build context
+		tar, dockerfilePath, err = AddDockerfileToBuildContext(dockerfileCtx, tar)
 
-	if err != nil {
-		return err
+		if err != nil {
+			return err
+		}
 	}
 
 	buildArgs := make(map[string]*string)
@@ -56,7 +62,7 @@ func (a *Agent) BuildLocal(opts *BuildOpts, dockerfilePath string) error {
 	}
 
 	out, err := a.client.ImageBuild(context.Background(), tar, types.ImageBuildOptions{
-		Dockerfile: relPath,
+		Dockerfile: dockerfilePath,
 		BuildArgs:  buildArgs,
 		Tags: []string{
 			fmt.Sprintf("%s:%s", opts.ImageRepo, opts.Tag),