pkg/testutil/bldr/oci_registry_server.go (105 lines of code) (raw):
package bldr
import (
"context"
"fmt"
"testing"
"time"
"github.com/distribution/distribution/v3/configuration"
"github.com/distribution/distribution/v3/registry"
"github.com/distribution/distribution/v3/registry/auth"
_ "github.com/distribution/distribution/v3/registry/storage/driver/inmemory"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/stretchr/testify/require"
)
type OCIRegistryServerOptions struct {
port string
requireAuth bool
user string
password string
}
func StartOCIRegistryServer(t *testing.T, options ...func(*OCIRegistryServerOptions)) *OCIRegistryServer {
port := TCPPort(t).FindFree()
opts := &OCIRegistryServerOptions{
requireAuth: false,
port: port,
}
for _, option := range options {
option(opts)
}
ociRegistry := NewOCIRegistryServer(t, opts)
ociRegistry.Serve(context.Background())
t.Cleanup(ociRegistry.Stop)
return ociRegistry
}
func WithRequireAuth(user, password string) func(*OCIRegistryServerOptions) {
return func(opts *OCIRegistryServerOptions) {
opts.requireAuth = true
opts.user = user
opts.password = password
}
}
type OCIRegistryServer struct {
server *registry.Registry
cancelFn context.CancelFunc
opts *OCIRegistryServerOptions
t *testing.T
}
func NewOCIRegistryServer(t *testing.T, opts *OCIRegistryServerOptions) *OCIRegistryServer {
return &OCIRegistryServer{
t: t,
opts: opts,
}
}
func (s *OCIRegistryServer) Serve(ctx context.Context) {
ctx, cancelFn := context.WithCancel(ctx)
s.cancelFn = cancelFn
config := &configuration.Configuration{}
config.Storage = configuration.Storage{}
config.Storage["inmemory"] = configuration.Parameters{}
config.Storage["maintenance"] = configuration.Parameters{"uploadpurging": map[any]any{"enabled": false}}
config.Log.Level = "debug"
config.Log.Formatter = "text"
config.HTTP.Secret = "secrety-secret"
config.HTTP.Addr = fmt.Sprintf(":%s", s.opts.port)
if s.opts.requireAuth {
err := auth.Register("basicauth", NewOCIBasicAuthAccess)
require.NoError(s.t, err)
config.Auth = configuration.Auth{"basicauth": configuration.Parameters{"username": s.opts.user, "password": s.opts.password}}
}
var err error
s.server, err = registry.NewRegistry(ctx, config)
require.NoError(s.t, err)
var errchan chan error
go func() {
errchan <- s.server.ListenAndServe()
}()
select {
case err = <-errchan:
s.t.Fatalf("error serving registry: %v", err)
default:
}
}
func (s *OCIRegistryServer) Address() string {
return fmt.Sprintf("127.0.0.1:%s", s.opts.port)
}
func (s *OCIRegistryServer) RefToImage(imageName, imageTag string) name.Reference {
remoteImgRef, err := name.ParseReference(fmt.Sprintf("%s/%s:%s", s.Address(), imageName, imageTag))
require.NoError(s.t, err)
return remoteImgRef
}
func (s *OCIRegistryServer) Push(remoteImgRef name.Reference, img v1.Image) {
err := remote.Write(remoteImgRef, img)
require.NoError(s.t, err)
}
func (s *OCIRegistryServer) PushImageIndex(remoteImgRef name.Reference, img v1.ImageIndex) {
err := remote.WriteIndex(remoteImgRef, img)
require.NoError(s.t, err)
}
func (s *OCIRegistryServer) Stop() {
s.cancelFn()
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_ = s.server.Shutdown(ctx)
}