/
uri.go
115 lines (96 loc) · 2.89 KB
/
uri.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// Copyright (c) 2018, Sylabs Inc. All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the
// LICENSE.md file distributed with the sources of this project regarding your
// rights to use or distribute this software.
package uri
import (
"fmt"
"strings"
)
const (
// Library is the keyword for a library ref
Library = "library"
// Shub is the keyword for a shub ref
Shub = "shub"
// HTTP is the keyword for http ref
HTTP = "http"
// HTTPS is the keyword for https ref
HTTPS = "https"
)
// validURIs contains a list of known uris
var validURIs = map[string]bool{
"library": true,
"shub": true,
"docker": true,
"docker-archive": true,
"docker-daemon": true,
"oci": true,
"oci-archive": true,
"http": true,
"https": true,
}
// IsValid returns whether or not the given source is valid
func IsValid(source string) (valid bool, err error) {
u := strings.SplitN(source, ":", 2)
if len(u) != 2 {
return false, fmt.Errorf("Invalid URI %s", source)
}
if _, ok := validURIs[u[0]]; ok {
return true, nil
}
return false, fmt.Errorf("Invalid URI %s", source)
}
// GetName turns a transport:ref URI into a name containing the top-level identifier
// of the image. For example, docker://godlovedc/lolcow returns lolcow
//
// Returns "" when not in transport:ref format
func GetName(uri string) string {
transport, ref := Split(uri)
if transport == "" {
return ""
}
ref = strings.TrimLeft(ref, "/") // Trim leading "/" characters
refSplit := strings.Split(ref, "/") // Split ref into parts
if transport == HTTP || transport == HTTPS {
imageName := refSplit[len(refSplit)-1]
return imageName
}
// Default tag is latest
tags := []string{"latest"}
container := refSplit[len(refSplit)-1]
if strings.Contains(container, ":") {
imageParts := strings.Split(container, ":")
container = imageParts[0]
tags = []string{imageParts[1]}
if strings.Contains(tags[0], ",") {
tags = strings.Split(tags[0], ",")
}
}
return fmt.Sprintf("%s_%s.sif", container, tags[0])
}
// Split splits a URI into it's components which can be used directly through containers/image
//
// This can be tricky if there is no type but a file name contains a colon.
//
// Examples:
// docker://ubuntu -> docker, //ubuntu
// docker://ubuntu:18.04 -> docker, //ubuntu:18.04
// oci-archive:path/to/archive -> oci-archive, path/to/archive
// ubuntu -> "", ubuntu
// ubuntu:18.04.img -> "", ubuntu:18.04.img
func Split(uri string) (transport string, ref string) {
uriSplit := strings.SplitN(uri, ":", 2)
if len(uriSplit) == 1 {
// no colon
return "", uri
}
if uriSplit[1][0:1] == "//" {
// the format was ://, so try it whether or not valid URI
return uriSplit[0], uriSplit[1]
}
if ok, err := IsValid(uri); ok && err == nil {
// also accept recognized URIs
return uriSplit[0], uriSplit[1]
}
return "", uri
}