...

Source file src/github.com/docker/distribution/configuration/configuration.go

Documentation: github.com/docker/distribution/configuration

     1  package configuration
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io"
     7  	"io/ioutil"
     8  	"net/http"
     9  	"reflect"
    10  	"strings"
    11  	"time"
    12  )
    13  
    14  // Configuration is a versioned registry configuration, intended to be provided by a yaml file, and
    15  // optionally modified by environment variables.
    16  //
    17  // Note that yaml field names should never include _ characters, since this is the separator used
    18  // in environment variable names.
    19  type Configuration struct {
    20  	// Version is the version which defines the format of the rest of the configuration
    21  	Version Version `yaml:"version"`
    22  
    23  	// Log supports setting various parameters related to the logging
    24  	// subsystem.
    25  	Log struct {
    26  		// AccessLog configures access logging.
    27  		AccessLog struct {
    28  			// Disabled disables access logging.
    29  			Disabled bool `yaml:"disabled,omitempty"`
    30  		} `yaml:"accesslog,omitempty"`
    31  
    32  		// Level is the granularity at which registry operations are logged.
    33  		Level Loglevel `yaml:"level,omitempty"`
    34  
    35  		// Formatter overrides the default formatter with another. Options
    36  		// include "text", "json" and "logstash".
    37  		Formatter string `yaml:"formatter,omitempty"`
    38  
    39  		// Fields allows users to specify static string fields to include in
    40  		// the logger context.
    41  		Fields map[string]interface{} `yaml:"fields,omitempty"`
    42  
    43  		// Hooks allows users to configure the log hooks, to enabling the
    44  		// sequent handling behavior, when defined levels of log message emit.
    45  		Hooks []LogHook `yaml:"hooks,omitempty"`
    46  	}
    47  
    48  	// Loglevel is the level at which registry operations are logged.
    49  	//
    50  	// Deprecated: Use Log.Level instead.
    51  	Loglevel Loglevel `yaml:"loglevel,omitempty"`
    52  
    53  	// Storage is the configuration for the registry's storage driver
    54  	Storage Storage `yaml:"storage"`
    55  
    56  	// Auth allows configuration of various authorization methods that may be
    57  	// used to gate requests.
    58  	Auth Auth `yaml:"auth,omitempty"`
    59  
    60  	// Middleware lists all middlewares to be used by the registry.
    61  	Middleware map[string][]Middleware `yaml:"middleware,omitempty"`
    62  
    63  	// Reporting is the configuration for error reporting
    64  	Reporting Reporting `yaml:"reporting,omitempty"`
    65  
    66  	// HTTP contains configuration parameters for the registry's http
    67  	// interface.
    68  	HTTP struct {
    69  		// Addr specifies the bind address for the registry instance.
    70  		Addr string `yaml:"addr,omitempty"`
    71  
    72  		// Net specifies the net portion of the bind address. A default empty value means tcp.
    73  		Net string `yaml:"net,omitempty"`
    74  
    75  		// Host specifies an externally-reachable address for the registry, as a fully
    76  		// qualified URL.
    77  		Host string `yaml:"host,omitempty"`
    78  
    79  		Prefix string `yaml:"prefix,omitempty"`
    80  
    81  		// Secret specifies the secret key which HMAC tokens are created with.
    82  		Secret string `yaml:"secret,omitempty"`
    83  
    84  		// RelativeURLs specifies that relative URLs should be returned in
    85  		// Location headers
    86  		RelativeURLs bool `yaml:"relativeurls,omitempty"`
    87  
    88  		// Amount of time to wait for connection to drain before shutting down when registry
    89  		// receives a stop signal
    90  		DrainTimeout time.Duration `yaml:"draintimeout,omitempty"`
    91  
    92  		// TLS instructs the http server to listen with a TLS configuration.
    93  		// This only support simple tls configuration with a cert and key.
    94  		// Mostly, this is useful for testing situations or simple deployments
    95  		// that require tls. If more complex configurations are required, use
    96  		// a proxy or make a proposal to add support here.
    97  		TLS struct {
    98  			// Certificate specifies the path to an x509 certificate file to
    99  			// be used for TLS.
   100  			Certificate string `yaml:"certificate,omitempty"`
   101  
   102  			// Key specifies the path to the x509 key file, which should
   103  			// contain the private portion for the file specified in
   104  			// Certificate.
   105  			Key string `yaml:"key,omitempty"`
   106  
   107  			// Specifies the CA certs for client authentication
   108  			// A file may contain multiple CA certificates encoded as PEM
   109  			ClientCAs []string `yaml:"clientcas,omitempty"`
   110  
   111  			// Specifies the lowest TLS version allowed
   112  			MinimumTLS string `yaml:"minimumtls,omitempty"`
   113  
   114  			// Specifies a list of cipher suites allowed
   115  			CipherSuites []string `yaml:"ciphersuites,omitempty"`
   116  
   117  			// LetsEncrypt is used to configuration setting up TLS through
   118  			// Let's Encrypt instead of manually specifying certificate and
   119  			// key. If a TLS certificate is specified, the Let's Encrypt
   120  			// section will not be used.
   121  			LetsEncrypt struct {
   122  				// CacheFile specifies cache file to use for lets encrypt
   123  				// certificates and keys.
   124  				CacheFile string `yaml:"cachefile,omitempty"`
   125  
   126  				// Email is the email to use during Let's Encrypt registration
   127  				Email string `yaml:"email,omitempty"`
   128  
   129  				// Hosts specifies the hosts which are allowed to obtain Let's
   130  				// Encrypt certificates.
   131  				Hosts []string `yaml:"hosts,omitempty"`
   132  			} `yaml:"letsencrypt,omitempty"`
   133  		} `yaml:"tls,omitempty"`
   134  
   135  		// Headers is a set of headers to include in HTTP responses. A common
   136  		// use case for this would be security headers such as
   137  		// Strict-Transport-Security. The map keys are the header names, and
   138  		// the values are the associated header payloads.
   139  		Headers http.Header `yaml:"headers,omitempty"`
   140  
   141  		// Debug configures the http debug interface, if specified. This can
   142  		// include services such as pprof, expvar and other data that should
   143  		// not be exposed externally. Left disabled by default.
   144  		Debug struct {
   145  			// Addr specifies the bind address for the debug server.
   146  			Addr string `yaml:"addr,omitempty"`
   147  			// Prometheus configures the Prometheus telemetry endpoint.
   148  			Prometheus struct {
   149  				Enabled bool   `yaml:"enabled,omitempty"`
   150  				Path    string `yaml:"path,omitempty"`
   151  			} `yaml:"prometheus,omitempty"`
   152  		} `yaml:"debug,omitempty"`
   153  
   154  		// HTTP2 configuration options
   155  		HTTP2 struct {
   156  			// Specifies whether the registry should disallow clients attempting
   157  			// to connect via http2. If set to true, only http/1.1 is supported.
   158  			Disabled bool `yaml:"disabled,omitempty"`
   159  		} `yaml:"http2,omitempty"`
   160  	} `yaml:"http,omitempty"`
   161  
   162  	// Notifications specifies configuration about various endpoint to which
   163  	// registry events are dispatched.
   164  	Notifications Notifications `yaml:"notifications,omitempty"`
   165  
   166  	// Redis configures the redis pool available to the registry webapp.
   167  	Redis struct {
   168  		// Addr specifies the the redis instance available to the application.
   169  		Addr string `yaml:"addr,omitempty"`
   170  
   171  		// Password string to use when making a connection.
   172  		Password string `yaml:"password,omitempty"`
   173  
   174  		// DB specifies the database to connect to on the redis instance.
   175  		DB int `yaml:"db,omitempty"`
   176  
   177  		DialTimeout  time.Duration `yaml:"dialtimeout,omitempty"`  // timeout for connect
   178  		ReadTimeout  time.Duration `yaml:"readtimeout,omitempty"`  // timeout for reads of data
   179  		WriteTimeout time.Duration `yaml:"writetimeout,omitempty"` // timeout for writes of data
   180  
   181  		// Pool configures the behavior of the redis connection pool.
   182  		Pool struct {
   183  			// MaxIdle sets the maximum number of idle connections.
   184  			MaxIdle int `yaml:"maxidle,omitempty"`
   185  
   186  			// MaxActive sets the maximum number of connections that should be
   187  			// opened before blocking a connection request.
   188  			MaxActive int `yaml:"maxactive,omitempty"`
   189  
   190  			// IdleTimeout sets the amount time to wait before closing
   191  			// inactive connections.
   192  			IdleTimeout time.Duration `yaml:"idletimeout,omitempty"`
   193  		} `yaml:"pool,omitempty"`
   194  	} `yaml:"redis,omitempty"`
   195  
   196  	Health  Health  `yaml:"health,omitempty"`
   197  	Catalog Catalog `yaml:"catalog,omitempty"`
   198  
   199  	Proxy Proxy `yaml:"proxy,omitempty"`
   200  
   201  	// Compatibility is used for configurations of working with older or deprecated features.
   202  	Compatibility struct {
   203  		// Schema1 configures how schema1 manifests will be handled
   204  		Schema1 struct {
   205  			// TrustKey is the signing key to use for adding the signature to
   206  			// schema1 manifests.
   207  			TrustKey string `yaml:"signingkeyfile,omitempty"`
   208  			// Enabled determines if schema1 manifests should be pullable
   209  			Enabled bool `yaml:"enabled,omitempty"`
   210  		} `yaml:"schema1,omitempty"`
   211  	} `yaml:"compatibility,omitempty"`
   212  
   213  	// Validation configures validation options for the registry.
   214  	Validation struct {
   215  		// Enabled enables the other options in this section. This field is
   216  		// deprecated in favor of Disabled.
   217  		Enabled bool `yaml:"enabled,omitempty"`
   218  		// Disabled disables the other options in this section.
   219  		Disabled bool `yaml:"disabled,omitempty"`
   220  		// Manifests configures manifest validation.
   221  		Manifests struct {
   222  			// URLs configures validation for URLs in pushed manifests.
   223  			URLs struct {
   224  				// Allow specifies regular expressions (https://godoc.org/regexp/syntax)
   225  				// that URLs in pushed manifests must match.
   226  				Allow []string `yaml:"allow,omitempty"`
   227  				// Deny specifies regular expressions (https://godoc.org/regexp/syntax)
   228  				// that URLs in pushed manifests must not match.
   229  				Deny []string `yaml:"deny,omitempty"`
   230  			} `yaml:"urls,omitempty"`
   231  		} `yaml:"manifests,omitempty"`
   232  	} `yaml:"validation,omitempty"`
   233  
   234  	// Policy configures registry policy options.
   235  	Policy struct {
   236  		// Repository configures policies for repositories
   237  		Repository struct {
   238  			// Classes is a list of repository classes which the
   239  			// registry allows content for. This class is matched
   240  			// against the configuration media type inside uploaded
   241  			// manifests. When non-empty, the registry will enforce
   242  			// the class in authorized resources.
   243  			Classes []string `yaml:"classes"`
   244  		} `yaml:"repository,omitempty"`
   245  	} `yaml:"policy,omitempty"`
   246  }
   247  
   248  // Catalog is composed of MaxEntries.
   249  // Catalog endpoint (/v2/_catalog) configuration, it provides the configuration
   250  // options to control the maximum number of entries returned by the catalog endpoint.
   251  type Catalog struct {
   252  	// Max number of entries returned by the catalog endpoint. Requesting n entries
   253  	// to the catalog endpoint will return at most MaxEntries entries.
   254  	// An empty or a negative value will set a default of 1000 maximum entries by default.
   255  	MaxEntries int `yaml:"maxentries,omitempty"`
   256  }
   257  
   258  // LogHook is composed of hook Level and Type.
   259  // After hooks configuration, it can execute the next handling automatically,
   260  // when defined levels of log message emitted.
   261  // Example: hook can sending an email notification when error log happens in app.
   262  type LogHook struct {
   263  	// Disable lets user select to enable hook or not.
   264  	Disabled bool `yaml:"disabled,omitempty"`
   265  
   266  	// Type allows user to select which type of hook handler they want.
   267  	Type string `yaml:"type,omitempty"`
   268  
   269  	// Levels set which levels of log message will let hook executed.
   270  	Levels []string `yaml:"levels,omitempty"`
   271  
   272  	// MailOptions allows user to configure email parameters.
   273  	MailOptions MailOptions `yaml:"options,omitempty"`
   274  }
   275  
   276  // MailOptions provides the configuration sections to user, for specific handler.
   277  type MailOptions struct {
   278  	SMTP struct {
   279  		// Addr defines smtp host address
   280  		Addr string `yaml:"addr,omitempty"`
   281  
   282  		// Username defines user name to smtp host
   283  		Username string `yaml:"username,omitempty"`
   284  
   285  		// Password defines password of login user
   286  		Password string `yaml:"password,omitempty"`
   287  
   288  		// Insecure defines if smtp login skips the secure certification.
   289  		Insecure bool `yaml:"insecure,omitempty"`
   290  	} `yaml:"smtp,omitempty"`
   291  
   292  	// From defines mail sending address
   293  	From string `yaml:"from,omitempty"`
   294  
   295  	// To defines mail receiving address
   296  	To []string `yaml:"to,omitempty"`
   297  }
   298  
   299  // FileChecker is a type of entry in the health section for checking files.
   300  type FileChecker struct {
   301  	// Interval is the duration in between checks
   302  	Interval time.Duration `yaml:"interval,omitempty"`
   303  	// File is the path to check
   304  	File string `yaml:"file,omitempty"`
   305  	// Threshold is the number of times a check must fail to trigger an
   306  	// unhealthy state
   307  	Threshold int `yaml:"threshold,omitempty"`
   308  }
   309  
   310  // HTTPChecker is a type of entry in the health section for checking HTTP URIs.
   311  type HTTPChecker struct {
   312  	// Timeout is the duration to wait before timing out the HTTP request
   313  	Timeout time.Duration `yaml:"timeout,omitempty"`
   314  	// StatusCode is the expected status code
   315  	StatusCode int
   316  	// Interval is the duration in between checks
   317  	Interval time.Duration `yaml:"interval,omitempty"`
   318  	// URI is the HTTP URI to check
   319  	URI string `yaml:"uri,omitempty"`
   320  	// Headers lists static headers that should be added to all requests
   321  	Headers http.Header `yaml:"headers"`
   322  	// Threshold is the number of times a check must fail to trigger an
   323  	// unhealthy state
   324  	Threshold int `yaml:"threshold,omitempty"`
   325  }
   326  
   327  // TCPChecker is a type of entry in the health section for checking TCP servers.
   328  type TCPChecker struct {
   329  	// Timeout is the duration to wait before timing out the TCP connection
   330  	Timeout time.Duration `yaml:"timeout,omitempty"`
   331  	// Interval is the duration in between checks
   332  	Interval time.Duration `yaml:"interval,omitempty"`
   333  	// Addr is the TCP address to check
   334  	Addr string `yaml:"addr,omitempty"`
   335  	// Threshold is the number of times a check must fail to trigger an
   336  	// unhealthy state
   337  	Threshold int `yaml:"threshold,omitempty"`
   338  }
   339  
   340  // Health provides the configuration section for health checks.
   341  type Health struct {
   342  	// FileCheckers is a list of paths to check
   343  	FileCheckers []FileChecker `yaml:"file,omitempty"`
   344  	// HTTPCheckers is a list of URIs to check
   345  	HTTPCheckers []HTTPChecker `yaml:"http,omitempty"`
   346  	// TCPCheckers is a list of URIs to check
   347  	TCPCheckers []TCPChecker `yaml:"tcp,omitempty"`
   348  	// StorageDriver configures a health check on the configured storage
   349  	// driver
   350  	StorageDriver struct {
   351  		// Enabled turns on the health check for the storage driver
   352  		Enabled bool `yaml:"enabled,omitempty"`
   353  		// Interval is the duration in between checks
   354  		Interval time.Duration `yaml:"interval,omitempty"`
   355  		// Threshold is the number of times a check must fail to trigger an
   356  		// unhealthy state
   357  		Threshold int `yaml:"threshold,omitempty"`
   358  	} `yaml:"storagedriver,omitempty"`
   359  }
   360  
   361  // v0_1Configuration is a Version 0.1 Configuration struct
   362  // This is currently aliased to Configuration, as it is the current version
   363  type v0_1Configuration Configuration
   364  
   365  // UnmarshalYAML implements the yaml.Unmarshaler interface
   366  // Unmarshals a string of the form X.Y into a Version, validating that X and Y can represent unsigned integers
   367  func (version *Version) UnmarshalYAML(unmarshal func(interface{}) error) error {
   368  	var versionString string
   369  	err := unmarshal(&versionString)
   370  	if err != nil {
   371  		return err
   372  	}
   373  
   374  	newVersion := Version(versionString)
   375  	if _, err := newVersion.major(); err != nil {
   376  		return err
   377  	}
   378  
   379  	if _, err := newVersion.minor(); err != nil {
   380  		return err
   381  	}
   382  
   383  	*version = newVersion
   384  	return nil
   385  }
   386  
   387  // CurrentVersion is the most recent Version that can be parsed
   388  var CurrentVersion = MajorMinorVersion(0, 1)
   389  
   390  // Loglevel is the level at which operations are logged
   391  // This can be error, warn, info, or debug
   392  type Loglevel string
   393  
   394  // UnmarshalYAML implements the yaml.Umarshaler interface
   395  // Unmarshals a string into a Loglevel, lowercasing the string and validating that it represents a
   396  // valid loglevel
   397  func (loglevel *Loglevel) UnmarshalYAML(unmarshal func(interface{}) error) error {
   398  	var loglevelString string
   399  	err := unmarshal(&loglevelString)
   400  	if err != nil {
   401  		return err
   402  	}
   403  
   404  	loglevelString = strings.ToLower(loglevelString)
   405  	switch loglevelString {
   406  	case "error", "warn", "info", "debug":
   407  	default:
   408  		return fmt.Errorf("invalid loglevel %s Must be one of [error, warn, info, debug]", loglevelString)
   409  	}
   410  
   411  	*loglevel = Loglevel(loglevelString)
   412  	return nil
   413  }
   414  
   415  // Parameters defines a key-value parameters mapping
   416  type Parameters map[string]interface{}
   417  
   418  // Storage defines the configuration for registry object storage
   419  type Storage map[string]Parameters
   420  
   421  // Type returns the storage driver type, such as filesystem or s3
   422  func (storage Storage) Type() string {
   423  	var storageType []string
   424  
   425  	// Return only key in this map
   426  	for k := range storage {
   427  		switch k {
   428  		case "maintenance":
   429  			// allow configuration of maintenance
   430  		case "cache":
   431  			// allow configuration of caching
   432  		case "delete":
   433  			// allow configuration of delete
   434  		case "redirect":
   435  			// allow configuration of redirect
   436  		default:
   437  			storageType = append(storageType, k)
   438  		}
   439  	}
   440  	if len(storageType) > 1 {
   441  		panic("multiple storage drivers specified in configuration or environment: " + strings.Join(storageType, ", "))
   442  	}
   443  	if len(storageType) == 1 {
   444  		return storageType[0]
   445  	}
   446  	return ""
   447  }
   448  
   449  // Parameters returns the Parameters map for a Storage configuration
   450  func (storage Storage) Parameters() Parameters {
   451  	return storage[storage.Type()]
   452  }
   453  
   454  // setParameter changes the parameter at the provided key to the new value
   455  func (storage Storage) setParameter(key string, value interface{}) {
   456  	storage[storage.Type()][key] = value
   457  }
   458  
   459  // UnmarshalYAML implements the yaml.Unmarshaler interface
   460  // Unmarshals a single item map into a Storage or a string into a Storage type with no parameters
   461  func (storage *Storage) UnmarshalYAML(unmarshal func(interface{}) error) error {
   462  	var storageMap map[string]Parameters
   463  	err := unmarshal(&storageMap)
   464  	if err == nil {
   465  		if len(storageMap) > 1 {
   466  			types := make([]string, 0, len(storageMap))
   467  			for k := range storageMap {
   468  				switch k {
   469  				case "maintenance":
   470  					// allow for configuration of maintenance
   471  				case "cache":
   472  					// allow configuration of caching
   473  				case "delete":
   474  					// allow configuration of delete
   475  				case "redirect":
   476  					// allow configuration of redirect
   477  				default:
   478  					types = append(types, k)
   479  				}
   480  			}
   481  
   482  			if len(types) > 1 {
   483  				return fmt.Errorf("must provide exactly one storage type. Provided: %v", types)
   484  			}
   485  		}
   486  		*storage = storageMap
   487  		return nil
   488  	}
   489  
   490  	var storageType string
   491  	err = unmarshal(&storageType)
   492  	if err == nil {
   493  		*storage = Storage{storageType: Parameters{}}
   494  		return nil
   495  	}
   496  
   497  	return err
   498  }
   499  
   500  // MarshalYAML implements the yaml.Marshaler interface
   501  func (storage Storage) MarshalYAML() (interface{}, error) {
   502  	if storage.Parameters() == nil {
   503  		return storage.Type(), nil
   504  	}
   505  	return map[string]Parameters(storage), nil
   506  }
   507  
   508  // Auth defines the configuration for registry authorization.
   509  type Auth map[string]Parameters
   510  
   511  // Type returns the auth type, such as htpasswd or token
   512  func (auth Auth) Type() string {
   513  	// Return only key in this map
   514  	for k := range auth {
   515  		return k
   516  	}
   517  	return ""
   518  }
   519  
   520  // Parameters returns the Parameters map for an Auth configuration
   521  func (auth Auth) Parameters() Parameters {
   522  	return auth[auth.Type()]
   523  }
   524  
   525  // setParameter changes the parameter at the provided key to the new value
   526  func (auth Auth) setParameter(key string, value interface{}) {
   527  	auth[auth.Type()][key] = value
   528  }
   529  
   530  // UnmarshalYAML implements the yaml.Unmarshaler interface
   531  // Unmarshals a single item map into a Storage or a string into a Storage type with no parameters
   532  func (auth *Auth) UnmarshalYAML(unmarshal func(interface{}) error) error {
   533  	var m map[string]Parameters
   534  	err := unmarshal(&m)
   535  	if err == nil {
   536  		if len(m) > 1 {
   537  			types := make([]string, 0, len(m))
   538  			for k := range m {
   539  				types = append(types, k)
   540  			}
   541  
   542  			// TODO(stevvooe): May want to change this slightly for
   543  			// authorization to allow multiple challenges.
   544  			return fmt.Errorf("must provide exactly one type. Provided: %v", types)
   545  
   546  		}
   547  		*auth = m
   548  		return nil
   549  	}
   550  
   551  	var authType string
   552  	err = unmarshal(&authType)
   553  	if err == nil {
   554  		*auth = Auth{authType: Parameters{}}
   555  		return nil
   556  	}
   557  
   558  	return err
   559  }
   560  
   561  // MarshalYAML implements the yaml.Marshaler interface
   562  func (auth Auth) MarshalYAML() (interface{}, error) {
   563  	if auth.Parameters() == nil {
   564  		return auth.Type(), nil
   565  	}
   566  	return map[string]Parameters(auth), nil
   567  }
   568  
   569  // Notifications configures multiple http endpoints.
   570  type Notifications struct {
   571  	// EventConfig is the configuration for the event format that is sent to each Endpoint.
   572  	EventConfig Events `yaml:"events,omitempty"`
   573  	// Endpoints is a list of http configurations for endpoints that
   574  	// respond to webhook notifications. In the future, we may allow other
   575  	// kinds of endpoints, such as external queues.
   576  	Endpoints []Endpoint `yaml:"endpoints,omitempty"`
   577  }
   578  
   579  // Endpoint describes the configuration of an http webhook notification
   580  // endpoint.
   581  type Endpoint struct {
   582  	Name              string        `yaml:"name"`              // identifies the endpoint in the registry instance.
   583  	Disabled          bool          `yaml:"disabled"`          // disables the endpoint
   584  	URL               string        `yaml:"url"`               // post url for the endpoint.
   585  	Headers           http.Header   `yaml:"headers"`           // static headers that should be added to all requests
   586  	Timeout           time.Duration `yaml:"timeout"`           // HTTP timeout
   587  	Threshold         int           `yaml:"threshold"`         // circuit breaker threshold before backing off on failure
   588  	Backoff           time.Duration `yaml:"backoff"`           // backoff duration
   589  	IgnoredMediaTypes []string      `yaml:"ignoredmediatypes"` // target media types to ignore
   590  	Ignore            Ignore        `yaml:"ignore"`            // ignore event types
   591  }
   592  
   593  // Events configures notification events.
   594  type Events struct {
   595  	IncludeReferences bool `yaml:"includereferences"` // include reference data in manifest events
   596  }
   597  
   598  // Ignore configures mediaTypes and actions of the event, that it won't be propagated
   599  type Ignore struct {
   600  	MediaTypes []string `yaml:"mediatypes"` // target media types to ignore
   601  	Actions    []string `yaml:"actions"`    // ignore action types
   602  }
   603  
   604  // Reporting defines error reporting methods.
   605  type Reporting struct {
   606  	// Bugsnag configures error reporting for Bugsnag (bugsnag.com).
   607  	Bugsnag BugsnagReporting `yaml:"bugsnag,omitempty"`
   608  	// NewRelic configures error reporting for NewRelic (newrelic.com)
   609  	NewRelic NewRelicReporting `yaml:"newrelic,omitempty"`
   610  }
   611  
   612  // BugsnagReporting configures error reporting for Bugsnag (bugsnag.com).
   613  type BugsnagReporting struct {
   614  	// APIKey is the Bugsnag api key.
   615  	APIKey string `yaml:"apikey,omitempty"`
   616  	// ReleaseStage tracks where the registry is deployed.
   617  	// Examples: production, staging, development
   618  	ReleaseStage string `yaml:"releasestage,omitempty"`
   619  	// Endpoint is used for specifying an enterprise Bugsnag endpoint.
   620  	Endpoint string `yaml:"endpoint,omitempty"`
   621  }
   622  
   623  // NewRelicReporting configures error reporting for NewRelic (newrelic.com)
   624  type NewRelicReporting struct {
   625  	// LicenseKey is the NewRelic user license key
   626  	LicenseKey string `yaml:"licensekey,omitempty"`
   627  	// Name is the component name of the registry in NewRelic
   628  	Name string `yaml:"name,omitempty"`
   629  	// Verbose configures debug output to STDOUT
   630  	Verbose bool `yaml:"verbose,omitempty"`
   631  }
   632  
   633  // Middleware configures named middlewares to be applied at injection points.
   634  type Middleware struct {
   635  	// Name the middleware registers itself as
   636  	Name string `yaml:"name"`
   637  	// Flag to disable middleware easily
   638  	Disabled bool `yaml:"disabled,omitempty"`
   639  	// Map of parameters that will be passed to the middleware's initialization function
   640  	Options Parameters `yaml:"options"`
   641  }
   642  
   643  // Proxy configures the registry as a pull through cache
   644  type Proxy struct {
   645  	// RemoteURL is the URL of the remote registry
   646  	RemoteURL string `yaml:"remoteurl"`
   647  
   648  	// Username of the hub user
   649  	Username string `yaml:"username"`
   650  
   651  	// Password of the hub user
   652  	Password string `yaml:"password"`
   653  }
   654  
   655  // Parse parses an input configuration yaml document into a Configuration struct
   656  // This should generally be capable of handling old configuration format versions
   657  //
   658  // Environment variables may be used to override configuration parameters other than version,
   659  // following the scheme below:
   660  // Configuration.Abc may be replaced by the value of REGISTRY_ABC,
   661  // Configuration.Abc.Xyz may be replaced by the value of REGISTRY_ABC_XYZ, and so forth
   662  func Parse(rd io.Reader) (*Configuration, error) {
   663  	in, err := ioutil.ReadAll(rd)
   664  	if err != nil {
   665  		return nil, err
   666  	}
   667  
   668  	p := NewParser("registry", []VersionedParseInfo{
   669  		{
   670  			Version: MajorMinorVersion(0, 1),
   671  			ParseAs: reflect.TypeOf(v0_1Configuration{}),
   672  			ConversionFunc: func(c interface{}) (interface{}, error) {
   673  				if v0_1, ok := c.(*v0_1Configuration); ok {
   674  					if v0_1.Log.Level == Loglevel("") {
   675  						if v0_1.Loglevel != Loglevel("") {
   676  							v0_1.Log.Level = v0_1.Loglevel
   677  						} else {
   678  							v0_1.Log.Level = Loglevel("info")
   679  						}
   680  					}
   681  					if v0_1.Loglevel != Loglevel("") {
   682  						v0_1.Loglevel = Loglevel("")
   683  					}
   684  
   685  					if v0_1.Catalog.MaxEntries <= 0 {
   686  						v0_1.Catalog.MaxEntries = 1000
   687  					}
   688  
   689  					if v0_1.Storage.Type() == "" {
   690  						return nil, errors.New("no storage configuration provided")
   691  					}
   692  					return (*Configuration)(v0_1), nil
   693  				}
   694  				return nil, fmt.Errorf("expected *v0_1Configuration, received %#v", c)
   695  			},
   696  		},
   697  	})
   698  
   699  	config := new(Configuration)
   700  	err = p.Parse(in, config)
   701  	if err != nil {
   702  		return nil, err
   703  	}
   704  
   705  	return config, nil
   706  }
   707  

View as plain text