mirror of
https://github.com/mudler/luet.git
synced 2025-09-12 13:26:16 +00:00
Handle empty packages when pushing final images
We used to create dockerfiles blindly assuming there is content, but that's not the case for virtual packages. Due to https://github.com/moby/moby/issues/38039 we are forced for a "unpleasant" workaround, as we can't create empty FROM scratch images and export them.
This commit is contained in:
@@ -290,15 +290,27 @@ func (a *PackageArtifact) GenerateFinalImage(imageName string, b CompilerBackend
|
|||||||
return builderOpts, errors.Wrap(err, "error met while creating tempdir for "+a.Path)
|
return builderOpts, errors.Wrap(err, "error met while creating tempdir for "+a.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := a.Unpack(uncompressedFiles, keepPerms); err != nil {
|
||||||
|
return builderOpts, errors.Wrap(err, "error met while uncompressing artifact "+a.Path)
|
||||||
|
}
|
||||||
|
|
||||||
|
empty, err := helpers.DirectoryIsEmpty(uncompressedFiles)
|
||||||
|
if err != nil {
|
||||||
|
return builderOpts, errors.Wrap(err, "error met while checking if directory is empty "+uncompressedFiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
// See https://github.com/moby/moby/issues/38039.
|
||||||
|
// We can't generate FROM scratch empty images. Docker will refuse to export them
|
||||||
|
// workaround: Inject a .virtual empty file
|
||||||
|
if empty {
|
||||||
|
helpers.Touch(filepath.Join(uncompressedFiles, ".virtual"))
|
||||||
|
}
|
||||||
|
|
||||||
data := a.genDockerfile()
|
data := a.genDockerfile()
|
||||||
if err := ioutil.WriteFile(dockerFile, []byte(data), 0644); err != nil {
|
if err := ioutil.WriteFile(dockerFile, []byte(data), 0644); err != nil {
|
||||||
return builderOpts, errors.Wrap(err, "error met while rendering artifact dockerfile "+a.Path)
|
return builderOpts, errors.Wrap(err, "error met while rendering artifact dockerfile "+a.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := a.Unpack(uncompressedFiles, keepPerms); err != nil {
|
|
||||||
return builderOpts, errors.Wrap(err, "error met while uncompressing artifact "+a.Path)
|
|
||||||
}
|
|
||||||
|
|
||||||
builderOpts = CompilerBackendOptions{
|
builderOpts = CompilerBackendOptions{
|
||||||
ImageName: imageName,
|
ImageName: imageName,
|
||||||
SourcePath: archive,
|
SourcePath: archive,
|
||||||
|
@@ -203,6 +203,44 @@ RUN echo bar > /test2`))
|
|||||||
Expect(content).To(Equal(testString))
|
Expect(content).To(Equal(testString))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("Generates empty packages images", func() {
|
||||||
|
b := NewSimpleDockerBackend()
|
||||||
|
imageprefix := "foo/"
|
||||||
|
|
||||||
|
tmpdir, err := ioutil.TempDir(os.TempDir(), "artifact")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
defer os.RemoveAll(tmpdir) // clean up
|
||||||
|
|
||||||
|
tmpWork, err := ioutil.TempDir(os.TempDir(), "artifact2")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
defer os.RemoveAll(tmpWork) // clean up
|
||||||
|
|
||||||
|
artifact := NewPackageArtifact(filepath.Join(tmpWork, "fake.tar"))
|
||||||
|
artifact.SetCompileSpec(&LuetCompilationSpec{Package: &pkg.DefaultPackage{Name: "foo", Version: "1.0"}})
|
||||||
|
|
||||||
|
err = artifact.Compress(tmpdir, 1)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
resultingImage := imageprefix + "foo--1.0"
|
||||||
|
opts, err := artifact.GenerateFinalImage(resultingImage, b, false)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(opts.ImageName).To(Equal(resultingImage))
|
||||||
|
|
||||||
|
Expect(b.ImageExists(resultingImage)).To(BeTrue())
|
||||||
|
|
||||||
|
result, err := ioutil.TempDir(os.TempDir(), "result")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
defer os.RemoveAll(result) // clean up
|
||||||
|
|
||||||
|
err = b.ExtractRootfs(CompilerBackendOptions{ImageName: resultingImage, Destination: result}, false)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(helpers.DirectoryIsEmpty(result)).To(BeFalse())
|
||||||
|
content, err := ioutil.ReadFile(filepath.Join(result, ".virtual"))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(string(content)).To(Equal(""))
|
||||||
|
})
|
||||||
|
|
||||||
It("Retrieves uncompressed name", func() {
|
It("Retrieves uncompressed name", func() {
|
||||||
a := NewPackageArtifact("foo.tar.gz")
|
a := NewPackageArtifact("foo.tar.gz")
|
||||||
a.SetCompressionType(compiler.GZip)
|
a.SetCompressionType(compiler.GZip)
|
||||||
|
@@ -315,5 +315,82 @@ urls:
|
|||||||
Expect(a.Unpack(extracted, false)).ToNot(HaveOccurred())
|
Expect(a.Unpack(extracted, false)).ToNot(HaveOccurred())
|
||||||
Expect(helpers.Read(filepath.Join(extracted, "test6"))).To(Equal("artifact6\n"))
|
Expect(helpers.Read(filepath.Join(extracted, "test6"))).To(Equal("artifact6\n"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("generates images of virtual packages", func() {
|
||||||
|
b := backend.NewSimpleDockerBackend()
|
||||||
|
tmpdir, err := ioutil.TempDir("", "tree")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
defer os.RemoveAll(tmpdir) // clean up
|
||||||
|
|
||||||
|
generalRecipe := tree.NewCompilerRecipe(pkg.NewInMemoryDatabase(false))
|
||||||
|
|
||||||
|
err = generalRecipe.Load("../../tests/fixtures/virtuals")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(5))
|
||||||
|
|
||||||
|
localcompiler := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), compiler.NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple})
|
||||||
|
|
||||||
|
spec, err := localcompiler.FromPackage(&pkg.DefaultPackage{Name: "a", Category: "test", Version: "1.99"})
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(spec.GetPackage().GetPath()).ToNot(Equal(""))
|
||||||
|
|
||||||
|
tmpdir, err = ioutil.TempDir("", "tree")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
defer os.RemoveAll(tmpdir) // clean up
|
||||||
|
|
||||||
|
spec.SetOutputPath(tmpdir)
|
||||||
|
localcompiler.SetConcurrency(1)
|
||||||
|
|
||||||
|
artifact, err := localcompiler.Compile(false, spec)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(helpers.Exists(artifact.GetPath())).To(BeTrue())
|
||||||
|
Expect(helpers.Untar(artifact.GetPath(), tmpdir, false)).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
repo, err := dockerStubRepo(tmpdir, "../../tests/fixtures/virtuals", repoImage, true, true)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(repo.GetName()).To(Equal("test"))
|
||||||
|
Expect(helpers.Exists(spec.Rel(REPOSITORY_SPECFILE))).ToNot(BeTrue())
|
||||||
|
Expect(helpers.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue())
|
||||||
|
Expect(helpers.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue())
|
||||||
|
err = repo.Write(repoImage, false, true)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(b.ImageAvailable(fmt.Sprintf("%s:%s", repoImage, "tree.tar.gz"))).To(BeTrue())
|
||||||
|
Expect(b.ImageAvailable(fmt.Sprintf("%s:%s", repoImage, "repository.meta.yaml.tar"))).To(BeTrue())
|
||||||
|
Expect(b.ImageAvailable(fmt.Sprintf("%s:%s", repoImage, "repository.yaml"))).To(BeTrue())
|
||||||
|
Expect(b.ImageAvailable(fmt.Sprintf("%s:%s", repoImage, "a-test-1.99"))).To(BeTrue())
|
||||||
|
|
||||||
|
extracted, err := ioutil.TempDir("", "extracted")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
defer os.RemoveAll(extracted) // clean up
|
||||||
|
|
||||||
|
c := repo.Client()
|
||||||
|
|
||||||
|
f, err := c.DownloadFile("repository.yaml")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(helpers.Read(f)).To(ContainSubstring("name: test"))
|
||||||
|
|
||||||
|
a, err := c.DownloadArtifact(&compiler.PackageArtifact{
|
||||||
|
Path: "test.tar",
|
||||||
|
CompileSpec: &compiler.LuetCompilationSpec{
|
||||||
|
Package: &pkg.DefaultPackage{
|
||||||
|
Name: "a",
|
||||||
|
Category: "test",
|
||||||
|
Version: "1.99",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(a.Unpack(extracted, false)).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(helpers.DirectoryIsEmpty(extracted)).To(BeFalse())
|
||||||
|
content, err := ioutil.ReadFile(filepath.Join(extracted, ".virtual"))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(string(content)).To(Equal(""))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user