Move registry service options to the daemon configuration.

Allowing to set their values in the daemon configuration file.

Signed-off-by: David Calavera <david.calavera@gmail.com>
This commit is contained in:
David Calavera 2016-03-08 16:03:37 -05:00
parent 065ddf0186
commit 7caf33d6c5
6 changed files with 62 additions and 71 deletions

View file

@ -13,10 +13,20 @@ import (
registrytypes "github.com/docker/engine-api/types/registry" registrytypes "github.com/docker/engine-api/types/registry"
) )
// Options holds command line options. // ServiceOptions holds command line options.
type Options struct { type ServiceOptions struct {
Mirrors opts.ListOpts Mirrors []string `json:"registry-mirrors,omitempty"`
InsecureRegistries opts.ListOpts InsecureRegistries []string `json:"insecure-registries,omitempty"`
// V2Only controls access to legacy registries. If it is set to true via the
// command line flag the daemon will not attempt to contact v1 legacy registries
V2Only bool `json:"disable-legacy-registry,omitempty"`
}
// serviceConfig holds daemon configuration for the registry service.
type serviceConfig struct {
registrytypes.ServiceConfig
V2Only bool
} }
var ( var (
@ -42,51 +52,45 @@ var (
// not have the correct form // not have the correct form
ErrInvalidRepositoryName = errors.New("Invalid repository name (ex: \"registry.domain.tld/myrepos\")") ErrInvalidRepositoryName = errors.New("Invalid repository name (ex: \"registry.domain.tld/myrepos\")")
emptyServiceConfig = NewServiceConfig(nil) emptyServiceConfig = newServiceConfig(ServiceOptions{})
// V2Only controls access to legacy registries. If it is set to true via the
// command line flag the daemon will not attempt to contact v1 legacy registries
V2Only = false
) )
// for mocking in unit tests // for mocking in unit tests
var lookupIP = net.LookupIP var lookupIP = net.LookupIP
// InstallFlags adds command-line options to the top-level flag parser for // InstallCliFlags adds command-line options to the top-level flag parser for
// the current process. // the current process.
func (options *Options) InstallFlags(cmd *flag.FlagSet, usageFn func(string) string) { func (options *ServiceOptions) InstallCliFlags(cmd *flag.FlagSet, usageFn func(string) string) {
options.Mirrors = opts.NewListOpts(ValidateMirror) mirrors := opts.NewNamedListOptsRef("registry-mirrors", &options.Mirrors, ValidateMirror)
cmd.Var(&options.Mirrors, []string{"-registry-mirror"}, usageFn("Preferred Docker registry mirror")) cmd.Var(mirrors, []string{"-registry-mirror"}, usageFn("Preferred Docker registry mirror"))
options.InsecureRegistries = opts.NewListOpts(ValidateIndexName)
cmd.Var(&options.InsecureRegistries, []string{"-insecure-registry"}, usageFn("Enable insecure registry communication")) insecureRegistries := opts.NewNamedListOptsRef("insecure-registries", &options.InsecureRegistries, ValidateIndexName)
cmd.BoolVar(&V2Only, []string{"-disable-legacy-registry"}, false, usageFn("Do not contact legacy registries")) cmd.Var(insecureRegistries, []string{"-insecure-registry"}, usageFn("Enable insecure registry communication"))
cmd.BoolVar(&options.V2Only, []string{"-disable-legacy-registry"}, false, usageFn("Do not contact legacy registries"))
} }
// NewServiceConfig returns a new instance of ServiceConfig // newServiceConfig returns a new instance of ServiceConfig
func NewServiceConfig(options *Options) *registrytypes.ServiceConfig { func newServiceConfig(options ServiceOptions) *serviceConfig {
if options == nil {
options = &Options{
Mirrors: opts.NewListOpts(nil),
InsecureRegistries: opts.NewListOpts(nil),
}
}
// Localhost is by default considered as an insecure registry // Localhost is by default considered as an insecure registry
// This is a stop-gap for people who are running a private registry on localhost (especially on Boot2docker). // This is a stop-gap for people who are running a private registry on localhost (especially on Boot2docker).
// //
// TODO: should we deprecate this once it is easier for people to set up a TLS registry or change // TODO: should we deprecate this once it is easier for people to set up a TLS registry or change
// daemon flags on boot2docker? // daemon flags on boot2docker?
options.InsecureRegistries.Set("127.0.0.0/8") options.InsecureRegistries = append(options.InsecureRegistries, "127.0.0.0/8")
config := &registrytypes.ServiceConfig{ config := &serviceConfig{
InsecureRegistryCIDRs: make([]*registrytypes.NetIPNet, 0), ServiceConfig: registrytypes.ServiceConfig{
IndexConfigs: make(map[string]*registrytypes.IndexInfo, 0), InsecureRegistryCIDRs: make([]*registrytypes.NetIPNet, 0),
// Hack: Bypass setting the mirrors to IndexConfigs since they are going away IndexConfigs: make(map[string]*registrytypes.IndexInfo, 0),
// and Mirrors are only for the official registry anyways. // Hack: Bypass setting the mirrors to IndexConfigs since they are going away
Mirrors: options.Mirrors.GetAll(), // and Mirrors are only for the official registry anyways.
Mirrors: options.Mirrors,
},
V2Only: options.V2Only,
} }
// Split --insecure-registry into CIDR and registry-specific settings. // Split --insecure-registry into CIDR and registry-specific settings.
for _, r := range options.InsecureRegistries.GetAll() { for _, r := range options.InsecureRegistries {
// Check if CIDR was passed to --insecure-registry // Check if CIDR was passed to --insecure-registry
_, ipnet, err := net.ParseCIDR(r) _, ipnet, err := net.ParseCIDR(r)
if err == nil { if err == nil {
@ -125,7 +129,7 @@ func NewServiceConfig(options *Options) *registrytypes.ServiceConfig {
// or an IP address. If it is a domain name, then it will be resolved in order to check if the IP is contained // or an IP address. If it is a domain name, then it will be resolved in order to check if the IP is contained
// in a subnet. If the resolving is not successful, isSecureIndex will only try to match hostname to any element // in a subnet. If the resolving is not successful, isSecureIndex will only try to match hostname to any element
// of insecureRegistries. // of insecureRegistries.
func isSecureIndex(config *registrytypes.ServiceConfig, indexName string) bool { func isSecureIndex(config *serviceConfig, indexName string) bool {
// Check for configured index, first. This is needed in case isSecureIndex // Check for configured index, first. This is needed in case isSecureIndex
// is called from anything besides newIndexInfo, in order to honor per-index configurations. // is called from anything besides newIndexInfo, in order to honor per-index configurations.
if index, ok := config.IndexConfigs[indexName]; ok { if index, ok := config.IndexConfigs[indexName]; ok {
@ -201,7 +205,7 @@ func validateNoSchema(reposName string) error {
} }
// newIndexInfo returns IndexInfo configuration from indexName // newIndexInfo returns IndexInfo configuration from indexName
func newIndexInfo(config *registrytypes.ServiceConfig, indexName string) (*registrytypes.IndexInfo, error) { func newIndexInfo(config *serviceConfig, indexName string) (*registrytypes.IndexInfo, error) {
var err error var err error
indexName, err = ValidateIndexName(indexName) indexName, err = ValidateIndexName(indexName)
if err != nil { if err != nil {
@ -233,7 +237,7 @@ func GetAuthConfigKey(index *registrytypes.IndexInfo) string {
} }
// newRepositoryInfo validates and breaks down a repository name into a RepositoryInfo // newRepositoryInfo validates and breaks down a repository name into a RepositoryInfo
func newRepositoryInfo(config *registrytypes.ServiceConfig, name reference.Named) (*RepositoryInfo, error) { func newRepositoryInfo(config *serviceConfig, name reference.Named) (*RepositoryInfo, error) {
index, err := newIndexInfo(config, name.Hostname()) index, err := newIndexInfo(config, name.Hostname())
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -11,7 +11,6 @@ import (
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
"runtime"
"strings" "strings"
"time" "time"
@ -26,12 +25,6 @@ var (
ErrAlreadyExists = errors.New("Image already exists") ErrAlreadyExists = errors.New("Image already exists")
) )
func init() {
if runtime.GOOS != "linux" {
V2Only = true
}
}
func newTLSConfig(hostname string, isSecure bool) (*tls.Config, error) { func newTLSConfig(hostname string, isSecure bool) (*tls.Config, error) {
// PreferredServerCipherSuites should have no effect // PreferredServerCipherSuites should have no effect
tlsConfig := tlsconfig.ServerDefault tlsConfig := tlsconfig.ServerDefault

View file

@ -15,7 +15,6 @@ import (
"testing" "testing"
"time" "time"
"github.com/docker/docker/opts"
"github.com/docker/docker/reference" "github.com/docker/docker/reference"
registrytypes "github.com/docker/engine-api/types/registry" registrytypes "github.com/docker/engine-api/types/registry"
"github.com/gorilla/mux" "github.com/gorilla/mux"
@ -174,23 +173,13 @@ func makePublicIndex() *registrytypes.IndexInfo {
return index return index
} }
func makeServiceConfig(mirrors []string, insecureRegistries []string) *registrytypes.ServiceConfig { func makeServiceConfig(mirrors []string, insecureRegistries []string) *serviceConfig {
options := &Options{ options := ServiceOptions{
Mirrors: opts.NewListOpts(nil), Mirrors: mirrors,
InsecureRegistries: opts.NewListOpts(nil), InsecureRegistries: insecureRegistries,
}
if mirrors != nil {
for _, mirror := range mirrors {
options.Mirrors.Set(mirror)
}
}
if insecureRegistries != nil {
for _, insecureRegistries := range insecureRegistries {
options.InsecureRegistries.Set(insecureRegistries)
}
} }
return NewServiceConfig(options) return newServiceConfig(options)
} }
func writeHeaders(w http.ResponseWriter) { func writeHeaders(w http.ResponseWriter) {

View file

@ -523,7 +523,7 @@ func TestParseRepositoryInfo(t *testing.T) {
} }
func TestNewIndexInfo(t *testing.T) { func TestNewIndexInfo(t *testing.T) {
testIndexInfo := func(config *registrytypes.ServiceConfig, expectedIndexInfos map[string]*registrytypes.IndexInfo) { testIndexInfo := func(config *serviceConfig, expectedIndexInfos map[string]*registrytypes.IndexInfo) {
for indexName, expectedIndexInfo := range expectedIndexInfos { for indexName, expectedIndexInfo := range expectedIndexInfos {
index, err := newIndexInfo(config, indexName) index, err := newIndexInfo(config, indexName)
if err != nil { if err != nil {
@ -537,7 +537,7 @@ func TestNewIndexInfo(t *testing.T) {
} }
} }
config := NewServiceConfig(nil) config := newServiceConfig(ServiceOptions{})
noMirrors := []string{} noMirrors := []string{}
expectedIndexInfos := map[string]*registrytypes.IndexInfo{ expectedIndexInfos := map[string]*registrytypes.IndexInfo{
IndexName: { IndexName: {
@ -661,7 +661,7 @@ func TestMirrorEndpointLookup(t *testing.T) {
} }
return false return false
} }
s := Service{Config: makeServiceConfig([]string{"my.mirror"}, nil)} s := Service{config: makeServiceConfig([]string{"my.mirror"}, nil)}
imageName, err := reference.WithName(IndexName + "/test/image") imageName, err := reference.WithName(IndexName + "/test/image")
if err != nil { if err != nil {

View file

@ -15,17 +15,22 @@ import (
// Service is a registry service. It tracks configuration data such as a list // Service is a registry service. It tracks configuration data such as a list
// of mirrors. // of mirrors.
type Service struct { type Service struct {
Config *registrytypes.ServiceConfig config *serviceConfig
} }
// NewService returns a new instance of Service ready to be // NewService returns a new instance of Service ready to be
// installed into an engine. // installed into an engine.
func NewService(options *Options) *Service { func NewService(options ServiceOptions) *Service {
return &Service{ return &Service{
Config: NewServiceConfig(options), config: newServiceConfig(options),
} }
} }
// ServiceConfig returns the public registry service configuration.
func (s *Service) ServiceConfig() *registrytypes.ServiceConfig {
return &s.config.ServiceConfig
}
// Auth contacts the public registry with the provided credentials, // Auth contacts the public registry with the provided credentials,
// and returns OK if authentication was successful. // and returns OK if authentication was successful.
// It can be used to verify the validity of a client's credentials. // It can be used to verify the validity of a client's credentials.
@ -82,7 +87,7 @@ func (s *Service) Search(term string, authConfig *types.AuthConfig, userAgent st
indexName, remoteName := splitReposSearchTerm(term) indexName, remoteName := splitReposSearchTerm(term)
index, err := newIndexInfo(s.Config, indexName) index, err := newIndexInfo(s.config, indexName)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -113,12 +118,12 @@ func (s *Service) Search(term string, authConfig *types.AuthConfig, userAgent st
// ResolveRepository splits a repository name into its components // ResolveRepository splits a repository name into its components
// and configuration of the associated registry. // and configuration of the associated registry.
func (s *Service) ResolveRepository(name reference.Named) (*RepositoryInfo, error) { func (s *Service) ResolveRepository(name reference.Named) (*RepositoryInfo, error) {
return newRepositoryInfo(s.Config, name) return newRepositoryInfo(s.config, name)
} }
// ResolveIndex takes indexName and returns index info // ResolveIndex takes indexName and returns index info
func (s *Service) ResolveIndex(name string) (*registrytypes.IndexInfo, error) { func (s *Service) ResolveIndex(name string) (*registrytypes.IndexInfo, error) {
return newIndexInfo(s.Config, name) return newIndexInfo(s.config, name)
} }
// APIEndpoint represents a remote API endpoint // APIEndpoint represents a remote API endpoint
@ -138,7 +143,7 @@ func (e APIEndpoint) ToV1Endpoint(userAgent string, metaHeaders http.Header) (*V
// TLSConfig constructs a client TLS configuration based on server defaults // TLSConfig constructs a client TLS configuration based on server defaults
func (s *Service) TLSConfig(hostname string) (*tls.Config, error) { func (s *Service) TLSConfig(hostname string) (*tls.Config, error) {
return newTLSConfig(hostname, isSecureIndex(s.Config, hostname)) return newTLSConfig(hostname, isSecureIndex(s.config, hostname))
} }
func (s *Service) tlsConfigForMirror(mirrorURL *url.URL) (*tls.Config, error) { func (s *Service) tlsConfigForMirror(mirrorURL *url.URL) (*tls.Config, error) {
@ -173,7 +178,7 @@ func (s *Service) lookupEndpoints(hostname string) (endpoints []APIEndpoint, err
return nil, err return nil, err
} }
if V2Only { if s.config.V2Only {
return endpoints, nil return endpoints, nil
} }

View file

@ -12,7 +12,7 @@ func (s *Service) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, e
tlsConfig := &cfg tlsConfig := &cfg
if hostname == DefaultNamespace { if hostname == DefaultNamespace {
// v2 mirrors // v2 mirrors
for _, mirror := range s.Config.Mirrors { for _, mirror := range s.config.Mirrors {
if !strings.HasPrefix(mirror, "http://") && !strings.HasPrefix(mirror, "https://") { if !strings.HasPrefix(mirror, "http://") && !strings.HasPrefix(mirror, "https://") {
mirror = "https://" + mirror mirror = "https://" + mirror
} }