1package services 2 3import ( 4 "fmt" 5 "regexp" 6 "strings" 7 8 "github.com/docker/distribution/reference" 9) 10 11type Service struct { 12 Service string 13 Version string 14 ImageName string 15 Aliases []string 16} 17 18var referenceRegexpNoPort = regexp.MustCompile(`^(.*?)(|:[0-9]+)(|/.*)$`) 19 20const imageVersionLatest = "latest" 21 22// SplitNameAndVersion parses Docker registry image urls and constructs a struct with correct 23// image url, name, version and aliases 24func SplitNameAndVersion(serviceDescription string) Service { 25 // Try to find matches in e.g. subdomain.domain.tld:8080/namespace/service:version 26 matches := reference.ReferenceRegexp.FindStringSubmatch(serviceDescription) 27 if len(matches) == 0 { 28 return Service{ 29 ImageName: serviceDescription, 30 Version: imageVersionLatest, 31 } 32 } 33 34 // -> subdomain.domain.tld:8080/namespace/service 35 imageWithoutVersion := matches[1] 36 // -> version 37 imageVersion := matches[2] 38 39 registryMatches := referenceRegexpNoPort.FindStringSubmatch(imageWithoutVersion) 40 // -> subdomain.domain.tld 41 registry := registryMatches[1] 42 // -> /namespace/service 43 imageName := registryMatches[3] 44 45 service := Service{} 46 service.Service = registry + imageName 47 48 if len(imageVersion) > 0 { 49 service.ImageName = serviceDescription 50 service.Version = imageVersion 51 } else { 52 service.ImageName = fmt.Sprintf("%s:%s", imageWithoutVersion, imageVersionLatest) 53 service.Version = imageVersionLatest 54 } 55 56 alias := strings.ReplaceAll(service.Service, "/", "__") 57 service.Aliases = append(service.Aliases, alias) 58 59 // Create alternative link name according to RFC 1123 60 // Where you can use only `a-zA-Z0-9-` 61 alternativeName := strings.ReplaceAll(service.Service, "/", "-") 62 if alias != alternativeName { 63 service.Aliases = append(service.Aliases, alternativeName) 64 } 65 66 return service 67} 68