Skip to content
This repository was archived by the owner on Mar 27, 2024. It is now read-only.

Commit 4a87618

Browse files
committed
Adding unpacking of tars into final FS
1 parent d505134 commit 4a87618

File tree

15 files changed

+102
-93
lines changed

15 files changed

+102
-93
lines changed

differs/fileDiff.go

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
package differs
22

33
import (
4-
"os"
54
"sort"
65

76
"github.com/GoogleCloudPlatform/container-diff/utils"
8-
"github.com/golang/glog"
97
)
108

119
type FileDiffer struct {
@@ -23,21 +21,11 @@ func diffImageFiles(image1, image2 utils.Image) (utils.DirDiff, error) {
2321

2422
var diff utils.DirDiff
2523

26-
target1 := "j1.json"
27-
err := utils.DirToJSON(img1, target1, true)
24+
img1Dir, err := utils.GetDirectory(img1, true)
2825
if err != nil {
2926
return diff, err
3027
}
31-
target2 := "j2.json"
32-
err = utils.DirToJSON(img2, target2, true)
33-
if err != nil {
34-
return diff, err
35-
}
36-
img1Dir, err := utils.GetDirectory(target1)
37-
if err != nil {
38-
return diff, err
39-
}
40-
img2Dir, err := utils.GetDirectory(target2)
28+
img2Dir, err := utils.GetDirectory(img2, true)
4129
if err != nil {
4230
return diff, err
4331
}
@@ -52,16 +40,7 @@ func diffImageFiles(image1, image2 utils.Image) (utils.DirDiff, error) {
5240
Image2: image2.Source,
5341
Adds: adds,
5442
Dels: dels,
55-
Mods: []string{},
56-
}
57-
58-
err = os.Remove(target1)
59-
if err != nil {
60-
glog.Error(err)
61-
}
62-
err = os.Remove(target2)
63-
if err != nil {
64-
glog.Error(err)
43+
Mods: []string{},
6544
}
6645
return diff, nil
6746
}

differs/pipDiff.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,7 @@ func (d PipDiffer) getPackages(image utils.Image) (map[string]map[string]utils.P
7575
for _, pythonPath := range pythonPaths {
7676
contents, err := ioutil.ReadDir(pythonPath)
7777
if err != nil {
78-
<<<<<<< HEAD
7978
// python version folder doesn't have a site-packages folder or PYTHONPATH doesn't exist
80-
=======
81-
>>>>>>> Addressing Abby's comment
8279
continue
8380
}
8481

tests/file_diff_expected.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"Dels": [
99
"/home/test"
1010
],
11-
"Mods": null
11+
"Mods": []
1212
}
1313
}
1414
]

