build.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. package deploy
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. "strings"
  8. api "github.com/porter-dev/porter/api/client"
  9. "github.com/porter-dev/porter/api/types"
  10. "github.com/porter-dev/porter/cli/cmd/docker"
  11. "github.com/porter-dev/porter/cli/cmd/pack"
  12. )
  13. // BuildAgent builds a new Docker container image for a new version of an application
  14. type BuildAgent struct {
  15. *SharedOpts
  16. APIClient api.Client
  17. ImageRepo string
  18. Env map[string]string
  19. ImageExists bool
  20. }
  21. // BuildDocker uses the local Docker daemon to build the image
  22. func (b *BuildAgent) BuildDocker(
  23. ctx context.Context,
  24. dockerAgent *docker.Agent,
  25. basePath,
  26. buildCtx,
  27. dockerfilePath,
  28. tag string,
  29. currentTag string,
  30. ) error {
  31. buildCtx, dockerfilePath, isDockerfileInCtx, err := ResolveDockerPaths(
  32. basePath,
  33. buildCtx,
  34. dockerfilePath,
  35. )
  36. if err != nil {
  37. return err
  38. }
  39. opts := &docker.BuildOpts{
  40. ImageRepo: b.ImageRepo,
  41. Tag: tag,
  42. CurrentTag: currentTag,
  43. BuildContext: buildCtx,
  44. Env: b.Env,
  45. DockerfilePath: dockerfilePath,
  46. IsDockerfileInCtx: isDockerfileInCtx,
  47. UseCache: b.UseCache,
  48. }
  49. return dockerAgent.BuildLocal(
  50. ctx,
  51. opts,
  52. )
  53. }
  54. // BuildPack uses the cloud-native buildpack client to build a container image
  55. func (b *BuildAgent) BuildPack(ctx context.Context, dockerAgent *docker.Agent, dst, tag, prevTag string, buildConfig *types.BuildConfig) error {
  56. // retag the image with "pack-cache" tag so that it doesn't re-pull from the registry
  57. if b.ImageExists {
  58. err := dockerAgent.TagImage(
  59. ctx,
  60. fmt.Sprintf("%s:%s", b.ImageRepo, prevTag),
  61. fmt.Sprintf("%s:%s", b.ImageRepo, "pack-cache"),
  62. )
  63. if err != nil {
  64. return err
  65. }
  66. }
  67. // create pack agent and build opts
  68. packAgent := &pack.Agent{}
  69. opts := &docker.BuildOpts{
  70. ImageRepo: b.ImageRepo,
  71. Tag: tag,
  72. BuildContext: dst,
  73. Env: b.Env,
  74. UseCache: b.UseCache,
  75. }
  76. // call builder
  77. return packAgent.Build(ctx, opts, buildConfig, fmt.Sprintf("%s:%s", b.ImageRepo, "pack-cache"))
  78. }
  79. // ResolveDockerPaths returns a path to the dockerfile that is either relative or absolute, and a path
  80. // to the build context that is absolute.
  81. //
  82. // The return value will be relative if the dockerfile exists within the build context, absolute
  83. // otherwise. The second return value is true if the dockerfile exists within the build context,
  84. // false otherwise.
  85. func ResolveDockerPaths(
  86. basePath string,
  87. buildContextPath string,
  88. dockerfilePath string,
  89. ) (
  90. resBuildCtxPath string,
  91. resDockerfilePath string,
  92. isDockerfileRelative bool,
  93. err error,
  94. ) {
  95. resBuildCtxPath, err = filepath.Abs(buildContextPath)
  96. resDockerfilePath = dockerfilePath
  97. // determine if the given dockerfile path is relative
  98. if !filepath.IsAbs(dockerfilePath) {
  99. // if path is relative, join basepath with path
  100. resDockerfilePath = filepath.Join(basePath, dockerfilePath)
  101. }
  102. // compare the path to the dockerfile with the build context
  103. pathComp, err := filepath.Rel(resBuildCtxPath, resDockerfilePath)
  104. if err != nil {
  105. return "", "", false, err
  106. }
  107. if !strings.HasPrefix(pathComp, ".."+string(os.PathSeparator)) {
  108. // return the relative path to the dockerfile
  109. return resBuildCtxPath, pathComp, true, nil
  110. }
  111. resDockerfilePath, err = filepath.Abs(resDockerfilePath)
  112. if err != nil {
  113. return "", "", false, err
  114. }
  115. return resBuildCtxPath, resDockerfilePath, false, nil
  116. }