From f4092ea58d4fe4abf9158fb55eedeac172b42000 Mon Sep 17 00:00:00 2001 From: Jesse Brown Date: Thu, 30 Mar 2023 15:51:34 -0500 Subject: [PATCH] fixup! Copy io.buildpacks.base.* labels on rebase Signed-off-by: Jesse Brown --- platform/files.go | 30 ++++++++++++++++++++++++ rebaser.go | 59 +++++------------------------------------------ rebaser_test.go | 12 +++++----- 3 files changed, 42 insertions(+), 59 deletions(-) diff --git a/platform/files.go b/platform/files.go index 4289b5d16..26ea95f7e 100644 --- a/platform/files.go +++ b/platform/files.go @@ -4,6 +4,7 @@ package platform import ( "encoding/json" + "fmt" "os" "github.com/BurntSushi/toml" @@ -102,6 +103,35 @@ func (t *TargetMetadata) IsSatisfiedBy(o *buildpack.TargetMetadata) bool { return true } +// IsValidRebaseTargetFor treats optional fields (ArchVariant and Distribution fields) as wildcards if empty, returns true if all populated fields match +func (t *TargetMetadata) IsValidRebaseTargetFor(appTargetMetadata *TargetMetadata) bool { + if t.Arch != appTargetMetadata.Arch || t.OS != appTargetMetadata.OS { + return false + } + if t.ArchVariant != "" && appTargetMetadata.ArchVariant != "" && t.ArchVariant != appTargetMetadata.ArchVariant { + return false + } + + if t.Distribution != nil && appTargetMetadata.Distribution != nil { + if t.Distribution.Name != appTargetMetadata.Distribution.Name { + return false + } + if t.Distribution.Version != appTargetMetadata.Distribution.Version { + return false + } + } + return true +} + +func (t *TargetMetadata) String() string { + var distName, distVersion string + if t.Distribution != nil { + distName = t.Distribution.Name + distVersion = t.Distribution.Version + } + return fmt.Sprintf("OS: %s, Arch: %s, ArchVariant: %s, Distribution: (Name: %s, Version: %s)", t.OS, t.Arch, t.ArchVariant, distName, distVersion) +} + func ReadAnalyzed(analyzedPath string, logger log.Logger) (AnalyzedMetadata, error) { var analyzedMD AnalyzedMetadata if _, err := toml.DecodeFile(analyzedPath, &analyzedMD); err != nil { diff --git a/rebaser.go b/rebaser.go index 84ccbcd81..03b4aab04 100644 --- a/rebaser.go +++ b/rebaser.go @@ -146,65 +146,18 @@ func (r *Rebaser) validateRebaseable(appImg imgutil.Image, newBaseImg imgutil.Im // check the OS, architecture, and variant values // if they are not the same, the image cannot be rebased unless the force flag is set if !r.Force { - appOS, err := appImg.OS() + appTarget, err := platform.GetTargetFromImage(appImg) if err != nil { - return errors.Wrap(err, "get app image os") - } - newBaseOS, err := newBaseImg.OS() - if err != nil { - return errors.Wrap(err, "get new base image os") - } - if appOS != newBaseOS { - return fmt.Errorf("incompatible os: '%s' is not compatible with '%s'", newBaseOS, appOS) - } - - appArch, err := appImg.Architecture() - if err != nil { - return errors.Wrap(err, "get app image architecture") - } - newBaseArch, err := newBaseImg.Architecture() - if err != nil { - return errors.Wrap(err, "get new base image architecture") - } - if appArch != newBaseArch { - return fmt.Errorf("incompatible architecture: '%s' is not compatible with '%s'", newBaseArch, appArch) - } - - appVariant, err := appImg.Variant() - if err != nil { - return errors.Wrap(err, "get app image variant") - } - newBaseVariant, err := newBaseImg.Variant() - if err != nil { - return errors.Wrap(err, "get new base image variant") - } - if appVariant != newBaseVariant { - return fmt.Errorf("incompatible variant: '%s' is not compatible with '%s'", newBaseVariant, appVariant) + return errors.Wrap(err, "get app image target") } - // check optional labels OSDistributionName and OSDistributionVersion - distroName, err := appImg.Label(platform.OSDistributionNameLabel) - if err != nil { - return errors.Wrap(err, "get app image os distribution name") - } - newBaseDistroName, err := newBaseImg.Label(platform.OSDistributionNameLabel) + newBaseTarget, err := platform.GetTargetFromImage(newBaseImg) if err != nil { - return errors.Wrap(err, "get new base image os distribution name") - } - if distroName != newBaseDistroName { - return fmt.Errorf("incompatible io.buildpacks.distribution.name: '%s' is not compatible with '%s'", newBaseDistroName, distroName) + return errors.Wrap(err, "get new base image target") } - distroVersion, err := appImg.Label(platform.OSDistributionVersionLabel) - if err != nil { - return errors.Wrap(err, "get app image os distribution version") - } - newBaseDistroVersion, err := newBaseImg.Label(platform.OSDistributionVersionLabel) - if err != nil { - return errors.Wrap(err, "get new base image os distribution version") - } - if distroVersion != newBaseDistroVersion { - return fmt.Errorf("incompatible io.buildpacks.distribution.version: '%s' is not compatible with '%s'", newBaseDistroVersion, distroVersion) + if !newBaseTarget.IsValidRebaseTargetFor(appTarget) { + return fmt.Errorf("invalid base image target: '%s' is not equal to '%s'", newBaseTarget, appTarget) } } } diff --git a/rebaser_test.go b/rebaser_test.go index 4bf004786..73a703435 100644 --- a/rebaser_test.go +++ b/rebaser_test.go @@ -436,7 +436,7 @@ func testRebaser(t *testing.T, when spec.G, it spec.S) { h.AssertNil(t, fakeNewBaseImage.SetOS("notlinux")) _, err := rebaser.Rebase(fakeAppImage, fakeNewBaseImage, fakeAppImage.Name(), additionalNames) - h.AssertError(t, err, "incompatible os: 'notlinux' is not compatible with 'linux'") + h.AssertError(t, err, "invalid base image target: 'OS: notlinux, Arch: amd64, ArchVariant: , Distribution: (Name: , Version: )' is not equal to 'OS: linux, Arch: amd64, ArchVariant: , Distribution: (Name: , Version: )'") }) it("returns an error and prevents the rebase from taking place when the architecture are different", func() { @@ -444,15 +444,15 @@ func testRebaser(t *testing.T, when spec.G, it spec.S) { h.AssertNil(t, fakeNewBaseImage.SetArchitecture("arm64")) _, err := rebaser.Rebase(fakeAppImage, fakeNewBaseImage, fakeAppImage.Name(), additionalNames) - h.AssertError(t, err, "incompatible architecture: 'arm64' is not compatible with 'amd64'") + h.AssertError(t, err, "invalid base image target: 'OS: linux, Arch: arm64, ArchVariant: , Distribution: (Name: , Version: )' is not equal to 'OS: linux, Arch: amd64, ArchVariant: , Distribution: (Name: , Version: )'") }) - it("returns an error and prevents the rebase from taking place when the architecture are different", func() { + it("returns an error and prevents the rebase from taking place when the architecture variant are different", func() { h.AssertNil(t, fakeAppImage.SetVariant("variant1")) h.AssertNil(t, fakeNewBaseImage.SetVariant("variant2")) _, err := rebaser.Rebase(fakeAppImage, fakeNewBaseImage, fakeAppImage.Name(), additionalNames) - h.AssertError(t, err, "incompatible variant: 'variant2' is not compatible with 'variant1'") + h.AssertError(t, err, "invalid base image target: 'OS: linux, Arch: amd64, ArchVariant: variant2, Distribution: (Name: , Version: )' is not equal to 'OS: linux, Arch: amd64, ArchVariant: variant1, Distribution: (Name: , Version: )'") }) it("returns an error and prevents the rebase from taking place when the io.buildpacks.distribution.name are different", func() { @@ -460,7 +460,7 @@ func testRebaser(t *testing.T, when spec.G, it spec.S) { h.AssertNil(t, fakeNewBaseImage.SetLabel("io.buildpacks.distribution.name", "distro2")) _, err := rebaser.Rebase(fakeAppImage, fakeNewBaseImage, fakeAppImage.Name(), additionalNames) - h.AssertError(t, err, "incompatible io.buildpacks.distribution.name: 'distro2' is not compatible with 'distro1'") + h.AssertError(t, err, "invalid base image target: 'OS: linux, Arch: amd64, ArchVariant: , Distribution: (Name: distro2, Version: )' is not equal to 'OS: linux, Arch: amd64, ArchVariant: , Distribution: (Name: distro1, Version: )'") }) it("returns an error and prevents the rebase from taking place when the io.buildpacks.distribution.version are different", func() { @@ -468,7 +468,7 @@ func testRebaser(t *testing.T, when spec.G, it spec.S) { h.AssertNil(t, fakeNewBaseImage.SetLabel("io.buildpacks.distribution.version", "version2")) _, err := rebaser.Rebase(fakeAppImage, fakeNewBaseImage, fakeAppImage.Name(), additionalNames) - h.AssertError(t, err, "incompatible io.buildpacks.distribution.version: 'version2' is not compatible with 'version1'") + h.AssertError(t, err, "invalid base image target: 'OS: linux, Arch: amd64, ArchVariant: , Distribution: (Name: , Version: version2)' is not equal to 'OS: linux, Arch: amd64, ArchVariant: , Distribution: (Name: , Version: version1)'") }) })