Compare commits

...

9 Commits

Author SHA1 Message Date
Ettore Di Giacinto
ddd61f769c Tag 0.9.25 2021-01-04 00:19:14 +01:00
Ettore Di Giacinto
1dd91b06bd Cleanup docker images on test teardown 2021-01-03 23:56:59 +01:00
Ettore Di Giacinto
11df314a26 Avoid clashing fixture version 2021-01-03 23:56:49 +01:00
Ettore Di Giacinto
2cbf547873 Add new fixtures 2021-01-03 23:37:34 +01:00
Ettore Di Giacinto
43f5b69c18 Let the build fail when depending on virtuals
This is currently not a valid use case. Virtuals are empty packages and
if the `build.yaml` is completely empty, nothing could depend on them.

Let's try to not be too smart and build the package image if a source
image is supplied, and fail hardly when we depend on a virtual in build
time.
2021-01-03 23:03:01 +01:00
Ettore Di Giacinto
1fdef757b6 Adapt other bunch of fixtures to changes 2021-01-03 22:22:32 +01:00
Ettore Di Giacinto
6c27af18c8 Adapt fixture to changes 2021-01-03 21:40:35 +01:00
Ettore Di Giacinto
f57f0f9588 Adapt complex selection fixtures to new changes
We don't generate anymore images if packages are empty - those are now
virtuals which just generates empty artifacts.

Virtuals are not meant to be required by other packages in build time,
because it would violate the virtual packages purpose (they are just
useful for runtime).

This test was used to verify version selection of the best match during build
time, not to actually test any build process. Inject steps so images are
actually generated, and they can depend on each others.
2021-01-03 20:50:32 +01:00
Ettore Di Giacinto
457acd0d8a Add virtual packages support 2021-01-03 20:08:04 +01:00
26 changed files with 167 additions and 22 deletions

View File

@@ -40,7 +40,7 @@ var Verbose bool
var LockedCommands = []string{"install", "uninstall", "upgrade"}
const (
LuetCLIVersion = "0.9.24"
LuetCLIVersion = "0.9.25"
LuetEnvPrefix = "LUET"
)

View File

