From e26c4850136967cf0391213fc255dda610e74f87 Mon Sep 17 00:00:00 2001 From: David Gageot Date: Fri, 27 Nov 2015 18:30:44 +0100 Subject: [PATCH 1/2] Vendor samalba.dockerclient Signed-off-by: David Gageot --- Godeps/Godeps.json | 12 + .../docker/docker/pkg/units/MAINTAINERS | 2 + .../docker/docker/pkg/units/duration.go | 31 + .../docker/docker/pkg/units/size.go | 91 ++ .../src/code.google.com/p/go.net/LICENSE | 27 - .../src/code.google.com/p/go.net/PATENTS | 22 - .../src/github.com/Sirupsen/logrus/LICENSE | 21 - .../src/github.com/coreos/go-systemd/LICENSE | 191 ---- .../github.com/docker/libcontainer/LICENSE | 191 ---- .../src/github.com/docker/libcontainer/NOTICE | 16 - .../github.com/go-fsnotify/fsnotify/LICENSE | 28 - .../vendor/src/github.com/godbus/dbus/LICENSE | 25 - .../src/github.com/gorilla/context/LICENSE | 27 - .../vendor/src/github.com/gorilla/mux/LICENSE | 27 - .../vendor/src/github.com/kr/pty/License | 23 - .../github.com/syndtr/gocapability/LICENSE | 24 - .../src/github.com/tchap/go-patricia/LICENSE | 20 - .../samalba/dockerclient/.gitignore | 22 + .../libtrust => samalba/dockerclient}/LICENSE | 17 +- .../github.com/samalba/dockerclient/README.md | 98 ++ .../github.com/samalba/dockerclient/auth.go | 38 + .../samalba/dockerclient/dockerclient.go | 930 ++++++++++++++++++ .../samalba/dockerclient/example_responses.go | 13 + .../samalba/dockerclient/examples/events.go | 39 + .../dockerclient/examples/stats/stats.go | 43 + .../samalba/dockerclient/interface.go | 59 ++ .../samalba/dockerclient/mockclient/mock.go | 227 +++++ .../samalba/dockerclient/nopclient/nop.go | 191 ++++ .../github.com/samalba/dockerclient/types.go | 538 ++++++++++ .../github.com/samalba/dockerclient/utils.go | 33 + 30 files changed, 2381 insertions(+), 645 deletions(-) create mode 100644 vendor/github.com/docker/docker/pkg/units/MAINTAINERS create mode 100644 vendor/github.com/docker/docker/pkg/units/duration.go create mode 100644 vendor/github.com/docker/docker/pkg/units/size.go delete mode 100644 vendor/github.com/docker/docker/vendor/src/code.google.com/p/go.net/LICENSE delete mode 100644 vendor/github.com/docker/docker/vendor/src/code.google.com/p/go.net/PATENTS delete mode 100644 vendor/github.com/docker/docker/vendor/src/github.com/Sirupsen/logrus/LICENSE delete mode 100644 vendor/github.com/docker/docker/vendor/src/github.com/coreos/go-systemd/LICENSE delete mode 100644 vendor/github.com/docker/docker/vendor/src/github.com/docker/libcontainer/LICENSE delete mode 100644 vendor/github.com/docker/docker/vendor/src/github.com/docker/libcontainer/NOTICE delete mode 100644 vendor/github.com/docker/docker/vendor/src/github.com/go-fsnotify/fsnotify/LICENSE delete mode 100644 vendor/github.com/docker/docker/vendor/src/github.com/godbus/dbus/LICENSE delete mode 100644 vendor/github.com/docker/docker/vendor/src/github.com/gorilla/context/LICENSE delete mode 100644 vendor/github.com/docker/docker/vendor/src/github.com/gorilla/mux/LICENSE delete mode 100644 vendor/github.com/docker/docker/vendor/src/github.com/kr/pty/License delete mode 100644 vendor/github.com/docker/docker/vendor/src/github.com/syndtr/gocapability/LICENSE delete mode 100644 vendor/github.com/docker/docker/vendor/src/github.com/tchap/go-patricia/LICENSE create mode 100644 vendor/github.com/samalba/dockerclient/.gitignore rename vendor/github.com/{docker/docker/vendor/src/github.com/docker/libtrust => samalba/dockerclient}/LICENSE (94%) create mode 100644 vendor/github.com/samalba/dockerclient/README.md create mode 100644 vendor/github.com/samalba/dockerclient/auth.go create mode 100644 vendor/github.com/samalba/dockerclient/dockerclient.go create mode 100644 vendor/github.com/samalba/dockerclient/example_responses.go create mode 100644 vendor/github.com/samalba/dockerclient/examples/events.go create mode 100644 vendor/github.com/samalba/dockerclient/examples/stats/stats.go create mode 100644 vendor/github.com/samalba/dockerclient/interface.go create mode 100644 vendor/github.com/samalba/dockerclient/mockclient/mock.go create mode 100644 vendor/github.com/samalba/dockerclient/nopclient/nop.go create mode 100644 vendor/github.com/samalba/dockerclient/types.go create mode 100644 vendor/github.com/samalba/dockerclient/utils.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 30121d0f7b..5b15919608 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -5,6 +5,7 @@ "github.com/docker/machine", "github.com/docker/machine/cmd", "github.com/docker/machine/commands", + "github.com/docker/machine/commands/commandstest", "github.com/docker/machine/commands/mcndirs", "github.com/docker/machine/drivers/amazonec2", "github.com/docker/machine/drivers/amazonec2/amz", @@ -36,11 +37,13 @@ "github.com/docker/machine/libmachine/examples", "github.com/docker/machine/libmachine/host", "github.com/docker/machine/libmachine/hosttest", + "github.com/docker/machine/libmachine/libmachinetest", "github.com/docker/machine/libmachine/log", "github.com/docker/machine/libmachine/mcnerror", "github.com/docker/machine/libmachine/mcnflag", "github.com/docker/machine/libmachine/mcnutils", "github.com/docker/machine/libmachine/persist", + "github.com/docker/machine/libmachine/persist/persisttest", "github.com/docker/machine/libmachine/provider", "github.com/docker/machine/libmachine/provision", "github.com/docker/machine/libmachine/provision/pkgaction", @@ -76,6 +79,11 @@ "Comment": "v1.5.0", "Rev": "a8a31eff10544860d2188dddabdee4d727545796" }, + { + "ImportPath": "github.com/docker/docker/pkg/units", + "Comment": "v1.5.0", + "Rev": "a8a31eff10544860d2188dddabdee4d727545796" + }, { "ImportPath": "github.com/google/go-querystring/query", "Rev": "30f7a39f4a218feb5325f3aebc60c32a572a8274" @@ -93,6 +101,10 @@ "Comment": "v1.0.0-558-gce0f487", "Rev": "ce0f487f6747ab43c4e4404722df25349385bebd" }, + { + "ImportPath": "github.com/samalba/dockerclient", + "Rev": "82381805d3533c97cec74e1cc79b00ef45774571" + }, { "ImportPath": "github.com/skarademir/naturalsort", "Rev": "69a5d87bef620f77ee8508db30c846b3b84b111e" diff --git a/vendor/github.com/docker/docker/pkg/units/MAINTAINERS b/vendor/github.com/docker/docker/pkg/units/MAINTAINERS new file mode 100644 index 0000000000..96abeae570 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/units/MAINTAINERS @@ -0,0 +1,2 @@ +Victor Vieux (@vieux) +Jessie Frazelle (@jfrazelle) diff --git a/vendor/github.com/docker/docker/pkg/units/duration.go b/vendor/github.com/docker/docker/pkg/units/duration.go new file mode 100644 index 0000000000..cd33121496 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/units/duration.go @@ -0,0 +1,31 @@ +package units + +import ( + "fmt" + "time" +) + +// HumanDuration returns a human-readable approximation of a duration +// (eg. "About a minute", "4 hours ago", etc.) +func HumanDuration(d time.Duration) string { + if seconds := int(d.Seconds()); seconds < 1 { + return "Less than a second" + } else if seconds < 60 { + return fmt.Sprintf("%d seconds", seconds) + } else if minutes := int(d.Minutes()); minutes == 1 { + return "About a minute" + } else if minutes < 60 { + return fmt.Sprintf("%d minutes", minutes) + } else if hours := int(d.Hours()); hours == 1 { + return "About an hour" + } else if hours < 48 { + return fmt.Sprintf("%d hours", hours) + } else if hours < 24*7*2 { + return fmt.Sprintf("%d days", hours/24) + } else if hours < 24*30*3 { + return fmt.Sprintf("%d weeks", hours/24/7) + } else if hours < 24*365*2 { + return fmt.Sprintf("%d months", hours/24/30) + } + return fmt.Sprintf("%f years", d.Hours()/24/365) +} diff --git a/vendor/github.com/docker/docker/pkg/units/size.go b/vendor/github.com/docker/docker/pkg/units/size.go new file mode 100644 index 0000000000..7cfb57ba51 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/units/size.go @@ -0,0 +1,91 @@ +package units + +import ( + "fmt" + "regexp" + "strconv" + "strings" +) + +// See: http://en.wikipedia.org/wiki/Binary_prefix +const ( + // Decimal + + KB = 1000 + MB = 1000 * KB + GB = 1000 * MB + TB = 1000 * GB + PB = 1000 * TB + + // Binary + + KiB = 1024 + MiB = 1024 * KiB + GiB = 1024 * MiB + TiB = 1024 * GiB + PiB = 1024 * TiB +) + +type unitMap map[string]int64 + +var ( + decimalMap = unitMap{"k": KB, "m": MB, "g": GB, "t": TB, "p": PB} + binaryMap = unitMap{"k": KiB, "m": MiB, "g": GiB, "t": TiB, "p": PiB} + sizeRegex = regexp.MustCompile(`^(\d+)([kKmMgGtTpP])?[bB]?$`) +) + +var decimapAbbrs = []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"} +var binaryAbbrs = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"} + +// HumanSize returns a human-readable approximation of a size +// using SI standard (eg. "44kB", "17MB") +func HumanSize(size float64) string { + return intToString(float64(size), 1000.0, decimapAbbrs) +} + +func BytesSize(size float64) string { + return intToString(size, 1024.0, binaryAbbrs) +} + +func intToString(size, unit float64, _map []string) string { + i := 0 + for size >= unit { + size = size / unit + i++ + } + return fmt.Sprintf("%.4g %s", size, _map[i]) +} + +// FromHumanSize returns an integer from a human-readable specification of a +// size using SI standard (eg. "44kB", "17MB") +func FromHumanSize(size string) (int64, error) { + return parseSize(size, decimalMap) +} + +// RAMInBytes parses a human-readable string representing an amount of RAM +// in bytes, kibibytes, mebibytes, gibibytes, or tebibytes and +// returns the number of bytes, or -1 if the string is unparseable. +// Units are case-insensitive, and the 'b' suffix is optional. +func RAMInBytes(size string) (int64, error) { + return parseSize(size, binaryMap) +} + +// Parses the human-readable size string into the amount it represents +func parseSize(sizeStr string, uMap unitMap) (int64, error) { + matches := sizeRegex.FindStringSubmatch(sizeStr) + if len(matches) != 3 { + return -1, fmt.Errorf("invalid size: '%s'", sizeStr) + } + + size, err := strconv.ParseInt(matches[1], 10, 0) + if err != nil { + return -1, err + } + + unitPrefix := strings.ToLower(matches[2]) + if mul, ok := uMap[unitPrefix]; ok { + size *= mul + } + + return size, nil +} diff --git a/vendor/github.com/docker/docker/vendor/src/code.google.com/p/go.net/LICENSE b/vendor/github.com/docker/docker/vendor/src/code.google.com/p/go.net/LICENSE deleted file mode 100644 index 6a66aea5ea..0000000000 --- a/vendor/github.com/docker/docker/vendor/src/code.google.com/p/go.net/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/docker/docker/vendor/src/code.google.com/p/go.net/PATENTS b/vendor/github.com/docker/docker/vendor/src/code.google.com/p/go.net/PATENTS deleted file mode 100644 index 733099041f..0000000000 --- a/vendor/github.com/docker/docker/vendor/src/code.google.com/p/go.net/PATENTS +++ /dev/null @@ -1,22 +0,0 @@ -Additional IP Rights Grant (Patents) - -"This implementation" means the copyrightable works distributed by -Google as part of the Go project. - -Google hereby grants to You a perpetual, worldwide, non-exclusive, -no-charge, royalty-free, irrevocable (except as stated in this section) -patent license to make, have made, use, offer to sell, sell, import, -transfer and otherwise run, modify and propagate the contents of this -implementation of Go, where such license applies only to those patent -claims, both currently owned or controlled by Google and acquired in -the future, licensable by Google that are necessarily infringed by this -implementation of Go. This grant does not include claims that would be -infringed only as a consequence of further modification of this -implementation. If you or your agent or exclusive licensee institute or -order or agree to the institution of patent litigation against any -entity (including a cross-claim or counterclaim in a lawsuit) alleging -that this implementation of Go or any code incorporated within this -implementation of Go constitutes direct or contributory patent -infringement, or inducement of patent infringement, then any patent -rights granted to you under this License for this implementation of Go -shall terminate as of the date such litigation is filed. diff --git a/vendor/github.com/docker/docker/vendor/src/github.com/Sirupsen/logrus/LICENSE b/vendor/github.com/docker/docker/vendor/src/github.com/Sirupsen/logrus/LICENSE deleted file mode 100644 index f090cb42f3..0000000000 --- a/vendor/github.com/docker/docker/vendor/src/github.com/Sirupsen/logrus/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Simon Eskildsen - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/github.com/docker/docker/vendor/src/github.com/coreos/go-systemd/LICENSE b/vendor/github.com/docker/docker/vendor/src/github.com/coreos/go-systemd/LICENSE deleted file mode 100644 index 37ec93a14f..0000000000 --- a/vendor/github.com/docker/docker/vendor/src/github.com/coreos/go-systemd/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ -Apache License -Version 2.0, January 2004 -http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - -"License" shall mean the terms and conditions for use, reproduction, and -distribution as defined by Sections 1 through 9 of this document. - -"Licensor" shall mean the copyright owner or entity authorized by the copyright -owner that is granting the License. - -"Legal Entity" shall mean the union of the acting entity and all other entities -that control, are controlled by, or are under common control with that entity. -For the purposes of this definition, "control" means (i) the power, direct or -indirect, to cause the direction or management of such entity, whether by -contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the -outstanding shares, or (iii) beneficial ownership of such entity. - -"You" (or "Your") shall mean an individual or Legal Entity exercising -permissions granted by this License. - -"Source" form shall mean the preferred form for making modifications, including -but not limited to software source code, documentation source, and configuration -files. - -"Object" form shall mean any form resulting from mechanical transformation or -translation of a Source form, including but not limited to compiled object code, -generated documentation, and conversions to other media types. - -"Work" shall mean the work of authorship, whether in Source or Object form, made -available under the License, as indicated by a copyright notice that is included -in or attached to the work (an example is provided in the Appendix below). - -"Derivative Works" shall mean any work, whether in Source or Object form, that -is based on (or derived from) the Work and for which the editorial revisions, -annotations, elaborations, or other modifications represent, as a whole, an -original work of authorship. For the purposes of this License, Derivative Works -shall not include works that remain separable from, or merely link (or bind by -name) to the interfaces of, the Work and Derivative Works thereof. - -"Contribution" shall mean any work of authorship, including the original version -of the Work and any modifications or additions to that Work or Derivative Works -thereof, that is intentionally submitted to Licensor for inclusion in the Work -by the copyright owner or by an individual or Legal Entity authorized to submit -on behalf of the copyright owner. For the purposes of this definition, -"submitted" means any form of electronic, verbal, or written communication sent -to the Licensor or its representatives, including but not limited to -communication on electronic mailing lists, source code control systems, and -issue tracking systems that are managed by, or on behalf of, the Licensor for -the purpose of discussing and improving the Work, but excluding communication -that is conspicuously marked or otherwise designated in writing by the copyright -owner as "Not a Contribution." - -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf -of whom a Contribution has been received by Licensor and subsequently -incorporated within the Work. - -2. Grant of Copyright License. - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable copyright license to reproduce, prepare Derivative Works of, -publicly display, publicly perform, sublicense, and distribute the Work and such -Derivative Works in Source or Object form. - -3. Grant of Patent License. - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable (except as stated in this section) patent license to make, have -made, use, offer to sell, sell, import, and otherwise transfer the Work, where -such license applies only to those patent claims licensable by such Contributor -that are necessarily infringed by their Contribution(s) alone or by combination -of their Contribution(s) with the Work to which such Contribution(s) was -submitted. If You institute patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the Work or a -Contribution incorporated within the Work constitutes direct or contributory -patent infringement, then any patent licenses granted to You under this License -for that Work shall terminate as of the date such litigation is filed. - -4. Redistribution. - -You may reproduce and distribute copies of the Work or Derivative Works thereof -in any medium, with or without modifications, and in Source or Object form, -provided that You meet the following conditions: - -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -You must retain, in the Source form of any Derivative Works that You distribute, -all copyright, patent, trademark, and attribution notices from the Source form -of the Work, excluding those notices that do not pertain to any part of the -Derivative Works; and -If the Work includes a "NOTICE" text file as part of its distribution, then any -Derivative Works that You distribute must include a readable copy of the -attribution notices contained within such NOTICE file, excluding those notices -that do not pertain to any part of the Derivative Works, in at least one of the -following places: within a NOTICE text file distributed as part of the -Derivative Works; within the Source form or documentation, if provided along -with the Derivative Works; or, within a display generated by the Derivative -Works, if and wherever such third-party notices normally appear. The contents of -the NOTICE file are for informational purposes only and do not modify the -License. You may add Your own attribution notices within Derivative Works that -You distribute, alongside or as an addendum to the NOTICE text from the Work, -provided that such additional attribution notices cannot be construed as -modifying the License. -You may add Your own copyright statement to Your modifications and may provide -additional or different license terms and conditions for use, reproduction, or -distribution of Your modifications, or for any such Derivative Works as a whole, -provided Your use, reproduction, and distribution of the Work otherwise complies -with the conditions stated in this License. - -5. Submission of Contributions. - -Unless You explicitly state otherwise, any Contribution intentionally submitted -for inclusion in the Work by You to the Licensor shall be under the terms and -conditions of this License, without any additional terms or conditions. -Notwithstanding the above, nothing herein shall supersede or modify the terms of -any separate license agreement you may have executed with Licensor regarding -such Contributions. - -6. Trademarks. - -This License does not grant permission to use the trade names, trademarks, -service marks, or product names of the Licensor, except as required for -reasonable and customary use in describing the origin of the Work and -reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. - -Unless required by applicable law or agreed to in writing, Licensor provides the -Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, -including, without limitation, any warranties or conditions of TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are -solely responsible for determining the appropriateness of using or -redistributing the Work and assume any risks associated with Your exercise of -permissions under this License. - -8. Limitation of Liability. - -In no event and under no legal theory, whether in tort (including negligence), -contract, or otherwise, unless required by applicable law (such as deliberate -and grossly negligent acts) or agreed to in writing, shall any Contributor be -liable to You for damages, including any direct, indirect, special, incidental, -or consequential damages of any character arising as a result of this License or -out of the use or inability to use the Work (including but not limited to -damages for loss of goodwill, work stoppage, computer failure or malfunction, or -any and all other commercial damages or losses), even if such Contributor has -been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. - -While redistributing the Work or Derivative Works thereof, You may choose to -offer, and charge a fee for, acceptance of support, warranty, indemnity, or -other liability obligations and/or rights consistent with this License. However, -in accepting such obligations, You may act only on Your own behalf and on Your -sole responsibility, not on behalf of any other Contributor, and only if You -agree to indemnify, defend, and hold each Contributor harmless for any liability -incurred by, or claims asserted against, such Contributor by reason of your -accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work - -To apply the Apache License to your work, attach the following boilerplate -notice, with the fields enclosed by brackets "[]" replaced with your own -identifying information. (Don't include the brackets!) The text should be -enclosed in the appropriate comment syntax for the file format. We also -recommend that a file or class name and description of purpose be included on -the same "printed page" as the copyright notice for easier identification within -third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/docker/docker/vendor/src/github.com/docker/libcontainer/LICENSE b/vendor/github.com/docker/docker/vendor/src/github.com/docker/libcontainer/LICENSE deleted file mode 100644 index 27448585ad..0000000000 --- a/vendor/github.com/docker/docker/vendor/src/github.com/docker/libcontainer/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2014 Docker, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/docker/docker/vendor/src/github.com/docker/libcontainer/NOTICE b/vendor/github.com/docker/docker/vendor/src/github.com/docker/libcontainer/NOTICE deleted file mode 100644 index ca1635f896..0000000000 --- a/vendor/github.com/docker/docker/vendor/src/github.com/docker/libcontainer/NOTICE +++ /dev/null @@ -1,16 +0,0 @@ -libcontainer -Copyright 2012-2014 Docker, Inc. - -This product includes software developed at Docker, Inc. (http://www.docker.com). - -The following is courtesy of our legal counsel: - - -Use and transfer of Docker may be subject to certain restrictions by the -United States and other governments. -It is your responsibility to ensure that your use and/or transfer does not -violate applicable laws. - -For more information, please see http://www.bis.doc.gov - -See also http://www.apache.org/dev/crypto.html and/or seek legal counsel. diff --git a/vendor/github.com/docker/docker/vendor/src/github.com/go-fsnotify/fsnotify/LICENSE b/vendor/github.com/docker/docker/vendor/src/github.com/go-fsnotify/fsnotify/LICENSE deleted file mode 100644 index f21e540800..0000000000 --- a/vendor/github.com/docker/docker/vendor/src/github.com/go-fsnotify/fsnotify/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (c) 2012 The Go Authors. All rights reserved. -Copyright (c) 2012 fsnotify Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/docker/docker/vendor/src/github.com/godbus/dbus/LICENSE b/vendor/github.com/docker/docker/vendor/src/github.com/godbus/dbus/LICENSE deleted file mode 100644 index 06b252bcbc..0000000000 --- a/vendor/github.com/docker/docker/vendor/src/github.com/godbus/dbus/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2013, Georg Reinke () -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/docker/docker/vendor/src/github.com/gorilla/context/LICENSE b/vendor/github.com/docker/docker/vendor/src/github.com/gorilla/context/LICENSE deleted file mode 100644 index 0e5fb87280..0000000000 --- a/vendor/github.com/docker/docker/vendor/src/github.com/gorilla/context/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2012 Rodrigo Moraes. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/docker/docker/vendor/src/github.com/gorilla/mux/LICENSE b/vendor/github.com/docker/docker/vendor/src/github.com/gorilla/mux/LICENSE deleted file mode 100644 index 0e5fb87280..0000000000 --- a/vendor/github.com/docker/docker/vendor/src/github.com/gorilla/mux/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2012 Rodrigo Moraes. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/docker/docker/vendor/src/github.com/kr/pty/License b/vendor/github.com/docker/docker/vendor/src/github.com/kr/pty/License deleted file mode 100644 index 6b7558b6b4..0000000000 --- a/vendor/github.com/docker/docker/vendor/src/github.com/kr/pty/License +++ /dev/null @@ -1,23 +0,0 @@ -Copyright (c) 2011 Keith Rarick - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall -be included in all copies or substantial portions of the -Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/docker/docker/vendor/src/github.com/syndtr/gocapability/LICENSE b/vendor/github.com/docker/docker/vendor/src/github.com/syndtr/gocapability/LICENSE deleted file mode 100644 index 80dd96de77..0000000000 --- a/vendor/github.com/docker/docker/vendor/src/github.com/syndtr/gocapability/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -Copyright 2013 Suryandaru Triandana -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/docker/docker/vendor/src/github.com/tchap/go-patricia/LICENSE b/vendor/github.com/docker/docker/vendor/src/github.com/tchap/go-patricia/LICENSE deleted file mode 100644 index e50d398e98..0000000000 --- a/vendor/github.com/docker/docker/vendor/src/github.com/tchap/go-patricia/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 The AUTHORS - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/samalba/dockerclient/.gitignore b/vendor/github.com/samalba/dockerclient/.gitignore new file mode 100644 index 0000000000..00268614f0 --- /dev/null +++ b/vendor/github.com/samalba/dockerclient/.gitignore @@ -0,0 +1,22 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe diff --git a/vendor/github.com/docker/docker/vendor/src/github.com/docker/libtrust/LICENSE b/vendor/github.com/samalba/dockerclient/LICENSE similarity index 94% rename from vendor/github.com/docker/docker/vendor/src/github.com/docker/libtrust/LICENSE rename to vendor/github.com/samalba/dockerclient/LICENSE index 27448585ad..00e1edb90f 100644 --- a/vendor/github.com/docker/docker/vendor/src/github.com/docker/libtrust/LICENSE +++ b/vendor/github.com/samalba/dockerclient/LICENSE @@ -1,5 +1,4 @@ - - Apache License +Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -176,7 +175,18 @@ END OF TERMS AND CONDITIONS - Copyright 2014 Docker, Inc. + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2014 Sam Alba Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -189,3 +199,4 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + diff --git a/vendor/github.com/samalba/dockerclient/README.md b/vendor/github.com/samalba/dockerclient/README.md new file mode 100644 index 0000000000..5a5027b8b7 --- /dev/null +++ b/vendor/github.com/samalba/dockerclient/README.md @@ -0,0 +1,98 @@ +Docker client library in Go +=========================== +[![GoDoc](http://godoc.org/github.com/samalba/dockerclient?status.png)](http://godoc.org/github.com/samalba/dockerclient) + +Well maintained docker client library. + +# How to use it? + +Here is an example showing how to use it: + +```go +package main + +import ( + "github.com/samalba/dockerclient" + "log" + "time" + "os" +) + +// Callback used to listen to Docker's events +func eventCallback(event *dockerclient.Event, ec chan error, args ...interface{}) { + log.Printf("Received event: %#v\n", *event) +} + +func main() { + // Init the client + docker, _ := dockerclient.NewDockerClient("unix:///var/run/docker.sock", nil) + + // Get only running containers + containers, err := docker.ListContainers(false, false, "") + if err != nil { + log.Fatal(err) + } + for _, c := range containers { + log.Println(c.Id, c.Names) + } + + // Inspect the first container returned + if len(containers) > 0 { + id := containers[0].Id + info, _ := docker.InspectContainer(id) + log.Println(info) + } + + // Build a docker image + // some.tar contains the build context (Dockerfile any any files it needs to add/copy) + dockerBuildContext, err := os.Open("some.tar") + defer dockerBuildContext.Close() + buildImageConfig := &dockerclient.BuildImage{ + Context: dockerBuildContext, + RepoName: "your_image_name", + SuppressOutput: false, + } + reader, err := docker.BuildImage(buildImageConfig) + if err != nil { + log.Fatal(err) + } + + // Create a container + containerConfig := &dockerclient.ContainerConfig{ + Image: "ubuntu:14.04", + Cmd: []string{"bash"}, + AttachStdin: true, + Tty: true} + containerId, err := docker.CreateContainer(containerConfig, "foobar") + if err != nil { + log.Fatal(err) + } + + // Start the container + hostConfig := &dockerclient.HostConfig{} + err = docker.StartContainer(containerId, hostConfig) + if err != nil { + log.Fatal(err) + } + + // Stop the container (with 5 seconds timeout) + docker.StopContainer(containerId, 5) + + // Listen to events + docker.StartMonitorEvents(eventCallback, nil) + + // Hold the execution to look at the events coming + time.Sleep(3600 * time.Second) +} +``` + +# Maintainers + +List of people you can ping for feedback on Pull Requests or any questions. + +- [Sam Alba](https://github.com/samalba) +- [Michael Crosby](https://github.com/crosbymichael) +- [Andrea Luzzardi](https://github.com/aluzzardi) +- [Victor Vieux](https://github.com/vieux) +- [Evan Hazlett](https://github.com/ehazlett) +- [Donald Huang](https://github.com/donhcd) diff --git a/vendor/github.com/samalba/dockerclient/auth.go b/vendor/github.com/samalba/dockerclient/auth.go new file mode 100644 index 0000000000..48f5f90b65 --- /dev/null +++ b/vendor/github.com/samalba/dockerclient/auth.go @@ -0,0 +1,38 @@ +package dockerclient + +import ( + "bytes" + "encoding/base64" + "encoding/json" +) + +// AuthConfig hold parameters for authenticating with the docker registry +type AuthConfig struct { + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + Email string `json:"email,omitempty"` +} + +// encode the auth configuration struct into base64 for the X-Registry-Auth header +func (c *AuthConfig) encode() (string, error) { + var buf bytes.Buffer + if err := json.NewEncoder(&buf).Encode(c); err != nil { + return "", err + } + return base64.URLEncoding.EncodeToString(buf.Bytes()), nil +} + +// ConfigFile holds parameters for authenticating during a BuildImage request +type ConfigFile struct { + Configs map[string]AuthConfig `json:"configs,omitempty"` + rootPath string +} + +// encode the configuration struct into base64 for the X-Registry-Config header +func (c *ConfigFile) encode() (string, error) { + var buf bytes.Buffer + if err := json.NewEncoder(&buf).Encode(c); err != nil { + return "", err + } + return base64.URLEncoding.EncodeToString(buf.Bytes()), nil +} diff --git a/vendor/github.com/samalba/dockerclient/dockerclient.go b/vendor/github.com/samalba/dockerclient/dockerclient.go new file mode 100644 index 0000000000..d8379fb1b7 --- /dev/null +++ b/vendor/github.com/samalba/dockerclient/dockerclient.go @@ -0,0 +1,930 @@ +package dockerclient + +import ( + "bytes" + "crypto/tls" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "strconv" + "strings" + "sync/atomic" + "time" +) + +const ( + APIVersion = "v1.15" +) + +var ( + ErrImageNotFound = errors.New("Image not found") + ErrNotFound = errors.New("Not found") + + defaultTimeout = 30 * time.Second +) + +type DockerClient struct { + URL *url.URL + HTTPClient *http.Client + TLSConfig *tls.Config + monitorStats int32 + eventStopChan chan (struct{}) +} + +type Error struct { + StatusCode int + Status string + msg string +} + +func (e Error) Error() string { + return fmt.Sprintf("%s: %s", e.Status, e.msg) +} + +func NewDockerClient(daemonUrl string, tlsConfig *tls.Config) (*DockerClient, error) { + return NewDockerClientTimeout(daemonUrl, tlsConfig, time.Duration(defaultTimeout)) +} + +func NewDockerClientTimeout(daemonUrl string, tlsConfig *tls.Config, timeout time.Duration) (*DockerClient, error) { + u, err := url.Parse(daemonUrl) + if err != nil { + return nil, err + } + if u.Scheme == "" || u.Scheme == "tcp" { + if tlsConfig == nil { + u.Scheme = "http" + } else { + u.Scheme = "https" + } + } + httpClient := newHTTPClient(u, tlsConfig, timeout) + return &DockerClient{u, httpClient, tlsConfig, 0, nil}, nil +} + +func (client *DockerClient) doRequest(method string, path string, body []byte, headers map[string]string) ([]byte, error) { + b := bytes.NewBuffer(body) + + reader, err := client.doStreamRequest(method, path, b, headers) + if err != nil { + return nil, err + } + + defer reader.Close() + data, err := ioutil.ReadAll(reader) + if err != nil { + return nil, err + } + return data, nil +} + +func (client *DockerClient) doStreamRequest(method string, path string, in io.Reader, headers map[string]string) (io.ReadCloser, error) { + if (method == "POST" || method == "PUT") && in == nil { + in = bytes.NewReader(nil) + } + req, err := http.NewRequest(method, client.URL.String()+path, in) + if err != nil { + return nil, err + } + req.Header.Add("Content-Type", "application/json") + if headers != nil { + for header, value := range headers { + req.Header.Add(header, value) + } + } + resp, err := client.HTTPClient.Do(req) + if err != nil { + if !strings.Contains(err.Error(), "connection refused") && client.TLSConfig == nil { + return nil, fmt.Errorf("%v. Are you trying to connect to a TLS-enabled daemon without TLS?", err) + } + return nil, err + } + if resp.StatusCode == 404 { + defer resp.Body.Close() + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, ErrNotFound + } + if len(data) > 0 { + // check if is image not found error + if strings.Index(string(data), "No such image") != -1 { + return nil, ErrImageNotFound + } + return nil, errors.New(string(data)) + } + return nil, ErrNotFound + } + if resp.StatusCode >= 400 { + defer resp.Body.Close() + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + return nil, Error{StatusCode: resp.StatusCode, Status: resp.Status, msg: string(data)} + } + + return resp.Body, nil +} + +func (client *DockerClient) Info() (*Info, error) { + uri := fmt.Sprintf("/%s/info", APIVersion) + data, err := client.doRequest("GET", uri, nil, nil) + if err != nil { + return nil, err + } + ret := &Info{} + err = json.Unmarshal(data, &ret) + if err != nil { + return nil, err + } + return ret, nil +} + +func (client *DockerClient) ListContainers(all bool, size bool, filters string) ([]Container, error) { + argAll := 0 + if all == true { + argAll = 1 + } + showSize := 0 + if size == true { + showSize = 1 + } + uri := fmt.Sprintf("/%s/containers/json?all=%d&size=%d", APIVersion, argAll, showSize) + + if filters != "" { + uri += "&filters=" + filters + } + + data, err := client.doRequest("GET", uri, nil, nil) + if err != nil { + return nil, err + } + ret := []Container{} + err = json.Unmarshal(data, &ret) + if err != nil { + return nil, err + } + return ret, nil +} + +func (client *DockerClient) InspectContainer(id string) (*ContainerInfo, error) { + uri := fmt.Sprintf("/%s/containers/%s/json", APIVersion, id) + data, err := client.doRequest("GET", uri, nil, nil) + if err != nil { + return nil, err + } + info := &ContainerInfo{} + err = json.Unmarshal(data, info) + if err != nil { + return nil, err + } + return info, nil +} + +func (client *DockerClient) CreateContainer(config *ContainerConfig, name string) (string, error) { + data, err := json.Marshal(config) + if err != nil { + return "", err + } + uri := fmt.Sprintf("/%s/containers/create", APIVersion) + if name != "" { + v := url.Values{} + v.Set("name", name) + uri = fmt.Sprintf("%s?%s", uri, v.Encode()) + } + data, err = client.doRequest("POST", uri, data, nil) + if err != nil { + return "", err + } + result := &RespContainersCreate{} + err = json.Unmarshal(data, result) + if err != nil { + return "", err + } + return result.Id, nil +} + +func (client *DockerClient) ContainerLogs(id string, options *LogOptions) (io.ReadCloser, error) { + v := url.Values{} + v.Add("follow", strconv.FormatBool(options.Follow)) + v.Add("stdout", strconv.FormatBool(options.Stdout)) + v.Add("stderr", strconv.FormatBool(options.Stderr)) + v.Add("timestamps", strconv.FormatBool(options.Timestamps)) + if options.Tail > 0 { + v.Add("tail", strconv.FormatInt(options.Tail, 10)) + } + + uri := fmt.Sprintf("/%s/containers/%s/logs?%s", APIVersion, id, v.Encode()) + req, err := http.NewRequest("GET", client.URL.String()+uri, nil) + if err != nil { + return nil, err + } + req.Header.Add("Content-Type", "application/json") + resp, err := client.HTTPClient.Do(req) + if err != nil { + return nil, err + } + return resp.Body, nil +} + +func (client *DockerClient) ContainerChanges(id string) ([]*ContainerChanges, error) { + uri := fmt.Sprintf("/%s/containers/%s/changes", APIVersion, id) + data, err := client.doRequest("GET", uri, nil, nil) + if err != nil { + return nil, err + } + changes := []*ContainerChanges{} + err = json.Unmarshal(data, &changes) + if err != nil { + return nil, err + } + return changes, nil +} + +func (client *DockerClient) readJSONStream(stream io.ReadCloser, decode func(*json.Decoder) decodingResult, stopChan <-chan struct{}) <-chan decodingResult { + resultChan := make(chan decodingResult) + + go func() { + decodeChan := make(chan decodingResult) + + go func() { + decoder := json.NewDecoder(stream) + for { + decodeResult := decode(decoder) + decodeChan <- decodeResult + if decodeResult.err != nil { + close(decodeChan) + return + } + } + }() + + defer close(resultChan) + + for { + select { + case <-stopChan: + stream.Close() + for range decodeChan { + } + return + case decodeResult := <-decodeChan: + resultChan <- decodeResult + if decodeResult.err != nil { + stream.Close() + return + } + } + } + + }() + + return resultChan +} + +func (client *DockerClient) ExecCreate(config *ExecConfig) (string, error) { + data, err := json.Marshal(config) + if err != nil { + return "", err + } + uri := fmt.Sprintf("/%s/containers/%s/exec", APIVersion, config.Container) + resp, err := client.doRequest("POST", uri, data, nil) + if err != nil { + return "", err + } + var createExecResp struct { + Id string + } + if err = json.Unmarshal(resp, &createExecResp); err != nil { + return "", err + } + return createExecResp.Id, nil +} + +func (client *DockerClient) ExecStart(id string, config *ExecConfig) error { + data, err := json.Marshal(config) + if err != nil { + return err + } + + uri := fmt.Sprintf("/%s/exec/%s/start", APIVersion, id) + if _, err := client.doRequest("POST", uri, data, nil); err != nil { + return err + } + + return nil +} + +func (client *DockerClient) ExecResize(id string, width, height int) error { + v := url.Values{} + + w := strconv.Itoa(width) + h := strconv.Itoa(height) + + v.Set("w", w) + v.Set("h", h) + + uri := fmt.Sprintf("/%s/exec/%s/resize?%s", APIVersion, id, v.Encode()) + if _, err := client.doRequest("POST", client.URL.String()+uri, nil, nil); err != nil { + return err + } + + return nil +} + +func (client *DockerClient) AttachContainer(id string, options *AttachOptions) (io.ReadCloser, error) { + v := url.Values{} + if options != nil { + if options.Logs { + v.Set("logs", "1") + } + if options.Stream { + v.Set("stream", "1") + } + if options.Stdin { + v.Set("stdin", "1") + } + if options.Stdout { + v.Set("stdout", "1") + } + if options.Stderr { + v.Set("stderr", "1") + } + } + uri := fmt.Sprintf("/%s/containers/%s/attach?%s", APIVersion, id, v.Encode()) + return client.doStreamRequest("POST", uri, nil, nil) +} + +func (client *DockerClient) StartContainer(id string, config *HostConfig) error { + data, err := json.Marshal(config) + if err != nil { + return err + } + uri := fmt.Sprintf("/%s/containers/%s/start", APIVersion, id) + _, err = client.doRequest("POST", uri, data, nil) + if err != nil { + return err + } + return nil +} + +func (client *DockerClient) StopContainer(id string, timeout int) error { + uri := fmt.Sprintf("/%s/containers/%s/stop?t=%d", APIVersion, id, timeout) + _, err := client.doRequest("POST", uri, nil, nil) + if err != nil { + return err + } + return nil +} + +func (client *DockerClient) RestartContainer(id string, timeout int) error { + uri := fmt.Sprintf("/%s/containers/%s/restart?t=%d", APIVersion, id, timeout) + _, err := client.doRequest("POST", uri, nil, nil) + if err != nil { + return err + } + return nil +} + +func (client *DockerClient) KillContainer(id, signal string) error { + uri := fmt.Sprintf("/%s/containers/%s/kill?signal=%s", APIVersion, id, signal) + _, err := client.doRequest("POST", uri, nil, nil) + if err != nil { + return err + } + return nil +} + +func (client *DockerClient) Wait(id string) <-chan WaitResult { + ch := make(chan WaitResult) + uri := fmt.Sprintf("/%s/containers/%s/wait", APIVersion, id) + + go func() { + data, err := client.doRequest("POST", uri, nil, nil) + if err != nil { + ch <- WaitResult{ExitCode: -1, Error: err} + return + } + + var result struct { + StatusCode int `json:"StatusCode"` + } + err = json.Unmarshal(data, &result) + ch <- WaitResult{ExitCode: result.StatusCode, Error: err} + }() + return ch +} + +func (client *DockerClient) MonitorEvents(options *MonitorEventsOptions, stopChan <-chan struct{}) (<-chan EventOrError, error) { + v := url.Values{} + if options != nil { + if options.Since != 0 { + v.Add("since", strconv.Itoa(options.Since)) + } + if options.Until != 0 { + v.Add("until", strconv.Itoa(options.Until)) + } + if options.Filters != nil { + filterMap := make(map[string][]string) + if len(options.Filters.Event) > 0 { + filterMap["event"] = []string{options.Filters.Event} + } + if len(options.Filters.Image) > 0 { + filterMap["image"] = []string{options.Filters.Image} + } + if len(options.Filters.Container) > 0 { + filterMap["container"] = []string{options.Filters.Container} + } + if len(filterMap) > 0 { + filterJSONBytes, err := json.Marshal(filterMap) + if err != nil { + return nil, err + } + v.Add("filters", string(filterJSONBytes)) + } + } + } + uri := fmt.Sprintf("%s/%s/events?%s", client.URL.String(), APIVersion, v.Encode()) + resp, err := client.HTTPClient.Get(uri) + if err != nil { + return nil, err + } + + decode := func(decoder *json.Decoder) decodingResult { + var event Event + if err := decoder.Decode(&event); err != nil { + return decodingResult{err: err} + } else { + return decodingResult{result: event} + } + } + decodingResultChan := client.readJSONStream(resp.Body, decode, stopChan) + eventOrErrorChan := make(chan EventOrError) + go func() { + for decodingResult := range decodingResultChan { + event, _ := decodingResult.result.(Event) + eventOrErrorChan <- EventOrError{ + Event: event, + Error: decodingResult.err, + } + } + close(eventOrErrorChan) + }() + return eventOrErrorChan, nil +} + +func (client *DockerClient) StartMonitorEvents(cb Callback, ec chan error, args ...interface{}) { + client.eventStopChan = make(chan struct{}) + + go func() { + eventErrChan, err := client.MonitorEvents(nil, client.eventStopChan) + if err != nil { + if ec != nil { + ec <- err + } + return + } + + for e := range eventErrChan { + if e.Error != nil { + if ec != nil { + ec <- err + } + return + } + cb(&e.Event, ec, args...) + } + }() +} + +func (client *DockerClient) StopAllMonitorEvents() { + close(client.eventStopChan) +} + +func (client *DockerClient) StartMonitorStats(id string, cb StatCallback, ec chan error, args ...interface{}) { + atomic.StoreInt32(&client.monitorStats, 1) + go client.getStats(id, cb, ec, args...) +} + +func (client *DockerClient) getStats(id string, cb StatCallback, ec chan error, args ...interface{}) { + uri := fmt.Sprintf("%s/%s/containers/%s/stats", client.URL.String(), APIVersion, id) + resp, err := client.HTTPClient.Get(uri) + if err != nil { + ec <- err + return + } + defer resp.Body.Close() + + dec := json.NewDecoder(resp.Body) + for atomic.LoadInt32(&client.monitorStats) > 0 { + var stats *Stats + if err := dec.Decode(&stats); err != nil { + ec <- err + return + } + cb(id, stats, ec, args...) + } +} + +func (client *DockerClient) StopAllMonitorStats() { + atomic.StoreInt32(&client.monitorStats, 0) +} + +func (client *DockerClient) TagImage(nameOrID string, repo string, tag string, force bool) error { + v := url.Values{} + v.Set("repo", repo) + v.Set("tag", tag) + if force { + v.Set("force", "1") + } + uri := fmt.Sprintf("/%s/images/%s/tag?%s", APIVersion, nameOrID, v.Encode()) + if _, err := client.doRequest("POST", uri, nil, nil); err != nil { + return err + } + return nil +} + +func (client *DockerClient) Version() (*Version, error) { + uri := fmt.Sprintf("/%s/version", APIVersion) + data, err := client.doRequest("GET", uri, nil, nil) + if err != nil { + return nil, err + } + version := &Version{} + err = json.Unmarshal(data, version) + if err != nil { + return nil, err + } + return version, nil +} + +func (client *DockerClient) PushImage(name string, tag string, auth *AuthConfig) error { + v := url.Values{} + if tag != "" { + v.Set("tag", tag) + } + uri := fmt.Sprintf("/%s/images/%s/push?%s", APIVersion, url.QueryEscape(name), v.Encode()) + req, err := http.NewRequest("POST", client.URL.String()+uri, nil) + if auth != nil { + if encodedAuth, err := auth.encode(); err != nil { + return err + } else { + req.Header.Add("X-Registry-Auth", encodedAuth) + } + } + resp, err := client.HTTPClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + var finalObj map[string]interface{} + for decoder := json.NewDecoder(resp.Body); err == nil; err = decoder.Decode(&finalObj) { + } + if err != io.EOF { + return err + } + if err, ok := finalObj["error"]; ok { + return fmt.Errorf("%v", err) + } + return nil +} + +func (client *DockerClient) PullImage(name string, auth *AuthConfig) error { + v := url.Values{} + v.Set("fromImage", name) + uri := fmt.Sprintf("/%s/images/create?%s", APIVersion, v.Encode()) + req, err := http.NewRequest("POST", client.URL.String()+uri, nil) + if auth != nil { + encoded_auth, err := auth.encode() + if err != nil { + return err + } + req.Header.Add("X-Registry-Auth", encoded_auth) + } + resp, err := client.HTTPClient.Do(req) + if err != nil { + return err + } + + defer resp.Body.Close() + if resp.StatusCode == 404 { + return ErrNotFound + } + if resp.StatusCode >= 400 { + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + return fmt.Errorf("%s", string(data)) + } + + var finalObj map[string]interface{} + for decoder := json.NewDecoder(resp.Body); err == nil; err = decoder.Decode(&finalObj) { + } + if err != io.EOF { + return err + } + if err, ok := finalObj["error"]; ok { + return fmt.Errorf("%v", err) + } + return nil +} + +func (client *DockerClient) InspectImage(id string) (*ImageInfo, error) { + uri := fmt.Sprintf("/%s/images/%s/json", APIVersion, id) + data, err := client.doRequest("GET", uri, nil, nil) + if err != nil { + return nil, err + } + info := &ImageInfo{} + err = json.Unmarshal(data, info) + if err != nil { + return nil, err + } + return info, nil +} + +func (client *DockerClient) LoadImage(reader io.Reader) error { + data, err := ioutil.ReadAll(reader) + if err != nil { + return err + } + + uri := fmt.Sprintf("/%s/images/load", APIVersion) + _, err = client.doRequest("POST", uri, data, nil) + if err != nil { + return err + } + return nil +} + +func (client *DockerClient) RemoveContainer(id string, force, volumes bool) error { + argForce := 0 + argVolumes := 0 + if force == true { + argForce = 1 + } + if volumes == true { + argVolumes = 1 + } + args := fmt.Sprintf("force=%d&v=%d", argForce, argVolumes) + uri := fmt.Sprintf("/%s/containers/%s?%s", APIVersion, id, args) + _, err := client.doRequest("DELETE", uri, nil, nil) + return err +} + +func (client *DockerClient) ListImages(all bool) ([]*Image, error) { + argAll := 0 + if all { + argAll = 1 + } + uri := fmt.Sprintf("/%s/images/json?all=%d", APIVersion, argAll) + data, err := client.doRequest("GET", uri, nil, nil) + if err != nil { + return nil, err + } + var images []*Image + if err := json.Unmarshal(data, &images); err != nil { + return nil, err + } + return images, nil +} + +func (client *DockerClient) RemoveImage(name string, force bool) ([]*ImageDelete, error) { + argForce := 0 + if force { + argForce = 1 + } + + args := fmt.Sprintf("force=%d", argForce) + uri := fmt.Sprintf("/%s/images/%s?%s", APIVersion, name, args) + data, err := client.doRequest("DELETE", uri, nil, nil) + if err != nil { + return nil, err + } + var imageDelete []*ImageDelete + if err := json.Unmarshal(data, &imageDelete); err != nil { + return nil, err + } + return imageDelete, nil +} + +func (client *DockerClient) PauseContainer(id string) error { + uri := fmt.Sprintf("/%s/containers/%s/pause", APIVersion, id) + _, err := client.doRequest("POST", uri, nil, nil) + if err != nil { + return err + } + return nil +} +func (client *DockerClient) UnpauseContainer(id string) error { + uri := fmt.Sprintf("/%s/containers/%s/unpause", APIVersion, id) + _, err := client.doRequest("POST", uri, nil, nil) + if err != nil { + return err + } + return nil +} + +func (client *DockerClient) RenameContainer(oldName string, newName string) error { + uri := fmt.Sprintf("/containers/%s/rename?name=%s", oldName, newName) + _, err := client.doRequest("POST", uri, nil, nil) + return err +} + +func (client *DockerClient) ImportImage(source string, repository string, tag string, tar io.Reader) (io.ReadCloser, error) { + var fromSrc string + v := &url.Values{} + if source == "" { + fromSrc = "-" + } else { + fromSrc = source + } + + v.Set("fromSrc", fromSrc) + v.Set("repo", repository) + if tag != "" { + v.Set("tag", tag) + } + + var in io.Reader + if fromSrc == "-" { + in = tar + } + return client.doStreamRequest("POST", "/images/create?"+v.Encode(), in, nil) +} + +func (client *DockerClient) BuildImage(image *BuildImage) (io.ReadCloser, error) { + v := url.Values{} + + if image.DockerfileName != "" { + v.Set("dockerfile", image.DockerfileName) + } + if image.RepoName != "" { + v.Set("t", image.RepoName) + } + if image.RemoteURL != "" { + v.Set("remote", image.RemoteURL) + } + if image.NoCache { + v.Set("nocache", "1") + } + if image.Pull { + v.Set("pull", "1") + } + if image.Remove { + v.Set("rm", "1") + } else { + v.Set("rm", "0") + } + if image.ForceRemove { + v.Set("forcerm", "1") + } + if image.SuppressOutput { + v.Set("q", "1") + } + + v.Set("memory", strconv.FormatInt(image.Memory, 10)) + v.Set("memswap", strconv.FormatInt(image.MemorySwap, 10)) + v.Set("cpushares", strconv.FormatInt(image.CpuShares, 10)) + v.Set("cpuperiod", strconv.FormatInt(image.CpuPeriod, 10)) + v.Set("cpuquota", strconv.FormatInt(image.CpuQuota, 10)) + v.Set("cpusetcpus", image.CpuSetCpus) + v.Set("cpusetmems", image.CpuSetMems) + v.Set("cgroupparent", image.CgroupParent) + if image.BuildArgs != nil { + buildArgsJSON, err := json.Marshal(image.BuildArgs) + if err != nil { + return nil, err + } + v.Set("buildargs", string(buildArgsJSON)) + } + + headers := make(map[string]string) + if image.Config != nil { + encoded_config, err := image.Config.encode() + if err != nil { + return nil, err + } + headers["X-Registry-Config"] = encoded_config + } + if image.Context != nil { + headers["Content-Type"] = "application/tar" + } + + uri := fmt.Sprintf("/%s/build?%s", APIVersion, v.Encode()) + return client.doStreamRequest("POST", uri, image.Context, headers) +} + +func (client *DockerClient) ListVolumes() ([]*Volume, error) { + uri := fmt.Sprintf("/%s/volumes", APIVersion) + data, err := client.doRequest("GET", uri, nil, nil) + if err != nil { + return nil, err + } + var volumesList VolumesListResponse + if err := json.Unmarshal(data, &volumesList); err != nil { + return nil, err + } + return volumesList.Volumes, nil +} + +func (client *DockerClient) RemoveVolume(name string) error { + uri := fmt.Sprintf("/%s/volumes/%s", APIVersion, name) + _, err := client.doRequest("DELETE", uri, nil, nil) + return err +} + +func (client *DockerClient) CreateVolume(request *VolumeCreateRequest) (*Volume, error) { + data, err := json.Marshal(request) + if err != nil { + return nil, err + } + uri := fmt.Sprintf("/%s/volumes/create", APIVersion) + data, err = client.doRequest("POST", uri, data, nil) + if err != nil { + return nil, err + } + volume := &Volume{} + err = json.Unmarshal(data, volume) + return volume, err +} + +func (client *DockerClient) ListNetworks(filters string) ([]*NetworkResource, error) { + uri := fmt.Sprintf("/%s/networks", APIVersion) + + if filters != "" { + uri += "&filters=" + filters + } + + data, err := client.doRequest("GET", uri, nil, nil) + if err != nil { + return nil, err + } + ret := []*NetworkResource{} + err = json.Unmarshal(data, &ret) + if err != nil { + return nil, err + } + return ret, nil +} + +func (client *DockerClient) InspectNetwork(id string) (*NetworkResource, error) { + uri := fmt.Sprintf("/%s/networks/%s", APIVersion, id) + + data, err := client.doRequest("GET", uri, nil, nil) + if err != nil { + return nil, err + } + ret := &NetworkResource{} + err = json.Unmarshal(data, ret) + if err != nil { + return nil, err + } + + return ret, nil +} + +func (client *DockerClient) CreateNetwork(config *NetworkCreate) (*NetworkCreateResponse, error) { + data, err := json.Marshal(config) + if err != nil { + return nil, err + } + uri := fmt.Sprintf("/%s/networks/create", APIVersion) + data, err = client.doRequest("POST", uri, data, nil) + if err != nil { + return nil, err + } + ret := &NetworkCreateResponse{} + err = json.Unmarshal(data, ret) + return ret, nil +} + +func (client *DockerClient) ConnectNetwork(id, container string) error { + data, err := json.Marshal(NetworkConnect{Container: container}) + if err != nil { + return err + } + uri := fmt.Sprintf("/%s/networks/%s/connect", APIVersion, id) + _, err = client.doRequest("POST", uri, data, nil) + return err +} + +func (client *DockerClient) DisconnectNetwork(id, container string) error { + data, err := json.Marshal(NetworkDisconnect{Container: container}) + if err != nil { + return err + } + uri := fmt.Sprintf("/%s/networks/%s/disconnect", APIVersion, id) + _, err = client.doRequest("POST", uri, data, nil) + return err +} + +func (client *DockerClient) RemoveNetwork(id string) error { + uri := fmt.Sprintf("/%s/networks/%s", APIVersion, id) + _, err := client.doRequest("DELETE", uri, nil, nil) + return err +} diff --git a/vendor/github.com/samalba/dockerclient/example_responses.go b/vendor/github.com/samalba/dockerclient/example_responses.go new file mode 100644 index 0000000000..670508c074 --- /dev/null +++ b/vendor/github.com/samalba/dockerclient/example_responses.go @@ -0,0 +1,13 @@ +package dockerclient + +var haproxyPullOutput = `{"status":"The image you are pulling has been verified","id":"haproxy:1"} +{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"66301eb54a7d"}{"status":"Already exists","progressDetail":{},"id":"e3990b07573f"}{"status":"Already exists","progressDetail":{},"id":"ecb4b23ca7ce"}{"status":"Already exists","progressDetail":{},"id":"f453e940c177"}{"status":"Already exists","progressDetail":{},"id":"fc5ea1bc05ab"}{"status":"Already exists","progressDetail":{},"id":"380557f8f7b3"}{"status":"The image you are pulling has been verified","id":"haproxy:1.4"} +{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"63a1b9929e14"}{"status":"Already exists","progressDetail":{},"id":"af43bf7d176e"}{"status":"Already exists","progressDetail":{},"id":"851aac2d69aa"}{"status":"Already exists","progressDetail":{},"id":"345053a92c95"}{"status":"Already exists","progressDetail":{},"id":"b41231d429c9"}{"status":"The image you are pulling has been verified","id":"haproxy:1.4.25"} +{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"63a1b9929e14"}{"status":"Already exists","progressDetail":{},"id":"af43bf7d176e"}{"status":"Already exists","progressDetail":{},"id":"851aac2d69aa"}{"status":"Already exists","progressDetail":{},"id":"345053a92c95"}{"status":"Already exists","progressDetail":{},"id":"b41231d429c9"}{"status":"The image you are pulling has been verified","id":"haproxy:1.5"} +{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"66301eb54a7d"}{"status":"Already exists","progressDetail":{},"id":"e3990b07573f"}{"status":"Already exists","progressDetail":{},"id":"ecb4b23ca7ce"}{"status":"Already exists","progressDetail":{},"id":"f453e940c177"}{"status":"Already exists","progressDetail":{},"id":"fc5ea1bc05ab"}{"status":"Already exists","progressDetail":{},"id":"380557f8f7b3"}{"status":"The image you are pulling has been verified","id":"haproxy:1.5.10"} +{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"66301eb54a7d"}{"status":"Already exists","progressDetail":{},"id":"e3990b07573f"}{"status":"Already exists","progressDetail":{},"id":"ecb4b23ca7ce"}{"status":"Already exists","progressDetail":{},"id":"f453e940c177"}{"status":"Already exists","progressDetail":{},"id":"fc5ea1bc05ab"}{"status":"Already exists","progressDetail":{},"id":"380557f8f7b3"}{"status":"The image you are pulling has been verified","id":"haproxy:1.5.9"} +{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"66301eb54a7d"}{"status":"Already exists","progressDetail":{},"id":"e3990b07573f"}{"status":"Already exists","progressDetail":{},"id":"3d894e6f7e63"}{"status":"Already exists","progressDetail":{},"id":"4d949c40bc77"}{"status":"Already exists","progressDetail":{},"id":"55e031889365"}{"status":"Already exists","progressDetail":{},"id":"c7aa675e1876"}{"status":"The image you are pulling has been verified","id":"haproxy:latest"} +{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"66301eb54a7d"}{"status":"Already exists","progressDetail":{},"id":"e3990b07573f"}{"status":"Already exists","progressDetail":{},"id":"ecb4b23ca7ce"}{"status":"Already exists","progressDetail":{},"id":"f453e940c177"}{"status":"Already exists","progressDetail":{},"id":"fc5ea1bc05ab"}{"status":"Already exists","progressDetail":{},"id":"380557f8f7b3"}{"status":"Status: Image is up to date for haproxy"} +` + +var eventsResp = `{"status":"pull","id":"nginx:latest","time":1428620433}{"status":"create","id":"9b818c3b8291708fdcecd7c4086b75c222cb503be10a93d9c11040886032a48b","from":"nginx:latest","time":1428620433}{"status":"start","id":"9b818c3b8291708fdcecd7c4086b75c222cb503be10a93d9c11040886032a48b","from":"nginx:latest","time":1428620433}{"status":"die","id":"9b818c3b8291708fdcecd7c4086b75c222cb503be10a93d9c11040886032a48b","from":"nginx:latest","time":1428620442}{"status":"create","id":"352d0b412aae5a5d2b14ae9d88be59dc276602d9edb9dcc33e138e475b3e4720","from":"52.11.96.81/foobar/ubuntu:latest","time":1428620444}{"status":"start","id":"352d0b412aae5a5d2b14ae9d88be59dc276602d9edb9dcc33e138e475b3e4720","from":"52.11.96.81/foobar/ubuntu:latest","time":1428620444}{"status":"die","id":"352d0b412aae5a5d2b14ae9d88be59dc276602d9edb9dcc33e138e475b3e4720","from":"52.11.96.81/foobar/ubuntu:latest","time":1428620444}{"status":"pull","id":"debian:latest","time":1428620453}{"status":"create","id":"668887b5729946546b3072655dc6da08f0e3210111b68b704eb842adfce53f6c","from":"debian:latest","time":1428620453}{"status":"start","id":"668887b5729946546b3072655dc6da08f0e3210111b68b704eb842adfce53f6c","from":"debian:latest","time":1428620453}{"status":"die","id":"668887b5729946546b3072655dc6da08f0e3210111b68b704eb842adfce53f6c","from":"debian:latest","time":1428620453}{"status":"create","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620458}{"status":"start","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620458}{"status":"pause","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620462}{"status":"unpause","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620466}{"status":"die","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620469}` diff --git a/vendor/github.com/samalba/dockerclient/examples/events.go b/vendor/github.com/samalba/dockerclient/examples/events.go new file mode 100644 index 0000000000..2d6de40c7a --- /dev/null +++ b/vendor/github.com/samalba/dockerclient/examples/events.go @@ -0,0 +1,39 @@ +package main + +import ( + "github.com/samalba/dockerclient" + "log" + "os" + "os/signal" + "syscall" +) + +func eventCallback(e *dockerclient.Event, ec chan error, args ...interface{}) { + log.Println(e) +} + +var ( + client *dockerclient.DockerClient +) + +func waitForInterrupt() { + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT) + for _ = range sigChan { + client.StopAllMonitorEvents() + os.Exit(0) + } +} + +func main() { + docker, err := dockerclient.NewDockerClient(os.Getenv("DOCKER_HOST"), nil) + if err != nil { + log.Fatal(err) + } + + client = docker + + client.StartMonitorEvents(eventCallback, nil) + + waitForInterrupt() +} diff --git a/vendor/github.com/samalba/dockerclient/examples/stats/stats.go b/vendor/github.com/samalba/dockerclient/examples/stats/stats.go new file mode 100644 index 0000000000..9027069ddc --- /dev/null +++ b/vendor/github.com/samalba/dockerclient/examples/stats/stats.go @@ -0,0 +1,43 @@ +package main + +import ( + "github.com/samalba/dockerclient" + "log" + "os" + "os/signal" + "syscall" +) + +func statCallback(id string, stat *dockerclient.Stats, ec chan error, args ...interface{}) { + log.Println(stat) +} + +func waitForInterrupt() { + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT) + for _ = range sigChan { + os.Exit(0) + } +} + +func main() { + docker, err := dockerclient.NewDockerClient(os.Getenv("DOCKER_HOST"), nil) + if err != nil { + log.Fatal(err) + } + + containerConfig := &dockerclient.ContainerConfig{Image: "busybox", Cmd: []string{"sh"}} + containerId, err := docker.CreateContainer(containerConfig, "") + if err != nil { + log.Fatal(err) + } + + // Start the container + err = docker.StartContainer(containerId, nil) + if err != nil { + log.Fatal(err) + } + docker.StartMonitorStats(containerId, statCallback, nil) + + waitForInterrupt() +} diff --git a/vendor/github.com/samalba/dockerclient/interface.go b/vendor/github.com/samalba/dockerclient/interface.go new file mode 100644 index 0000000000..2b6c390edc --- /dev/null +++ b/vendor/github.com/samalba/dockerclient/interface.go @@ -0,0 +1,59 @@ +package dockerclient + +import ( + "io" +) + +type Callback func(*Event, chan error, ...interface{}) + +type StatCallback func(string, *Stats, chan error, ...interface{}) + +type Client interface { + Info() (*Info, error) + ListContainers(all, size bool, filters string) ([]Container, error) + InspectContainer(id string) (*ContainerInfo, error) + InspectImage(id string) (*ImageInfo, error) + CreateContainer(config *ContainerConfig, name string) (string, error) + ContainerLogs(id string, options *LogOptions) (io.ReadCloser, error) + ContainerChanges(id string) ([]*ContainerChanges, error) + ExecCreate(config *ExecConfig) (string, error) + ExecStart(id string, config *ExecConfig) error + ExecResize(id string, width, height int) error + StartContainer(id string, config *HostConfig) error + AttachContainer(id string, options *AttachOptions) (io.ReadCloser, error) + StopContainer(id string, timeout int) error + RestartContainer(id string, timeout int) error + KillContainer(id, signal string) error + Wait(id string) <-chan WaitResult + // MonitorEvents takes options and an optional stop channel, and returns + // an EventOrError channel. If an error is ever sent, then no more + // events will be sent. If a stop channel is provided, events will stop + // being monitored after the stop channel is closed. + MonitorEvents(options *MonitorEventsOptions, stopChan <-chan struct{}) (<-chan EventOrError, error) + StartMonitorEvents(cb Callback, ec chan error, args ...interface{}) + StopAllMonitorEvents() + StartMonitorStats(id string, cb StatCallback, ec chan error, args ...interface{}) + StopAllMonitorStats() + TagImage(nameOrID string, repo string, tag string, force bool) error + Version() (*Version, error) + PullImage(name string, auth *AuthConfig) error + PushImage(name string, tag string, auth *AuthConfig) error + LoadImage(reader io.Reader) error + RemoveContainer(id string, force, volumes bool) error + ListImages(all bool) ([]*Image, error) + RemoveImage(name string, force bool) ([]*ImageDelete, error) + PauseContainer(name string) error + UnpauseContainer(name string) error + RenameContainer(oldName string, newName string) error + ImportImage(source string, repository string, tag string, tar io.Reader) (io.ReadCloser, error) + BuildImage(image *BuildImage) (io.ReadCloser, error) + ListVolumes() ([]*Volume, error) + RemoveVolume(name string) error + CreateVolume(request *VolumeCreateRequest) (*Volume, error) + ListNetworks(filters string) ([]*NetworkResource, error) + InspectNetwork(id string) (*NetworkResource, error) + CreateNetwork(config *NetworkCreate) (*NetworkCreateResponse, error) + ConnectNetwork(id, container string) error + DisconnectNetwork(id, container string) error + RemoveNetwork(id string) error +} diff --git a/vendor/github.com/samalba/dockerclient/mockclient/mock.go b/vendor/github.com/samalba/dockerclient/mockclient/mock.go new file mode 100644 index 0000000000..95303677c6 --- /dev/null +++ b/vendor/github.com/samalba/dockerclient/mockclient/mock.go @@ -0,0 +1,227 @@ +package mockclient + +import ( + "io" + + "github.com/samalba/dockerclient" + "github.com/stretchr/testify/mock" +) + +type MockClient struct { + mock.Mock +} + +func NewMockClient() *MockClient { + return &MockClient{} +} + +func (client *MockClient) Info() (*dockerclient.Info, error) { + args := client.Mock.Called() + return args.Get(0).(*dockerclient.Info), args.Error(1) +} + +func (client *MockClient) ListContainers(all bool, size bool, filters string) ([]dockerclient.Container, error) { + args := client.Mock.Called(all, size, filters) + return args.Get(0).([]dockerclient.Container), args.Error(1) +} + +func (client *MockClient) InspectContainer(id string) (*dockerclient.ContainerInfo, error) { + args := client.Mock.Called(id) + return args.Get(0).(*dockerclient.ContainerInfo), args.Error(1) +} + +func (client *MockClient) InspectImage(id string) (*dockerclient.ImageInfo, error) { + args := client.Mock.Called(id) + return args.Get(0).(*dockerclient.ImageInfo), args.Error(1) +} + +func (client *MockClient) CreateContainer(config *dockerclient.ContainerConfig, name string) (string, error) { + args := client.Mock.Called(config, name) + return args.String(0), args.Error(1) +} + +func (client *MockClient) ContainerLogs(id string, options *dockerclient.LogOptions) (io.ReadCloser, error) { + args := client.Mock.Called(id, options) + return args.Get(0).(io.ReadCloser), args.Error(1) +} + +func (client *MockClient) ContainerChanges(id string) ([]*dockerclient.ContainerChanges, error) { + args := client.Mock.Called(id) + return args.Get(0).([]*dockerclient.ContainerChanges), args.Error(1) +} + +func (client *MockClient) AttachContainer(id string, options *dockerclient.AttachOptions) (io.ReadCloser, error) { + args := client.Mock.Called(id, options) + return args.Get(0).(io.ReadCloser), args.Error(1) +} + +func (client *MockClient) StartContainer(id string, config *dockerclient.HostConfig) error { + args := client.Mock.Called(id, config) + return args.Error(0) +} + +func (client *MockClient) StopContainer(id string, timeout int) error { + args := client.Mock.Called(id, timeout) + return args.Error(0) +} + +func (client *MockClient) RestartContainer(id string, timeout int) error { + args := client.Mock.Called(id, timeout) + return args.Error(0) +} + +func (client *MockClient) KillContainer(id, signal string) error { + args := client.Mock.Called(id, signal) + return args.Error(0) +} + +func (client *MockClient) Wait(id string) <-chan dockerclient.WaitResult { + args := client.Mock.Called(id) + return args.Get(0).(<-chan dockerclient.WaitResult) +} + +func (client *MockClient) MonitorEvents(options *dockerclient.MonitorEventsOptions, stopChan <-chan struct{}) (<-chan dockerclient.EventOrError, error) { + args := client.Mock.Called(options, stopChan) + return args.Get(0).(<-chan dockerclient.EventOrError), args.Error(1) +} + +func (client *MockClient) StartMonitorEvents(cb dockerclient.Callback, ec chan error, args ...interface{}) { + client.Mock.Called(cb, ec, args) +} + +func (client *MockClient) StopAllMonitorEvents() { + client.Mock.Called() +} + +func (client *MockClient) TagImage(nameOrID string, repo string, tag string, force bool) error { + args := client.Mock.Called(nameOrID, repo, tag, force) + return args.Error(0) +} + +func (client *MockClient) StartMonitorStats(id string, cb dockerclient.StatCallback, ec chan error, args ...interface{}) { + client.Mock.Called(id, cb, ec, args) +} + +func (client *MockClient) StopAllMonitorStats() { + client.Mock.Called() +} + +func (client *MockClient) Version() (*dockerclient.Version, error) { + args := client.Mock.Called() + return args.Get(0).(*dockerclient.Version), args.Error(1) +} + +func (client *MockClient) PullImage(name string, auth *dockerclient.AuthConfig) error { + args := client.Mock.Called(name, auth) + return args.Error(0) +} + +func (client *MockClient) PushImage(name string, tag string, auth *dockerclient.AuthConfig) error { + args := client.Mock.Called(name, tag, auth) + return args.Error(0) +} + +func (client *MockClient) LoadImage(reader io.Reader) error { + args := client.Mock.Called(reader) + return args.Error(0) +} + +func (client *MockClient) RemoveContainer(id string, force, volumes bool) error { + args := client.Mock.Called(id, force, volumes) + return args.Error(0) +} + +func (client *MockClient) ListImages(all bool) ([]*dockerclient.Image, error) { + args := client.Mock.Called(all) + return args.Get(0).([]*dockerclient.Image), args.Error(1) +} + +func (client *MockClient) RemoveImage(name string, force bool) ([]*dockerclient.ImageDelete, error) { + args := client.Mock.Called(name, force) + return args.Get(0).([]*dockerclient.ImageDelete), args.Error(1) +} + +func (client *MockClient) PauseContainer(name string) error { + args := client.Mock.Called(name) + return args.Error(0) +} + +func (client *MockClient) UnpauseContainer(name string) error { + args := client.Mock.Called(name) + return args.Error(0) +} + +func (client *MockClient) ExecCreate(config *dockerclient.ExecConfig) (string, error) { + args := client.Mock.Called(config) + return args.String(0), args.Error(1) +} + +func (client *MockClient) ExecStart(id string, config *dockerclient.ExecConfig) error { + args := client.Mock.Called(id, config) + return args.Error(0) +} + +func (client *MockClient) ExecResize(id string, width, height int) error { + args := client.Mock.Called(id, width, height) + return args.Error(0) +} + +func (client *MockClient) RenameContainer(oldName string, newName string) error { + args := client.Mock.Called(oldName, newName) + return args.Error(0) +} + +func (client *MockClient) ImportImage(source string, repository string, tag string, tar io.Reader) (io.ReadCloser, error) { + args := client.Mock.Called(source, repository, tag, tar) + return args.Get(0).(io.ReadCloser), args.Error(1) +} + +func (client *MockClient) BuildImage(image *dockerclient.BuildImage) (io.ReadCloser, error) { + args := client.Mock.Called(image) + return args.Get(0).(io.ReadCloser), args.Error(1) +} + +func (client *MockClient) ListVolumes() ([]*dockerclient.Volume, error) { + args := client.Mock.Called() + return args.Get(0).([]*dockerclient.Volume), args.Error(1) +} + +func (client *MockClient) RemoveVolume(name string) error { + args := client.Mock.Called(name) + return args.Error(0) +} + +func (client *MockClient) CreateVolume(request *dockerclient.VolumeCreateRequest) (*dockerclient.Volume, error) { + args := client.Mock.Called(request) + return args.Get(0).(*dockerclient.Volume), args.Error(1) +} + +func (client *MockClient) ListNetworks(filters string) ([]*dockerclient.NetworkResource, error) { + args := client.Mock.Called(filters) + return args.Get(0).([]*dockerclient.NetworkResource), args.Error(1) +} + +func (client *MockClient) InspectNetwork(id string) (*dockerclient.NetworkResource, error) { + args := client.Mock.Called(id) + return args.Get(0).(*dockerclient.NetworkResource), args.Error(1) +} + +func (client *MockClient) CreateNetwork(config *dockerclient.NetworkCreate) (*dockerclient.NetworkCreateResponse, error) { + args := client.Mock.Called(config) + return args.Get(0).(*dockerclient.NetworkCreateResponse), args.Error(1) +} + +func (client *MockClient) ConnectNetwork(id, container string) error { + args := client.Mock.Called(id, container) + return args.Error(0) +} + +func (client *MockClient) DisconnectNetwork(id, container string) error { + args := client.Mock.Called(id, container) + return args.Error(0) +} + +func (client *MockClient) RemoveNetwork(id string) error { + args := client.Mock.Called(id) + return args.Error(0) +} diff --git a/vendor/github.com/samalba/dockerclient/nopclient/nop.go b/vendor/github.com/samalba/dockerclient/nopclient/nop.go new file mode 100644 index 0000000000..9ab8bf7881 --- /dev/null +++ b/vendor/github.com/samalba/dockerclient/nopclient/nop.go @@ -0,0 +1,191 @@ +package nopclient + +import ( + "errors" + "io" + + "github.com/samalba/dockerclient" +) + +var ( + ErrNoEngine = errors.New("Engine no longer exists") +) + +type NopClient struct { +} + +func NewNopClient() *NopClient { + return &NopClient{} +} + +func (client *NopClient) Info() (*dockerclient.Info, error) { + return nil, ErrNoEngine +} + +func (client *NopClient) ListContainers(all bool, size bool, filters string) ([]dockerclient.Container, error) { + return nil, ErrNoEngine +} + +func (client *NopClient) InspectContainer(id string) (*dockerclient.ContainerInfo, error) { + return nil, ErrNoEngine +} + +func (client *NopClient) InspectImage(id string) (*dockerclient.ImageInfo, error) { + return nil, ErrNoEngine +} + +func (client *NopClient) CreateContainer(config *dockerclient.ContainerConfig, name string) (string, error) { + return "", ErrNoEngine +} + +func (client *NopClient) ContainerLogs(id string, options *dockerclient.LogOptions) (io.ReadCloser, error) { + return nil, ErrNoEngine +} + +func (client *NopClient) ContainerChanges(id string) ([]*dockerclient.ContainerChanges, error) { + return nil, ErrNoEngine +} + +func (client *NopClient) AttachContainer(id string, options *dockerclient.AttachOptions) (io.ReadCloser, error) { + return nil, ErrNoEngine +} + +func (client *NopClient) StartContainer(id string, config *dockerclient.HostConfig) error { + return ErrNoEngine +} + +func (client *NopClient) StopContainer(id string, timeout int) error { + return ErrNoEngine +} + +func (client *NopClient) RestartContainer(id string, timeout int) error { + return ErrNoEngine +} + +func (client *NopClient) KillContainer(id, signal string) error { + return ErrNoEngine +} + +func (client *NopClient) Wait(id string) <-chan dockerclient.WaitResult { + return nil +} + +func (client *NopClient) MonitorEvents(options *dockerclient.MonitorEventsOptions, stopChan <-chan struct{}) (<-chan dockerclient.EventOrError, error) { + return nil, ErrNoEngine +} + +func (client *NopClient) StartMonitorEvents(cb dockerclient.Callback, ec chan error, args ...interface{}) { + return +} + +func (client *NopClient) StopAllMonitorEvents() { + return +} + +func (client *NopClient) TagImage(nameOrID string, repo string, tag string, force bool) error { + return ErrNoEngine +} + +func (client *NopClient) StartMonitorStats(id string, cb dockerclient.StatCallback, ec chan error, args ...interface{}) { + return +} + +func (client *NopClient) StopAllMonitorStats() { + return +} + +func (client *NopClient) Version() (*dockerclient.Version, error) { + return nil, ErrNoEngine +} + +func (client *NopClient) PullImage(name string, auth *dockerclient.AuthConfig) error { + return ErrNoEngine +} + +func (client *NopClient) PushImage(name, tag string, auth *dockerclient.AuthConfig) error { + return ErrNoEngine +} + +func (client *NopClient) LoadImage(reader io.Reader) error { + return ErrNoEngine +} + +func (client *NopClient) RemoveContainer(id string, force, volumes bool) error { + return ErrNoEngine +} + +func (client *NopClient) ListImages(all bool) ([]*dockerclient.Image, error) { + return nil, ErrNoEngine +} + +func (client *NopClient) RemoveImage(name string, force bool) ([]*dockerclient.ImageDelete, error) { + return nil, ErrNoEngine +} + +func (client *NopClient) PauseContainer(name string) error { + return ErrNoEngine +} + +func (client *NopClient) UnpauseContainer(name string) error { + return ErrNoEngine +} + +func (client *NopClient) ExecCreate(config *dockerclient.ExecConfig) (string, error) { + return "", ErrNoEngine +} + +func (client *NopClient) ExecStart(id string, config *dockerclient.ExecConfig) error { + return ErrNoEngine +} + +func (client *NopClient) ExecResize(id string, width, height int) error { + return ErrNoEngine +} + +func (client *NopClient) RenameContainer(oldName string, newName string) error { + return ErrNoEngine +} + +func (client *NopClient) ImportImage(source string, repository string, tag string, tar io.Reader) (io.ReadCloser, error) { + return nil, ErrNoEngine +} + +func (client *NopClient) BuildImage(image *dockerclient.BuildImage) (io.ReadCloser, error) { + return nil, ErrNoEngine +} + +func (client *NopClient) ListVolumes() ([]*dockerclient.Volume, error) { + return nil, ErrNoEngine +} + +func (client *NopClient) RemoveVolume(name string) error { + return ErrNoEngine +} + +func (client *NopClient) CreateVolume(request *dockerclient.VolumeCreateRequest) (*dockerclient.Volume, error) { + return nil, ErrNoEngine +} + +func (client *NopClient) ListNetworks(filters string) ([]*dockerclient.NetworkResource, error) { + return nil, ErrNoEngine +} + +func (client *NopClient) InspectNetwork(id string) (*dockerclient.NetworkResource, error) { + return nil, ErrNoEngine +} + +func (client *NopClient) CreateNetwork(config *dockerclient.NetworkCreate) (*dockerclient.NetworkCreateResponse, error) { + return nil, ErrNoEngine +} + +func (client *NopClient) ConnectNetwork(id, container string) error { + return ErrNoEngine +} + +func (client *NopClient) DisconnectNetwork(id, container string) error { + return ErrNoEngine +} + +func (client *NopClient) RemoveNetwork(id string) error { + return ErrNoEngine +} diff --git a/vendor/github.com/samalba/dockerclient/types.go b/vendor/github.com/samalba/dockerclient/types.go new file mode 100644 index 0000000000..95dcb42d2b --- /dev/null +++ b/vendor/github.com/samalba/dockerclient/types.go @@ -0,0 +1,538 @@ +package dockerclient + +import ( + "fmt" + "io" + "time" + + "github.com/docker/docker/pkg/units" +) + +type ContainerConfig struct { + Hostname string + Domainname string + User string + AttachStdin bool + AttachStdout bool + AttachStderr bool + ExposedPorts map[string]struct{} + Tty bool + OpenStdin bool + StdinOnce bool + Env []string + Cmd []string + Image string + Volumes map[string]struct{} + WorkingDir string + Entrypoint []string + NetworkDisabled bool + MacAddress string + OnBuild []string + Labels map[string]string + StopSignal string + + // FIXME: VolumeDriver have been removed since docker 1.9 + VolumeDriver string + + // FIXME: The following fields have been removed since API v1.18 + Memory int64 + MemorySwap int64 + CpuShares int64 + Cpuset string + PortSpecs []string + + // This is used only by the create command + HostConfig HostConfig +} + +type HostConfig struct { + Binds []string + ContainerIDFile string + LxcConf []map[string]string + Memory int64 + MemoryReservation int64 + MemorySwap int64 + KernelMemory int64 + CpuShares int64 + CpuPeriod int64 + CpusetCpus string + CpusetMems string + CpuQuota int64 + BlkioWeight int64 + OomKillDisable bool + MemorySwappiness int64 + Privileged bool + PortBindings map[string][]PortBinding + Links []string + PublishAllPorts bool + Dns []string + DNSOptions []string + DnsSearch []string + ExtraHosts []string + VolumesFrom []string + Devices []DeviceMapping + NetworkMode string + IpcMode string + PidMode string + UTSMode string + CapAdd []string + CapDrop []string + GroupAdd []string + RestartPolicy RestartPolicy + SecurityOpt []string + ReadonlyRootfs bool + Ulimits []Ulimit + LogConfig LogConfig + CgroupParent string + ConsoleSize [2]int + VolumeDriver string +} + +type DeviceMapping struct { + PathOnHost string `json:"PathOnHost"` + PathInContainer string `json:"PathInContainer"` + CgroupPermissions string `json:"CgroupPermissions"` +} + +type ExecConfig struct { + AttachStdin bool + AttachStdout bool + AttachStderr bool + Tty bool + Cmd []string + Container string + Detach bool +} + +type LogOptions struct { + Follow bool + Stdout bool + Stderr bool + Timestamps bool + Tail int64 +} + +type AttachOptions struct { + Logs bool + Stream bool + Stdin bool + Stdout bool + Stderr bool +} + +type MonitorEventsFilters struct { + Event string `json:",omitempty"` + Image string `json:",omitempty"` + Container string `json:",omitempty"` +} + +type MonitorEventsOptions struct { + Since int + Until int + Filters *MonitorEventsFilters `json:",omitempty"` +} + +type RestartPolicy struct { + Name string + MaximumRetryCount int64 +} + +type PortBinding struct { + HostIp string + HostPort string +} + +type State struct { + Running bool + Paused bool + Restarting bool + OOMKilled bool + Dead bool + Pid int + ExitCode int + Error string // contains last known error when starting the container + StartedAt time.Time + FinishedAt time.Time + Ghost bool +} + +// String returns a human-readable description of the state +// Stoken from docker/docker/daemon/state.go +func (s *State) String() string { + if s.Running { + if s.Paused { + return fmt.Sprintf("Up %s (Paused)", units.HumanDuration(time.Now().UTC().Sub(s.StartedAt))) + } + if s.Restarting { + return fmt.Sprintf("Restarting (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt))) + } + + return fmt.Sprintf("Up %s", units.HumanDuration(time.Now().UTC().Sub(s.StartedAt))) + } + + if s.Dead { + return "Dead" + } + + if s.FinishedAt.IsZero() { + return "" + } + + return fmt.Sprintf("Exited (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt))) +} + +// StateString returns a single string to describe state +// Stoken from docker/docker/daemon/state.go +func (s *State) StateString() string { + if s.Running { + if s.Paused { + return "paused" + } + if s.Restarting { + return "restarting" + } + return "running" + } + + if s.Dead { + return "dead" + } + + return "exited" +} + +type ImageInfo struct { + Architecture string + Author string + Comment string + Config *ContainerConfig + Container string + ContainerConfig *ContainerConfig + Created time.Time + DockerVersion string + Id string + Os string + Parent string + Size int64 + VirtualSize int64 +} + +type ContainerInfo struct { + Id string + Created string + Path string + Name string + Args []string + ExecIDs []string + Config *ContainerConfig + State *State + Image string + NetworkSettings struct { + IPAddress string `json:"IpAddress"` + IPPrefixLen int `json:"IpPrefixLen"` + Gateway string + Bridge string + Ports map[string][]PortBinding + } + SysInitPath string + ResolvConfPath string + Volumes map[string]string + HostConfig *HostConfig +} + +type ContainerChanges struct { + Path string + Kind int +} + +type Port struct { + IP string + PrivatePort int + PublicPort int + Type string +} + +type Container struct { + Id string + Names []string + Image string + Command string + Created int64 + Status string + Ports []Port + SizeRw int64 + SizeRootFs int64 + Labels map[string]string +} + +type Event struct { + Id string + Status string + From string + Time int64 +} + +type Version struct { + ApiVersion string + Arch string + GitCommit string + GoVersion string + KernelVersion string + Os string + Version string +} + +type RespContainersCreate struct { + Id string + Warnings []string +} + +type Image struct { + Created int64 + Id string + Labels map[string]string + ParentId string + RepoDigests []string + RepoTags []string + Size int64 + VirtualSize int64 +} + +// Info is the struct returned by /info +// The API is currently in flux, so Debug, MemoryLimit, SwapLimit, and +// IPv4Forwarding are interfaces because in docker 1.6.1 they are 0 or 1 but in +// master they are bools. +type Info struct { + ID string + Containers int64 + Driver string + DriverStatus [][]string + ExecutionDriver string + Images int64 + KernelVersion string + OperatingSystem string + NCPU int64 + MemTotal int64 + Name string + Labels []string + Debug interface{} + NFd int64 + NGoroutines int64 + SystemTime string + NEventsListener int64 + InitPath string + InitSha1 string + IndexServerAddress string + MemoryLimit interface{} + SwapLimit interface{} + IPv4Forwarding interface{} + BridgeNfIptables bool + BridgeNfIp6tables bool + DockerRootDir string + HttpProxy string + HttpsProxy string + NoProxy string +} + +type ImageDelete struct { + Deleted string + Untagged string +} + +type EventOrError struct { + Event + Error error +} + +type WaitResult struct { + ExitCode int + Error error +} + +type decodingResult struct { + result interface{} + err error +} + +// The following are types for the API stats endpoint +type ThrottlingData struct { + // Number of periods with throttling active + Periods uint64 `json:"periods"` + // Number of periods when the container hit its throttling limit. + ThrottledPeriods uint64 `json:"throttled_periods"` + // Aggregate time the container was throttled for in nanoseconds. + ThrottledTime uint64 `json:"throttled_time"` +} + +type CpuUsage struct { + // Total CPU time consumed. + // Units: nanoseconds. + TotalUsage uint64 `json:"total_usage"` + // Total CPU time consumed per core. + // Units: nanoseconds. + PercpuUsage []uint64 `json:"percpu_usage"` + // Time spent by tasks of the cgroup in kernel mode. + // Units: nanoseconds. + UsageInKernelmode uint64 `json:"usage_in_kernelmode"` + // Time spent by tasks of the cgroup in user mode. + // Units: nanoseconds. + UsageInUsermode uint64 `json:"usage_in_usermode"` +} + +type CpuStats struct { + CpuUsage CpuUsage `json:"cpu_usage"` + SystemUsage uint64 `json:"system_cpu_usage"` + ThrottlingData ThrottlingData `json:"throttling_data,omitempty"` +} + +type NetworkStats struct { + RxBytes uint64 `json:"rx_bytes"` + RxPackets uint64 `json:"rx_packets"` + RxErrors uint64 `json:"rx_errors"` + RxDropped uint64 `json:"rx_dropped"` + TxBytes uint64 `json:"tx_bytes"` + TxPackets uint64 `json:"tx_packets"` + TxErrors uint64 `json:"tx_errors"` + TxDropped uint64 `json:"tx_dropped"` +} + +type MemoryStats struct { + Usage uint64 `json:"usage"` + MaxUsage uint64 `json:"max_usage"` + Stats map[string]uint64 `json:"stats"` + Failcnt uint64 `json:"failcnt"` + Limit uint64 `json:"limit"` +} + +type BlkioStatEntry struct { + Major uint64 `json:"major"` + Minor uint64 `json:"minor"` + Op string `json:"op"` + Value uint64 `json:"value"` +} + +type BlkioStats struct { + // number of bytes tranferred to and from the block device + IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive"` + IoServicedRecursive []BlkioStatEntry `json:"io_serviced_recursive"` + IoQueuedRecursive []BlkioStatEntry `json:"io_queue_recursive"` + IoServiceTimeRecursive []BlkioStatEntry `json:"io_service_time_recursive"` + IoWaitTimeRecursive []BlkioStatEntry `json:"io_wait_time_recursive"` + IoMergedRecursive []BlkioStatEntry `json:"io_merged_recursive"` + IoTimeRecursive []BlkioStatEntry `json:"io_time_recursive"` + SectorsRecursive []BlkioStatEntry `json:"sectors_recursive"` +} + +type Stats struct { + Read time.Time `json:"read"` + NetworkStats NetworkStats `json:"network,omitempty"` + CpuStats CpuStats `json:"cpu_stats,omitempty"` + MemoryStats MemoryStats `json:"memory_stats,omitempty"` + BlkioStats BlkioStats `json:"blkio_stats,omitempty"` +} + +type Ulimit struct { + Name string `json:"name"` + Soft uint64 `json:"soft"` + Hard uint64 `json:"hard"` +} + +type LogConfig struct { + Type string `json:"type"` + Config map[string]string `json:"config"` +} + +type BuildImage struct { + Config *ConfigFile + DockerfileName string + Context io.Reader + RemoteURL string + RepoName string + SuppressOutput bool + NoCache bool + Remove bool + ForceRemove bool + Pull bool + Memory int64 + MemorySwap int64 + CpuShares int64 + CpuPeriod int64 + CpuQuota int64 + CpuSetCpus string + CpuSetMems string + CgroupParent string + BuildArgs map[string]string +} + +type Volume struct { + Name string // Name is the name of the volume + Driver string // Driver is the Driver name used to create the volume + Mountpoint string // Mountpoint is the location on disk of the volume +} + +type VolumesListResponse struct { + Volumes []*Volume // Volumes is the list of volumes being returned +} + +type VolumeCreateRequest struct { + Name string // Name is the requested name of the volume + Driver string // Driver is the name of the driver that should be used to create the volume + DriverOpts map[string]string // DriverOpts holds the driver specific options to use for when creating the volume. +} + +// IPAM represents IP Address Management +type IPAM struct { + Driver string + Config []IPAMConfig +} + +// IPAMConfig represents IPAM configurations +type IPAMConfig struct { + Subnet string `json:",omitempty"` + IPRange string `json:",omitempty"` + Gateway string `json:",omitempty"` + AuxAddress map[string]string `json:"AuxiliaryAddresses,omitempty"` +} + +// NetworkResource is the body of the "get network" http response message +type NetworkResource struct { + Name string + ID string `json:"Id"` + Scope string + Driver string + IPAM IPAM + Containers map[string]EndpointResource +} + +//EndpointResource contains network resources allocated and usd for a container in a network +type EndpointResource struct { + EndpointID string + MacAddress string + IPv4Address string + IPv6Address string +} + +// NetworkCreate is the expected body of the "create network" http request message +type NetworkCreate struct { + Name string + CheckDuplicate bool + Driver string + IPAM IPAM + Options map[string]string +} + +// NetworkCreateResponse is the response message sent by the server for network create call +type NetworkCreateResponse struct { + ID string `json:"Id"` + Warning string +} + +// NetworkConnect represents the data to be used to connect a container to the network +type NetworkConnect struct { + Container string +} + +// NetworkDisconnect represents the data to be used to disconnect a container from the network +type NetworkDisconnect struct { + Container string +} diff --git a/vendor/github.com/samalba/dockerclient/utils.go b/vendor/github.com/samalba/dockerclient/utils.go new file mode 100644 index 0000000000..806f1b3e6a --- /dev/null +++ b/vendor/github.com/samalba/dockerclient/utils.go @@ -0,0 +1,33 @@ +package dockerclient + +import ( + "crypto/tls" + "net" + "net/http" + "net/url" + "time" +) + +func newHTTPClient(u *url.URL, tlsConfig *tls.Config, timeout time.Duration) *http.Client { + httpTransport := &http.Transport{ + TLSClientConfig: tlsConfig, + } + + switch u.Scheme { + default: + httpTransport.Dial = func(proto, addr string) (net.Conn, error) { + return net.DialTimeout(proto, addr, timeout) + } + case "unix": + socketPath := u.Path + unixDial := func(proto, addr string) (net.Conn, error) { + return net.DialTimeout("unix", socketPath, timeout) + } + httpTransport.Dial = unixDial + // Override the main URL object so the HTTP lib won't complain + u.Scheme = "http" + u.Host = "unix.sock" + u.Path = "" + } + return &http.Client{Transport: httpTransport} +} From 3612c556770b19e330356f8e285becfd392328b5 Mon Sep 17 00:00:00 2001 From: David Gageot Date: Fri, 27 Nov 2015 18:32:13 +0100 Subject: [PATCH 2/2] Add version to machine ls Signed-off-by: David Gageot --- commands/active.go | 5 +- commands/commands.go | 5 +- commands/commandstest/fake_command_line.go | 4 +- commands/ls.go | 48 ++++++---- commands/ls_test.go | 40 ++++++--- commands/url.go | 2 +- commands/version.go | 35 +++++++- commands/version_test.go | 89 +++++++++++++++++++ contrib/completion/bash/docker-machine.bash | 8 ++ docs/install-machine.md | 4 +- libmachine/cert/cert.go | 22 +++-- libmachine/check/check_test.go | 6 ++ libmachine/host/host.go | 11 ++- libmachine/mcndockerclient/docker_client.go | 22 +++++ libmachine/mcndockerclient/docker_host.go | 16 ++++ .../mcndockerclient/docker_versioner.go | 29 ++++++ .../mcndockerclient/fake_docker_versioner.go | 20 +++++ libmachine/persist/filestore_test.go | 2 +- test/integration/core/core-commands.bats | 14 +++ 19 files changed, 332 insertions(+), 50 deletions(-) create mode 100644 commands/version_test.go create mode 100644 libmachine/mcndockerclient/docker_client.go create mode 100644 libmachine/mcndockerclient/docker_host.go create mode 100644 libmachine/mcndockerclient/docker_versioner.go create mode 100644 libmachine/mcndockerclient/fake_docker_versioner.go diff --git a/commands/active.go b/commands/active.go index 09661cc239..33743b08b3 100644 --- a/commands/active.go +++ b/commands/active.go @@ -9,13 +9,12 @@ import ( ) var ( - errTooManyArguments = errors.New("Error: Too many arguments given") - errNoActiveHost = errors.New("No active host found") + errNoActiveHost = errors.New("No active host found") ) func cmdActive(c CommandLine, api libmachine.API) error { if len(c.Args()) > 0 { - return errTooManyArguments + return ErrTooManyArguments } hosts, hostsInError, err := persist.LoadAllHosts(api) diff --git a/commands/commands.go b/commands/commands.go index 8727bb3006..ab67792b67 100644 --- a/commands/commands.go +++ b/commands/commands.go @@ -22,6 +22,7 @@ var ( ErrUnknownShell = errors.New("Error: Unknown shell") ErrNoMachineSpecified = errors.New("Error: Expected to get one or more machine names as arguments") ErrExpectedOneMachine = errors.New("Error: Expected one machine name as an argument") + ErrTooManyArguments = errors.New("Error: Too many arguments given") ) // CommandLine contains all the information passed to the commands on the command line. @@ -305,7 +306,7 @@ var Commands = []cli.Command{ }, { Name: "version", - Usage: "Show the Docker Machine version information", + Usage: "Show the Docker Machine version or a machine docker version", Action: fatalOnError(cmdVersion), }, } @@ -316,7 +317,9 @@ func printIP(h *host.Host) func() error { if err != nil { return fmt.Errorf("Error getting IP address: %s", err) } + fmt.Println(ip) + return nil } } diff --git a/commands/commandstest/fake_command_line.go b/commands/commandstest/fake_command_line.go index df11c488d6..4a070b5a19 100644 --- a/commands/commandstest/fake_command_line.go +++ b/commands/commandstest/fake_command_line.go @@ -10,7 +10,7 @@ type FakeFlagger struct { type FakeCommandLine struct { LocalFlags, GlobalFlags *FakeFlagger - HelpShown bool + HelpShown, VersionShown bool CliArgs []string } @@ -91,5 +91,5 @@ func (fcli *FakeCommandLine) Args() cli.Args { } func (fcli *FakeCommandLine) ShowVersion() { - return + fcli.VersionShown = true } diff --git a/commands/ls.go b/commands/ls.go index 71e9ad3ef5..1a30b68f51 100644 --- a/commands/ls.go +++ b/commands/ls.go @@ -33,13 +33,14 @@ type FilterOptions struct { } type HostListItem struct { - Name string - Active bool - DriverName string - State state.State - URL string - SwarmOptions *swarm.Options - Error string + Name string + Active bool + DriverName string + State state.State + URL string + SwarmOptions *swarm.Options + Error string + DockerVersion string } func cmdLs(c CommandLine, api libmachine.API) error { @@ -68,7 +69,7 @@ func cmdLs(c CommandLine, api libmachine.API) error { swarmInfo := make(map[string]string) w := tabwriter.NewWriter(os.Stdout, 5, 1, 3, ' ', 0) - fmt.Fprintln(w, "NAME\tACTIVE\tDRIVER\tSTATE\tURL\tSWARM\tERRORS") + fmt.Fprintln(w, "NAME\tACTIVE\tDRIVER\tSTATE\tURL\tSWARM\tDOCKER\tERRORS") for _, host := range hostList { swarmOptions := host.HostOptions.SwarmOptions @@ -97,8 +98,8 @@ func cmdLs(c CommandLine, api libmachine.API) error { swarmInfo = fmt.Sprintf("%s (master)", swarmInfo) } } - fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", - item.Name, activeString, item.DriverName, item.State, item.URL, swarmInfo, item.Error) + fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", + item.Name, activeString, item.DriverName, item.State, item.URL, swarmInfo, item.DockerVersion, item.Error) } w.Flush() @@ -232,11 +233,21 @@ func matchesName(host *host.Host, names []string) bool { func attemptGetHostState(h *host.Host, stateQueryChan chan<- HostListItem) { url := "" hostError := "" + dockerVersion := "Unknown" currentState, err := h.Driver.GetState() if err == nil { - url, err = h.GetURL() + url, err = h.URL() } + if err == nil { + dockerVersion, err = h.DockerVersion() + if err != nil { + dockerVersion = "Unknown" + } else { + dockerVersion = fmt.Sprintf("v%s", dockerVersion) + } + } + if err != nil { hostError = err.Error() } @@ -250,13 +261,14 @@ func attemptGetHostState(h *host.Host, stateQueryChan chan<- HostListItem) { } stateQueryChan <- HostListItem{ - Name: h.Name, - Active: isActive(currentState, url), - DriverName: h.Driver.DriverName(), - State: currentState, - URL: url, - SwarmOptions: swarmOptions, - Error: hostError, + Name: h.Name, + Active: isActive(currentState, url), + DriverName: h.Driver.DriverName(), + State: currentState, + URL: url, + SwarmOptions: swarmOptions, + DockerVersion: dockerVersion, + Error: hostError, } } diff --git a/commands/ls_test.go b/commands/ls_test.go index 1ed2bd4451..2b3ffdd5fa 100644 --- a/commands/ls_test.go +++ b/commands/ls_test.go @@ -10,6 +10,7 @@ import ( "github.com/docker/machine/drivers/fakedriver" "github.com/docker/machine/libmachine/host" + "github.com/docker/machine/libmachine/mcndockerclient" "github.com/docker/machine/libmachine/state" "github.com/docker/machine/libmachine/swarm" "github.com/stretchr/testify/assert" @@ -296,6 +297,9 @@ func TestFilterHostsDifferentFlagsProduceAND(t *testing.T) { } func TestGetHostListItems(t *testing.T) { + mcndockerclient.CurrentDockerVersioner = &mcndockerclient.FakeDockerVersioner{Version: "1.9"} + defer mcndockerclient.CleanupDockerVersioner() + // TODO: Ideally this would mockable via interface instead. os.Setenv("DOCKER_HOST", "tcp://active.host.com:2376") @@ -331,14 +335,15 @@ func TestGetHostListItems(t *testing.T) { } expected := []struct { - name string - state state.State - active bool - error string + name string + state state.State + active bool + version string + error string }{ - {"bar10", state.Error, false, "Unable to get ip"}, - {"bar100", state.Stopped, false, ""}, - {"foo", state.Running, true, ""}, + {"bar10", state.Error, false, "Unknown", "Unable to get ip"}, + {"bar100", state.Stopped, false, "Unknown", ""}, + {"foo", state.Running, true, "v1.9", ""}, } items := getHostListItems(hosts, map[string]error{}) @@ -347,6 +352,7 @@ func TestGetHostListItems(t *testing.T) { assert.Equal(t, expected[i].name, items[i].Name) assert.Equal(t, expected[i].state, items[i].State) assert.Equal(t, expected[i].active, items[i].Active) + assert.Equal(t, expected[i].version, items[i].DockerVersion) assert.Equal(t, expected[i].error, items[i].Error) } @@ -355,6 +361,9 @@ func TestGetHostListItems(t *testing.T) { // issue #1908 func TestGetHostListItemsEnvDockerHostUnset(t *testing.T) { + mcndockerclient.CurrentDockerVersioner = &mcndockerclient.FakeDockerVersioner{Version: "1.9"} + defer mcndockerclient.CleanupDockerVersioner() + orgDockerHost := os.Getenv("DOCKER_HOST") defer func() { // revert DOCKER_HOST @@ -408,12 +417,13 @@ func TestGetHostListItemsEnvDockerHostUnset(t *testing.T) { } expected := map[string]struct { - state state.State - active bool + state state.State + active bool + version string }{ - "foo": {state.Running, false}, - "bar": {state.Stopped, false}, - "baz": {state.Saved, false}, + "foo": {state.Running, false, "v1.9"}, + "bar": {state.Stopped, false, "Unknown"}, + "baz": {state.Saved, false, "Unknown"}, } items := getHostListItems(hosts, map[string]error{}) @@ -423,6 +433,7 @@ func TestGetHostListItemsEnvDockerHostUnset(t *testing.T) { assert.Equal(t, expected.state, item.State) assert.Equal(t, expected.active, item.Active) + assert.Equal(t, expected.version, item.DockerVersion) } } @@ -463,7 +474,7 @@ func TestGetHostStateTimeout(t *testing.T) { }, } - stateTimeoutDuration = 1 * time.Second + stateTimeoutDuration = 1 * time.Millisecond hostItems := getHostListItems(hosts, map[string]error{}) hostItem := hostItems[0] @@ -496,6 +507,9 @@ func TestGetHostStateError(t *testing.T) { } func TestGetSomeHostInEror(t *testing.T) { + mcndockerclient.CurrentDockerVersioner = &mcndockerclient.FakeDockerVersioner{Version: "1.9"} + defer mcndockerclient.CleanupDockerVersioner() + hosts := []*host.Host{ { Name: "foo", diff --git a/commands/url.go b/commands/url.go index 7847c25d35..e5611f209b 100644 --- a/commands/url.go +++ b/commands/url.go @@ -16,7 +16,7 @@ func cmdURL(c CommandLine, api libmachine.API) error { return err } - url, err := host.GetURL() + url, err := host.URL() if err != nil { return err } diff --git a/commands/version.go b/commands/version.go index 835b511eeb..467af675e4 100644 --- a/commands/version.go +++ b/commands/version.go @@ -1,8 +1,39 @@ package commands -import "github.com/docker/machine/libmachine" +import ( + "fmt" + + "io" + "os" + + "github.com/docker/machine/libmachine" +) func cmdVersion(c CommandLine, api libmachine.API) error { - c.ShowVersion() + return printVersion(c, api, os.Stdout) +} + +func printVersion(c CommandLine, api libmachine.API, out io.Writer) error { + if len(c.Args()) == 0 { + c.ShowVersion() + return nil + } + + if len(c.Args()) != 1 { + return ErrExpectedOneMachine + } + + host, err := api.Load(c.Args().First()) + if err != nil { + return err + } + + version, err := host.DockerVersion() + if err != nil { + return err + } + + fmt.Fprintln(out, version) + return nil } diff --git a/commands/version_test.go b/commands/version_test.go new file mode 100644 index 0000000000..9675745d3a --- /dev/null +++ b/commands/version_test.go @@ -0,0 +1,89 @@ +package commands + +import ( + "testing" + + "bytes" + + "github.com/docker/machine/commands/commandstest" + "github.com/docker/machine/drivers/vmwarevsphere/errors" + "github.com/docker/machine/libmachine/host" + "github.com/docker/machine/libmachine/libmachinetest" + "github.com/docker/machine/libmachine/mcndockerclient" + "github.com/stretchr/testify/assert" +) + +func TestCmdVersion(t *testing.T) { + commandLine := &commandstest.FakeCommandLine{} + api := &libmachinetest.FakeAPI{} + + err := cmdVersion(commandLine, api) + + assert.True(t, commandLine.VersionShown) + assert.NoError(t, err) +} + +func TestCmdVersionTooManyNames(t *testing.T) { + commandLine := &commandstest.FakeCommandLine{ + CliArgs: []string{"machine1", "machine2"}, + } + api := &libmachinetest.FakeAPI{} + + err := cmdVersion(commandLine, api) + + assert.EqualError(t, err, "Error: Expected one machine name as an argument") +} + +func TestCmdVersionNotFound(t *testing.T) { + commandLine := &commandstest.FakeCommandLine{ + CliArgs: []string{"unknown"}, + } + api := &libmachinetest.FakeAPI{} + + err := cmdVersion(commandLine, api) + + assert.EqualError(t, err, `Host does not exist: "unknown"`) +} + +func TestCmdVersionOnHost(t *testing.T) { + mcndockerclient.CurrentDockerVersioner = &mcndockerclient.FakeDockerVersioner{Version: "1.9.1"} + defer mcndockerclient.CleanupDockerVersioner() + + commandLine := &commandstest.FakeCommandLine{ + CliArgs: []string{"machine"}, + } + api := &libmachinetest.FakeAPI{ + Hosts: []*host.Host{ + { + Name: "machine", + }, + }, + } + + out := &bytes.Buffer{} + err := printVersion(commandLine, api, out) + + assert.NoError(t, err) + assert.Equal(t, "1.9.1\n", out.String()) +} + +func TestCmdVersionFailure(t *testing.T) { + mcndockerclient.CurrentDockerVersioner = &mcndockerclient.FakeDockerVersioner{Err: errors.New("connection failure")} + defer mcndockerclient.CleanupDockerVersioner() + + commandLine := &commandstest.FakeCommandLine{ + CliArgs: []string{"machine"}, + } + api := &libmachinetest.FakeAPI{ + Hosts: []*host.Host{ + { + Name: "machine", + }, + }, + } + + out := &bytes.Buffer{} + err := printVersion(commandLine, api, out) + + assert.EqualError(t, err, "connection failure") +} diff --git a/contrib/completion/bash/docker-machine.bash b/contrib/completion/bash/docker-machine.bash index ebbe4bb628..bca335ad64 100644 --- a/contrib/completion/bash/docker-machine.bash +++ b/contrib/completion/bash/docker-machine.bash @@ -185,6 +185,14 @@ _docker_machine_url() { fi } +_docker_machine_version() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--help" -- "${cur}")) + else + COMPREPLY=($(compgen -W "$(docker-machine ls -q)" -- "${cur}")) + fi +} + _docker_machine_help() { if [[ "${cur}" == -* ]]; then COMPREPLY=($(compgen -W "--help" -- "${cur}")) diff --git a/docs/install-machine.md b/docs/install-machine.md index a7e2e3f4d6..dc9ed00430 100644 --- a/docs/install-machine.md +++ b/docs/install-machine.md @@ -54,8 +54,8 @@ instructions in the next section. 3. Check the installation by displaying the Machine version: - $ docker-machine -v - machine version 0.5.0 (3e06852) + $ docker-machine version + docker-machine version 0.5.2 (0456b9f) ## Installing bash completion scripts diff --git a/libmachine/cert/cert.go b/libmachine/cert/cert.go index 624cd3396a..b2db6cbf28 100644 --- a/libmachine/cert/cert.go +++ b/libmachine/cert/cert.go @@ -24,6 +24,7 @@ var defaultGenerator = NewX509CertGenerator() type Generator interface { GenerateCACertificate(certFile, keyFile, org string, bits int) error GenerateCert(hosts []string, certFile, keyFile, caFile, caKeyFile, org string, bits int) error + ReadTLSConfig(addr string, authOptions *auth.Options) (*tls.Config, error) ValidateCertificate(addr string, authOptions *auth.Options) (bool, error) } @@ -45,6 +46,10 @@ func ValidateCertificate(addr string, authOptions *auth.Options) (bool, error) { return defaultGenerator.ValidateCertificate(addr, authOptions) } +func ReadTLSConfig(addr string, authOptions *auth.Options) (*tls.Config, error) { + return defaultGenerator.ReadTLSConfig(addr, authOptions) +} + func SetCertGenerator(cg Generator) { defaultGenerator = cg } @@ -204,8 +209,8 @@ func (xcg *X509CertGenerator) GenerateCert(hosts []string, certFile, keyFile, ca return nil } -// ValidateCertificate validate the certificate installed on the vm. -func (xcg *X509CertGenerator) ValidateCertificate(addr string, authOptions *auth.Options) (bool, error) { +// ReadTLSConfig reads the tls config for a machine. +func (xcg *X509CertGenerator) ReadTLSConfig(addr string, authOptions *auth.Options) (*tls.Config, error) { caCertPath := authOptions.CaCertPath serverCertPath := authOptions.ServerCertPath serverKeyPath := authOptions.ServerKeyPath @@ -213,22 +218,27 @@ func (xcg *X509CertGenerator) ValidateCertificate(addr string, authOptions *auth log.Debugf("Reading CA certificate from %s", caCertPath) caCert, err := ioutil.ReadFile(caCertPath) if err != nil { - return false, err + return nil, err } log.Debugf("Reading server certificate from %s", serverCertPath) serverCert, err := ioutil.ReadFile(serverCertPath) if err != nil { - return false, err + return nil, err } log.Debugf("Reading server key from %s", serverKeyPath) serverKey, err := ioutil.ReadFile(serverKeyPath) if err != nil { - return false, err + return nil, err } - tlsConfig, err := xcg.getTLSConfig(caCert, serverCert, serverKey, false) + return xcg.getTLSConfig(caCert, serverCert, serverKey, false) +} + +// ValidateCertificate validate the certificate installed on the vm. +func (xcg *X509CertGenerator) ValidateCertificate(addr string, authOptions *auth.Options) (bool, error) { + tlsConfig, err := xcg.ReadTLSConfig(addr, authOptions) if err != nil { return false, err } diff --git a/libmachine/check/check_test.go b/libmachine/check/check_test.go index 08972c6dd2..8054704e42 100644 --- a/libmachine/check/check_test.go +++ b/libmachine/check/check_test.go @@ -4,6 +4,8 @@ import ( "errors" "testing" + "crypto/tls" + "github.com/docker/machine/libmachine/auth" "github.com/docker/machine/libmachine/cert" "github.com/stretchr/testify/assert" @@ -30,6 +32,10 @@ func (fcg FakeCertGenerator) ValidateCertificate(addr string, authOptions *auth. return fcg.fakeValidateCertificate.IsValid, fcg.fakeValidateCertificate.Err } +func (fcg FakeCertGenerator) ReadTLSConfig(addr string, authOptions *auth.Options) (*tls.Config, error) { + return nil, nil +} + func TestCheckCert(t *testing.T) { errCertsExpired := errors.New("Certs have expired") diff --git a/libmachine/host/host.go b/libmachine/host/host.go index c0672affda..1c7d04a8c8 100644 --- a/libmachine/host/host.go +++ b/libmachine/host/host.go @@ -10,6 +10,7 @@ import ( "github.com/docker/machine/libmachine/drivers" "github.com/docker/machine/libmachine/engine" "github.com/docker/machine/libmachine/log" + "github.com/docker/machine/libmachine/mcndockerclient" "github.com/docker/machine/libmachine/mcnutils" "github.com/docker/machine/libmachine/provision" "github.com/docker/machine/libmachine/provision/pkgaction" @@ -145,10 +146,18 @@ func (h *Host) Upgrade() error { return provisioner.Service("docker", serviceaction.Restart) } -func (h *Host) GetURL() (string, error) { +func (h *Host) URL() (string, error) { return h.Driver.GetURL() } +func (h *Host) AuthOptions() *auth.Options { + return h.HostOptions.AuthOptions +} + +func (h *Host) DockerVersion() (string, error) { + return mcndockerclient.DockerVersion(h) +} + func (h *Host) ConfigureAuth() error { provisioner, err := provision.DetectProvisioner(h.Driver) if err != nil { diff --git a/libmachine/mcndockerclient/docker_client.go b/libmachine/mcndockerclient/docker_client.go new file mode 100644 index 0000000000..438bddd6ab --- /dev/null +++ b/libmachine/mcndockerclient/docker_client.go @@ -0,0 +1,22 @@ +package mcndockerclient + +import ( + "fmt" + + "github.com/docker/machine/libmachine/cert" + "github.com/samalba/dockerclient" +) + +func DockerClient(host DockerHost) (*dockerclient.DockerClient, error) { + url, err := host.URL() + if err != nil { + return nil, err + } + + tlsConfig, err := cert.ReadTLSConfig(url, host.AuthOptions()) + if err != nil { + return nil, fmt.Errorf("Unable to read TLS config: %s", err) + } + + return dockerclient.NewDockerClient(url, tlsConfig) +} diff --git a/libmachine/mcndockerclient/docker_host.go b/libmachine/mcndockerclient/docker_host.go new file mode 100644 index 0000000000..d9b10f3c5f --- /dev/null +++ b/libmachine/mcndockerclient/docker_host.go @@ -0,0 +1,16 @@ +package mcndockerclient + +import "github.com/docker/machine/libmachine/auth" + +type URLer interface { + URL() (string, error) +} + +type AuthOptionser interface { + AuthOptions() *auth.Options +} + +type DockerHost interface { + URLer + AuthOptionser +} diff --git a/libmachine/mcndockerclient/docker_versioner.go b/libmachine/mcndockerclient/docker_versioner.go new file mode 100644 index 0000000000..b8279c777e --- /dev/null +++ b/libmachine/mcndockerclient/docker_versioner.go @@ -0,0 +1,29 @@ +package mcndockerclient + +import "fmt" + +var CurrentDockerVersioner DockerVersioner = &defaultDockerVersioner{} + +type DockerVersioner interface { + DockerVersion(host DockerHost) (string, error) +} + +func DockerVersion(host DockerHost) (string, error) { + return CurrentDockerVersioner.DockerVersion(host) +} + +type defaultDockerVersioner struct{} + +func (dv *defaultDockerVersioner) DockerVersion(host DockerHost) (string, error) { + client, err := DockerClient(host) + if err != nil { + return "", fmt.Errorf("Unable to query docker version: %s", err) + } + + version, err := client.Version() + if err != nil { + return "", fmt.Errorf("Unable to query docker version: %s", err) + } + + return version.Version, nil +} diff --git a/libmachine/mcndockerclient/fake_docker_versioner.go b/libmachine/mcndockerclient/fake_docker_versioner.go new file mode 100644 index 0000000000..8d30360008 --- /dev/null +++ b/libmachine/mcndockerclient/fake_docker_versioner.go @@ -0,0 +1,20 @@ +package mcndockerclient + +var originalDockerVersioner = CurrentDockerVersioner + +func CleanupDockerVersioner() { + CurrentDockerVersioner = originalDockerVersioner +} + +type FakeDockerVersioner struct { + Version string + Err error +} + +func (dv *FakeDockerVersioner) DockerVersion(host DockerHost) (string, error) { + if dv.Err != nil { + return "", dv.Err + } + + return dv.Version, nil +} diff --git a/libmachine/persist/filestore_test.go b/libmachine/persist/filestore_test.go index 874ecda43b..243d565b0b 100644 --- a/libmachine/persist/filestore_test.go +++ b/libmachine/persist/filestore_test.go @@ -238,7 +238,7 @@ func TestStoreLoad(t *testing.T) { h.Driver = realDriver - actualURL, err := h.GetURL() + actualURL, err := h.URL() if err != nil { t.Fatal(err) } diff --git a/test/integration/core/core-commands.bats b/test/integration/core/core-commands.bats index 9d236f733e..7615ad1274 100644 --- a/test/integration/core/core-commands.bats +++ b/test/integration/core/core-commands.bats @@ -61,6 +61,12 @@ load ${BASE_TEST_DIR}/helpers.bash [[ ${lines[0]} =~ "total" ]] } +@test "$DRIVER: version" { + run machine version $NAME + echo ${output} + [ "$status" -eq 0 ] +} + @test "$DRIVER: docker commands with the socket should work" { run machine ssh $NAME -- sudo docker version echo ${output} @@ -93,6 +99,14 @@ load ${BASE_TEST_DIR}/helpers.bash [[ ${output} == *"not running. Please start"* ]] } +@test "$DRIVER: version should show an error when machine is stopped" { + run machine version $NAME + echo ${output} + [ "$status" -eq 1 ] + [[ ${output} == *"not running"* ]] +} + + @test "$DRIVER: machine should not allow upgrade when stopped" { run machine upgrade $NAME echo ${output}