Skip to content

Commit cff0e18

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

File tree

3 files changed

+119
-264
lines changed

3 files changed

+119
-264
lines changed

pkg/image/registry_test.go

Lines changed: 90 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,60 @@ 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+
require.NoError(t, caFile.Close())
51+
return caDir
52+
}
53+
54+
func poolForCert(serverCert *x509.Certificate) *x509.CertPool {
55+
rootCAs := x509.NewCertPool()
56+
rootCAs.AddCert(serverCert)
4257
return rootCAs
4358
}
4459

4560
func TestRegistries(t *testing.T) {
4661
registries := map[string]newRegistryFunc{
47-
"containerd": func(t *testing.T, cafile string) (image.Registry, cleanupFunc) {
62+
"containersimage": func(t *testing.T, serverCert *x509.Certificate) (image.Registry, cleanupFunc) {
63+
caDir := caDirForCert(t, serverCert)
64+
sourceCtx := &types.SystemContext{
65+
OCICertPath: caDir,
66+
DockerCertPath: caDir,
67+
DockerPerHostCertDirPath: caDir,
68+
}
69+
r, err := containersimageregistry.New(sourceCtx, containersimageregistry.ForceTemporaryImageCache())
70+
require.NoError(t, err)
71+
cleanup := func() {
72+
require.NoError(t, os.RemoveAll(caDir))
73+
require.NoError(t, r.Destroy())
74+
}
75+
return r, cleanup
76+
},
77+
"containerd": func(t *testing.T, serverCert *x509.Certificate) (image.Registry, cleanupFunc) {
4878
val, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64))
4979
require.NoError(t, err)
5080
r, err := containerdregistry.NewRegistry(
5181
containerdregistry.WithLog(logrus.New().WithField("test", t.Name())),
5282
containerdregistry.WithCacheDir(fmt.Sprintf("cache-%x", val)),
53-
containerdregistry.WithRootCAs(poolForCertFile(t, cafile)),
83+
containerdregistry.WithRootCAs(poolForCert(serverCert)),
5484
)
5585
require.NoError(t, err)
5686
cleanup := func() {
@@ -59,37 +89,25 @@ func TestRegistries(t *testing.T) {
5989

6090
return r, cleanup
6191
},
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-
// },
8692
}
8793

8894
for name, registry := range registries {
8995
testPullAndUnpack(t, name, registry)
9096
}
9197
}
9298

99+
type httpError struct {
100+
statusCode int
101+
error error
102+
}
103+
104+
func (e *httpError) Error() string {
105+
if e.error != nil {
106+
return e.error.Error()
107+
}
108+
return http.StatusText(e.statusCode)
109+
}
110+
93111
func testPullAndUnpack(t *testing.T, name string, newRegistry newRegistryFunc) {
94112
type args struct {
95113
dockerRootDir string
@@ -134,7 +152,7 @@ func testPullAndUnpack(t *testing.T, name string, newRegistry newRegistryFunc) {
134152
dockerRootDir: "testdata/golden",
135153
img: "/olmtest/kiali:1.4.2",
136154
pullErrCount: 1,
137-
pullErr: errors.New("dummy"),
155+
pullErr: &httpError{statusCode: http.StatusTooManyRequests},
138156
},
139157
expected: expected{
140158
checksum: dirChecksum(t, "testdata/golden/bundles/kiali"),
@@ -158,10 +176,12 @@ func testPullAndUnpack(t *testing.T, name string, newRegistry newRegistryFunc) {
158176
dockerRootDir: "testdata/golden",
159177
img: "/olmtest/kiali:1.4.2",
160178
pullErrCount: math.MaxInt64,
161-
pullErr: errors.New("dummy"),
179+
pullErr: &httpError{statusCode: http.StatusTooManyRequests},
162180
},
163181
expected: expected{
164-
pullAssertion: require.Error,
182+
pullAssertion: func(t require.TestingT, err error, i ...interface{}) {
183+
require.Error(t, err)
184+
},
165185
},
166186
},
167187
}
@@ -171,36 +191,24 @@ func testPullAndUnpack(t *testing.T, name string, newRegistry newRegistryFunc) {
171191
ctx, close := context.WithCancel(context.Background())
172192
defer close()
173193

174-
configOpts := []libimage.ConfigOpt{}
175-
194+
var middlewares []func(next http.Handler) http.Handler
176195
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-
})
196+
middlewares = append(middlewares, failureMiddleware(tt.args.pullErrCount, tt.args.pullErr))
195197
}
196198

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

200-
r, cleanup := newRegistry(t, cafile)
204+
r, cleanup := newRegistry(t, dockerServer.Certificate())
201205
defer cleanup()
202206

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

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

0 commit comments

Comments
 (0)