Compare commits
12 Commits
main
...
v0.17.0-rc
Author | SHA1 | Date |
---|---|---|
|
02e9a563eb | |
|
bfc5cda949 | |
|
6bc53d6f70 | |
|
b363b2a3b2 | |
|
87d4f057b8 | |
|
dc6af53456 | |
|
40ac1ee05e | |
|
fbe3cb075d | |
|
c5b14c5bbc | |
|
0580136826 | |
|
495eefbd77 | |
|
147890216d |
|
@ -255,8 +255,7 @@ jobs:
|
|||
- name: Set up go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
check-latest: true
|
||||
go-version-file: 'pack/go.mod'
|
||||
go-version: '1.20.5'
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: version
|
||||
|
@ -297,8 +296,7 @@ jobs:
|
|||
- name: Set up go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
check-latest: true
|
||||
go-version-file: 'pack/go.mod'
|
||||
go-version: '1.20.5'
|
||||
- name: Add runner IP to daemon insecure-registries and firewall
|
||||
shell: powershell
|
||||
run: |
|
||||
|
|
|
@ -20,6 +20,8 @@ import (
|
|||
h "github.com/buildpacks/lifecycle/testhelpers"
|
||||
)
|
||||
|
||||
const emptyImageSHA = "03cbce912ef1a8a658f73c660ab9c539d67188622f00b15c4f15b89b884f0e10"
|
||||
|
||||
var (
|
||||
restoreImage string
|
||||
restoreRegAuthConfig string
|
||||
|
@ -239,6 +241,8 @@ func testRestorerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe
|
|||
h.AssertStringContains(t, analyzedMD.RunImage.Reference, restoreRegFixtures.ReadOnlyRunImage+"@sha256:")
|
||||
h.AssertEq(t, analyzedMD.RunImage.Image, restoreRegFixtures.ReadOnlyRunImage)
|
||||
h.AssertEq(t, analyzedMD.RunImage.TargetMetadata.OS, "linux")
|
||||
t.Log("does not return the digest for an empty image")
|
||||
h.AssertStringDoesNotContain(t, analyzedMD.RunImage.Reference, restoreRegFixtures.ReadOnlyRunImage+"@sha256:"+emptyImageSHA)
|
||||
t.Log("writes run image manifest and config to the kaniko cache")
|
||||
ref, err := name.ParseReference(analyzedMD.RunImage.Reference)
|
||||
h.AssertNil(t, err)
|
||||
|
@ -274,6 +278,8 @@ func testRestorerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe
|
|||
h.AssertStringContains(t, analyzedMD.RunImage.Reference, restoreRegFixtures.ReadOnlyRunImage+"@sha256:")
|
||||
h.AssertEq(t, analyzedMD.RunImage.Image, restoreRegFixtures.ReadOnlyRunImage)
|
||||
h.AssertEq(t, analyzedMD.RunImage.TargetMetadata.OS, "linux")
|
||||
t.Log("does not return the digest for an empty image")
|
||||
h.AssertStringDoesNotContain(t, analyzedMD.RunImage.Reference, restoreRegFixtures.ReadOnlyRunImage+"@sha256:"+emptyImageSHA)
|
||||
t.Log("does not write run image manifest and config to the kaniko cache")
|
||||
fis, err := os.ReadDir(filepath.Join(copyDir, "kaniko"))
|
||||
h.AssertNil(t, err)
|
||||
|
@ -285,6 +291,39 @@ func testRestorerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe
|
|||
h.AssertNil(t, analyzedMD.RunImage.TargetMetadata)
|
||||
}
|
||||
})
|
||||
|
||||
when("-daemon", func() {
|
||||
it("updates run image reference in analyzed.toml to include digest and target data on newer platforms", func() {
|
||||
h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.12"), "Platform API < 0.12 does not support -daemon flag")
|
||||
h.DockerRunAndCopy(t,
|
||||
containerName,
|
||||
copyDir,
|
||||
"/",
|
||||
restoreImage,
|
||||
h.WithFlags(append(
|
||||
dockerSocketMount,
|
||||
"--env", "CNB_PLATFORM_API="+platformAPI,
|
||||
"--env", "DOCKER_CONFIG=/docker-config",
|
||||
"--network", restoreRegNetwork,
|
||||
)...),
|
||||
h.WithArgs(
|
||||
"-analyzed", "/layers/some-extend-false-analyzed.toml",
|
||||
"-daemon",
|
||||
"-log-level", "debug",
|
||||
),
|
||||
)
|
||||
t.Log("updates run image reference in analyzed.toml to include digest and target data")
|
||||
analyzedMD, err := lifecycle.Config.ReadAnalyzed(filepath.Join(copyDir, "layers", "some-extend-false-analyzed.toml"), cmd.DefaultLogger)
|
||||
h.AssertNil(t, err)
|
||||
h.AssertStringDoesNotContain(t, analyzedMD.RunImage.Reference, "@sha256:") // daemon image ID
|
||||
h.AssertEq(t, analyzedMD.RunImage.Image, restoreRegFixtures.ReadOnlyRunImage)
|
||||
h.AssertEq(t, analyzedMD.RunImage.TargetMetadata.OS, "linux")
|
||||
t.Log("does not write run image manifest and config to the kaniko cache")
|
||||
fis, err := os.ReadDir(filepath.Join(copyDir, "kaniko"))
|
||||
h.AssertNil(t, err)
|
||||
h.AssertEq(t, len(fis), 1) // .gitkeep
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ echo
|
|||
echo "CNB_TARGET_ARCH:" `printenv CNB_TARGET_ARCH`
|
||||
echo "CNB_TARGET_ARCH_VARIANT:" `printenv CNB_TARGET_ARCH_VARIANT`
|
||||
echo "CNB_TARGET_OS:" `printenv CNB_TARGET_OS`
|
||||
echo "CNB_TARGET_ID:" `printenv CNB_TARGET_ID`
|
||||
echo "CNB_TARGET_DISTRO_NAME:" `printenv CNB_TARGET_DISTRO_NAME`
|
||||
echo "CNB_TARGET_DISTRO_VERSION:" `printenv CNB_TARGET_DISTRO_VERSION`
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
os = "linux"
|
||||
arch = "amd64"
|
||||
arch-variant = "some-variant"
|
||||
[run-image.target.distribution]
|
||||
[run-image.target.distro]
|
||||
name = "ubuntu"
|
||||
version = "some-cute-version"
|
||||
|
||||
|
|
|
@ -190,6 +190,7 @@ func (f *AnalyzerFactory) setRun(analyzer *Analyzer, imageRef string) error {
|
|||
|
||||
// Analyze fetches the layers metadata from the previous image and writes analyzed.toml.
|
||||
func (a *Analyzer) Analyze() (files.Analyzed, error) {
|
||||
defer log.NewMeasurement("Analyzer", a.Logger)()
|
||||
var (
|
||||
err error
|
||||
appMeta files.LayersMetadata
|
||||
|
|
|
@ -666,14 +666,14 @@ func testAnalyzer(platformAPI string) func(t *testing.T, when spec.G, it spec.S)
|
|||
|
||||
h.AssertEq(t, md.RunImage.Reference, "s0m3D1g3sT")
|
||||
})
|
||||
it("populates Target metadata from the run image", func() {
|
||||
h.AssertNil(t, image.SetLabel("io.buildpacks.id", "id software"))
|
||||
it("populates target metadata from the run image", func() {
|
||||
h.AssertNil(t, image.SetLabel("io.buildpacks.base.id", "id software"))
|
||||
h.AssertNil(t, image.SetOS("windows"))
|
||||
h.AssertNil(t, image.SetOSVersion("95"))
|
||||
h.AssertNil(t, image.SetArchitecture("Pentium"))
|
||||
h.AssertNil(t, image.SetVariant("MMX"))
|
||||
h.AssertNil(t, image.SetLabel("io.buildpacks.distribution.name", "moobuntu"))
|
||||
h.AssertNil(t, image.SetLabel("io.buildpacks.distribution.version", "Helpful Holstein"))
|
||||
h.AssertNil(t, image.SetLabel("io.buildpacks.distro.name", "moobuntu"))
|
||||
h.AssertNil(t, image.SetLabel("io.buildpacks.distro.version", "Helpful Holstein"))
|
||||
|
||||
md, err := analyzer.Analyze()
|
||||
h.AssertNil(t, err)
|
||||
|
@ -685,9 +685,9 @@ func testAnalyzer(platformAPI string) func(t *testing.T, when spec.G, it spec.S)
|
|||
h.AssertEq(t, md.RunImage.TargetMetadata.ArchVariant, "MMX")
|
||||
h.AssertEq(t, md.RunImage.TargetMetadata.OS, "windows")
|
||||
h.AssertEq(t, md.RunImage.TargetMetadata.ID, "id software")
|
||||
h.AssertNotNil(t, md.RunImage.TargetMetadata.Distribution)
|
||||
h.AssertEq(t, md.RunImage.TargetMetadata.Distribution.Name, "moobuntu")
|
||||
h.AssertEq(t, md.RunImage.TargetMetadata.Distribution.Version, "Helpful Holstein")
|
||||
h.AssertNotNil(t, md.RunImage.TargetMetadata.Distro)
|
||||
h.AssertEq(t, md.RunImage.TargetMetadata.Distro.Name, "moobuntu")
|
||||
h.AssertEq(t, md.RunImage.TargetMetadata.Distro.Version, "Helpful Holstein")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
@ -49,7 +49,7 @@ type Builder struct {
|
|||
}
|
||||
|
||||
func (b *Builder) Build() (*files.BuildMetadata, error) {
|
||||
b.Logger.Debug("Starting build")
|
||||
defer log.NewMeasurement("Builder", b.Logger)()
|
||||
|
||||
// ensure layers SBOM directory is removed
|
||||
if err := os.RemoveAll(filepath.Join(b.LayersDir, "sbom")); err != nil {
|
||||
|
@ -142,7 +142,6 @@ func (b *Builder) Build() (*files.BuildMetadata, error) {
|
|||
b.Group.GroupExtensions[i] = ext.NoExtension().NoOpt()
|
||||
}
|
||||
|
||||
b.Logger.Debug("Finished build")
|
||||
return &files.BuildMetadata{
|
||||
BOM: launchBOM,
|
||||
Buildpacks: b.Group.Group,
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
package buildpack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
|
||||
"github.com/buildpacks/lifecycle/internal/encoding"
|
||||
)
|
||||
|
||||
type BpDescriptor struct {
|
||||
|
@ -25,29 +26,22 @@ type StackMetadata struct {
|
|||
}
|
||||
|
||||
type TargetMetadata struct {
|
||||
OS string `json:"os" toml:"os"`
|
||||
Arch string `json:"arch" toml:"arch"`
|
||||
ArchVariant string `json:"arch-variant,omitempty" toml:"arch-variant"`
|
||||
Distributions []OSDistribution `json:"distributions,omitempty" toml:"distributions"`
|
||||
OS string `json:"os" toml:"os"`
|
||||
Arch string `json:"arch" toml:"arch"`
|
||||
ArchVariant string `json:"arch-variant,omitempty" toml:"arch-variant"`
|
||||
Distros []OSDistro `json:"distros,omitempty" toml:"distros"`
|
||||
}
|
||||
|
||||
func (t *TargetMetadata) String() string {
|
||||
s := fmt.Sprintf("OS: %s, Arch: %s, ArchVariant: %s", t.OS, t.Arch, t.ArchVariant)
|
||||
if len(t.Distributions) > 0 {
|
||||
s += fmt.Sprintf(", Distributions: %s", t.Distributions)
|
||||
}
|
||||
return s
|
||||
return encoding.ToJSONMaybe(*t)
|
||||
}
|
||||
|
||||
type OSDistribution struct {
|
||||
// OSDistro is an OS distribution that a buildpack or extension can support.
|
||||
type OSDistro struct {
|
||||
Name string `json:"name" toml:"name"`
|
||||
Version string `json:"version" toml:"version"`
|
||||
}
|
||||
|
||||
func (d OSDistribution) String() string {
|
||||
return fmt.Sprintf("Distribution: (Name: %s, Version: %s)", d.Name, d.Version)
|
||||
}
|
||||
|
||||
type BpInfo struct {
|
||||
BaseInfo
|
||||
SBOM []string `toml:"sbom-formats,omitempty" json:"sbom-formats,omitempty"`
|
||||
|
@ -75,9 +69,9 @@ func ReadBpDescriptor(path string) (*BpDescriptor, error) {
|
|||
if len(descriptor.Targets) == 0 {
|
||||
for _, stack := range descriptor.Stacks {
|
||||
if stack.ID == "io.buildpacks.stacks.bionic" {
|
||||
descriptor.Targets = append(descriptor.Targets, TargetMetadata{OS: "linux", Arch: "amd64", Distributions: []OSDistribution{{Name: "ubuntu", Version: "18.04"}}})
|
||||
descriptor.Targets = append(descriptor.Targets, TargetMetadata{OS: "linux", Arch: "amd64", Distros: []OSDistro{{Name: "ubuntu", Version: "18.04"}}})
|
||||
} else if stack.ID == "*" {
|
||||
descriptor.Targets = append(descriptor.Targets, TargetMetadata{OS: "*", Arch: "*", Distributions: []OSDistribution{}})
|
||||
descriptor.Targets = append(descriptor.Targets, TargetMetadata{}) // matches any
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -93,10 +87,10 @@ func ReadBpDescriptor(path string) (*BpDescriptor, error) {
|
|||
bf := binFiles[len(binFiles)-i-1] // we're iterating backwards b/c os.ReadDir sorts "build.exe" after "build" but we want to preferentially detect windows first.
|
||||
fname := bf.Name()
|
||||
if fname == "build.exe" || fname == "build.bat" {
|
||||
descriptor.Targets = append(descriptor.Targets, TargetMetadata{OS: "windows", Arch: "*"})
|
||||
descriptor.Targets = append(descriptor.Targets, TargetMetadata{OS: "windows"})
|
||||
}
|
||||
if fname == "build" {
|
||||
descriptor.Targets = append(descriptor.Targets, TargetMetadata{OS: "linux", Arch: "*"})
|
||||
descriptor.Targets = append(descriptor.Targets, TargetMetadata{OS: "linux"})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,14 +24,14 @@ func testBpDescriptor(t *testing.T, when spec.G, it spec.S) {
|
|||
OS: "some-os",
|
||||
Arch: "some-arch",
|
||||
ArchVariant: "some-arch-variant",
|
||||
Distributions: []buildpack.OSDistribution{
|
||||
Distros: []buildpack.OSDistro{
|
||||
{
|
||||
Name: "some-os-dist",
|
||||
Version: "some-os-dist-version",
|
||||
},
|
||||
},
|
||||
}
|
||||
h.AssertEq(t, tm.String(), "OS: some-os, Arch: some-arch, ArchVariant: some-arch-variant, Distributions: [Distribution: (Name: some-os-dist, Version: some-os-dist-version)]")
|
||||
h.AssertEq(t, tm.String(), `{"os":"some-os","arch":"some-arch","arch-variant":"some-arch-variant","distros":[{"name":"some-os-dist","version":"some-os-dist-version"}]}`)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -42,7 +42,7 @@ func testBpDescriptor(t *testing.T, when spec.G, it spec.S) {
|
|||
Arch: "some-arch",
|
||||
ArchVariant: "some-arch-variant",
|
||||
}
|
||||
h.AssertEq(t, tm.String(), "OS: some-os, Arch: some-arch, ArchVariant: some-arch-variant")
|
||||
h.AssertEq(t, tm.String(), `{"os":"some-os","arch":"some-arch","arch-variant":"some-arch-variant"}`)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -77,8 +77,8 @@ func testBpDescriptor(t *testing.T, when spec.G, it spec.S) {
|
|||
h.AssertEq(t, len(descriptor.Targets), 1)
|
||||
h.AssertEq(t, descriptor.Targets[0].Arch, "IA64")
|
||||
h.AssertEq(t, descriptor.Targets[0].OS, "OpenVMS")
|
||||
h.AssertEq(t, descriptor.Targets[0].Distributions[0].Name, "VSI OpenVMS")
|
||||
h.AssertEq(t, descriptor.Targets[0].Distributions[0].Version, "V8.4-2L3")
|
||||
h.AssertEq(t, descriptor.Targets[0].Distros[0].Name, "VSI OpenVMS")
|
||||
h.AssertEq(t, descriptor.Targets[0].Distros[0].Version, "V8.4-2L3")
|
||||
})
|
||||
|
||||
it("does translate one special stack value into target values for older apis", func() {
|
||||
|
@ -97,8 +97,8 @@ func testBpDescriptor(t *testing.T, when spec.G, it spec.S) {
|
|||
h.AssertEq(t, len(descriptor.Targets), 1)
|
||||
h.AssertEq(t, descriptor.Targets[0].Arch, "amd64")
|
||||
h.AssertEq(t, descriptor.Targets[0].OS, "linux")
|
||||
h.AssertEq(t, descriptor.Targets[0].Distributions[0].Name, "ubuntu")
|
||||
h.AssertEq(t, descriptor.Targets[0].Distributions[0].Version, "18.04")
|
||||
h.AssertEq(t, descriptor.Targets[0].Distros[0].Name, "ubuntu")
|
||||
h.AssertEq(t, descriptor.Targets[0].Distros[0].Version, "18.04")
|
||||
})
|
||||
|
||||
it("translates one special stack value into target values", func() {
|
||||
|
@ -117,8 +117,8 @@ func testBpDescriptor(t *testing.T, when spec.G, it spec.S) {
|
|||
h.AssertEq(t, len(descriptor.Targets), 1)
|
||||
h.AssertEq(t, descriptor.Targets[0].Arch, "amd64")
|
||||
h.AssertEq(t, descriptor.Targets[0].OS, "linux")
|
||||
h.AssertEq(t, descriptor.Targets[0].Distributions[0].Name, "ubuntu")
|
||||
h.AssertEq(t, descriptor.Targets[0].Distributions[0].Version, "18.04")
|
||||
h.AssertEq(t, descriptor.Targets[0].Distros[0].Name, "ubuntu")
|
||||
h.AssertEq(t, descriptor.Targets[0].Distros[0].Version, "18.04")
|
||||
})
|
||||
|
||||
it("does not translate non-special stack values", func() {
|
||||
|
@ -152,9 +152,9 @@ func testBpDescriptor(t *testing.T, when spec.G, it spec.S) {
|
|||
h.AssertEq(t, descriptor.Stacks[0].ID, "some.non-magic.value")
|
||||
h.AssertEq(t, len(descriptor.Targets), 1)
|
||||
h.AssertEq(t, len(descriptor.Targets), 1)
|
||||
h.AssertEq(t, descriptor.Targets[0].Arch, "*")
|
||||
h.AssertEq(t, descriptor.Targets[0].Arch, "")
|
||||
h.AssertEq(t, descriptor.Targets[0].OS, "linux")
|
||||
h.AssertEq(t, len(descriptor.Targets[0].Distributions), 0)
|
||||
h.AssertEq(t, len(descriptor.Targets[0].Distros), 0)
|
||||
})
|
||||
|
||||
it("detects windows/* if batch files are present and ignores linux", func() {
|
||||
|
@ -170,9 +170,9 @@ func testBpDescriptor(t *testing.T, when spec.G, it spec.S) {
|
|||
h.AssertEq(t, descriptor.Buildpack.SBOM, []string{"application/vnd.cyclonedx+json"})
|
||||
// specific behaviors for this test
|
||||
h.AssertEq(t, len(descriptor.Targets), 2)
|
||||
h.AssertEq(t, descriptor.Targets[0].Arch, "*")
|
||||
h.AssertEq(t, descriptor.Targets[0].Arch, "")
|
||||
h.AssertEq(t, descriptor.Targets[0].OS, "windows")
|
||||
h.AssertEq(t, descriptor.Targets[1].Arch, "*")
|
||||
h.AssertEq(t, descriptor.Targets[1].Arch, "")
|
||||
h.AssertEq(t, descriptor.Targets[1].OS, "linux")
|
||||
})
|
||||
})
|
||||
|
|
|
@ -48,19 +48,18 @@ func (d *ExtDescriptor) inferTargets() error {
|
|||
bf := binFiles[len(binFiles)-i-1] // we're iterating backwards b/c os.ReadDir sorts "foo.exe" after "foo" but we want to preferentially detect windows first.
|
||||
fname := bf.Name()
|
||||
if !windowsDetected && (fname == "detect.exe" || fname == "detect.bat" || fname == "generate.exe" || fname == "generate.bat") {
|
||||
d.Targets = append(d.Targets, TargetMetadata{OS: "windows", Arch: "*"})
|
||||
d.Targets = append(d.Targets, TargetMetadata{OS: "windows"})
|
||||
windowsDetected = true
|
||||
}
|
||||
if !linuxDetected && (fname == "detect" || fname == "generate") {
|
||||
d.Targets = append(d.Targets, TargetMetadata{OS: "linux", Arch: "*"})
|
||||
d.Targets = append(d.Targets, TargetMetadata{OS: "linux"})
|
||||
linuxDetected = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// fallback: if nothing worked just mark it */*
|
||||
if len(d.Targets) == 0 {
|
||||
d.Targets = append(d.Targets, TargetMetadata{OS: "*", Arch: "*"})
|
||||
d.Targets = append(d.Targets, TargetMetadata{}) // matches any
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -29,15 +29,15 @@ func testExtDescriptor(t *testing.T, when spec.G, it spec.S) {
|
|||
h.AssertEq(t, descriptor.Extension.Homepage, "Extension A Homepage")
|
||||
h.AssertEq(t, len(descriptor.Targets), 1)
|
||||
h.AssertEq(t, descriptor.Targets[0].OS, "linux")
|
||||
h.AssertEq(t, descriptor.Targets[0].Arch, "*")
|
||||
h.AssertEq(t, descriptor.Targets[0].Arch, "")
|
||||
})
|
||||
it("infers */* if there's no files to infer from", func() {
|
||||
path := filepath.Join("testdata", "extension", "by-id", "B", "v1", "extension.toml")
|
||||
descriptor, err := buildpack.ReadExtDescriptor(path)
|
||||
h.AssertNil(t, err)
|
||||
h.AssertEq(t, len(descriptor.Targets), 1)
|
||||
h.AssertEq(t, descriptor.Targets[0].OS, "*")
|
||||
h.AssertEq(t, descriptor.Targets[0].Arch, "*")
|
||||
h.AssertEq(t, descriptor.Targets[0].OS, "")
|
||||
h.AssertEq(t, descriptor.Targets[0].Arch, "")
|
||||
})
|
||||
it("slices, it dices, it even does windows", func() {
|
||||
path := filepath.Join("testdata", "extension", "by-id", "D", "v1", "extension.toml")
|
||||
|
@ -45,7 +45,7 @@ func testExtDescriptor(t *testing.T, when spec.G, it spec.S) {
|
|||
h.AssertNil(t, err)
|
||||
h.AssertEq(t, len(descriptor.Targets), 1)
|
||||
h.AssertEq(t, descriptor.Targets[0].OS, "windows")
|
||||
h.AssertEq(t, descriptor.Targets[0].Arch, "*")
|
||||
h.AssertEq(t, descriptor.Targets[0].Arch, "")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -10,6 +10,6 @@ sbom-formats = ["application/vnd.cyclonedx+json"]
|
|||
[[targets]]
|
||||
os = "OpenVMS"
|
||||
arch = "IA64"
|
||||
[[targets.distributions]]
|
||||
[[targets.distros]]
|
||||
name = "VSI OpenVMS"
|
||||
version = "V8.4-2L3"
|
||||
|
|
1
cache.go
1
cache.go
|
@ -19,6 +19,7 @@ type LayerDir interface {
|
|||
}
|
||||
|
||||
func (e *Exporter) Cache(layersDir string, cacheStore Cache) error {
|
||||
defer log.NewMeasurement("Cache", e.Logger)()
|
||||
var err error
|
||||
if !cacheStore.Exists() {
|
||||
e.Logger.Info("Layer cache not found")
|
||||
|
|
|
@ -269,19 +269,19 @@ func testCache(t *testing.T, when spec.G, it spec.S) {
|
|||
AnyTimes()
|
||||
layersDir = filepath.Join("testdata", "cacher", "invalid-layers")
|
||||
h.AssertNil(t, exporter.Cache(layersDir, testCache))
|
||||
h.AssertEq(t, len(logHandler.Entries), 3)
|
||||
h.AssertEq(t, len(logHandler.Entries), 5)
|
||||
})
|
||||
|
||||
it("warns when there is a cache=true layer without contents", func() {
|
||||
h.AssertStringContains(t, logHandler.Entries[0].Message, "Failed to cache layer 'buildpack.id:cache-true-no-contents' because it has no contents")
|
||||
h.AssertStringContains(t, logHandler.Entries[1].Message, "Failed to cache layer 'buildpack.id:cache-true-no-contents' because it has no contents")
|
||||
})
|
||||
|
||||
it("warns when there is an error adding a layer", func() {
|
||||
h.AssertStringContains(t, logHandler.Entries[1].Message, "Failed to cache layer 'buildpack.id:layer-1': creating layer 'buildpack.id:layer-1': test error")
|
||||
h.AssertStringContains(t, logHandler.Entries[2].Message, "Failed to cache layer 'buildpack.id:layer-1': creating layer 'buildpack.id:layer-1': test error")
|
||||
})
|
||||
|
||||
it("continues caching valid layers", func() {
|
||||
h.AssertStringContains(t, logHandler.Entries[2].Message, "Adding cache layer 'buildpack.id:layer-2'")
|
||||
h.AssertStringContains(t, logHandler.Entries[3].Message, "Adding cache layer 'buildpack.id:layer-2'")
|
||||
assertCacheHasLayer(t, testCache, "buildpack.id:layer-2")
|
||||
})
|
||||
})
|
||||
|
|
|
@ -57,6 +57,12 @@ func Run(c Command, withPhaseName string, asSubcommand bool) {
|
|||
}
|
||||
cmd.DefaultLogger.Debugf("Starting %s...", withPhaseName)
|
||||
|
||||
for _, arg := range flagSet.Args() {
|
||||
if arg[0:1] == "-" {
|
||||
cmd.DefaultLogger.Warnf("Warning: unconsumed flag-like positional arg: \n\t%s\n\t This will not be interpreted as a flag.\n\t Did you mean to put this before the first positional argument?", arg)
|
||||
}
|
||||
}
|
||||
|
||||
// Warn when CNB_PLATFORM_API is unset
|
||||
if os.Getenv(platform.EnvPlatformAPI) == "" {
|
||||
cmd.DefaultLogger.Warnf("%s is unset; using Platform API version '%s'", platform.EnvPlatformAPI, platform.DefaultPlatformAPI)
|
||||
|
|
|
@ -75,7 +75,7 @@ func subcommand(platformAPI string) {
|
|||
case "extend":
|
||||
cli.Run(&extendCmd{Platform: platform.NewPlatformFor(platformAPI)}, phase, true)
|
||||
default:
|
||||
cmd.Exit(cmd.FailCode(cmd.CodeForInvalidArgs, "unknown phase:", phase))
|
||||
cmd.Exit(cmd.FailCode(cmd.CodeForInvalidArgs, "recognize phase:", phase, "\nValid phases: detect, analyze, restore, build, export, rebase, create, extend"))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/buildpacks/imgutil/layout"
|
||||
"github.com/buildpacks/imgutil/layout/sparse"
|
||||
"github.com/buildpacks/imgutil/remote"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/google/go-containerregistry/pkg/authn"
|
||||
|
||||
"github.com/buildpacks/lifecycle"
|
||||
|
@ -17,6 +18,7 @@ import (
|
|||
"github.com/buildpacks/lifecycle/buildpack"
|
||||
"github.com/buildpacks/lifecycle/cmd"
|
||||
"github.com/buildpacks/lifecycle/cmd/lifecycle/cli"
|
||||
"github.com/buildpacks/lifecycle/image"
|
||||
"github.com/buildpacks/lifecycle/internal/encoding"
|
||||
"github.com/buildpacks/lifecycle/internal/layer"
|
||||
"github.com/buildpacks/lifecycle/platform"
|
||||
|
@ -29,12 +31,14 @@ const kanikoDir = "/kaniko"
|
|||
type restoreCmd struct {
|
||||
*platform.Platform
|
||||
|
||||
keychain authn.Keychain // construct if necessary before dropping privileges
|
||||
docker client.CommonAPIClient // construct if necessary before dropping privileges
|
||||
keychain authn.Keychain // construct if necessary before dropping privileges
|
||||
}
|
||||
|
||||
// DefineFlags defines the flags that are considered valid and reads their values (if provided).
|
||||
func (r *restoreCmd) DefineFlags() {
|
||||
if r.PlatformAPI.AtLeast("0.12") {
|
||||
cli.FlagUseDaemon(&r.UseDaemon)
|
||||
cli.FlagGeneratedDir(&r.GeneratedDir)
|
||||
}
|
||||
if r.PlatformAPI.AtLeast("0.10") {
|
||||
|
@ -46,9 +50,10 @@ func (r *restoreCmd) DefineFlags() {
|
|||
}
|
||||
cli.FlagCacheDir(&r.CacheDir)
|
||||
cli.FlagCacheImage(&r.CacheImageRef)
|
||||
cli.FlagGroupPath(&r.GroupPath)
|
||||
cli.FlagUID(&r.UID)
|
||||
cli.FlagGID(&r.GID)
|
||||
cli.FlagGroupPath(&r.GroupPath)
|
||||
cli.FlagLayersDir(&r.LayersDir)
|
||||
cli.FlagUID(&r.UID)
|
||||
}
|
||||
|
||||
// Args validates arguments and flags, and fills in default values.
|
||||
|
@ -68,6 +73,13 @@ func (r *restoreCmd) Privileges() error {
|
|||
if err != nil {
|
||||
return cmd.FailErr(err, "resolve keychain")
|
||||
}
|
||||
if r.UseDaemon {
|
||||
var err error
|
||||
r.docker, err = priv.DockerClient()
|
||||
if err != nil {
|
||||
return cmd.FailErr(err, "initialize docker client")
|
||||
}
|
||||
}
|
||||
if err = priv.EnsureOwner(r.UID, r.GID, r.LayersDir, r.CacheDir, r.KanikoDir); err != nil {
|
||||
return cmd.FailErr(err, "chown volumes")
|
||||
}
|
||||
|
@ -98,28 +110,29 @@ func (r *restoreCmd) Exec() error {
|
|||
cmd.DefaultLogger.Debugf(encoding.ToJSONMaybe(analyzedMD.BuildImage))
|
||||
}
|
||||
var (
|
||||
remoteRunImage imgutil.Image
|
||||
runImage imgutil.Image
|
||||
)
|
||||
runImageName := analyzedMD.RunImageImage() // FIXME: if we have a digest reference available in `Reference` (e.g., in the non-daemon case) we should use it
|
||||
if r.supportsRunImageExtension() && needsPulling(analyzedMD.RunImage) {
|
||||
cmd.DefaultLogger.Debugf("Pulling run image metadata for %s...", runImageName)
|
||||
remoteRunImage, err = r.pullSparse(runImageName)
|
||||
runImage, err = r.pullSparse(runImageName)
|
||||
if err != nil {
|
||||
return cmd.FailErr(err, "pull run image")
|
||||
}
|
||||
// update analyzed metadata, even if we only needed to pull the image metadata, because
|
||||
// the extender needs a digest reference in analyzed.toml,
|
||||
// and daemon images will only have a daemon image ID
|
||||
if err = updateAnalyzedMD(&analyzedMD, remoteRunImage); err != nil {
|
||||
if err = updateAnalyzedMD(&analyzedMD, runImage); err != nil {
|
||||
return cmd.FailErr(err, "update analyzed metadata")
|
||||
}
|
||||
} else if r.supportsTargetData() && needsUpdating(analyzedMD.RunImage) {
|
||||
cmd.DefaultLogger.Debugf("Updating run image info in analyzed metadata...")
|
||||
remoteRunImage, err = remote.NewImage(runImageName, r.keychain)
|
||||
if err != nil || !remoteRunImage.Found() {
|
||||
h := image.NewHandler(r.docker, r.keychain, r.LayoutDir, r.UseLayout)
|
||||
runImage, err = h.InitImage(runImageName)
|
||||
if err != nil || !runImage.Found() {
|
||||
return cmd.FailErr(err, "pull run image")
|
||||
}
|
||||
if err = updateAnalyzedMD(&analyzedMD, remoteRunImage); err != nil {
|
||||
if err = updateAnalyzedMD(&analyzedMD, runImage); err != nil {
|
||||
return cmd.FailErr(err, "update analyzed metadata")
|
||||
}
|
||||
}
|
||||
|
@ -197,7 +210,7 @@ func (r *restoreCmd) supportsBuildImageExtension() bool {
|
|||
}
|
||||
|
||||
func (r *restoreCmd) supportsRunImageExtension() bool {
|
||||
return r.PlatformAPI.AtLeast("0.12")
|
||||
return r.PlatformAPI.AtLeast("0.12") && !r.UseLayout // FIXME: add layout support as part of https://github.com/buildpacks/lifecycle/issues/1057
|
||||
}
|
||||
|
||||
func (r *restoreCmd) supportsTargetData() bool {
|
||||
|
|
|
@ -126,6 +126,7 @@ func (f *DetectorFactory) verifyAPIs(orderBp buildpack.Order, orderExt buildpack
|
|||
}
|
||||
|
||||
func (d *Detector) Detect() (buildpack.Group, files.Plan, error) {
|
||||
defer log.NewMeasurement("Detector", d.Logger)()
|
||||
group, plan, detectErr := d.DetectOrder(d.Order)
|
||||
for _, e := range d.memHandler.Entries {
|
||||
if detectErr != nil || e.Level >= d.Logger.LogLevel() {
|
||||
|
@ -196,7 +197,7 @@ func isWildcard(t files.TargetMetadata) bool {
|
|||
|
||||
func hasWildcard(ts []buildpack.TargetMetadata) bool {
|
||||
for _, tm := range ts {
|
||||
if tm.OS == "*" && tm.Arch == "*" {
|
||||
if tm.OS == "" && tm.Arch == "" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -826,9 +826,9 @@ func testDetector(t *testing.T, when spec.G, it spec.S) {
|
|||
it("totally works if the constraints are met", func() {
|
||||
detector.AnalyzeMD.RunImage = &files.RunImage{
|
||||
TargetMetadata: &files.TargetMetadata{
|
||||
OS: "MacOS",
|
||||
Arch: "ARM64",
|
||||
Distribution: &files.OSDistribution{Name: "MacOS", Version: "snow cheetah"},
|
||||
OS: "MacOS",
|
||||
Arch: "ARM64",
|
||||
Distro: &files.OSDistro{Name: "MacOS", Version: "snow cheetah"},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -837,9 +837,9 @@ func testDetector(t *testing.T, when spec.G, it spec.S) {
|
|||
Buildpack: buildpack.BpInfo{BaseInfo: buildpack.BaseInfo{ID: "A", Version: "v1"}},
|
||||
Targets: []buildpack.TargetMetadata{
|
||||
{Arch: "P6", ArchVariant: "Pentium Pro", OS: "Win95",
|
||||
Distributions: []buildpack.OSDistribution{
|
||||
Distros: []buildpack.OSDistro{
|
||||
{Name: "Windows 95", Version: "OSR1"}, {Name: "Windows 95", Version: "OSR2.5"}}},
|
||||
{Arch: "ARM64", OS: "MacOS", Distributions: []buildpack.OSDistribution{{Name: "MacOS", Version: "snow cheetah"}}}},
|
||||
{Arch: "ARM64", OS: "MacOS", Distros: []buildpack.OSDistro{{Name: "MacOS", Version: "snow cheetah"}}}},
|
||||
}
|
||||
dirStore.EXPECT().LookupBp("A", "v1").Return(bpA1, nil).AnyTimes()
|
||||
executor.EXPECT().Detect(bpA1, gomock.Any(), gomock.Any())
|
||||
|
@ -862,9 +862,9 @@ func testDetector(t *testing.T, when spec.G, it spec.S) {
|
|||
it("was born to be wildcard compliant", func() {
|
||||
detector.AnalyzeMD.RunImage = &files.RunImage{
|
||||
TargetMetadata: &files.TargetMetadata{
|
||||
OS: "MacOS",
|
||||
Arch: "ARM64",
|
||||
Distribution: &files.OSDistribution{Name: "MacOS", Version: "snow cheetah"},
|
||||
OS: "MacOS",
|
||||
Arch: "ARM64",
|
||||
Distro: &files.OSDistro{Name: "MacOS", Version: "snow cheetah"},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -872,7 +872,7 @@ func testDetector(t *testing.T, when spec.G, it spec.S) {
|
|||
WithAPI: "0.12",
|
||||
Buildpack: buildpack.BpInfo{BaseInfo: buildpack.BaseInfo{ID: "A", Version: "v1"}},
|
||||
Targets: []buildpack.TargetMetadata{
|
||||
{Arch: "*", OS: "*"}},
|
||||
{Arch: "", OS: ""}},
|
||||
}
|
||||
dirStore.EXPECT().LookupBp("A", "v1").Return(bpA1, nil).AnyTimes()
|
||||
executor.EXPECT().Detect(bpA1, gomock.Any(), gomock.Any())
|
||||
|
@ -896,9 +896,9 @@ func testDetector(t *testing.T, when spec.G, it spec.S) {
|
|||
it("totally works if the constraints are met", func() {
|
||||
detector.AnalyzeMD.RunImage = &files.RunImage{
|
||||
TargetMetadata: &files.TargetMetadata{
|
||||
OS: "MacOS",
|
||||
Arch: "ARM64",
|
||||
Distribution: &files.OSDistribution{Name: "MacOS", Version: "snow cheetah"},
|
||||
OS: "MacOS",
|
||||
Arch: "ARM64",
|
||||
Distro: &files.OSDistro{Name: "MacOS", Version: "snow cheetah"},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -917,9 +917,9 @@ func testDetector(t *testing.T, when spec.G, it spec.S) {
|
|||
Buildpack: buildpack.BpInfo{BaseInfo: buildpack.BaseInfo{ID: "A", Version: "v1"}},
|
||||
Targets: []buildpack.TargetMetadata{
|
||||
{Arch: "P6", ArchVariant: "Pentium Pro", OS: "Win95",
|
||||
Distributions: []buildpack.OSDistribution{
|
||||
Distros: []buildpack.OSDistro{
|
||||
{Name: "Windows 95", Version: "OSR1"}, {Name: "Windows 95", Version: "OSR2.5"}}},
|
||||
{Arch: "ARM64", OS: "MacOS", Distributions: []buildpack.OSDistribution{{Name: "MacOS", Version: "snow cheetah"}}}},
|
||||
{Arch: "ARM64", OS: "MacOS", Distros: []buildpack.OSDistro{{Name: "MacOS", Version: "snow cheetah"}}}},
|
||||
}
|
||||
dirStore.EXPECT().LookupBp("A", "v1").Return(bpA1, nil).AnyTimes()
|
||||
|
||||
|
@ -946,9 +946,9 @@ func testDetector(t *testing.T, when spec.G, it spec.S) {
|
|||
it("errors if the buildpacks don't share that target arch/os", func() {
|
||||
detector.AnalyzeMD.RunImage = &files.RunImage{
|
||||
TargetMetadata: &files.TargetMetadata{
|
||||
OS: "MacOS",
|
||||
Arch: "ARM64",
|
||||
Distribution: &files.OSDistribution{Name: "MacOS", Version: "some kind of big cat"},
|
||||
OS: "MacOS",
|
||||
Arch: "ARM64",
|
||||
Distro: &files.OSDistro{Name: "MacOS", Version: "some kind of big cat"},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -957,10 +957,10 @@ func testDetector(t *testing.T, when spec.G, it spec.S) {
|
|||
Buildpack: buildpack.BpInfo{BaseInfo: buildpack.BaseInfo{ID: "A", Version: "v1"}},
|
||||
Targets: []buildpack.TargetMetadata{
|
||||
{Arch: "P6", ArchVariant: "Pentium Pro", OS: "Win95",
|
||||
Distributions: []buildpack.OSDistribution{
|
||||
Distros: []buildpack.OSDistro{
|
||||
{Name: "Windows 95", Version: "OSR1"}, {Name: "Windows 95", Version: "OSR2.5"}}},
|
||||
{Arch: "Pentium M", OS: "Win98",
|
||||
Distributions: []buildpack.OSDistribution{{Name: "Windows 2000", Version: "Server"}}},
|
||||
Distros: []buildpack.OSDistro{{Name: "Windows 2000", Version: "Server"}}},
|
||||
},
|
||||
}
|
||||
dirStore.EXPECT().LookupBp("A", "v1").Return(bpA1, nil).AnyTimes()
|
||||
|
@ -972,7 +972,7 @@ func testDetector(t *testing.T, when spec.G, it spec.S) {
|
|||
h.AssertEq(t, ok, true)
|
||||
outs := val.(buildpack.DetectOutputs)
|
||||
h.AssertEq(t, outs.Code, -1)
|
||||
h.AssertStringContains(t, outs.Err.Error(), `unable to satisfy target os/arch constraints; run image: {"os":"MacOS","arch":"ARM64","distribution":{"name":"MacOS","version":"some kind of big cat"}}, buildpack: [{"os":"Win95","arch":"P6","arch-variant":"Pentium Pro","distributions":[{"name":"Windows 95","version":"OSR1"},{"name":"Windows 95","version":"OSR2.5"}]},{"os":"Win98","arch":"Pentium M","distributions":[{"name":"Windows 2000","version":"Server"}]}]`)
|
||||
h.AssertStringContains(t, outs.Err.Error(), `unable to satisfy target os/arch constraints; run image: {"os":"MacOS","arch":"ARM64","distro":{"name":"MacOS","version":"some kind of big cat"}}, buildpack: [{"os":"Win95","arch":"P6","arch-variant":"Pentium Pro","distros":[{"name":"Windows 95","version":"OSR1"},{"name":"Windows 95","version":"OSR2.5"}]},{"os":"Win98","arch":"Pentium M","distros":[{"name":"Windows 2000","version":"Server"}]}]`)
|
||||
return []buildpack.GroupElement{}, []files.BuildPlanEntry{}, nil
|
||||
})
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ var BuildEnvIncludelist = []string{
|
|||
"CNB_TARGET_OS",
|
||||
"CNB_TARGET_ARCH",
|
||||
"CNB_TARGET_ARCH_VARIANT",
|
||||
"CNB_TARGET_ID",
|
||||
"CNB_TARGET_DISTRO_NAME",
|
||||
"CNB_TARGET_DISTRO_VERSION",
|
||||
"HOSTNAME",
|
||||
|
|
|
@ -38,7 +38,6 @@ func testBuildEnv(t *testing.T, when spec.G, it spec.S) {
|
|||
"CNB_TARGET_ARCH=st-louis",
|
||||
"CNB_TARGET_ARCH_VARIANT=suburban",
|
||||
"CNB_TARGET_OS=BeOS",
|
||||
"CNB_TARGET_ID=tahr-jzay",
|
||||
"CNB_TARGET_DISTRO_NAME=web",
|
||||
"CNB_TARGET_DISTRO_VERSION=3.0",
|
||||
"HOSTNAME=some-hostname",
|
||||
|
@ -64,7 +63,6 @@ func testBuildEnv(t *testing.T, when spec.G, it spec.S) {
|
|||
"CNB_TARGET_ARCH_VARIANT=suburban",
|
||||
"CNB_TARGET_DISTRO_NAME=web",
|
||||
"CNB_TARGET_DISTRO_VERSION=3.0",
|
||||
"CNB_TARGET_ID=tahr-jzay",
|
||||
"CNB_TARGET_OS=BeOS",
|
||||
"CPATH=some-cpath",
|
||||
"HOME=some-home",
|
||||
|
|
|
@ -88,6 +88,7 @@ type ExportOptions struct {
|
|||
|
||||
func (e *Exporter) Export(opts ExportOptions) (files.Report, error) {
|
||||
var err error
|
||||
defer log.NewMeasurement("Exporter", e.Logger)()
|
||||
|
||||
if e.PlatformAPI.AtLeast("0.11") {
|
||||
if err = e.copyBuildpacksioSBOMs(opts); err != nil {
|
||||
|
|
|
@ -285,6 +285,7 @@ const (
|
|||
)
|
||||
|
||||
func (e *Extender) extend(kind string, baseImage v1.Image, logger log.Logger) (v1.Image, error) {
|
||||
defer log.NewMeasurement("Extender", logger)()
|
||||
logger.Debugf("Extending base image for %s: %s", kind, e.ImageRef)
|
||||
dockerfiles, err := e.dockerfilesFor(kind, logger)
|
||||
if err != nil {
|
||||
|
|
|
@ -118,6 +118,7 @@ type GenerateResult struct {
|
|||
}
|
||||
|
||||
func (g *Generator) Generate() (GenerateResult, error) {
|
||||
defer log.NewMeasurement("Generator", g.Logger)()
|
||||
inputs := g.getGenerateInputs()
|
||||
extensionOutputParentDir, err := os.MkdirTemp("", "cnb-extensions-generated.")
|
||||
if err != nil {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// Package log has logging interfaces for convenience in lifecycle
|
||||
package log
|
||||
|
||||
import "github.com/apex/log"
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package log
|
||||
|
||||
import "time"
|
||||
|
||||
// Chronit is, I guess, short for chronological unit because it measures time or something
|
||||
type Chronit struct {
|
||||
StartTime time.Time
|
||||
EndTime time.Time
|
||||
Log Logger
|
||||
FunctionName string
|
||||
}
|
||||
|
||||
// NewMeasurement initializes a chronological measuring tool, logs out the start time, and returns a function you can defer that will log the end time
|
||||
func NewMeasurement(funcName string, lager Logger) func() {
|
||||
c := Chronit{Log: lager, FunctionName: funcName}
|
||||
c.RecordStart()
|
||||
return func() {
|
||||
c.RecordEnd()
|
||||
}
|
||||
}
|
||||
|
||||
// RecordStart grabs the current time and logs it, but it will be called for you if you use the NewMeasurement convenience function.
|
||||
func (c *Chronit) RecordStart() {
|
||||
c.StartTime = time.Now()
|
||||
c.Log.Infof("Timer: %s started at %s", c.FunctionName, c.StartTime.Format(time.RFC3339))
|
||||
}
|
||||
|
||||
// RecordEnd is called in the function returned by NewMeasurement.
|
||||
// the EndTime will be populated just in case you'll keep the object in scope for later.
|
||||
func (c *Chronit) RecordEnd() {
|
||||
c.EndTime = time.Now()
|
||||
c.Log.Infof("Timer: %s ran for %v and ended at %s", c.FunctionName, c.EndTime.Sub(c.StartTime), c.EndTime.Format(time.RFC3339))
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package log_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/sclevine/spec"
|
||||
"github.com/sclevine/spec/report"
|
||||
|
||||
"github.com/buildpacks/lifecycle/log"
|
||||
h "github.com/buildpacks/lifecycle/testhelpers"
|
||||
)
|
||||
|
||||
type mockLog struct {
|
||||
callCount map[string]int
|
||||
}
|
||||
|
||||
func (m mockLog) incr(key string) {
|
||||
val, ok := m.callCount[key]
|
||||
if !ok {
|
||||
m.callCount[key] = 1
|
||||
} else {
|
||||
m.callCount[key] = val + 1
|
||||
}
|
||||
}
|
||||
|
||||
func (m mockLog) Debug(msg string) {
|
||||
m.incr("Debug")
|
||||
}
|
||||
func (m mockLog) Debugf(fmt string, v ...interface{}) {
|
||||
m.incr("Debug")
|
||||
}
|
||||
func (m mockLog) Info(msg string) {
|
||||
m.incr("Info")
|
||||
}
|
||||
func (m mockLog) Infof(fmt string, v ...interface{}) {
|
||||
m.incr("Info")
|
||||
}
|
||||
func (m mockLog) Warn(msg string) {
|
||||
m.incr("Warn")
|
||||
}
|
||||
func (m mockLog) Warnf(fmt string, v ...interface{}) {
|
||||
m.incr("Warn")
|
||||
}
|
||||
func (m mockLog) Error(msg string) {
|
||||
m.incr("Error")
|
||||
}
|
||||
func (m mockLog) Errorf(fmt string, v ...interface{}) {
|
||||
m.incr("Error")
|
||||
}
|
||||
|
||||
func TestTimeLog(t *testing.T) {
|
||||
spec.Run(t, "Exporter", testTimeLog, spec.Parallel(), spec.Report(report.Terminal{}))
|
||||
}
|
||||
|
||||
func testTimeLog(t *testing.T, when spec.G, it spec.S) {
|
||||
when("we use the time log", func() {
|
||||
it("the granular api works step by step", func() {
|
||||
logger := mockLog{callCount: map[string]int{}}
|
||||
c1 := log.Chronit{}
|
||||
nullTime := time.Time{}
|
||||
h.AssertEq(t, c1.StartTime, nullTime)
|
||||
h.AssertEq(t, c1.EndTime, nullTime)
|
||||
|
||||
c1.Log = logger
|
||||
c1.RecordStart()
|
||||
h.AssertEq(t, logger.callCount["Info"], 1)
|
||||
h.AssertEq(t, c1.StartTime == nullTime, false)
|
||||
h.AssertEq(t, c1.EndTime, nullTime)
|
||||
|
||||
c1.RecordEnd()
|
||||
h.AssertEq(t, logger.callCount["Info"], 2)
|
||||
h.AssertEq(t, c1.EndTime == nullTime, false)
|
||||
})
|
||||
it("the convenience functions call the logger", func() {
|
||||
logger := mockLog{callCount: map[string]int{}}
|
||||
endfunc := log.NewMeasurement("value", logger)
|
||||
h.AssertEq(t, logger.callCount["Info"], 1)
|
||||
endfunc()
|
||||
h.AssertEq(t, logger.callCount["Info"], 2)
|
||||
})
|
||||
})
|
||||
}
|
|
@ -1,16 +1,16 @@
|
|||
package files
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
|
||||
"github.com/buildpacks/lifecycle/buildpack"
|
||||
"github.com/buildpacks/lifecycle/internal/encoding"
|
||||
"github.com/buildpacks/lifecycle/log"
|
||||
)
|
||||
|
||||
// Analyzed is written by the analyzer as analyzed.toml to record information about:
|
||||
// Analyzed is written by the analyzer as analyzed.toml and updated in subsequent phases to record information about:
|
||||
// * the previous image (if it exists),
|
||||
// * the run image,
|
||||
// * the build image (if provided).
|
||||
|
@ -157,17 +157,15 @@ type TargetMetadata struct {
|
|||
Arch string `json:"arch" toml:"arch"`
|
||||
ArchVariant string `json:"arch-variant,omitempty" toml:"arch-variant,omitempty"`
|
||||
|
||||
Distribution *OSDistribution `json:"distribution,omitempty" toml:"distribution,omitempty"`
|
||||
Distro *OSDistro `json:"distro,omitempty" toml:"distro,omitempty"`
|
||||
}
|
||||
|
||||
func (t *TargetMetadata) String() string {
|
||||
if t.Distribution != nil {
|
||||
return fmt.Sprintf("OS: %s, Arch: %s, ArchVariant: %s, Distribution: (Name: %s, Version: %s)", t.OS, t.Arch, t.ArchVariant, t.Distribution.Name, t.Distribution.Version)
|
||||
}
|
||||
return fmt.Sprintf("OS: %s, Arch: %s, ArchVariant: %s", t.OS, t.Arch, t.ArchVariant)
|
||||
return encoding.ToJSONMaybe(*t)
|
||||
}
|
||||
|
||||
type OSDistribution struct {
|
||||
// OSDistro is the OS distribution that a base image provides.
|
||||
type OSDistro struct {
|
||||
Name string `json:"name" toml:"name"`
|
||||
Version string `json:"version" toml:"version"`
|
||||
}
|
||||
|
|
|
@ -14,9 +14,12 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
TargetLabel = "io.buildpacks.id"
|
||||
OSDistributionNameLabel = "io.buildpacks.distribution.name"
|
||||
OSDistributionVersionLabel = "io.buildpacks.distribution.version"
|
||||
// TargetLabel is the label containing the target ID.
|
||||
TargetLabel = "io.buildpacks.base.id"
|
||||
// OSDistroNameLabel is the label containing the OS distribution name.
|
||||
OSDistroNameLabel = "io.buildpacks.distro.name"
|
||||
// OSDistroVersionLabel is the label containing the OS distribution version.
|
||||
OSDistroVersionLabel = "io.buildpacks.distro.version"
|
||||
)
|
||||
|
||||
func BestRunImageMirrorFor(targetRegistry string, runImageMD files.RunImageForExport, checkReadAccess CheckReadAccess) (string, error) {
|
||||
|
|
|
@ -149,15 +149,14 @@ func testRunImage(t *testing.T, when spec.G, it spec.S) {
|
|||
|
||||
when(".EnvVarsFor", func() {
|
||||
it("returns the right thing", func() {
|
||||
tm := files.TargetMetadata{Arch: "pentium", ArchVariant: "mmx", ID: "my-id", OS: "linux", Distribution: &files.OSDistribution{Name: "nix", Version: "22.11"}}
|
||||
tm := files.TargetMetadata{Arch: "pentium", ArchVariant: "mmx", ID: "my-id", OS: "linux", Distro: &files.OSDistro{Name: "nix", Version: "22.11"}}
|
||||
observed := platform.EnvVarsFor(tm)
|
||||
h.AssertContains(t, observed, "CNB_TARGET_ARCH="+tm.Arch)
|
||||
h.AssertContains(t, observed, "CNB_TARGET_ARCH_VARIANT="+tm.ArchVariant)
|
||||
h.AssertContains(t, observed, "CNB_TARGET_DISTRO_NAME="+tm.Distribution.Name)
|
||||
h.AssertContains(t, observed, "CNB_TARGET_DISTRO_VERSION="+tm.Distribution.Version)
|
||||
h.AssertContains(t, observed, "CNB_TARGET_ID="+tm.ID)
|
||||
h.AssertContains(t, observed, "CNB_TARGET_DISTRO_NAME="+tm.Distro.Name)
|
||||
h.AssertContains(t, observed, "CNB_TARGET_DISTRO_VERSION="+tm.Distro.Version)
|
||||
h.AssertContains(t, observed, "CNB_TARGET_OS="+tm.OS)
|
||||
h.AssertEq(t, len(observed), 6)
|
||||
h.AssertEq(t, len(observed), 5)
|
||||
})
|
||||
|
||||
it("does not return the wrong thing", func() {
|
||||
|
|
|
@ -15,15 +15,12 @@ func EnvVarsFor(tm files.TargetMetadata) []string {
|
|||
ret := []string{"CNB_TARGET_OS=" + tm.OS, "CNB_TARGET_ARCH=" + tm.Arch}
|
||||
ret = append(ret, "CNB_TARGET_ARCH_VARIANT="+tm.ArchVariant)
|
||||
var distName, distVersion string
|
||||
if tm.Distribution != nil {
|
||||
distName = tm.Distribution.Name
|
||||
distVersion = tm.Distribution.Version
|
||||
if tm.Distro != nil {
|
||||
distName = tm.Distro.Name
|
||||
distVersion = tm.Distro.Version
|
||||
}
|
||||
ret = append(ret, "CNB_TARGET_DISTRO_NAME="+distName)
|
||||
ret = append(ret, "CNB_TARGET_DISTRO_VERSION="+distVersion)
|
||||
if tm.ID != "" {
|
||||
ret = append(ret, "CNB_TARGET_ID="+tm.ID)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
|
@ -46,10 +43,10 @@ func GetTargetMetadata(fromImage imgutil.Image) (*files.TargetMetadata, error) {
|
|||
if err != nil {
|
||||
return &tm, err
|
||||
}
|
||||
distName, distNameExists := labels[OSDistributionNameLabel]
|
||||
distVersion, distVersionExists := labels[OSDistributionVersionLabel]
|
||||
distName, distNameExists := labels[OSDistroNameLabel]
|
||||
distVersion, distVersionExists := labels[OSDistroVersionLabel]
|
||||
if distNameExists || distVersionExists {
|
||||
tm.Distribution = &files.OSDistribution{Name: distName, Version: distVersion}
|
||||
tm.Distro = &files.OSDistro{Name: distName, Version: distVersion}
|
||||
}
|
||||
if id, exists := labels[TargetLabel]; exists {
|
||||
tm.ID = id
|
||||
|
@ -70,51 +67,58 @@ func GetTargetOSFromFileSystem(d fsutil.Detector, tm *files.TargetMetadata, logg
|
|||
info := d.GetInfo(contents)
|
||||
if info.Version != "" || info.Name != "" {
|
||||
tm.OS = "linux"
|
||||
tm.Distribution = &files.OSDistribution{Name: info.Name, Version: info.Version}
|
||||
tm.Distro = &files.OSDistro{Name: info.Name, Version: info.Version}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TargetSatisfiedForBuild treats optional fields (ArchVariant and Distributions) as wildcards if empty, returns true if all populated fields match
|
||||
func TargetSatisfiedForBuild(t files.TargetMetadata, o buildpack.TargetMetadata) bool {
|
||||
if (o.Arch != "*" && t.Arch != o.Arch) || (o.OS != "*" && t.OS != o.OS) {
|
||||
// TargetSatisfiedForBuild treats empty fields as wildcards and returns true if all populated fields match.
|
||||
func TargetSatisfiedForBuild(base files.TargetMetadata, module buildpack.TargetMetadata) bool {
|
||||
if !matches(base.OS, module.OS) {
|
||||
return false
|
||||
}
|
||||
if t.ArchVariant != "" && o.ArchVariant != "" && t.ArchVariant != o.ArchVariant {
|
||||
if !matches(base.Arch, module.Arch) {
|
||||
return false
|
||||
}
|
||||
if !matches(base.ArchVariant, module.ArchVariant) {
|
||||
return false
|
||||
}
|
||||
if base.Distro == nil || len(module.Distros) == 0 {
|
||||
return true
|
||||
}
|
||||
foundMatchingDist := false
|
||||
for _, modDist := range module.Distros {
|
||||
if matches(base.Distro.Name, modDist.Name) && matches(base.Distro.Version, modDist.Version) {
|
||||
foundMatchingDist = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return foundMatchingDist
|
||||
}
|
||||
|
||||
// if either of the lengths of Distributions are zero, treat it as a wildcard.
|
||||
if t.Distribution != nil && len(o.Distributions) > 0 {
|
||||
// this could be more efficient but the lists are probably short...
|
||||
found := false
|
||||
for _, odist := range o.Distributions {
|
||||
if t.Distribution.Name == odist.Name && t.Distribution.Version == odist.Version {
|
||||
found = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return false
|
||||
}
|
||||
func matches(target1, target2 string) bool {
|
||||
if target1 == "" || target2 == "" {
|
||||
return true
|
||||
}
|
||||
return true
|
||||
return target1 == target2
|
||||
}
|
||||
|
||||
// TargetSatisfiedForRebase treats optional fields (ArchVariant and Distribution fields) as wildcards if empty, returns true if all populated fields match
|
||||
func TargetSatisfiedForRebase(t files.TargetMetadata, appTargetMetadata files.TargetMetadata) bool {
|
||||
if t.Arch != appTargetMetadata.Arch || t.OS != appTargetMetadata.OS {
|
||||
if t.OS != appTargetMetadata.OS || t.Arch != appTargetMetadata.Arch {
|
||||
return false
|
||||
}
|
||||
if t.ArchVariant != "" && appTargetMetadata.ArchVariant != "" && t.ArchVariant != appTargetMetadata.ArchVariant {
|
||||
if !matches(t.ArchVariant, appTargetMetadata.ArchVariant) {
|
||||
return false
|
||||
}
|
||||
|
||||
if t.Distribution != nil && appTargetMetadata.Distribution != nil {
|
||||
if t.Distribution.Name != appTargetMetadata.Distribution.Name {
|
||||
if t.Distro != nil {
|
||||
if appTargetMetadata.Distro == nil {
|
||||
return false
|
||||
}
|
||||
if t.Distribution.Version != appTargetMetadata.Distribution.Version {
|
||||
if t.Distro.Name != "" && t.Distro.Name != appTargetMetadata.Distro.Name {
|
||||
return false
|
||||
}
|
||||
if t.Distro.Version != "" && t.Distro.Version != appTargetMetadata.Distro.Version {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,50 +21,150 @@ func TestTargetData(t *testing.T) {
|
|||
|
||||
func testTargetData(t *testing.T, when spec.G, it spec.S) {
|
||||
when(".TargetSatisfiedForBuild", func() {
|
||||
it("requires equality of OS and Arch", func() {
|
||||
d := files.TargetMetadata{OS: "Win95", Arch: "Pentium"}
|
||||
var baseTarget files.TargetMetadata
|
||||
when("base image data", func() {
|
||||
when("has os and arch", func() {
|
||||
baseTarget = files.TargetMetadata{OS: "Win95", Arch: "Pentium"}
|
||||
|
||||
if platform.TargetSatisfiedForBuild(d, buildpack.TargetMetadata{OS: "Win98", Arch: d.Arch}) {
|
||||
t.Fatal("TargetMetadata with different OS were equal")
|
||||
}
|
||||
if platform.TargetSatisfiedForBuild(d, buildpack.TargetMetadata{OS: d.OS, Arch: "Pentium MMX"}) {
|
||||
t.Fatal("TargetMetadata with different Arch were equal")
|
||||
}
|
||||
if !platform.TargetSatisfiedForBuild(d, buildpack.TargetMetadata{OS: d.OS, Arch: d.Arch, ArchVariant: "MMX"}) {
|
||||
t.Fatal("blank arch variant was not treated as wildcard")
|
||||
}
|
||||
if !platform.TargetSatisfiedForBuild(d, buildpack.TargetMetadata{
|
||||
OS: d.OS,
|
||||
Arch: d.Arch,
|
||||
Distributions: []buildpack.OSDistribution{{Name: "a", Version: "2"}},
|
||||
}) {
|
||||
t.Fatal("blank distributions list was not treated as wildcard")
|
||||
}
|
||||
when("buildpack data", func() {
|
||||
when("has os and arch", func() {
|
||||
it("must match", func() {
|
||||
h.AssertEq(t, platform.TargetSatisfiedForBuild(baseTarget, buildpack.TargetMetadata{OS: baseTarget.OS, Arch: baseTarget.Arch}), true)
|
||||
h.AssertEq(t, platform.TargetSatisfiedForBuild(baseTarget, buildpack.TargetMetadata{OS: "Win98", Arch: baseTarget.Arch}), false)
|
||||
h.AssertEq(t, platform.TargetSatisfiedForBuild(baseTarget, buildpack.TargetMetadata{OS: baseTarget.OS, Arch: "Pentium MMX"}), false)
|
||||
})
|
||||
})
|
||||
|
||||
d.Distribution = &files.OSDistribution{Name: "A", Version: "1"}
|
||||
if platform.TargetSatisfiedForBuild(d, buildpack.TargetMetadata{OS: d.OS, Arch: d.Arch, Distributions: []buildpack.OSDistribution{{Name: "g", Version: "2"}, {Name: "B", Version: "2"}}}) {
|
||||
t.Fatal("unsatisfactory distribution lists were treated as satisfying")
|
||||
}
|
||||
if !platform.TargetSatisfiedForBuild(d, buildpack.TargetMetadata{OS: d.OS, Arch: d.Arch, Distributions: []buildpack.OSDistribution{}}) {
|
||||
t.Fatal("blank distributions list was not treated as wildcard")
|
||||
}
|
||||
if !platform.TargetSatisfiedForBuild(d, buildpack.TargetMetadata{OS: d.OS, Arch: d.Arch, Distributions: []buildpack.OSDistribution{{Name: "B", Version: "2"}, {Name: "A", Version: "1"}}}) {
|
||||
t.Fatal("distributions list including target's distribution not recognized as satisfying")
|
||||
}
|
||||
when("missing os and arch", func() {
|
||||
it("matches", func() {
|
||||
h.AssertEq(t, platform.TargetSatisfiedForBuild(baseTarget, buildpack.TargetMetadata{OS: "", Arch: ""}), true)
|
||||
})
|
||||
})
|
||||
|
||||
when("has extra information", func() {
|
||||
it("matches", func() {
|
||||
h.AssertEq(t, platform.TargetSatisfiedForBuild(baseTarget, buildpack.TargetMetadata{OS: baseTarget.OS, Arch: baseTarget.Arch, ArchVariant: "MMX"}), true)
|
||||
h.AssertEq(t, platform.TargetSatisfiedForBuild(baseTarget, buildpack.TargetMetadata{
|
||||
OS: baseTarget.OS,
|
||||
Arch: baseTarget.Arch,
|
||||
Distros: []buildpack.OSDistro{{Name: "a", Version: "2"}},
|
||||
}), true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
when("has arch variant", func() {
|
||||
baseTarget.ArchVariant = "some-arch-variant"
|
||||
|
||||
when("buildpack data", func() {
|
||||
when("has arch variant", func() {
|
||||
it("must match", func() {
|
||||
h.AssertEq(t, platform.TargetSatisfiedForBuild(baseTarget, buildpack.TargetMetadata{OS: baseTarget.OS, Arch: baseTarget.Arch, ArchVariant: "some-arch-variant"}), true)
|
||||
h.AssertEq(t, platform.TargetSatisfiedForBuild(baseTarget, buildpack.TargetMetadata{OS: baseTarget.OS, Arch: baseTarget.Arch, ArchVariant: "some-other-arch-variant"}), false)
|
||||
})
|
||||
})
|
||||
|
||||
when("missing arch variant", func() {
|
||||
it("matches", func() {
|
||||
h.AssertEq(t, platform.TargetSatisfiedForBuild(baseTarget, buildpack.TargetMetadata{OS: baseTarget.OS, Arch: baseTarget.Arch}), true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
when("has distro information", func() {
|
||||
baseTarget.Distro = &files.OSDistro{Name: "A", Version: "1"}
|
||||
|
||||
when("buildpack data", func() {
|
||||
when("has distro information", func() {
|
||||
it("must match", func() {
|
||||
h.AssertEq(t, platform.TargetSatisfiedForBuild(baseTarget, buildpack.TargetMetadata{OS: baseTarget.OS, Arch: baseTarget.Arch, Distros: []buildpack.OSDistro{{Name: "B", Version: "2"}, {Name: "A", Version: "1"}}}), true)
|
||||
h.AssertEq(t, platform.TargetSatisfiedForBuild(baseTarget, buildpack.TargetMetadata{OS: baseTarget.OS, Arch: baseTarget.Arch, Distros: []buildpack.OSDistro{{Name: "g", Version: "2"}, {Name: "B", Version: "2"}}}), false)
|
||||
})
|
||||
})
|
||||
|
||||
when("missing distro information", func() {
|
||||
it("matches", func() {
|
||||
h.AssertEq(t, platform.TargetSatisfiedForBuild(baseTarget, buildpack.TargetMetadata{OS: baseTarget.OS, Arch: baseTarget.Arch}), true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it("is cool with starry arches", func() {
|
||||
d := files.TargetMetadata{OS: "windows", Arch: "amd64"}
|
||||
if !platform.TargetSatisfiedForBuild(d, buildpack.TargetMetadata{OS: d.OS, Arch: "*"}) {
|
||||
t.Fatal("Arch wildcard should have been satisfied with whatever we gave it")
|
||||
}
|
||||
})
|
||||
when(".TargetSatisfiedForRebase", func() {
|
||||
var baseTarget files.TargetMetadata
|
||||
when("orig image data", func() {
|
||||
when("has os and arch", func() {
|
||||
baseTarget = files.TargetMetadata{OS: "Win95", Arch: "Pentium"}
|
||||
|
||||
it("is down with OS stars", func() {
|
||||
d := files.TargetMetadata{OS: "plan 9", Arch: "amd64"}
|
||||
if !platform.TargetSatisfiedForBuild(d, buildpack.TargetMetadata{OS: "*", Arch: d.Arch}) {
|
||||
t.Fatal("OS wildcard should have been satisfied by plan 9")
|
||||
}
|
||||
when("new image data", func() {
|
||||
it("must match", func() {
|
||||
h.AssertEq(t, platform.TargetSatisfiedForRebase(baseTarget, files.TargetMetadata{OS: baseTarget.OS, Arch: baseTarget.Arch}), true)
|
||||
h.AssertEq(t, platform.TargetSatisfiedForRebase(baseTarget, files.TargetMetadata{OS: "Win98", Arch: baseTarget.Arch}), false)
|
||||
h.AssertEq(t, platform.TargetSatisfiedForRebase(baseTarget, files.TargetMetadata{OS: baseTarget.OS, Arch: "Pentium MMX"}), false)
|
||||
})
|
||||
|
||||
when("has extra information", func() {
|
||||
it("matches", func() {
|
||||
h.AssertEq(t, platform.TargetSatisfiedForRebase(baseTarget, files.TargetMetadata{OS: baseTarget.OS, Arch: baseTarget.Arch, ArchVariant: "MMX"}), true)
|
||||
h.AssertEq(t, platform.TargetSatisfiedForRebase(baseTarget, files.TargetMetadata{
|
||||
OS: baseTarget.OS,
|
||||
Arch: baseTarget.Arch,
|
||||
Distro: &files.OSDistro{Name: "a", Version: "2"},
|
||||
}), true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
when("has arch variant", func() {
|
||||
baseTarget.ArchVariant = "some-arch-variant"
|
||||
|
||||
when("new image data", func() {
|
||||
when("has arch variant", func() {
|
||||
it("must match", func() {
|
||||
h.AssertEq(t, platform.TargetSatisfiedForRebase(baseTarget, files.TargetMetadata{OS: baseTarget.OS, Arch: baseTarget.Arch, ArchVariant: "some-arch-variant"}), true)
|
||||
h.AssertEq(t, platform.TargetSatisfiedForRebase(baseTarget, files.TargetMetadata{OS: baseTarget.OS, Arch: baseTarget.Arch, ArchVariant: "some-other-arch-variant"}), false)
|
||||
})
|
||||
})
|
||||
|
||||
when("missing arch variant", func() {
|
||||
it("matches", func() {
|
||||
h.AssertEq(t, platform.TargetSatisfiedForRebase(baseTarget, files.TargetMetadata{OS: baseTarget.OS, Arch: baseTarget.Arch}), true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
when("has distro information", func() {
|
||||
baseTarget.Distro = &files.OSDistro{Name: "A", Version: "1"}
|
||||
|
||||
when("new image data", func() {
|
||||
when("has distro information", func() {
|
||||
it("must match", func() {
|
||||
h.AssertEq(t, platform.TargetSatisfiedForRebase(baseTarget, files.TargetMetadata{
|
||||
OS: baseTarget.OS,
|
||||
Arch: baseTarget.Arch,
|
||||
Distro: &files.OSDistro{Name: "A", Version: "1"},
|
||||
}), true)
|
||||
h.AssertEq(t, platform.TargetSatisfiedForRebase(baseTarget, files.TargetMetadata{
|
||||
OS: baseTarget.OS,
|
||||
Arch: baseTarget.Arch,
|
||||
Distro: &files.OSDistro{Name: "B", Version: "2"},
|
||||
}), false)
|
||||
})
|
||||
})
|
||||
|
||||
when("missing distro information", func() {
|
||||
it("errors", func() {
|
||||
h.AssertEq(t, platform.TargetSatisfiedForRebase(baseTarget, files.TargetMetadata{OS: baseTarget.OS, Arch: baseTarget.Arch}), false)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -76,8 +176,8 @@ func testTargetData(t *testing.T, when spec.G, it spec.S) {
|
|||
t: t,
|
||||
HasFile: true}
|
||||
platform.GetTargetOSFromFileSystem(&d, &tm, logr)
|
||||
h.AssertEq(t, "opensesame", tm.Distribution.Name)
|
||||
h.AssertEq(t, "3.14", tm.Distribution.Version)
|
||||
h.AssertEq(t, "opensesame", tm.Distro.Name)
|
||||
h.AssertEq(t, "3.14", tm.Distro.Version)
|
||||
})
|
||||
|
||||
it("doesn't populate if there's no file", func() {
|
||||
|
@ -87,7 +187,7 @@ func testTargetData(t *testing.T, when spec.G, it spec.S) {
|
|||
t: t,
|
||||
HasFile: false}
|
||||
platform.GetTargetOSFromFileSystem(&d, &tm, logr)
|
||||
h.AssertNil(t, tm.Distribution)
|
||||
h.AssertNil(t, tm.Distro)
|
||||
})
|
||||
|
||||
it("doesn't populate if there's an error reading the file", func() {
|
||||
|
@ -99,7 +199,7 @@ func testTargetData(t *testing.T, when spec.G, it spec.S) {
|
|||
ReadFileErr: fmt.Errorf("I'm sorry Dave, I don't even remember exactly what HAL says"),
|
||||
}
|
||||
platform.GetTargetOSFromFileSystem(&d, &tm, logr)
|
||||
h.AssertNil(t, tm.Distribution)
|
||||
h.AssertNil(t, tm.Distro)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ type RebaseReport struct {
|
|||
}
|
||||
|
||||
func (r *Rebaser) Rebase(workingImage imgutil.Image, newBaseImage imgutil.Image, outputImageRef string, additionalNames []string) (RebaseReport, error) {
|
||||
defer log.NewMeasurement("Rebaser", r.Logger)()
|
||||
appPlatformAPI, err := workingImage.Env(platform.EnvPlatformAPI)
|
||||
if err != nil {
|
||||
return RebaseReport{}, fmt.Errorf("failed to get app image platform API: %w", err)
|
||||
|
|
|
@ -793,20 +793,20 @@ func testRebaser(t *testing.T, when spec.G, it spec.S) {
|
|||
h.AssertError(t, err, `unable to satisfy target os/arch constraints; new run image: {"os":"linux","arch":"amd64","arch-variant":"variant2"}, old run image: {"os":"linux","arch":"amd64","arch-variant":"variant1"}`)
|
||||
})
|
||||
|
||||
it("errors and prevents the rebase from taking place when the io.buildpacks.distribution.name are different", func() {
|
||||
h.AssertNil(t, fakeAppImage.SetLabel("io.buildpacks.distribution.name", "distro1"))
|
||||
h.AssertNil(t, fakeNewBaseImage.SetLabel("io.buildpacks.distribution.name", "distro2"))
|
||||
it("errors and prevents the rebase from taking place when the io.buildpacks.distro.name are different", func() {
|
||||
h.AssertNil(t, fakeAppImage.SetLabel("io.buildpacks.distro.name", "distro1"))
|
||||
h.AssertNil(t, fakeNewBaseImage.SetLabel("io.buildpacks.distro.name", "distro2"))
|
||||
|
||||
_, err := rebaser.Rebase(fakeAppImage, fakeNewBaseImage, fakeAppImage.Name(), additionalNames)
|
||||
h.AssertError(t, err, `unable to satisfy target os/arch constraints; new run image: {"os":"linux","arch":"amd64","distribution":{"name":"distro2","version":""}}, old run image: {"os":"linux","arch":"amd64","distribution":{"name":"distro1","version":""}}`)
|
||||
h.AssertError(t, err, `unable to satisfy target os/arch constraints; new run image: {"os":"linux","arch":"amd64","distro":{"name":"distro2","version":""}}, old run image: {"os":"linux","arch":"amd64","distro":{"name":"distro1","version":""}}`)
|
||||
})
|
||||
|
||||
it("errors and prevents the rebase from taking place when the io.buildpacks.distribution.version are different", func() {
|
||||
h.AssertNil(t, fakeAppImage.SetLabel("io.buildpacks.distribution.version", "version1"))
|
||||
h.AssertNil(t, fakeNewBaseImage.SetLabel("io.buildpacks.distribution.version", "version2"))
|
||||
it("errors and prevents the rebase from taking place when the io.buildpacks.distro.version are different", func() {
|
||||
h.AssertNil(t, fakeAppImage.SetLabel("io.buildpacks.distro.version", "version1"))
|
||||
h.AssertNil(t, fakeNewBaseImage.SetLabel("io.buildpacks.distro.version", "version2"))
|
||||
|
||||
_, err := rebaser.Rebase(fakeAppImage, fakeNewBaseImage, fakeAppImage.Name(), additionalNames)
|
||||
h.AssertError(t, err, `unable to satisfy target os/arch constraints; new run image: {"os":"linux","arch":"amd64","distribution":{"name":"","version":"version2"}}, old run image: {"os":"linux","arch":"amd64","distribution":{"name":"","version":"version1"}}`)
|
||||
h.AssertError(t, err, `unable to satisfy target os/arch constraints; new run image: {"os":"linux","arch":"amd64","distro":{"name":"","version":"version2"}}, old run image: {"os":"linux","arch":"amd64","distro":{"name":"","version":"version1"}}`)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -28,6 +28,7 @@ type Restorer struct {
|
|||
// Restore restores metadata for launch and cache layers into the layers directory and attempts to restore layer data for cache=true layers, removing the layer when unsuccessful.
|
||||
// If a usable cache is not provided, Restore will not restore any cache=true layer metadata.
|
||||
func (r *Restorer) Restore(cache Cache) error {
|
||||
defer log.NewMeasurement("Restorer", r.Logger)()
|
||||
cacheMeta, err := retrieveCacheMetadata(cache, r.Logger)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -36,6 +37,7 @@ func (r *Restorer) Restore(cache Cache) error {
|
|||
useShaFiles := !r.restoresLayerMetadata()
|
||||
layerSHAStore := layer.NewSHAStore(useShaFiles)
|
||||
if r.restoresLayerMetadata() {
|
||||
r.Logger.Debug("Restoring Layer Metadata")
|
||||
if err := r.LayerMetadataRestorer.Restore(r.Buildpacks, r.LayersMetadata, cacheMeta, layerSHAStore); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -61,6 +63,7 @@ func (r *Restorer) Restore(cache Cache) error {
|
|||
cachedFn = buildpack.MadeCached
|
||||
}
|
||||
|
||||
r.Logger.Debugf("Reading Buildpack Layers directory %s", r.LayersDir)
|
||||
buildpackDir, err := buildpack.ReadLayersDir(r.LayersDir, bp, r.Logger)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "reading buildpack layer directory")
|
||||
|
|
2
save.go
2
save.go
|
@ -17,9 +17,9 @@ func saveImage(image imgutil.Image, additionalNames []string, logger log.Logger)
|
|||
}
|
||||
|
||||
func saveImageAs(image imgutil.Image, name string, additionalNames []string, logger log.Logger) (files.ImageReport, error) {
|
||||
defer log.NewMeasurement("Saving "+name+"...", logger)()
|
||||
var saveErr error
|
||||
imageReport := files.ImageReport{}
|
||||
logger.Infof("Saving %s...\n", name)
|
||||
if err := image.SaveAs(name, additionalNames...); err != nil {
|
||||
var ok bool
|
||||
if saveErr, ok = err.(imgutil.SaveError); !ok {
|
||||
|
|
Loading…
Reference in New Issue