github.com/cloudfoundry-attic/ltc@v0.0.0-20151123212628-098adc7919fc/docker_runner/docker_repository_name_formatter/docker_repository_name_formatter.go (about)

     1  package docker_repository_name_formatter
     2  
     3  import (
     4  	"fmt"
     5  	"net/url"
     6  	"strings"
     7  
     8  	"github.com/docker/docker/registry"
     9  )
    10  
    11  const (
    12  	DockerScheme      = "docker"
    13  	DockerIndexServer = "docker.io"
    14  )
    15  
    16  func FormatForReceptor(dockerPath string) (string, error) {
    17  	return convertDockerURI(dockerPath)
    18  }
    19  
    20  func ParseRepoNameAndTagFromImageReference(dockerPath string) (string, string, string, error) {
    21  	return parseDockerRepoUrl(dockerPath)
    22  }
    23  
    24  func convertDockerURI(dockerURI string) (string, error) {
    25  	if strings.Contains(dockerURI, "://") {
    26  		return "", fmt.Errorf("docker URI [%s] should not contain scheme", dockerURI)
    27  	}
    28  
    29  	indexName, remoteName, tag, err := parseDockerRepoUrl(dockerURI)
    30  	if err != nil {
    31  		return "", err
    32  	}
    33  
    34  	return (&url.URL{
    35  		Scheme:   DockerScheme,
    36  		Path:     indexName + "/" + remoteName,
    37  		Fragment: tag,
    38  	}).String(), nil
    39  }
    40  
    41  // via https://github.com/docker/docker/blob/a271eaeba224652e3a12af0287afbae6f82a9333/registry/config.go#L295
    42  func parseDockerRepoUrl(dockerURI string) (indexName, remoteName, tag string, err error) {
    43  	nameParts := strings.SplitN(dockerURI, "/", 2)
    44  
    45  	if officialRegistry(nameParts) {
    46  		// URI without host
    47  		indexName = ""
    48  		remoteName = dockerURI
    49  
    50  		// URI has format docker.io/<path>
    51  		if nameParts[0] == DockerIndexServer {
    52  			indexName = DockerIndexServer
    53  			remoteName = nameParts[1]
    54  		}
    55  
    56  		// Remote name contain no '/' - prefix it with "library/"
    57  		// via https://github.com/docker/docker/blob/a271eaeba224652e3a12af0287afbae6f82a9333/registry/config.go#L343
    58  		if strings.IndexRune(remoteName, '/') == -1 {
    59  			remoteName = "library/" + remoteName
    60  		}
    61  	} else {
    62  		indexName = nameParts[0]
    63  		remoteName = nameParts[1]
    64  	}
    65  
    66  	remoteName, tag = parseDockerRepositoryTag(remoteName)
    67  
    68  	_, err = registry.ParseRepositoryInfo(remoteName)
    69  	if err != nil {
    70  		return "", "", "", err
    71  	}
    72  
    73  	return indexName, remoteName, tag, nil
    74  }
    75  
    76  func officialRegistry(nameParts []string) bool {
    77  	return len(nameParts) == 1 ||
    78  		nameParts[0] == DockerIndexServer ||
    79  		(!strings.Contains(nameParts[0], ".") &&
    80  			!strings.Contains(nameParts[0], ":") &&
    81  			nameParts[0] != "localhost")
    82  }
    83  
    84  // via https://github.com/docker/docker/blob/4398108/pkg/parsers/parsers.go#L72
    85  func parseDockerRepositoryTag(remoteName string) (string, string) {
    86  	n := strings.LastIndex(remoteName, ":")
    87  	if n < 0 {
    88  		return remoteName, "latest" // before:  remoteName, ""
    89  	}
    90  
    91  	if tag := remoteName[n+1:]; !strings.Contains(tag, "/") {
    92  		return remoteName[:n], tag
    93  	}
    94  
    95  	return remoteName, ""
    96  }