diff --git a/docs/config.go b/docs/config.go index 7d8b6301a..ab6f07158 100644 --- a/docs/config.go +++ b/docs/config.go @@ -13,10 +13,20 @@ import ( registrytypes "github.com/docker/engine-api/types/registry" ) -// Options holds command line options. -type Options struct { - Mirrors opts.ListOpts - InsecureRegistries opts.ListOpts +// ServiceOptions holds command line options. +type ServiceOptions struct { + Mirrors []string `json:"registry-mirrors,omitempty"` + 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 ( @@ -42,51 +52,45 @@ var ( // not have the correct form ErrInvalidRepositoryName = errors.New("Invalid repository name (ex: \"registry.domain.tld/myrepos\")") - emptyServiceConfig = NewServiceConfig(nil) - - // 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 + emptyServiceConfig = newServiceConfig(ServiceOptions{}) ) // for mocking in unit tests 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. -func (options *Options) InstallFlags(cmd *flag.FlagSet, usageFn func(string) string) { - options.Mirrors = opts.NewListOpts(ValidateMirror) - cmd.Var(&options.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")) - cmd.BoolVar(&V2Only, []string{"-disable-legacy-registry"}, false, usageFn("Do not contact legacy registries")) +func (options *ServiceOptions) InstallCliFlags(cmd *flag.FlagSet, usageFn func(string) string) { + mirrors := opts.NewNamedListOptsRef("registry-mirrors", &options.Mirrors, ValidateMirror) + cmd.Var(mirrors, []string{"-registry-mirror"}, usageFn("Preferred Docker registry mirror")) + + insecureRegistries := opts.NewNamedListOptsRef("insecure-registries", &options.InsecureRegistries, ValidateIndexName) + 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 -func NewServiceConfig(options *Options) *registrytypes.ServiceConfig { - if options == nil { - options = &Options{ - Mirrors: opts.NewListOpts(nil), - InsecureRegistries: opts.NewListOpts(nil), - } - } - +// newServiceConfig returns a new instance of ServiceConfig +func newServiceConfig(options ServiceOptions) *serviceConfig { // 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). // // TODO: should we deprecate this once it is easier for people to set up a TLS registry or change // daemon flags on boot2docker? - options.InsecureRegistries.Set("127.0.0.0/8") + options.InsecureRegistries = append(options.InsecureRegistries, "127.0.0.0/8") - config := ®istrytypes.ServiceConfig{ - InsecureRegistryCIDRs: make([]*registrytypes.NetIPNet, 0), - IndexConfigs: make(map[string]*registrytypes.IndexInfo, 0), - // Hack: Bypass setting the mirrors to IndexConfigs since they are going away - // and Mirrors are only for the official registry anyways. - Mirrors: options.Mirrors.GetAll(), + config := &serviceConfig{ + ServiceConfig: registrytypes.ServiceConfig{ + InsecureRegistryCIDRs: make([]*registrytypes.NetIPNet, 0), + IndexConfigs: make(map[string]*registrytypes.IndexInfo, 0), + // Hack: Bypass setting the mirrors to IndexConfigs since they are going away + // and Mirrors are only for the official registry anyways. + Mirrors: options.Mirrors, + }, + V2Only: options.V2Only, } // 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 _, ipnet, err := net.ParseCIDR(r) 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 // in a subnet. If the resolving is not successful, isSecureIndex will only try to match hostname to any element // 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 // is called from anything besides newIndexInfo, in order to honor per-index configurations. if index, ok := config.IndexConfigs[indexName]; ok { @@ -201,7 +205,7 @@ func validateNoSchema(reposName string) error { } // 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 indexName, err = ValidateIndexName(indexName) if err != nil { @@ -233,7 +237,7 @@ func GetAuthConfigKey(index *registrytypes.IndexInfo) string { } // 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()) if err != nil { return nil, err diff --git a/docs/registry.go b/docs/registry.go index 9071d9dc1..8fdfe3b0a 100644 --- a/docs/registry.go +++ b/docs/registry.go @@ -11,7 +11,6 @@ import ( "net/http" "os" "path/filepath" - "runtime" "strings" "time" @@ -26,12 +25,6 @@ var ( ErrAlreadyExists = errors.New("Image already exists") ) -func init() { - if runtime.GOOS != "linux" { - V2Only = true - } -} - func newTLSConfig(hostname string, isSecure bool) (*tls.Config, error) { // PreferredServerCipherSuites should have no effect tlsConfig := tlsconfig.ServerDefault diff --git a/docs/registry_mock_test.go b/docs/registry_mock_test.go index 057afac10..828f48fc9 100644 --- a/docs/registry_mock_test.go +++ b/docs/registry_mock_test.go @@ -15,7 +15,6 @@ import ( "testing" "time" - "github.com/docker/docker/opts" "github.com/docker/docker/reference" registrytypes "github.com/docker/engine-api/types/registry" "github.com/gorilla/mux" @@ -174,23 +173,13 @@ func makePublicIndex() *registrytypes.IndexInfo { return index } -func makeServiceConfig(mirrors []string, insecureRegistries []string) *registrytypes.ServiceConfig { - options := &Options{ - Mirrors: opts.NewListOpts(nil), - InsecureRegistries: opts.NewListOpts(nil), - } - if mirrors != nil { - for _, mirror := range mirrors { - options.Mirrors.Set(mirror) - } - } - if insecureRegistries != nil { - for _, insecureRegistries := range insecureRegistries { - options.InsecureRegistries.Set(insecureRegistries) - } +func makeServiceConfig(mirrors []string, insecureRegistries []string) *serviceConfig { + options := ServiceOptions{ + Mirrors: mirrors, + InsecureRegistries: insecureRegistries, } - return NewServiceConfig(options) + return newServiceConfig(options) } func writeHeaders(w http.ResponseWriter) { diff --git a/docs/registry_test.go b/docs/registry_test.go index 02eb683d0..7f9cc8e4c 100644 --- a/docs/registry_test.go +++ b/docs/registry_test.go @@ -523,7 +523,7 @@ func TestParseRepositoryInfo(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 { index, err := newIndexInfo(config, indexName) if err != nil { @@ -537,7 +537,7 @@ func TestNewIndexInfo(t *testing.T) { } } - config := NewServiceConfig(nil) + config := newServiceConfig(ServiceOptions{}) noMirrors := []string{} expectedIndexInfos := map[string]*registrytypes.IndexInfo{ IndexName: { @@ -661,7 +661,7 @@ func TestMirrorEndpointLookup(t *testing.T) { } 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") if err != nil { diff --git a/docs/service.go b/docs/service.go index d9ea71b37..1439e9d7f 100644 --- a/docs/service.go +++ b/docs/service.go @@ -15,17 +15,22 @@ import ( // Service is a registry service. It tracks configuration data such as a list // of mirrors. type Service struct { - Config *registrytypes.ServiceConfig + config *serviceConfig } // NewService returns a new instance of Service ready to be // installed into an engine. -func NewService(options *Options) *Service { +func NewService(options ServiceOptions) *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, // and returns OK if authentication was successful. // 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) - index, err := newIndexInfo(s.Config, indexName) + index, err := newIndexInfo(s.config, indexName) if err != nil { 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 // and configuration of the associated registry. 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 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 @@ -138,7 +143,7 @@ func (e APIEndpoint) ToV1Endpoint(userAgent string, metaHeaders http.Header) (*V // TLSConfig constructs a client TLS configuration based on server defaults 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) { @@ -173,7 +178,7 @@ func (s *Service) lookupEndpoints(hostname string) (endpoints []APIEndpoint, err return nil, err } - if V2Only { + if s.config.V2Only { return endpoints, nil } diff --git a/docs/service_v2.go b/docs/service_v2.go index 9c909f186..744be691e 100644 --- a/docs/service_v2.go +++ b/docs/service_v2.go @@ -12,7 +12,7 @@ func (s *Service) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, e tlsConfig := &cfg if hostname == DefaultNamespace { // v2 mirrors - for _, mirror := range s.Config.Mirrors { + for _, mirror := range s.config.Mirrors { if !strings.HasPrefix(mirror, "http://") && !strings.HasPrefix(mirror, "https://") { mirror = "https://" + mirror }