cleanup: move init funcs to the top of the source

We make sure they're not hiding at the bottom or in the middle
which makes debugging an utter nightmare!

Signed-off-by: Milos Gajdos <milosthegajdos@gmail.com>
This commit is contained in:
Milos Gajdos 2023-11-28 06:50:48 +00:00
parent d9abc517e8
commit d8ff41a344
No known key found for this signature in database
14 changed files with 203 additions and 201 deletions

View File

@ -9,6 +9,13 @@ import (
var updater = health.NewStatusUpdater()
// init sets up the two endpoints to bring the service up and down
func init() {
health.Register("manual_http_status", updater)
http.HandleFunc("/debug/health/down", DownHandler)
http.HandleFunc("/debug/health/up", UpHandler)
}
// DownHandler registers a manual_http_status that always returns an Error
func DownHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodPost {
@ -26,10 +33,3 @@ func UpHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
}
}
// init sets up the two endpoints to bring the service up and down
func init() {
health.Register("manual_http_status", updater)
http.HandleFunc("/debug/health/down", DownHandler)
http.HandleFunc("/debug/health/up", UpHandler)
}

View File

@ -13,6 +13,12 @@ import (
"github.com/distribution/distribution/v3/registry/api/errcode"
)
// Registers global /debug/health api endpoint, creates default registry
func init() {
DefaultRegistry = NewRegistry()
http.HandleFunc("/debug/health", StatusHandler)
}
// A Registry is a collection of checks. Most applications will use the global
// registry defined in DefaultRegistry. However, unit tests may need to create
// separate registries to isolate themselves from other tests.
@ -278,9 +284,3 @@ func statusResponse(w http.ResponseWriter, r *http.Request, status int, checks m
dcontext.GetLogger(r.Context()).Errorf("error writing health status response body: %v", err)
}
}
// Registers global /debug/health api endpoint, creates default registry
func init() {
DefaultRegistry = NewRegistry()
http.HandleFunc("/debug/health", StatusHandler)
}

View File

