Docker-DCO-1.1-Signed-off-by: Erik Hollensbe <github@hollensbe.org> (github: erikh)
| ... | ... |
@@ -28,13 +28,14 @@ import ( |
| 28 | 28 |
"github.com/docker/docker/engine" |
| 29 | 29 |
"github.com/docker/docker/nat" |
| 30 | 30 |
"github.com/docker/docker/opts" |
| 31 |
+ "github.com/docker/docker/pkg/parsers" |
|
| 32 |
+ "github.com/docker/docker/pkg/parsers/filters" |
|
| 31 | 33 |
"github.com/docker/docker/pkg/signal" |
| 32 | 34 |
"github.com/docker/docker/pkg/term" |
| 33 | 35 |
"github.com/docker/docker/pkg/units" |
| 34 | 36 |
"github.com/docker/docker/registry" |
| 35 | 37 |
"github.com/docker/docker/runconfig" |
| 36 | 38 |
"github.com/docker/docker/utils" |
| 37 |
- "github.com/docker/docker/utils/filters" |
|
| 38 | 39 |
) |
| 39 | 40 |
|
| 40 | 41 |
const ( |
| ... | ... |
@@ -204,7 +205,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
|
| 204 | 204 |
|
| 205 | 205 |
//Check if the given image name can be resolved |
| 206 | 206 |
if *tag != "" {
|
| 207 |
- repository, _ := utils.ParseRepositoryTag(*tag) |
|
| 207 |
+ repository, _ := parsers.ParseRepositoryTag(*tag) |
|
| 208 | 208 |
if _, _, err := registry.ResolveRepositoryName(repository); err != nil {
|
| 209 | 209 |
return err |
| 210 | 210 |
} |
| ... | ... |
@@ -1137,7 +1138,7 @@ func (cli *DockerCli) CmdPush(args ...string) error {
|
| 1137 | 1137 |
|
| 1138 | 1138 |
cli.LoadConfigFile() |
| 1139 | 1139 |
|
| 1140 |
- remote, tag := utils.ParseRepositoryTag(name) |
|
| 1140 |
+ remote, tag := parsers.ParseRepositoryTag(name) |
|
| 1141 | 1141 |
|
| 1142 | 1142 |
// Resolve the Repository name from fqn to hostname + name |
| 1143 | 1143 |
hostname, _, err := registry.ResolveRepositoryName(remote) |
| ... | ... |
@@ -1210,7 +1211,7 @@ func (cli *DockerCli) CmdPull(args ...string) error {
|
| 1210 | 1210 |
v.Set("tag", *tag)
|
| 1211 | 1211 |
} |
| 1212 | 1212 |
|
| 1213 |
- remote, _ = utils.ParseRepositoryTag(remote) |
|
| 1213 |
+ remote, _ = parsers.ParseRepositoryTag(remote) |
|
| 1214 | 1214 |
// Resolve the Repository name from fqn to hostname + name |
| 1215 | 1215 |
hostname, _, err := registry.ResolveRepositoryName(remote) |
| 1216 | 1216 |
if err != nil {
|
| ... | ... |
@@ -1393,7 +1394,7 @@ func (cli *DockerCli) CmdImages(args ...string) error {
|
| 1393 | 1393 |
for _, out := range outs.Data {
|
| 1394 | 1394 |
for _, repotag := range out.GetList("RepoTags") {
|
| 1395 | 1395 |
|
| 1396 |
- repo, tag := utils.ParseRepositoryTag(repotag) |
|
| 1396 |
+ repo, tag := parsers.ParseRepositoryTag(repotag) |
|
| 1397 | 1397 |
outID := out.Get("Id")
|
| 1398 | 1398 |
if !*noTrunc {
|
| 1399 | 1399 |
outID = utils.TruncateID(outID) |
| ... | ... |
@@ -1594,7 +1595,7 @@ func (cli *DockerCli) CmdCommit(args ...string) error {
|
| 1594 | 1594 |
|
| 1595 | 1595 |
var ( |
| 1596 | 1596 |
name = cmd.Arg(0) |
| 1597 |
- repository, tag = utils.ParseRepositoryTag(cmd.Arg(1)) |
|
| 1597 |
+ repository, tag = parsers.ParseRepositoryTag(cmd.Arg(1)) |
|
| 1598 | 1598 |
) |
| 1599 | 1599 |
|
| 1600 | 1600 |
if name == "" || len(cmd.Args()) > 2 {
|
| ... | ... |
@@ -1918,7 +1919,7 @@ func (cli *DockerCli) CmdTag(args ...string) error {
|
| 1918 | 1918 |
} |
| 1919 | 1919 |
|
| 1920 | 1920 |
var ( |
| 1921 |
- repository, tag = utils.ParseRepositoryTag(cmd.Arg(1)) |
|
| 1921 |
+ repository, tag = parsers.ParseRepositoryTag(cmd.Arg(1)) |
|
| 1922 | 1922 |
v = url.Values{}
|
| 1923 | 1923 |
) |
| 1924 | 1924 |
|
| ... | ... |
@@ -1941,7 +1942,7 @@ func (cli *DockerCli) CmdTag(args ...string) error {
|
| 1941 | 1941 |
|
| 1942 | 1942 |
func (cli *DockerCli) pullImage(image string) error {
|
| 1943 | 1943 |
v := url.Values{}
|
| 1944 |
- repos, tag := utils.ParseRepositoryTag(image) |
|
| 1944 |
+ repos, tag := parsers.ParseRepositoryTag(image) |
|
| 1945 | 1945 |
// pull only the image tagged 'latest' if no tag was specified |
| 1946 | 1946 |
if tag == "" {
|
| 1947 | 1947 |
tag = "latest" |
| ... | ... |
@@ -6,6 +6,7 @@ import ( |
| 6 | 6 |
"strings" |
| 7 | 7 |
|
| 8 | 8 |
"github.com/docker/docker/engine" |
| 9 |
+ "github.com/docker/docker/pkg/parsers" |
|
| 9 | 10 |
"github.com/docker/docker/pkg/version" |
| 10 | 11 |
"github.com/docker/docker/utils" |
| 11 | 12 |
) |
| ... | ... |
@@ -17,7 +18,7 @@ const ( |
| 17 | 17 |
) |
| 18 | 18 |
|
| 19 | 19 |
func ValidateHost(val string) (string, error) {
|
| 20 |
- host, err := utils.ParseHost(DEFAULTHTTPHOST, DEFAULTUNIXSOCKET, val) |
|
| 20 |
+ host, err := parsers.ParseHost(DEFAULTHTTPHOST, DEFAULTUNIXSOCKET, val) |
|
| 21 | 21 |
if err != nil {
|
| 22 | 22 |
return val, err |
| 23 | 23 |
} |
| ... | ... |
@@ -25,6 +25,7 @@ import ( |
| 25 | 25 |
"github.com/docker/docker/api" |
| 26 | 26 |
"github.com/docker/docker/engine" |
| 27 | 27 |
"github.com/docker/docker/pkg/listenbuffer" |
| 28 |
+ "github.com/docker/docker/pkg/parsers" |
|
| 28 | 29 |
"github.com/docker/docker/pkg/systemd" |
| 29 | 30 |
"github.com/docker/docker/pkg/user" |
| 30 | 31 |
"github.com/docker/docker/pkg/version" |
| ... | ... |
@@ -484,7 +485,7 @@ func postImagesCreate(eng *engine.Engine, version version.Version, w http.Respon |
| 484 | 484 |
} |
| 485 | 485 |
if image != "" { //pull
|
| 486 | 486 |
if tag == "" {
|
| 487 |
- image, tag = utils.ParseRepositoryTag(image) |
|
| 487 |
+ image, tag = parsers.ParseRepositoryTag(image) |
|
| 488 | 488 |
} |
| 489 | 489 |
metaHeaders := map[string][]string{}
|
| 490 | 490 |
for k, v := range r.Header {
|
| ... | ... |
@@ -498,7 +499,7 @@ func postImagesCreate(eng *engine.Engine, version version.Version, w http.Respon |
| 498 | 498 |
job.SetenvJson("authConfig", authConfig)
|
| 499 | 499 |
} else { //import
|
| 500 | 500 |
if tag == "" {
|
| 501 |
- repo, tag = utils.ParseRepositoryTag(repo) |
|
| 501 |
+ repo, tag = parsers.ParseRepositoryTag(repo) |
|
| 502 | 502 |
} |
| 503 | 503 |
job = eng.Job("import", r.Form.Get("fromSrc"), repo, tag)
|
| 504 | 504 |
job.Stdin.Add(r.Body) |
| ... | ... |
@@ -23,6 +23,7 @@ import ( |
| 23 | 23 |
"github.com/docker/docker/daemon" |
| 24 | 24 |
"github.com/docker/docker/engine" |
| 25 | 25 |
"github.com/docker/docker/nat" |
| 26 |
+ "github.com/docker/docker/pkg/parsers" |
|
| 26 | 27 |
"github.com/docker/docker/pkg/symlink" |
| 27 | 28 |
"github.com/docker/docker/pkg/system" |
| 28 | 29 |
"github.com/docker/docker/registry" |
| ... | ... |
@@ -86,7 +87,7 @@ func (b *buildFile) CmdFrom(name string) error {
|
| 86 | 86 |
image, err := b.daemon.Repositories().LookupImage(name) |
| 87 | 87 |
if err != nil {
|
| 88 | 88 |
if b.daemon.Graph().IsNotExist(err) {
|
| 89 |
- remote, tag := utils.ParseRepositoryTag(name) |
|
| 89 |
+ remote, tag := parsers.ParseRepositoryTag(name) |
|
| 90 | 90 |
pullRegistryAuth := b.authConfig |
| 91 | 91 |
if len(b.configFile.Configs) > 0 {
|
| 92 | 92 |
// The request came with a full auth config file, we prefer to use that |
| ... | ... |
@@ -8,9 +8,9 @@ import ( |
| 8 | 8 |
"github.com/docker/docker/daemon/networkdriver/bridge" |
| 9 | 9 |
"github.com/docker/docker/dockerversion" |
| 10 | 10 |
"github.com/docker/docker/engine" |
| 11 |
+ "github.com/docker/docker/pkg/parsers/kernel" |
|
| 11 | 12 |
"github.com/docker/docker/registry" |
| 12 | 13 |
"github.com/docker/docker/server" |
| 13 |
- "github.com/docker/docker/utils" |
|
| 14 | 14 |
) |
| 15 | 15 |
|
| 16 | 16 |
func Register(eng *engine.Engine) error {
|
| ... | ... |
@@ -68,7 +68,7 @@ func dockerVersion(job *engine.Job) engine.Status {
|
| 68 | 68 |
v.Set("GoVersion", runtime.Version())
|
| 69 | 69 |
v.Set("Os", runtime.GOOS)
|
| 70 | 70 |
v.Set("Arch", runtime.GOARCH)
|
| 71 |
- if kernelVersion, err := utils.GetKernelVersion(); err == nil {
|
|
| 71 |
+ if kernelVersion, err := kernel.GetKernelVersion(); err == nil {
|
|
| 72 | 72 |
v.Set("KernelVersion", kernelVersion.String())
|
| 73 | 73 |
} |
| 74 | 74 |
if _, err := v.WriteTo(job.Stdout); err != nil {
|
| ... | ... |
@@ -28,6 +28,7 @@ import ( |
| 28 | 28 |
"github.com/docker/docker/pkg/graphdb" |
| 29 | 29 |
"github.com/docker/docker/pkg/namesgenerator" |
| 30 | 30 |
"github.com/docker/docker/pkg/networkfs/resolvconf" |
| 31 |
+ "github.com/docker/docker/pkg/parsers" |
|
| 31 | 32 |
"github.com/docker/docker/pkg/sysinfo" |
| 32 | 33 |
"github.com/docker/docker/pkg/truncindex" |
| 33 | 34 |
"github.com/docker/docker/runconfig" |
| ... | ... |
@@ -724,7 +725,7 @@ func (daemon *Daemon) RegisterLink(parent, child *Container, alias string) error |
| 724 | 724 |
func (daemon *Daemon) RegisterLinks(container *Container, hostConfig *runconfig.HostConfig) error {
|
| 725 | 725 |
if hostConfig != nil && hostConfig.Links != nil {
|
| 726 | 726 |
for _, l := range hostConfig.Links {
|
| 727 |
- parts, err := utils.PartParser("name:alias", l)
|
|
| 727 |
+ parts, err := parsers.PartParser("name:alias", l)
|
|
| 728 | 728 |
if err != nil {
|
| 729 | 729 |
return err |
| 730 | 730 |
} |
| ... | ... |
@@ -19,6 +19,7 @@ import ( |
| 19 | 19 |
"time" |
| 20 | 20 |
|
| 21 | 21 |
"github.com/docker/docker/daemon/graphdriver" |
| 22 |
+ "github.com/docker/docker/pkg/parsers" |
|
| 22 | 23 |
"github.com/docker/docker/pkg/units" |
| 23 | 24 |
"github.com/docker/docker/utils" |
| 24 | 25 |
"github.com/docker/libcontainer/label" |
| ... | ... |
@@ -1166,7 +1167,7 @@ func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error |
| 1166 | 1166 |
|
| 1167 | 1167 |
foundBlkDiscard := false |
| 1168 | 1168 |
for _, option := range options {
|
| 1169 |
- key, val, err := utils.ParseKeyValueOpt(option) |
|
| 1169 |
+ key, val, err := parsers.ParseKeyValueOpt(option) |
|
| 1170 | 1170 |
if err != nil {
|
| 1171 | 1171 |
return nil, err |
| 1172 | 1172 |
} |
| ... | ... |
@@ -15,6 +15,7 @@ import ( |
| 15 | 15 |
"github.com/docker/docker/engine" |
| 16 | 16 |
"github.com/docker/docker/pkg/iptables" |
| 17 | 17 |
"github.com/docker/docker/pkg/networkfs/resolvconf" |
| 18 |
+ "github.com/docker/docker/pkg/parsers/kernel" |
|
| 18 | 19 |
"github.com/docker/docker/utils" |
| 19 | 20 |
"github.com/docker/libcontainer/netlink" |
| 20 | 21 |
) |
| ... | ... |
@@ -306,7 +307,7 @@ func createBridge(bridgeIP string) error {
|
| 306 | 306 |
} |
| 307 | 307 |
|
| 308 | 308 |
func createBridgeIface(name string) error {
|
| 309 |
- kv, err := utils.GetKernelVersion() |
|
| 309 |
+ kv, err := kernel.GetKernelVersion() |
|
| 310 | 310 |
// only set the bridge's mac address if the kernel version is > 3.3 |
| 311 | 311 |
// before that it was not supported |
| 312 | 312 |
setBridgeMacAddr := err == nil && (kv.Kernel >= 3 && kv.Major >= 3) |
| ... | ... |
@@ -19,6 +19,7 @@ import ( |
| 19 | 19 |
"github.com/docker/docker/engine" |
| 20 | 20 |
"github.com/docker/docker/opts" |
| 21 | 21 |
flag "github.com/docker/docker/pkg/mflag" |
| 22 |
+ "github.com/docker/docker/pkg/parsers/kernel" |
|
| 22 | 23 |
"github.com/docker/docker/sysinit" |
| 23 | 24 |
"github.com/docker/docker/utils" |
| 24 | 25 |
) |
| ... | ... |
@@ -292,10 +293,10 @@ func checkKernelAndArch() error {
|
| 292 | 292 |
// without actually causing a kernel panic, so we need this workaround until |
| 293 | 293 |
// the circumstances of pre-3.8 crashes are clearer. |
| 294 | 294 |
// For details see http://github.com/docker/docker/issues/407 |
| 295 |
- if k, err := utils.GetKernelVersion(); err != nil {
|
|
| 295 |
+ if k, err := kernel.GetKernelVersion(); err != nil {
|
|
| 296 | 296 |
log.Printf("WARNING: %s\n", err)
|
| 297 | 297 |
} else {
|
| 298 |
- if utils.CompareKernelVersion(k, &utils.KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}) < 0 {
|
|
| 298 |
+ if kernel.CompareKernelVersion(k, &kernel.KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}) < 0 {
|
|
| 299 | 299 |
if os.Getenv("DOCKER_NOWARN_KERNEL_VERSION") == "" {
|
| 300 | 300 |
log.Printf("WARNING: You are running linux kernel version %s, which might be unstable running docker. Please upgrade your kernel to 3.8.0.", k.String())
|
| 301 | 301 |
} |
| ... | ... |
@@ -5,6 +5,7 @@ import ( |
| 5 | 5 |
|
| 6 | 6 |
"github.com/docker/docker/engine" |
| 7 | 7 |
"github.com/docker/docker/image" |
| 8 |
+ "github.com/docker/docker/pkg/parsers" |
|
| 8 | 9 |
"github.com/docker/docker/utils" |
| 9 | 10 |
) |
| 10 | 11 |
|
| ... | ... |
@@ -78,7 +79,7 @@ func (s *TagStore) CmdTag(job *engine.Job) engine.Status {
|
| 78 | 78 |
newName = job.Args[0] |
| 79 | 79 |
oldName = job.Args[1] |
| 80 | 80 |
) |
| 81 |
- newRepo, newTag := utils.ParseRepositoryTag(newName) |
|
| 81 |
+ newRepo, newTag := parsers.ParseRepositoryTag(newName) |
|
| 82 | 82 |
// FIXME: Set should either parse both old and new name, or neither. |
| 83 | 83 |
// the current prototype is inconsistent. |
| 84 | 84 |
if err := s.Set(newRepo, newTag, oldName, true); err != nil {
|
| ... | ... |
@@ -11,6 +11,7 @@ import ( |
| 11 | 11 |
"sync" |
| 12 | 12 |
|
| 13 | 13 |
"github.com/docker/docker/image" |
| 14 |
+ "github.com/docker/docker/pkg/parsers" |
|
| 14 | 15 |
"github.com/docker/docker/utils" |
| 15 | 16 |
) |
| 16 | 17 |
|
| ... | ... |
@@ -72,7 +73,7 @@ func (store *TagStore) reload() error {
|
| 72 | 72 |
func (store *TagStore) LookupImage(name string) (*image.Image, error) {
|
| 73 | 73 |
// FIXME: standardize on returning nil when the image doesn't exist, and err for everything else |
| 74 | 74 |
// (so we can pass all errors here) |
| 75 |
- repos, tag := utils.ParseRepositoryTag(name) |
|
| 75 |
+ repos, tag := parsers.ParseRepositoryTag(name) |
|
| 76 | 76 |
if tag == "" {
|
| 77 | 77 |
tag = DEFAULTTAG |
| 78 | 78 |
} |
| ... | ... |
@@ -8,7 +8,7 @@ import ( |
| 8 | 8 |
"strconv" |
| 9 | 9 |
"strings" |
| 10 | 10 |
|
| 11 |
- "github.com/docker/docker/utils" |
|
| 11 |
+ "github.com/docker/docker/pkg/parsers" |
|
| 12 | 12 |
) |
| 13 | 13 |
|
| 14 | 14 |
const ( |
| ... | ... |
@@ -103,7 +103,7 @@ func ParsePortSpecs(ports []string) (map[Port]struct{}, map[Port][]PortBinding,
|
| 103 | 103 |
rawPort = fmt.Sprintf(":%s", rawPort)
|
| 104 | 104 |
} |
| 105 | 105 |
|
| 106 |
- parts, err := utils.PartParser(PortSpecTemplate, rawPort) |
|
| 106 |
+ parts, err := parsers.PartParser(PortSpecTemplate, rawPort) |
|
| 107 | 107 |
if err != nil {
|
| 108 | 108 |
return nil, nil, err |
| 109 | 109 |
} |
| ... | ... |
@@ -8,7 +8,7 @@ import ( |
| 8 | 8 |
"regexp" |
| 9 | 9 |
"strings" |
| 10 | 10 |
|
| 11 |
- "github.com/docker/docker/utils" |
|
| 11 |
+ "github.com/docker/docker/pkg/parsers" |
|
| 12 | 12 |
) |
| 13 | 13 |
|
| 14 | 14 |
// ListOpts type |
| ... | ... |
@@ -94,7 +94,7 @@ func ValidateAttach(val string) (string, error) {
|
| 94 | 94 |
} |
| 95 | 95 |
|
| 96 | 96 |
func ValidateLink(val string) (string, error) {
|
| 97 |
- if _, err := utils.PartParser("name:alias", val); err != nil {
|
|
| 97 |
+ if _, err := parsers.PartParser("name:alias", val); err != nil {
|
|
| 98 | 98 |
return val, err |
| 99 | 99 |
} |
| 100 | 100 |
return val, nil |
| 0 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,63 @@ |
| 0 |
+package filters |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "encoding/json" |
|
| 4 |
+ "errors" |
|
| 5 |
+ "strings" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+type Args map[string][]string |
|
| 9 |
+ |
|
| 10 |
+// Parse the argument to the filter flag. Like |
|
| 11 |
+// |
|
| 12 |
+// `docker ps -f 'created=today' -f 'image.name=ubuntu*'` |
|
| 13 |
+// |
|
| 14 |
+// If prev map is provided, then it is appended to, and returned. By default a new |
|
| 15 |
+// map is created. |
|
| 16 |
+func ParseFlag(arg string, prev Args) (Args, error) {
|
|
| 17 |
+ var filters Args = prev |
|
| 18 |
+ if prev == nil {
|
|
| 19 |
+ filters = Args{}
|
|
| 20 |
+ } |
|
| 21 |
+ if len(arg) == 0 {
|
|
| 22 |
+ return filters, nil |
|
| 23 |
+ } |
|
| 24 |
+ |
|
| 25 |
+ if !strings.Contains(arg, "=") {
|
|
| 26 |
+ return filters, ErrorBadFormat |
|
| 27 |
+ } |
|
| 28 |
+ |
|
| 29 |
+ f := strings.SplitN(arg, "=", 2) |
|
| 30 |
+ filters[f[0]] = append(filters[f[0]], f[1]) |
|
| 31 |
+ |
|
| 32 |
+ return filters, nil |
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+var ErrorBadFormat = errors.New("bad format of filter (expected name=value)")
|
|
| 36 |
+ |
|
| 37 |
+// packs the Args into an string for easy transport from client to server |
|
| 38 |
+func ToParam(a Args) (string, error) {
|
|
| 39 |
+ // this way we don't URL encode {}, just empty space
|
|
| 40 |
+ if len(a) == 0 {
|
|
| 41 |
+ return "", nil |
|
| 42 |
+ } |
|
| 43 |
+ |
|
| 44 |
+ buf, err := json.Marshal(a) |
|
| 45 |
+ if err != nil {
|
|
| 46 |
+ return "", err |
|
| 47 |
+ } |
|
| 48 |
+ return string(buf), nil |
|
| 49 |
+} |
|
| 50 |
+ |
|
| 51 |
+// unpacks the filter Args |
|
| 52 |
+func FromParam(p string) (Args, error) {
|
|
| 53 |
+ args := Args{}
|
|
| 54 |
+ if len(p) == 0 {
|
|
| 55 |
+ return args, nil |
|
| 56 |
+ } |
|
| 57 |
+ err := json.Unmarshal([]byte(p), &args) |
|
| 58 |
+ if err != nil {
|
|
| 59 |
+ return nil, err |
|
| 60 |
+ } |
|
| 61 |
+ return args, nil |
|
| 62 |
+} |
| 0 | 63 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,78 @@ |
| 0 |
+package filters |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "sort" |
|
| 4 |
+ "testing" |
|
| 5 |
+) |
|
| 6 |
+ |
|
| 7 |
+func TestParseArgs(t *testing.T) {
|
|
| 8 |
+ // equivalent of `docker ps -f 'created=today' -f 'image.name=ubuntu*' -f 'image.name=*untu'` |
|
| 9 |
+ flagArgs := []string{
|
|
| 10 |
+ "created=today", |
|
| 11 |
+ "image.name=ubuntu*", |
|
| 12 |
+ "image.name=*untu", |
|
| 13 |
+ } |
|
| 14 |
+ var ( |
|
| 15 |
+ args = Args{}
|
|
| 16 |
+ err error |
|
| 17 |
+ ) |
|
| 18 |
+ for i := range flagArgs {
|
|
| 19 |
+ args, err = ParseFlag(flagArgs[i], args) |
|
| 20 |
+ if err != nil {
|
|
| 21 |
+ t.Errorf("failed to parse %s: %s", flagArgs[i], err)
|
|
| 22 |
+ } |
|
| 23 |
+ } |
|
| 24 |
+ if len(args["created"]) != 1 {
|
|
| 25 |
+ t.Errorf("failed to set this arg")
|
|
| 26 |
+ } |
|
| 27 |
+ if len(args["image.name"]) != 2 {
|
|
| 28 |
+ t.Errorf("the args should have collapsed")
|
|
| 29 |
+ } |
|
| 30 |
+} |
|
| 31 |
+ |
|
| 32 |
+func TestParam(t *testing.T) {
|
|
| 33 |
+ a := Args{
|
|
| 34 |
+ "created": []string{"today"},
|
|
| 35 |
+ "image.name": []string{"ubuntu*", "*untu"},
|
|
| 36 |
+ } |
|
| 37 |
+ |
|
| 38 |
+ v, err := ToParam(a) |
|
| 39 |
+ if err != nil {
|
|
| 40 |
+ t.Errorf("failed to marshal the filters: %s", err)
|
|
| 41 |
+ } |
|
| 42 |
+ v1, err := FromParam(v) |
|
| 43 |
+ if err != nil {
|
|
| 44 |
+ t.Errorf("%s", err)
|
|
| 45 |
+ } |
|
| 46 |
+ for key, vals := range v1 {
|
|
| 47 |
+ if _, ok := a[key]; !ok {
|
|
| 48 |
+ t.Errorf("could not find key %s in original set", key)
|
|
| 49 |
+ } |
|
| 50 |
+ sort.Strings(vals) |
|
| 51 |
+ sort.Strings(a[key]) |
|
| 52 |
+ if len(vals) != len(a[key]) {
|
|
| 53 |
+ t.Errorf("value lengths ought to match")
|
|
| 54 |
+ continue |
|
| 55 |
+ } |
|
| 56 |
+ for i := range vals {
|
|
| 57 |
+ if vals[i] != a[key][i] {
|
|
| 58 |
+ t.Errorf("expected %s, but got %s", a[key][i], vals[i])
|
|
| 59 |
+ } |
|
| 60 |
+ } |
|
| 61 |
+ } |
|
| 62 |
+} |
|
| 63 |
+ |
|
| 64 |
+func TestEmpty(t *testing.T) {
|
|
| 65 |
+ a := Args{}
|
|
| 66 |
+ v, err := ToParam(a) |
|
| 67 |
+ if err != nil {
|
|
| 68 |
+ t.Errorf("failed to marshal the filters: %s", err)
|
|
| 69 |
+ } |
|
| 70 |
+ v1, err := FromParam(v) |
|
| 71 |
+ if err != nil {
|
|
| 72 |
+ t.Errorf("%s", err)
|
|
| 73 |
+ } |
|
| 74 |
+ if len(a) != len(v1) {
|
|
| 75 |
+ t.Errorf("these should both be empty sets")
|
|
| 76 |
+ } |
|
| 77 |
+} |
| 0 | 78 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,93 @@ |
| 0 |
+package kernel |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "errors" |
|
| 5 |
+ "fmt" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+type KernelVersionInfo struct {
|
|
| 9 |
+ Kernel int |
|
| 10 |
+ Major int |
|
| 11 |
+ Minor int |
|
| 12 |
+ Flavor string |
|
| 13 |
+} |
|
| 14 |
+ |
|
| 15 |
+func (k *KernelVersionInfo) String() string {
|
|
| 16 |
+ return fmt.Sprintf("%d.%d.%d%s", k.Kernel, k.Major, k.Minor, k.Flavor)
|
|
| 17 |
+} |
|
| 18 |
+ |
|
| 19 |
+// Compare two KernelVersionInfo struct. |
|
| 20 |
+// Returns -1 if a < b, 0 if a == b, 1 it a > b |
|
| 21 |
+func CompareKernelVersion(a, b *KernelVersionInfo) int {
|
|
| 22 |
+ if a.Kernel < b.Kernel {
|
|
| 23 |
+ return -1 |
|
| 24 |
+ } else if a.Kernel > b.Kernel {
|
|
| 25 |
+ return 1 |
|
| 26 |
+ } |
|
| 27 |
+ |
|
| 28 |
+ if a.Major < b.Major {
|
|
| 29 |
+ return -1 |
|
| 30 |
+ } else if a.Major > b.Major {
|
|
| 31 |
+ return 1 |
|
| 32 |
+ } |
|
| 33 |
+ |
|
| 34 |
+ if a.Minor < b.Minor {
|
|
| 35 |
+ return -1 |
|
| 36 |
+ } else if a.Minor > b.Minor {
|
|
| 37 |
+ return 1 |
|
| 38 |
+ } |
|
| 39 |
+ |
|
| 40 |
+ return 0 |
|
| 41 |
+} |
|
| 42 |
+ |
|
| 43 |
+func GetKernelVersion() (*KernelVersionInfo, error) {
|
|
| 44 |
+ var ( |
|
| 45 |
+ err error |
|
| 46 |
+ ) |
|
| 47 |
+ |
|
| 48 |
+ uts, err := uname() |
|
| 49 |
+ if err != nil {
|
|
| 50 |
+ return nil, err |
|
| 51 |
+ } |
|
| 52 |
+ |
|
| 53 |
+ release := make([]byte, len(uts.Release)) |
|
| 54 |
+ |
|
| 55 |
+ i := 0 |
|
| 56 |
+ for _, c := range uts.Release {
|
|
| 57 |
+ release[i] = byte(c) |
|
| 58 |
+ i++ |
|
| 59 |
+ } |
|
| 60 |
+ |
|
| 61 |
+ // Remove the \x00 from the release for Atoi to parse correctly |
|
| 62 |
+ release = release[:bytes.IndexByte(release, 0)] |
|
| 63 |
+ |
|
| 64 |
+ return ParseRelease(string(release)) |
|
| 65 |
+} |
|
| 66 |
+ |
|
| 67 |
+func ParseRelease(release string) (*KernelVersionInfo, error) {
|
|
| 68 |
+ var ( |
|
| 69 |
+ kernel, major, minor, parsed int |
|
| 70 |
+ flavor, partial string |
|
| 71 |
+ ) |
|
| 72 |
+ |
|
| 73 |
+ // Ignore error from Sscanf to allow an empty flavor. Instead, just |
|
| 74 |
+ // make sure we got all the version numbers. |
|
| 75 |
+ parsed, _ = fmt.Sscanf(release, "%d.%d%s", &kernel, &major, &partial) |
|
| 76 |
+ if parsed < 2 {
|
|
| 77 |
+ return nil, errors.New("Can't parse kernel version " + release)
|
|
| 78 |
+ } |
|
| 79 |
+ |
|
| 80 |
+ // sometimes we have 3.12.25-gentoo, but sometimes we just have 3.12-1-amd64 |
|
| 81 |
+ parsed, _ = fmt.Sscanf(partial, ".%d%s", &minor, &flavor) |
|
| 82 |
+ if parsed < 1 {
|
|
| 83 |
+ flavor = partial |
|
| 84 |
+ } |
|
| 85 |
+ |
|
| 86 |
+ return &KernelVersionInfo{
|
|
| 87 |
+ Kernel: kernel, |
|
| 88 |
+ Major: major, |
|
| 89 |
+ Minor: minor, |
|
| 90 |
+ Flavor: flavor, |
|
| 91 |
+ }, nil |
|
| 92 |
+} |
| 0 | 93 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,61 @@ |
| 0 |
+package kernel |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "testing" |
|
| 4 |
+) |
|
| 5 |
+ |
|
| 6 |
+func assertParseRelease(t *testing.T, release string, b *KernelVersionInfo, result int) {
|
|
| 7 |
+ var ( |
|
| 8 |
+ a *KernelVersionInfo |
|
| 9 |
+ ) |
|
| 10 |
+ a, _ = ParseRelease(release) |
|
| 11 |
+ |
|
| 12 |
+ if r := CompareKernelVersion(a, b); r != result {
|
|
| 13 |
+ t.Fatalf("Unexpected kernel version comparison result. Found %d, expected %d", r, result)
|
|
| 14 |
+ } |
|
| 15 |
+ if a.Flavor != b.Flavor {
|
|
| 16 |
+ t.Fatalf("Unexpected parsed kernel flavor. Found %s, expected %s", a.Flavor, b.Flavor)
|
|
| 17 |
+ } |
|
| 18 |
+} |
|
| 19 |
+ |
|
| 20 |
+func TestParseRelease(t *testing.T) {
|
|
| 21 |
+ assertParseRelease(t, "3.8.0", &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}, 0)
|
|
| 22 |
+ assertParseRelease(t, "3.4.54.longterm-1", &KernelVersionInfo{Kernel: 3, Major: 4, Minor: 54, Flavor: ".longterm-1"}, 0)
|
|
| 23 |
+ assertParseRelease(t, "3.4.54.longterm-1", &KernelVersionInfo{Kernel: 3, Major: 4, Minor: 54, Flavor: ".longterm-1"}, 0)
|
|
| 24 |
+ assertParseRelease(t, "3.8.0-19-generic", &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0, Flavor: "-19-generic"}, 0)
|
|
| 25 |
+ assertParseRelease(t, "3.12.8tag", &KernelVersionInfo{Kernel: 3, Major: 12, Minor: 8, Flavor: "tag"}, 0)
|
|
| 26 |
+ assertParseRelease(t, "3.12-1-amd64", &KernelVersionInfo{Kernel: 3, Major: 12, Minor: 0, Flavor: "-1-amd64"}, 0)
|
|
| 27 |
+} |
|
| 28 |
+ |
|
| 29 |
+func assertKernelVersion(t *testing.T, a, b *KernelVersionInfo, result int) {
|
|
| 30 |
+ if r := CompareKernelVersion(a, b); r != result {
|
|
| 31 |
+ t.Fatalf("Unexpected kernel version comparison result. Found %d, expected %d", r, result)
|
|
| 32 |
+ } |
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+func TestCompareKernelVersion(t *testing.T) {
|
|
| 36 |
+ assertKernelVersion(t, |
|
| 37 |
+ &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
|
| 38 |
+ &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
|
| 39 |
+ 0) |
|
| 40 |
+ assertKernelVersion(t, |
|
| 41 |
+ &KernelVersionInfo{Kernel: 2, Major: 6, Minor: 0},
|
|
| 42 |
+ &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
|
| 43 |
+ -1) |
|
| 44 |
+ assertKernelVersion(t, |
|
| 45 |
+ &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
|
| 46 |
+ &KernelVersionInfo{Kernel: 2, Major: 6, Minor: 0},
|
|
| 47 |
+ 1) |
|
| 48 |
+ assertKernelVersion(t, |
|
| 49 |
+ &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
|
| 50 |
+ &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
|
| 51 |
+ 0) |
|
| 52 |
+ assertKernelVersion(t, |
|
| 53 |
+ &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 5},
|
|
| 54 |
+ &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
|
| 55 |
+ 1) |
|
| 56 |
+ assertKernelVersion(t, |
|
| 57 |
+ &KernelVersionInfo{Kernel: 3, Major: 0, Minor: 20},
|
|
| 58 |
+ &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
|
| 59 |
+ -1) |
|
| 60 |
+} |
| 0 | 61 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,18 @@ |
| 0 |
+// +build amd64 |
|
| 1 |
+ |
|
| 2 |
+package kernel |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "syscall" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+type Utsname syscall.Utsname |
|
| 9 |
+ |
|
| 10 |
+func uname() (*syscall.Utsname, error) {
|
|
| 11 |
+ uts := &syscall.Utsname{}
|
|
| 12 |
+ |
|
| 13 |
+ if err := syscall.Uname(uts); err != nil {
|
|
| 14 |
+ return nil, err |
|
| 15 |
+ } |
|
| 16 |
+ return uts, nil |
|
| 17 |
+} |
| 0 | 18 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,15 @@ |
| 0 |
+// +build !linux !amd64 |
|
| 1 |
+ |
|
| 2 |
+package kernel |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "errors" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+type Utsname struct {
|
|
| 9 |
+ Release [65]byte |
|
| 10 |
+} |
|
| 11 |
+ |
|
| 12 |
+func uname() (*Utsname, error) {
|
|
| 13 |
+ return nil, errors.New("Kernel version detection is available only on linux")
|
|
| 14 |
+} |
| 0 | 15 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,110 @@ |
| 0 |
+package parsers |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "strconv" |
|
| 5 |
+ "strings" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+// FIXME: Change this not to receive default value as parameter |
|
| 9 |
+func ParseHost(defaultHost string, defaultUnix, addr string) (string, error) {
|
|
| 10 |
+ var ( |
|
| 11 |
+ proto string |
|
| 12 |
+ host string |
|
| 13 |
+ port int |
|
| 14 |
+ ) |
|
| 15 |
+ addr = strings.TrimSpace(addr) |
|
| 16 |
+ switch {
|
|
| 17 |
+ case addr == "tcp://": |
|
| 18 |
+ return "", fmt.Errorf("Invalid bind address format: %s", addr)
|
|
| 19 |
+ case strings.HasPrefix(addr, "unix://"): |
|
| 20 |
+ proto = "unix" |
|
| 21 |
+ addr = strings.TrimPrefix(addr, "unix://") |
|
| 22 |
+ if addr == "" {
|
|
| 23 |
+ addr = defaultUnix |
|
| 24 |
+ } |
|
| 25 |
+ case strings.HasPrefix(addr, "tcp://"): |
|
| 26 |
+ proto = "tcp" |
|
| 27 |
+ addr = strings.TrimPrefix(addr, "tcp://") |
|
| 28 |
+ case strings.HasPrefix(addr, "fd://"): |
|
| 29 |
+ return addr, nil |
|
| 30 |
+ case addr == "": |
|
| 31 |
+ proto = "unix" |
|
| 32 |
+ addr = defaultUnix |
|
| 33 |
+ default: |
|
| 34 |
+ if strings.Contains(addr, "://") {
|
|
| 35 |
+ return "", fmt.Errorf("Invalid bind address protocol: %s", addr)
|
|
| 36 |
+ } |
|
| 37 |
+ proto = "tcp" |
|
| 38 |
+ } |
|
| 39 |
+ |
|
| 40 |
+ if proto != "unix" && strings.Contains(addr, ":") {
|
|
| 41 |
+ hostParts := strings.Split(addr, ":") |
|
| 42 |
+ if len(hostParts) != 2 {
|
|
| 43 |
+ return "", fmt.Errorf("Invalid bind address format: %s", addr)
|
|
| 44 |
+ } |
|
| 45 |
+ if hostParts[0] != "" {
|
|
| 46 |
+ host = hostParts[0] |
|
| 47 |
+ } else {
|
|
| 48 |
+ host = defaultHost |
|
| 49 |
+ } |
|
| 50 |
+ |
|
| 51 |
+ if p, err := strconv.Atoi(hostParts[1]); err == nil && p != 0 {
|
|
| 52 |
+ port = p |
|
| 53 |
+ } else {
|
|
| 54 |
+ return "", fmt.Errorf("Invalid bind address format: %s", addr)
|
|
| 55 |
+ } |
|
| 56 |
+ |
|
| 57 |
+ } else if proto == "tcp" && !strings.Contains(addr, ":") {
|
|
| 58 |
+ return "", fmt.Errorf("Invalid bind address format: %s", addr)
|
|
| 59 |
+ } else {
|
|
| 60 |
+ host = addr |
|
| 61 |
+ } |
|
| 62 |
+ if proto == "unix" {
|
|
| 63 |
+ return fmt.Sprintf("%s://%s", proto, host), nil
|
|
| 64 |
+ } |
|
| 65 |
+ return fmt.Sprintf("%s://%s:%d", proto, host, port), nil
|
|
| 66 |
+} |
|
| 67 |
+ |
|
| 68 |
+// Get a repos name and returns the right reposName + tag |
|
| 69 |
+// The tag can be confusing because of a port in a repository name. |
|
| 70 |
+// Ex: localhost.localdomain:5000/samalba/hipache:latest |
|
| 71 |
+func ParseRepositoryTag(repos string) (string, string) {
|
|
| 72 |
+ n := strings.LastIndex(repos, ":") |
|
| 73 |
+ if n < 0 {
|
|
| 74 |
+ return repos, "" |
|
| 75 |
+ } |
|
| 76 |
+ if tag := repos[n+1:]; !strings.Contains(tag, "/") {
|
|
| 77 |
+ return repos[:n], tag |
|
| 78 |
+ } |
|
| 79 |
+ return repos, "" |
|
| 80 |
+} |
|
| 81 |
+ |
|
| 82 |
+func PartParser(template, data string) (map[string]string, error) {
|
|
| 83 |
+ // ip:public:private |
|
| 84 |
+ var ( |
|
| 85 |
+ templateParts = strings.Split(template, ":") |
|
| 86 |
+ parts = strings.Split(data, ":") |
|
| 87 |
+ out = make(map[string]string, len(templateParts)) |
|
| 88 |
+ ) |
|
| 89 |
+ if len(parts) != len(templateParts) {
|
|
| 90 |
+ return nil, fmt.Errorf("Invalid format to parse. %s should match template %s", data, template)
|
|
| 91 |
+ } |
|
| 92 |
+ |
|
| 93 |
+ for i, t := range templateParts {
|
|
| 94 |
+ value := "" |
|
| 95 |
+ if len(parts) > i {
|
|
| 96 |
+ value = parts[i] |
|
| 97 |
+ } |
|
| 98 |
+ out[t] = value |
|
| 99 |
+ } |
|
| 100 |
+ return out, nil |
|
| 101 |
+} |
|
| 102 |
+ |
|
| 103 |
+func ParseKeyValueOpt(opt string) (string, string, error) {
|
|
| 104 |
+ parts := strings.SplitN(opt, "=", 2) |
|
| 105 |
+ if len(parts) != 2 {
|
|
| 106 |
+ return "", "", fmt.Errorf("Unable to parse key/value option: %s", opt)
|
|
| 107 |
+ } |
|
| 108 |
+ return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil |
|
| 109 |
+} |
| 0 | 110 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,83 @@ |
| 0 |
+package parsers |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "testing" |
|
| 4 |
+) |
|
| 5 |
+ |
|
| 6 |
+func TestParseHost(t *testing.T) {
|
|
| 7 |
+ var ( |
|
| 8 |
+ defaultHttpHost = "127.0.0.1" |
|
| 9 |
+ defaultUnix = "/var/run/docker.sock" |
|
| 10 |
+ ) |
|
| 11 |
+ if addr, err := ParseHost(defaultHttpHost, defaultUnix, "0.0.0.0"); err == nil {
|
|
| 12 |
+ t.Errorf("tcp 0.0.0.0 address expected error return, but err == nil, got %s", addr)
|
|
| 13 |
+ } |
|
| 14 |
+ if addr, err := ParseHost(defaultHttpHost, defaultUnix, "tcp://"); err == nil {
|
|
| 15 |
+ t.Errorf("default tcp:// address expected error return, but err == nil, got %s", addr)
|
|
| 16 |
+ } |
|
| 17 |
+ if addr, err := ParseHost(defaultHttpHost, defaultUnix, "0.0.0.1:5555"); err != nil || addr != "tcp://0.0.0.1:5555" {
|
|
| 18 |
+ t.Errorf("0.0.0.1:5555 -> expected tcp://0.0.0.1:5555, got %s", addr)
|
|
| 19 |
+ } |
|
| 20 |
+ if addr, err := ParseHost(defaultHttpHost, defaultUnix, ":6666"); err != nil || addr != "tcp://127.0.0.1:6666" {
|
|
| 21 |
+ t.Errorf(":6666 -> expected tcp://127.0.0.1:6666, got %s", addr)
|
|
| 22 |
+ } |
|
| 23 |
+ if addr, err := ParseHost(defaultHttpHost, defaultUnix, "tcp://:7777"); err != nil || addr != "tcp://127.0.0.1:7777" {
|
|
| 24 |
+ t.Errorf("tcp://:7777 -> expected tcp://127.0.0.1:7777, got %s", addr)
|
|
| 25 |
+ } |
|
| 26 |
+ if addr, err := ParseHost(defaultHttpHost, defaultUnix, ""); err != nil || addr != "unix:///var/run/docker.sock" {
|
|
| 27 |
+ t.Errorf("empty argument -> expected unix:///var/run/docker.sock, got %s", addr)
|
|
| 28 |
+ } |
|
| 29 |
+ if addr, err := ParseHost(defaultHttpHost, defaultUnix, "unix:///var/run/docker.sock"); err != nil || addr != "unix:///var/run/docker.sock" {
|
|
| 30 |
+ t.Errorf("unix:///var/run/docker.sock -> expected unix:///var/run/docker.sock, got %s", addr)
|
|
| 31 |
+ } |
|
| 32 |
+ if addr, err := ParseHost(defaultHttpHost, defaultUnix, "unix://"); err != nil || addr != "unix:///var/run/docker.sock" {
|
|
| 33 |
+ t.Errorf("unix:///var/run/docker.sock -> expected unix:///var/run/docker.sock, got %s", addr)
|
|
| 34 |
+ } |
|
| 35 |
+ if addr, err := ParseHost(defaultHttpHost, defaultUnix, "udp://127.0.0.1"); err == nil {
|
|
| 36 |
+ t.Errorf("udp protocol address expected error return, but err == nil. Got %s", addr)
|
|
| 37 |
+ } |
|
| 38 |
+ if addr, err := ParseHost(defaultHttpHost, defaultUnix, "udp://127.0.0.1:2375"); err == nil {
|
|
| 39 |
+ t.Errorf("udp protocol address expected error return, but err == nil. Got %s", addr)
|
|
| 40 |
+ } |
|
| 41 |
+} |
|
| 42 |
+ |
|
| 43 |
+func TestParseRepositoryTag(t *testing.T) {
|
|
| 44 |
+ if repo, tag := ParseRepositoryTag("root"); repo != "root" || tag != "" {
|
|
| 45 |
+ t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "root", "", repo, tag)
|
|
| 46 |
+ } |
|
| 47 |
+ if repo, tag := ParseRepositoryTag("root:tag"); repo != "root" || tag != "tag" {
|
|
| 48 |
+ t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "root", "tag", repo, tag)
|
|
| 49 |
+ } |
|
| 50 |
+ if repo, tag := ParseRepositoryTag("user/repo"); repo != "user/repo" || tag != "" {
|
|
| 51 |
+ t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "user/repo", "", repo, tag)
|
|
| 52 |
+ } |
|
| 53 |
+ if repo, tag := ParseRepositoryTag("user/repo:tag"); repo != "user/repo" || tag != "tag" {
|
|
| 54 |
+ t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "user/repo", "tag", repo, tag)
|
|
| 55 |
+ } |
|
| 56 |
+ if repo, tag := ParseRepositoryTag("url:5000/repo"); repo != "url:5000/repo" || tag != "" {
|
|
| 57 |
+ t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "url:5000/repo", "", repo, tag)
|
|
| 58 |
+ } |
|
| 59 |
+ if repo, tag := ParseRepositoryTag("url:5000/repo:tag"); repo != "url:5000/repo" || tag != "tag" {
|
|
| 60 |
+ t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "url:5000/repo", "tag", repo, tag)
|
|
| 61 |
+ } |
|
| 62 |
+} |
|
| 63 |
+ |
|
| 64 |
+func TestParsePortMapping(t *testing.T) {
|
|
| 65 |
+ data, err := PartParser("ip:public:private", "192.168.1.1:80:8080")
|
|
| 66 |
+ if err != nil {
|
|
| 67 |
+ t.Fatal(err) |
|
| 68 |
+ } |
|
| 69 |
+ |
|
| 70 |
+ if len(data) != 3 {
|
|
| 71 |
+ t.FailNow() |
|
| 72 |
+ } |
|
| 73 |
+ if data["ip"] != "192.168.1.1" {
|
|
| 74 |
+ t.Fail() |
|
| 75 |
+ } |
|
| 76 |
+ if data["public"] != "80" {
|
|
| 77 |
+ t.Fail() |
|
| 78 |
+ } |
|
| 79 |
+ if data["private"] != "8080" {
|
|
| 80 |
+ t.Fail() |
|
| 81 |
+ } |
|
| 82 |
+} |
| ... | ... |
@@ -25,6 +25,7 @@ import ( |
| 25 | 25 |
|
| 26 | 26 |
"github.com/docker/docker/dockerversion" |
| 27 | 27 |
"github.com/docker/docker/pkg/httputils" |
| 28 |
+ "github.com/docker/docker/pkg/parsers/kernel" |
|
| 28 | 29 |
"github.com/docker/docker/utils" |
| 29 | 30 |
) |
| 30 | 31 |
|
| ... | ... |
@@ -956,7 +957,7 @@ func HTTPRequestFactory(metaHeaders map[string][]string) *utils.HTTPRequestFacto |
| 956 | 956 |
httpVersion = append(httpVersion, &simpleVersionInfo{"docker", dockerversion.VERSION})
|
| 957 | 957 |
httpVersion = append(httpVersion, &simpleVersionInfo{"go", runtime.Version()})
|
| 958 | 958 |
httpVersion = append(httpVersion, &simpleVersionInfo{"git-commit", dockerversion.GITCOMMIT})
|
| 959 |
- if kernelVersion, err := utils.GetKernelVersion(); err == nil {
|
|
| 959 |
+ if kernelVersion, err := kernel.GetKernelVersion(); err == nil {
|
|
| 960 | 960 |
httpVersion = append(httpVersion, &simpleVersionInfo{"kernel", kernelVersion.String()})
|
| 961 | 961 |
} |
| 962 | 962 |
httpVersion = append(httpVersion, &simpleVersionInfo{"os", runtime.GOOS})
|
| ... | ... |
@@ -9,6 +9,7 @@ import ( |
| 9 | 9 |
"github.com/docker/docker/nat" |
| 10 | 10 |
"github.com/docker/docker/opts" |
| 11 | 11 |
flag "github.com/docker/docker/pkg/mflag" |
| 12 |
+ "github.com/docker/docker/pkg/parsers" |
|
| 12 | 13 |
"github.com/docker/docker/pkg/sysinfo" |
| 13 | 14 |
"github.com/docker/docker/pkg/units" |
| 14 | 15 |
"github.com/docker/docker/utils" |
| ... | ... |
@@ -306,7 +307,7 @@ func parseDriverOpts(opts opts.ListOpts) (map[string][]string, error) {
|
| 306 | 306 |
func parseKeyValueOpts(opts opts.ListOpts) ([]utils.KeyValuePair, error) {
|
| 307 | 307 |
out := make([]utils.KeyValuePair, opts.Len()) |
| 308 | 308 |
for i, o := range opts.GetAll() {
|
| 309 |
- k, v, err := utils.ParseKeyValueOpt(o) |
|
| 309 |
+ k, v, err := parsers.ParseKeyValueOpt(o) |
|
| 310 | 310 |
if err != nil {
|
| 311 | 311 |
return nil, err |
| 312 | 312 |
} |
| ... | ... |
@@ -3,14 +3,14 @@ package runconfig |
| 3 | 3 |
import ( |
| 4 | 4 |
"testing" |
| 5 | 5 |
|
| 6 |
- "github.com/docker/docker/utils" |
|
| 6 |
+ "github.com/docker/docker/pkg/parsers" |
|
| 7 | 7 |
) |
| 8 | 8 |
|
| 9 | 9 |
func TestParseLxcConfOpt(t *testing.T) {
|
| 10 | 10 |
opts := []string{"lxc.utsname=docker", "lxc.utsname = docker "}
|
| 11 | 11 |
|
| 12 | 12 |
for _, o := range opts {
|
| 13 |
- k, v, err := utils.ParseKeyValueOpt(o) |
|
| 13 |
+ k, v, err := parsers.ParseKeyValueOpt(o) |
|
| 14 | 14 |
if err != nil {
|
| 15 | 15 |
t.FailNow() |
| 16 | 16 |
} |
| ... | ... |
@@ -54,12 +54,14 @@ import ( |
| 54 | 54 |
"github.com/docker/docker/graph" |
| 55 | 55 |
"github.com/docker/docker/image" |
| 56 | 56 |
"github.com/docker/docker/pkg/graphdb" |
| 57 |
+ "github.com/docker/docker/pkg/parsers" |
|
| 58 |
+ "github.com/docker/docker/pkg/parsers/filters" |
|
| 59 |
+ "github.com/docker/docker/pkg/parsers/kernel" |
|
| 57 | 60 |
"github.com/docker/docker/pkg/signal" |
| 58 | 61 |
"github.com/docker/docker/pkg/tailfile" |
| 59 | 62 |
"github.com/docker/docker/registry" |
| 60 | 63 |
"github.com/docker/docker/runconfig" |
| 61 | 64 |
"github.com/docker/docker/utils" |
| 62 |
- "github.com/docker/docker/utils/filters" |
|
| 63 | 65 |
) |
| 64 | 66 |
|
| 65 | 67 |
func (srv *Server) handlerWrap(h engine.Handler) engine.Handler {
|
| ... | ... |
@@ -383,7 +385,7 @@ func (srv *Server) ImageExport(job *engine.Job) engine.Status {
|
| 383 | 383 |
} |
| 384 | 384 |
if img != nil {
|
| 385 | 385 |
// This is a named image like 'busybox:latest' |
| 386 |
- repoName, repoTag := utils.ParseRepositoryTag(name) |
|
| 386 |
+ repoName, repoTag := parsers.ParseRepositoryTag(name) |
|
| 387 | 387 |
if err := srv.exportImage(job.Eng, img.ID, tempdir); err != nil {
|
| 388 | 388 |
return job.Error(err) |
| 389 | 389 |
} |
| ... | ... |
@@ -493,7 +495,7 @@ func (srv *Server) Build(job *engine.Job) engine.Status {
|
| 493 | 493 |
) |
| 494 | 494 |
job.GetenvJson("authConfig", authConfig)
|
| 495 | 495 |
job.GetenvJson("configFile", configFile)
|
| 496 |
- repoName, tag = utils.ParseRepositoryTag(repoName) |
|
| 496 |
+ repoName, tag = parsers.ParseRepositoryTag(repoName) |
|
| 497 | 497 |
|
| 498 | 498 |
if remoteURL == "" {
|
| 499 | 499 |
context = ioutil.NopCloser(job.Stdin) |
| ... | ... |
@@ -789,7 +791,7 @@ func (srv *Server) DockerInfo(job *engine.Job) engine.Status {
|
| 789 | 789 |
imgcount = len(images) |
| 790 | 790 |
} |
| 791 | 791 |
kernelVersion := "<unknown>" |
| 792 |
- if kv, err := utils.GetKernelVersion(); err == nil {
|
|
| 792 |
+ if kv, err := kernel.GetKernelVersion(); err == nil {
|
|
| 793 | 793 |
kernelVersion = kv.String() |
| 794 | 794 |
} |
| 795 | 795 |
|
| ... | ... |
@@ -1746,7 +1748,7 @@ func (srv *Server) ContainerCreate(job *engine.Job) engine.Status {
|
| 1746 | 1746 |
container, buildWarnings, err := srv.daemon.Create(config, name) |
| 1747 | 1747 |
if err != nil {
|
| 1748 | 1748 |
if srv.daemon.Graph().IsNotExist(err) {
|
| 1749 |
- _, tag := utils.ParseRepositoryTag(config.Image) |
|
| 1749 |
+ _, tag := parsers.ParseRepositoryTag(config.Image) |
|
| 1750 | 1750 |
if tag == "" {
|
| 1751 | 1751 |
tag = graph.DEFAULTTAG |
| 1752 | 1752 |
} |
| ... | ... |
@@ -1924,7 +1926,7 @@ func (srv *Server) DeleteImage(name string, imgs *engine.Table, first, force, no |
| 1924 | 1924 |
tagDeleted bool |
| 1925 | 1925 |
) |
| 1926 | 1926 |
|
| 1927 |
- repoName, tag = utils.ParseRepositoryTag(name) |
|
| 1927 |
+ repoName, tag = parsers.ParseRepositoryTag(name) |
|
| 1928 | 1928 |
if tag == "" {
|
| 1929 | 1929 |
tag = graph.DEFAULTTAG |
| 1930 | 1930 |
} |
| ... | ... |
@@ -1950,7 +1952,7 @@ func (srv *Server) DeleteImage(name string, imgs *engine.Table, first, force, no |
| 1950 | 1950 |
//If delete by id, see if the id belong only to one repository |
| 1951 | 1951 |
if repoName == "" {
|
| 1952 | 1952 |
for _, repoAndTag := range srv.daemon.Repositories().ByID()[img.ID] {
|
| 1953 |
- parsedRepo, parsedTag := utils.ParseRepositoryTag(repoAndTag) |
|
| 1953 |
+ parsedRepo, parsedTag := parsers.ParseRepositoryTag(repoAndTag) |
|
| 1954 | 1954 |
if repoName == "" || repoName == parsedRepo {
|
| 1955 | 1955 |
repoName = parsedRepo |
| 1956 | 1956 |
if parsedTag != "" {
|
| 1957 | 1957 |
deleted file mode 100644 |
| ... | ... |
@@ -1,63 +0,0 @@ |
| 1 |
-package filters |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "encoding/json" |
|
| 5 |
- "errors" |
|
| 6 |
- "strings" |
|
| 7 |
-) |
|
| 8 |
- |
|
| 9 |
-type Args map[string][]string |
|
| 10 |
- |
|
| 11 |
-// Parse the argument to the filter flag. Like |
|
| 12 |
-// |
|
| 13 |
-// `docker ps -f 'created=today' -f 'image.name=ubuntu*'` |
|
| 14 |
-// |
|
| 15 |
-// If prev map is provided, then it is appended to, and returned. By default a new |
|
| 16 |
-// map is created. |
|
| 17 |
-func ParseFlag(arg string, prev Args) (Args, error) {
|
|
| 18 |
- var filters Args = prev |
|
| 19 |
- if prev == nil {
|
|
| 20 |
- filters = Args{}
|
|
| 21 |
- } |
|
| 22 |
- if len(arg) == 0 {
|
|
| 23 |
- return filters, nil |
|
| 24 |
- } |
|
| 25 |
- |
|
| 26 |
- if !strings.Contains(arg, "=") {
|
|
| 27 |
- return filters, ErrorBadFormat |
|
| 28 |
- } |
|
| 29 |
- |
|
| 30 |
- f := strings.SplitN(arg, "=", 2) |
|
| 31 |
- filters[f[0]] = append(filters[f[0]], f[1]) |
|
| 32 |
- |
|
| 33 |
- return filters, nil |
|
| 34 |
-} |
|
| 35 |
- |
|
| 36 |
-var ErrorBadFormat = errors.New("bad format of filter (expected name=value)")
|
|
| 37 |
- |
|
| 38 |
-// packs the Args into an string for easy transport from client to server |
|
| 39 |
-func ToParam(a Args) (string, error) {
|
|
| 40 |
- // this way we don't URL encode {}, just empty space
|
|
| 41 |
- if len(a) == 0 {
|
|
| 42 |
- return "", nil |
|
| 43 |
- } |
|
| 44 |
- |
|
| 45 |
- buf, err := json.Marshal(a) |
|
| 46 |
- if err != nil {
|
|
| 47 |
- return "", err |
|
| 48 |
- } |
|
| 49 |
- return string(buf), nil |
|
| 50 |
-} |
|
| 51 |
- |
|
| 52 |
-// unpacks the filter Args |
|
| 53 |
-func FromParam(p string) (Args, error) {
|
|
| 54 |
- args := Args{}
|
|
| 55 |
- if len(p) == 0 {
|
|
| 56 |
- return args, nil |
|
| 57 |
- } |
|
| 58 |
- err := json.Unmarshal([]byte(p), &args) |
|
| 59 |
- if err != nil {
|
|
| 60 |
- return nil, err |
|
| 61 |
- } |
|
| 62 |
- return args, nil |
|
| 63 |
-} |
| 64 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,78 +0,0 @@ |
| 1 |
-package filters |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "sort" |
|
| 5 |
- "testing" |
|
| 6 |
-) |
|
| 7 |
- |
|
| 8 |
-func TestParseArgs(t *testing.T) {
|
|
| 9 |
- // equivalent of `docker ps -f 'created=today' -f 'image.name=ubuntu*' -f 'image.name=*untu'` |
|
| 10 |
- flagArgs := []string{
|
|
| 11 |
- "created=today", |
|
| 12 |
- "image.name=ubuntu*", |
|
| 13 |
- "image.name=*untu", |
|
| 14 |
- } |
|
| 15 |
- var ( |
|
| 16 |
- args = Args{}
|
|
| 17 |
- err error |
|
| 18 |
- ) |
|
| 19 |
- for i := range flagArgs {
|
|
| 20 |
- args, err = ParseFlag(flagArgs[i], args) |
|
| 21 |
- if err != nil {
|
|
| 22 |
- t.Errorf("failed to parse %s: %s", flagArgs[i], err)
|
|
| 23 |
- } |
|
| 24 |
- } |
|
| 25 |
- if len(args["created"]) != 1 {
|
|
| 26 |
- t.Errorf("failed to set this arg")
|
|
| 27 |
- } |
|
| 28 |
- if len(args["image.name"]) != 2 {
|
|
| 29 |
- t.Errorf("the args should have collapsed")
|
|
| 30 |
- } |
|
| 31 |
-} |
|
| 32 |
- |
|
| 33 |
-func TestParam(t *testing.T) {
|
|
| 34 |
- a := Args{
|
|
| 35 |
- "created": []string{"today"},
|
|
| 36 |
- "image.name": []string{"ubuntu*", "*untu"},
|
|
| 37 |
- } |
|
| 38 |
- |
|
| 39 |
- v, err := ToParam(a) |
|
| 40 |
- if err != nil {
|
|
| 41 |
- t.Errorf("failed to marshal the filters: %s", err)
|
|
| 42 |
- } |
|
| 43 |
- v1, err := FromParam(v) |
|
| 44 |
- if err != nil {
|
|
| 45 |
- t.Errorf("%s", err)
|
|
| 46 |
- } |
|
| 47 |
- for key, vals := range v1 {
|
|
| 48 |
- if _, ok := a[key]; !ok {
|
|
| 49 |
- t.Errorf("could not find key %s in original set", key)
|
|
| 50 |
- } |
|
| 51 |
- sort.Strings(vals) |
|
| 52 |
- sort.Strings(a[key]) |
|
| 53 |
- if len(vals) != len(a[key]) {
|
|
| 54 |
- t.Errorf("value lengths ought to match")
|
|
| 55 |
- continue |
|
| 56 |
- } |
|
| 57 |
- for i := range vals {
|
|
| 58 |
- if vals[i] != a[key][i] {
|
|
| 59 |
- t.Errorf("expected %s, but got %s", a[key][i], vals[i])
|
|
| 60 |
- } |
|
| 61 |
- } |
|
| 62 |
- } |
|
| 63 |
-} |
|
| 64 |
- |
|
| 65 |
-func TestEmpty(t *testing.T) {
|
|
| 66 |
- a := Args{}
|
|
| 67 |
- v, err := ToParam(a) |
|
| 68 |
- if err != nil {
|
|
| 69 |
- t.Errorf("failed to marshal the filters: %s", err)
|
|
| 70 |
- } |
|
| 71 |
- v1, err := FromParam(v) |
|
| 72 |
- if err != nil {
|
|
| 73 |
- t.Errorf("%s", err)
|
|
| 74 |
- } |
|
| 75 |
- if len(a) != len(v1) {
|
|
| 76 |
- t.Errorf("these should both be empty sets")
|
|
| 77 |
- } |
|
| 78 |
-} |
| 79 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,18 +0,0 @@ |
| 1 |
-// +build amd64 |
|
| 2 |
- |
|
| 3 |
-package utils |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "syscall" |
|
| 7 |
-) |
|
| 8 |
- |
|
| 9 |
-type Utsname syscall.Utsname |
|
| 10 |
- |
|
| 11 |
-func uname() (*syscall.Utsname, error) {
|
|
| 12 |
- uts := &syscall.Utsname{}
|
|
| 13 |
- |
|
| 14 |
- if err := syscall.Uname(uts); err != nil {
|
|
| 15 |
- return nil, err |
|
| 16 |
- } |
|
| 17 |
- return uts, nil |
|
| 18 |
-} |
| 19 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,15 +0,0 @@ |
| 1 |
-// +build !linux !amd64 |
|
| 2 |
- |
|
| 3 |
-package utils |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "errors" |
|
| 7 |
-) |
|
| 8 |
- |
|
| 9 |
-type Utsname struct {
|
|
| 10 |
- Release [65]byte |
|
| 11 |
-} |
|
| 12 |
- |
|
| 13 |
-func uname() (*Utsname, error) {
|
|
| 14 |
- return nil, errors.New("Kernel version detection is available only on linux")
|
|
| 15 |
-} |
| ... | ... |
@@ -7,7 +7,6 @@ import ( |
| 7 | 7 |
"crypto/sha256" |
| 8 | 8 |
"encoding/hex" |
| 9 | 9 |
"encoding/json" |
| 10 |
- "errors" |
|
| 11 | 10 |
"fmt" |
| 12 | 11 |
"io" |
| 13 | 12 |
"io/ioutil" |
| ... | ... |
@@ -401,92 +400,6 @@ func HashData(src io.Reader) (string, error) {
|
| 401 | 401 |
return "sha256:" + hex.EncodeToString(h.Sum(nil)), nil |
| 402 | 402 |
} |
| 403 | 403 |
|
| 404 |
-type KernelVersionInfo struct {
|
|
| 405 |
- Kernel int |
|
| 406 |
- Major int |
|
| 407 |
- Minor int |
|
| 408 |
- Flavor string |
|
| 409 |
-} |
|
| 410 |
- |
|
| 411 |
-func (k *KernelVersionInfo) String() string {
|
|
| 412 |
- return fmt.Sprintf("%d.%d.%d%s", k.Kernel, k.Major, k.Minor, k.Flavor)
|
|
| 413 |
-} |
|
| 414 |
- |
|
| 415 |
-// Compare two KernelVersionInfo struct. |
|
| 416 |
-// Returns -1 if a < b, 0 if a == b, 1 it a > b |
|
| 417 |
-func CompareKernelVersion(a, b *KernelVersionInfo) int {
|
|
| 418 |
- if a.Kernel < b.Kernel {
|
|
| 419 |
- return -1 |
|
| 420 |
- } else if a.Kernel > b.Kernel {
|
|
| 421 |
- return 1 |
|
| 422 |
- } |
|
| 423 |
- |
|
| 424 |
- if a.Major < b.Major {
|
|
| 425 |
- return -1 |
|
| 426 |
- } else if a.Major > b.Major {
|
|
| 427 |
- return 1 |
|
| 428 |
- } |
|
| 429 |
- |
|
| 430 |
- if a.Minor < b.Minor {
|
|
| 431 |
- return -1 |
|
| 432 |
- } else if a.Minor > b.Minor {
|
|
| 433 |
- return 1 |
|
| 434 |
- } |
|
| 435 |
- |
|
| 436 |
- return 0 |
|
| 437 |
-} |
|
| 438 |
- |
|
| 439 |
-func GetKernelVersion() (*KernelVersionInfo, error) {
|
|
| 440 |
- var ( |
|
| 441 |
- err error |
|
| 442 |
- ) |
|
| 443 |
- |
|
| 444 |
- uts, err := uname() |
|
| 445 |
- if err != nil {
|
|
| 446 |
- return nil, err |
|
| 447 |
- } |
|
| 448 |
- |
|
| 449 |
- release := make([]byte, len(uts.Release)) |
|
| 450 |
- |
|
| 451 |
- i := 0 |
|
| 452 |
- for _, c := range uts.Release {
|
|
| 453 |
- release[i] = byte(c) |
|
| 454 |
- i++ |
|
| 455 |
- } |
|
| 456 |
- |
|
| 457 |
- // Remove the \x00 from the release for Atoi to parse correctly |
|
| 458 |
- release = release[:bytes.IndexByte(release, 0)] |
|
| 459 |
- |
|
| 460 |
- return ParseRelease(string(release)) |
|
| 461 |
-} |
|
| 462 |
- |
|
| 463 |
-func ParseRelease(release string) (*KernelVersionInfo, error) {
|
|
| 464 |
- var ( |
|
| 465 |
- kernel, major, minor, parsed int |
|
| 466 |
- flavor, partial string |
|
| 467 |
- ) |
|
| 468 |
- |
|
| 469 |
- // Ignore error from Sscanf to allow an empty flavor. Instead, just |
|
| 470 |
- // make sure we got all the version numbers. |
|
| 471 |
- parsed, _ = fmt.Sscanf(release, "%d.%d%s", &kernel, &major, &partial) |
|
| 472 |
- if parsed < 2 {
|
|
| 473 |
- return nil, errors.New("Can't parse kernel version " + release)
|
|
| 474 |
- } |
|
| 475 |
- |
|
| 476 |
- // sometimes we have 3.12.25-gentoo, but sometimes we just have 3.12-1-amd64 |
|
| 477 |
- parsed, _ = fmt.Sscanf(partial, ".%d%s", &minor, &flavor) |
|
| 478 |
- if parsed < 1 {
|
|
| 479 |
- flavor = partial |
|
| 480 |
- } |
|
| 481 |
- |
|
| 482 |
- return &KernelVersionInfo{
|
|
| 483 |
- Kernel: kernel, |
|
| 484 |
- Major: major, |
|
| 485 |
- Minor: minor, |
|
| 486 |
- Flavor: flavor, |
|
| 487 |
- }, nil |
|
| 488 |
-} |
|
| 489 |
- |
|
| 490 | 404 |
// FIXME: this is deprecated by CopyWithTar in archive.go |
| 491 | 405 |
func CopyDirectory(source, dest string) error {
|
| 492 | 406 |
if output, err := exec.Command("cp", "-ra", source, dest).CombinedOutput(); err != nil {
|
| ... | ... |
@@ -580,80 +493,6 @@ func GetLines(input []byte, commentMarker []byte) [][]byte {
|
| 580 | 580 |
return output |
| 581 | 581 |
} |
| 582 | 582 |
|
| 583 |
-// FIXME: Change this not to receive default value as parameter |
|
| 584 |
-func ParseHost(defaultHost string, defaultUnix, addr string) (string, error) {
|
|
| 585 |
- var ( |
|
| 586 |
- proto string |
|
| 587 |
- host string |
|
| 588 |
- port int |
|
| 589 |
- ) |
|
| 590 |
- addr = strings.TrimSpace(addr) |
|
| 591 |
- switch {
|
|
| 592 |
- case addr == "tcp://": |
|
| 593 |
- return "", fmt.Errorf("Invalid bind address format: %s", addr)
|
|
| 594 |
- case strings.HasPrefix(addr, "unix://"): |
|
| 595 |
- proto = "unix" |
|
| 596 |
- addr = strings.TrimPrefix(addr, "unix://") |
|
| 597 |
- if addr == "" {
|
|
| 598 |
- addr = defaultUnix |
|
| 599 |
- } |
|
| 600 |
- case strings.HasPrefix(addr, "tcp://"): |
|
| 601 |
- proto = "tcp" |
|
| 602 |
- addr = strings.TrimPrefix(addr, "tcp://") |
|
| 603 |
- case strings.HasPrefix(addr, "fd://"): |
|
| 604 |
- return addr, nil |
|
| 605 |
- case addr == "": |
|
| 606 |
- proto = "unix" |
|
| 607 |
- addr = defaultUnix |
|
| 608 |
- default: |
|
| 609 |
- if strings.Contains(addr, "://") {
|
|
| 610 |
- return "", fmt.Errorf("Invalid bind address protocol: %s", addr)
|
|
| 611 |
- } |
|
| 612 |
- proto = "tcp" |
|
| 613 |
- } |
|
| 614 |
- |
|
| 615 |
- if proto != "unix" && strings.Contains(addr, ":") {
|
|
| 616 |
- hostParts := strings.Split(addr, ":") |
|
| 617 |
- if len(hostParts) != 2 {
|
|
| 618 |
- return "", fmt.Errorf("Invalid bind address format: %s", addr)
|
|
| 619 |
- } |
|
| 620 |
- if hostParts[0] != "" {
|
|
| 621 |
- host = hostParts[0] |
|
| 622 |
- } else {
|
|
| 623 |
- host = defaultHost |
|
| 624 |
- } |
|
| 625 |
- |
|
| 626 |
- if p, err := strconv.Atoi(hostParts[1]); err == nil && p != 0 {
|
|
| 627 |
- port = p |
|
| 628 |
- } else {
|
|
| 629 |
- return "", fmt.Errorf("Invalid bind address format: %s", addr)
|
|
| 630 |
- } |
|
| 631 |
- |
|
| 632 |
- } else if proto == "tcp" && !strings.Contains(addr, ":") {
|
|
| 633 |
- return "", fmt.Errorf("Invalid bind address format: %s", addr)
|
|
| 634 |
- } else {
|
|
| 635 |
- host = addr |
|
| 636 |
- } |
|
| 637 |
- if proto == "unix" {
|
|
| 638 |
- return fmt.Sprintf("%s://%s", proto, host), nil
|
|
| 639 |
- } |
|
| 640 |
- return fmt.Sprintf("%s://%s:%d", proto, host, port), nil
|
|
| 641 |
-} |
|
| 642 |
- |
|
| 643 |
-// Get a repos name and returns the right reposName + tag |
|
| 644 |
-// The tag can be confusing because of a port in a repository name. |
|
| 645 |
-// Ex: localhost.localdomain:5000/samalba/hipache:latest |
|
| 646 |
-func ParseRepositoryTag(repos string) (string, string) {
|
|
| 647 |
- n := strings.LastIndex(repos, ":") |
|
| 648 |
- if n < 0 {
|
|
| 649 |
- return repos, "" |
|
| 650 |
- } |
|
| 651 |
- if tag := repos[n+1:]; !strings.Contains(tag, "/") {
|
|
| 652 |
- return repos[:n], tag |
|
| 653 |
- } |
|
| 654 |
- return repos, "" |
|
| 655 |
-} |
|
| 656 |
- |
|
| 657 | 583 |
// An StatusError reports an unsuccessful exit by a command. |
| 658 | 584 |
type StatusError struct {
|
| 659 | 585 |
Status string |
| ... | ... |
@@ -699,27 +538,6 @@ func ShellQuoteArguments(args []string) string {
|
| 699 | 699 |
return buf.String() |
| 700 | 700 |
} |
| 701 | 701 |
|
| 702 |
-func PartParser(template, data string) (map[string]string, error) {
|
|
| 703 |
- // ip:public:private |
|
| 704 |
- var ( |
|
| 705 |
- templateParts = strings.Split(template, ":") |
|
| 706 |
- parts = strings.Split(data, ":") |
|
| 707 |
- out = make(map[string]string, len(templateParts)) |
|
| 708 |
- ) |
|
| 709 |
- if len(parts) != len(templateParts) {
|
|
| 710 |
- return nil, fmt.Errorf("Invalid format to parse. %s should match template %s", data, template)
|
|
| 711 |
- } |
|
| 712 |
- |
|
| 713 |
- for i, t := range templateParts {
|
|
| 714 |
- value := "" |
|
| 715 |
- if len(parts) > i {
|
|
| 716 |
- value = parts[i] |
|
| 717 |
- } |
|
| 718 |
- out[t] = value |
|
| 719 |
- } |
|
| 720 |
- return out, nil |
|
| 721 |
-} |
|
| 722 |
- |
|
| 723 | 702 |
var globalTestID string |
| 724 | 703 |
|
| 725 | 704 |
// TestDirectory creates a new temporary directory and returns its path. |
| ... | ... |
@@ -833,14 +651,6 @@ func ReadSymlinkedDirectory(path string) (string, error) {
|
| 833 | 833 |
return realPath, nil |
| 834 | 834 |
} |
| 835 | 835 |
|
| 836 |
-func ParseKeyValueOpt(opt string) (string, string, error) {
|
|
| 837 |
- parts := strings.SplitN(opt, "=", 2) |
|
| 838 |
- if len(parts) != 2 {
|
|
| 839 |
- return "", "", fmt.Errorf("Unable to parse key/value option: %s", opt)
|
|
| 840 |
- } |
|
| 841 |
- return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil |
|
| 842 |
-} |
|
| 843 |
- |
|
| 844 | 836 |
// TreeSize walks a directory tree and returns its total size in bytes. |
| 845 | 837 |
func TreeSize(dir string) (size int64, err error) {
|
| 846 | 838 |
data := make(map[uint64]struct{})
|
| ... | ... |
@@ -34,97 +34,6 @@ func TestBufReader(t *testing.T) {
|
| 34 | 34 |
} |
| 35 | 35 |
} |
| 36 | 36 |
|
| 37 |
-func assertKernelVersion(t *testing.T, a, b *KernelVersionInfo, result int) {
|
|
| 38 |
- if r := CompareKernelVersion(a, b); r != result {
|
|
| 39 |
- t.Fatalf("Unexpected kernel version comparison result. Found %d, expected %d", r, result)
|
|
| 40 |
- } |
|
| 41 |
-} |
|
| 42 |
- |
|
| 43 |
-func TestCompareKernelVersion(t *testing.T) {
|
|
| 44 |
- assertKernelVersion(t, |
|
| 45 |
- &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
|
| 46 |
- &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
|
| 47 |
- 0) |
|
| 48 |
- assertKernelVersion(t, |
|
| 49 |
- &KernelVersionInfo{Kernel: 2, Major: 6, Minor: 0},
|
|
| 50 |
- &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
|
| 51 |
- -1) |
|
| 52 |
- assertKernelVersion(t, |
|
| 53 |
- &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
|
| 54 |
- &KernelVersionInfo{Kernel: 2, Major: 6, Minor: 0},
|
|
| 55 |
- 1) |
|
| 56 |
- assertKernelVersion(t, |
|
| 57 |
- &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
|
| 58 |
- &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
|
| 59 |
- 0) |
|
| 60 |
- assertKernelVersion(t, |
|
| 61 |
- &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 5},
|
|
| 62 |
- &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
|
| 63 |
- 1) |
|
| 64 |
- assertKernelVersion(t, |
|
| 65 |
- &KernelVersionInfo{Kernel: 3, Major: 0, Minor: 20},
|
|
| 66 |
- &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
|
|
| 67 |
- -1) |
|
| 68 |
-} |
|
| 69 |
- |
|
| 70 |
-func TestParseHost(t *testing.T) {
|
|
| 71 |
- var ( |
|
| 72 |
- defaultHttpHost = "127.0.0.1" |
|
| 73 |
- defaultUnix = "/var/run/docker.sock" |
|
| 74 |
- ) |
|
| 75 |
- if addr, err := ParseHost(defaultHttpHost, defaultUnix, "0.0.0.0"); err == nil {
|
|
| 76 |
- t.Errorf("tcp 0.0.0.0 address expected error return, but err == nil, got %s", addr)
|
|
| 77 |
- } |
|
| 78 |
- if addr, err := ParseHost(defaultHttpHost, defaultUnix, "tcp://"); err == nil {
|
|
| 79 |
- t.Errorf("default tcp:// address expected error return, but err == nil, got %s", addr)
|
|
| 80 |
- } |
|
| 81 |
- if addr, err := ParseHost(defaultHttpHost, defaultUnix, "0.0.0.1:5555"); err != nil || addr != "tcp://0.0.0.1:5555" {
|
|
| 82 |
- t.Errorf("0.0.0.1:5555 -> expected tcp://0.0.0.1:5555, got %s", addr)
|
|
| 83 |
- } |
|
| 84 |
- if addr, err := ParseHost(defaultHttpHost, defaultUnix, ":6666"); err != nil || addr != "tcp://127.0.0.1:6666" {
|
|
| 85 |
- t.Errorf(":6666 -> expected tcp://127.0.0.1:6666, got %s", addr)
|
|
| 86 |
- } |
|
| 87 |
- if addr, err := ParseHost(defaultHttpHost, defaultUnix, "tcp://:7777"); err != nil || addr != "tcp://127.0.0.1:7777" {
|
|
| 88 |
- t.Errorf("tcp://:7777 -> expected tcp://127.0.0.1:7777, got %s", addr)
|
|
| 89 |
- } |
|
| 90 |
- if addr, err := ParseHost(defaultHttpHost, defaultUnix, ""); err != nil || addr != "unix:///var/run/docker.sock" {
|
|
| 91 |
- t.Errorf("empty argument -> expected unix:///var/run/docker.sock, got %s", addr)
|
|
| 92 |
- } |
|
| 93 |
- if addr, err := ParseHost(defaultHttpHost, defaultUnix, "unix:///var/run/docker.sock"); err != nil || addr != "unix:///var/run/docker.sock" {
|
|
| 94 |
- t.Errorf("unix:///var/run/docker.sock -> expected unix:///var/run/docker.sock, got %s", addr)
|
|
| 95 |
- } |
|
| 96 |
- if addr, err := ParseHost(defaultHttpHost, defaultUnix, "unix://"); err != nil || addr != "unix:///var/run/docker.sock" {
|
|
| 97 |
- t.Errorf("unix:///var/run/docker.sock -> expected unix:///var/run/docker.sock, got %s", addr)
|
|
| 98 |
- } |
|
| 99 |
- if addr, err := ParseHost(defaultHttpHost, defaultUnix, "udp://127.0.0.1"); err == nil {
|
|
| 100 |
- t.Errorf("udp protocol address expected error return, but err == nil. Got %s", addr)
|
|
| 101 |
- } |
|
| 102 |
- if addr, err := ParseHost(defaultHttpHost, defaultUnix, "udp://127.0.0.1:2375"); err == nil {
|
|
| 103 |
- t.Errorf("udp protocol address expected error return, but err == nil. Got %s", addr)
|
|
| 104 |
- } |
|
| 105 |
-} |
|
| 106 |
- |
|
| 107 |
-func TestParseRepositoryTag(t *testing.T) {
|
|
| 108 |
- if repo, tag := ParseRepositoryTag("root"); repo != "root" || tag != "" {
|
|
| 109 |
- t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "root", "", repo, tag)
|
|
| 110 |
- } |
|
| 111 |
- if repo, tag := ParseRepositoryTag("root:tag"); repo != "root" || tag != "tag" {
|
|
| 112 |
- t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "root", "tag", repo, tag)
|
|
| 113 |
- } |
|
| 114 |
- if repo, tag := ParseRepositoryTag("user/repo"); repo != "user/repo" || tag != "" {
|
|
| 115 |
- t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "user/repo", "", repo, tag)
|
|
| 116 |
- } |
|
| 117 |
- if repo, tag := ParseRepositoryTag("user/repo:tag"); repo != "user/repo" || tag != "tag" {
|
|
| 118 |
- t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "user/repo", "tag", repo, tag)
|
|
| 119 |
- } |
|
| 120 |
- if repo, tag := ParseRepositoryTag("url:5000/repo"); repo != "url:5000/repo" || tag != "" {
|
|
| 121 |
- t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "url:5000/repo", "", repo, tag)
|
|
| 122 |
- } |
|
| 123 |
- if repo, tag := ParseRepositoryTag("url:5000/repo:tag"); repo != "url:5000/repo" || tag != "tag" {
|
|
| 124 |
- t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "url:5000/repo", "tag", repo, tag)
|
|
| 125 |
- } |
|
| 126 |
-} |
|
| 127 |
- |
|
| 128 | 37 |
func TestCheckLocalDns(t *testing.T) {
|
| 129 | 38 |
for resolv, result := range map[string]bool{`# Dynamic
|
| 130 | 39 |
nameserver 10.0.2.3 |
| ... | ... |
@@ -154,50 +63,6 @@ search docker.com`: true, |
| 154 | 154 |
} |
| 155 | 155 |
} |
| 156 | 156 |
} |
| 157 |
- |
|
| 158 |
-func assertParseRelease(t *testing.T, release string, b *KernelVersionInfo, result int) {
|
|
| 159 |
- var ( |
|
| 160 |
- a *KernelVersionInfo |
|
| 161 |
- ) |
|
| 162 |
- a, _ = ParseRelease(release) |
|
| 163 |
- |
|
| 164 |
- if r := CompareKernelVersion(a, b); r != result {
|
|
| 165 |
- t.Fatalf("Unexpected kernel version comparison result. Found %d, expected %d", r, result)
|
|
| 166 |
- } |
|
| 167 |
- if a.Flavor != b.Flavor {
|
|
| 168 |
- t.Fatalf("Unexpected parsed kernel flavor. Found %s, expected %s", a.Flavor, b.Flavor)
|
|
| 169 |
- } |
|
| 170 |
-} |
|
| 171 |
- |
|
| 172 |
-func TestParseRelease(t *testing.T) {
|
|
| 173 |
- assertParseRelease(t, "3.8.0", &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}, 0)
|
|
| 174 |
- assertParseRelease(t, "3.4.54.longterm-1", &KernelVersionInfo{Kernel: 3, Major: 4, Minor: 54, Flavor: ".longterm-1"}, 0)
|
|
| 175 |
- assertParseRelease(t, "3.4.54.longterm-1", &KernelVersionInfo{Kernel: 3, Major: 4, Minor: 54, Flavor: ".longterm-1"}, 0)
|
|
| 176 |
- assertParseRelease(t, "3.8.0-19-generic", &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0, Flavor: "-19-generic"}, 0)
|
|
| 177 |
- assertParseRelease(t, "3.12.8tag", &KernelVersionInfo{Kernel: 3, Major: 12, Minor: 8, Flavor: "tag"}, 0)
|
|
| 178 |
- assertParseRelease(t, "3.12-1-amd64", &KernelVersionInfo{Kernel: 3, Major: 12, Minor: 0, Flavor: "-1-amd64"}, 0)
|
|
| 179 |
-} |
|
| 180 |
- |
|
| 181 |
-func TestParsePortMapping(t *testing.T) {
|
|
| 182 |
- data, err := PartParser("ip:public:private", "192.168.1.1:80:8080")
|
|
| 183 |
- if err != nil {
|
|
| 184 |
- t.Fatal(err) |
|
| 185 |
- } |
|
| 186 |
- |
|
| 187 |
- if len(data) != 3 {
|
|
| 188 |
- t.FailNow() |
|
| 189 |
- } |
|
| 190 |
- if data["ip"] != "192.168.1.1" {
|
|
| 191 |
- t.Fail() |
|
| 192 |
- } |
|
| 193 |
- if data["public"] != "80" {
|
|
| 194 |
- t.Fail() |
|
| 195 |
- } |
|
| 196 |
- if data["private"] != "8080" {
|
|
| 197 |
- t.Fail() |
|
| 198 |
- } |
|
| 199 |
-} |
|
| 200 |
- |
|
| 201 | 157 |
func TestReplaceAndAppendEnvVars(t *testing.T) {
|
| 202 | 158 |
var ( |
| 203 | 159 |
d = []string{"HOME=/"}
|