utils/docker_utils.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@ import (
55
"bytes"
66
"context"
77
"encoding/json"
8+
"errors"
89
"fmt"
910
"io"
11+
"io/ioutil"
12+
"os"
1013
"os/exec"
14+
"path/filepath"
1115
"regexp"
1216
"strings"
1317
"syscall"
@@ -36,6 +40,7 @@ func ValidDockerVersion() (bool, error) {
3640
}
3741
return false, nil
3842
}
43+
3944
func getImagePullResponse(image string, response []Event) (string, error) {
4045
var imageDigest string
4146
for _, event := range response {
@@ -303,3 +308,59 @@ func getImageConfig(image string) (container.Config, error) {
303308
}
304309
return config, nil
305310
}
311+
312+
func getLayersFromManifest(manifestPath string) ([]string, error) {
313+
type Manifest struct {
314+
Layers []string
315+
}
316+
317+
manifestJSON, err := ioutil.ReadFile(manifestPath)
318+
if err != nil {
319+
errMsg := fmt.Sprintf("Could not open manifest to get layer order: %s", err)
320+
return []string{}, errors.New(errMsg)
321+
}
322+
323+
var imageManifest []Manifest
324+
err = json.Unmarshal(manifestJSON, &imageManifest)
325+
if err != nil {
326+
errMsg := fmt.Sprintf("Could not unmarshal manifest to get layer order: %s", err)
327+
return []string{}, errors.New(errMsg)
328+
}
329+
return imageManifest[0].Layers, nil
330+
}
331+
332+
func unpackDockerSave(tarPath string, target string) error {
333+
if _, ok := os.Stat(target); ok != nil {
334+
os.MkdirAll(target, 0777)
335+
}
336+
337+
tempLayerDir := target + "-temp"
338+
err := UnTar(tarPath, tempLayerDir)
339+
if err != nil {
340+
errMsg := fmt.Sprintf("Could not unpack saved Docker image %s: %s", tarPath, err)
341+
return errors.New(errMsg)
342+
}
343+
344+
manifest := filepath.Join(tempLayerDir, "manifest.json")
345+
layers, err := getLayersFromManifest(manifest)
346+
if err != nil {
347+
return err
348+
}
349+
350+
for _, layer := range layers {
351+
layerTar := filepath.Join(tempLayerDir, layer)
352+
if _, err := os.Stat(layerTar); err != nil {
353+
glog.Infof("Did not unpack layer %s because no layer.tar found", layer)
354+
continue
355+
}
356+
err = UnTar(layerTar, target)
357+
if err != nil {
358+
glog.Errorf("Could not unpack layer %s: %s", layer, err)
359+
}
360+
}
361+
err = os.RemoveAll(tempLayerDir)
362+
if err != nil {
363+
glog.Errorf("Error deleting temp image layer filesystem: %s", err)
364+
}
365+
return nil
366+
}

utils/fs_utils.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,22 @@ func GetModifiedEntries(d1, d2 Directory) []string {
6868
glog.Errorf("Error checking directory entry %s: %s\n", f, err)
6969
continue
7070
}
71+
f2stat, err := os.Stat(f2path)
72+
if err != nil {
73+
glog.Errorf("Error checking directory entry %s: %s\n", f, err)
74+
continue
75+
}
76+
77+
// If the directory entry in question is a tar, verify that the two have the same size
78+
if isTar(f1path) {
79+
if f1stat.Size() != f2stat.Size() {
80+
modified = append(modified, f)
81+
}
82+
continue
83+
}
84+
85+
// If the directory entry is not a tar and not a directory, then it's a file so make sure the file contents are the same
86+
// Note: We skip over directory entries because to compare directories, we compare their contents
7187
if !f1stat.IsDir() {
7288
same, err := checkSameFile(f1path, f2path)
7389
if err != nil {
@@ -103,7 +119,7 @@ func DiffDirectory(d1, d2 Directory) (DirDiff, bool) {
103119
adds := GetAddedEntries(d1, d2)
104120
dels := GetDeletedEntries(d1, d2)
105121
mods := GetModifiedEntries(d1, d2)
106-
122+
107123
var same bool
108124
if len(adds) == 0 && len(dels) == 0 && len(mods) == 0 {
109125
same = true

utils/fs_utils_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,20 +75,20 @@ func TestGetDirectory(t *testing.T) {
7575
deep bool
7676
}{
7777
{
78-
descrip: "deep",
79-
path: "testTars/la-croix3-full",
78+
descrip: "deep",
79+
path: "testTars/la-croix3-full",
8080
expected: Directory{
81-
Root: "testTars/la-croix3-full",
82-
Content: []string{"/lime.txt","/nest","/nest/f1.txt","/nested-dir","/nested-dir/f2.txt","/passionfruit.txt","/peach-pear.txt"},
81+
Root: "testTars/la-croix3-full",
82+
Content: []string{"/lime.txt", "/nest", "/nest/f1.txt", "/nested-dir", "/nested-dir/f2.txt", "/passionfruit.txt", "/peach-pear.txt"},
8383
},
8484
deep: true,
8585
},
8686
{
87-
descrip: "shallow",
88-
path: "testTars/la-croix3-full",
87+
descrip: "shallow",
88+
path: "testTars/la-croix3-full",
8989
expected: Directory{
90-
Root: "testTars/la-croix3-full",
91-
Content: []string{"/lime.txt","/nest","/nested-dir","/passionfruit.txt","/peach-pear.txt"},
90+
Root: "testTars/la-croix3-full",
91+
Content: []string{"/lime.txt", "/nest", "/nested-dir", "/passionfruit.txt", "/peach-pear.txt"},
9292
},
9393
deep: false,
9494
},

utils/image_prep_utils.go

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ func (p ImagePrepper) GetImage() (Image, error) {
9595
func getImageFromTar(tarPath string) (string, error) {
9696
glog.Info("Extracting image tar to obtain image file system")
9797
path := strings.TrimSuffix(tarPath, filepath.Ext(tarPath))
98-
err := UnTar(tarPath, path)
98+
err := unpackDockerSave(tarPath, path)
9999
return path, err
100100
}
101101

@@ -201,10 +201,7 @@ func (p IDPrepper) getFileSystem() (string, error) {
201201
}
202202

203203
defer os.Remove(tarPath)
204-
glog.Info("Extracting image tar to obtain image file system")
205-
path := strings.TrimSuffix(tarPath, filepath.Ext(tarPath))
206-
err = ExtractTar(tarPath)
207-
return path, err
204+
return getImageFromTar(tarPath)
208205
}
209206

210207
func (p IDPrepper) getConfig() (ConfigSchema, error) {
@@ -255,13 +252,13 @@ func (p TarPrepper) getFileSystem() (string, error) {
255252
}
256253

257254
func (p TarPrepper) getConfig() (ConfigSchema, error) {
258-
tmpDir := strings.TrimSuffix(p.Source, filepath.Ext(p.Source))
259-
defer os.Remove(tmpDir)
260-
err := UnTar(p.Source, tmpDir)
255+
tempDir := strings.TrimSuffix(p.Source, filepath.Ext(p.Source)) + "-config"
256+
defer os.RemoveAll(tempDir)
257+
err := UnTar(p.Source, tempDir)
261258
if err != nil {
262259
return ConfigSchema{}, err
263260
}
264-
contents, err := ioutil.ReadDir(tmpDir)
261+
contents, err := ioutil.ReadDir(tempDir)
265262
if err != nil {
266263
glog.Errorf("Could not read image tar contents: %s", err)
267264
return ConfigSchema{}, errors.New("Could not obtain image config")
@@ -276,7 +273,7 @@ func (p TarPrepper) getConfig() (ConfigSchema, error) {
276273
glog.Error("Multiple possible config sources detected for image at " + p.Source + ". Multiple images likely contained in tar. Choosing first one, but diff results may not be completely accurate.")
277274
break
278275
}
279-
fileName := filepath.Join(tmpDir, item.Name())
276+
fileName := filepath.Join(tempDir, item.Name())
280277
file, err := ioutil.ReadFile(fileName)
281278
if err != nil {
282279
glog.Errorf("Could not read config file %s: %s", fileName, err)

utils/tar_utils.go

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ func UnTar(filename string, target string) error {
7979
if _, ok := os.Stat(target); ok != nil {
8080
os.MkdirAll(target, 0777)
8181
}
82-
8382
file, err := os.Open(filename)
8483
if err != nil {
8584
return err
@@ -98,30 +97,6 @@ func isTar(path string) bool {
9897
return filepath.Ext(path) == ".tar"
9998
}
10099

101-
// ExtractTar extracts the tar and any nested tar at the given path.
102-
// After execution the original tar file is removed and the untarred version is in it place.
103-
func ExtractTar(path string) error {
104-
removeTar := false
105-
106-
var untarWalkFn func(path string, info os.FileInfo, err error) error
107-
108-
untarWalkFn = func(path string, info os.FileInfo, err error) error {
109-
if isTar(path) {
110-
target := strings.TrimSuffix(path, filepath.Ext(path))
111-
UnTar(path, target)
112-
if removeTar {
113-
os.Remove(path)
114-
}
115-
// remove nested tar files that get copied but not the original tar passed
116-
removeTar = true
117-
filepath.Walk(target, untarWalkFn)
118-
}
119-
return nil
120-
}
121-
122-
return filepath.Walk(path, untarWalkFn)
123-
}
124-
125100
func CheckTar(image string) bool {
126101
if strings.TrimSuffix(image, ".tar") == image {
127102
return false

utils/tar_utils_test.go

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package utils
22

33
import (
4-
//"fmt"
54
"errors"
5+
"fmt"
66
"io"
77
"io/ioutil"
88
"log"
@@ -74,10 +74,6 @@ func TestUnTar(t *testing.T) {
7474
remove = false
7575
}
7676
if !dirEquals(test.expected, test.target) {
77-
//d1, _ := GetDirectory(test.expected, true)
78-
//fmt.Println(d1.Content)
79-
//d2, _ := GetDirectory(test.target, true)
80-
//fmt.Println(d2.Content)
8177
t.Error(test.descrip, ": Directory created not correct structure.")
8278
remove = false
8379
}
@@ -178,24 +174,12 @@ func TestIsTar(t *testing.T) {
178174
}
179175
}
180176

181-
/*func TestExtractTar(t *testing.T) {
182-
tarPath := "testTars/la-croix3.tar"
183-
target := "testTars/la-croix3"
184-
expected := "testTars/la-croix3-full"
185-
err := ExtractTar(tarPath)
186-
if err != nil {
187-
t.Errorf("Got unexpected error: %s", err)
188-
}
189-
if !dirEquals(expected, target) || !dirEquals(target, expected) {
190-
t.Errorf("Directory created not correct structure.")
191-
}
192-
os.RemoveAll(target)
193-
194-
}*/
195-
196177
func dirEquals(actual string, path string) bool {
197178
d1, _ := GetDirectory(actual, true)
198179
d2, _ := GetDirectory(path, true)
199-
_, same := DiffDirectory(d1, d2)
180+
diff, same := DiffDirectory(d1, d2)
181+
if !same {
182+
fmt.Printf("%v", diff)
183+
}
200184
return same
201185
}

utils/testTars/la-croix-dir-update-actual/lime.txt

Whitespace-only changes.

0 commit comments

Comments
 (0)