mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
graph: isolate the (dis)assembly logic
with the current duplication of code in the grap.go split-up, this puts all assembly/disassembly logic into isolated functions Signed-off-by: Vincent Batts <vbatts@redhat.com>
This commit is contained in:
parent
5a00326d29
commit
22347fdb63
3 changed files with 85 additions and 137 deletions
|
@ -28,6 +28,8 @@ import (
|
||||||
"github.com/docker/docker/pkg/system"
|
"github.com/docker/docker/pkg/system"
|
||||||
"github.com/docker/docker/pkg/truncindex"
|
"github.com/docker/docker/pkg/truncindex"
|
||||||
"github.com/docker/docker/runconfig"
|
"github.com/docker/docker/runconfig"
|
||||||
|
"github.com/vbatts/tar-split/tar/asm"
|
||||||
|
"github.com/vbatts/tar-split/tar/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The type is used to protect pulling or building related image
|
// The type is used to protect pulling or building related image
|
||||||
|
@ -530,3 +532,80 @@ func (graph *Graph) RawJSON(id string) ([]byte, error) {
|
||||||
func jsonPath(root string) string {
|
func jsonPath(root string) string {
|
||||||
return filepath.Join(root, jsonFileName)
|
return filepath.Join(root, jsonFileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (graph *Graph) disassembleAndApplyTarLayer(img *image.Image, layerData archive.ArchiveReader, root string) error {
|
||||||
|
// this is saving the tar-split metadata
|
||||||
|
mf, err := os.OpenFile(filepath.Join(root, tarDataFileName), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
mfz := gzip.NewWriter(mf)
|
||||||
|
metaPacker := storage.NewJSONPacker(mfz)
|
||||||
|
defer mf.Close()
|
||||||
|
defer mfz.Close()
|
||||||
|
|
||||||
|
inflatedLayerData, err := archive.DecompressStream(layerData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// we're passing nil here for the file putter, because the ApplyDiff will
|
||||||
|
// handle the extraction of the archive
|
||||||
|
rdr, err := asm.NewInputTarStream(inflatedLayerData, metaPacker, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if img.Size, err = graph.driver.ApplyDiff(img.ID, img.Parent, archive.ArchiveReader(rdr)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (graph *Graph) assembleTarLayer(img *image.Image) (archive.Archive, error) {
|
||||||
|
root := graph.imageRoot(img.ID)
|
||||||
|
mFileName := filepath.Join(root, tarDataFileName)
|
||||||
|
mf, err := os.Open(mFileName)
|
||||||
|
if err != nil {
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
logrus.Errorf("failed to open %q: %s", mFileName, err)
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pR, pW := io.Pipe()
|
||||||
|
// this will need to be in a goroutine, as we are returning the stream of a
|
||||||
|
// tar archive, but can not close the metadata reader early (when this
|
||||||
|
// function returns)...
|
||||||
|
go func() {
|
||||||
|
defer mf.Close()
|
||||||
|
// let's reassemble!
|
||||||
|
logrus.Debugf("[graph] TarLayer with reassembly: %s", img.ID)
|
||||||
|
mfz, err := gzip.NewReader(mf)
|
||||||
|
if err != nil {
|
||||||
|
pW.CloseWithError(fmt.Errorf("[graph] error with %s: %s", mFileName, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer mfz.Close()
|
||||||
|
|
||||||
|
// get our relative path to the container
|
||||||
|
fsLayer, err := graph.driver.Get(img.ID, "")
|
||||||
|
if err != nil {
|
||||||
|
pW.CloseWithError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer graph.driver.Put(img.ID)
|
||||||
|
|
||||||
|
metaUnpacker := storage.NewJSONUnpacker(mfz)
|
||||||
|
fileGetter := storage.NewPathFileGetter(fsLayer)
|
||||||
|
logrus.Debugf("[graph] %s is at %q", img.ID, fsLayer)
|
||||||
|
ots := asm.NewOutputTarStream(fileGetter, metaUnpacker)
|
||||||
|
defer ots.Close()
|
||||||
|
if _, err := io.Copy(pW, ots); err != nil {
|
||||||
|
pW.CloseWithError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pW.Close()
|
||||||
|
}()
|
||||||
|
return pR, nil
|
||||||
|
}
|
||||||
|
|
|
@ -3,10 +3,8 @@
|
||||||
package graph
|
package graph
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"compress/gzip"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -16,8 +14,6 @@ import (
|
||||||
"github.com/docker/docker/image"
|
"github.com/docker/docker/image"
|
||||||
"github.com/docker/docker/pkg/archive"
|
"github.com/docker/docker/pkg/archive"
|
||||||
"github.com/docker/docker/pkg/system"
|
"github.com/docker/docker/pkg/system"
|
||||||
"github.com/vbatts/tar-split/tar/asm"
|
|
||||||
"github.com/vbatts/tar-split/tar/storage"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// setupInitLayer populates a directory with mountpoints suitable
|
// setupInitLayer populates a directory with mountpoints suitable
|
||||||
|
@ -95,29 +91,7 @@ func (graph *Graph) restoreBaseImages() ([]string, error) {
|
||||||
func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader, root string) (err error) {
|
func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader, root string) (err error) {
|
||||||
// Store the layer. If layerData is not nil, unpack it into the new layer
|
// Store the layer. If layerData is not nil, unpack it into the new layer
|
||||||
if layerData != nil {
|
if layerData != nil {
|
||||||
// this is saving the tar-split metadata
|
if err := graph.disassembleAndApplyTarLayer(img, layerData, root); err != nil {
|
||||||
mf, err := os.OpenFile(filepath.Join(root, tarDataFileName), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer mf.Close()
|
|
||||||
mfz := gzip.NewWriter(mf)
|
|
||||||
defer mfz.Close()
|
|
||||||
metaPacker := storage.NewJSONPacker(mfz)
|
|
||||||
|
|
||||||
inflatedLayerData, err := archive.DecompressStream(layerData)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// we're passing nil here for the file putter, because the ApplyDiff will
|
|
||||||
// handle the extraction of the archive
|
|
||||||
its, err := asm.NewInputTarStream(inflatedLayerData, metaPacker, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if img.Size, err = graph.driver.ApplyDiff(img.ID, img.Parent, archive.ArchiveReader(its)); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,49 +112,10 @@ func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader
|
||||||
|
|
||||||
// TarLayer returns a tar archive of the image's filesystem layer.
|
// TarLayer returns a tar archive of the image's filesystem layer.
|
||||||
func (graph *Graph) TarLayer(img *image.Image) (arch archive.Archive, err error) {
|
func (graph *Graph) TarLayer(img *image.Image) (arch archive.Archive, err error) {
|
||||||
root := graph.imageRoot(img.ID)
|
rdr, err := graph.assembleTarLayer(img)
|
||||||
mFileName := filepath.Join(root, tarDataFileName)
|
|
||||||
mf, err := os.Open(mFileName)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !os.IsNotExist(err) {
|
|
||||||
logrus.Errorf("failed to open %q: %s", mFileName, err)
|
|
||||||
}
|
|
||||||
logrus.Debugf("[graph] TarLayer with traditional differ: %s", img.ID)
|
logrus.Debugf("[graph] TarLayer with traditional differ: %s", img.ID)
|
||||||
return graph.driver.Diff(img.ID, img.Parent)
|
return graph.driver.Diff(img.ID, img.Parent)
|
||||||
}
|
}
|
||||||
pR, pW := io.Pipe()
|
return rdr, nil
|
||||||
// this will need to be in a goroutine, as we are returning the stream of a
|
|
||||||
// tar archive, but can not close the metadata reader early (when this
|
|
||||||
// function returns)...
|
|
||||||
go func() {
|
|
||||||
defer mf.Close()
|
|
||||||
// let's reassemble!
|
|
||||||
logrus.Debugf("[graph] TarLayer with reassembly: %s", img.ID)
|
|
||||||
mfz, err := gzip.NewReader(mf)
|
|
||||||
if err != nil {
|
|
||||||
pW.CloseWithError(fmt.Errorf("[graph] error with %s: %s", mFileName, err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer mfz.Close()
|
|
||||||
|
|
||||||
// get our relative path to the container
|
|
||||||
fsLayer, err := graph.driver.Get(img.ID, "")
|
|
||||||
if err != nil {
|
|
||||||
pW.CloseWithError(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer graph.driver.Put(img.ID)
|
|
||||||
|
|
||||||
metaUnpacker := storage.NewJSONUnpacker(mfz)
|
|
||||||
fileGetter := storage.NewPathFileGetter(fsLayer)
|
|
||||||
logrus.Debugf("[graph] %s is at %q", img.ID, fsLayer)
|
|
||||||
ots := asm.NewOutputTarStream(fileGetter, metaUnpacker)
|
|
||||||
defer ots.Close()
|
|
||||||
if _, err := io.Copy(pW, ots); err != nil {
|
|
||||||
pW.CloseWithError(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pW.Close()
|
|
||||||
}()
|
|
||||||
return pR, nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,19 +3,14 @@
|
||||||
package graph
|
package graph
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"compress/gzip"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/docker/daemon/graphdriver/windows"
|
"github.com/docker/docker/daemon/graphdriver/windows"
|
||||||
"github.com/docker/docker/image"
|
"github.com/docker/docker/image"
|
||||||
"github.com/docker/docker/pkg/archive"
|
"github.com/docker/docker/pkg/archive"
|
||||||
"github.com/vbatts/tar-split/tar/asm"
|
|
||||||
"github.com/vbatts/tar-split/tar/storage"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// setupInitLayer populates a directory with mountpoints suitable
|
// setupInitLayer populates a directory with mountpoints suitable
|
||||||
|
@ -120,29 +115,7 @@ func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader
|
||||||
|
|
||||||
// Store the layer. If layerData is not nil, unpack it into the new layer
|
// Store the layer. If layerData is not nil, unpack it into the new layer
|
||||||
if layerData != nil {
|
if layerData != nil {
|
||||||
// this is saving the tar-split metadata
|
if err := graph.disassembleAndApplyTarLayer(img, layerData, root); err != nil {
|
||||||
mf, err := os.OpenFile(filepath.Join(root, tarDataFileName), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer mf.Close()
|
|
||||||
mfz := gzip.NewWriter(mf)
|
|
||||||
defer mfz.Close()
|
|
||||||
metaPacker := storage.NewJSONPacker(mfz)
|
|
||||||
|
|
||||||
inflatedLayerData, err := archive.DecompressStream(layerData)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// we're passing nil here for the file putter, because the ApplyDiff will
|
|
||||||
// handle the extraction of the archive
|
|
||||||
its, err := asm.NewInputTarStream(inflatedLayerData, metaPacker, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if img.Size, err = graph.driver.ApplyDiff(img.ID, img.Parent, archive.ArchiveReader(its)); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -183,50 +156,11 @@ func (graph *Graph) TarLayer(img *image.Image) (arch archive.Archive, err error)
|
||||||
// We keep this functionality here so that we can still work with the VFS
|
// We keep this functionality here so that we can still work with the VFS
|
||||||
// driver during development. VFS is not supported (and just will not work)
|
// driver during development. VFS is not supported (and just will not work)
|
||||||
// for Windows containers.
|
// for Windows containers.
|
||||||
root := graph.imageRoot(img.ID)
|
rdr, err := graph.assembleTarLayer(img)
|
||||||
mFileName := filepath.Join(root, tarDataFileName)
|
|
||||||
mf, err := os.Open(mFileName)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !os.IsNotExist(err) {
|
|
||||||
logrus.Errorf("failed to open %q: %s", mFileName, err)
|
|
||||||
}
|
|
||||||
logrus.Debugf("[graph] TarLayer with traditional differ: %s", img.ID)
|
logrus.Debugf("[graph] TarLayer with traditional differ: %s", img.ID)
|
||||||
return graph.driver.Diff(img.ID, img.Parent)
|
return graph.driver.Diff(img.ID, img.Parent)
|
||||||
}
|
}
|
||||||
pR, pW := io.Pipe()
|
return rdr, nil
|
||||||
// this will need to be in a goroutine, as we are returning the stream of a
|
|
||||||
// tar archive, but can not close the metadata reader early (when this
|
|
||||||
// function returns)...
|
|
||||||
go func() {
|
|
||||||
defer mf.Close()
|
|
||||||
// let's reassemble!
|
|
||||||
logrus.Debugf("[graph] TarLayer with reassembly: %s", img.ID)
|
|
||||||
mfz, err := gzip.NewReader(mf)
|
|
||||||
if err != nil {
|
|
||||||
pW.CloseWithError(fmt.Errorf("[graph] error with %s: %s", mFileName, err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer mfz.Close()
|
|
||||||
|
|
||||||
// get our relative path to the container
|
|
||||||
fsLayer, err := graph.driver.Get(img.ID, "")
|
|
||||||
if err != nil {
|
|
||||||
pW.CloseWithError(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer graph.driver.Put(img.ID)
|
|
||||||
|
|
||||||
metaUnpacker := storage.NewJSONUnpacker(mfz)
|
|
||||||
fileGetter := storage.NewPathFileGetter(fsLayer)
|
|
||||||
logrus.Debugf("[graph] %s is at %q", img.ID, fsLayer)
|
|
||||||
ots := asm.NewOutputTarStream(fileGetter, metaUnpacker)
|
|
||||||
defer ots.Close()
|
|
||||||
if _, err := io.Copy(pW, ots); err != nil {
|
|
||||||
pW.CloseWithError(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pW.Close()
|
|
||||||
}()
|
|
||||||
return pR, nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue