mirror of https://github.com/knative/func.git
fix: OCI content creation by "host" builder on Win (#1871)
Signed-off-by: Matej Vasek <mvasek@redhat.com>
This commit is contained in:
parent
ba798408de
commit
a9e52815bc
|
@ -1,15 +1,22 @@
|
||||||
package oci
|
package oci
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"compress/gzip"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||||
fn "knative.dev/func/pkg/functions"
|
fn "knative.dev/func/pkg/functions"
|
||||||
. "knative.dev/func/pkg/testing"
|
. "knative.dev/func/pkg/testing"
|
||||||
|
@ -172,8 +179,82 @@ func validateOCI(path string, t *testing.T) {
|
||||||
t.Fatalf("invalid schema version, expected 2, got %d", imageIndex.SchemaVersion)
|
t.Fatalf("invalid schema version, expected 2, got %d", imageIndex.SchemaVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Additional validation of the Image Index structure can be added here
|
if len(imageIndex.Manifests) < 1 {
|
||||||
// extract. for example checking that the path includes the README.md
|
t.Fatal("fewer manifests")
|
||||||
// and one of the binaries in the exact location expected (the data layer
|
}
|
||||||
// blob and exec layer blob, respectively)
|
|
||||||
|
digest := strings.TrimPrefix(imageIndex.Manifests[0].Digest, "sha256:")
|
||||||
|
manifestFile := filepath.Join(path, "blobs", "sha256", digest)
|
||||||
|
manifestFileData, err := os.ReadFile(manifestFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
mf := struct {
|
||||||
|
Layers []struct {
|
||||||
|
Digest string `json:"digest"`
|
||||||
|
} `json:"layers"`
|
||||||
|
}{}
|
||||||
|
err = json.Unmarshal(manifestFileData, &mf)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type fileInfo struct {
|
||||||
|
Path string
|
||||||
|
Type fs.FileMode
|
||||||
|
Executable bool
|
||||||
|
}
|
||||||
|
var files []fileInfo
|
||||||
|
|
||||||
|
for _, layer := range mf.Layers {
|
||||||
|
func() {
|
||||||
|
digest = strings.TrimPrefix(layer.Digest, "sha256:")
|
||||||
|
f, err := os.Open(filepath.Join(path, "blobs", "sha256", digest))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
gr, err := gzip.NewReader(f)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer gr.Close()
|
||||||
|
|
||||||
|
tr := tar.NewReader(gr)
|
||||||
|
for {
|
||||||
|
hdr, err := tr.Next()
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, io.EOF) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
files = append(files, fileInfo{
|
||||||
|
Path: hdr.Name,
|
||||||
|
Type: hdr.FileInfo().Mode() & fs.ModeType,
|
||||||
|
Executable: (hdr.FileInfo().Mode()&0111 == 0111) && !hdr.FileInfo().IsDir(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
sort.Slice(files, func(i, j int) bool {
|
||||||
|
return files[i].Path < files[j].Path
|
||||||
|
})
|
||||||
|
|
||||||
|
expectedFiles := []fileInfo{
|
||||||
|
{Path: "/etc/pki/tls/certs/ca-certificates.crt"},
|
||||||
|
{Path: "/etc/ssl/certs/ca-certificates.crt"},
|
||||||
|
{Path: "/func", Type: fs.ModeDir},
|
||||||
|
{Path: "/func/README.md"},
|
||||||
|
{Path: "/func/f", Executable: true},
|
||||||
|
{Path: "/func/func.yaml"},
|
||||||
|
{Path: "/func/go.mod"},
|
||||||
|
{Path: "/func/handle.go"},
|
||||||
|
{Path: "/func/handle_test.go"},
|
||||||
|
}
|
||||||
|
|
||||||
|
if diff := cmp.Diff(expectedFiles, files); diff != "" {
|
||||||
|
t.Error("files in oci differ from expectation (-want, +got):", diff)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
slashpath "path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -159,7 +160,7 @@ func newDataTarball(source, target string, ignored []string, verbose bool) error
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
header.Name = filepath.Join("/func", relPath)
|
header.Name = slashpath.Join("/func", filepath.ToSlash(relPath))
|
||||||
// TODO: should we set file timestamps to the build start time of cfg.t?
|
// TODO: should we set file timestamps to the build start time of cfg.t?
|
||||||
// header.ModTime = timestampArgument
|
// header.ModTime = timestampArgument
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,10 @@ import (
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
slashpath "path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -169,8 +171,9 @@ func newExecTarball(source, target string, verbose bool) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
header.Mode = (header.Mode & ^int64(fs.ModePerm)) | 0755
|
||||||
|
|
||||||
header.Name = path("/func", "f")
|
header.Name = slashpath.Join("/func", "f")
|
||||||
// TODO: should we set file timestamps to the build start time of cfg.t?
|
// TODO: should we set file timestamps to the build start time of cfg.t?
|
||||||
// header.ModTime = timestampArgument
|
// header.ModTime = timestampArgument
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue