Skip to content

Commit b14250b

Browse files
authored
Merge pull request #1969 from buildpacks/bugfix/jjbustamante/issue-1968
Retrying logic when pulling an image and platform doesn't match
2 parents b12c9b3 + 63cf11a commit b14250b

4 files changed

Lines changed: 71 additions & 1 deletion

File tree

acceptance/acceptance_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1551,6 +1551,45 @@ func testAcceptance(
15511551
assertBuildpackOutput := assertions.NewTestBuildpackOutputAssertionManager(t, output)
15521552
assertBuildpackOutput.ReportsBuildStep("Simple Layers Buildpack")
15531553
})
1554+
1555+
when("buildpackage is in a registry", func() {
1556+
it("adds the buildpacks to the builder and runs them", func() {
1557+
h.SkipIf(t, !pack.SupportsFeature(invoke.PlatformRetries), "")
1558+
packageImageName = registryConfig.RepoName("buildpack-" + h.RandString(8))
1559+
1560+
packageTomlPath := generatePackageTomlWithOS(t, assert, pack, tmpDir, "package_for_build_cmd.toml", imageManager.HostOS())
1561+
packageImage := buildpacks.NewPackageImage(
1562+
t,
1563+
pack,
1564+
packageImageName,
1565+
packageTomlPath,
1566+
buildpacks.WithRequiredBuildpacks(
1567+
buildpacks.BpFolderSimpleLayersParent,
1568+
buildpacks.BpFolderSimpleLayers,
1569+
),
1570+
buildpacks.WithPublish(),
1571+
)
1572+
1573+
buildpackManager.PrepareBuildModules(tmpDir, packageImage)
1574+
1575+
output := pack.RunSuccessfully(
1576+
"build", repoName,
1577+
"-p", filepath.Join("testdata", "mock_app"),
1578+
"--buildpack", packageImageName,
1579+
)
1580+
1581+
assertOutput := assertions.NewOutputAssertionManager(t, output)
1582+
assertOutput.ReportsAddingBuildpack(
1583+
"simple/layers/parent",
1584+
"simple-layers-parent-version",
1585+
)
1586+
assertOutput.ReportsAddingBuildpack("simple/layers", "simple-layers-version")
1587+
assertOutput.ReportsSuccessfulImageBuild(repoName)
1588+
1589+
assertBuildpackOutput := assertions.NewTestBuildpackOutputAssertionManager(t, output)
1590+
assertBuildpackOutput.ReportsBuildStep("Simple Layers Buildpack")
1591+
})
1592+
})
15541593
})
15551594

15561595
when("the argument is a buildpackage file", func() {

acceptance/invoke/pack.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ const (
235235
ForceRebase
236236
BuildpackFlatten
237237
MetaBuildpackFolder
238+
PlatformRetries
238239
)
239240

240241
var featureTests = map[Feature]func(i *PackInvoker) bool{
@@ -262,6 +263,9 @@ var featureTests = map[Feature]func(i *PackInvoker) bool{
262263
MetaBuildpackFolder: func(i *PackInvoker) bool {
263264
return i.atLeast("v0.30.0")
264265
},
266+
PlatformRetries: func(i *PackInvoker) bool {
267+
return i.atLeast("v0.32.1")
268+
},
265269
}
266270

267271
func (i *PackInvoker) SupportsFeature(f Feature) bool {

pkg/image/fetcher.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,13 @@ func (f *Fetcher) Fetch(ctx context.Context, name string, options FetchOptions)
109109
}
110110

111111
f.logger.Debugf("Pulling image %s", style.Symbol(name))
112-
err = f.pullImage(ctx, name, options.Platform)
112+
if err = f.pullImage(ctx, name, options.Platform); err != nil {
113+
// sample error from docker engine:
114+
// image with reference <image> was found but does not match the specified platform: wanted linux/amd64, actual: linux
115+
if strings.Contains(err.Error(), "does not match the specified platform") {
116+
err = f.pullImage(ctx, name, "")
117+
}
118+
}
113119
if err != nil && !errors.Is(err, ErrNotFound) {
114120
return nil, err
115121
}

pkg/image/fetcher_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ import (
66
"fmt"
77
"os"
88
"path/filepath"
9+
"runtime"
910
"testing"
1011

12+
"github.com/buildpacks/imgutil"
13+
1114
"github.com/buildpacks/imgutil/local"
1215
"github.com/buildpacks/imgutil/remote"
1316
"github.com/docker/docker/client"
@@ -48,12 +51,17 @@ func testFetcher(t *testing.T, when spec.G, it spec.S) {
4851
repoName string
4952
repo string
5053
outBuf bytes.Buffer
54+
osType string
5155
)
5256

5357
it.Before(func() {
5458
repo = "some-org/" + h.RandString(10)
5559
repoName = registryConfig.RepoName(repo)
5660
imageFetcher = image.NewFetcher(logging.NewLogWithWriters(&outBuf, &outBuf), docker)
61+
62+
info, err := docker.Info(context.TODO())
63+
h.AssertNil(t, err)
64+
osType = info.OSType
5765
})
5866

5967
when("#Fetch", func() {
@@ -213,6 +221,19 @@ func testFetcher(t *testing.T, when spec.G, it spec.S) {
213221
_, err := imageFetcher.Fetch(context.TODO(), repoName, image.FetchOptions{Daemon: true, PullPolicy: image.PullAlways, Platform: "some-unsupported-platform"})
214222
h.AssertError(t, err, "unknown operating system or architecture")
215223
})
224+
225+
when("remote platform does not match", func() {
226+
it.Before(func() {
227+
img, err := remote.NewImage(repoName, authn.DefaultKeychain, remote.WithDefaultPlatform(imgutil.Platform{OS: osType, Architecture: ""}))
228+
h.AssertNil(t, err)
229+
h.AssertNil(t, img.Save())
230+
})
231+
232+
it("retry without setting platform", func() {
233+
_, err := imageFetcher.Fetch(context.TODO(), repoName, image.FetchOptions{Daemon: true, PullPolicy: image.PullAlways, Platform: fmt.Sprintf("%s/%s", osType, runtime.GOARCH)})
234+
h.AssertNil(t, err)
235+
})
236+
})
216237
})
217238
})
218239

0 commit comments

Comments
 (0)