Skip to content

Commit 81e4712

Browse files
committed
add containersimageregistry to standard registry test suite
Signed-off-by: Joe Lanford <[email protected]>
1 parent ca6094a commit 81e4712

File tree

2 files changed

+97
-252
lines changed

2 files changed

+97
-252
lines changed

pkg/image/registry_test.go

Lines changed: 89 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,21 @@ import (
44
"context"
55
"crypto/rand"
66
"crypto/x509"
7+
"encoding/pem"
78
"errors"
89
"fmt"
910
"io"
1011
"math"
1112
"math/big"
1213
"net/http"
14+
"net/url"
1315
"os"
16+
"path/filepath"
1417
"sync"
1518
"testing"
1619

17-
distribution "github.com/distribution/distribution/v3"
18-
"github.com/distribution/distribution/v3/configuration"
19-
repositorymiddleware "github.com/distribution/distribution/v3/registry/middleware/repository"
20+
"github.com/containers/image/v5/types"
21+
"github.com/distribution/distribution/v3"
2022
"github.com/distribution/reference"
2123
"github.com/opencontainers/go-digest"
2224
"github.com/sirupsen/logrus"
@@ -25,32 +27,59 @@ import (
2527

2628
"github.com/operator-framework/operator-registry/pkg/image"
2729
"github.com/operator-framework/operator-registry/pkg/image/containerdregistry"
30+
"github.com/operator-framework/operator-registry/pkg/image/containersimageregistry"
2831
libimage "github.com/operator-framework/operator-registry/pkg/lib/image"
2932
)
3033

3134
// cleanupFunc is a function that cleans up after some test infra.
3235
type cleanupFunc func()
3336

3437
// newRegistryFunc is a function that creates and returns a new image.Registry to test its cleanupFunc.
35-
type newRegistryFunc func(t *testing.T, cafile string) (image.Registry, cleanupFunc)
38+
type newRegistryFunc func(t *testing.T, serverCert *x509.Certificate) (image.Registry, cleanupFunc)
3639

37-
func poolForCertFile(t *testing.T, file string) *x509.CertPool {
38-
rootCAs := x509.NewCertPool()
39-
certs, err := os.ReadFile(file)
40+
func caDirForCert(t *testing.T, serverCert *x509.Certificate) string {
41+
caDir, err := os.MkdirTemp("", "opm-registry-test-ca-")
42+
require.NoError(t, err)
43+
caFile, err := os.Create(filepath.Join(caDir, "ca.crt"))
4044
require.NoError(t, err)
41-
require.True(t, rootCAs.AppendCertsFromPEM(certs))
45+
46+
require.NoError(t, pem.Encode(caFile, &pem.Block{
47+
Type: "CERTIFICATE",
48+
Bytes: serverCert.Raw,
49+
}))
50+
return caDir
51+
}
52+
53+
func poolForCert(serverCert *x509.Certificate) *x509.CertPool {
54+
rootCAs := x509.NewCertPool()
55+
rootCAs.AddCert(serverCert)
4256
return rootCAs
4357
}
4458

4559
func TestRegistries(t *testing.T) {
4660
registries := map[string]newRegistryFunc{
47-
"containerd": func(t *testing.T, cafile string) (image.Registry, cleanupFunc) {
61+
"containersimage": func(t *testing.T, serverCert *x509.Certificate) (image.Registry, cleanupFunc) {
62+
caDir := caDirForCert(t, serverCert)
63+
sourceCtx := &types.SystemContext{
64+
OCICertPath: caDir,
65+
DockerCertPath: caDir,
66+
DockerPerHostCertDirPath: caDir,
67+
}
68+
r, err := containersimageregistry.New(sourceCtx, containersimageregistry.ForceTemporaryImageCache())
69+
require.NoError(t, err)
70+
cleanup := func() {
71+
require.NoError(t, os.RemoveAll(caDir))
72+
require.NoError(t, r.Destroy())
73+
}
74+
return r, cleanup
75+
},
76+
"containerd": func(t *testing.T, serverCert *x509.Certificate) (image.Registry, cleanupFunc) {
4877
val, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64))
4978
require.NoError(t, err)
5079
r, err := containerdregistry.NewRegistry(
5180
containerdregistry.WithLog(logrus.New().WithField("test", t.Name())),
5281
containerdregistry.WithCacheDir(fmt.Sprintf("cache-%x", val)),
53-
containerdregistry.WithRootCAs(poolForCertFile(t, cafile)),
82+
containerdregistry.WithRootCAs(poolForCert(serverCert)),
5483
)
5584
require.NoError(t, err)
5685
cleanup := func() {
@@ -59,37 +88,25 @@ func TestRegistries(t *testing.T) {
5988

6089
return r, cleanup
6190
},
62-
// TODO: enable docker tests - currently blocked on a cross-platform way to configure either insecure registries
63-
// or CA certs
64-
//"docker": func(t *testing.T, cafile string) (image.Registry, cleanupFunc) {
65-
// r, err := execregistry.NewRegistry(containertools.DockerTool,
66-
// logrus.New().WithField("test", t.Name()),
67-
// cafile,
68-
// )
69-
// require.NoError(t, err)
70-
// cleanup := func() {
71-
// require.NoError(t, r.Destroy())
72-
// }
73-
//
74-
// return r, cleanup
75-
//},
76-
// TODO: Enable buildah tests
77-
// func(t *testing.T) image.Registry {
78-
// r, err := buildahregistry.NewRegistry(
79-
// buildahregistry.WithLog(logrus.New().WithField("test", t.Name())),
80-
// buildahregistry.WithCacheDir(fmt.Sprintf("cache-%x", rand.Int())),
81-
// )
82-
// require.NoError(t, err)
83-
84-
// return r
85-
// },
8691
}
8792

8893
for name, registry := range registries {
8994
testPullAndUnpack(t, name, registry)
9095
}
9196
}
9297

98+
type httpError struct {
99+
statusCode int
100+
error error
101+
}
102+
103+
func (e *httpError) Error() string {
104+
if e.error != nil {
105+
return e.error.Error()
106+
}
107+
return http.StatusText(e.statusCode)
108+
}
109+
93110
func testPullAndUnpack(t *testing.T, name string, newRegistry newRegistryFunc) {
94111
type args struct {
95112
dockerRootDir string
@@ -134,7 +151,7 @@ func testPullAndUnpack(t *testing.T, name string, newRegistry newRegistryFunc) {
134151
dockerRootDir: "testdata/golden",
135152
img: "/olmtest/kiali:1.4.2",
136153
pullErrCount: 1,
137-
pullErr: errors.New("dummy"),
154+
pullErr: &httpError{statusCode: http.StatusTooManyRequests},
138155
},
139156
expected: expected{
140157
checksum: dirChecksum(t, "testdata/golden/bundles/kiali"),
@@ -158,10 +175,12 @@ func testPullAndUnpack(t *testing.T, name string, newRegistry newRegistryFunc) {
158175
dockerRootDir: "testdata/golden",
159176
img: "/olmtest/kiali:1.4.2",
160177
pullErrCount: math.MaxInt64,
161-
pullErr: errors.New("dummy"),
178+
pullErr: &httpError{statusCode: http.StatusTooManyRequests},
162179
},
163180
expected: expected{
164-
pullAssertion: require.Error,
181+
pullAssertion: func(t require.TestingT, err error, i ...interface{}) {
182+
require.Error(t, err)
183+
},
165184
},
166185
},
167186
}
@@ -171,36 +190,24 @@ func testPullAndUnpack(t *testing.T, name string, newRegistry newRegistryFunc) {
171190
ctx, close := context.WithCancel(context.Background())
172191
defer close()
173192

174-
configOpts := []libimage.ConfigOpt{}
175-
193+
var middlewares []func(next http.Handler) http.Handler
176194
if tt.args.pullErrCount > 0 {
177-
configOpts = append(configOpts, func(config *configuration.Configuration) {
178-
if config.Middleware == nil {
179-
config.Middleware = make(map[string][]configuration.Middleware)
180-
}
181-
182-
mockRepo := &mockRepo{blobStore: &mockBlobStore{
183-
maxCount: tt.args.pullErrCount,
184-
err: tt.args.pullErr,
185-
}}
186-
val, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64))
187-
require.NoError(t, err)
188-
189-
middlewareName := fmt.Sprintf("test-%x", val)
190-
require.NoError(t, repositorymiddleware.Register(middlewareName, mockRepo.init))
191-
config.Middleware["repository"] = append(config.Middleware["repository"], configuration.Middleware{
192-
Name: middlewareName,
193-
})
194-
})
195+
middlewares = append(middlewares, failureMiddleware(tt.args.pullErrCount, tt.args.pullErr))
195196
}
196197

197-
host, cafile, err := libimage.RunDockerRegistry(ctx, tt.args.dockerRootDir, configOpts...)
198-
require.NoError(t, err)
198+
t.Log("starting docker registry")
199+
dockerServer := libimage.RunDockerRegistry(ctx, tt.args.dockerRootDir, middlewares...)
200+
defer dockerServer.Close()
201+
t.Log("started docker registry")
199202

200-
r, cleanup := newRegistry(t, cafile)
203+
r, cleanup := newRegistry(t, dockerServer.Certificate())
201204
defer cleanup()
202205

203-
ref := image.SimpleReference(host + tt.args.img)
206+
url, err := url.Parse(dockerServer.URL)
207+
require.NoError(t, err)
208+
209+
ref := image.SimpleReference(fmt.Sprintf("%s%s", url.Host, tt.args.img))
210+
t.Log("pulling image", ref)
204211
tt.expected.pullAssertion(t, r.Pull(ctx, ref))
205212

206213
if tt.expected.checksum != "" {
@@ -303,3 +310,24 @@ func (f *mockBlobStore) ServeBlob(ctx context.Context, w http.ResponseWriter, r
303310
func (f *mockBlobStore) Delete(ctx context.Context, dgst digest.Digest) error {
304311
return f.base.Delete(ctx, dgst)
305312
}
313+
314+
func failureMiddleware(totalCount int, err error) func(next http.Handler) http.Handler {
315+
return func(next http.Handler) http.Handler {
316+
count := 0
317+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
318+
if count >= totalCount {
319+
next.ServeHTTP(w, r)
320+
return
321+
}
322+
count++
323+
statusCode := http.StatusInternalServerError
324+
325+
var httpErr *httpError
326+
if errors.As(err, &httpErr) {
327+
statusCode = httpErr.statusCode
328+
}
329+
330+
http.Error(w, err.Error(), statusCode)
331+
})
332+
}
333+
}

0 commit comments

Comments
 (0)