Skip to content
This repository was archived by the owner on Dec 2, 2020. It is now read-only.

Commit d3ed907

Browse files
committed
Write layer files out to zip files
1 parent aad6f8a commit d3ed907

File tree

2 files changed

+66
-11
lines changed

2 files changed

+66
-11
lines changed

main.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package main
33
import (
44
"context"
55
"fmt"
6-
"log"
76
"os"
87
"path/filepath"
98

@@ -60,7 +59,7 @@ func ConvertImage(name string) (retErr error) {
6059
// Unpack and inspect each image layer, copy relevant files to new Lambda layer
6160
dir, err := os.Getwd()
6261
if err != nil {
63-
log.Fatal(err)
62+
return err
6463
}
6564
layerOutputDir := filepath.Join(dir, "image-output", name)
6665
if err := os.MkdirAll(layerOutputDir, 0777); err != nil {

repack_layer.go

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,46 @@ import (
44
"archive/tar"
55
"fmt"
66
"io"
7-
"log"
7+
"os"
88
"strings"
99

1010
zglob "github.com/mattn/go-zglob"
1111
"github.com/mholt/archiver"
12+
"github.com/pkg/errors"
1213
)
1314

1415
// Converts container image layer archive (tar) to Lambda layer archive (zip).
1516
// Filters files from the source and only writes a new archive if at least
1617
// one file in the source matches the filter (i.e. does not create empty archives).
17-
func RepackLayer(outputFilename string, layerContents io.Reader, filterPattern string) (created bool, err error) {
18+
func RepackLayer(outputFilename string, layerContents io.Reader, filterPattern string) (created bool, retError error) {
1819
// TODO: support image types other than local Docker images (docker-daemon transport),
1920
// where the layer format is tar. For example, layers directly from a Docker registry
2021
// will be .tar.gz-formatted. OCI images can be either tar or tar.gz, based on the
2122
// layer's media type.
2223
t := archiver.NewTar()
2324

24-
err = t.Open(layerContents, 0)
25+
err := t.Open(layerContents, 0)
2526
if err != nil {
2627
return false, fmt.Errorf("opening layer tar: %v", err)
2728
}
2829
defer t.Close()
2930

3031
// Walk the files in the tar
32+
z := (*archiver.Zip)(nil)
33+
out := (*os.File)(nil)
34+
defer func() {
35+
if z != nil {
36+
if err := z.Close(); err != nil {
37+
retError = errors.Wrapf(err, " (zip close error: %v)", err)
38+
}
39+
}
40+
if out != nil {
41+
if err := out.Close(); err != nil {
42+
retError = errors.Wrapf(err, " (file close error: %v)", err)
43+
}
44+
}
45+
}()
46+
3147
for {
3248
// Get next file in tar
3349
f, err := t.Read()
@@ -45,15 +61,38 @@ func RepackLayer(outputFilename string, layerContents io.Reader, filterPattern s
4561
return false, fmt.Errorf("filtering file in layer tar: %v", err)
4662
}
4763
if repack {
48-
err = repackLayerFile(f)
64+
if z == nil {
65+
z, out, err = startZipFile(outputFilename)
66+
if err != nil {
67+
return false, fmt.Errorf("starting zip file: %v", err)
68+
}
69+
}
70+
71+
err = repackLayerFile(f, z)
4972
}
5073

5174
if err != nil {
5275
return false, fmt.Errorf("walking %s in layer tar: %v", f.Name(), err)
5376
}
5477
}
5578

56-
return false, nil
79+
return (z != nil), nil
80+
}
81+
82+
func startZipFile(destination string) (zip *archiver.Zip, zipFile *os.File, err error) {
83+
z := archiver.NewZip()
84+
85+
out, err := os.Create(destination)
86+
if err != nil {
87+
return nil, nil, fmt.Errorf("creating %s: %v", destination, err)
88+
}
89+
90+
err = z.Create(out)
91+
if err != nil {
92+
return nil, nil, fmt.Errorf("creating zip: %v", err)
93+
}
94+
95+
return z, out, nil
5796
}
5897

5998
func shouldRepackLayerFile(f archiver.File, matchPattern string) (should bool, err error) {
@@ -62,19 +101,36 @@ func shouldRepackLayerFile(f archiver.File, matchPattern string) (should bool, e
62101
return false, fmt.Errorf("expected header to be *tar.Header but was %T", f.Header)
63102
}
64103

65-
if f.IsDir() {
104+
if f.IsDir() || header.Typeflag == tar.TypeDir {
66105
return false, nil
67106
}
68107

108+
// Ignore whiteout files
69109
if strings.HasPrefix(f.Name(), ".wh.") {
70110
return false, nil
71111
}
72112

73113
return zglob.Match(matchPattern, header.Name)
74114
}
75115

76-
func repackLayerFile(f archiver.File) error {
77-
log.Printf(f.Header.(*tar.Header).Name)
116+
func repackLayerFile(f archiver.File, z *archiver.Zip) error {
117+
hdr, ok := f.Header.(*tar.Header)
118+
if !ok {
119+
return fmt.Errorf("expected header to be *tar.Header but was %T", f.Header)
120+
}
78121

79-
return nil
122+
switch hdr.Typeflag {
123+
case tar.TypeReg, tar.TypeRegA, tar.TypeChar, tar.TypeBlock, tar.TypeFifo, tar.TypeSymlink, tar.TypeLink:
124+
return z.Write(archiver.File{
125+
FileInfo: archiver.FileInfo{
126+
FileInfo: f.FileInfo,
127+
CustomName: hdr.Name,
128+
},
129+
ReadCloser: f,
130+
})
131+
case tar.TypeXGlobalHeader:
132+
return nil // ignore
133+
default:
134+
return fmt.Errorf("%s: unknown type flag: %c", hdr.Name, hdr.Typeflag)
135+
}
80136
}

0 commit comments

Comments
 (0)