Add GenerateFinalImage to package artifacts

GenerateFinalImage generates a docker image from scratch with the
artifact content.

Related to #169
This commit is contained in:
Ettore Di Giacinto
2021-01-18 12:08:47 +01:00
parent 43b0b11028
commit a1f4c28973
5 changed files with 98 additions and 3 deletions

View File

@@ -241,6 +241,46 @@ func (a *PackageArtifact) SetPath(p string) {
a.Path = p
}
func (a *PackageArtifact) genDockerfile() string {
return `
FROM scratch
COPY * /`
}
// GenerateFinalImage takes an artifact and builds a Docker image with its content
func (a *PackageArtifact) GenerateFinalImage(imageprefix string, b CompilerBackend, keepPerms bool) (CompilerBackendOptions, error) {
builderOpts := CompilerBackendOptions{}
archive, err := LuetCfg.GetSystem().TempDir("archive")
if err != nil {
return builderOpts, errors.Wrap(err, "error met while creating tempdir for "+a.Path)
}
defer os.RemoveAll(archive) // clean up
uncompressedFiles := filepath.Join(archive, "files")
dockerFile := filepath.Join(archive, "Dockerfile")
if err := os.MkdirAll(uncompressedFiles, os.ModePerm); err != nil {
return builderOpts, errors.Wrap(err, "error met while creating tempdir for "+a.Path)
}
data := a.genDockerfile()
if err := ioutil.WriteFile(dockerFile, []byte(data), 0644); err != nil {
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{
ImageName: imageprefix + a.CompileSpec.Package.GetFingerPrint(),
SourcePath: archive,
DockerFileName: dockerFile,
Context: uncompressedFiles,
}
return builderOpts, b.BuildImage(builderOpts)
}
// Compress Archives and compress (TODO) to the artifact path
func (a *PackageArtifact) Compress(src string, concurrency int) error {
switch a.CompressionType {

View File

@@ -159,5 +159,46 @@ RUN echo bar > /test2`))
Expect(err).To(HaveOccurred())
})
It("Generates packages images", func() {
b := NewSimpleDockerBackend()
imageprefix := "foo/"
testString := []byte(`funky test data`)
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
err = ioutil.WriteFile(filepath.Join(tmpdir, "test"), testString, 0644)
Expect(err).ToNot(HaveOccurred())
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(imageprefix, 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())
content, err := ioutil.ReadFile(filepath.Join(result, "test"))
Expect(err).ToNot(HaveOccurred())
Expect(content).To(Equal(testString))
})
})
})

View File

@@ -183,10 +183,23 @@ type ManifestEntry struct {
Layers []string `json:"Layers"`
}
func (*SimpleDocker) ExtractRootfs(opts compiler.CompilerBackendOptions, keepPerms bool) error {
func (b *SimpleDocker) ExtractRootfs(opts compiler.CompilerBackendOptions, keepPerms bool) error {
src := opts.SourcePath
dst := opts.Destination
if src == "" && opts.ImageName != "" {
tempUnpack, err := ioutil.TempDir(dst, "tempUnpack")
if err != nil {
return errors.Wrap(err, "Error met while creating tempdir for rootfs")
}
defer os.RemoveAll(tempUnpack) // clean up
imageExport := filepath.Join(tempUnpack, "image.tar")
if err := b.ExportImage(compiler.CompilerBackendOptions{ImageName: opts.ImageName, Destination: imageExport}); err != nil {
return errors.Wrap(err, "while exporting image before extraction")
}
src = imageExport
}
rootfs, err := ioutil.TempDir(dst, "tmprootfs")
if err != nil {
return errors.Wrap(err, "Error met while creating tempdir for rootfs")

View File

@@ -139,7 +139,7 @@ func (*SimpleImg) ExportImage(opts compiler.CompilerBackendOptions) error {
return nil
}
// TODO: Dup in docker, refactor common code in helpers for shared parts
// ExtractRootfs extracts the docker image content inside the destination
func (*SimpleImg) ExtractRootfs(opts compiler.CompilerBackendOptions, keepPerms bool) error {
name := opts.ImageName
path := opts.Destination
@@ -153,7 +153,6 @@ func (*SimpleImg) ExtractRootfs(opts compiler.CompilerBackendOptions, keepPerms
}
Info(":tea: Image " + name + " extracted")
return nil
//return NewSimpleDockerBackend().ExtractRootfs(opts, keepPerms)
}
// TODO: Use container-diff (https://github.com/GoogleContainerTools/container-diff) for checking out layer diffs

View File

@@ -114,6 +114,8 @@ type Artifact interface {
GetChecksums() Checksums
SetChecksums(c Checksums)
GenerateFinalImage(string, CompilerBackend, bool) (CompilerBackendOptions, error)
}
type ArtifactNode struct {