github.com/cvmfs/docker-graphdriver@v0.0.0-20181206110523-155ec6df0521/repository-manager/lib/parse.go (about) 1 package lib 2 3 import ( 4 "fmt" 5 "net/url" 6 "strings" 7 ) 8 9 func ParseImage(image string) (img Image, err error) { 10 url, err := url.Parse(image) 11 if err != nil { 12 return Image{}, err 13 } 14 if url.Host == "" { 15 return Image{}, fmt.Errorf("Impossible to identify the registry of the image: %s", image) 16 } 17 if url.Path == "" { 18 return Image{}, fmt.Errorf("Impossible to identify the repository of the image: %s", image) 19 } 20 colonPathSplitted := strings.Split(url.Path, ":") 21 if len(colonPathSplitted) == 0 { 22 return Image{}, fmt.Errorf("Impossible to identify the path of the image: %s", image) 23 } 24 // no split happened, hence we don't have neither a tag nor a digest, but only a path 25 if len(colonPathSplitted) == 1 { 26 27 // we remove the first and the trailing `/` 28 repository := strings.TrimLeft(colonPathSplitted[0], "/") 29 repository = strings.TrimRight(repository, "/") 30 if repository == "" { 31 return Image{}, fmt.Errorf("Impossible to find the repository for: %s", image) 32 } 33 return Image{ 34 Scheme: url.Scheme, 35 Registry: url.Host, 36 Repository: repository, 37 }, nil 38 39 } 40 if len(colonPathSplitted) > 3 { 41 fmt.Println(colonPathSplitted) 42 return Image{}, fmt.Errorf("Impossible to parse the string into an image, too many `:` in : %s", image) 43 } 44 // the colon `:` is used also as separator in the digest between sha256 45 // and the actuall digest, a len(pathSplitted) == 2 could either means 46 // a repository and a tag or a repository and an hash, in the case of 47 // the hash however the split will be more complex. Now we split for 48 // the at `@` which separate the digest from everything else. If this 49 // split produce only one result we have a repository and maybe a tag, 50 // if it produce two we have a repository, maybe a tag and definitely a 51 // digest, if it produce more than two we have an error. 52 atPathSplitted := strings.Split(url.Path, "@") 53 if len(atPathSplitted) > 2 { 54 return Image{}, fmt.Errorf("To many `@` in the image name: %s", image) 55 } 56 var repoTag, digest string 57 if len(atPathSplitted) == 2 { 58 digest = atPathSplitted[1] 59 repoTag = atPathSplitted[0] 60 } 61 if len(atPathSplitted) == 1 { 62 repoTag = atPathSplitted[0] 63 } 64 // finally we break up also the repoTag to find out if we have also a 65 // tag or just a repository name 66 colonRepoTagSplitted := strings.Split(repoTag, ":") 67 68 // only the repository, without the tag 69 if len(colonRepoTagSplitted) == 1 { 70 repository := strings.TrimLeft(colonRepoTagSplitted[0], "/") 71 repository = strings.TrimRight(repository, "/") 72 if repository == "" { 73 return Image{}, fmt.Errorf("Impossible to find the repository for: %s", image) 74 } 75 return Image{ 76 Scheme: url.Scheme, 77 Registry: url.Host, 78 Repository: repository, 79 Digest: digest, 80 }, nil 81 } 82 83 // both repository and tag 84 if len(colonRepoTagSplitted) == 2 { 85 repository := strings.TrimLeft(colonRepoTagSplitted[0], "/") 86 repository = strings.TrimRight(repository, "/") 87 if repository == "" { 88 return Image{}, fmt.Errorf("Impossible to find the repository for: %s", image) 89 } 90 return Image{ 91 Scheme: url.Scheme, 92 Registry: url.Host, 93 Repository: repository, 94 Tag: colonRepoTagSplitted[1], 95 Digest: digest, 96 }, nil 97 } 98 return Image{}, fmt.Errorf("Impossible to parse the image: %s", image) 99 }