mirror of https://github.com/docker/docs.git
Merge pull request #1299 from dnephin/use_parse_repo_tags
Use ParseRepositoryTag() from engine
This commit is contained in:
commit
384c29163a
|
@ -40,7 +40,7 @@
|
|||
"Rev": "c7a04fda2ad804601385f054c19b69cf43fcfe46"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/docker/docker/pkg/parsers/filters",
|
||||
"ImportPath": "github.com/docker/docker/pkg/parsers",
|
||||
"Comment": "v1.4.1-3245-g443437f",
|
||||
"Rev": "443437f5ea04da9d62bf3e05d7951f7d30e77d96"
|
||||
},
|
||||
|
|
93
Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/kernel.go
generated
vendored
Normal file
93
Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/kernel.go
generated
vendored
Normal file
|
@ -0,0 +1,93 @@
|
|||
package kernel
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type KernelVersionInfo struct {
|
||||
Kernel int
|
||||
Major int
|
||||
Minor int
|
||||
Flavor string
|
||||
}
|
||||
|
||||
func (k *KernelVersionInfo) String() string {
|
||||
return fmt.Sprintf("%d.%d.%d%s", k.Kernel, k.Major, k.Minor, k.Flavor)
|
||||
}
|
||||
|
||||
// Compare two KernelVersionInfo struct.
|
||||
// Returns -1 if a < b, 0 if a == b, 1 it a > b
|
||||
func CompareKernelVersion(a, b *KernelVersionInfo) int {
|
||||
if a.Kernel < b.Kernel {
|
||||
return -1
|
||||
} else if a.Kernel > b.Kernel {
|
||||
return 1
|
||||
}
|
||||
|
||||
if a.Major < b.Major {
|
||||
return -1
|
||||
} else if a.Major > b.Major {
|
||||
return 1
|
||||
}
|
||||
|
||||
if a.Minor < b.Minor {
|
||||
return -1
|
||||
} else if a.Minor > b.Minor {
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetKernelVersion() (*KernelVersionInfo, error) {
|
||||
var (
|
||||
err error
|
||||
)
|
||||
|
||||
uts, err := uname()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
release := make([]byte, len(uts.Release))
|
||||
|
||||
i := 0
|
||||
for _, c := range uts.Release {
|
||||
release[i] = byte(c)
|
||||
i++
|
||||
}
|
||||
|
||||
// Remove the \x00 from the release for Atoi to parse correctly
|
||||
release = release[:bytes.IndexByte(release, 0)]
|
||||
|
||||
return ParseRelease(string(release))
|
||||
}
|
||||
|
||||
func ParseRelease(release string) (*KernelVersionInfo, error) {
|
||||
var (
|
||||
kernel, major, minor, parsed int
|
||||
flavor, partial string
|
||||
)
|
||||
|
||||
// Ignore error from Sscanf to allow an empty flavor. Instead, just
|
||||
// make sure we got all the version numbers.
|
||||
parsed, _ = fmt.Sscanf(release, "%d.%d%s", &kernel, &major, &partial)
|
||||
if parsed < 2 {
|
||||
return nil, errors.New("Can't parse kernel version " + release)
|
||||
}
|
||||
|
||||
// sometimes we have 3.12.25-gentoo, but sometimes we just have 3.12-1-amd64
|
||||
parsed, _ = fmt.Sscanf(partial, ".%d%s", &minor, &flavor)
|
||||
if parsed < 1 {
|
||||
flavor = partial
|
||||
}
|
||||
|
||||
return &KernelVersionInfo{
|
||||
Kernel: kernel,
|
||||
Major: major,
|
||||
Minor: minor,
|
||||
Flavor: flavor,
|
||||
}, nil
|
||||
}
|
61
Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/kernel_test.go
generated
vendored
Normal file
61
Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/kernel_test.go
generated
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
package kernel
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func assertParseRelease(t *testing.T, release string, b *KernelVersionInfo, result int) {
|
||||
var (
|
||||
a *KernelVersionInfo
|
||||
)
|
||||
a, _ = ParseRelease(release)
|
||||
|
||||
if r := CompareKernelVersion(a, b); r != result {
|
||||
t.Fatalf("Unexpected kernel version comparison result. Found %d, expected %d", r, result)
|
||||
}
|
||||
if a.Flavor != b.Flavor {
|
||||
t.Fatalf("Unexpected parsed kernel flavor. Found %s, expected %s", a.Flavor, b.Flavor)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseRelease(t *testing.T) {
|
||||
assertParseRelease(t, "3.8.0", &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}, 0)
|
||||
assertParseRelease(t, "3.4.54.longterm-1", &KernelVersionInfo{Kernel: 3, Major: 4, Minor: 54, Flavor: ".longterm-1"}, 0)
|
||||
assertParseRelease(t, "3.4.54.longterm-1", &KernelVersionInfo{Kernel: 3, Major: 4, Minor: 54, Flavor: ".longterm-1"}, 0)
|
||||
assertParseRelease(t, "3.8.0-19-generic", &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0, Flavor: "-19-generic"}, 0)
|
||||
assertParseRelease(t, "3.12.8tag", &KernelVersionInfo{Kernel: 3, Major: 12, Minor: 8, Flavor: "tag"}, 0)
|
||||
assertParseRelease(t, "3.12-1-amd64", &KernelVersionInfo{Kernel: 3, Major: 12, Minor: 0, Flavor: "-1-amd64"}, 0)
|
||||
}
|
||||
|
||||
func assertKernelVersion(t *testing.T, a, b *KernelVersionInfo, result int) {
|
||||
if r := CompareKernelVersion(a, b); r != result {
|
||||
t.Fatalf("Unexpected kernel version comparison result. Found %d, expected %d", r, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompareKernelVersion(t *testing.T) {
|
||||
assertKernelVersion(t,
|
||||
&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
||||
&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
||||
0)
|
||||
assertKernelVersion(t,
|
||||
&KernelVersionInfo{Kernel: 2, Major: 6, Minor: 0},
|
||||
&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
||||
-1)
|
||||
assertKernelVersion(t,
|
||||
&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
||||
&KernelVersionInfo{Kernel: 2, Major: 6, Minor: 0},
|
||||
1)
|
||||
assertKernelVersion(t,
|
||||
&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
||||
&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
||||
0)
|
||||
assertKernelVersion(t,
|
||||
&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 5},
|
||||
&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
||||
1)
|
||||
assertKernelVersion(t,
|
||||
&KernelVersionInfo{Kernel: 3, Major: 0, Minor: 20},
|
||||
&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
||||
-1)
|
||||
}
|
16
Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/uname_linux.go
generated
vendored
Normal file
16
Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/uname_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
package kernel
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
type Utsname syscall.Utsname
|
||||
|
||||
func uname() (*syscall.Utsname, error) {
|
||||
uts := &syscall.Utsname{}
|
||||
|
||||
if err := syscall.Uname(uts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return uts, nil
|
||||
}
|
15
Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/uname_unsupported.go
generated
vendored
Normal file
15
Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/uname_unsupported.go
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
// +build !linux
|
||||
|
||||
package kernel
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
type Utsname struct {
|
||||
Release [65]byte
|
||||
}
|
||||
|
||||
func uname() (*Utsname, error) {
|
||||
return nil, errors.New("Kernel version detection is available only on linux")
|
||||
}
|
40
Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem.go
generated
vendored
Normal file
40
Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem.go
generated
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
package operatingsystem
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
var (
|
||||
// file to use to detect if the daemon is running in a container
|
||||
proc1Cgroup = "/proc/1/cgroup"
|
||||
|
||||
// file to check to determine Operating System
|
||||
etcOsRelease = "/etc/os-release"
|
||||
)
|
||||
|
||||
func GetOperatingSystem() (string, error) {
|
||||
b, err := ioutil.ReadFile(etcOsRelease)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if i := bytes.Index(b, []byte("PRETTY_NAME")); i >= 0 {
|
||||
b = b[i+13:]
|
||||
return string(b[:bytes.IndexByte(b, '"')]), nil
|
||||
}
|
||||
return "", errors.New("PRETTY_NAME not found")
|
||||
}
|
||||
|
||||
func IsContainerized() (bool, error) {
|
||||
b, err := ioutil.ReadFile(proc1Cgroup)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, line := range bytes.Split(b, []byte{'\n'}) {
|
||||
if len(line) > 0 && !bytes.HasSuffix(line, []byte{'/'}) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
124
Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_test.go
generated
vendored
Normal file
124
Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_test.go
generated
vendored
Normal file
|
@ -0,0 +1,124 @@
|
|||
package operatingsystem
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetOperatingSystem(t *testing.T) {
|
||||
var (
|
||||
backup = etcOsRelease
|
||||
ubuntuTrusty = []byte(`NAME="Ubuntu"
|
||||
VERSION="14.04, Trusty Tahr"
|
||||
ID=ubuntu
|
||||
ID_LIKE=debian
|
||||
PRETTY_NAME="Ubuntu 14.04 LTS"
|
||||
VERSION_ID="14.04"
|
||||
HOME_URL="http://www.ubuntu.com/"
|
||||
SUPPORT_URL="http://help.ubuntu.com/"
|
||||
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`)
|
||||
gentoo = []byte(`NAME=Gentoo
|
||||
ID=gentoo
|
||||
PRETTY_NAME="Gentoo/Linux"
|
||||
ANSI_COLOR="1;32"
|
||||
HOME_URL="http://www.gentoo.org/"
|
||||
SUPPORT_URL="http://www.gentoo.org/main/en/support.xml"
|
||||
BUG_REPORT_URL="https://bugs.gentoo.org/"
|
||||
`)
|
||||
noPrettyName = []byte(`NAME="Ubuntu"
|
||||
VERSION="14.04, Trusty Tahr"
|
||||
ID=ubuntu
|
||||
ID_LIKE=debian
|
||||
VERSION_ID="14.04"
|
||||
HOME_URL="http://www.ubuntu.com/"
|
||||
SUPPORT_URL="http://help.ubuntu.com/"
|
||||
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`)
|
||||
)
|
||||
|
||||
dir := os.TempDir()
|
||||
etcOsRelease = filepath.Join(dir, "etcOsRelease")
|
||||
|
||||
defer func() {
|
||||
os.Remove(etcOsRelease)
|
||||
etcOsRelease = backup
|
||||
}()
|
||||
|
||||
for expect, osRelease := range map[string][]byte{
|
||||
"Ubuntu 14.04 LTS": ubuntuTrusty,
|
||||
"Gentoo/Linux": gentoo,
|
||||
"": noPrettyName,
|
||||
} {
|
||||
if err := ioutil.WriteFile(etcOsRelease, osRelease, 0600); err != nil {
|
||||
t.Fatalf("failed to write to %s: %v", etcOsRelease, err)
|
||||
}
|
||||
s, err := GetOperatingSystem()
|
||||
if s != expect {
|
||||
if expect == "" {
|
||||
t.Fatalf("Expected error 'PRETTY_NAME not found', but got %v", err)
|
||||
} else {
|
||||
t.Fatalf("Expected '%s', but got '%s'. Err=%v", expect, s, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsContainerized(t *testing.T) {
|
||||
var (
|
||||
backup = proc1Cgroup
|
||||
nonContainerizedProc1Cgroup = []byte(`14:name=systemd:/
|
||||
13:hugetlb:/
|
||||
12:net_prio:/
|
||||
11:perf_event:/
|
||||
10:bfqio:/
|
||||
9:blkio:/
|
||||
8:net_cls:/
|
||||
7:freezer:/
|
||||
6:devices:/
|
||||
5:memory:/
|
||||
4:cpuacct:/
|
||||
3:cpu:/
|
||||
2:cpuset:/
|
||||
`)
|
||||
containerizedProc1Cgroup = []byte(`9:perf_event:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d
|
||||
8:blkio:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d
|
||||
7:net_cls:/
|
||||
6:freezer:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d
|
||||
5:devices:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d
|
||||
4:memory:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d
|
||||
3:cpuacct:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d
|
||||
2:cpu:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d
|
||||
1:cpuset:/`)
|
||||
)
|
||||
|
||||
dir := os.TempDir()
|
||||
proc1Cgroup = filepath.Join(dir, "proc1Cgroup")
|
||||
|
||||
defer func() {
|
||||
os.Remove(proc1Cgroup)
|
||||
proc1Cgroup = backup
|
||||
}()
|
||||
|
||||
if err := ioutil.WriteFile(proc1Cgroup, nonContainerizedProc1Cgroup, 0600); err != nil {
|
||||
t.Fatalf("failed to write to %s: %v", proc1Cgroup, err)
|
||||
}
|
||||
inContainer, err := IsContainerized()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if inContainer {
|
||||
t.Fatal("Wrongly assuming containerized")
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(proc1Cgroup, containerizedProc1Cgroup, 0600); err != nil {
|
||||
t.Fatalf("failed to write to %s: %v", proc1Cgroup, err)
|
||||
}
|
||||
inContainer, err = IsContainerized()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !inContainer {
|
||||
t.Fatal("Wrongly assuming non-containerized")
|
||||
}
|
||||
}
|
137
Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/parsers.go
generated
vendored
Normal file
137
Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/parsers.go
generated
vendored
Normal file
|
@ -0,0 +1,137 @@
|
|||
package parsers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// FIXME: Change this not to receive default value as parameter
|
||||
func ParseHost(defaultTCPAddr, defaultUnixAddr, addr string) (string, error) {
|
||||
addr = strings.TrimSpace(addr)
|
||||
if addr == "" {
|
||||
addr = fmt.Sprintf("unix://%s", defaultUnixAddr)
|
||||
}
|
||||
addrParts := strings.Split(addr, "://")
|
||||
if len(addrParts) == 1 {
|
||||
addrParts = []string{"tcp", addrParts[0]}
|
||||
}
|
||||
|
||||
switch addrParts[0] {
|
||||
case "tcp":
|
||||
return ParseTCPAddr(addrParts[1], defaultTCPAddr)
|
||||
case "unix":
|
||||
return ParseUnixAddr(addrParts[1], defaultUnixAddr)
|
||||
case "fd":
|
||||
return addr, nil
|
||||
default:
|
||||
return "", fmt.Errorf("Invalid bind address format: %s", addr)
|
||||
}
|
||||
}
|
||||
|
||||
func ParseUnixAddr(addr string, defaultAddr string) (string, error) {
|
||||
addr = strings.TrimPrefix(addr, "unix://")
|
||||
if strings.Contains(addr, "://") {
|
||||
return "", fmt.Errorf("Invalid proto, expected unix: %s", addr)
|
||||
}
|
||||
if addr == "" {
|
||||
addr = defaultAddr
|
||||
}
|
||||
return fmt.Sprintf("unix://%s", addr), nil
|
||||
}
|
||||
|
||||
func ParseTCPAddr(addr string, defaultAddr string) (string, error) {
|
||||
addr = strings.TrimPrefix(addr, "tcp://")
|
||||
if strings.Contains(addr, "://") || addr == "" {
|
||||
return "", fmt.Errorf("Invalid proto, expected tcp: %s", addr)
|
||||
}
|
||||
|
||||
hostParts := strings.Split(addr, ":")
|
||||
if len(hostParts) != 2 {
|
||||
return "", fmt.Errorf("Invalid bind address format: %s", addr)
|
||||
}
|
||||
host := hostParts[0]
|
||||
if host == "" {
|
||||
host = defaultAddr
|
||||
}
|
||||
|
||||
p, err := strconv.Atoi(hostParts[1])
|
||||
if err != nil && p == 0 {
|
||||
return "", fmt.Errorf("Invalid bind address format: %s", addr)
|
||||
}
|
||||
return fmt.Sprintf("tcp://%s:%d", host, p), nil
|
||||
}
|
||||
|
||||
// Get a repos name and returns the right reposName + tag|digest
|
||||
// The tag can be confusing because of a port in a repository name.
|
||||
// Ex: localhost.localdomain:5000/samalba/hipache:latest
|
||||
// Digest ex: localhost:5000/foo/bar@sha256:bc8813ea7b3603864987522f02a76101c17ad122e1c46d790efc0fca78ca7bfb
|
||||
func ParseRepositoryTag(repos string) (string, string) {
|
||||
n := strings.Index(repos, "@")
|
||||
if n >= 0 {
|
||||
parts := strings.Split(repos, "@")
|
||||
return parts[0], parts[1]
|
||||
}
|
||||
n = strings.LastIndex(repos, ":")
|
||||
if n < 0 {
|
||||
return repos, ""
|
||||
}
|
||||
if tag := repos[n+1:]; !strings.Contains(tag, "/") {
|
||||
return repos[:n], tag
|
||||
}
|
||||
return repos, ""
|
||||
}
|
||||
|
||||
func PartParser(template, data string) (map[string]string, error) {
|
||||
// ip:public:private
|
||||
var (
|
||||
templateParts = strings.Split(template, ":")
|
||||
parts = strings.Split(data, ":")
|
||||
out = make(map[string]string, len(templateParts))
|
||||
)
|
||||
if len(parts) != len(templateParts) {
|
||||
return nil, fmt.Errorf("Invalid format to parse. %s should match template %s", data, template)
|
||||
}
|
||||
|
||||
for i, t := range templateParts {
|
||||
value := ""
|
||||
if len(parts) > i {
|
||||
value = parts[i]
|
||||
}
|
||||
out[t] = value
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func ParseKeyValueOpt(opt string) (string, string, error) {
|
||||
parts := strings.SplitN(opt, "=", 2)
|
||||
if len(parts) != 2 {
|
||||
return "", "", fmt.Errorf("Unable to parse key/value option: %s", opt)
|
||||
}
|
||||
return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil
|
||||
}
|
||||
|
||||
func ParsePortRange(ports string) (uint64, uint64, error) {
|
||||
if ports == "" {
|
||||
return 0, 0, fmt.Errorf("Empty string specified for ports.")
|
||||
}
|
||||
if !strings.Contains(ports, "-") {
|
||||
start, err := strconv.ParseUint(ports, 10, 16)
|
||||
end := start
|
||||
return start, end, err
|
||||
}
|
||||
|
||||
parts := strings.Split(ports, "-")
|
||||
start, err := strconv.ParseUint(parts[0], 10, 16)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
end, err := strconv.ParseUint(parts[1], 10, 16)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
if end < start {
|
||||
return 0, 0, fmt.Errorf("Invalid range specified for the Port: %s", ports)
|
||||
}
|
||||
return start, end, nil
|
||||
}
|
125
Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/parsers_test.go
generated
vendored
Normal file
125
Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/parsers_test.go
generated
vendored
Normal file
|
@ -0,0 +1,125 @@
|
|||
package parsers
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseHost(t *testing.T) {
|
||||
var (
|
||||
defaultHttpHost = "127.0.0.1"
|
||||
defaultUnix = "/var/run/docker.sock"
|
||||
)
|
||||
if addr, err := ParseHost(defaultHttpHost, defaultUnix, "0.0.0.0"); err == nil {
|
||||
t.Errorf("tcp 0.0.0.0 address expected error return, but err == nil, got %s", addr)
|
||||
}
|
||||
if addr, err := ParseHost(defaultHttpHost, defaultUnix, "tcp://"); err == nil {
|
||||
t.Errorf("default tcp:// address expected error return, but err == nil, got %s", addr)
|
||||
}
|
||||
if addr, err := ParseHost(defaultHttpHost, defaultUnix, "0.0.0.1:5555"); err != nil || addr != "tcp://0.0.0.1:5555" {
|
||||
t.Errorf("0.0.0.1:5555 -> expected tcp://0.0.0.1:5555, got %s", addr)
|
||||
}
|
||||
if addr, err := ParseHost(defaultHttpHost, defaultUnix, ":6666"); err != nil || addr != "tcp://127.0.0.1:6666" {
|
||||
t.Errorf(":6666 -> expected tcp://127.0.0.1:6666, got %s", addr)
|
||||
}
|
||||
if addr, err := ParseHost(defaultHttpHost, defaultUnix, "tcp://:7777"); err != nil || addr != "tcp://127.0.0.1:7777" {
|
||||
t.Errorf("tcp://:7777 -> expected tcp://127.0.0.1:7777, got %s", addr)
|
||||
}
|
||||
if addr, err := ParseHost(defaultHttpHost, defaultUnix, ""); err != nil || addr != "unix:///var/run/docker.sock" {
|
||||
t.Errorf("empty argument -> expected unix:///var/run/docker.sock, got %s", addr)
|
||||
}
|
||||
if addr, err := ParseHost(defaultHttpHost, defaultUnix, "unix:///var/run/docker.sock"); err != nil || addr != "unix:///var/run/docker.sock" {
|
||||
t.Errorf("unix:///var/run/docker.sock -> expected unix:///var/run/docker.sock, got %s", addr)
|
||||
}
|
||||
if addr, err := ParseHost(defaultHttpHost, defaultUnix, "unix://"); err != nil || addr != "unix:///var/run/docker.sock" {
|
||||
t.Errorf("unix:///var/run/docker.sock -> expected unix:///var/run/docker.sock, got %s", addr)
|
||||
}
|
||||
if addr, err := ParseHost(defaultHttpHost, defaultUnix, "udp://127.0.0.1"); err == nil {
|
||||
t.Errorf("udp protocol address expected error return, but err == nil. Got %s", addr)
|
||||
}
|
||||
if addr, err := ParseHost(defaultHttpHost, defaultUnix, "udp://127.0.0.1:2375"); err == nil {
|
||||
t.Errorf("udp protocol address expected error return, but err == nil. Got %s", addr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseRepositoryTag(t *testing.T) {
|
||||
if repo, tag := ParseRepositoryTag("root"); repo != "root" || tag != "" {
|
||||
t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "root", "", repo, tag)
|
||||
}
|
||||
if repo, tag := ParseRepositoryTag("root:tag"); repo != "root" || tag != "tag" {
|
||||
t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "root", "tag", repo, tag)
|
||||
}
|
||||
if repo, digest := ParseRepositoryTag("root@sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); repo != "root" || digest != "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" {
|
||||
t.Errorf("Expected repo: '%s' and digest: '%s', got '%s' and '%s'", "root", "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", repo, digest)
|
||||
}
|
||||
if repo, tag := ParseRepositoryTag("user/repo"); repo != "user/repo" || tag != "" {
|
||||
t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "user/repo", "", repo, tag)
|
||||
}
|
||||
if repo, tag := ParseRepositoryTag("user/repo:tag"); repo != "user/repo" || tag != "tag" {
|
||||
t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "user/repo", "tag", repo, tag)
|
||||
}
|
||||
if repo, digest := ParseRepositoryTag("user/repo@sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); repo != "user/repo" || digest != "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" {
|
||||
t.Errorf("Expected repo: '%s' and digest: '%s', got '%s' and '%s'", "user/repo", "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", repo, digest)
|
||||
}
|
||||
if repo, tag := ParseRepositoryTag("url:5000/repo"); repo != "url:5000/repo" || tag != "" {
|
||||
t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "url:5000/repo", "", repo, tag)
|
||||
}
|
||||
if repo, tag := ParseRepositoryTag("url:5000/repo:tag"); repo != "url:5000/repo" || tag != "tag" {
|
||||
t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "url:5000/repo", "tag", repo, tag)
|
||||
}
|
||||
if repo, digest := ParseRepositoryTag("url:5000/repo@sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); repo != "url:5000/repo" || digest != "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" {
|
||||
t.Errorf("Expected repo: '%s' and digest: '%s', got '%s' and '%s'", "url:5000/repo", "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", repo, digest)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParsePortMapping(t *testing.T) {
|
||||
data, err := PartParser("ip:public:private", "192.168.1.1:80:8080")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(data) != 3 {
|
||||
t.FailNow()
|
||||
}
|
||||
if data["ip"] != "192.168.1.1" {
|
||||
t.Fail()
|
||||
}
|
||||
if data["public"] != "80" {
|
||||
t.Fail()
|
||||
}
|
||||
if data["private"] != "8080" {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestParsePortRange(t *testing.T) {
|
||||
if start, end, err := ParsePortRange("8000-8080"); err != nil || start != 8000 || end != 8080 {
|
||||
t.Fatalf("Error: %s or Expecting {start,end} values {8000,8080} but found {%d,%d}.", err, start, end)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParsePortRangeIncorrectRange(t *testing.T) {
|
||||
if _, _, err := ParsePortRange("9000-8080"); err == nil || !strings.Contains(err.Error(), "Invalid range specified for the Port") {
|
||||
t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParsePortRangeIncorrectEndRange(t *testing.T) {
|
||||
if _, _, err := ParsePortRange("8000-a"); err == nil || !strings.Contains(err.Error(), "invalid syntax") {
|
||||
t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err)
|
||||
}
|
||||
|
||||
if _, _, err := ParsePortRange("8000-30a"); err == nil || !strings.Contains(err.Error(), "invalid syntax") {
|
||||
t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParsePortRangeIncorrectStartRange(t *testing.T) {
|
||||
if _, _, err := ParsePortRange("a-8000"); err == nil || !strings.Contains(err.Error(), "invalid syntax") {
|
||||
t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err)
|
||||
}
|
||||
|
||||
if _, _, err := ParsePortRange("30a-8000"); err == nil || !strings.Contains(err.Error(), "invalid syntax") {
|
||||
t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err)
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package cluster
|
|||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/pkg/parsers"
|
||||
"github.com/samalba/dockerclient"
|
||||
)
|
||||
|
||||
|
@ -13,59 +14,24 @@ type Image struct {
|
|||
Engine *Engine
|
||||
}
|
||||
|
||||
func toImageName(repo string, name string, tag string) string {
|
||||
fullname := name
|
||||
if tag != "" {
|
||||
fullname = name + ":" + tag
|
||||
}
|
||||
if repo != "" {
|
||||
fullname = repo + "/" + fullname
|
||||
}
|
||||
return fullname
|
||||
}
|
||||
|
||||
func parseImageName(fullname string) (repo string, name string, tag string) {
|
||||
parts := strings.SplitN(fullname, "/", 2)
|
||||
|
||||
nameAndTag := parts[0]
|
||||
if len(parts) == 2 {
|
||||
repo = parts[0]
|
||||
nameAndTag = parts[1]
|
||||
}
|
||||
|
||||
parts = strings.SplitN(nameAndTag, ":", 2)
|
||||
name = parts[0]
|
||||
if len(parts) == 2 {
|
||||
tag = parts[1]
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Match is exported
|
||||
func (image *Image) Match(IDOrName string, matchTag bool) bool {
|
||||
size := len(IDOrName)
|
||||
|
||||
// TODO: prefix match can cause false positives with image names
|
||||
if image.Id == IDOrName || (size > 2 && strings.HasPrefix(image.Id, IDOrName)) {
|
||||
return true
|
||||
}
|
||||
|
||||
imageName := IDOrName
|
||||
repo, name, tag := parseImageName(imageName)
|
||||
if matchTag {
|
||||
if tag == "" {
|
||||
imageName = toImageName(repo, name, "latest")
|
||||
}
|
||||
} else {
|
||||
imageName = toImageName(repo, name, "")
|
||||
}
|
||||
repoName, tag := parsers.ParseRepositoryTag(IDOrName)
|
||||
|
||||
for _, repoTag := range image.RepoTags {
|
||||
if matchTag == false {
|
||||
r, n, _ := parseImageName(repoTag)
|
||||
repoTag = toImageName(r, n, "")
|
||||
for _, imageRepoTag := range image.RepoTags {
|
||||
imageRepoName, imageTag := parsers.ParseRepositoryTag(imageRepoTag)
|
||||
|
||||
if matchTag == false && imageRepoName == repoName {
|
||||
return true
|
||||
}
|
||||
if repoTag == imageName {
|
||||
if imageRepoName == repoName && (imageTag == tag || tag == "") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,35 +33,6 @@ func TestMatch(t *testing.T) {
|
|||
assert.False(t, img.Match("na", false))
|
||||
}
|
||||
|
||||
func TestParseImage(t *testing.T) {
|
||||
repo, name, tag := parseImageName("private.registry.com:5000/name:latest")
|
||||
assert.Equal(t, repo, "private.registry.com:5000")
|
||||
assert.Equal(t, name, "name")
|
||||
assert.Equal(t, tag, "latest")
|
||||
|
||||
repo, name, tag = parseImageName("name:latest")
|
||||
assert.Equal(t, repo, "")
|
||||
assert.Equal(t, name, "name")
|
||||
assert.Equal(t, tag, "latest")
|
||||
|
||||
repo, name, tag = parseImageName("name")
|
||||
assert.Equal(t, repo, "")
|
||||
assert.Equal(t, name, "name")
|
||||
assert.Equal(t, tag, "")
|
||||
|
||||
repo, name, tag = parseImageName("")
|
||||
assert.Equal(t, repo, "")
|
||||
assert.Equal(t, name, "")
|
||||
assert.Equal(t, tag, "")
|
||||
}
|
||||
|
||||
func TestToImage(t *testing.T) {
|
||||
assert.Equal(t, toImageName("", "name", ""), "name")
|
||||
assert.Equal(t, toImageName("", "name", "latest"), "name:latest")
|
||||
assert.Equal(t, toImageName("a", "name", ""), "a/name")
|
||||
assert.Equal(t, toImageName("private.registry.com:5000", "name", "latest"), "private.registry.com:5000/name:latest")
|
||||
}
|
||||
|
||||
func TestMatchPrivateRepo(t *testing.T) {
|
||||
img := Image{}
|
||||
|
||||
|
|
Loading…
Reference in New Issue