Deprecating ResolveRepositoryName
Passing RepositoryInfo to ResolveAuthConfig, pullRepository, and pushRepository Moving --registry-mirror configuration to registry config Created resolve_repository job Repo names with 'index.docker.io' or 'docker.io' are now synonymous with omitting an index name. Adding test for RepositoryInfo Adding tests for opts.StringSetOpts and registry.ValidateMirror Fixing search term use of repoInfo Adding integration tests for registry mirror configuration Normalizing LookupImage image name to match LocalName parsing rules Normalizing repository LocalName to avoid multiple references to an official image Removing errorOut use in tests Removing TODO comment gofmt changes golint comments cleanup. renaming RegistryOptions => registry.Options, and RegistryServiceConfig => registry.ServiceConfig Splitting out builtins.Registry and registry.NewService calls Stray whitespace cleanup Moving integration tests for Mirrors and InsecureRegistries into TestNewIndexInfo unit test Factoring out ValidateRepositoryName from NewRepositoryInfo Removing unused IndexServerURL Allowing json marshaling of ServiceConfig. Exposing ServiceConfig in /info Switching to CamelCase for json marshaling PR cleanup; removing 'Is' prefix from boolean members. Removing unneeded json tags. Removing non-cleanup related fix for 'localhost:[port]' in splitReposName Merge fixes for gh9735 Fixing integration test Reapplying #9754 Adding comment on config.IndexConfigs use from isSecureIndex Remove unused error return value from isSecureIndex Signed-off-by: Don Kjer <don.kjer@gmail.com> Adding back comment in isSecureIndex Signed-off-by: Don Kjer <don.kjer@gmail.com>
This commit is contained in:
parent
eb9ddb7b86
commit
64b000c3ea
11 changed files with 1179 additions and 156 deletions
165
docs/registry.go
165
docs/registry.go
|
@ -25,6 +25,7 @@ var (
|
|||
errLoginRequired = errors.New("Authentication is required.")
|
||||
validNamespaceChars = regexp.MustCompile(`^([a-z0-9-_]*)$`)
|
||||
validRepo = regexp.MustCompile(`^([a-z0-9-_.]+)$`)
|
||||
emptyServiceConfig = NewServiceConfig(nil)
|
||||
)
|
||||
|
||||
type TimeoutType uint32
|
||||
|
@ -160,12 +161,12 @@ func doRequest(req *http.Request, jar http.CookieJar, timeout TimeoutType, secur
|
|||
return res, client, err
|
||||
}
|
||||
|
||||
func validateRepositoryName(repositoryName string) error {
|
||||
func validateRemoteName(remoteName string) error {
|
||||
var (
|
||||
namespace string
|
||||
name string
|
||||
)
|
||||
nameParts := strings.SplitN(repositoryName, "/", 2)
|
||||
nameParts := strings.SplitN(remoteName, "/", 2)
|
||||
if len(nameParts) < 2 {
|
||||
namespace = "library"
|
||||
name = nameParts[0]
|
||||
|
@ -196,29 +197,147 @@ func validateRepositoryName(repositoryName string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Resolves a repository name to a hostname + name
|
||||
func ResolveRepositoryName(reposName string) (string, string, error) {
|
||||
if strings.Contains(reposName, "://") {
|
||||
// It cannot contain a scheme!
|
||||
return "", "", ErrInvalidRepositoryName
|
||||
}
|
||||
nameParts := strings.SplitN(reposName, "/", 2)
|
||||
if len(nameParts) == 1 || (!strings.Contains(nameParts[0], ".") && !strings.Contains(nameParts[0], ":") &&
|
||||
nameParts[0] != "localhost") {
|
||||
// This is a Docker Index repos (ex: samalba/hipache or ubuntu)
|
||||
err := validateRepositoryName(reposName)
|
||||
return IndexServerAddress(), reposName, err
|
||||
}
|
||||
hostname := nameParts[0]
|
||||
reposName = nameParts[1]
|
||||
if strings.Contains(hostname, "index.docker.io") {
|
||||
return "", "", fmt.Errorf("Invalid repository name, try \"%s\" instead", reposName)
|
||||
}
|
||||
if err := validateRepositoryName(reposName); err != nil {
|
||||
return "", "", err
|
||||
// NewIndexInfo returns IndexInfo configuration from indexName
|
||||
func NewIndexInfo(config *ServiceConfig, indexName string) (*IndexInfo, error) {
|
||||
var err error
|
||||
indexName, err = ValidateIndexName(indexName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return hostname, reposName, nil
|
||||
// Return any configured index info, first.
|
||||
if index, ok := config.IndexConfigs[indexName]; ok {
|
||||
return index, nil
|
||||
}
|
||||
|
||||
// Construct a non-configured index info.
|
||||
index := &IndexInfo{
|
||||
Name: indexName,
|
||||
Mirrors: make([]string, 0),
|
||||
Official: false,
|
||||
}
|
||||
index.Secure = config.isSecureIndex(indexName)
|
||||
return index, nil
|
||||
}
|
||||
|
||||
func validateNoSchema(reposName string) error {
|
||||
if strings.Contains(reposName, "://") {
|
||||
// It cannot contain a scheme!
|
||||
return ErrInvalidRepositoryName
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// splitReposName breaks a reposName into an index name and remote name
|
||||
func splitReposName(reposName string) (string, string) {
|
||||
nameParts := strings.SplitN(reposName, "/", 2)
|
||||
var indexName, remoteName string
|
||||
if len(nameParts) == 1 || (!strings.Contains(nameParts[0], ".") &&
|
||||
!strings.Contains(nameParts[0], ":") && nameParts[0] != "localhost") {
|
||||
// This is a Docker Index repos (ex: samalba/hipache or ubuntu)
|
||||
// 'docker.io'
|
||||
indexName = IndexServerName()
|
||||
remoteName = reposName
|
||||
} else {
|
||||
indexName = nameParts[0]
|
||||
remoteName = nameParts[1]
|
||||
}
|
||||
return indexName, remoteName
|
||||
}
|
||||
|
||||
// NewRepositoryInfo validates and breaks down a repository name into a RepositoryInfo
|
||||
func NewRepositoryInfo(config *ServiceConfig, reposName string) (*RepositoryInfo, error) {
|
||||
if err := validateNoSchema(reposName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
indexName, remoteName := splitReposName(reposName)
|
||||
if err := validateRemoteName(remoteName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repoInfo := &RepositoryInfo{
|
||||
RemoteName: remoteName,
|
||||
}
|
||||
|
||||
var err error
|
||||
repoInfo.Index, err = NewIndexInfo(config, indexName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if repoInfo.Index.Official {
|
||||
normalizedName := repoInfo.RemoteName
|
||||
if strings.HasPrefix(normalizedName, "library/") {
|
||||
// If pull "library/foo", it's stored locally under "foo"
|
||||
normalizedName = strings.SplitN(normalizedName, "/", 2)[1]
|
||||
}
|
||||
|
||||
repoInfo.LocalName = normalizedName
|
||||
repoInfo.RemoteName = normalizedName
|
||||
// If the normalized name does not contain a '/' (e.g. "foo")
|
||||
// then it is an official repo.
|
||||
if strings.IndexRune(normalizedName, '/') == -1 {
|
||||
repoInfo.Official = true
|
||||
// Fix up remote name for official repos.
|
||||
repoInfo.RemoteName = "library/" + normalizedName
|
||||
}
|
||||
|
||||
// *TODO: Prefix this with 'docker.io/'.
|
||||
repoInfo.CanonicalName = repoInfo.LocalName
|
||||
} else {
|
||||
// *TODO: Decouple index name from hostname (via registry configuration?)
|
||||
repoInfo.LocalName = repoInfo.Index.Name + "/" + repoInfo.RemoteName
|
||||
repoInfo.CanonicalName = repoInfo.LocalName
|
||||
}
|
||||
return repoInfo, nil
|
||||
}
|
||||
|
||||
// ValidateRepositoryName validates a repository name
|
||||
func ValidateRepositoryName(reposName string) error {
|
||||
var err error
|
||||
if err = validateNoSchema(reposName); err != nil {
|
||||
return err
|
||||
}
|
||||
indexName, remoteName := splitReposName(reposName)
|
||||
if _, err = ValidateIndexName(indexName); err != nil {
|
||||
return err
|
||||
}
|
||||
return validateRemoteName(remoteName)
|
||||
}
|
||||
|
||||
// ParseRepositoryInfo performs the breakdown of a repository name into a RepositoryInfo, but
|
||||
// lacks registry configuration.
|
||||
func ParseRepositoryInfo(reposName string) (*RepositoryInfo, error) {
|
||||
return NewRepositoryInfo(emptyServiceConfig, reposName)
|
||||
}
|
||||
|
||||
// NormalizeLocalName transforms a repository name into a normalize LocalName
|
||||
// Passes through the name without transformation on error (image id, etc)
|
||||
func NormalizeLocalName(name string) string {
|
||||
repoInfo, err := ParseRepositoryInfo(name)
|
||||
if err != nil {
|
||||
return name
|
||||
}
|
||||
return repoInfo.LocalName
|
||||
}
|
||||
|
||||
// GetAuthConfigKey special-cases using the full index address of the official
|
||||
// index as the AuthConfig key, and uses the (host)name[:port] for private indexes.
|
||||
func (index *IndexInfo) GetAuthConfigKey() string {
|
||||
if index.Official {
|
||||
return IndexServerAddress()
|
||||
}
|
||||
return index.Name
|
||||
}
|
||||
|
||||
// GetSearchTerm special-cases using local name for official index, and
|
||||
// remote name for private indexes.
|
||||
func (repoInfo *RepositoryInfo) GetSearchTerm() string {
|
||||
if repoInfo.Index.Official {
|
||||
return repoInfo.LocalName
|
||||
}
|
||||
return repoInfo.RemoteName
|
||||
}
|
||||
|
||||
func trustedLocation(req *http.Request) bool {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue