Skip to content

Commit

Permalink
[8.12](backport #37727) package_test.go - Support OCI Image Layout (#…
Browse files Browse the repository at this point in the history
…37730)

* package_test.go - Support OCI Image Layout (#37727)

Modify TestDocker such that is can read both the original docker image layout and the OCI Image Layout.
This works by reading the config and layer file names from the manifest.yml instead of assuming their names.

Fixes #37726

(cherry picked from commit ebd8512)

* Replace slices.Contains usage with helper func

The 8.12 branch is not yet on Go 1.21 so the slices package isn't available.
  • Loading branch information
mergify[bot] authored Jan 25, 2024
1 parent 4e4f2d3 commit 6769cee
Showing 1 changed file with 62 additions and 15 deletions.
77 changes: 62 additions & 15 deletions dev-tools/packaging/package_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import (
"flag"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"regexp"
Expand Down Expand Up @@ -106,6 +105,7 @@ func TestZip(t *testing.T) {
func TestDocker(t *testing.T) {
dockers := getFiles(t, regexp.MustCompile(`\.docker\.tar\.gz$`))
for _, docker := range dockers {
t.Log(docker)
checkDocker(t, docker)
}
}
Expand Down Expand Up @@ -713,13 +713,19 @@ func readZip(t *testing.T, zipFile string, inspectors ...inspector) (*packageFil
}

func readDocker(dockerFile string) (*packageFile, *dockerInfo, error) {
// Read the manifest file first so that the config file and layer
// names are known in advance.
manifest, err := getDockerManifest(dockerFile)
if err != nil {
return nil, nil, err
}

file, err := os.Open(dockerFile)
if err != nil {
return nil, nil, err
}
defer file.Close()

var manifest *dockerManifest
var info *dockerInfo
layers := make(map[string]*packageFile)

Expand All @@ -740,22 +746,17 @@ func readDocker(dockerFile string) (*packageFile, *dockerInfo, error) {
}

switch {
case header.Name == "manifest.json":
manifest, err = readDockerManifest(tarReader)
if err != nil {
return nil, nil, err
}
case strings.HasSuffix(header.Name, ".json") && header.Name != "manifest.json":
case header.Name == manifest.Config:
info, err = readDockerInfo(tarReader)
if err != nil {
return nil, nil, err
}
case strings.HasSuffix(header.Name, "/layer.tar"):
case sliceContains(manifest.Layers, header.Name):
layer, err := readTarContents(header.Name, tarReader)
if err != nil {
return nil, nil, err
}
layers[filepath.Dir(header.Name)] = layer
layers[header.Name] = layer
}
}

Expand All @@ -769,10 +770,9 @@ func readDocker(dockerFile string) (*packageFile, *dockerInfo, error) {
// Read layers in order and for each file keep only the entry seen in the later layer
p := &packageFile{Name: filepath.Base(dockerFile), Contents: map[string]packageEntry{}}
for _, layer := range manifest.Layers {
layerID := filepath.Dir(layer)
layerFile, found := layers[layerID]
layerFile, found := layers[layer]
if !found {
return nil, nil, fmt.Errorf("layer not found: %s", layerID)
return nil, nil, fmt.Errorf("layer not found: %s", layer)
}
for name, entry := range layerFile.Contents {
// Check only files in working dir and entrypoint
Expand All @@ -798,14 +798,52 @@ func readDocker(dockerFile string) (*packageFile, *dockerInfo, error) {
return p, info, nil
}

// getDockerManifest opens a gzipped tar file to read the Docker manifest.json
// that it is expected to contain.
func getDockerManifest(file string) (*dockerManifest, error) {
f, err := os.Open(file)
if err != nil {
return nil, err
}
defer f.Close()

gzipReader, err := gzip.NewReader(f)
if err != nil {
return nil, err
}
defer gzipReader.Close()

var manifest *dockerManifest
tarReader := tar.NewReader(gzipReader)
for {
header, err := tarReader.Next()
if err != nil {
if errors.Is(err, io.EOF) {
break
}
return nil, err
}

if header.Name == "manifest.json" {
manifest, err = readDockerManifest(tarReader)
if err != nil {
return nil, err
}
break
}
}

return manifest, nil
}

type dockerManifest struct {
Config string
RepoTags []string
Layers []string
}

func readDockerManifest(r io.Reader) (*dockerManifest, error) {
data, err := ioutil.ReadAll(r)
data, err := io.ReadAll(r)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -833,7 +871,7 @@ type dockerInfo struct {
}

func readDockerInfo(r io.Reader) (*dockerInfo, error) {
data, err := ioutil.ReadAll(r)
data, err := io.ReadAll(r)
if err != nil {
return nil, err
}
Expand All @@ -846,3 +884,12 @@ func readDockerInfo(r io.Reader) (*dockerInfo, error) {

return &info, nil
}

func sliceContains(s []string, e string) bool {
for _, v := range s {
if e == v {
return true
}
}
return false
}

0 comments on commit 6769cee

Please sign in to comment.