From 3c83697344fd063b10c2d50d9e1384322b3d6b10 Mon Sep 17 00:00:00 2001 From: Yousef Haggy Date: Mon, 12 Jul 2021 21:50:36 -0400 Subject: [PATCH] Refactor DownloadBuildpack to use dependency injection strategy and add tests --- build.go | 8 +- buildpack_downloader.go | 109 ++++ buildpack_downloader_test.go | 457 +++++++++++++++++ client.go | 38 +- common.go | 2 +- create_builder.go | 86 +--- create_builder_test.go | 479 +++--------------- inspect_builder.go | 2 +- inspect_builder_test.go | 2 +- inspect_buildpack.go | 4 +- inspect_buildpack_test.go | 2 +- inspect_image.go | 2 +- inspect_image_test.go | 2 +- .../builder/fakes/fake_inspectable_fetcher.go | 2 +- internal/builder/image_fetcher_wrapper.go | 2 +- internal/builder/inspect.go | 2 +- internal/commands/buildpack_inspect_test.go | 2 +- internal/commands/inspect_buildpack_test.go | 2 +- internal/fakes/fake_image_fetcher.go | 2 +- {image => internal/image}/factory.go | 0 {image => internal/image}/fetcher.go | 0 {image => internal/image}/fetcher_test.go | 2 +- mock_buildpack_downloader.go | 52 ++ pack.go | 7 +- package_buildpack.go | 9 +- package_buildpack_test.go | 2 +- pull_buildpack.go | 4 +- pull_buildpack_test.go | 2 +- rebase.go | 2 +- register_buildpack.go | 4 +- testmocks/mock_image_fetcher.go | 2 +- 31 files changed, 750 insertions(+), 541 deletions(-) create mode 100644 buildpack_downloader.go create mode 100644 buildpack_downloader_test.go rename {image => internal/image}/factory.go (100%) rename {image => internal/image}/fetcher.go (100%) rename {image => internal/image}/fetcher_test.go (99%) create mode 100644 mock_buildpack_downloader.go diff --git a/build.go b/build.go index 27eb1bf1a2..01f50a5293 100644 --- a/build.go +++ b/build.go @@ -20,7 +20,6 @@ import ( ignore "github.com/sabhiram/go-gitignore" "github.com/buildpacks/pack/config" - "github.com/buildpacks/pack/image" "github.com/buildpacks/pack/internal/blob" "github.com/buildpacks/pack/internal/build" "github.com/buildpacks/pack/internal/builder" @@ -28,6 +27,7 @@ import ( "github.com/buildpacks/pack/internal/buildpackage" internalConfig "github.com/buildpacks/pack/internal/config" "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/image" "github.com/buildpacks/pack/internal/layer" "github.com/buildpacks/pack/internal/paths" "github.com/buildpacks/pack/internal/stack" @@ -717,7 +717,7 @@ func (c *Client) processBuildpacks(ctx context.Context, builderImage imgutil.Ima order = appendBuildpackToOrder(order, mainBP.Descriptor().Info) case buildpack.PackageLocator: imageName := buildpack.ParsePackageLocator(bp) - mainBP, depBPs, err := extractPackagedBuildpacks(ctx, imageName, c.imageFetcher, image.FetchOptions{Daemon: !publish, PullPolicy: pullPolicy}) + mainBP, depBPs, err := extractPackagedBuildpacks(ctx, imageName, c.imageFetcher, !publish, pullPolicy) if err != nil { return fetchedBPs, order, errors.Wrapf(err, "creating from buildpackage %s", style.Symbol(bp)) } @@ -725,7 +725,7 @@ func (c *Client) processBuildpacks(ctx context.Context, builderImage imgutil.Ima fetchedBPs = append(append(fetchedBPs, mainBP), depBPs...) order = appendBuildpackToOrder(order, mainBP.Descriptor().Info) case buildpack.RegistryLocator: - registryCache, err := c.getRegistry(c.logger, registry) + registryCache, err := getRegistry(c.logger, registry) if err != nil { return fetchedBPs, order, errors.Wrapf(err, "invalid registry '%s'", registry) } @@ -735,7 +735,7 @@ func (c *Client) processBuildpacks(ctx context.Context, builderImage imgutil.Ima return fetchedBPs, order, errors.Wrapf(err, "locating in registry %s", style.Symbol(bp)) } - mainBP, depBPs, err := extractPackagedBuildpacks(ctx, registryBp.Address, c.imageFetcher, image.FetchOptions{Daemon: !publish, PullPolicy: pullPolicy}) + mainBP, depBPs, err := extractPackagedBuildpacks(ctx, registryBp.Address, c.imageFetcher, !publish, pullPolicy) if err != nil { return fetchedBPs, order, errors.Wrapf(err, "extracting from registry %s", style.Symbol(bp)) } diff --git a/buildpack_downloader.go b/buildpack_downloader.go new file mode 100644 index 0000000000..e6751a983f --- /dev/null +++ b/buildpack_downloader.go @@ -0,0 +1,109 @@ +package pack + +import ( + "context" + "fmt" + + "github.com/buildpacks/pack/config" + "github.com/buildpacks/pack/internal/buildpack" + "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/paths" + "github.com/buildpacks/pack/internal/style" + "github.com/buildpacks/pack/logging" + "github.com/pkg/errors" +) + +type buildpackDownloader struct { + logger logging.Logger + imageFetcher ImageFetcher + downloader Downloader +} + +func NewBuildpackDownloader(logger logging.Logger, imageFetcher ImageFetcher, downloader Downloader) *buildpackDownloader { //nolint:golint,gosimple + return &buildpackDownloader{ + logger: logger, + imageFetcher: imageFetcher, + downloader: downloader, + } +} + +type BuildpackDownloadOptions struct { + // Buildpack registry name. Defines where all registry buildpacks will be pulled from. + RegistryName string + + // The base directory to use to resolve relative assets + RelativeBaseDir string + + // The OS of the builder image + ImageOS string + + // Deprecated, the older alternative to buildpack URI + ImageName string + + Daemon bool + + PullPolicy config.PullPolicy +} + +func (c *buildpackDownloader) Download(ctx context.Context, buildpackURI string, opts BuildpackDownloadOptions) (dist.Buildpack, []dist.Buildpack, error) { + var err error + var locatorType buildpack.LocatorType + if buildpackURI == "" && opts.ImageName != "" { + c.logger.Warn("The 'image' key is deprecated. Use 'uri=\"docker://...\"' instead.") + buildpackURI = opts.ImageName + locatorType = buildpack.PackageLocator + } else { + locatorType, err = buildpack.GetLocatorType(buildpackURI, opts.RelativeBaseDir, []dist.BuildpackInfo{}) + if err != nil { + return nil, nil, err + } + } + + var mainBP dist.Buildpack + var depBPs []dist.Buildpack + switch locatorType { + case buildpack.PackageLocator: + imageName := buildpack.ParsePackageLocator(buildpackURI) + c.logger.Debugf("Downloading buildpack from image: %s", style.Symbol(imageName)) + mainBP, depBPs, err = extractPackagedBuildpacks(ctx, imageName, c.imageFetcher, opts.Daemon, opts.PullPolicy) + if err != nil { + return nil, nil, errors.Wrapf(err, "extracting from registry %s", style.Symbol(buildpackURI)) + } + case buildpack.RegistryLocator: + c.logger.Debugf("Downloading buildpack from registry: %s", style.Symbol(buildpackURI)) + registryCache, err := getRegistry(c.logger, opts.RegistryName) + if err != nil { + return nil, nil, errors.Wrapf(err, "invalid registry '%s'", opts.RegistryName) + } + + registryBp, err := registryCache.LocateBuildpack(buildpackURI) + if err != nil { + return nil, nil, errors.Wrapf(err, "locating in registry %s", style.Symbol(buildpackURI)) + } + + mainBP, depBPs, err = extractPackagedBuildpacks(ctx, registryBp.Address, c.imageFetcher, opts.Daemon, opts.PullPolicy) + if err != nil { + return nil, nil, errors.Wrapf(err, "extracting from registry %s", style.Symbol(buildpackURI)) + } + case buildpack.URILocator: + buildpackURI, err = paths.FilePathToURI(buildpackURI, opts.RelativeBaseDir) + if err != nil { + return nil, nil, errors.Wrapf(err, "making absolute: %s", style.Symbol(buildpackURI)) + } + + c.logger.Debugf("Downloading buildpack from URI: %s", style.Symbol(buildpackURI)) + + blob, err := c.downloader.Download(ctx, buildpackURI) + if err != nil { + return nil, nil, errors.Wrapf(err, "downloading buildpack from %s", style.Symbol(buildpackURI)) + } + + mainBP, depBPs, err = decomposeBuildpack(blob, opts.ImageOS) + if err != nil { + return nil, nil, errors.Wrapf(err, "extracting from %s", style.Symbol(buildpackURI)) + } + default: + return nil, nil, fmt.Errorf("error reading %s: invalid locator: %s", buildpackURI, locatorType) + } + return mainBP, depBPs, nil +} diff --git a/buildpack_downloader_test.go b/buildpack_downloader_test.go new file mode 100644 index 0000000000..b71e78f6c1 --- /dev/null +++ b/buildpack_downloader_test.go @@ -0,0 +1,457 @@ +package pack_test + +import ( + "bytes" + "context" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "testing" + + "github.com/buildpacks/imgutil/fakes" + "github.com/buildpacks/lifecycle/api" + "github.com/docker/docker/api/types" + "github.com/golang/mock/gomock" + "github.com/heroku/color" + "github.com/pkg/errors" + "github.com/sclevine/spec" + "github.com/sclevine/spec/report" + + "github.com/buildpacks/pack" + pubbldpkg "github.com/buildpacks/pack/buildpackage" + "github.com/buildpacks/pack/config" + "github.com/buildpacks/pack/internal/blob" + cfg "github.com/buildpacks/pack/internal/config" + "github.com/buildpacks/pack/internal/dist" + ifakes "github.com/buildpacks/pack/internal/fakes" + image "github.com/buildpacks/pack/internal/image" + ilogging "github.com/buildpacks/pack/internal/logging" + "github.com/buildpacks/pack/internal/paths" + "github.com/buildpacks/pack/logging" + h "github.com/buildpacks/pack/testhelpers" + "github.com/buildpacks/pack/testmocks" +) + +func TestBuildpackDownloader(t *testing.T) { + color.Disable(true) + defer color.Disable(false) + spec.Run(t, "BuildpackDownloader", testBuildpackDownloader, spec.Parallel(), spec.Report(report.Terminal{})) +} +func testBuildpackDownloader(t *testing.T, when spec.G, it spec.S) { + var ( + mockController *gomock.Controller + mockDownloader *testmocks.MockDownloader + mockImageFactory *testmocks.MockImageFactory + mockImageFetcher *testmocks.MockImageFetcher + mockDockerClient *testmocks.MockCommonAPIClient + subject *pack.Client + buildpackDownloader pack.BuildpackDownloader + logger logging.Logger + out bytes.Buffer + tmpDir string + ) + var createBuildpack = func(descriptor dist.BuildpackDescriptor) string { + bp, err := ifakes.NewFakeBuildpackBlob(descriptor, 0644) + h.AssertNil(t, err) + url := fmt.Sprintf("https://example.com/bp.%s.tgz", h.RandString(12)) + mockDownloader.EXPECT().Download(gomock.Any(), url).Return(bp, nil).AnyTimes() + return url + } + + var createPackage = func(imageName string) *fakes.Image { + packageImage := fakes.NewImage(imageName, "", nil) + mockImageFactory.EXPECT().NewImage(packageImage.Name(), false, "linux").Return(packageImage, nil) + + h.AssertNil(t, subject.PackageBuildpack(context.TODO(), pack.PackageBuildpackOptions{ + Name: packageImage.Name(), + Config: pubbldpkg.Config{ + Platform: dist.Platform{OS: "linux"}, + Buildpack: dist.BuildpackURI{URI: createBuildpack(dist.BuildpackDescriptor{ + API: api.MustParse("0.3"), + Info: dist.BuildpackInfo{ID: "example/foo", Version: "1.1.0"}, + Stacks: []dist.Stack{{ID: "some.stack.id"}}, + })}, + }, + Publish: true, + })) + + return packageImage + } + it.Before(func() { + logger = ilogging.NewLogWithWriters(&out, &out, ilogging.WithVerbose()) + mockController = gomock.NewController(t) + mockDownloader = testmocks.NewMockDownloader(mockController) + mockImageFetcher = testmocks.NewMockImageFetcher(mockController) + mockImageFactory = testmocks.NewMockImageFactory(mockController) + mockDockerClient = testmocks.NewMockCommonAPIClient(mockController) + mockDownloader.EXPECT().Download(gomock.Any(), "https://example.fake/bp-one.tgz").Return(blob.NewBlob(filepath.Join("testdata", "buildpack")), nil).AnyTimes() + mockDownloader.EXPECT().Download(gomock.Any(), "some/buildpack/dir").Return(blob.NewBlob(filepath.Join("testdata", "buildpack")), nil).AnyTimes() + var err error + subject, err = pack.NewClient( + pack.WithLogger(logger), + pack.WithDownloader(mockDownloader), + pack.WithImageFactory(mockImageFactory), + pack.WithFetcher(mockImageFetcher), + pack.WithDockerClient(mockDockerClient), + ) + h.AssertNil(t, err) + + buildpackDownloader = pack.NewBuildpackDownloader(logger, mockImageFetcher, mockDownloader) + + mockDockerClient.EXPECT().Info(context.TODO()).Return(types.Info{OSType: "linux"}, nil).AnyTimes() + + tmpDir, err = ioutil.TempDir("", "buildpack-downloader-test") + h.AssertNil(t, err) + }) + + it.After(func() { + mockController.Finish() + h.AssertNil(t, os.RemoveAll(tmpDir)) + }) + + when("#DownloadBuildpack", func() { + var ( + packageImage *fakes.Image + ) + + shouldFetchPackageImageWith := func(demon bool, pull config.PullPolicy) { + mockImageFetcher.EXPECT().Fetch(gomock.Any(), packageImage.Name(), image.FetchOptions{Daemon: demon, PullPolicy: pull}).Return(packageImage, nil) + } + + var buildpackDownloadOptions pack.BuildpackDownloadOptions = pack.BuildpackDownloadOptions{ImageOS: "linux"} + when("package image lives in cnb registry", func() { + var ( + registryFixture string + packHome string + tmpDir string + ) + it.Before(func() { + var err error + tmpDir, err = ioutil.TempDir("", "registry") + h.AssertNil(t, err) + + packHome = filepath.Join(tmpDir, ".pack") + err = os.MkdirAll(packHome, 0755) + h.AssertNil(t, err) + os.Setenv("PACK_HOME", packHome) + + registryFixture = h.CreateRegistryFixture(t, tmpDir, filepath.Join("testdata", "registry")) + + packageImage = createPackage("example.com/some/package@sha256:74eb48882e835d8767f62940d453eb96ed2737de3a16573881dcea7dea769df7") + }) + it.After(func() { + os.Unsetenv("PACK_HOME") + err := os.RemoveAll(tmpDir) + h.AssertNil(t, err) + }) + when("daemon=true and pull-policy=always", func() { + var configPath string + + it("should pull and use local package image", func() { + packHome := filepath.Join(tmpDir, "packHome") + h.AssertNil(t, os.Setenv("PACK_HOME", packHome)) + configPath = filepath.Join(packHome, "config.toml") + h.AssertNil(t, cfg.Write(cfg.Config{ + Registries: []cfg.Registry{ + { + Name: "some-registry", + Type: "github", + URL: registryFixture, + }, + }, + }, configPath)) + buildpackDownloadOptions = pack.BuildpackDownloadOptions{ + RegistryName: "some-registry", + ImageOS: "linux", + Daemon: true, + PullPolicy: config.PullAlways, + } + + shouldFetchPackageImageWith(true, config.PullAlways) + mainBP, _, err := buildpackDownloader.Download(context.TODO(), "urn:cnb:registry:example/foo@1.1.0", buildpackDownloadOptions) + h.AssertNil(t, err) + h.AssertEq(t, mainBP.Descriptor().Info.ID, "example/foo") + }) + }) + when("ambigious URI provided", func() { + var configPath string + + it("should find package in registry", func() { + packHome := filepath.Join(tmpDir, "packHome") + h.AssertNil(t, os.Setenv("PACK_HOME", packHome)) + configPath = filepath.Join(packHome, "config.toml") + h.AssertNil(t, cfg.Write(cfg.Config{ + Registries: []cfg.Registry{ + { + Name: "some-registry", + Type: "github", + URL: registryFixture, + }, + }, + }, configPath)) + + buildpackDownloadOptions = pack.BuildpackDownloadOptions{ + RegistryName: "some-registry", + ImageOS: "linux", + Daemon: true, + PullPolicy: config.PullAlways, + } + + shouldFetchPackageImageWith(true, config.PullAlways) + mainBP, _, err := buildpackDownloader.Download(context.TODO(), "example/foo@1.1.0", buildpackDownloadOptions) + h.AssertNil(t, err) + h.AssertEq(t, mainBP.Descriptor().Info.ID, "example/foo") + }) + }) + }) + + when("package image lives in docker registry", func() { + it.Before(func() { + packageImage = fakes.NewImage("docker.io/some/package-"+h.RandString(12), "", nil) + mockImageFactory.EXPECT().NewImage(packageImage.Name(), false, "linux").Return(packageImage, nil) + + bpd := dist.BuildpackDescriptor{ + API: api.MustParse("0.3"), + Info: dist.BuildpackInfo{ID: "some.pkg.bp", Version: "2.3.4", Homepage: "http://meta.buildpack"}, + Stacks: []dist.Stack{{ID: "some.stack.id"}}, + } + + h.AssertNil(t, subject.PackageBuildpack(context.TODO(), pack.PackageBuildpackOptions{ + Name: packageImage.Name(), + Config: pubbldpkg.Config{ + Platform: dist.Platform{OS: "linux"}, + Buildpack: dist.BuildpackURI{URI: createBuildpack(bpd)}, + }, + Publish: true, + PullPolicy: config.PullAlways, + })) + }) + + prepareFetcherWithMissingPackageImage := func() { + mockImageFetcher.EXPECT().Fetch(gomock.Any(), packageImage.Name(), gomock.Any()).Return(nil, image.ErrNotFound) + } + + when("image key is provided", func() { + it("should succeed", func() { + packageImage = createPackage("some/package:tag") + buildpackDownloadOptions = pack.BuildpackDownloadOptions{ + Daemon: true, + PullPolicy: config.PullAlways, + ImageOS: "linux", + ImageName: "some/package:tag", + } + + shouldFetchPackageImageWith(true, config.PullAlways) + mainBP, _, err := buildpackDownloader.Download(context.TODO(), "", buildpackDownloadOptions) + h.AssertNil(t, err) + h.AssertEq(t, mainBP.Descriptor().Info.ID, "example/foo") + }) + }) + + when("daemon=true and pull-policy=always", func() { + it("should pull and use local package image", func() { + buildpackDownloadOptions = pack.BuildpackDownloadOptions{ + ImageOS: "linux", + ImageName: packageImage.Name(), + Daemon: true, + PullPolicy: config.PullAlways, + } + + shouldFetchPackageImageWith(true, config.PullAlways) + mainBP, _, err := buildpackDownloader.Download(context.TODO(), "", buildpackDownloadOptions) + h.AssertNil(t, err) + h.AssertEq(t, mainBP.Descriptor().Info.ID, "some.pkg.bp") + }) + }) + + when("daemon=false and pull-policy=always", func() { + it("should use remote package image", func() { + buildpackDownloadOptions = pack.BuildpackDownloadOptions{ + ImageOS: "linux", + ImageName: packageImage.Name(), + Daemon: false, + PullPolicy: config.PullAlways, + } + + shouldFetchPackageImageWith(false, config.PullAlways) + mainBP, _, err := buildpackDownloader.Download(context.TODO(), "", buildpackDownloadOptions) + h.AssertNil(t, err) + h.AssertEq(t, mainBP.Descriptor().Info.ID, "some.pkg.bp") + + }) + }) + + when("daemon=false and pull-policy=always", func() { + it("should use remote package URI", func() { + buildpackDownloadOptions = pack.BuildpackDownloadOptions{ + ImageOS: "linux", + Daemon: false, + PullPolicy: config.PullAlways, + } + shouldFetchPackageImageWith(false, config.PullAlways) + mainBP, _, err := buildpackDownloader.Download(context.TODO(), packageImage.Name(), buildpackDownloadOptions) + h.AssertNil(t, err) + h.AssertEq(t, mainBP.Descriptor().Info.ID, "some.pkg.bp") + }) + }) + + when("publish=true and pull-policy=never", func() { + it("should push to registry and not pull package image", func() { + buildpackDownloadOptions = pack.BuildpackDownloadOptions{ + ImageOS: "linux", + ImageName: packageImage.Name(), + Daemon: false, + PullPolicy: config.PullNever, + } + + shouldFetchPackageImageWith(false, config.PullNever) + mainBP, _, err := buildpackDownloader.Download(context.TODO(), "", buildpackDownloadOptions) + h.AssertNil(t, err) + h.AssertEq(t, mainBP.Descriptor().Info.ID, "some.pkg.bp") + + }) + }) + + when("daemon=true pull-policy=never and there is no local package image", func() { + it("should fail without trying to retrieve package image from registry", func() { + buildpackDownloadOptions = pack.BuildpackDownloadOptions{ + ImageOS: "linux", + ImageName: packageImage.Name(), + Daemon: true, + PullPolicy: config.PullNever, + } + prepareFetcherWithMissingPackageImage() + _, _, err := buildpackDownloader.Download(context.TODO(), "", buildpackDownloadOptions) + h.AssertError(t, err, "not found") + }) + }) + }) + when("package lives on filesystem", func() { + it("should succesfully retrieve package from absolute path", func() { + buildpackPath := filepath.Join("testdata", "buildpack") + buildpackURI, _ := paths.FilePathToURI(buildpackPath, "") + mockDownloader.EXPECT().Download(gomock.Any(), buildpackURI).Return(blob.NewBlob(buildpackPath), nil).AnyTimes() + mainBP, _, err := buildpackDownloader.Download(context.TODO(), buildpackURI, buildpackDownloadOptions) + h.AssertNil(t, err) + h.AssertEq(t, mainBP.Descriptor().Info.ID, "bp.one") + }) + it("should succesfully retrieve package from relative path", func() { + buildpackPath := filepath.Join("testdata", "buildpack") + buildpackURI, _ := paths.FilePathToURI(buildpackPath, "") + mockDownloader.EXPECT().Download(gomock.Any(), buildpackURI).Return(blob.NewBlob(buildpackPath), nil).AnyTimes() + buildpackDownloadOptions = pack.BuildpackDownloadOptions{ + ImageOS: "linux", + RelativeBaseDir: "testdata", + } + mainBP, _, err := buildpackDownloader.Download(context.TODO(), "buildpack", buildpackDownloadOptions) + h.AssertNil(t, err) + h.AssertEq(t, mainBP.Descriptor().Info.ID, "bp.one") + }) + }) + when("package image is not a valid package", func() { + it("should error", func() { + notPackageImage := fakes.NewImage("docker.io/not/package", "", nil) + + mockImageFetcher.EXPECT().Fetch(gomock.Any(), notPackageImage.Name(), gomock.Any()).Return(notPackageImage, nil) + h.AssertNil(t, notPackageImage.SetLabel("io.buildpacks.buildpack.layers", "")) + + buildpackDownloadOptions.ImageName = notPackageImage.Name() + _, _, err := buildpackDownloader.Download(context.TODO(), "", buildpackDownloadOptions) + h.AssertError(t, err, "extracting buildpacks from 'docker.io/not/package': could not find label 'io.buildpacks.buildpackage.metadata'") + }) + }) + when("invalid buildpack URI", func() { + when("buildpack URI is from=builder:fake", func() { + it("errors", func() { + _, _, err := subject.BuildpackDownloader.Download(context.TODO(), "from=builder:fake", buildpackDownloadOptions) + h.AssertError(t, err, "'from=builder:fake' is not a valid identifier") + }) + }) + + when("buildpack URI is from=builder", func() { + it("errors", func() { + _, _, err := subject.BuildpackDownloader.Download(context.TODO(), "from=builder", buildpackDownloadOptions) + h.AssertError(t, err, + "invalid locator: FromBuilderLocator") + }) + }) + + when("buildpack URI is invalid registry", func() { + it("errors", func() { + buildpackDownloadOptions.RegistryName = "://bad-url" + _, _, err := subject.BuildpackDownloader.Download(context.TODO(), "urn:cnb:registry:fake", buildpackDownloadOptions) + h.AssertError(t, err, + "invalid registry") + }) + }) + + when("buildpack is missing from registry", func() { + var configPath string + var registryFixture string + + it("errors", func() { + registryFixture = h.CreateRegistryFixture(t, tmpDir, filepath.Join("testdata", "registry")) + + packHome := filepath.Join(tmpDir, "packHome") + h.AssertNil(t, os.Setenv("PACK_HOME", packHome)) + + configPath = filepath.Join(packHome, "config.toml") + h.AssertNil(t, cfg.Write(cfg.Config{ + Registries: []cfg.Registry{ + { + Name: "some-registry", + Type: "github", + URL: registryFixture, + }, + }, + }, configPath)) + + buildpackDownloadOptions.RegistryName = "some-registry" + _, _, err := subject.BuildpackDownloader.Download(context.TODO(), "urn:cnb:registry:fake", buildpackDownloadOptions) + h.AssertError(t, err, + "locating in registry") + }) + }) + + when("can't download image from registry", func() { + var configPath string + var registryFixture string + + it("errors", func() { + registryFixture = h.CreateRegistryFixture(t, tmpDir, filepath.Join("testdata", "registry")) + packHome := filepath.Join(tmpDir, "packHome") + h.AssertNil(t, os.Setenv("PACK_HOME", packHome)) + + configPath = filepath.Join(packHome, "config.toml") + h.AssertNil(t, cfg.Write(cfg.Config{ + Registries: []cfg.Registry{ + { + Name: "some-registry", + Type: "github", + URL: registryFixture, + }, + }, + }, configPath)) + + packageImage := fakes.NewImage("example.com/some/package@sha256:74eb48882e835d8767f62940d453eb96ed2737de3a16573881dcea7dea769df7", "", nil) + mockImageFetcher.EXPECT().Fetch(gomock.Any(), packageImage.Name(), image.FetchOptions{Daemon: false, PullPolicy: config.PullAlways}).Return(nil, errors.New("failed to pull")) + + buildpackDownloadOptions.RegistryName = "some-registry" + _, _, err := subject.BuildpackDownloader.Download(context.TODO(), "urn:cnb:registry:example/foo@1.1.0", buildpackDownloadOptions) + h.AssertError(t, err, + "extracting from registry") + }) + }) + + when("buildpack URI is an invalid locator", func() { + it("errors", func() { + _, _, err := subject.BuildpackDownloader.Download(context.TODO(), "nonsense string here", buildpackDownloadOptions) + h.AssertError(t, err, + "invalid locator: InvalidLocator") + }) + }) + }) + }) + +} diff --git a/client.go b/client.go index db1b9533c5..a71813e245 100644 --- a/client.go +++ b/client.go @@ -10,10 +10,11 @@ import ( "github.com/google/go-containerregistry/pkg/authn" "github.com/pkg/errors" - "github.com/buildpacks/pack/image" "github.com/buildpacks/pack/internal/blob" "github.com/buildpacks/pack/internal/build" "github.com/buildpacks/pack/internal/config" + "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/image" "github.com/buildpacks/pack/logging" ) @@ -53,17 +54,26 @@ type ImageFactory interface { NewImage(repoName string, local bool, imageOS string) (imgutil.Image, error) } +//go:generate mockgen -package pack -destination mock_buildpack_downloader.go github.com/buildpacks/pack BuildpackDownloader + +// BuildpackDownloader is an interface for downloading and extracting buildpacks from various sources +type BuildpackDownloader interface { + // Download parses a buildpack URI and downloads the buildpack and any depedencies buildpacks from the appropriate source + Download(ctx context.Context, buildpackURI string, opts BuildpackDownloadOptions) (dist.Buildpack, []dist.Buildpack, error) +} + // Client is an orchestration object, it contains all parameters needed to // build an app image using Cloud Native Buildpacks. // All settings on this object should be changed through ClientOption functions. type Client struct { - logger logging.Logger - imageFetcher ImageFetcher - downloader Downloader - lifecycleExecutor LifecycleExecutor - docker dockerClient.CommonAPIClient - imageFactory ImageFactory - experimental bool + logger logging.Logger + imageFetcher ImageFetcher + downloader Downloader + lifecycleExecutor LifecycleExecutor + docker dockerClient.CommonAPIClient + imageFactory ImageFactory + BuildpackDownloader BuildpackDownloader + experimental bool } // ClientOption is a type of function that mutate settings on the client. @@ -100,6 +110,14 @@ func WithDownloader(d Downloader) ClientOption { } } +// WithBuildpackDownloader supply your own BuildpackDownloader. +// A BuildpackDownloader is used to gather buildpacks from both remote urls, or local sources. +func WithBuildpackDownloader(d BuildpackDownloader) ClientOption { + return func(c *Client) { + c.BuildpackDownloader = d + } +} + // Deprecated: use WithDownloader instead. // // WithCacheDir supply your own cache directory. @@ -162,6 +180,10 @@ func NewClient(opts ...ClientOption) (*Client, error) { client.imageFactory = image.NewFactory(client.docker, authn.DefaultKeychain) } + if client.BuildpackDownloader == nil { + client.BuildpackDownloader = NewBuildpackDownloader(client.logger, client.imageFetcher, client.downloader) + } + client.lifecycleExecutor = build.NewLifecycleExecutor(client.logger, client.docker) return &client, nil diff --git a/common.go b/common.go index 171208ca54..54f3b4b8cb 100644 --- a/common.go +++ b/common.go @@ -57,7 +57,7 @@ func (c *Client) resolveRunImage(runImage, imgRegistry, bldrRegistry string, sta return runImageName } -func (c *Client) getRegistry(logger logging.Logger, registryName string) (registry.Cache, error) { +func getRegistry(logger logging.Logger, registryName string) (registry.Cache, error) { home, err := config.PackHome() if err != nil { return registry.Cache{}, err diff --git a/create_builder.go b/create_builder.go index cda044b57f..2b25664e43 100644 --- a/create_builder.go +++ b/create_builder.go @@ -11,10 +11,9 @@ import ( "github.com/pkg/errors" pubbldr "github.com/buildpacks/pack/builder" - "github.com/buildpacks/pack/image" "github.com/buildpacks/pack/internal/builder" - "github.com/buildpacks/pack/internal/buildpack" "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/image" "github.com/buildpacks/pack/internal/paths" "github.com/buildpacks/pack/internal/style" ) @@ -202,84 +201,6 @@ func (c *Client) fetchLifecycle(ctx context.Context, config pubbldr.LifecycleCon return lifecycle, nil } -type DownloadBuildpackOptions struct { - // Buildpack registry name. Defines where all registry buildpacks will be pulled from. - RegistryName string - - // The base directory to use to resolve relative assets - RelativeBaseDir string - - // The OS of the builder image - ImageOS string - - FetchOptions image.FetchOptions - - // Deprecated, the older alternative to buildpack URI - ImageName string -} - -func (c *Client) DownloadBuildpack(ctx context.Context, buildpackURI string, opts DownloadBuildpackOptions) (dist.Buildpack, []dist.Buildpack, error) { - var err error - var locatorType buildpack.LocatorType - if buildpackURI == "" && opts.ImageName != "" { - c.logger.Warn("The 'image' key is deprecated. Use 'uri=\"docker://...\"' instead.") - buildpackURI = opts.ImageName - locatorType = buildpack.PackageLocator - } else { - locatorType, err = buildpack.GetLocatorType(buildpackURI, opts.RelativeBaseDir, []dist.BuildpackInfo{}) - if err != nil { - return nil, nil, err - } - } - - var mainBP dist.Buildpack - var depBPs []dist.Buildpack - switch locatorType { - case buildpack.PackageLocator: - imageName := buildpack.ParsePackageLocator(buildpackURI) - c.logger.Debugf("Downloading buildpack from image: %s", style.Symbol(imageName)) - mainBP, depBPs, err = extractPackagedBuildpacks(ctx, imageName, c.imageFetcher, opts.FetchOptions) - if err != nil { - return nil, nil, errors.Wrapf(err, "extracting from registry %s", style.Symbol(buildpackURI)) - } - case buildpack.RegistryLocator: - c.logger.Debugf("Downloading buildpack from registry: %s", style.Symbol(buildpackURI)) - registryCache, err := c.getRegistry(c.logger, opts.RegistryName) - if err != nil { - return nil, nil, errors.Wrapf(err, "invalid registry '%s'", opts.RegistryName) - } - - registryBp, err := registryCache.LocateBuildpack(buildpackURI) - if err != nil { - return nil, nil, errors.Wrapf(err, "locating in registry %s", style.Symbol(buildpackURI)) - } - - mainBP, depBPs, err = extractPackagedBuildpacks(ctx, registryBp.Address, c.imageFetcher, opts.FetchOptions) - if err != nil { - return nil, nil, errors.Wrapf(err, "extracting from registry %s", style.Symbol(buildpackURI)) - } - case buildpack.URILocator: - buildpackURI, err = paths.FilePathToURI(buildpackURI, opts.RelativeBaseDir) - if err != nil { - return nil, nil, errors.Wrapf(err, "making absolute: %s", style.Symbol(buildpackURI)) - } - - c.logger.Debugf("Downloading buildpack from URI: %s", style.Symbol(buildpackURI)) - - blob, err := c.downloader.Download(ctx, buildpackURI) - if err != nil { - return nil, nil, errors.Wrapf(err, "downloading buildpack from %s", style.Symbol(buildpackURI)) - } - - mainBP, depBPs, err = decomposeBuildpack(blob, opts.ImageOS) - if err != nil { - return nil, nil, errors.Wrapf(err, "extracting from %s", style.Symbol(buildpackURI)) - } - default: - return nil, nil, fmt.Errorf("error reading %s: invalid locator: %s", buildpackURI, locatorType) - } - return mainBP, depBPs, nil -} func (c *Client) addBuildpacksToBuilder(ctx context.Context, opts CreateBuilderOptions, bldr *builder.Builder) error { for _, b := range opts.Config.Buildpacks { c.logger.Debugf("Looking up buildpack %s", style.Symbol(b.DisplayString())) @@ -289,11 +210,12 @@ func (c *Client) addBuildpacksToBuilder(ctx context.Context, opts CreateBuilderO return errors.Wrapf(err, "getting OS from %s", style.Symbol(bldr.Image().Name())) } - mainBP, depBPs, err := c.DownloadBuildpack(ctx, b.URI, DownloadBuildpackOptions{ + mainBP, depBPs, err := c.BuildpackDownloader.Download(ctx, b.URI, BuildpackDownloadOptions{ RegistryName: opts.Registry, ImageOS: imageOS, RelativeBaseDir: opts.RelativeBaseDir, - FetchOptions: image.FetchOptions{Daemon: !opts.Publish, PullPolicy: opts.PullPolicy}, + Daemon: !opts.Publish, + PullPolicy: opts.PullPolicy, ImageName: b.ImageName, }) if err != nil { diff --git a/create_builder_test.go b/create_builder_test.go index 27b0c3cc43..cc5689c1af 100644 --- a/create_builder_test.go +++ b/create_builder_test.go @@ -22,16 +22,17 @@ import ( pubbldr "github.com/buildpacks/pack/builder" pubbldpkg "github.com/buildpacks/pack/buildpackage" "github.com/buildpacks/pack/config" - "github.com/buildpacks/pack/image" "github.com/buildpacks/pack/internal/blob" "github.com/buildpacks/pack/internal/builder" - cfg "github.com/buildpacks/pack/internal/config" + "github.com/buildpacks/pack/internal/buildpackage" "github.com/buildpacks/pack/internal/dist" ifakes "github.com/buildpacks/pack/internal/fakes" + "github.com/buildpacks/pack/internal/image" ilogging "github.com/buildpacks/pack/internal/logging" "github.com/buildpacks/pack/internal/paths" "github.com/buildpacks/pack/internal/style" "github.com/buildpacks/pack/logging" + "github.com/buildpacks/pack/pkg/archive" h "github.com/buildpacks/pack/testhelpers" "github.com/buildpacks/pack/testmocks" ) @@ -45,20 +46,43 @@ func TestCreateBuilder(t *testing.T) { func testCreateBuilder(t *testing.T, when spec.G, it spec.S) { when("#CreateBuilder", func() { var ( - mockController *gomock.Controller - mockDownloader *testmocks.MockDownloader - mockImageFactory *testmocks.MockImageFactory - mockImageFetcher *testmocks.MockImageFetcher - mockDockerClient *testmocks.MockCommonAPIClient - fakeBuildImage *fakes.Image - fakeRunImage *fakes.Image - fakeRunImageMirror *fakes.Image - opts pack.CreateBuilderOptions - subject *pack.Client - logger logging.Logger - out bytes.Buffer - tmpDir string + mockController *gomock.Controller + mockDownloader *testmocks.MockDownloader + mockBuildpackDownloader *pack.MockBuildpackDownloader + mockImageFactory *testmocks.MockImageFactory + mockImageFetcher *testmocks.MockImageFetcher + mockDockerClient *testmocks.MockCommonAPIClient + fakeBuildImage *fakes.Image + fakeRunImage *fakes.Image + fakeRunImageMirror *fakes.Image + opts pack.CreateBuilderOptions + subject *pack.Client + logger logging.Logger + out bytes.Buffer + tmpDir string ) + var prepareFetcherWithRunImages = func() { + mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/run-image", gomock.Any()).Return(fakeRunImage, nil).AnyTimes() + mockImageFetcher.EXPECT().Fetch(gomock.Any(), "localhost:5000/some/run-image", gomock.Any()).Return(fakeRunImageMirror, nil).AnyTimes() + } + + var prepareFetcherWithBuildImage = func() { + mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/build-image", gomock.Any()).Return(fakeBuildImage, nil) + } + + var createBuildpack = func(descriptor dist.BuildpackDescriptor) dist.Buildpack { + buildpack, err := ifakes.NewFakeBuildpack(descriptor, 0644) + h.AssertNil(t, err) + return buildpack + } + var shouldCallBuildpackDownloaderWith = func(uri string, buildpackDownloadOptions pack.BuildpackDownloadOptions) { + buildpack := createBuildpack(dist.BuildpackDescriptor{ + API: api.MustParse("0.3"), + Info: dist.BuildpackInfo{ID: "example/foo", Version: "1.1.0"}, + Stacks: []dist.Stack{{ID: "some.stack.id"}}, + }) + mockBuildpackDownloader.EXPECT().Download(gomock.Any(), uri, gomock.Any()).Return(buildpack, nil, nil) + } it.Before(func() { logger = ilogging.NewLogWithWriters(&out, &out, ilogging.WithVerbose()) @@ -67,6 +91,7 @@ func testCreateBuilder(t *testing.T, when spec.G, it spec.S) { mockImageFetcher = testmocks.NewMockImageFetcher(mockController) mockImageFactory = testmocks.NewMockImageFactory(mockController) mockDockerClient = testmocks.NewMockCommonAPIClient(mockController) + mockBuildpackDownloader = pack.NewMockBuildpackDownloader(mockController) fakeBuildImage = fakes.NewImage("some/build-image", "", nil) h.AssertNil(t, fakeBuildImage.SetLabel("io.buildpacks.stack.id", "some.stack.id")) @@ -80,18 +105,25 @@ func testCreateBuilder(t *testing.T, when spec.G, it spec.S) { fakeRunImageMirror = fakes.NewImage("localhost:5000/some/run-image", "", nil) h.AssertNil(t, fakeRunImageMirror.SetLabel("io.buildpacks.stack.id", "some.stack.id")) - mockDownloader.EXPECT().Download(gomock.Any(), "https://example.fake/bp-one.tgz").Return(blob.NewBlob(filepath.Join("testdata", "buildpack")), nil).AnyTimes() + exampleBuildpackBlob := blob.NewBlob(filepath.Join("testdata", "buildpack")) + mockDownloader.EXPECT().Download(gomock.Any(), "https://example.fake/bp-one.tgz").Return(exampleBuildpackBlob, nil).AnyTimes() mockDownloader.EXPECT().Download(gomock.Any(), "some/buildpack/dir").Return(blob.NewBlob(filepath.Join("testdata", "buildpack")), nil).AnyTimes() mockDownloader.EXPECT().Download(gomock.Any(), "file:///some-lifecycle").Return(blob.NewBlob(filepath.Join("testdata", "lifecycle", "platform-0.4")), nil).AnyTimes() mockDownloader.EXPECT().Download(gomock.Any(), "file:///some-lifecycle-platform-0-1").Return(blob.NewBlob(filepath.Join("testdata", "lifecycle-platform-0.1")), nil).AnyTimes() + var buildpack dist.Buildpack var err error + buildpack, err = dist.BuildpackFromRootBlob(exampleBuildpackBlob, archive.DefaultTarWriterFactory()) + h.AssertNil(t, err) + mockBuildpackDownloader.EXPECT().Download(gomock.Any(), "https://example.fake/bp-one.tgz", gomock.Any()).Return(buildpack, nil, nil).AnyTimes() + subject, err = pack.NewClient( pack.WithLogger(logger), pack.WithDownloader(mockDownloader), pack.WithImageFactory(mockImageFactory), pack.WithFetcher(mockImageFetcher), pack.WithDockerClient(mockDockerClient), + pack.WithBuildpackDownloader(mockBuildpackDownloader), ) h.AssertNil(t, err) @@ -138,15 +170,6 @@ func testCreateBuilder(t *testing.T, when spec.G, it spec.S) { h.AssertNil(t, os.RemoveAll(tmpDir)) }) - var prepareFetcherWithRunImages = func() { - mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/run-image", gomock.Any()).Return(fakeRunImage, nil).AnyTimes() - mockImageFetcher.EXPECT().Fetch(gomock.Any(), "localhost:5000/some/run-image", gomock.Any()).Return(fakeRunImageMirror, nil).AnyTimes() - } - - var prepareFetcherWithBuildImage = func() { - mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/build-image", gomock.Any()).Return(fakeBuildImage, nil) - } - var successfullyCreateBuilder = func() *builder.Builder { t.Helper() @@ -160,34 +183,6 @@ func testCreateBuilder(t *testing.T, when spec.G, it spec.S) { return bldr } - var createBuildpack = func(descriptor dist.BuildpackDescriptor) string { - bp, err := ifakes.NewFakeBuildpackBlob(descriptor, 0644) - h.AssertNil(t, err) - url := fmt.Sprintf("https://example.com/bp.%s.tgz", h.RandString(12)) - mockDownloader.EXPECT().Download(gomock.Any(), url).Return(bp, nil).AnyTimes() - return url - } - - var createPackage = func(imageName string) *fakes.Image { - packageImage := fakes.NewImage(imageName, "", nil) - mockImageFactory.EXPECT().NewImage(packageImage.Name(), false, "linux").Return(packageImage, nil) - - h.AssertNil(t, subject.PackageBuildpack(context.TODO(), pack.PackageBuildpackOptions{ - Name: packageImage.Name(), - Config: pubbldpkg.Config{ - Platform: dist.Platform{OS: "linux"}, - Buildpack: dist.BuildpackURI{URI: createBuildpack(dist.BuildpackDescriptor{ - API: api.MustParse("0.3"), - Info: dist.BuildpackInfo{ID: "example/foo", Version: "1.1.0"}, - Stacks: []dist.Stack{{ID: "some.stack.id"}}, - })}, - }, - Publish: true, - })) - - return packageImage - } - when("validating the builder config", func() { it("should fail when the stack ID is empty", func() { opts.Config.Stack.ID = "" @@ -629,7 +624,12 @@ func testCreateBuilder(t *testing.T, when spec.G, it spec.S) { prepareFetcherWithBuildImage() prepareFetcherWithRunImages() opts.Config.Buildpacks[0].URI = "https://example.fake/bp-one-with-api-4.tgz" - mockDownloader.EXPECT().Download(gomock.Any(), "https://example.fake/bp-one-with-api-4.tgz").Return(blob.NewBlob(filepath.Join("testdata", "buildpack-api-0.4")), nil).AnyTimes() + + buildpackBlob := blob.NewBlob(filepath.Join("testdata", "buildpack-api-0.4")) + buildpack, err := dist.BuildpackFromRootBlob(buildpackBlob, archive.DefaultTarWriterFactory()) + h.AssertNil(t, err) + mockBuildpackDownloader.EXPECT().Download(gomock.Any(), "https://example.fake/bp-one-with-api-4.tgz", gomock.Any()).Return(buildpack, nil, nil) + bldr := successfullyCreateBuilder() h.AssertEq(t, bldr.LifecycleDescriptor().APIs.Buildpack.Deprecated.AsStrings(), []string{"0.2", "0.3"}) @@ -644,134 +644,15 @@ func testCreateBuilder(t *testing.T, when spec.G, it spec.S) { directoryPath := "testdata/buildpack" opts.Config.Buildpacks[0].URI = directoryPath - absURI, err := paths.FilePathToURI(directoryPath, "") + buildpackBlob := blob.NewBlob(directoryPath) + buildpack, err := dist.BuildpackFromRootBlob(buildpackBlob, archive.DefaultTarWriterFactory()) h.AssertNil(t, err) - - mockDownloader.EXPECT().Download(gomock.Any(), absURI).Return(blob.NewBlob(directoryPath), nil).AnyTimes() + mockBuildpackDownloader.EXPECT().Download(gomock.Any(), directoryPath, gomock.Any()).Return(buildpack, nil, nil) err = subject.CreateBuilder(context.TODO(), opts) h.AssertNil(t, err) }) - when("invalid buildpack URI", func() { - when("buildpack URI is from=builder:fake", func() { - it("errors", func() { - prepareFetcherWithBuildImage() - prepareFetcherWithRunImages() - opts.Config.Buildpacks[0].URI = "from=builder:fake" - - err := subject.CreateBuilder(context.TODO(), opts) - h.AssertError(t, err, "'from=builder:fake' is not a valid identifier") - }) - }) - - when("buildpack URI is from=builder", func() { - it("errors", func() { - prepareFetcherWithBuildImage() - prepareFetcherWithRunImages() - opts.Config.Buildpacks[0].URI = "from=builder" - - err := subject.CreateBuilder(context.TODO(), opts) - h.AssertError(t, err, - "invalid locator: FromBuilderLocator") - }) - }) - - when("buildpack URI is invalid registry", func() { - it("errors", func() { - prepareFetcherWithBuildImage() - prepareFetcherWithRunImages() - opts.Registry = "://bad-url" - opts.Config.Buildpacks[0].URI = "urn:cnb:registry:fake" - - err := subject.CreateBuilder(context.TODO(), opts) - h.AssertError(t, err, - "invalid registry") - }) - }) - - when("buildpack is missing from registry", func() { - var configPath string - var registryFixture string - - it("errors", func() { - prepareFetcherWithBuildImage() - prepareFetcherWithRunImages() - - registryFixture = h.CreateRegistryFixture(t, tmpDir, filepath.Join("testdata", "registry")) - - packHome := filepath.Join(tmpDir, "packHome") - h.AssertNil(t, os.Setenv("PACK_HOME", packHome)) - - configPath = filepath.Join(packHome, "config.toml") - h.AssertNil(t, cfg.Write(cfg.Config{ - Registries: []cfg.Registry{ - { - Name: "some-registry", - Type: "github", - URL: registryFixture, - }, - }, - }, configPath)) - opts.Config.Buildpacks[0].URI = "urn:cnb:registry:fake" - - opts.Registry = "some-registry" - - err := subject.CreateBuilder(context.TODO(), opts) - h.AssertError(t, err, - "locating in registry") - }) - }) - - when("can't download image from registry", func() { - var configPath string - var registryFixture string - - it("errors", func() { - prepareFetcherWithBuildImage() - prepareFetcherWithRunImages() - - registryFixture = h.CreateRegistryFixture(t, tmpDir, filepath.Join("testdata", "registry")) - opts.Config.Buildpacks[0].URI = "urn:cnb:registry:example/foo@1.1.0" - - packHome := filepath.Join(tmpDir, "packHome") - h.AssertNil(t, os.Setenv("PACK_HOME", packHome)) - - configPath = filepath.Join(packHome, "config.toml") - h.AssertNil(t, cfg.Write(cfg.Config{ - Registries: []cfg.Registry{ - { - Name: "some-registry", - Type: "github", - URL: registryFixture, - }, - }, - }, configPath)) - - opts.Registry = "some-registry" - - packageImage := fakes.NewImage("example.com/some/package@sha256:74eb48882e835d8767f62940d453eb96ed2737de3a16573881dcea7dea769df7", "", nil) - mockImageFetcher.EXPECT().Fetch(gomock.Any(), packageImage.Name(), image.FetchOptions{Daemon: true, PullPolicy: config.PullAlways}).Return(nil, errors.New("failed to pull")) - - err := subject.CreateBuilder(context.TODO(), opts) - h.AssertError(t, err, - "extracting from registry") - }) - }) - - when("buildpack URI is an invalid locator", func() { - it("errors", func() { - prepareFetcherWithBuildImage() - prepareFetcherWithRunImages() - opts.Config.Buildpacks[0].URI = "nonsense string here" - - err := subject.CreateBuilder(context.TODO(), opts) - h.AssertError(t, err, - "invalid locator: InvalidLocator") - }) - }) - }) - when("package file", func() { it.Before(func() { fileURI := func(path string) (original, uri string) { @@ -780,7 +661,7 @@ func testCreateBuilder(t *testing.T, when spec.G, it spec.S) { return path, absPath } - cnbFile, cnbFileURI := fileURI(filepath.Join(tmpDir, "bp_one1.cnb")) + cnbFile, _ := fileURI(filepath.Join(tmpDir, "bp_one1.cnb")) buildpackPath, buildpackPathURI := fileURI(filepath.Join("testdata", "buildpack")) mockDownloader.EXPECT().Download(gomock.Any(), buildpackPathURI).Return(blob.NewBlob(buildpackPath), nil) @@ -793,7 +674,9 @@ func testCreateBuilder(t *testing.T, when spec.G, it spec.S) { Format: "file", })) - mockDownloader.EXPECT().Download(gomock.Any(), cnbFileURI).Return(blob.NewBlob(cnbFile), nil).AnyTimes() + buildpack, _, err := buildpackage.BuildpacksFromOCILayoutBlob(blob.NewBlob(cnbFile)) + h.AssertNil(t, err) + mockBuildpackDownloader.EXPECT().Download(gomock.Any(), cnbFile, gomock.Any()).Return(buildpack, nil, nil).AnyTimes() opts.Config.Buildpacks = []pubbldr.BuildpackConfig{{ ImageOrURI: dist.ImageOrURI{BuildpackURI: dist.BuildpackURI{URI: cnbFile}}, }} @@ -821,63 +704,12 @@ func testCreateBuilder(t *testing.T, when spec.G, it spec.S) { }) when("packages", func() { - var ( - packageImage *fakes.Image - ) - - shouldFetchPackageImageWith := func(demon bool, pull config.PullPolicy) { - mockImageFetcher.EXPECT().Fetch(gomock.Any(), packageImage.Name(), image.FetchOptions{Daemon: demon, PullPolicy: pull}).Return(packageImage, nil) - } - when("package image lives in cnb registry", func() { - var ( - tmpDir string - registryFixture string - packHome string - ) - - it.Before(func() { - var err error - tmpDir, err = ioutil.TempDir("", "registry") - h.AssertNil(t, err) - - packHome = filepath.Join(tmpDir, ".pack") - err = os.MkdirAll(packHome, 0755) - h.AssertNil(t, err) - os.Setenv("PACK_HOME", packHome) - - registryFixture = h.CreateRegistryFixture(t, tmpDir, filepath.Join("testdata", "registry")) - - packageImage = createPackage("example.com/some/package@sha256:74eb48882e835d8767f62940d453eb96ed2737de3a16573881dcea7dea769df7") - }) - - it.After(func() { - os.Unsetenv("PACK_HOME") - err := os.RemoveAll(tmpDir) - h.AssertNil(t, err) - }) - when("publish=false and pull-policy=always", func() { - var configPath string - - it("should pull and use local package image", func() { + it("should call BuildpackDownloader with the proper argumentss", func() { prepareFetcherWithBuildImage() prepareFetcherWithRunImages() opts.BuilderName = "some/builder" - - packHome := filepath.Join(tmpDir, "packHome") - h.AssertNil(t, os.Setenv("PACK_HOME", packHome)) - configPath = filepath.Join(packHome, "config.toml") - h.AssertNil(t, cfg.Write(cfg.Config{ - Registries: []cfg.Registry{ - { - Name: "some-registry", - Type: "github", - URL: registryFixture, - }, - }, - }, configPath)) - opts.Publish = false opts.PullPolicy = config.PullAlways opts.Registry = "some-registry" @@ -892,195 +724,10 @@ func testCreateBuilder(t *testing.T, when spec.G, it spec.S) { }, ) - shouldFetchPackageImageWith(true, config.PullAlways) - h.AssertNil(t, subject.CreateBuilder(context.TODO(), opts)) - }) - }) - }) - - when("package image lives in docker registry", func() { - it.Before(func() { - packageImage = fakes.NewImage("docker.io/some/package-"+h.RandString(12), "", nil) - mockImageFactory.EXPECT().NewImage(packageImage.Name(), false, "linux").Return(packageImage, nil) - - bpd := dist.BuildpackDescriptor{ - API: api.MustParse("0.3"), - Info: dist.BuildpackInfo{ID: "some.pkg.bp", Version: "2.3.4", Homepage: "http://meta.buildpack"}, - Stacks: []dist.Stack{{ID: "some.stack.id"}}, - } - - h.AssertNil(t, subject.PackageBuildpack(context.TODO(), pack.PackageBuildpackOptions{ - Name: packageImage.Name(), - Config: pubbldpkg.Config{ - Platform: dist.Platform{OS: "linux"}, - Buildpack: dist.BuildpackURI{URI: createBuildpack(bpd)}, - }, - Publish: true, - PullPolicy: config.PullAlways, - })) - }) - - prepareFetcherWithMissingPackageImage := func() { - mockImageFetcher.EXPECT().Fetch(gomock.Any(), packageImage.Name(), gomock.Any()).Return(nil, image.ErrNotFound) - } - - when("image key is provided", func() { - it("should succeed", func() { - prepareFetcherWithBuildImage() - prepareFetcherWithRunImages() - - packageImage = createPackage("some/package:tag") - - opts.BuilderName = "some/builder" - opts.Publish = false - opts.PullPolicy = config.PullAlways - opts.Config.Buildpacks = append( - opts.Config.Buildpacks, - pubbldr.BuildpackConfig{ - ImageOrURI: dist.ImageOrURI{ - ImageRef: dist.ImageRef{ImageName: "some/package:tag"}, - }, - }, - ) - - shouldFetchPackageImageWith(true, config.PullAlways) - h.AssertNil(t, subject.CreateBuilder(context.TODO(), opts)) - }) - }) - - when("publish=false and pull-policy=always", func() { - it("should pull and use local package image", func() { - prepareFetcherWithBuildImage() - prepareFetcherWithRunImages() - opts.BuilderName = "some/builder" - - opts.Publish = false - opts.PullPolicy = config.PullAlways - opts.Config.Buildpacks = append( - opts.Config.Buildpacks, - pubbldr.BuildpackConfig{ - ImageOrURI: dist.ImageOrURI{ - ImageRef: dist.ImageRef{ImageName: packageImage.Name()}, - }, - }, - ) - - shouldFetchPackageImageWith(true, config.PullAlways) - h.AssertNil(t, subject.CreateBuilder(context.TODO(), opts)) - }) - }) - - when("publish=true and pull-policy=always", func() { - it("should use remote package image", func() { - prepareFetcherWithBuildImage() - prepareFetcherWithRunImages() - opts.BuilderName = "some/builder" - - opts.Publish = true - opts.PullPolicy = config.PullAlways - opts.Config.Buildpacks = append( - opts.Config.Buildpacks, - pubbldr.BuildpackConfig{ - ImageOrURI: dist.ImageOrURI{ - ImageRef: dist.ImageRef{ImageName: packageImage.Name()}, - }, - }, - ) - - shouldFetchPackageImageWith(false, config.PullAlways) + shouldCallBuildpackDownloaderWith("urn:cnb:registry:example/foo@1.1.0", pack.BuildpackDownloadOptions{Daemon: true, PullPolicy: config.PullAlways, RegistryName: "some-"}) h.AssertNil(t, subject.CreateBuilder(context.TODO(), opts)) }) }) - - when("publish=true and pull-policy=always", func() { - it("should use remote package URI", func() { - prepareFetcherWithBuildImage() - prepareFetcherWithRunImages() - opts.BuilderName = "some/builder" - - opts.Publish = true - opts.PullPolicy = config.PullAlways - opts.Config.Buildpacks = append( - opts.Config.Buildpacks, - pubbldr.BuildpackConfig{ - ImageOrURI: dist.ImageOrURI{ - BuildpackURI: dist.BuildpackURI{URI: packageImage.Name()}, - }, - }, - ) - - shouldFetchPackageImageWith(false, config.PullAlways) - h.AssertNil(t, subject.CreateBuilder(context.TODO(), opts)) - }) - }) - - when("publish=true and pull-policy=never", func() { - it("should push to registry and not pull package image", func() { - prepareFetcherWithBuildImage() - prepareFetcherWithRunImages() - opts.BuilderName = "some/builder" - - opts.Publish = true - opts.PullPolicy = config.PullNever - opts.Config.Buildpacks = append( - opts.Config.Buildpacks, - pubbldr.BuildpackConfig{ - ImageOrURI: dist.ImageOrURI{ - ImageRef: dist.ImageRef{ImageName: packageImage.Name()}, - }, - }, - ) - - shouldFetchPackageImageWith(false, config.PullNever) - h.AssertNil(t, subject.CreateBuilder(context.TODO(), opts)) - }) - }) - - when("publish=false pull-policy=never and there is no local package image", func() { - it("should fail without trying to retrieve package image from registry", func() { - prepareFetcherWithBuildImage() - prepareFetcherWithRunImages() - opts.BuilderName = "some/builder" - - opts.Publish = false - opts.PullPolicy = config.PullNever - opts.Config.Buildpacks = append( - opts.Config.Buildpacks, - pubbldr.BuildpackConfig{ - ImageOrURI: dist.ImageOrURI{ - ImageRef: dist.ImageRef{ImageName: packageImage.Name()}, - }, - }, - ) - - prepareFetcherWithMissingPackageImage() - - h.AssertError(t, subject.CreateBuilder(context.TODO(), opts), "not found") - }) - }) - }) - - when("package image is not a valid package", func() { - it("should error", func() { - prepareFetcherWithBuildImage() - prepareFetcherWithRunImages() - opts.BuilderName = "some/builder" - - notPackageImage := fakes.NewImage("docker.io/not/package", "", nil) - opts.Config.Buildpacks = append( - opts.Config.Buildpacks, - pubbldr.BuildpackConfig{ - ImageOrURI: dist.ImageOrURI{ - ImageRef: dist.ImageRef{ImageName: notPackageImage.Name()}, - }, - }, - ) - - mockImageFetcher.EXPECT().Fetch(gomock.Any(), notPackageImage.Name(), gomock.Any()).Return(notPackageImage, nil) - h.AssertNil(t, notPackageImage.SetLabel("io.buildpacks.buildpack.layers", "")) - - h.AssertError(t, subject.CreateBuilder(context.TODO(), opts), "extracting buildpacks from 'docker.io/not/package': could not find label 'io.buildpacks.buildpackage.metadata'") - }) }) }) }) diff --git a/inspect_builder.go b/inspect_builder.go index ddb2a22368..c445a498f7 100644 --- a/inspect_builder.go +++ b/inspect_builder.go @@ -5,9 +5,9 @@ import ( pubbldr "github.com/buildpacks/pack/builder" - "github.com/buildpacks/pack/image" "github.com/buildpacks/pack/internal/builder" "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/image" ) // BuilderInfo is a collection of metadata describing a builder created using pack. diff --git a/inspect_builder_test.go b/inspect_builder_test.go index 50ca6a0fe6..f22edb0db1 100644 --- a/inspect_builder_test.go +++ b/inspect_builder_test.go @@ -18,9 +18,9 @@ import ( "github.com/sclevine/spec" "github.com/sclevine/spec/report" - "github.com/buildpacks/pack/image" "github.com/buildpacks/pack/internal/builder" "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/image" "github.com/buildpacks/pack/internal/logging" h "github.com/buildpacks/pack/testhelpers" "github.com/buildpacks/pack/testmocks" diff --git a/inspect_buildpack.go b/inspect_buildpack.go index 12a4be6b01..028f4b5850 100644 --- a/inspect_buildpack.go +++ b/inspect_buildpack.go @@ -8,10 +8,10 @@ import ( v1 "github.com/opencontainers/image-spec/specs-go/v1" "github.com/buildpacks/pack/config" - "github.com/buildpacks/pack/image" "github.com/buildpacks/pack/internal/buildpack" "github.com/buildpacks/pack/internal/buildpackage" "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/image" "github.com/buildpacks/pack/internal/style" ) @@ -69,7 +69,7 @@ func (c *Client) InspectBuildpack(opts InspectBuildpackOptions) (*BuildpackInfo, } func metadataFromRegistry(client *Client, name, registry string) (buildpackMd buildpackage.Metadata, layersMd dist.BuildpackLayers, err error) { - registryCache, err := client.getRegistry(client.logger, registry) + registryCache, err := getRegistry(client.logger, registry) if err != nil { return buildpackage.Metadata{}, dist.BuildpackLayers{}, fmt.Errorf("invalid registry %s: %q", registry, err) } diff --git a/inspect_buildpack_test.go b/inspect_buildpack_test.go index 9e83a77c93..6908cbbe1f 100644 --- a/inspect_buildpack_test.go +++ b/inspect_buildpack_test.go @@ -11,8 +11,8 @@ import ( "github.com/pkg/errors" - "github.com/buildpacks/pack/image" cfg "github.com/buildpacks/pack/internal/config" + "github.com/buildpacks/pack/internal/image" "github.com/google/go-containerregistry/pkg/v1/empty" "github.com/google/go-containerregistry/pkg/v1/layout" diff --git a/inspect_image.go b/inspect_image.go index 82b69fca70..eb0fe7f302 100644 --- a/inspect_image.go +++ b/inspect_image.go @@ -11,8 +11,8 @@ import ( "github.com/pkg/errors" "github.com/buildpacks/pack/config" - "github.com/buildpacks/pack/image" "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/image" ) // ImageInfo is a collection of metadata describing diff --git a/inspect_image_test.go b/inspect_image_test.go index bb6e3d3817..51a03f38d2 100644 --- a/inspect_image_test.go +++ b/inspect_image_test.go @@ -16,7 +16,7 @@ import ( "github.com/sclevine/spec/report" "github.com/buildpacks/pack/config" - "github.com/buildpacks/pack/image" + "github.com/buildpacks/pack/internal/image" "github.com/buildpacks/pack/internal/logging" h "github.com/buildpacks/pack/testhelpers" "github.com/buildpacks/pack/testmocks" diff --git a/internal/builder/fakes/fake_inspectable_fetcher.go b/internal/builder/fakes/fake_inspectable_fetcher.go index 8229e8991b..968930e985 100644 --- a/internal/builder/fakes/fake_inspectable_fetcher.go +++ b/internal/builder/fakes/fake_inspectable_fetcher.go @@ -4,8 +4,8 @@ import ( "context" "github.com/buildpacks/pack/config" - "github.com/buildpacks/pack/image" "github.com/buildpacks/pack/internal/builder" + "github.com/buildpacks/pack/internal/image" ) type FakeInspectableFetcher struct { diff --git a/internal/builder/image_fetcher_wrapper.go b/internal/builder/image_fetcher_wrapper.go index 6ba4ab4f71..d7657e129a 100644 --- a/internal/builder/image_fetcher_wrapper.go +++ b/internal/builder/image_fetcher_wrapper.go @@ -5,7 +5,7 @@ import ( "github.com/buildpacks/imgutil" - "github.com/buildpacks/pack/image" + "github.com/buildpacks/pack/internal/image" ) type ImageFetcher interface { diff --git a/internal/builder/inspect.go b/internal/builder/inspect.go index a54afad4d9..3cc3a8c63c 100644 --- a/internal/builder/inspect.go +++ b/internal/builder/inspect.go @@ -8,8 +8,8 @@ import ( pubbldr "github.com/buildpacks/pack/builder" "github.com/buildpacks/pack/config" - "github.com/buildpacks/pack/image" "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/image" ) type Info struct { diff --git a/internal/commands/buildpack_inspect_test.go b/internal/commands/buildpack_inspect_test.go index 1622a58187..b8cb6b5f78 100644 --- a/internal/commands/buildpack_inspect_test.go +++ b/internal/commands/buildpack_inspect_test.go @@ -7,7 +7,7 @@ import ( "github.com/pkg/errors" - "github.com/buildpacks/pack/image" + "github.com/buildpacks/pack/internal/image" "github.com/buildpacks/lifecycle/api" "github.com/golang/mock/gomock" diff --git a/internal/commands/inspect_buildpack_test.go b/internal/commands/inspect_buildpack_test.go index fd20aa3cf1..34d5722807 100644 --- a/internal/commands/inspect_buildpack_test.go +++ b/internal/commands/inspect_buildpack_test.go @@ -7,7 +7,7 @@ import ( "github.com/pkg/errors" - "github.com/buildpacks/pack/image" + "github.com/buildpacks/pack/internal/image" "github.com/buildpacks/lifecycle/api" "github.com/golang/mock/gomock" diff --git a/internal/fakes/fake_image_fetcher.go b/internal/fakes/fake_image_fetcher.go index e4ca88968a..142d82aa29 100644 --- a/internal/fakes/fake_image_fetcher.go +++ b/internal/fakes/fake_image_fetcher.go @@ -8,7 +8,7 @@ import ( "github.com/buildpacks/imgutil" "github.com/pkg/errors" - "github.com/buildpacks/pack/image" + "github.com/buildpacks/pack/internal/image" ) type FetchArgs struct { diff --git a/image/factory.go b/internal/image/factory.go similarity index 100% rename from image/factory.go rename to internal/image/factory.go diff --git a/image/fetcher.go b/internal/image/fetcher.go similarity index 100% rename from image/fetcher.go rename to internal/image/fetcher.go diff --git a/image/fetcher_test.go b/internal/image/fetcher_test.go similarity index 99% rename from image/fetcher_test.go rename to internal/image/fetcher_test.go index f0a36fc62c..56036f5e05 100644 --- a/image/fetcher_test.go +++ b/internal/image/fetcher_test.go @@ -18,7 +18,7 @@ import ( "github.com/sclevine/spec/report" pubcfg "github.com/buildpacks/pack/config" - "github.com/buildpacks/pack/image" + "github.com/buildpacks/pack/internal/image" "github.com/buildpacks/pack/internal/logging" h "github.com/buildpacks/pack/testhelpers" ) diff --git a/mock_buildpack_downloader.go b/mock_buildpack_downloader.go new file mode 100644 index 0000000000..52900bc859 --- /dev/null +++ b/mock_buildpack_downloader.go @@ -0,0 +1,52 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/buildpacks/pack (interfaces: BuildpackDownloader) + +// Package testmocks is a generated GoMock package. +package pack + +import ( + context "context" + reflect "reflect" + + dist "github.com/buildpacks/pack/internal/dist" + gomock "github.com/golang/mock/gomock" +) + +// MockBuildpackDownloader is a mock of BuildpackDownloader interface. +type MockBuildpackDownloader struct { + ctrl *gomock.Controller + recorder *MockBuildpackDownloaderMockRecorder +} + +// MockBuildpackDownloaderMockRecorder is the mock recorder for MockBuildpackDownloader. +type MockBuildpackDownloaderMockRecorder struct { + mock *MockBuildpackDownloader +} + +// NewMockBuildpackDownloader creates a new mock instance. +func NewMockBuildpackDownloader(ctrl *gomock.Controller) *MockBuildpackDownloader { + mock := &MockBuildpackDownloader{ctrl: ctrl} + mock.recorder = &MockBuildpackDownloaderMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockBuildpackDownloader) EXPECT() *MockBuildpackDownloaderMockRecorder { + return m.recorder +} + +// Download mocks base method. +func (m *MockBuildpackDownloader) Download(arg0 context.Context, arg1 string, arg2 BuildpackDownloadOptions) (dist.Buildpack, []dist.Buildpack, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Download", arg0, arg1, arg2) + ret0, _ := ret[0].(dist.Buildpack) + ret1, _ := ret[1].([]dist.Buildpack) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// Download indicates an expected call of Download. +func (mr *MockBuildpackDownloaderMockRecorder) Download(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Download", reflect.TypeOf((*MockBuildpackDownloader)(nil).Download), arg0, arg1, arg2) +} diff --git a/pack.go b/pack.go index 96a45e23c4..311bbb9aa7 100644 --- a/pack.go +++ b/pack.go @@ -5,9 +5,10 @@ import ( "github.com/pkg/errors" - "github.com/buildpacks/pack/image" + "github.com/buildpacks/pack/config" "github.com/buildpacks/pack/internal/buildpackage" "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/image" "github.com/buildpacks/pack/internal/style" ) @@ -16,8 +17,8 @@ var ( Version = "0.0.0" ) -func extractPackagedBuildpacks(ctx context.Context, pkgImageRef string, fetcher ImageFetcher, fetchOptions image.FetchOptions) (mainBP dist.Buildpack, depBPs []dist.Buildpack, err error) { - pkgImage, err := fetcher.Fetch(ctx, pkgImageRef, fetchOptions) +func extractPackagedBuildpacks(ctx context.Context, pkgImageRef string, fetcher ImageFetcher, daemon bool, pullPolicy config.PullPolicy) (mainBP dist.Buildpack, depBPs []dist.Buildpack, err error) { + pkgImage, err := fetcher.Fetch(ctx, pkgImageRef, image.FetchOptions{Daemon: daemon, PullPolicy: pullPolicy}) if err != nil { return nil, nil, errors.Wrapf(err, "fetching image") } diff --git a/package_buildpack.go b/package_buildpack.go index fd073fef8c..9d40bd2753 100644 --- a/package_buildpack.go +++ b/package_buildpack.go @@ -7,7 +7,6 @@ import ( pubbldpkg "github.com/buildpacks/pack/buildpackage" "github.com/buildpacks/pack/config" - "github.com/buildpacks/pack/image" "github.com/buildpacks/pack/internal/blob" "github.com/buildpacks/pack/internal/buildpack" "github.com/buildpacks/pack/internal/buildpackage" @@ -99,7 +98,7 @@ func (c *Client) PackageBuildpack(ctx context.Context, opts PackageBuildpackOpti if dep.ImageName != "" { c.logger.Warn("The 'image' key is deprecated. Use 'uri=\"docker://...\"' instead.") - mainBP, deps, err := extractPackagedBuildpacks(ctx, dep.ImageName, c.imageFetcher, image.FetchOptions{Daemon: !opts.Publish, PullPolicy: opts.PullPolicy}) + mainBP, deps, err := extractPackagedBuildpacks(ctx, dep.ImageName, c.imageFetcher, !opts.Publish, opts.PullPolicy) if err != nil { return err } @@ -140,14 +139,14 @@ func (c *Client) PackageBuildpack(ctx context.Context, opts PackageBuildpackOpti case buildpack.PackageLocator: imageName := buildpack.ParsePackageLocator(dep.URI) c.logger.Debugf("Downloading buildpack from image: %s", style.Symbol(imageName)) - mainBP, deps, err := extractPackagedBuildpacks(ctx, imageName, c.imageFetcher, image.FetchOptions{Daemon: !opts.Publish, PullPolicy: opts.PullPolicy}) + mainBP, deps, err := extractPackagedBuildpacks(ctx, imageName, c.imageFetcher, !opts.Publish, opts.PullPolicy) if err != nil { return err } depBPs = append([]dist.Buildpack{mainBP}, deps...) case buildpack.RegistryLocator: - registryCache, err := c.getRegistry(c.logger, opts.Registry) + registryCache, err := getRegistry(c.logger, opts.Registry) if err != nil { return errors.Wrapf(err, "invalid registry '%s'", opts.Registry) } @@ -157,7 +156,7 @@ func (c *Client) PackageBuildpack(ctx context.Context, opts PackageBuildpackOpti return errors.Wrapf(err, "locating in registry %s", style.Symbol(dep.URI)) } - mainBP, deps, err := extractPackagedBuildpacks(ctx, registryBp.Address, c.imageFetcher, image.FetchOptions{Daemon: !opts.Publish, PullPolicy: opts.PullPolicy}) + mainBP, deps, err := extractPackagedBuildpacks(ctx, registryBp.Address, c.imageFetcher, !opts.Publish, opts.PullPolicy) if err != nil { return errors.Wrapf(err, "extracting from registry %s", style.Symbol(dep.URI)) } diff --git a/package_buildpack_test.go b/package_buildpack_test.go index 1c78924523..478c90c0bc 100644 --- a/package_buildpack_test.go +++ b/package_buildpack_test.go @@ -21,12 +21,12 @@ import ( "github.com/buildpacks/pack" pubbldpkg "github.com/buildpacks/pack/buildpackage" pubcfg "github.com/buildpacks/pack/config" - "github.com/buildpacks/pack/image" "github.com/buildpacks/pack/internal/blob" "github.com/buildpacks/pack/internal/buildpackage" cfg "github.com/buildpacks/pack/internal/config" "github.com/buildpacks/pack/internal/dist" ifakes "github.com/buildpacks/pack/internal/fakes" + "github.com/buildpacks/pack/internal/image" "github.com/buildpacks/pack/internal/logging" "github.com/buildpacks/pack/internal/paths" h "github.com/buildpacks/pack/testhelpers" diff --git a/pull_buildpack.go b/pull_buildpack.go index c328d1b001..5edcba13b0 100644 --- a/pull_buildpack.go +++ b/pull_buildpack.go @@ -7,9 +7,9 @@ import ( "github.com/pkg/errors" "github.com/buildpacks/pack/config" - "github.com/buildpacks/pack/image" "github.com/buildpacks/pack/internal/buildpack" "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/image" "github.com/buildpacks/pack/internal/style" ) @@ -41,7 +41,7 @@ func (c *Client) PullBuildpack(ctx context.Context, opts PullBuildpackOptions) e } case buildpack.RegistryLocator: c.logger.Debugf("Pulling buildpack from registry: %s", style.Symbol(opts.URI)) - registryCache, err := c.getRegistry(c.logger, opts.RegistryName) + registryCache, err := getRegistry(c.logger, opts.RegistryName) if err != nil { return errors.Wrapf(err, "invalid registry '%s'", opts.RegistryName) diff --git a/pull_buildpack_test.go b/pull_buildpack_test.go index 2d49476046..34ace793b6 100644 --- a/pull_buildpack_test.go +++ b/pull_buildpack_test.go @@ -16,8 +16,8 @@ import ( "github.com/buildpacks/pack" "github.com/buildpacks/pack/config" - "github.com/buildpacks/pack/image" cfg "github.com/buildpacks/pack/internal/config" + "github.com/buildpacks/pack/internal/image" "github.com/buildpacks/pack/internal/logging" "github.com/buildpacks/pack/internal/registry" h "github.com/buildpacks/pack/testhelpers" diff --git a/rebase.go b/rebase.go index cb3638e458..3e4e194f90 100644 --- a/rebase.go +++ b/rebase.go @@ -8,10 +8,10 @@ import ( "github.com/pkg/errors" "github.com/buildpacks/pack/config" - "github.com/buildpacks/pack/image" "github.com/buildpacks/pack/internal/build" "github.com/buildpacks/pack/internal/builder" "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/image" "github.com/buildpacks/pack/internal/style" ) diff --git a/register_buildpack.go b/register_buildpack.go index e403b6ac15..2dfa2de6a1 100644 --- a/register_buildpack.go +++ b/register_buildpack.go @@ -8,9 +8,9 @@ import ( "strings" "github.com/buildpacks/pack/config" - "github.com/buildpacks/pack/image" "github.com/buildpacks/pack/internal/buildpackage" "github.com/buildpacks/pack/internal/dist" + "github.com/buildpacks/pack/internal/image" "github.com/buildpacks/pack/internal/registry" ) @@ -78,7 +78,7 @@ func (c *Client) RegisterBuildpack(ctx context.Context, opts RegisterBuildpackOp return cmd.Start() } else if opts.Type == "git" { - registryCache, err := c.getRegistry(c.logger, opts.Name) + registryCache, err := getRegistry(c.logger, opts.Name) if err != nil { return err } diff --git a/testmocks/mock_image_fetcher.go b/testmocks/mock_image_fetcher.go index a645ed14a7..6dc84adec6 100644 --- a/testmocks/mock_image_fetcher.go +++ b/testmocks/mock_image_fetcher.go @@ -11,7 +11,7 @@ import ( imgutil "github.com/buildpacks/imgutil" gomock "github.com/golang/mock/gomock" - image "github.com/buildpacks/pack/image" + image "github.com/buildpacks/pack/internal/image" ) // MockImageFetcher is a mock of ImageFetcher interface.