Skip to content

Commit

Permalink
Port Sideload tests; all tests pass
Browse files Browse the repository at this point in the history
  • Loading branch information
tomasaschan committed May 6, 2024
1 parent b3a4f85 commit a99e5c3
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 50 deletions.
5 changes: 4 additions & 1 deletion pkg/envtest/setup/env/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,11 @@ func WithStore(store *store.Store) Option {
func WithClient(client *remote.Client) Option { return func(c *Env) { c.Client = client } }

// WithFS allows injecting a configured fs.FS, e.g. for mocking.
// TODO: fix this so it's actually used!
func WithFS(fs fs.FS) Option {
return func(c *Env) { c.FS = fs }
return func(c *Env) {
c.FS = fs
}
}

// New returns a new environment, configured with the provided options.
Expand Down
3 changes: 2 additions & 1 deletion pkg/envtest/setup/list/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ var _ = Describe("List", func() {
)

JustBeforeEach(func() {
addr, shutdown := testhelpers.NewServer()
addr, shutdown, err := testhelpers.NewServer()
Expect(err).NotTo(HaveOccurred())
DeferCleanup(shutdown)

envOpts = append(
Expand Down
76 changes: 76 additions & 0 deletions pkg/envtest/setup/sideload/sideload_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package sideload_test

import (
"bytes"
"context"
"io"
"path/filepath"
"runtime"
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"github.com/go-logr/logr"
"sigs.k8s.io/controller-runtime/pkg/envtest/setup/env"
"sigs.k8s.io/controller-runtime/pkg/envtest/setup/sideload"
"sigs.k8s.io/controller-runtime/pkg/envtest/setup/testhelpers"
"sigs.k8s.io/controller-runtime/pkg/envtest/setup/versions"
)

var (
testLog logr.Logger
ctx context.Context
)

func TestEnv(t *testing.T) {
testLog = testhelpers.GetLogger()
ctx = logr.NewContext(context.Background(), testLog)

RegisterFailHandler(Fail)
RunSpecs(t, "Sideload Suite")
}

var _ = Describe("Sideload", func() {
var (
prefix = "a-test-package"
input io.Reader
)
BeforeEach(func() {
contents, err := testhelpers.ContentsFor(prefix)
Expect(err).NotTo(HaveOccurred())

input = bytes.NewReader(contents)
})

It("should fail if a non-concrete version is given", func() {
err := sideload.Sideload(ctx, versions.LatestVersion)
Expect(err).To(HaveOccurred())
})

It("should fail if a non-concrete platform is given", func() {
err := sideload.Sideload(ctx, versions.Spec{Selector: &versions.Concrete{Major: 1, Minor: 2, Patch: 3}}, sideload.WithPlatform("*", "*"))
Expect(err).To(HaveOccurred())
})

It("should load the given tarball into our store as the given version", func() {
v := &versions.Concrete{Major: 1, Minor: 2, Patch: 3}
store := testhelpers.NewMockStore()
Expect(sideload.Sideload(
ctx,
versions.Spec{Selector: v},
sideload.WithInput(input),
sideload.WithEnvOptions(env.WithStore(store)),
)).To(Succeed())

baseName := versions.Platform{OS: runtime.GOOS, Arch: runtime.GOARCH}.BaseName(*v)
expectedPath := filepath.Join("k8s", baseName, prefix)

outFile, err := store.Root.Open(expectedPath)
Expect(err).NotTo(HaveOccurred())
DeferCleanup(outFile.Close)
contents, err := io.ReadAll(outFile)
Expect(err).NotTo(HaveOccurred())
Expect(contents).To(HavePrefix(prefix))
})
})
2 changes: 1 addition & 1 deletion pkg/envtest/setup/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ func (s *Store) Add(ctx context.Context, item Item, contents io.Reader) (resErr
return err
}
}
if err != nil && !errors.Is(err, io.EOF) { //nolint:govet
if !errors.Is(err, io.EOF) {
return fmt.Errorf("unable to finish un-tar-ing the downloaded archive: %w", err)
}
log.V(1).Info("unpacked archive")
Expand Down
52 changes: 52 additions & 0 deletions pkg/envtest/setup/testhelpers/package.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package testhelpers

import (
"archive/tar"
"bytes"
"compress/gzip"
"crypto/md5" //nolint:gosec
"crypto/rand"
"encoding/base64"
"fmt"
"path/filepath"
)

func ContentsFor(filename string) ([]byte, error) { //nolint:revive
var chunk [1024 * 48]byte // 1.5 times our chunk read size in GetVersion
copy(chunk[:], filename)
if _, err := rand.Read(chunk[len(filename):]); err != nil {
return nil, err
}

out := new(bytes.Buffer)
gzipWriter := gzip.NewWriter(out)

tarWriter := tar.NewWriter(gzipWriter)

if err := tarWriter.WriteHeader(&tar.Header{
Name: filepath.Join("kubebuilder/bin", filename),
Size: int64(len(chunk)),
Mode: 0777, // so we can check that we fix this later
}); err != nil {
return nil, fmt.Errorf("write tar header: %w", err)
}
if _, err := tarWriter.Write(chunk[:]); err != nil {
return nil, fmt.Errorf("write tar contents: %w", err)
}

// can't defer these, because they need to happen before out.Bytes() below
tarWriter.Close()
gzipWriter.Close()

return out.Bytes(), nil
}

func verWith(name string, contents []byte) item {
res := item{
meta: bucketObject{Name: name},
contents: contents,
}
hash := md5.Sum(res.contents) //nolint:gosec
res.meta.Hash = base64.StdEncoding.EncodeToString(hash[:])
return res
}
71 changes: 24 additions & 47 deletions pkg/envtest/setup/testhelpers/remote.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
package testhelpers

import (
"archive/tar"
"bytes"
"compress/gzip"
"crypto/md5" //nolint:gosec
"crypto/rand"
"encoding/base64"
"errors"
"net/http"

"github.com/onsi/gomega"
Expand Down Expand Up @@ -73,57 +68,47 @@ var (
contents map[string]item
)

func makeContents(names []string) []item {
func makeContents(names []string) ([]item, error) {
res := make([]item, len(names))
if contents == nil {
contents = make(map[string]item, len(RemoteNames))
}

var errs error
for i, name := range names {
if item, ok := contents[name]; ok {
res[i] = item
continue
}

var chunk [1024 * 48]byte // 1.5 times our chunk read size in GetVersion
copy(chunk[:], name)
if _, err := rand.Read(chunk[len(name):]); err != nil {
panic(err)
chunk, err := ContentsFor(name)
if err != nil {
errs = errors.Join(errs, err)
continue
}
item := verWith(name, chunk[:])

item := verWith(name, chunk)
contents[name] = item
res[i] = item
}
return res
}
func verWith(name string, contents []byte) item {
out := new(bytes.Buffer)
gzipWriter := gzip.NewWriter(out)
tarWriter := tar.NewWriter(gzipWriter)
err := tarWriter.WriteHeader(&tar.Header{
Name: "kubebuilder/bin/some-file",
Size: int64(len(contents)),
Mode: 0777, // so we can check that we fix this later
})
if err != nil {
panic(err)

if errs != nil {
return nil, errs
}
_, err = tarWriter.Write(contents)

return res, nil
}

// NewServer spins up a mock server that knows about the provided packages.
// The package names should be a subset of RemoteNames.
//
// The returned shutdown function should be called at the end of the test
func NewServer() (addr string, shutdown func(), err error) {
versions, err := makeContents(RemoteNames)
if err != nil {
panic(err)
}
tarWriter.Close()
gzipWriter.Close()
res := item{
meta: bucketObject{Name: name},
contents: out.Bytes(),
return
}
hash := md5.Sum(res.contents) //nolint:gosec
res.meta.Hash = base64.StdEncoding.EncodeToString(hash[:])
return res
}

func configure(versions []item) (string, func()) {
server := ghttp.NewServer()

list := objectList{Items: make([]bucketObject, len(versions))}
Expand All @@ -147,13 +132,5 @@ func configure(versions []item) (string, func()) {
list,
))

return server.Addr(), server.Close
}

// NewServer spins up a mock server that knows about the provided packages.
// The package names should be a subset of RemoteNames.
//
// The returned shutdown function should be called at the end of the test
func NewServer() (addr string, shutdown func()) {
return configure(makeContents(RemoteNames))
return server.Addr(), server.Close, nil
}

0 comments on commit a99e5c3

Please sign in to comment.