mirror of
https://github.com/hauler-dev/hauler.git
synced 2026-08-19 04:16:27 +00:00
fixed registry bug with debug config (#722)
This commit is contained in:
@@ -126,6 +126,18 @@ func ServeRegistryCmd(ctx context.Context, o *flags.ServeRegistryOpts, s *store.
|
||||
return err
|
||||
}
|
||||
|
||||
if cfg.HTTP.Debug.Addr != "" {
|
||||
l.Infof("starting debug server on address [%s]", cfg.HTTP.Debug.Addr)
|
||||
if cfg.HTTP.Debug.Prometheus.Enabled {
|
||||
path := cfg.HTTP.Debug.Prometheus.Path
|
||||
if path == "" {
|
||||
path = "/metrics"
|
||||
}
|
||||
l.Infof("providing prometheus metrics on [%s]", path)
|
||||
}
|
||||
}
|
||||
server.ConfigureDebugServer(cfg)
|
||||
|
||||
if err = r.ListenAndServe(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ require (
|
||||
github.com/containerd/errdefs v1.0.0
|
||||
github.com/distribution/distribution/v3 v3.1.1
|
||||
github.com/distribution/reference v0.6.0
|
||||
github.com/docker/go-metrics v0.0.1
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/google/go-containerregistry v0.21.9
|
||||
github.com/google/uuid v1.6.0
|
||||
@@ -132,7 +133,6 @@ require (
|
||||
github.com/docker/docker-credential-helpers v0.9.5 // indirect
|
||||
github.com/docker/go-connections v0.7.0 // indirect
|
||||
github.com/docker/go-events v0.0.0-20250808211157-605354379745 // indirect
|
||||
github.com/docker/go-metrics v0.0.1 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect
|
||||
github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a // indirect
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/distribution/distribution/v3/configuration"
|
||||
"github.com/distribution/distribution/v3/registry"
|
||||
"github.com/distribution/distribution/v3/registry/handlers"
|
||||
dockermetrics "github.com/docker/go-metrics"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@@ -24,6 +25,27 @@ func NewRegistry(ctx context.Context, cfg *configuration.Configuration) (*regist
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// ConfigureDebugServer starts pprof/expvar/prometheus on cfg.HTTP.Debug.Addr
|
||||
func ConfigureDebugServer(cfg *configuration.Configuration) {
|
||||
if cfg.HTTP.Debug.Addr == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if cfg.HTTP.Debug.Prometheus.Enabled {
|
||||
path := cfg.HTTP.Debug.Prometheus.Path
|
||||
if path == "" {
|
||||
path = "/metrics"
|
||||
}
|
||||
http.Handle(path, dockermetrics.Handler())
|
||||
}
|
||||
|
||||
go func(addr string) {
|
||||
if err := http.ListenAndServe(addr, nil); err != nil { //nolint:gosec // debug interface: internal-only, no read/write timeouts needed
|
||||
logrus.Fatalf("error listening on debug interface: %v", err)
|
||||
}
|
||||
}(cfg.HTTP.Debug.Addr)
|
||||
}
|
||||
|
||||
type tmpRegistryServer struct {
|
||||
*httptest.Server
|
||||
}
|
||||
|
||||
@@ -2,10 +2,14 @@ package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/distribution/distribution/v3/configuration"
|
||||
// Register the filesystem storage driver for the distribution registry.
|
||||
_ "github.com/distribution/distribution/v3/registry/storage/driver/filesystem"
|
||||
|
||||
@@ -16,9 +20,8 @@ func TestNewTempRegistry_StartStop(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
srv := NewTempRegistry(ctx, t.TempDir())
|
||||
|
||||
// Start the httptest server directly to avoid the Start() method's
|
||||
// retry logic which only accepts HTTP 200, while /v2 returns 401
|
||||
// from the distribution registry.
|
||||
// start the httptest server directly to avoid the retry logic which only accepts HTTP 200
|
||||
// while /v2 returns 401 from the distribution registry.
|
||||
srv.Server.Start()
|
||||
t.Cleanup(func() { srv.Stop() })
|
||||
|
||||
@@ -74,6 +77,55 @@ func TestNewFile_Configuration(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// this is the only test in the package allowed to enable prometheus, since it registers
|
||||
// on http.DefaultServeMux and a second registration would panic.
|
||||
func TestConfigureDebugServer_Prometheus(t *testing.T) {
|
||||
// grab a free port and release it so ConfigureDebugServer can bind it
|
||||
l, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to reserve a free port: %v", err)
|
||||
}
|
||||
addr := l.Addr().String()
|
||||
l.Close()
|
||||
|
||||
cfg := &configuration.Configuration{}
|
||||
cfg.HTTP.Debug.Addr = addr
|
||||
cfg.HTTP.Debug.Prometheus.Enabled = true
|
||||
cfg.HTTP.Debug.Prometheus.Path = "/metrics"
|
||||
|
||||
ConfigureDebugServer(cfg)
|
||||
|
||||
var resp *http.Response
|
||||
for i := 0; i < 20; i++ {
|
||||
resp, err = http.Get("http://" + addr + "/metrics")
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("expected GET /metrics to eventually succeed, got error: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Fatalf("expected status 200 from the prometheus handler, got %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read response body: %v", err)
|
||||
}
|
||||
if !strings.Contains(string(body), "go_gc_duration_seconds") {
|
||||
t.Fatalf("expected prometheus-formatted metrics output, got: %s", body)
|
||||
}
|
||||
}
|
||||
|
||||
// an empty Debug.Addr should just no-op, not start a listener.
|
||||
func TestConfigureDebugServer_NoAddr(t *testing.T) {
|
||||
ConfigureDebugServer(&configuration.Configuration{})
|
||||
}
|
||||
|
||||
func TestNewFile_DefaultPort(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
opts := flags.ServeFilesOpts{
|
||||
|
||||
Reference in New Issue
Block a user