github.com/campoy/docker@v1.8.0-rc1/pkg/parsers/parsers.go (about) 1 package parsers 2 3 import ( 4 "fmt" 5 "net/url" 6 "path" 7 "runtime" 8 "strconv" 9 "strings" 10 ) 11 12 // FIXME: Change this not to receive default value as parameter 13 func ParseHost(defaultTCPAddr, defaultUnixAddr, addr string) (string, error) { 14 addr = strings.TrimSpace(addr) 15 if addr == "" { 16 if runtime.GOOS != "windows" { 17 addr = fmt.Sprintf("unix://%s", defaultUnixAddr) 18 } else { 19 // Note - defaultTCPAddr already includes tcp:// prefix 20 addr = fmt.Sprintf("%s", defaultTCPAddr) 21 } 22 } 23 addrParts := strings.Split(addr, "://") 24 if len(addrParts) == 1 { 25 addrParts = []string{"tcp", addrParts[0]} 26 } 27 28 switch addrParts[0] { 29 case "tcp": 30 return ParseTCPAddr(addrParts[1], defaultTCPAddr) 31 case "unix": 32 return ParseUnixAddr(addrParts[1], defaultUnixAddr) 33 case "fd": 34 return addr, nil 35 default: 36 return "", fmt.Errorf("Invalid bind address format: %s", addr) 37 } 38 } 39 40 func ParseUnixAddr(addr string, defaultAddr string) (string, error) { 41 addr = strings.TrimPrefix(addr, "unix://") 42 if strings.Contains(addr, "://") { 43 return "", fmt.Errorf("Invalid proto, expected unix: %s", addr) 44 } 45 if addr == "" { 46 addr = defaultAddr 47 } 48 return fmt.Sprintf("unix://%s", addr), nil 49 } 50 51 func ParseTCPAddr(addr string, defaultAddr string) (string, error) { 52 addr = strings.TrimPrefix(addr, "tcp://") 53 if strings.Contains(addr, "://") || addr == "" { 54 return "", fmt.Errorf("Invalid proto, expected tcp: %s", addr) 55 } 56 57 u, err := url.Parse("tcp://" + addr) 58 if err != nil { 59 return "", err 60 } 61 hostParts := strings.Split(u.Host, ":") 62 if len(hostParts) != 2 { 63 return "", fmt.Errorf("Invalid bind address format: %s", addr) 64 } 65 host := hostParts[0] 66 if host == "" { 67 host = defaultAddr 68 } 69 70 p, err := strconv.Atoi(hostParts[1]) 71 if err != nil && p == 0 { 72 return "", fmt.Errorf("Invalid bind address format: %s", addr) 73 } 74 return fmt.Sprintf("tcp://%s:%d%s", host, p, u.Path), nil 75 } 76 77 // Get a repos name and returns the right reposName + tag|digest 78 // The tag can be confusing because of a port in a repository name. 79 // Ex: localhost.localdomain:5000/samalba/hipache:latest 80 // Digest ex: localhost:5000/foo/bar@sha256:bc8813ea7b3603864987522f02a76101c17ad122e1c46d790efc0fca78ca7bfb 81 func ParseRepositoryTag(repos string) (string, string) { 82 n := strings.Index(repos, "@") 83 if n >= 0 { 84 parts := strings.Split(repos, "@") 85 return parts[0], parts[1] 86 } 87 n = strings.LastIndex(repos, ":") 88 if n < 0 { 89 return repos, "" 90 } 91 if tag := repos[n+1:]; !strings.Contains(tag, "/") { 92 return repos[:n], tag 93 } 94 return repos, "" 95 } 96 97 func PartParser(template, data string) (map[string]string, error) { 98 // ip:public:private 99 var ( 100 templateParts = strings.Split(template, ":") 101 parts = strings.Split(data, ":") 102 out = make(map[string]string, len(templateParts)) 103 ) 104 if len(parts) != len(templateParts) { 105 return nil, fmt.Errorf("Invalid format to parse. %s should match template %s", data, template) 106 } 107 108 for i, t := range templateParts { 109 value := "" 110 if len(parts) > i { 111 value = parts[i] 112 } 113 out[t] = value 114 } 115 return out, nil 116 } 117 118 func ParseKeyValueOpt(opt string) (string, string, error) { 119 parts := strings.SplitN(opt, "=", 2) 120 if len(parts) != 2 { 121 return "", "", fmt.Errorf("Unable to parse key/value option: %s", opt) 122 } 123 return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil 124 } 125 126 func ParsePortRange(ports string) (uint64, uint64, error) { 127 if ports == "" { 128 return 0, 0, fmt.Errorf("Empty string specified for ports.") 129 } 130 if !strings.Contains(ports, "-") { 131 start, err := strconv.ParseUint(ports, 10, 16) 132 end := start 133 return start, end, err 134 } 135 136 parts := strings.Split(ports, "-") 137 start, err := strconv.ParseUint(parts[0], 10, 16) 138 if err != nil { 139 return 0, 0, err 140 } 141 end, err := strconv.ParseUint(parts[1], 10, 16) 142 if err != nil { 143 return 0, 0, err 144 } 145 if end < start { 146 return 0, 0, fmt.Errorf("Invalid range specified for the Port: %s", ports) 147 } 148 return start, end, nil 149 } 150 151 func ParseLink(val string) (string, string, error) { 152 if val == "" { 153 return "", "", fmt.Errorf("empty string specified for links") 154 } 155 arr := strings.Split(val, ":") 156 if len(arr) > 2 { 157 return "", "", fmt.Errorf("bad format for links: %s", val) 158 } 159 if len(arr) == 1 { 160 return val, val, nil 161 } 162 // This is kept because we can actually get an HostConfig with links 163 // from an already created container and the format is not `foo:bar` 164 // but `/foo:/c1/bar` 165 if strings.HasPrefix(arr[0], "/") { 166 _, alias := path.Split(arr[1]) 167 return arr[0][1:], alias, nil 168 } 169 return arr[0], arr[1], nil 170 }