1
0
mirror of synced 2026-02-06 19:05:55 +00:00

Add test for tag/list/build/pull/push artifacts

Signed-off-by: Somtochi Onyekwere <somtochionyekwere@gmail.com>
This commit is contained in:
Somtochi Onyekwere
2022-07-08 15:54:57 +01:00
committed by Stefan Prodan
parent 1b327e9d4e
commit 3e15e83926
8 changed files with 371 additions and 3 deletions

View File

@@ -0,0 +1,48 @@
/*
Copyright 2022 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package oci
import (
"os"
"path/filepath"
"testing"
. "github.com/onsi/gomega"
)
func TestBuild(t *testing.T) {
g := NewWithT(t)
testDir := "./testdata/build"
tmpDir := t.TempDir()
artifactPath := filepath.Join(tmpDir, "files.tar.gz")
// test with non-existent path
err := Build(artifactPath, "testdata/non-existent")
g.Expect(err).To(HaveOccurred())
err = Build(artifactPath, testDir)
g.Expect(err).ToNot(HaveOccurred())
if _, err := os.Stat(artifactPath); err != nil {
g.Expect(err).ToNot(HaveOccurred())
}
if err != nil {
t.Errorf("error working directory, %s", err)
}
}

53
internal/oci/list_test.go Normal file
View File

@@ -0,0 +1,53 @@
/*
Copyright 2022 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package oci
import (
"context"
"fmt"
"testing"
"github.com/google/go-containerregistry/pkg/crane"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/random"
. "github.com/onsi/gomega"
)
func Test_List(t *testing.T) {
g := NewWithT(t)
ctx := context.Background()
repo := "test-list" + randStringRunes(5)
tags := []string{"v0.0.1", "v0.0.2", "v0.0.3"}
for _, tag := range tags {
dst := fmt.Sprintf("%s/%s:%s", dockerReg, repo, tag)
img, err := random.Image(1024, 1)
g.Expect(err).ToNot(HaveOccurred())
err = crane.Push(img, dst, craneOptions(ctx)...)
g.Expect(err).ToNot(HaveOccurred())
}
metadata, err := List(ctx, fmt.Sprintf("%s/%s", dockerReg, repo))
g.Expect(err).ToNot(HaveOccurred())
g.Expect(len(metadata)).To(Equal(len(tags)))
for _, meta := range metadata {
tag, err := name.NewTag(meta.URL)
g.Expect(err).ToNot(HaveOccurred())
g.Expect(tag.TagStr()).Should(BeElementOf(tags))
}
}

View File

@@ -0,0 +1,64 @@
/*
Copyright 2022 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package oci
import (
"context"
"fmt"
"io/fs"
"os"
"path/filepath"
"testing"
"github.com/google/go-containerregistry/pkg/crane"
. "github.com/onsi/gomega"
)
func Test_Push_Pull(t *testing.T) {
g := NewWithT(t)
ctx := context.Background()
tag := "v0.0.1"
repo := "test-push" + randStringRunes(5)
url := fmt.Sprintf("%s/%s:%s", dockerReg, repo, tag)
metadata := Metadata{
Source: "github.com/fluxcd/fluxv2",
Revision: "rev",
}
testDir := "testdata/build"
_, err := Push(ctx, url, testDir, metadata)
g.Expect(err).ToNot(HaveOccurred())
tags, err := crane.ListTags(fmt.Sprintf("%s/%s", dockerReg, repo))
g.Expect(err).ToNot(HaveOccurred())
g.Expect(len(tags)).To(BeEquivalentTo(1))
tmpDir := t.TempDir()
_, err = Pull(ctx, url, tmpDir)
g.Expect(err).ToNot(HaveOccurred())
// Walk directory the test directory and check that each path exists in the extracted archive
err = filepath.Walk(testDir, func(path string, info fs.FileInfo, err error) error {
tmpPath := filepath.Join(tmpDir, path)
if _, err := os.Stat(tmpPath); err != nil && os.IsNotExist(err) {
return fmt.Errorf("path '%s' doesn't exist in archive", path)
}
return nil
})
}

115
internal/oci/suite_test.go Normal file
View File

@@ -0,0 +1,115 @@
/*
Copyright 2022 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package oci
import (
"context"
"fmt"
"io/ioutil"
"math/rand"
"os"
"path/filepath"
"testing"
"time"
ctrl "sigs.k8s.io/controller-runtime"
"github.com/distribution/distribution/v3/configuration"
"github.com/distribution/distribution/v3/registry"
_ "github.com/distribution/distribution/v3/registry/auth/htpasswd"
_ "github.com/distribution/distribution/v3/registry/storage/driver/inmemory"
"github.com/phayes/freeport"
"golang.org/x/crypto/bcrypt"
)
const (
testRegistryHtpasswdFileBasename = "authtest.htpasswd"
testRegistryUsername = "myuser"
testRegistryPassword = "mypass"
)
var (
dockerReg string
)
func init() {
rand.Seed(time.Now().UnixNano())
}
func setupRegistryServer(ctx context.Context) error {
// Create a temporary workspace directory for the registry
workspaceDir, err := os.MkdirTemp("", "registry-test-")
if err != nil {
return fmt.Errorf("failed to create workspace directory: %w", err)
}
// create htpasswd file (w BCrypt, which is required)
pwBytes, err := bcrypt.GenerateFromPassword([]byte(testRegistryPassword), bcrypt.DefaultCost)
if err != nil {
return fmt.Errorf("failed to generate password: %s", err)
}
htpasswdPath := filepath.Join(workspaceDir, testRegistryHtpasswdFileBasename)
err = ioutil.WriteFile(htpasswdPath, []byte(fmt.Sprintf("%s:%s\n", testRegistryUsername, string(pwBytes))), 0644)
if err != nil {
return fmt.Errorf("failed to create htpasswd file: %s", err)
}
// Registry config
config := &configuration.Configuration{}
port, err := freeport.GetFreePort()
if err != nil {
return fmt.Errorf("failed to get free port: %s", err)
}
dockerReg = fmt.Sprintf("localhost:%d", port)
config.HTTP.Addr = fmt.Sprintf("127.0.0.1:%d", port)
config.HTTP.DrainTimeout = time.Duration(10) * time.Second
config.Storage = map[string]configuration.Parameters{"inmemory": map[string]interface{}{}}
dockerRegistry, err := registry.NewRegistry(ctx, config)
if err != nil {
return fmt.Errorf("failed to create docker registry: %w", err)
}
// Start Docker registry
go dockerRegistry.ListenAndServe()
return nil
}
func TestMain(m *testing.M) {
ctx := ctrl.SetupSignalHandler()
err := setupRegistryServer(ctx)
if err != nil {
panic(fmt.Sprintf("failed to start docker registry: %s", err))
}
code := m.Run()
os.Exit(code)
}
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz1234567890")
func randStringRunes(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
return string(b)
}

46
internal/oci/tag_test.go Normal file
View File

@@ -0,0 +1,46 @@
/*
Copyright 2022 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package oci
import (
"context"
"fmt"
"testing"
"github.com/google/go-containerregistry/pkg/crane"
"github.com/google/go-containerregistry/pkg/v1/random"
. "github.com/onsi/gomega"
)
func Test_Tag(t *testing.T) {
g := NewWithT(t)
ctx := context.Background()
testRepo := "test-tag"
url := fmt.Sprintf("%s/%s:v0.0.1", dockerReg, testRepo)
img, err := random.Image(1024, 1)
g.Expect(err).ToNot(HaveOccurred())
err = crane.Push(img, url, craneOptions(ctx)...)
g.Expect(err).ToNot(HaveOccurred())
_, err = Tag(ctx, url, "v0.0.2")
g.Expect(err).ToNot(HaveOccurred())
tags, err := crane.ListTags(fmt.Sprintf("%s/%s", dockerReg, testRepo))
g.Expect(err).ToNot(HaveOccurred())
g.Expect(len(tags)).To(BeEquivalentTo(2))
g.Expect(tags).To(BeEquivalentTo([]string{"v0.0.1", "v0.0.2"}))
}

View File

View File