@ -8,6 +8,48 @@ import (
"sync"
)
// Octet types from RFC 2616.
type octetType byte
var octetTypes [256]octetType
const (
isToken octetType = 1 << iota
isSpace
)
func init() {
// OCTET = <any 8-bit sequence of data>
// CHAR = <any US-ASCII character (octets 0 - 127)>
// CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
// CR = <US-ASCII CR, carriage return (13)>
// LF = <US-ASCII LF, linefeed (10)>
// SP = <US-ASCII SP, space (32)>
// HT = <US-ASCII HT, horizontal-tab (9)>
// <"> = <US-ASCII double-quote mark (34)>
// CRLF = CR LF
// LWS = [CRLF] 1*( SP | HT )
// TEXT = <any OCTET except CTLs, but including LWS>
// separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <">
// | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT
// token = 1*<any CHAR except CTLs or separators>
// qdtext = <any TEXT except <">>
for c := 0; c < 256; c++ {
var t octetType
isCtl := c <= 31 || c == 127
isChar := 0 <= c && c <= 127
isSeparator := strings.ContainsRune(" \t\"(),/:;<=>?@[]\\{}", rune(c))
if strings.ContainsRune(" \t\r\n", rune(c)) {
t |= isSpace
}
if isChar && !isCtl && !isSeparator {
t |= isToken
}
octetTypes[c] = t
}
}
// Challenge carries information from a WWW-Authenticate response header.
// See RFC 2617.
type Challenge struct {
@ -86,48 +128,6 @@ func (m *simpleManager) AddResponse(resp *http.Response) error {
return nil
}
// Octet types from RFC 2616.
type octetType byte
var octetTypes [256]octetType
const (
isToken octetType = 1 << iota
isSpace
)
func init() {
// OCTET = <any 8-bit sequence of data>
// CHAR = <any US-ASCII character (octets 0 - 127)>
// CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
// CR = <US-ASCII CR, carriage return (13)>
// LF = <US-ASCII LF, linefeed (10)>
// SP = <US-ASCII SP, space (32)>
// HT = <US-ASCII HT, horizontal-tab (9)>
// <"> = <US-ASCII double-quote mark (34)>
// CRLF = CR LF
// LWS = [CRLF] 1*( SP | HT )
// TEXT = <any OCTET except CTLs, but including LWS>
// separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <">
// | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT
// token = 1*<any CHAR except CTLs or separators>
// qdtext = <any TEXT except <">>
for c := 0; c < 256; c++ {
var t octetType
isCtl := c <= 31 || c == 127
isChar := 0 <= c && c <= 127
isSeparator := strings.ContainsRune(" \t\"(),/:;<=>?@[]\\{}", rune(c))
if strings.ContainsRune(" \t\r\n", rune(c)) {
t |= isSpace
}
if isChar && !isCtl && !isSeparator {
t |= isToken
}
octetTypes[c] = t
}
}
// ResponseChallenges returns a list of authorization challenges
// for the given http Response. Challenges are only checked if
// the response status code was a 401.

View File

@ -20,6 +20,57 @@ var (
statusCounter = prometheus.NotificationsNamespace.NewLabeledCounter("status", "The number of status code", "code", "endpoint")
)
// endpoints is global registry of endpoints used to report metrics to expvar
var endpoints struct {
registered []*Endpoint
mu sync.Mutex
}
func init() {
// NOTE(stevvooe): Setup registry metrics structure to report to expvar.
// Ideally, we do more metrics through logging but we need some nice
// realtime metrics for queue state for now.
registry := expvar.Get("registry")
if registry == nil {
registry = expvar.NewMap("registry")
}
var notifications expvar.Map
notifications.Init()
notifications.Set("endpoints", expvar.Func(func() interface{} {
endpoints.mu.Lock()
defer endpoints.mu.Unlock()
var names []interface{}
for _, v := range endpoints.registered {
var epjson struct {
Name string `json:"name"`
URL string `json:"url"`
EndpointConfig
Metrics EndpointMetrics
}
epjson.Name = v.Name()
epjson.URL = v.URL()
epjson.EndpointConfig = v.EndpointConfig
v.ReadMetrics(&epjson.Metrics)
names = append(names, epjson)
}
return names
}))
registry.(*expvar.Map).Set("notifications", &notifications)
// register prometheus metrics
metrics.Register(prometheus.NotificationsNamespace)
}
// EndpointMetrics track various actions taken by the endpoint, typically by
// number of events. The goal of this to export it via expvar but we may find
// some other future solution to be better.
@ -123,12 +174,6 @@ func (eqc *endpointMetricsEventQueueListener) egress(event events.Event) {
pendingGauge.WithValues(eqc.EndpointName).Dec(1)
}
// endpoints is global registry of endpoints used to report metrics to expvar
var endpoints struct {
registered []*Endpoint
mu sync.Mutex
}
// register places the endpoint into expvar so that stats are tracked.
func register(e *Endpoint) {
endpoints.mu.Lock()
@ -136,48 +181,3 @@ func register(e *Endpoint) {
endpoints.registered = append(endpoints.registered, e)
}
func init() {
// NOTE(stevvooe): Setup registry metrics structure to report to expvar.
// Ideally, we do more metrics through logging but we need some nice
// realtime metrics for queue state for now.
registry := expvar.Get("registry")
if registry == nil {
registry = expvar.NewMap("registry")
}
var notifications expvar.Map
notifications.Init()
notifications.Set("endpoints", expvar.Func(func() interface{} {
endpoints.mu.Lock()
defer endpoints.mu.Unlock()
var names []interface{}
for _, v := range endpoints.registered {
var epjson struct {
Name string `json:"name"`
URL string `json:"url"`
EndpointConfig
Metrics EndpointMetrics
}
epjson.Name = v.Name()
epjson.URL = v.URL()
epjson.EndpointConfig = v.EndpointConfig
v.ReadMetrics(&epjson.Metrics)
names = append(names, epjson)
}
return names
}))
registry.(*expvar.Map).Set("notifications", &notifications)
// register prometheus metrics
metrics.Register(prometheus.NotificationsNamespace)
}

View File

@ -9,6 +9,16 @@ import (
"github.com/opencontainers/go-digest"
)
var routeDescriptorsMap map[string]RouteDescriptor
func init() {
routeDescriptorsMap = make(map[string]RouteDescriptor, len(routeDescriptors))
for _, descriptor := range routeDescriptors {
routeDescriptorsMap[descriptor.Name] = descriptor
}
}
var (
nameParameterDescriptor = ParameterDescriptor{
Name: "name",
@ -1600,13 +1610,3 @@ var routeDescriptors = []RouteDescriptor{
},
},
}
var routeDescriptorsMap map[string]RouteDescriptor
func init() {
routeDescriptorsMap = make(map[string]RouteDescriptor, len(routeDescriptors))
for _, descriptor := range routeDescriptors {
routeDescriptorsMap[descriptor.Name] = descriptor
}
}

View File

@ -45,6 +45,16 @@ var (
ErrAuthenticationFailure = errors.New("authentication failure")
)
// InitFunc is the type of an AccessController factory function and is used
// to register the constructor for different AccesController backends.
type InitFunc func(options map[string]interface{}) (AccessController, error)
var accessControllers map[string]InitFunc
func init() {
accessControllers = make(map[string]InitFunc)
}
// UserInfo carries information about
// an autenticated/authorized client.
type UserInfo struct {
@ -104,16 +114,6 @@ type CredentialAuthenticator interface {
AuthenticateUser(username, password string) error
}
// InitFunc is the type of an AccessController factory function and is used
// to register the constructor for different AccesController backends.
type InitFunc func(options map[string]interface{}) (AccessController, error)
var accessControllers map[string]InitFunc
func init() {
accessControllers = make(map[string]InitFunc)
}
// Register is used to register an InitFunc for
// an AccessController backend with the given name.
func Register(name string, initFunc InitFunc) error {

View File

@ -23,6 +23,12 @@ import (
"github.com/sirupsen/logrus"
)
func init() {
if err := auth.Register("htpasswd", auth.InitFunc(newAccessController)); err != nil {
logrus.Errorf("failed to register htpasswd auth: %v", err)
}
}
type accessController struct {
realm string
path string
@ -150,9 +156,3 @@ func createHtpasswdFile(path string) error {
}).Warnf("htpasswd is missing, provisioning with default user")
return nil
}
func init() {
if err := auth.Register("htpasswd", auth.InitFunc(newAccessController)); err != nil {
logrus.Errorf("failed to register htpasswd auth: %v", err)
}
}

View File

@ -16,6 +16,13 @@ import (
"github.com/sirupsen/logrus"
)
// init registers the silly auth backend.
func init() {
if err := auth.Register("silly", auth.InitFunc(newAccessController)); err != nil {
logrus.Errorf("failed to register silly auth: %v", err)
}
}
// accessController provides a simple implementation of auth.AccessController
// that simply checks for a non-empty Authorization header. It is useful for
// demonstration and testing.
@ -85,10 +92,3 @@ func (ch challenge) SetHeaders(r *http.Request, w http.ResponseWriter) {
func (ch challenge) Error() string {
return fmt.Sprintf("silly authentication challenge: %#v", ch)
}
// init registers the silly auth backend.
func init() {
if err := auth.Register("silly", auth.InitFunc(newAccessController)); err != nil {
logrus.Errorf("failed to register silly auth: %v", err)
}
}

View File

@ -17,6 +17,13 @@ import (
"github.com/sirupsen/logrus"
)
// init handles registering the token auth backend.
func init() {
if err := auth.Register("token", auth.InitFunc(newAccessController)); err != nil {
logrus.Errorf("tailed to register token auth: %v", err)
}
}
// accessSet maps a typed, named resource to
// a set of actions requested or authorized.
type accessSet map[auth.Resource]actionSet
@ -337,10 +344,3 @@ func (ac *accessController) Authorized(req *http.Request, accessItems ...auth.Ac
Resources: claims.resources(),
}, nil
}
// init handles registering the token auth backend.
func init() {
if err := auth.Register("token", auth.InitFunc(newAccessController)); err != nil {
logrus.Errorf("tailed to register token auth: %v", err)
}
}

View File

@ -20,14 +20,20 @@ import (
"github.com/opencontainers/go-digest"
)
var sbsMu sync.Mutex
var randSource rand.Rand
var (
sbsMu sync.Mutex
randSource rand.Rand
)
type statsBlobStore struct {
stats map[string]int
blobs distribution.BlobStore
}
func init() {
randSource = *rand.New(rand.NewSource(42))
}
func (sbs statsBlobStore) Put(ctx context.Context, mediaType string, p []byte) (distribution.Descriptor, error) {
sbsMu.Lock()
sbs.stats["put"]++
@ -195,10 +201,6 @@ func makeBlob(size int) []byte {
return blob
}
func init() {
randSource = *rand.New(rand.NewSource(42))
}
func populate(t *testing.T, te *testEnv, blobCount, size, numUnique int) {
var inRemote []distribution.Descriptor

View File

@ -36,6 +36,34 @@ type proxyMetricsCollector struct {
manifestMetrics Metrics
}
// proxyMetrics tracks metrics about the proxy cache. This is
// kept globally and made available via expvar.
var proxyMetrics = &proxyMetricsCollector{}
func init() {
registry := expvar.Get("registry")
if registry == nil {
registry = expvar.NewMap("registry")
}
pm := registry.(*expvar.Map).Get("proxy")
if pm == nil {
pm = &expvar.Map{}
pm.(*expvar.Map).Init()
registry.(*expvar.Map).Set("proxy", pm)
}
pm.(*expvar.Map).Set("blobs", expvar.Func(func() interface{} {
return proxyMetrics.blobMetrics
}))
pm.(*expvar.Map).Set("manifests", expvar.Func(func() interface{} {
return proxyMetrics.manifestMetrics
}))
metrics.Register(prometheus.ProxyNamespace)
}
// BlobPull tracks metrics about blobs pulled into the cache
func (pmc *proxyMetricsCollector) BlobPull(bytesPulled uint64) {
atomic.AddUint64(&pmc.blobMetrics.Misses, 1)
@ -83,31 +111,3 @@ func (pmc *proxyMetricsCollector) ManifestPush(bytesPushed uint64, isHit bool) {
hits.WithValues("manifest").Inc(1)
}
}
// proxyMetrics tracks metrics about the proxy cache. This is
// kept globally and made available via expvar.
var proxyMetrics = &proxyMetricsCollector{}
func init() {
registry := expvar.Get("registry")
if registry == nil {
registry = expvar.NewMap("registry")
}
pm := registry.(*expvar.Map).Get("proxy")
if pm == nil {
pm = &expvar.Map{}
pm.(*expvar.Map).Init()
registry.(*expvar.Map).Set("proxy", pm)
}
pm.(*expvar.Map).Set("blobs", expvar.Func(func() interface{} {
return proxyMetrics.blobMetrics
}))
pm.(*expvar.Map).Set("manifests", expvar.Func(func() interface{} {
return proxyMetrics.manifestMetrics
}))
metrics.Register(prometheus.ProxyNamespace)
}

View File

@ -20,6 +20,13 @@ import (
"github.com/sirupsen/logrus"
)
// init registers the cloudfront layerHandler backend.
func init() {
if err := storagemiddleware.Register("cloudfront", newCloudFrontStorageMiddleware); err != nil {
logrus.Errorf("failed to register cloudfront middleware: %v", err)
}
}
// cloudFrontStorageMiddleware provides a simple implementation of layerHandler that
// constructs temporary signed CloudFront URLs from the storagedriver layer URL,
// then issues HTTP Temporary Redirects to this CloudFront content URL.
@ -224,10 +231,3 @@ func (lh *cloudFrontStorageMiddleware) RedirectURL(r *http.Request, path string)
}
return cfURL, nil
}
// init registers the cloudfront layerHandler backend.
func init() {
if err := storagemiddleware.Register("cloudfront", newCloudFrontStorageMiddleware); err != nil {
logrus.Errorf("failed to register cloudfront middleware: %v", err)
}
}

View File

@ -12,6 +12,12 @@ import (
"github.com/sirupsen/logrus"
)
func init() {
if err := storagemiddleware.Register("redirect", newRedirectStorageMiddleware); err != nil {
logrus.Errorf("tailed to register redirect storage middleware: %v", err)
}
}
type redirectStorageMiddleware struct {
storagedriver.StorageDriver
scheme string
@ -51,9 +57,3 @@ func (r *redirectStorageMiddleware) RedirectURL(_ *http.Request, urlPath string)
u := &url.URL{Scheme: r.scheme, Host: r.host, Path: urlPath}
return u.String(), nil
}
func init() {
if err := storagemiddleware.Register("redirect", newRedirectStorageMiddleware); err != nil {
logrus.Errorf("tailed to register redirect storage middleware: %v", err)
}
}

View File

@ -24,6 +24,14 @@ import (
// Test hooks up gocheck into the "go test" runner.
func Test(t *testing.T) { check.TestingT(t) }
// randomBytes pre-allocates all of the memory sizes needed for the test. If
// anything panics while accessing randomBytes, just make this number bigger.
var randomBytes = make([]byte, 128<<20)
func init() {
_, _ = crand.Read(randomBytes) // always returns len(randomBytes) and nil error
}
// RegisterSuite registers an in-process storage driver test suite with
// the go test runner.
func RegisterSuite(driverConstructor DriverConstructor, skipCheck SkipCheck) {
@ -1343,14 +1351,6 @@ func randomFilename(length int64) string {
return string(b)
}
// randomBytes pre-allocates all of the memory sizes needed for the test. If
// anything panics while accessing randomBytes, just make this number bigger.
var randomBytes = make([]byte, 128<<20)
func init() {
_, _ = crand.Read(randomBytes) // always returns len(randomBytes) and nil error
}
func randomContents(length int64) []byte {
return randomBytes[:length]
}