From c51c6264d7a8f5d5878b6b5317bf469a1e52a7af Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Sun, 10 Nov 2019 10:47:28 +0100 Subject: [PATCH] Backend nows must expose a way to unpack rootfs of images --- pkg/compiler/backend/simpledocker.go | 72 ++++++++++++++++++++++++++++ pkg/compiler/backend/simpleimg.go | 3 ++ pkg/compiler/interface.go | 1 + 3 files changed, 76 insertions(+) diff --git a/pkg/compiler/backend/simpledocker.go b/pkg/compiler/backend/simpledocker.go index a06386c9..c89161fc 100644 --- a/pkg/compiler/backend/simpledocker.go +++ b/pkg/compiler/backend/simpledocker.go @@ -17,9 +17,16 @@ package backend import ( "encoding/json" + "io/ioutil" + "os" "os/exec" + "path/filepath" + "strings" + + capi "github.com/mudler/docker-companion/api" "github.com/mudler/luet/pkg/compiler" + "github.com/mudler/luet/pkg/helpers" . "github.com/mudler/luet/pkg/logger" "github.com/pkg/errors" @@ -94,6 +101,71 @@ func (*SimpleDocker) ExportImage(opts compiler.CompilerBackendOptions) error { return nil } +type ManifestEntry struct { + Layers []string `json:"Layers"` +} + +func (*SimpleDocker) ExtractRootfs(opts compiler.CompilerBackendOptions, keepPerms bool) error { + src := opts.SourcePath + dst := opts.Destination + + rootfs, err := ioutil.TempDir(os.TempDir(), "rootfs") + if err != nil { + return errors.Wrap(err, "Error met while creating tempdir for rootfs") + } + defer os.RemoveAll(rootfs) // clean up + + // TODO: Following as option if archive as output? + // archive, err := ioutil.TempDir(os.TempDir(), "archive") + // if err != nil { + // return nil, errors.Wrap(err, "Error met while creating tempdir for rootfs") + // } + // defer os.RemoveAll(archive) // clean up + + err = helpers.Untar(src, rootfs, keepPerms) + if err != nil { + return errors.Wrap(err, "Error met while unpacking rootfs") + } + + manifest, err := helpers.Read(filepath.Join(rootfs, "manifest.json")) + if err != nil { + return errors.Wrap(err, "Error met while reading image manifest") + } + + // Unpack all layers + var manifestData []ManifestEntry + + if err := json.Unmarshal([]byte(manifest), &manifestData); err != nil { + return errors.Wrap(err, "Error met while unmarshalling manifest") + } + + layers_sha := []string{} + + if len(manifestData) != 1 { + return errors.New("Manifest should have one entry") + } + for _, l := range manifestData[0].Layers { + layers_sha = append(layers_sha, strings.Replace(l, "/layer.tar", "", -1)) + } + + export, err := capi.CreateExport(rootfs) + if err != nil { + return err + } + + err = export.UnPackLayers(layers_sha, dst, "") + if err != nil { + return err + } + + // err = helpers.Tar(archive, dst) + // if err != nil { + // return nil, errors.Wrap(err, "Error met while creating package archive") + // } + + return nil +} + // container-diff diff daemon://luet/base alpine --type=file -j // [ // { diff --git a/pkg/compiler/backend/simpleimg.go b/pkg/compiler/backend/simpleimg.go index d45d9cef..282141a0 100644 --- a/pkg/compiler/backend/simpleimg.go +++ b/pkg/compiler/backend/simpleimg.go @@ -91,6 +91,9 @@ func (*SimpleImg) ExportImage(opts compiler.CompilerBackendOptions) error { } // TODO: Dup in docker, refactor common code in helpers for shared parts +func (*SimpleImg) ExtractRootfs(opts compiler.CompilerBackendOptions, keepPerms bool) error { + return errors.New("Not implemented") +} // TODO: Use container-diff (https://github.com/GoogleContainerTools/container-diff) for checking out layer diffs // Changes uses container-diff (https://github.com/GoogleContainerTools/container-diff) for retrieving out layer diffs diff --git a/pkg/compiler/interface.go b/pkg/compiler/interface.go index 2d4aeda2..5b55c5c4 100644 --- a/pkg/compiler/interface.go +++ b/pkg/compiler/interface.go @@ -40,6 +40,7 @@ type CompilerBackend interface { RemoveImage(CompilerBackendOptions) error Changes(fromImage, toImage string) ([]ArtifactLayer, error) ImageDefinitionToTar(CompilerBackendOptions) error + ExtractRootfs(opts CompilerBackendOptions, keepPerms bool) error } type Artifact interface {