github.com/apptainer/singularity@v3.1.1+incompatible/pkg/client/shub/util.go (about) 1 // Copyright (c) 2018, Sylabs Inc. All rights reserved. 2 // This software is licensed under a 3-clause BSD license. Please consult the 3 // LICENSE.md file distributed with the sources of this project regarding your 4 // rights to use or distribute this software. 5 6 package client 7 8 import ( 9 "errors" 10 "regexp" 11 "strings" 12 ) 13 14 // isShubPullRef returns true if the provided string is a valid Shub 15 // reference for a pull operation. 16 func isShubPullRef(shubRef string) bool { 17 // define regex for each URI component 18 registryRegexp := `([-.a-zA-Z0-9/]{1,64}\/)?` // target is very open, outside registry 19 nameRegexp := `([-a-zA-Z0-9]{1,39}\/)` // target valid github usernames 20 containerRegexp := `([-_.a-zA-Z0-9]{1,64})` // target valid github repo names 21 tagRegexp := `(:[-_.a-zA-Z0-9]{1,64})?` // target is very open, file extensions or branch names 22 digestRegexp := `((\@[a-f0-9]{32})|(\@[a-f0-9]{40}))?$` // target file md5 has, git commit hash, git branch 23 24 // expression is anchored 25 shubRegex, err := regexp.Compile(`^(shub://)` + registryRegexp + nameRegexp + containerRegexp + tagRegexp + digestRegexp + `$`) 26 if err != nil { 27 return false 28 } 29 30 found := shubRegex.FindString(shubRef) 31 32 // sanity check 33 // if found string is not equal to the input, input isn't a valid URI 34 if strings.Compare(shubRef, found) != 0 { 35 return false 36 } 37 38 return true 39 } 40 41 // shubParseReference accepts a valid Shub reference string and parses its content 42 // It will return an error if the given URI is not valid, 43 // otherwise it will parse the contents into a ShubURI struct 44 func shubParseReference(src string) (uri ShubURI, err error) { 45 ShubRef := strings.TrimPrefix(src, "shub://") 46 refParts := strings.Split(ShubRef, "/") 47 48 if l := len(refParts); l > 2 { 49 // more than two pieces indicates a custom registry 50 uri.registry = strings.Join(refParts[:l-2], "") + shubAPIRoute 51 uri.user = refParts[l-2] 52 src = refParts[l-1] 53 } else if l == 2 { 54 // two pieces means default registry 55 uri.registry = defaultRegistry + shubAPIRoute 56 uri.user = refParts[l-2] 57 src = refParts[l-1] 58 } else if l < 2 { 59 return ShubURI{}, errors.New("Not a valid Shub reference") 60 } 61 62 // look for an @ and split if it exists 63 if strings.Contains(src, `@`) { 64 refParts = strings.Split(src, `@`) 65 uri.digest = `@` + refParts[1] 66 src = refParts[0] 67 } 68 69 // look for a : and split if it exists 70 if strings.Contains(src, `:`) { 71 refParts = strings.Split(src, `:`) 72 uri.tag = `:` + refParts[1] 73 src = refParts[0] 74 } 75 76 // container name is left over after other parts are split from it 77 uri.container = src 78 79 if uri.tag == "" && uri.digest == "" { 80 uri.tag = ":latest" 81 } 82 83 return uri, nil 84 }