@@ -16,7 +16,6 @@
package compiler
import (
"archive/tar"
"fmt"
"io/ioutil"
"os"
@@ -427,29 +426,33 @@ func (cs *LuetCompiler) genArtifact(p CompilationSpec, builderOpts, runnerOpts C
var artifact Artifact
var rootfs string
var err error
unpack := p.ImageUnpack()
pkgTag := ":package: " + p.GetPackage().HumanReadableString()
// If package_dir was specified in the spec, we want to treat the content of the directory
// as the root of our archive. ImageUnpack is implied to be true. override it
if p.GetPackageDir() != "" {
unpack = true
}
if len(p.BuildSteps()) == 0 && len(p.GetPreBuildSteps()) == 0 && !unpack {
// We can't generate delta in this case. It implies the package is a virtual, and nothing has to be done really
if p.EmptyPackage() {
fakePackage := p.Rel(p.GetPackage().GetFingerPrint() + ".package.tar")
// We can't generate delta in this case. It implies the package is a virtual, and nothing has to be done really
file, err := os.Create(fakePackage)
rootfs, err = ioutil.TempDir(p.GetOutputPath(), "rootfs")
if err != nil {
return nil, errors.Wrap(err, "Failed creating virtual package")
return nil, errors.Wrap(err, "Could not create tempdir")
}
defer file.Close()
tw := tar.NewWriter(file)
defer tw.Close()
defer os.RemoveAll(rootfs) // clean up
artifact := NewPackageArtifact(fakePackage)
artifact.SetCompressionType(cs.CompressionType)
if err := artifact.Compress(rootfs, concurrency); err != nil {
return nil, errors.Wrap(err, "Error met while creating package archive")
}
artifact.SetCompileSpec(p)
artifact.GetCompileSpec().GetPackage().SetBuildTimestamp(time.Now().String())
err = artifact.WriteYaml(p.GetOutputPath())
if err != nil {
return artifact, errors.Wrap(err, "Failed while writing metadata file")
}
Info(pkgTag, " :white_check_mark: done (empty virtual package)")
return artifact, nil
}
@@ -476,7 +479,7 @@ func (cs *LuetCompiler) genArtifact(p CompilationSpec, builderOpts, runnerOpts C
return nil, errors.Wrap(err, "Could not extract rootfs")
}
if unpack {
if p.UnpackedPackage() {
// Take content of container as a base for our package files
artifact, err = cs.unpackFs(rootfs, concurrency, p)
if err != nil {
@@ -524,6 +527,13 @@ func (cs *LuetCompiler) compileWithImage(image, buildertaggedImage, packageImage
keepPermissions, keepImg bool,
p CompilationSpec, generateArtifact bool) (Artifact, error) {
// If it is a virtual, check if we have to generate an empty artifact or not.
if generateArtifact && p.EmptyPackage() && !p.HasImageSource() {
return cs.genArtifact(p, CompilerBackendOptions{}, CompilerBackendOptions{}, concurrency, keepPermissions)
} else if p.EmptyPackage() && !p.HasImageSource() {
return &PackageArtifact{}, nil
}
if !generateArtifact {
exists := cs.Backend.ImageExists(packageImage)
if art, err := LoadArtifactFromYaml(p); err == nil && exists { // If YAML is correctly loaded, and both images exists, no reason to rebuild.
@@ -649,10 +659,13 @@ func (cs *LuetCompiler) Compile(keepPermissions bool, p CompilationSpec) (Artifa
func (cs *LuetCompiler) compile(concurrency int, keepPermissions bool, p CompilationSpec) (Artifact, error) {
Info(":package: Compiling", p.GetPackage().HumanReadableString(), ".... :coffee:")
if len(p.GetPackage().GetRequires()) == 0 && p.GetImage() == "" {
Error("Package with no deps and no seed image supplied, bailing out")
return nil, errors.New("Package " + p.GetPackage().GetFingerPrint() +
" with no deps and no seed image supplied, bailing out")
Debug(fmt.Sprintf("%s: has images %t, empty package: %t", p.GetPackage().HumanReadableString(), p.HasImageSource(), p.EmptyPackage()))
if !p.HasImageSource() && !p.EmptyPackage() {
return nil,
fmt.Errorf(
"%s is invalid: package has no dependencies and no seed image supplied while it has steps defined",
p.GetPackage().GetFingerPrint(),
)
}
targetAssertion := p.GetSourceAssertion().Search(p.GetPackage().GetFingerPrint())

View File

@@ -178,6 +178,10 @@ type CompilationSpec interface {
SetPackageDir(string)
GetPackageDir() string
EmptyPackage() bool
UnpackedPackage() bool
HasImageSource() bool
}
type CompilationSpecs interface {

View File

@@ -185,6 +185,24 @@ func (cs *LuetCompilationSpec) SetSeedImage(s string) {
cs.Seed = s
}
func (cs *LuetCompilationSpec) EmptyPackage() bool {
return len(cs.BuildSteps()) == 0 && len(cs.GetPreBuildSteps()) == 0 && !cs.UnpackedPackage()
}
func (cs *LuetCompilationSpec) UnpackedPackage() bool {
// If package_dir was specified in the spec, we want to treat the content of the directory
// as the root of our archive. ImageUnpack is implied to be true. override it
unpack := cs.ImageUnpack()
if cs.GetPackageDir() != "" {
unpack = true
}
return unpack
}
func (cs *LuetCompilationSpec) HasImageSource() bool {
return len(cs.GetPackage().GetRequires()) != 0 || cs.GetImage() != ""
}
func (cs *LuetCompilationSpec) CopyRetrieves(dest string) error {
var err error
if len(cs.Retrieve) > 0 {

View File

@@ -1,2 +1,4 @@
image: "alpine:3.5"
steps:
- echo "foo"

View File

@@ -15,3 +15,6 @@ requires:
- category: "layer"
name: "build-sabayon-overlay"
version: "0.20191212"
steps:
- echo "foo"

View File

@@ -5,3 +5,6 @@ requires:
includes:
- /usr/portage/packages/.*
steps:
- echo "foo"

View File

@@ -16,3 +16,6 @@ requires:
- category: "layer"
name: "build-sabayon-overlay"
version: ">=0.1"
steps:
- echo "foo"

View File

@@ -2,3 +2,5 @@ requires:
- category: "layer"
name: "build"
version: ">=0.1"
steps:
- echo "foo"

View File

@@ -2,3 +2,5 @@ requires:
- category: "layer"
version: "0.1"
name: "build"
steps:
- echo "foo"

View File

@@ -5,3 +5,5 @@ requires:
- category: "layer"
name: "sabayon-build-portage"
version: ">=0.1"
steps:
- echo "foo"

View File

@@ -1,3 +1,5 @@
category: "layer"
name: "build-sabayon-overlay"
version: "0.20191205"
steps:
- echo "foo"

View File

@@ -5,3 +5,5 @@ requires:
- category: "layer"
name: "sabayon-build-portage"
version: ">=0.1"
steps:
- echo "foo"

View File

@@ -2,6 +2,7 @@ requires:
- category: "layer"
version: "0.1"
name: "build-sabayon-overlays"
steps:
- echo "foo"
includes:
- /usr/portage/packages/.*

0
tests/fixtures/virtuals/a/build.yaml vendored Normal file
View File

View File

@@ -0,0 +1,3 @@
category: test
name: "a"
version: "1.99"

4
tests/fixtures/virtuals/b/build.yaml vendored Normal file
View File

@@ -0,0 +1,4 @@
requires:
- category: "test"
name: "a"
version: ">=0"

View File

@@ -0,0 +1,3 @@
category: test
name: "b"
version: "1.0"

4
tests/fixtures/virtuals/c/build.yaml vendored Normal file
View File

@@ -0,0 +1,4 @@
# Invalid, no source image or requires defined, but we define steps
steps:
- echo "fail!"

View File

@@ -0,0 +1,3 @@
category: test
name: "c"
version: "1.0"

View File

@@ -0,0 +1 @@
image: "busybox"

View File

@@ -0,0 +1,3 @@
category: test
name: "image"
version: "1.0"

View File

@@ -0,0 +1,4 @@
requires:
- category: "test"
name: "image"
version: ">=0"

View File

@@ -0,0 +1,3 @@
category: test
name: "virtual"
version: "1.0"

View File

@@ -8,6 +8,7 @@ export tmpdir="$(mktemp -d)"
oneTimeTearDown() {
rm -rf "$tmpdir"
docker system prune --force --volumes --all > /dev/null
}
testBuild() {

View File

@@ -0,0 +1,59 @@
#!/bin/bash
export LUET_NOLOCK=true
oneTimeSetUp() {
export tmpdir="$(mktemp -d)"
}
oneTimeTearDown() {
rm -rf "$tmpdir"
docker system prune --force --volumes --all > /dev/null
}
testBuildA() {
mkdir $tmpdir/testbuild1
luet build --tree "$ROOT_DIR/tests/fixtures/virtuals" --debug --compression "gzip" --destination $tmpdir/testbuild1 test/a
buildst=$?
assertEquals 'builds successfully' "$buildst" "0"
assertTrue 'create package A 1.99' "[ -e '$tmpdir/testbuild1/a-test-1.99.package.tar.gz' ]"
assertTrue 'create package A 1.99' "[ -e '$tmpdir/testbuild1/a-test-1.99.metadata.yaml' ]"
}
testBuildB() {
mkdir $tmpdir/testbuild2
luet build --tree "$ROOT_DIR/tests/fixtures/virtuals" --debug --compression "gzip" --destination $tmpdir/testbuild2 test/b
buildst=$?
assertEquals 'builds of B expected to fail. It depends on a virtual' "$buildst" "1"
}
testBuildC() {
mkdir $tmpdir/testbuild3
luet build --tree "$ROOT_DIR/tests/fixtures/virtuals" --debug --compression "gzip" --destination $tmpdir/testbuild3 test/c
buildst=$?
assertEquals 'builds of C expected to fail. Steps with no source image' "$buildst" "1"
}
testBuildImage() {
mkdir $tmpdir/testbuild4
luet build --tree "$ROOT_DIR/tests/fixtures/virtuals" --debug --compression "gzip" --destination $tmpdir/testbuild4 test/image
buildst=$?
assertEquals 'builds of test/image expected to succeed' "$buildst" "0"
assertTrue 'create package test/image 1.0' "[ -e '$tmpdir/testbuild4/image-test-1.0.package.tar.gz' ]"
assertTrue 'create package test/image 1.0' "[ -e '$tmpdir/testbuild4/image-test-1.0.metadata.yaml' ]"
}
testBuildVirtual() {
mkdir $tmpdir/testbuild5
luet build --tree "$ROOT_DIR/tests/fixtures/virtuals" --debug --compression "gzip" --destination $tmpdir/testbuild5 test/virtual
buildst=$?
assertEquals 'builds of test/virtual expected to succeed' "$buildst" "0"
assertTrue 'create package test/image 1.0' "[ -e '$tmpdir/testbuild5/image-test-1.0.package.tar.gz' ]"
assertTrue 'create package test/image 1.0' "[ -e '$tmpdir/testbuild5/image-test-1.0.metadata.yaml' ]"
assertTrue 'create package test/virtual 1.0' "[ -e '$tmpdir/testbuild5/virtual-test-1.0.package.tar.gz' ]"
assertTrue 'create package test/virtual 1.0' "[ -e '$tmpdir/testbuild5/virtual-test-1.0.metadata.yaml' ]"
}
# Load shUnit2.
. "$ROOT_DIR/tests/integration/shunit2"/shunit2