Skip to content

Commit 68eb4c6

Browse files
masahiro331knqyf263
andcommitted
Revert part of fanal#51 (fanal#64)
* Fix getFilteredTarballBuffer function * Add dotfilepath tar.gz * Add dot filepath test * fix test name * change test filename * Add empty files * fix(docker): remove getFilteredTarballBuffer * test(docker): remove tests for TestDocker_ExtractLayerWorker * test(docker): remove unused files Co-authored-by: Teppei Fukuda <[email protected]>
1 parent eaf9fa5 commit 68eb4c6

File tree

5 files changed

+26
-197
lines changed

5 files changed

+26
-197
lines changed

extractor/docker/docker.go

Lines changed: 26 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ func (d Extractor) Extract(ctx context.Context, imageName string, filenames []st
228228
for _, ref := range m.Manifest.Layers {
229229
layerIDs = append(layerIDs, string(ref.Digest))
230230
go func(dig digest.Digest) {
231-
d.extractLayerWorker(dig, r, ctx, image, errCh, layerCh, filenames)
231+
d.extractLayerWorker(dig, r, ctx, image, errCh, layerCh)
232232
}(ref.Digest)
233233
}
234234

@@ -289,50 +289,40 @@ func (d Extractor) extractLayerFiles(ctx context.Context, layerCh chan layer, er
289289
return nil
290290
}
291291

292-
func (d Extractor) extractLayerWorker(dig digest.Digest, r *registry.Registry, ctx context.Context, image registry.Image, errCh chan error, layerCh chan layer, filenames []string) {
293-
var tarContent bytes.Buffer
292+
func (d Extractor) extractLayerWorker(dig digest.Digest, r *registry.Registry, ctx context.Context, image registry.Image, errCh chan error, layerCh chan layer) {
294293
var cacheContent []byte
295-
var cacheBuf bytes.Buffer
296294

297295
found, _ := d.cache.Get(LayerTarsBucket, string(dig), &cacheContent)
298296

299297
if found {
300-
b, errTar := extractTarFromTarZstd(cacheContent)
301-
n, errWrite := cacheBuf.Write(b)
302-
if errTar != nil || len(b) <= 0 || errWrite != nil || n <= 0 {
303-
found = false
304-
}
305-
}
306-
307-
if !found {
308-
rc, err := r.DownloadLayer(ctx, image.Path, dig)
309-
if err != nil {
310-
errCh <- xerrors.Errorf("failed to download the layer(%s): %w", dig, err)
298+
b, err := extractTarFromTarZstd(cacheContent)
299+
if err == nil && len(b) > 0 {
300+
cacheBuf := bytes.NewBuffer(b)
301+
layerCh <- layer{ID: dig, Content: ioutil.NopCloser(cacheBuf)}
311302
return
312303
}
313-
defer rc.Close()
314-
315-
// read the incoming gzip from the layer
316-
gzipReader, err := gzip.NewReader(rc)
317-
if err != nil {
318-
errCh <- xerrors.Errorf("could not init gzip reader: %w", err)
319-
return
320-
}
321-
defer gzipReader.Close()
322-
323-
tarReader := tar.NewReader(io.TeeReader(gzipReader, &tarContent))
304+
}
324305

325-
if len(filenames) > 0 {
326-
if cacheBuf, err = getFilteredTarballBuffer(tarReader, filenames); err != nil {
327-
errCh <- err
328-
return
329-
}
330-
}
306+
rc, err := r.DownloadLayer(ctx, image.Path, dig)
307+
if err != nil {
308+
errCh <- xerrors.Errorf("failed to download the layer(%s): %w", dig, err)
309+
return
310+
}
311+
defer rc.Close()
331312

332-
d.storeLayerInCache(cacheBuf, dig)
313+
// read the incoming gzip from the layer
314+
gzipReader, err := gzip.NewReader(rc)
315+
if err != nil {
316+
errCh <- xerrors.Errorf("could not init gzip reader: %w", err)
317+
return
333318
}
319+
defer gzipReader.Close()
320+
321+
b := bytes.NewBuffer(nil)
322+
tr := io.TeeReader(gzipReader, b)
323+
d.storeLayerInCache(tr, dig)
324+
layerCh <- layer{ID: dig, Content: ioutil.NopCloser(b)}
334325

335-
layerCh <- layer{ID: dig, Content: ioutil.NopCloser(&cacheBuf)}
336326
return
337327
}
338328

@@ -352,48 +342,11 @@ func extractTarFromTarZstd(cacheContent []byte) ([]byte, error) {
352342
return tarContent, nil
353343
}
354344

355-
func getFilteredTarballBuffer(tr *tar.Reader, requiredFilenames []string) (bytes.Buffer, error) {
356-
var cacheBuf bytes.Buffer
357-
// Create a new tar to store in the cache
358-
twc := tar.NewWriter(&cacheBuf)
359-
defer twc.Close()
360-
361-
// check what files are inside the tar
362-
for {
363-
hdr, err := tr.Next()
364-
if err == io.EOF {
365-
break // end of archive
366-
}
367-
if err != nil {
368-
return cacheBuf, xerrors.Errorf("%s: invalid tar: %w", ErrFailedCacheWrite, err)
369-
}
370-
if !utils.StringInSlice(hdr.Name, requiredFilenames) {
371-
continue
372-
}
373-
374-
hdrtwc := &tar.Header{
375-
Name: hdr.Name,
376-
Mode: 0600,
377-
Size: hdr.Size,
378-
}
379-
380-
if err := twc.WriteHeader(hdrtwc); err != nil {
381-
return cacheBuf, xerrors.Errorf("%s: %s", ErrFailedCacheWrite, err)
382-
}
383-
384-
_, err = io.Copy(twc, tr)
385-
if err != nil {
386-
return cacheBuf, xerrors.Errorf("%s: %s", ErrFailedCacheWrite, err)
387-
}
388-
}
389-
return cacheBuf, nil
390-
}
391-
392-
func (d Extractor) storeLayerInCache(cacheBuf bytes.Buffer, dig digest.Digest) {
345+
func (d Extractor) storeLayerInCache(r io.Reader, dig digest.Digest) {
393346
// compress tar to zstd before storing to cache
394347
var dst bytes.Buffer
395348
w, _ := zstd.NewWriter(&dst, zstd.WithEncoderLevel(zstd.SpeedFastest))
396-
_, _ = io.Copy(w, &cacheBuf)
349+
_, _ = io.Copy(w, r)
397350
_ = w.Close()
398351

399352
if err := d.cache.Set(LayerTarsBucket, string(dig), dst.Bytes()); err != nil {

extractor/docker/docker_test.go

Lines changed: 0 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,7 @@ import (
1919
"github.com/aquasecurity/fanal/extractor"
2020
"github.com/aquasecurity/fanal/types"
2121
"github.com/docker/docker/client"
22-
"github.com/genuinetools/reg/registry"
23-
"github.com/opencontainers/go-digest"
2422
"github.com/stretchr/testify/assert"
25-
"github.com/stretchr/testify/require"
2623
)
2724

2825
// TODO: Use a memory based FS rather than actual fs
@@ -405,127 +402,6 @@ func TestDockerExtractor_Extract(t *testing.T) {
405402
}
406403
}
407404

408-
func TestDocker_ExtractLayerWorker(t *testing.T) {
409-
goodtarzstdgolden, _ := ioutil.ReadFile("testdata/testdir.tar.zstd")
410-
goodReturnedTarContent, _ := ioutil.ReadFile("testdata/goodTarContent.golden")
411-
412-
testCases := []struct {
413-
name string
414-
cacheHit bool
415-
garbageCache bool
416-
requiredFiles []string
417-
expectedCacheContents []byte
418-
expectedReturnedTarContent []byte
419-
}{
420-
{
421-
name: "happy path with cache miss and write back",
422-
cacheHit: false,
423-
requiredFiles: []string{"testdir/helloworld.txt", "testdir/badworld.txt"},
424-
expectedCacheContents: goodtarzstdgolden,
425-
expectedReturnedTarContent: goodReturnedTarContent,
426-
},
427-
{
428-
name: "happy path with cache hit with garbage cache and write back",
429-
cacheHit: true,
430-
garbageCache: true,
431-
requiredFiles: []string{"testdir/helloworld.txt", "testdir/badworld.txt"},
432-
expectedCacheContents: goodtarzstdgolden,
433-
expectedReturnedTarContent: goodReturnedTarContent,
434-
},
435-
{
436-
name: "happy path with cache hit",
437-
cacheHit: true,
438-
expectedCacheContents: goodtarzstdgolden,
439-
expectedReturnedTarContent: goodReturnedTarContent,
440-
},
441-
{
442-
name: "happy path with cache miss but no write back",
443-
cacheHit: false,
444-
expectedCacheContents: []byte{0x28, 0xb5, 0x2f, 0xfd, 0x4, 0x60, 0x1, 0x0, 0x0, 0x99, 0xe9, 0xd8, 0x51}, // just the empty tar header
445-
expectedReturnedTarContent: []byte{},
446-
},
447-
}
448-
449-
for _, tc := range testCases {
450-
inputDigest := digest.Digest("sha256:62d8908bee94c202b2d35224a221aaa2058318bfa9879fa541efaecba272331b")
451-
452-
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
453-
httpPath := r.URL.String()
454-
switch {
455-
case strings.Contains(httpPath, "/v2/library/fooimage/blobs/sha256:62d8908bee94c202b2d35224a221aaa2058318bfa9879fa541efaecba272331b"):
456-
layerData, _ := ioutil.ReadFile("testdata/testdir.tar.gz")
457-
_, _ = w.Write(layerData)
458-
default:
459-
assert.FailNow(t, "unexpected path accessed: ", fmt.Sprintf("%s %s", r.URL.String(), tc.name))
460-
}
461-
}))
462-
defer ts.Close()
463-
464-
c, err := client.NewClientWithOpts(client.WithHost(ts.URL))
465-
assert.NoError(t, err)
466-
467-
// setup cache
468-
s, tmpDir, err := setupCache()
469-
require.NoError(t, err, tc.name)
470-
defer os.RemoveAll(tmpDir)
471-
472-
if tc.cacheHit {
473-
switch tc.garbageCache {
474-
case true:
475-
garbage, _ := ioutil.ReadFile("testdata/invalidgzvalidtar.tar.gz")
476-
assert.NoError(t, s.Set(LayerTarsBucket, string(inputDigest), garbage))
477-
default:
478-
assert.NoError(t, s.Set(LayerTarsBucket, string(inputDigest), goodtarzstdgolden))
479-
}
480-
}
481-
482-
de := Extractor{
483-
Option: types.DockerOption{
484-
AuthURL: ts.URL,
485-
NonSSL: true,
486-
SkipPing: true,
487-
Timeout: time.Second * 1000,
488-
},
489-
Client: c,
490-
cache: s,
491-
}
492-
493-
tsUrl := strings.TrimPrefix(ts.URL, "http://")
494-
inputImage := registry.Image{
495-
Domain: tsUrl,
496-
Path: "library/fooimage",
497-
Tag: "latest",
498-
}
499-
500-
layerCh := make(chan layer)
501-
errCh := make(chan error)
502-
r, err := de.createRegistryClient(context.TODO(), inputImage.Domain)
503-
go func() {
504-
de.extractLayerWorker(inputDigest, r, context.TODO(), inputImage, errCh, layerCh, tc.requiredFiles)
505-
}()
506-
507-
var errRecieved error
508-
var layerReceived layer
509-
510-
select {
511-
case errRecieved = <-errCh:
512-
assert.FailNow(t, "unexpected error received, err: ", fmt.Sprintf("%s, %s", errRecieved, tc.name))
513-
case layerReceived = <-layerCh:
514-
assert.Equal(t, inputDigest, layerReceived.ID, tc.name)
515-
got, _ := ioutil.ReadAll(layerReceived.Content)
516-
assert.Equal(t, tc.expectedReturnedTarContent, got, tc.name)
517-
}
518-
519-
// check cache contents
520-
var actualCacheContents []byte
521-
found, err := s.Get(LayerTarsBucket, string(inputDigest), &actualCacheContents)
522-
523-
assert.True(t, found, tc.name)
524-
assert.NoError(t, err, tc.name)
525-
assert.Equal(t, tc.expectedCacheContents, actualCacheContents, tc.name)
526-
}
527-
}
528-
529405
func TestDocker_ExtractLayerFiles(t *testing.T) {
530406
de := Extractor{}
531407

-1.51 KB
Binary file not shown.
-204 Bytes
Binary file not shown.
-145 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)