wip layers
This commit is contained in:
parent
273c337a23
commit
4d6476cca9
86
rootfs.go
86
rootfs.go
|
@ -1,7 +1,13 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
goflags "github.com/jessevdk/go-flags"
|
||||
)
|
||||
|
@ -13,9 +19,87 @@ type cmdRootFS struct {
|
|||
} `positional-args:"yes" required:"yes"`
|
||||
}
|
||||
|
||||
const (
|
||||
_manifestJSON = "manifest.json"
|
||||
)
|
||||
|
||||
func (r *cmdRootFS) Execute(args []string) error {
|
||||
if len(args) != 0 {
|
||||
return errors.New("too many args")
|
||||
}
|
||||
return nil
|
||||
|
||||
in, err := os.Open(string(r.PositionalArgs.Infile))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer in.Close()
|
||||
|
||||
out, err := os.Create(string(r.PositionalArgs.Outfile))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
return r.rootfs(in, out)
|
||||
}
|
||||
|
||||
type dockerManifestJSON []struct {
|
||||
Config string `json:"Config"`
|
||||
Layers []string `json:"Layers"`
|
||||
}
|
||||
|
||||
// rootfs accepts a docker layer tarball and writes it to outfile.
|
||||
// 1. create map[string]io.ReadSeeker for each layer.
|
||||
// 2. parse manifest.json and get the layer order.
|
||||
// 3. go through each layer in order and write:
|
||||
// a) to an ordered slice: the file name.
|
||||
// b) to an FS map: where does the file come from?
|
||||
// I) layer name
|
||||
// II) offset (0 being the first file in the layer)
|
||||
// 4. go through
|
||||
func (r *cmdRootFS) rootfs(in io.ReadSeeker, out io.Writer) error {
|
||||
tr := tar.NewReader(in)
|
||||
layerOffsets := map[string]int64{}
|
||||
var manifest dockerManifestJSON
|
||||
|
||||
// phase 1: get layer offsets and manifest.json
|
||||
for {
|
||||
hdrIn, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
|
||||
if hdrIn.Typeflag != tar.TypeReg {
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case hdrIn.Name == _manifestJSON:
|
||||
dec := json.NewDecoder(tr)
|
||||
if err := dec.Decode(&manifest); err != nil {
|
||||
return fmt.Errorf("decode manifest.json: %w", err)
|
||||
}
|
||||
case strings.HasSuffix(hdrIn.Name, "/layer.tar"):
|
||||
here, err := in.Seek(0, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return fmt.Errorf("seek: %w", err)
|
||||
}
|
||||
layers[hdrIn.Name] = here
|
||||
}
|
||||
}
|
||||
|
||||
// phase 1.5: enumerate layers
|
||||
layers := make([]int64, len(layers))
|
||||
for i, name := range manifest.Layers {
|
||||
layers[i] = layerOffsets[name]
|
||||
}
|
||||
|
||||
// phase 2: iterate through all layers and extract filenames
|
||||
// to files and ordered
|
||||
files := map[string]struct{
|
||||
layer string
|
||||
|
||||
fmt.Printf("layers: %+v\n", layers)
|
||||
|
||||
return nil
|
||||
//return tw.Close()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue