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>
| ... | ... |
@@ -28,6 +28,8 @@ import ( |
| 28 | 28 |
"github.com/docker/docker/pkg/system" |
| 29 | 29 |
"github.com/docker/docker/pkg/truncindex" |
| 30 | 30 |
"github.com/docker/docker/runconfig" |
| 31 |
+ "github.com/vbatts/tar-split/tar/asm" |
|
| 32 |
+ "github.com/vbatts/tar-split/tar/storage" |
|
| 31 | 33 |
) |
| 32 | 34 |
|
| 33 | 35 |
// The type is used to protect pulling or building related image |
| ... | ... |
@@ -530,3 +532,80 @@ func (graph *Graph) RawJSON(id string) ([]byte, error) {
|
| 530 | 530 |
func jsonPath(root string) string {
|
| 531 | 531 |
return filepath.Join(root, jsonFileName) |
| 532 | 532 |
} |
| 533 |
+ |
|
| 534 |
+func (graph *Graph) disassembleAndApplyTarLayer(img *image.Image, layerData archive.ArchiveReader, root string) error {
|
|
| 535 |
+ // this is saving the tar-split metadata |
|
| 536 |
+ mf, err := os.OpenFile(filepath.Join(root, tarDataFileName), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600)) |
|
| 537 |
+ if err != nil {
|
|
| 538 |
+ return err |
|
| 539 |
+ } |
|
| 540 |
+ mfz := gzip.NewWriter(mf) |
|
| 541 |
+ metaPacker := storage.NewJSONPacker(mfz) |
|
| 542 |
+ defer mf.Close() |
|
| 543 |
+ defer mfz.Close() |
|
| 544 |
+ |
|
| 545 |
+ inflatedLayerData, err := archive.DecompressStream(layerData) |
|
| 546 |
+ if err != nil {
|
|
| 547 |
+ return err |
|
| 548 |
+ } |
|
| 549 |
+ |
|
| 550 |
+ // we're passing nil here for the file putter, because the ApplyDiff will |
|
| 551 |
+ // handle the extraction of the archive |
|
| 552 |
+ rdr, err := asm.NewInputTarStream(inflatedLayerData, metaPacker, nil) |
|
| 553 |
+ if err != nil {
|
|
| 554 |
+ return err |
|
| 555 |
+ } |
|
| 556 |
+ |
|
| 557 |
+ if img.Size, err = graph.driver.ApplyDiff(img.ID, img.Parent, archive.ArchiveReader(rdr)); err != nil {
|
|
| 558 |
+ return err |
|
| 559 |
+ } |
|
| 560 |
+ |
|
| 561 |
+ return nil |
|
| 562 |
+} |
|
| 563 |
+ |
|
| 564 |
+func (graph *Graph) assembleTarLayer(img *image.Image) (archive.Archive, error) {
|
|
| 565 |
+ root := graph.imageRoot(img.ID) |
|
| 566 |
+ mFileName := filepath.Join(root, tarDataFileName) |
|
| 567 |
+ mf, err := os.Open(mFileName) |
|
| 568 |
+ if err != nil {
|
|
| 569 |
+ if !os.IsNotExist(err) {
|
|
| 570 |
+ logrus.Errorf("failed to open %q: %s", mFileName, err)
|
|
| 571 |
+ } |
|
| 572 |
+ return nil, err |
|
| 573 |
+ } |
|
| 574 |
+ pR, pW := io.Pipe() |
|
| 575 |
+ // this will need to be in a goroutine, as we are returning the stream of a |
|
| 576 |
+ // tar archive, but can not close the metadata reader early (when this |
|
| 577 |
+ // function returns)... |
|
| 578 |
+ go func() {
|
|
| 579 |
+ defer mf.Close() |
|
| 580 |
+ // let's reassemble! |
|
| 581 |
+ logrus.Debugf("[graph] TarLayer with reassembly: %s", img.ID)
|
|
| 582 |
+ mfz, err := gzip.NewReader(mf) |
|
| 583 |
+ if err != nil {
|
|
| 584 |
+ pW.CloseWithError(fmt.Errorf("[graph] error with %s: %s", mFileName, err))
|
|
| 585 |
+ return |
|
| 586 |
+ } |
|
| 587 |
+ defer mfz.Close() |
|
| 588 |
+ |
|
| 589 |
+ // get our relative path to the container |
|
| 590 |
+ fsLayer, err := graph.driver.Get(img.ID, "") |
|
| 591 |
+ if err != nil {
|
|
| 592 |
+ pW.CloseWithError(err) |
|
| 593 |
+ return |
|
| 594 |
+ } |
|
| 595 |
+ defer graph.driver.Put(img.ID) |
|
| 596 |
+ |
|
| 597 |
+ metaUnpacker := storage.NewJSONUnpacker(mfz) |
|
| 598 |
+ fileGetter := storage.NewPathFileGetter(fsLayer) |
|
| 599 |
+ logrus.Debugf("[graph] %s is at %q", img.ID, fsLayer)
|
|
| 600 |
+ ots := asm.NewOutputTarStream(fileGetter, metaUnpacker) |
|
| 601 |
+ defer ots.Close() |
|
| 602 |
+ if _, err := io.Copy(pW, ots); err != nil {
|
|
| 603 |
+ pW.CloseWithError(err) |
|
| 604 |
+ return |
|
| 605 |
+ } |
|
| 606 |
+ pW.Close() |
|
| 607 |
+ }() |
|
| 608 |
+ return pR, nil |
|
| 609 |
+} |
| ... | ... |
@@ -3,10 +3,8 @@ |
| 3 | 3 |
package graph |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 |
- "compress/gzip" |
|
| 7 | 6 |
"encoding/json" |
| 8 | 7 |
"fmt" |
| 9 |
- "io" |
|
| 10 | 8 |
"os" |
| 11 | 9 |
"path/filepath" |
| 12 | 10 |
"strings" |
| ... | ... |
@@ -16,8 +14,6 @@ import ( |
| 16 | 16 |
"github.com/docker/docker/image" |
| 17 | 17 |
"github.com/docker/docker/pkg/archive" |
| 18 | 18 |
"github.com/docker/docker/pkg/system" |
| 19 |
- "github.com/vbatts/tar-split/tar/asm" |
|
| 20 |
- "github.com/vbatts/tar-split/tar/storage" |
|
| 21 | 19 |
) |
| 22 | 20 |
|
| 23 | 21 |
// setupInitLayer populates a directory with mountpoints suitable |
| ... | ... |
@@ -95,29 +91,7 @@ func (graph *Graph) restoreBaseImages() ([]string, error) {
|
| 95 | 95 |
func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader, root string) (err error) {
|
| 96 | 96 |
// Store the layer. If layerData is not nil, unpack it into the new layer |
| 97 | 97 |
if layerData != nil {
|
| 98 |
- // this is saving the tar-split metadata |
|
| 99 |
- mf, err := os.OpenFile(filepath.Join(root, tarDataFileName), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600)) |
|
| 100 |
- if err != nil {
|
|
| 101 |
- return err |
|
| 102 |
- } |
|
| 103 |
- defer mf.Close() |
|
| 104 |
- mfz := gzip.NewWriter(mf) |
|
| 105 |
- defer mfz.Close() |
|
| 106 |
- metaPacker := storage.NewJSONPacker(mfz) |
|
| 107 |
- |
|
| 108 |
- inflatedLayerData, err := archive.DecompressStream(layerData) |
|
| 109 |
- if err != nil {
|
|
| 110 |
- return err |
|
| 111 |
- } |
|
| 112 |
- |
|
| 113 |
- // we're passing nil here for the file putter, because the ApplyDiff will |
|
| 114 |
- // handle the extraction of the archive |
|
| 115 |
- its, err := asm.NewInputTarStream(inflatedLayerData, metaPacker, nil) |
|
| 116 |
- if err != nil {
|
|
| 117 |
- return err |
|
| 118 |
- } |
|
| 119 |
- |
|
| 120 |
- if img.Size, err = graph.driver.ApplyDiff(img.ID, img.Parent, archive.ArchiveReader(its)); err != nil {
|
|
| 98 |
+ if err := graph.disassembleAndApplyTarLayer(img, layerData, root); err != nil {
|
|
| 121 | 99 |
return err |
| 122 | 100 |
} |
| 123 | 101 |
} |
| ... | ... |
@@ -138,49 +112,10 @@ func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader |
| 138 | 138 |
|
| 139 | 139 |
// TarLayer returns a tar archive of the image's filesystem layer. |
| 140 | 140 |
func (graph *Graph) TarLayer(img *image.Image) (arch archive.Archive, err error) {
|
| 141 |
- root := graph.imageRoot(img.ID) |
|
| 142 |
- mFileName := filepath.Join(root, tarDataFileName) |
|
| 143 |
- mf, err := os.Open(mFileName) |
|
| 141 |
+ rdr, err := graph.assembleTarLayer(img) |
|
| 144 | 142 |
if err != nil {
|
| 145 |
- if !os.IsNotExist(err) {
|
|
| 146 |
- logrus.Errorf("failed to open %q: %s", mFileName, err)
|
|
| 147 |
- } |
|
| 148 | 143 |
logrus.Debugf("[graph] TarLayer with traditional differ: %s", img.ID)
|
| 149 | 144 |
return graph.driver.Diff(img.ID, img.Parent) |
| 150 | 145 |
} |
| 151 |
- pR, pW := io.Pipe() |
|
| 152 |
- // this will need to be in a goroutine, as we are returning the stream of a |
|
| 153 |
- // tar archive, but can not close the metadata reader early (when this |
|
| 154 |
- // function returns)... |
|
| 155 |
- go func() {
|
|
| 156 |
- defer mf.Close() |
|
| 157 |
- // let's reassemble! |
|
| 158 |
- logrus.Debugf("[graph] TarLayer with reassembly: %s", img.ID)
|
|
| 159 |
- mfz, err := gzip.NewReader(mf) |
|
| 160 |
- if err != nil {
|
|
| 161 |
- pW.CloseWithError(fmt.Errorf("[graph] error with %s: %s", mFileName, err))
|
|
| 162 |
- return |
|
| 163 |
- } |
|
| 164 |
- defer mfz.Close() |
|
| 165 |
- |
|
| 166 |
- // get our relative path to the container |
|
| 167 |
- fsLayer, err := graph.driver.Get(img.ID, "") |
|
| 168 |
- if err != nil {
|
|
| 169 |
- pW.CloseWithError(err) |
|
| 170 |
- return |
|
| 171 |
- } |
|
| 172 |
- defer graph.driver.Put(img.ID) |
|
| 173 |
- |
|
| 174 |
- metaUnpacker := storage.NewJSONUnpacker(mfz) |
|
| 175 |
- fileGetter := storage.NewPathFileGetter(fsLayer) |
|
| 176 |
- logrus.Debugf("[graph] %s is at %q", img.ID, fsLayer)
|
|
| 177 |
- ots := asm.NewOutputTarStream(fileGetter, metaUnpacker) |
|
| 178 |
- defer ots.Close() |
|
| 179 |
- if _, err := io.Copy(pW, ots); err != nil {
|
|
| 180 |
- pW.CloseWithError(err) |
|
| 181 |
- return |
|
| 182 |
- } |
|
| 183 |
- pW.Close() |
|
| 184 |
- }() |
|
| 185 |
- return pR, nil |
|
| 146 |
+ return rdr, nil |
|
| 186 | 147 |
} |
| ... | ... |
@@ -3,19 +3,14 @@ |
| 3 | 3 |
package graph |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 |
- "compress/gzip" |
|
| 7 | 6 |
"encoding/json" |
| 8 | 7 |
"fmt" |
| 9 |
- "io" |
|
| 10 | 8 |
"os" |
| 11 |
- "path/filepath" |
|
| 12 | 9 |
|
| 13 | 10 |
"github.com/Sirupsen/logrus" |
| 14 | 11 |
"github.com/docker/docker/daemon/graphdriver/windows" |
| 15 | 12 |
"github.com/docker/docker/image" |
| 16 | 13 |
"github.com/docker/docker/pkg/archive" |
| 17 |
- "github.com/vbatts/tar-split/tar/asm" |
|
| 18 |
- "github.com/vbatts/tar-split/tar/storage" |
|
| 19 | 14 |
) |
| 20 | 15 |
|
| 21 | 16 |
// setupInitLayer populates a directory with mountpoints suitable |
| ... | ... |
@@ -120,29 +115,7 @@ func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader |
| 120 | 120 |
|
| 121 | 121 |
// Store the layer. If layerData is not nil, unpack it into the new layer |
| 122 | 122 |
if layerData != nil {
|
| 123 |
- // this is saving the tar-split metadata |
|
| 124 |
- mf, err := os.OpenFile(filepath.Join(root, tarDataFileName), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600)) |
|
| 125 |
- if err != nil {
|
|
| 126 |
- return err |
|
| 127 |
- } |
|
| 128 |
- defer mf.Close() |
|
| 129 |
- mfz := gzip.NewWriter(mf) |
|
| 130 |
- defer mfz.Close() |
|
| 131 |
- metaPacker := storage.NewJSONPacker(mfz) |
|
| 132 |
- |
|
| 133 |
- inflatedLayerData, err := archive.DecompressStream(layerData) |
|
| 134 |
- if err != nil {
|
|
| 135 |
- return err |
|
| 136 |
- } |
|
| 137 |
- |
|
| 138 |
- // we're passing nil here for the file putter, because the ApplyDiff will |
|
| 139 |
- // handle the extraction of the archive |
|
| 140 |
- its, err := asm.NewInputTarStream(inflatedLayerData, metaPacker, nil) |
|
| 141 |
- if err != nil {
|
|
| 142 |
- return err |
|
| 143 |
- } |
|
| 144 |
- |
|
| 145 |
- if img.Size, err = graph.driver.ApplyDiff(img.ID, img.Parent, archive.ArchiveReader(its)); err != nil {
|
|
| 123 |
+ if err := graph.disassembleAndApplyTarLayer(img, layerData, root); err != nil {
|
|
| 146 | 124 |
return err |
| 147 | 125 |
} |
| 148 | 126 |
} |
| ... | ... |
@@ -183,50 +156,11 @@ func (graph *Graph) TarLayer(img *image.Image) (arch archive.Archive, err error) |
| 183 | 183 |
// We keep this functionality here so that we can still work with the VFS |
| 184 | 184 |
// driver during development. VFS is not supported (and just will not work) |
| 185 | 185 |
// for Windows containers. |
| 186 |
- root := graph.imageRoot(img.ID) |
|
| 187 |
- mFileName := filepath.Join(root, tarDataFileName) |
|
| 188 |
- mf, err := os.Open(mFileName) |
|
| 186 |
+ rdr, err := graph.assembleTarLayer(img) |
|
| 189 | 187 |
if err != nil {
|
| 190 |
- if !os.IsNotExist(err) {
|
|
| 191 |
- logrus.Errorf("failed to open %q: %s", mFileName, err)
|
|
| 192 |
- } |
|
| 193 | 188 |
logrus.Debugf("[graph] TarLayer with traditional differ: %s", img.ID)
|
| 194 | 189 |
return graph.driver.Diff(img.ID, img.Parent) |
| 195 | 190 |
} |
| 196 |
- pR, pW := io.Pipe() |
|
| 197 |
- // this will need to be in a goroutine, as we are returning the stream of a |
|
| 198 |
- // tar archive, but can not close the metadata reader early (when this |
|
| 199 |
- // function returns)... |
|
| 200 |
- go func() {
|
|
| 201 |
- defer mf.Close() |
|
| 202 |
- // let's reassemble! |
|
| 203 |
- logrus.Debugf("[graph] TarLayer with reassembly: %s", img.ID)
|
|
| 204 |
- mfz, err := gzip.NewReader(mf) |
|
| 205 |
- if err != nil {
|
|
| 206 |
- pW.CloseWithError(fmt.Errorf("[graph] error with %s: %s", mFileName, err))
|
|
| 207 |
- return |
|
| 208 |
- } |
|
| 209 |
- defer mfz.Close() |
|
| 210 |
- |
|
| 211 |
- // get our relative path to the container |
|
| 212 |
- fsLayer, err := graph.driver.Get(img.ID, "") |
|
| 213 |
- if err != nil {
|
|
| 214 |
- pW.CloseWithError(err) |
|
| 215 |
- return |
|
| 216 |
- } |
|
| 217 |
- defer graph.driver.Put(img.ID) |
|
| 218 |
- |
|
| 219 |
- metaUnpacker := storage.NewJSONUnpacker(mfz) |
|
| 220 |
- fileGetter := storage.NewPathFileGetter(fsLayer) |
|
| 221 |
- logrus.Debugf("[graph] %s is at %q", img.ID, fsLayer)
|
|
| 222 |
- ots := asm.NewOutputTarStream(fileGetter, metaUnpacker) |
|
| 223 |
- defer ots.Close() |
|
| 224 |
- if _, err := io.Copy(pW, ots); err != nil {
|
|
| 225 |
- pW.CloseWithError(err) |
|
| 226 |
- return |
|
| 227 |
- } |
|
| 228 |
- pW.Close() |
|
| 229 |
- }() |
|
| 230 |
- return pR, nil |
|
| 191 |
+ return rdr, nil |
|
| 231 | 192 |
} |
| 232 | 193 |
} |