diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 6bd860c7f0..8f66b8e9ae 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -12,11 +12,6 @@
"Comment": "v1.1-17-g515f3ec",
"Rev": "515f3ec74ce6a5b31e934cefae997c97bd0a1b1e"
},
- {
- "ImportPath": "github.com/Sirupsen/logrus",
- "Comment": "v0.6.1",
- "Rev": "1f2ba2c6317323dd667bd266c1e8ebffc4a4c62f"
- },
{
"ImportPath": "github.com/cenkalti/backoff",
"Rev": "9831e1e25c874e0a0601b6dc43641071414eec7a"
@@ -31,11 +26,6 @@
"Comment": "v0.5.0",
"Rev": "5478aae80694de1d2d0e02c386bbedd201266234"
},
- {
- "ImportPath": "github.com/docker/docker/api",
- "Comment": "v1.5.0",
- "Rev": "a8a31eff10544860d2188dddabdee4d727545796"
- },
{
"ImportPath": "github.com/docker/docker/dockerversion",
"Comment": "v1.5.0",
@@ -106,11 +96,6 @@
"Comment": "v1.5.0",
"Rev": "a8a31eff10544860d2188dddabdee4d727545796"
},
- {
- "ImportPath": "github.com/docker/docker/utils",
- "Comment": "v1.5.0",
- "Rev": "a8a31eff10544860d2188dddabdee4d727545796"
- },
{
"ImportPath": "github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar",
"Comment": "v1.5.0",
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/.gitignore b/Godeps/_workspace/src/github.com/Sirupsen/logrus/.gitignore
deleted file mode 100644
index 66be63a005..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-logrus
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/.travis.yml b/Godeps/_workspace/src/github.com/Sirupsen/logrus/.travis.yml
deleted file mode 100644
index d5a559f840..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/.travis.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-language: go
-go:
- - 1.2
- - 1.3
- - tip
-install:
- - go get github.com/stretchr/testify
- - go get github.com/stvp/go-udp-testing
- - go get github.com/tobi/airbrake-go
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/LICENSE b/Godeps/_workspace/src/github.com/Sirupsen/logrus/LICENSE
deleted file mode 100644
index f090cb42f3..0000000000
--- a/Godeps/_workspace/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/Godeps/_workspace/src/github.com/Sirupsen/logrus/README.md b/Godeps/_workspace/src/github.com/Sirupsen/logrus/README.md
deleted file mode 100644
index cabd027ae9..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/README.md
+++ /dev/null
@@ -1,349 +0,0 @@
-# Logrus
[](https://travis-ci.org/Sirupsen/logrus)
-
-Logrus is a structured logger for Go (golang), completely API compatible with
-the standard library logger. [Godoc][godoc]. **Please note the Logrus API is not
-yet stable (pre 1.0), the core API is unlikely change much but please version
-control your Logrus to make sure you aren't fetching latest `master` on every
-build.**
-
-Nicely color-coded in development (when a TTY is attached, otherwise just
-plain text):
-
-
-
-With `log.Formatter = new(logrus.JSONFormatter)`, for easy parsing by logstash
-or Splunk:
-
-```json
-{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the
-ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}
-
-{"level":"warning","msg":"The group's number increased tremendously!",
-"number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"}
-
-{"animal":"walrus","level":"info","msg":"A giant walrus appears!",
-"size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"}
-
-{"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.",
-"size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"}
-
-{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true,
-"time":"2014-03-10 19:57:38.562543128 -0400 EDT"}
-```
-
-With the default `log.Formatter = new(logrus.TextFormatter)` when a TTY is not
-attached, the output is compatible with the
-[l2met](http://r.32k.io/l2met-introduction) format:
-
-```text
-time="2014-04-20 15:36:23.830442383 -0400 EDT" level="info" msg="A group of walrus emerges from the ocean" animal="walrus" size=10
-time="2014-04-20 15:36:23.830584199 -0400 EDT" level="warning" msg="The group's number increased tremendously!" omg=true number=122
-time="2014-04-20 15:36:23.830596521 -0400 EDT" level="info" msg="A giant walrus appears!" animal="walrus" size=10
-time="2014-04-20 15:36:23.830611837 -0400 EDT" level="info" msg="Tremendously sized cow enters the ocean." animal="walrus" size=9
-time="2014-04-20 15:36:23.830626464 -0400 EDT" level="fatal" msg="The ice breaks!" omg=true number=100
-```
-
-#### Example
-
-The simplest way to use Logrus is simply the package-level exported logger:
-
-```go
-package main
-
-import (
- log "github.com/Sirupsen/logrus"
-)
-
-func main() {
- log.WithFields(log.Fields{
- "animal": "walrus",
- }).Info("A walrus appears")
-}
-```
-
-Note that it's completely api-compatible with the stdlib logger, so you can
-replace your `log` imports everywhere with `log "github.com/Sirupsen/logrus"`
-and you'll now have the flexibility of Logrus. You can customize it all you
-want:
-
-```go
-package main
-
-import (
- "os"
- log "github.com/Sirupsen/logrus"
- "github.com/Sirupsen/logrus/hooks/airbrake"
-)
-
-func init() {
- // Log as JSON instead of the default ASCII formatter.
- log.SetFormatter(&log.JSONFormatter{})
-
- // Use the Airbrake hook to report errors that have Error severity or above to
- // an exception tracker. You can create custom hooks, see the Hooks section.
- log.AddHook(&logrus_airbrake.AirbrakeHook{})
-
- // Output to stderr instead of stdout, could also be a file.
- log.SetOutput(os.Stderr)
-
- // Only log the warning severity or above.
- log.SetLevel(log.WarnLevel)
-}
-
-func main() {
- log.WithFields(log.Fields{
- "animal": "walrus",
- "size": 10,
- }).Info("A group of walrus emerges from the ocean")
-
- log.WithFields(log.Fields{
- "omg": true,
- "number": 122,
- }).Warn("The group's number increased tremendously!")
-
- log.WithFields(log.Fields{
- "omg": true,
- "number": 100,
- }).Fatal("The ice breaks!")
-}
-```
-
-For more advanced usage such as logging to multiple locations from the same
-application, you can also create an instance of the `logrus` Logger:
-
-```go
-package main
-
-import (
- "github.com/Sirupsen/logrus"
-)
-
-// Create a new instance of the logger. You can have any number of instances.
-var log = logrus.New()
-
-func main() {
- // The API for setting attributes is a little different than the package level
- // exported logger. See Godoc.
- log.Out = os.Stderr
-
- log.WithFields(logrus.Fields{
- "animal": "walrus",
- "size": 10,
- }).Info("A group of walrus emerges from the ocean")
-}
-```
-
-#### Fields
-
-Logrus encourages careful, structured logging though logging fields instead of
-long, unparseable error messages. For example, instead of: `log.Fatalf("Failed
-to send event %s to topic %s with key %d")`, you should log the much more
-discoverable:
-
-```go
-log.WithFields(log.Fields{
- "event": event,
- "topic": topic,
- "key": key,
-}).Fatal("Failed to send event")
-```
-
-We've found this API forces you to think about logging in a way that produces
-much more useful logging messages. We've been in countless situations where just
-a single added field to a log statement that was already there would've saved us
-hours. The `WithFields` call is optional.
-
-In general, with Logrus using any of the `printf`-family functions should be
-seen as a hint you should add a field, however, you can still use the
-`printf`-family functions with Logrus.
-
-#### Hooks
-
-You can add hooks for logging levels. For example to send errors to an exception
-tracking service on `Error`, `Fatal` and `Panic`, info to StatsD or log to
-multiple places simultaneously, e.g. syslog.
-
-```go
-// Not the real implementation of the Airbrake hook. Just a simple sample.
-import (
- log "github.com/Sirupsen/logrus"
-)
-
-func init() {
- log.AddHook(new(AirbrakeHook))
-}
-
-type AirbrakeHook struct{}
-
-// `Fire()` takes the entry that the hook is fired for. `entry.Data[]` contains
-// the fields for the entry. See the Fields section of the README.
-func (hook *AirbrakeHook) Fire(entry *logrus.Entry) error {
- err := airbrake.Notify(entry.Data["error"].(error))
- if err != nil {
- log.WithFields(log.Fields{
- "source": "airbrake",
- "endpoint": airbrake.Endpoint,
- }).Info("Failed to send error to Airbrake")
- }
-
- return nil
-}
-
-// `Levels()` returns a slice of `Levels` the hook is fired for.
-func (hook *AirbrakeHook) Levels() []log.Level {
- return []log.Level{
- log.ErrorLevel,
- log.FatalLevel,
- log.PanicLevel,
- }
-}
-```
-
-Logrus comes with built-in hooks. Add those, or your custom hook, in `init`:
-
-```go
-import (
- log "github.com/Sirupsen/logrus"
- "github.com/Sirupsen/logrus/hooks/airbrake"
- "github.com/Sirupsen/logrus/hooks/syslog"
- "log/syslog"
-)
-
-func init() {
- log.AddHook(new(logrus_airbrake.AirbrakeHook))
-
- hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
- if err != nil {
- log.Error("Unable to connect to local syslog daemon")
- } else {
- log.AddHook(hook)
- }
-}
-```
-
-* [`github.com/Sirupsen/logrus/hooks/airbrake`](https://github.com/Sirupsen/logrus/blob/master/hooks/airbrake/airbrake.go)
- Send errors to an exception tracking service compatible with the Airbrake API.
- Uses [`airbrake-go`](https://github.com/tobi/airbrake-go) behind the scenes.
-
-* [`github.com/Sirupsen/logrus/hooks/papertrail`](https://github.com/Sirupsen/logrus/blob/master/hooks/papertrail/papertrail.go)
- Send errors to the Papertrail hosted logging service via UDP.
-
-* [`github.com/Sirupsen/logrus/hooks/syslog`](https://github.com/Sirupsen/logrus/blob/master/hooks/syslog/syslog.go)
- Send errors to remote syslog server.
- Uses standard library `log/syslog` behind the scenes.
-
-* [`github.com/nubo/hiprus`](https://github.com/nubo/hiprus)
- Send errors to a channel in hipchat.
-
-#### Level logging
-
-Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic.
-
-```go
-log.Debug("Useful debugging information.")
-log.Info("Something noteworthy happened!")
-log.Warn("You should probably take a look at this.")
-log.Error("Something failed but I'm not quitting.")
-// Calls os.Exit(1) after logging
-log.Fatal("Bye.")
-// Calls panic() after logging
-log.Panic("I'm bailing.")
-```
-
-You can set the logging level on a `Logger`, then it will only log entries with
-that severity or anything above it:
-
-```go
-// Will log anything that is info or above (warn, error, fatal, panic). Default.
-log.SetLevel(log.InfoLevel)
-```
-
-It may be useful to set `log.Level = logrus.DebugLevel` in a debug or verbose
-environment if your application has that.
-
-#### Entries
-
-Besides the fields added with `WithField` or `WithFields` some fields are
-automatically added to all logging events:
-
-1. `time`. The timestamp when the entry was created.
-2. `msg`. The logging message passed to `{Info,Warn,Error,Fatal,Panic}` after
- the `AddFields` call. E.g. `Failed to send event.`
-3. `level`. The logging level. E.g. `info`.
-
-#### Environments
-
-Logrus has no notion of environment.
-
-If you wish for hooks and formatters to only be used in specific environments,
-you should handle that yourself. For example, if your application has a global
-variable `Environment`, which is a string representation of the environment you
-could do:
-
-```go
-import (
- log "github.com/Sirupsen/logrus"
-)
-
-init() {
- // do something here to set environment depending on an environment variable
- // or command-line flag
- if Environment == "production" {
- log.SetFormatter(logrus.JSONFormatter)
- } else {
- // The TextFormatter is default, you don't actually have to do this.
- log.SetFormatter(logrus.TextFormatter)
- }
-}
-```
-
-This configuration is how `logrus` was intended to be used, but JSON in
-production is mostly only useful if you do log aggregation with tools like
-Splunk or Logstash.
-
-#### Formatters
-
-The built-in logging formatters are:
-
-* `logrus.TextFormatter`. Logs the event in colors if stdout is a tty, otherwise
- without colors.
- * *Note:* to force colored output when there is no TTY, set the `ForceColors`
- field to `true`. To force no colored output even if there is a TTY set the
- `DisableColors` field to `true`
-* `logrus.JSONFormatter`. Logs fields as JSON.
-
-Third party logging formatters:
-
-* [`zalgo`](https://github.com/aybabtme/logzalgo): invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
-
-You can define your formatter by implementing the `Formatter` interface,
-requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a
-`Fields` type (`map[string]interface{}`) with all your fields as well as the
-default ones (see Entries section above):
-
-```go
-type MyJSONFormatter struct {
-}
-
-log.SetFormatter(new(MyJSONFormatter))
-
-func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
- // Note this doesn't include Time, Level and Message which are available on
- // the Entry. Consult `godoc` on information about those fields or read the
- // source of the official loggers.
- serialized, err := json.Marshal(entry.Data)
- if err != nil {
- return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
- }
- return append(serialized, '\n'), nil
-}
-```
-
-#### Rotation
-
-Log rotation is not provided with Logrus. Log rotation should be done by an
-external program (like `logrotated(8)`) that can compress and delete old log
-entries. It should not be a feature of the application-level logger.
-
-
-[godoc]: https://godoc.org/github.com/Sirupsen/logrus
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/entry.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/entry.go
deleted file mode 100644
index e164eecb5f..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/entry.go
+++ /dev/null
@@ -1,248 +0,0 @@
-package logrus
-
-import (
- "bytes"
- "fmt"
- "io"
- "os"
- "time"
-)
-
-// An entry is the final or intermediate Logrus logging entry. It contains all
-// the fields passed with WithField{,s}. It's finally logged when Debug, Info,
-// Warn, Error, Fatal or Panic is called on it. These objects can be reused and
-// passed around as much as you wish to avoid field duplication.
-type Entry struct {
- Logger *Logger
-
- // Contains all the fields set by the user.
- Data Fields
-
- // Time at which the log entry was created
- Time time.Time
-
- // Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
- Level Level
-
- // Message passed to Debug, Info, Warn, Error, Fatal or Panic
- Message string
-}
-
-func NewEntry(logger *Logger) *Entry {
- return &Entry{
- Logger: logger,
- // Default is three fields, give a little extra room
- Data: make(Fields, 5),
- }
-}
-
-// Returns a reader for the entry, which is a proxy to the formatter.
-func (entry *Entry) Reader() (*bytes.Buffer, error) {
- serialized, err := entry.Logger.Formatter.Format(entry)
- return bytes.NewBuffer(serialized), err
-}
-
-// Returns the string representation from the reader and ultimately the
-// formatter.
-func (entry *Entry) String() (string, error) {
- reader, err := entry.Reader()
- if err != nil {
- return "", err
- }
-
- return reader.String(), err
-}
-
-// Add a single field to the Entry.
-func (entry *Entry) WithField(key string, value interface{}) *Entry {
- return entry.WithFields(Fields{key: value})
-}
-
-// Add a map of fields to the Entry.
-func (entry *Entry) WithFields(fields Fields) *Entry {
- data := Fields{}
- for k, v := range entry.Data {
- data[k] = v
- }
- for k, v := range fields {
- data[k] = v
- }
- return &Entry{Logger: entry.Logger, Data: data}
-}
-
-func (entry *Entry) log(level Level, msg string) {
- entry.Time = time.Now()
- entry.Level = level
- entry.Message = msg
-
- if err := entry.Logger.Hooks.Fire(level, entry); err != nil {
- entry.Logger.mu.Lock()
- fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
- entry.Logger.mu.Unlock()
- }
-
- reader, err := entry.Reader()
- if err != nil {
- entry.Logger.mu.Lock()
- fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
- entry.Logger.mu.Unlock()
- }
-
- entry.Logger.mu.Lock()
- defer entry.Logger.mu.Unlock()
-
- _, err = io.Copy(entry.Logger.Out, reader)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
- }
-
- // To avoid Entry#log() returning a value that only would make sense for
- // panic() to use in Entry#Panic(), we avoid the allocation by checking
- // directly here.
- if level <= PanicLevel {
- panic(entry)
- }
-}
-
-func (entry *Entry) Debug(args ...interface{}) {
- if entry.Logger.Level >= DebugLevel {
- entry.log(DebugLevel, fmt.Sprint(args...))
- }
-}
-
-func (entry *Entry) Print(args ...interface{}) {
- entry.Info(args...)
-}
-
-func (entry *Entry) Info(args ...interface{}) {
- if entry.Logger.Level >= InfoLevel {
- entry.log(InfoLevel, fmt.Sprint(args...))
- }
-}
-
-func (entry *Entry) Warn(args ...interface{}) {
- if entry.Logger.Level >= WarnLevel {
- entry.log(WarnLevel, fmt.Sprint(args...))
- }
-}
-
-func (entry *Entry) Error(args ...interface{}) {
- if entry.Logger.Level >= ErrorLevel {
- entry.log(ErrorLevel, fmt.Sprint(args...))
- }
-}
-
-func (entry *Entry) Fatal(args ...interface{}) {
- if entry.Logger.Level >= FatalLevel {
- entry.log(FatalLevel, fmt.Sprint(args...))
- }
- os.Exit(1)
-}
-
-func (entry *Entry) Panic(args ...interface{}) {
- if entry.Logger.Level >= PanicLevel {
- entry.log(PanicLevel, fmt.Sprint(args...))
- }
- panic(fmt.Sprint(args...))
-}
-
-// Entry Printf family functions
-
-func (entry *Entry) Debugf(format string, args ...interface{}) {
- if entry.Logger.Level >= DebugLevel {
- entry.Debug(fmt.Sprintf(format, args...))
- }
-}
-
-func (entry *Entry) Infof(format string, args ...interface{}) {
- if entry.Logger.Level >= InfoLevel {
- entry.Info(fmt.Sprintf(format, args...))
- }
-}
-
-func (entry *Entry) Printf(format string, args ...interface{}) {
- entry.Infof(format, args...)
-}
-
-func (entry *Entry) Warnf(format string, args ...interface{}) {
- if entry.Logger.Level >= WarnLevel {
- entry.Warn(fmt.Sprintf(format, args...))
- }
-}
-
-func (entry *Entry) Warningf(format string, args ...interface{}) {
- entry.Warnf(format, args...)
-}
-
-func (entry *Entry) Errorf(format string, args ...interface{}) {
- if entry.Logger.Level >= ErrorLevel {
- entry.Error(fmt.Sprintf(format, args...))
- }
-}
-
-func (entry *Entry) Fatalf(format string, args ...interface{}) {
- if entry.Logger.Level >= FatalLevel {
- entry.Fatal(fmt.Sprintf(format, args...))
- }
-}
-
-func (entry *Entry) Panicf(format string, args ...interface{}) {
- if entry.Logger.Level >= PanicLevel {
- entry.Panic(fmt.Sprintf(format, args...))
- }
-}
-
-// Entry Println family functions
-
-func (entry *Entry) Debugln(args ...interface{}) {
- if entry.Logger.Level >= DebugLevel {
- entry.Debug(entry.sprintlnn(args...))
- }
-}
-
-func (entry *Entry) Infoln(args ...interface{}) {
- if entry.Logger.Level >= InfoLevel {
- entry.Info(entry.sprintlnn(args...))
- }
-}
-
-func (entry *Entry) Println(args ...interface{}) {
- entry.Infoln(args...)
-}
-
-func (entry *Entry) Warnln(args ...interface{}) {
- if entry.Logger.Level >= WarnLevel {
- entry.Warn(entry.sprintlnn(args...))
- }
-}
-
-func (entry *Entry) Warningln(args ...interface{}) {
- entry.Warnln(args...)
-}
-
-func (entry *Entry) Errorln(args ...interface{}) {
- if entry.Logger.Level >= ErrorLevel {
- entry.Error(entry.sprintlnn(args...))
- }
-}
-
-func (entry *Entry) Fatalln(args ...interface{}) {
- if entry.Logger.Level >= FatalLevel {
- entry.Fatal(entry.sprintlnn(args...))
- }
-}
-
-func (entry *Entry) Panicln(args ...interface{}) {
- if entry.Logger.Level >= PanicLevel {
- entry.Panic(entry.sprintlnn(args...))
- }
-}
-
-// Sprintlnn => Sprint no newline. This is to get the behavior of how
-// fmt.Sprintln where spaces are always added between operands, regardless of
-// their type. Instead of vendoring the Sprintln implementation to spare a
-// string allocation, we do the simplest thing.
-func (entry *Entry) sprintlnn(args ...interface{}) string {
- msg := fmt.Sprintln(args...)
- return msg[:len(msg)-1]
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/entry_test.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/entry_test.go
deleted file mode 100644
index 98717df490..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/entry_test.go
+++ /dev/null
@@ -1,53 +0,0 @@
-package logrus
-
-import (
- "bytes"
- "fmt"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestEntryPanicln(t *testing.T) {
- errBoom := fmt.Errorf("boom time")
-
- defer func() {
- p := recover()
- assert.NotNil(t, p)
-
- switch pVal := p.(type) {
- case *Entry:
- assert.Equal(t, "kaboom", pVal.Message)
- assert.Equal(t, errBoom, pVal.Data["err"])
- default:
- t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
- }
- }()
-
- logger := New()
- logger.Out = &bytes.Buffer{}
- entry := NewEntry(logger)
- entry.WithField("err", errBoom).Panicln("kaboom")
-}
-
-func TestEntryPanicf(t *testing.T) {
- errBoom := fmt.Errorf("boom again")
-
- defer func() {
- p := recover()
- assert.NotNil(t, p)
-
- switch pVal := p.(type) {
- case *Entry:
- assert.Equal(t, "kaboom true", pVal.Message)
- assert.Equal(t, errBoom, pVal.Data["err"])
- default:
- t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
- }
- }()
-
- logger := New()
- logger.Out = &bytes.Buffer{}
- entry := NewEntry(logger)
- entry.WithField("err", errBoom).Panicf("kaboom %v", true)
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/examples/basic/basic.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/examples/basic/basic.go
deleted file mode 100644
index a62ba45de5..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/examples/basic/basic.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package main
-
-import (
- "github.com/Sirupsen/logrus"
-)
-
-var log = logrus.New()
-
-func init() {
- log.Formatter = new(logrus.JSONFormatter)
- log.Formatter = new(logrus.TextFormatter) // default
-}
-
-func main() {
- defer func() {
- err := recover()
- if err != nil {
- log.WithFields(logrus.Fields{
- "omg": true,
- "err": err,
- "number": 100,
- }).Fatal("The ice breaks!")
- }
- }()
-
- log.WithFields(logrus.Fields{
- "animal": "walrus",
- "size": 10,
- }).Info("A group of walrus emerges from the ocean")
-
- log.WithFields(logrus.Fields{
- "omg": true,
- "number": 122,
- }).Warn("The group's number increased tremendously!")
-
- log.WithFields(logrus.Fields{
- "animal": "orca",
- "size": 9009,
- }).Panic("It's over 9000!")
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/examples/hook/hook.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/examples/hook/hook.go
deleted file mode 100644
index 42e7a4c982..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/examples/hook/hook.go
+++ /dev/null
@@ -1,35 +0,0 @@
-package main
-
-import (
- "github.com/Sirupsen/logrus"
- "github.com/Sirupsen/logrus/hooks/airbrake"
- "github.com/tobi/airbrake-go"
-)
-
-var log = logrus.New()
-
-func init() {
- log.Formatter = new(logrus.TextFormatter) // default
- log.Hooks.Add(new(logrus_airbrake.AirbrakeHook))
-}
-
-func main() {
- airbrake.Endpoint = "https://exceptions.whatever.com/notifier_api/v2/notices.xml"
- airbrake.ApiKey = "whatever"
- airbrake.Environment = "production"
-
- log.WithFields(logrus.Fields{
- "animal": "walrus",
- "size": 10,
- }).Info("A group of walrus emerges from the ocean")
-
- log.WithFields(logrus.Fields{
- "omg": true,
- "number": 122,
- }).Warn("The group's number increased tremendously!")
-
- log.WithFields(logrus.Fields{
- "omg": true,
- "number": 100,
- }).Fatal("The ice breaks!")
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/exported.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/exported.go
deleted file mode 100644
index d087124481..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/exported.go
+++ /dev/null
@@ -1,182 +0,0 @@
-package logrus
-
-import (
- "io"
-)
-
-var (
- // std is the name of the standard logger in stdlib `log`
- std = New()
-)
-
-// SetOutput sets the standard logger output.
-func SetOutput(out io.Writer) {
- std.mu.Lock()
- defer std.mu.Unlock()
- std.Out = out
-}
-
-// SetFormatter sets the standard logger formatter.
-func SetFormatter(formatter Formatter) {
- std.mu.Lock()
- defer std.mu.Unlock()
- std.Formatter = formatter
-}
-
-// SetLevel sets the standard logger level.
-func SetLevel(level Level) {
- std.mu.Lock()
- defer std.mu.Unlock()
- std.Level = level
-}
-
-// GetLevel returns the standard logger level.
-func GetLevel() Level {
- return std.Level
-}
-
-// AddHook adds a hook to the standard logger hooks.
-func AddHook(hook Hook) {
- std.mu.Lock()
- defer std.mu.Unlock()
- std.Hooks.Add(hook)
-}
-
-// WithField creates an entry from the standard logger and adds a field to
-// it. If you want multiple fields, use `WithFields`.
-//
-// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
-// or Panic on the Entry it returns.
-func WithField(key string, value interface{}) *Entry {
- return std.WithField(key, value)
-}
-
-// WithFields creates an entry from the standard logger and adds multiple
-// fields to it. This is simply a helper for `WithField`, invoking it
-// once for each field.
-//
-// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
-// or Panic on the Entry it returns.
-func WithFields(fields Fields) *Entry {
- return std.WithFields(fields)
-}
-
-// Debug logs a message at level Debug on the standard logger.
-func Debug(args ...interface{}) {
- std.Debug(args...)
-}
-
-// Print logs a message at level Info on the standard logger.
-func Print(args ...interface{}) {
- std.Print(args...)
-}
-
-// Info logs a message at level Info on the standard logger.
-func Info(args ...interface{}) {
- std.Info(args...)
-}
-
-// Warn logs a message at level Warn on the standard logger.
-func Warn(args ...interface{}) {
- std.Warn(args...)
-}
-
-// Warning logs a message at level Warn on the standard logger.
-func Warning(args ...interface{}) {
- std.Warning(args...)
-}
-
-// Error logs a message at level Error on the standard logger.
-func Error(args ...interface{}) {
- std.Error(args...)
-}
-
-// Panic logs a message at level Panic on the standard logger.
-func Panic(args ...interface{}) {
- std.Panic(args...)
-}
-
-// Fatal logs a message at level Fatal on the standard logger.
-func Fatal(args ...interface{}) {
- std.Fatal(args...)
-}
-
-// Debugf logs a message at level Debug on the standard logger.
-func Debugf(format string, args ...interface{}) {
- std.Debugf(format, args...)
-}
-
-// Printf logs a message at level Info on the standard logger.
-func Printf(format string, args ...interface{}) {
- std.Printf(format, args...)
-}
-
-// Infof logs a message at level Info on the standard logger.
-func Infof(format string, args ...interface{}) {
- std.Infof(format, args...)
-}
-
-// Warnf logs a message at level Warn on the standard logger.
-func Warnf(format string, args ...interface{}) {
- std.Warnf(format, args...)
-}
-
-// Warningf logs a message at level Warn on the standard logger.
-func Warningf(format string, args ...interface{}) {
- std.Warningf(format, args...)
-}
-
-// Errorf logs a message at level Error on the standard logger.
-func Errorf(format string, args ...interface{}) {
- std.Errorf(format, args...)
-}
-
-// Panicf logs a message at level Panic on the standard logger.
-func Panicf(format string, args ...interface{}) {
- std.Panicf(format, args...)
-}
-
-// Fatalf logs a message at level Fatal on the standard logger.
-func Fatalf(format string, args ...interface{}) {
- std.Fatalf(format, args...)
-}
-
-// Debugln logs a message at level Debug on the standard logger.
-func Debugln(args ...interface{}) {
- std.Debugln(args...)
-}
-
-// Println logs a message at level Info on the standard logger.
-func Println(args ...interface{}) {
- std.Println(args...)
-}
-
-// Infoln logs a message at level Info on the standard logger.
-func Infoln(args ...interface{}) {
- std.Infoln(args...)
-}
-
-// Warnln logs a message at level Warn on the standard logger.
-func Warnln(args ...interface{}) {
- std.Warnln(args...)
-}
-
-// Warningln logs a message at level Warn on the standard logger.
-func Warningln(args ...interface{}) {
- std.Warningln(args...)
-}
-
-// Errorln logs a message at level Error on the standard logger.
-func Errorln(args ...interface{}) {
- std.Errorln(args...)
-}
-
-// Panicln logs a message at level Panic on the standard logger.
-func Panicln(args ...interface{}) {
- std.Panicln(args...)
-}
-
-// Fatalln logs a message at level Fatal on the standard logger.
-func Fatalln(args ...interface{}) {
- std.Fatalln(args...)
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/formatter.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/formatter.go
deleted file mode 100644
index 74c49a0e0e..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/formatter.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package logrus
-
-// The Formatter interface is used to implement a custom Formatter. It takes an
-// `Entry`. It exposes all the fields, including the default ones:
-//
-// * `entry.Data["msg"]`. The message passed from Info, Warn, Error ..
-// * `entry.Data["time"]`. The timestamp.
-// * `entry.Data["level"]. The level the entry was logged at.
-//
-// Any additional fields added with `WithField` or `WithFields` are also in
-// `entry.Data`. Format is expected to return an array of bytes which are then
-// logged to `logger.Out`.
-type Formatter interface {
- Format(*Entry) ([]byte, error)
-}
-
-// This is to not silently overwrite `time`, `msg` and `level` fields when
-// dumping it. If this code wasn't there doing:
-//
-// logrus.WithField("level", 1).Info("hello")
-//
-// Would just silently drop the user provided level. Instead with this code
-// it'll logged as:
-//
-// {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."}
-//
-// It's not exported because it's still using Data in an opinionated way. It's to
-// avoid code duplication between the two default formatters.
-func prefixFieldClashes(entry *Entry) {
- _, ok := entry.Data["time"]
- if ok {
- entry.Data["fields.time"] = entry.Data["time"]
- }
-
- _, ok = entry.Data["msg"]
- if ok {
- entry.Data["fields.msg"] = entry.Data["msg"]
- }
-
- _, ok = entry.Data["level"]
- if ok {
- entry.Data["fields.level"] = entry.Data["level"]
- }
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/formatter_bench_test.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/formatter_bench_test.go
deleted file mode 100644
index 77989da629..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/formatter_bench_test.go
+++ /dev/null
@@ -1,88 +0,0 @@
-package logrus
-
-import (
- "testing"
- "time"
-)
-
-// smallFields is a small size data set for benchmarking
-var smallFields = Fields{
- "foo": "bar",
- "baz": "qux",
- "one": "two",
- "three": "four",
-}
-
-// largeFields is a large size data set for benchmarking
-var largeFields = Fields{
- "foo": "bar",
- "baz": "qux",
- "one": "two",
- "three": "four",
- "five": "six",
- "seven": "eight",
- "nine": "ten",
- "eleven": "twelve",
- "thirteen": "fourteen",
- "fifteen": "sixteen",
- "seventeen": "eighteen",
- "nineteen": "twenty",
- "a": "b",
- "c": "d",
- "e": "f",
- "g": "h",
- "i": "j",
- "k": "l",
- "m": "n",
- "o": "p",
- "q": "r",
- "s": "t",
- "u": "v",
- "w": "x",
- "y": "z",
- "this": "will",
- "make": "thirty",
- "entries": "yeah",
-}
-
-func BenchmarkSmallTextFormatter(b *testing.B) {
- doBenchmark(b, &TextFormatter{DisableColors: true}, smallFields)
-}
-
-func BenchmarkLargeTextFormatter(b *testing.B) {
- doBenchmark(b, &TextFormatter{DisableColors: true}, largeFields)
-}
-
-func BenchmarkSmallColoredTextFormatter(b *testing.B) {
- doBenchmark(b, &TextFormatter{ForceColors: true}, smallFields)
-}
-
-func BenchmarkLargeColoredTextFormatter(b *testing.B) {
- doBenchmark(b, &TextFormatter{ForceColors: true}, largeFields)
-}
-
-func BenchmarkSmallJSONFormatter(b *testing.B) {
- doBenchmark(b, &JSONFormatter{}, smallFields)
-}
-
-func BenchmarkLargeJSONFormatter(b *testing.B) {
- doBenchmark(b, &JSONFormatter{}, largeFields)
-}
-
-func doBenchmark(b *testing.B, formatter Formatter, fields Fields) {
- entry := &Entry{
- Time: time.Time{},
- Level: InfoLevel,
- Message: "message",
- Data: fields,
- }
- var d []byte
- var err error
- for i := 0; i < b.N; i++ {
- d, err = formatter.Format(entry)
- if err != nil {
- b.Fatal(err)
- }
- b.SetBytes(int64(len(d)))
- }
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/hook_test.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/hook_test.go
deleted file mode 100644
index 13f34cb6f8..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/hook_test.go
+++ /dev/null
@@ -1,122 +0,0 @@
-package logrus
-
-import (
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-type TestHook struct {
- Fired bool
-}
-
-func (hook *TestHook) Fire(entry *Entry) error {
- hook.Fired = true
- return nil
-}
-
-func (hook *TestHook) Levels() []Level {
- return []Level{
- DebugLevel,
- InfoLevel,
- WarnLevel,
- ErrorLevel,
- FatalLevel,
- PanicLevel,
- }
-}
-
-func TestHookFires(t *testing.T) {
- hook := new(TestHook)
-
- LogAndAssertJSON(t, func(log *Logger) {
- log.Hooks.Add(hook)
- assert.Equal(t, hook.Fired, false)
-
- log.Print("test")
- }, func(fields Fields) {
- assert.Equal(t, hook.Fired, true)
- })
-}
-
-type ModifyHook struct {
-}
-
-func (hook *ModifyHook) Fire(entry *Entry) error {
- entry.Data["wow"] = "whale"
- return nil
-}
-
-func (hook *ModifyHook) Levels() []Level {
- return []Level{
- DebugLevel,
- InfoLevel,
- WarnLevel,
- ErrorLevel,
- FatalLevel,
- PanicLevel,
- }
-}
-
-func TestHookCanModifyEntry(t *testing.T) {
- hook := new(ModifyHook)
-
- LogAndAssertJSON(t, func(log *Logger) {
- log.Hooks.Add(hook)
- log.WithField("wow", "elephant").Print("test")
- }, func(fields Fields) {
- assert.Equal(t, fields["wow"], "whale")
- })
-}
-
-func TestCanFireMultipleHooks(t *testing.T) {
- hook1 := new(ModifyHook)
- hook2 := new(TestHook)
-
- LogAndAssertJSON(t, func(log *Logger) {
- log.Hooks.Add(hook1)
- log.Hooks.Add(hook2)
-
- log.WithField("wow", "elephant").Print("test")
- }, func(fields Fields) {
- assert.Equal(t, fields["wow"], "whale")
- assert.Equal(t, hook2.Fired, true)
- })
-}
-
-type ErrorHook struct {
- Fired bool
-}
-
-func (hook *ErrorHook) Fire(entry *Entry) error {
- hook.Fired = true
- return nil
-}
-
-func (hook *ErrorHook) Levels() []Level {
- return []Level{
- ErrorLevel,
- }
-}
-
-func TestErrorHookShouldntFireOnInfo(t *testing.T) {
- hook := new(ErrorHook)
-
- LogAndAssertJSON(t, func(log *Logger) {
- log.Hooks.Add(hook)
- log.Info("test")
- }, func(fields Fields) {
- assert.Equal(t, hook.Fired, false)
- })
-}
-
-func TestErrorHookShouldFireOnError(t *testing.T) {
- hook := new(ErrorHook)
-
- LogAndAssertJSON(t, func(log *Logger) {
- log.Hooks.Add(hook)
- log.Error("test")
- }, func(fields Fields) {
- assert.Equal(t, hook.Fired, true)
- })
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks.go
deleted file mode 100644
index 0da2b3653f..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks.go
+++ /dev/null
@@ -1,34 +0,0 @@
-package logrus
-
-// A hook to be fired when logging on the logging levels returned from
-// `Levels()` on your implementation of the interface. Note that this is not
-// fired in a goroutine or a channel with workers, you should handle such
-// functionality yourself if your call is non-blocking and you don't wish for
-// the logging calls for levels returned from `Levels()` to block.
-type Hook interface {
- Levels() []Level
- Fire(*Entry) error
-}
-
-// Internal type for storing the hooks on a logger instance.
-type levelHooks map[Level][]Hook
-
-// Add a hook to an instance of logger. This is called with
-// `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface.
-func (hooks levelHooks) Add(hook Hook) {
- for _, level := range hook.Levels() {
- hooks[level] = append(hooks[level], hook)
- }
-}
-
-// Fire all the hooks for the passed level. Used by `entry.log` to fire
-// appropriate hooks for a log entry.
-func (hooks levelHooks) Fire(level Level, entry *Entry) error {
- for _, hook := range hooks[level] {
- if err := hook.Fire(entry); err != nil {
- return err
- }
- }
-
- return nil
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/airbrake/airbrake.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/airbrake/airbrake.go
deleted file mode 100644
index 880d21ecdc..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/airbrake/airbrake.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package logrus_airbrake
-
-import (
- "github.com/Sirupsen/logrus"
- "github.com/tobi/airbrake-go"
-)
-
-// AirbrakeHook to send exceptions to an exception-tracking service compatible
-// with the Airbrake API. You must set:
-// * airbrake.Endpoint
-// * airbrake.ApiKey
-// * airbrake.Environment (only sends exceptions when set to "production")
-//
-// Before using this hook, to send an error. Entries that trigger an Error,
-// Fatal or Panic should now include an "error" field to send to Airbrake.
-type AirbrakeHook struct{}
-
-func (hook *AirbrakeHook) Fire(entry *logrus.Entry) error {
- if entry.Data["error"] == nil {
- entry.Logger.WithFields(logrus.Fields{
- "source": "airbrake",
- "endpoint": airbrake.Endpoint,
- }).Warn("Exceptions sent to Airbrake must have an 'error' key with the error")
- return nil
- }
-
- err, ok := entry.Data["error"].(error)
- if !ok {
- entry.Logger.WithFields(logrus.Fields{
- "source": "airbrake",
- "endpoint": airbrake.Endpoint,
- }).Warn("Exceptions sent to Airbrake must have an `error` key of type `error`")
- return nil
- }
-
- airErr := airbrake.Notify(err)
- if airErr != nil {
- entry.Logger.WithFields(logrus.Fields{
- "source": "airbrake",
- "endpoint": airbrake.Endpoint,
- "error": airErr,
- }).Warn("Failed to send error to Airbrake")
- }
-
- return nil
-}
-
-func (hook *AirbrakeHook) Levels() []logrus.Level {
- return []logrus.Level{
- logrus.ErrorLevel,
- logrus.FatalLevel,
- logrus.PanicLevel,
- }
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/README.md b/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/README.md
deleted file mode 100644
index ae61e9229a..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/README.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# Papertrail Hook for Logrus
-
-[Papertrail](https://papertrailapp.com) provides hosted log management. Once stored in Papertrail, you can [group](http://help.papertrailapp.com/kb/how-it-works/groups/) your logs on various dimensions, [search](http://help.papertrailapp.com/kb/how-it-works/search-syntax) them, and trigger [alerts](http://help.papertrailapp.com/kb/how-it-works/alerts).
-
-In most deployments, you'll want to send logs to Papertrail via their [remote_syslog](http://help.papertrailapp.com/kb/configuration/configuring-centralized-logging-from-text-log-files-in-unix/) daemon, which requires no application-specific configuration. This hook is intended for relatively low-volume logging, likely in managed cloud hosting deployments where installing `remote_syslog` is not possible.
-
-## Usage
-
-You can find your Papertrail UDP port on your [Papertrail account page](https://papertrailapp.com/account/destinations). Substitute it below for `YOUR_PAPERTRAIL_UDP_PORT`.
-
-For `YOUR_APP_NAME`, substitute a short string that will readily identify your application or service in the logs.
-
-```go
-import (
- "log/syslog"
- "github.com/Sirupsen/logrus"
- "github.com/Sirupsen/logrus/hooks/papertrail"
-)
-
-func main() {
- log := logrus.New()
- hook, err := logrus_papertrail.NewPapertrailHook("logs.papertrailapp.com", YOUR_PAPERTRAIL_UDP_PORT, YOUR_APP_NAME)
-
- if err == nil {
- log.Hooks.Add(hook)
- }
-}
-```
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/papertrail.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/papertrail.go
deleted file mode 100644
index 48e2feaeb5..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/papertrail.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package logrus_papertrail
-
-import (
- "fmt"
- "net"
- "os"
- "time"
-
- "github.com/Sirupsen/logrus"
-)
-
-const (
- format = "Jan 2 15:04:05"
-)
-
-// PapertrailHook to send logs to a logging service compatible with the Papertrail API.
-type PapertrailHook struct {
- Host string
- Port int
- AppName string
- UDPConn net.Conn
-}
-
-// NewPapertrailHook creates a hook to be added to an instance of logger.
-func NewPapertrailHook(host string, port int, appName string) (*PapertrailHook, error) {
- conn, err := net.Dial("udp", fmt.Sprintf("%s:%d", host, port))
- return &PapertrailHook{host, port, appName, conn}, err
-}
-
-// Fire is called when a log event is fired.
-func (hook *PapertrailHook) Fire(entry *logrus.Entry) error {
- date := time.Now().Format(format)
- payload := fmt.Sprintf("<22> %s %s: [%s] %s", date, hook.AppName, entry.Data["level"], entry.Message)
-
- bytesWritten, err := hook.UDPConn.Write([]byte(payload))
- if err != nil {
- fmt.Fprintf(os.Stderr, "Unable to send log line to Papertrail via UDP. Wrote %d bytes before error: %v", bytesWritten, err)
- return err
- }
-
- return nil
-}
-
-// Levels returns the available logging levels.
-func (hook *PapertrailHook) Levels() []logrus.Level {
- return []logrus.Level{
- logrus.PanicLevel,
- logrus.FatalLevel,
- logrus.ErrorLevel,
- logrus.WarnLevel,
- logrus.InfoLevel,
- logrus.DebugLevel,
- }
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/papertrail_test.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/papertrail_test.go
deleted file mode 100644
index 96318d0030..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/papertrail_test.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package logrus_papertrail
-
-import (
- "fmt"
- "testing"
-
- "github.com/Sirupsen/logrus"
- "github.com/stvp/go-udp-testing"
-)
-
-func TestWritingToUDP(t *testing.T) {
- port := 16661
- udp.SetAddr(fmt.Sprintf(":%d", port))
-
- hook, err := NewPapertrailHook("localhost", port, "test")
- if err != nil {
- t.Errorf("Unable to connect to local UDP server.")
- }
-
- log := logrus.New()
- log.Hooks.Add(hook)
-
- udp.ShouldReceive(t, "foo", func() {
- log.Info("foo")
- })
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/README.md b/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/README.md
deleted file mode 100644
index cd706bc1b1..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/README.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# Syslog Hooks for Logrus
-
-## Usage
-
-```go
-import (
- "log/syslog"
- "github.com/Sirupsen/logrus"
- "github.com/Sirupsen/logrus/hooks/syslog"
-)
-
-func main() {
- log := logrus.New()
- hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
-
- if err == nil {
- log.Hooks.Add(hook)
- }
-}
-```
\ No newline at end of file
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/syslog.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/syslog.go
deleted file mode 100644
index b6fa374628..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/syslog.go
+++ /dev/null
@@ -1,59 +0,0 @@
-package logrus_syslog
-
-import (
- "fmt"
- "github.com/Sirupsen/logrus"
- "log/syslog"
- "os"
-)
-
-// SyslogHook to send logs via syslog.
-type SyslogHook struct {
- Writer *syslog.Writer
- SyslogNetwork string
- SyslogRaddr string
-}
-
-// Creates a hook to be added to an instance of logger. This is called with
-// `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")`
-// `if err == nil { log.Hooks.Add(hook) }`
-func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) {
- w, err := syslog.Dial(network, raddr, priority, tag)
- return &SyslogHook{w, network, raddr}, err
-}
-
-func (hook *SyslogHook) Fire(entry *logrus.Entry) error {
- line, err := entry.String()
- if err != nil {
- fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err)
- return err
- }
-
- switch entry.Level {
- case logrus.PanicLevel:
- return hook.Writer.Crit(line)
- case logrus.FatalLevel:
- return hook.Writer.Crit(line)
- case logrus.ErrorLevel:
- return hook.Writer.Err(line)
- case logrus.WarnLevel:
- return hook.Writer.Warning(line)
- case logrus.InfoLevel:
- return hook.Writer.Info(line)
- case logrus.DebugLevel:
- return hook.Writer.Debug(line)
- default:
- return nil
- }
-}
-
-func (hook *SyslogHook) Levels() []logrus.Level {
- return []logrus.Level{
- logrus.PanicLevel,
- logrus.FatalLevel,
- logrus.ErrorLevel,
- logrus.WarnLevel,
- logrus.InfoLevel,
- logrus.DebugLevel,
- }
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/syslog_test.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/syslog_test.go
deleted file mode 100644
index 42762dc10d..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/syslog_test.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package logrus_syslog
-
-import (
- "github.com/Sirupsen/logrus"
- "log/syslog"
- "testing"
-)
-
-func TestLocalhostAddAndPrint(t *testing.T) {
- log := logrus.New()
- hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
-
- if err != nil {
- t.Errorf("Unable to connect to local syslog.")
- }
-
- log.Hooks.Add(hook)
-
- for _, level := range hook.Levels() {
- if len(log.Hooks[level]) != 1 {
- t.Errorf("SyslogHook was not added. The length of log.Hooks[%v]: %v", level, len(log.Hooks[level]))
- }
- }
-
- log.Info("Congratulations!")
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/json_formatter.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/json_formatter.go
deleted file mode 100644
index 9d11b642d4..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/json_formatter.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package logrus
-
-import (
- "encoding/json"
- "fmt"
- "time"
-)
-
-type JSONFormatter struct{}
-
-func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
- prefixFieldClashes(entry)
- entry.Data["time"] = entry.Time.Format(time.RFC3339)
- entry.Data["msg"] = entry.Message
- entry.Data["level"] = entry.Level.String()
-
- serialized, err := json.Marshal(entry.Data)
- if err != nil {
- return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
- }
- return append(serialized, '\n'), nil
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/logger.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/logger.go
deleted file mode 100644
index 7374fe365d..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/logger.go
+++ /dev/null
@@ -1,161 +0,0 @@
-package logrus
-
-import (
- "io"
- "os"
- "sync"
-)
-
-type Logger struct {
- // The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
- // file, or leave it default which is `os.Stdout`. You can also set this to
- // something more adventorous, such as logging to Kafka.
- Out io.Writer
- // Hooks for the logger instance. These allow firing events based on logging
- // levels and log entries. For example, to send errors to an error tracking
- // service, log to StatsD or dump the core on fatal errors.
- Hooks levelHooks
- // All log entries pass through the formatter before logged to Out. The
- // included formatters are `TextFormatter` and `JSONFormatter` for which
- // TextFormatter is the default. In development (when a TTY is attached) it
- // logs with colors, but to a file it wouldn't. You can easily implement your
- // own that implements the `Formatter` interface, see the `README` or included
- // formatters for examples.
- Formatter Formatter
- // The logging level the logger should log at. This is typically (and defaults
- // to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
- // logged. `logrus.Debug` is useful in
- Level Level
- // Used to sync writing to the log.
- mu sync.Mutex
-}
-
-// Creates a new logger. Configuration should be set by changing `Formatter`,
-// `Out` and `Hooks` directly on the default logger instance. You can also just
-// instantiate your own:
-//
-// var log = &Logger{
-// Out: os.Stderr,
-// Formatter: new(JSONFormatter),
-// Hooks: make(levelHooks),
-// Level: logrus.Debug,
-// }
-//
-// It's recommended to make this a global instance called `log`.
-func New() *Logger {
- return &Logger{
- Out: os.Stdout,
- Formatter: new(TextFormatter),
- Hooks: make(levelHooks),
- Level: InfoLevel,
- }
-}
-
-// Adds a field to the log entry, note that you it doesn't log until you call
-// Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry.
-// Ff you want multiple fields, use `WithFields`.
-func (logger *Logger) WithField(key string, value interface{}) *Entry {
- return NewEntry(logger).WithField(key, value)
-}
-
-// Adds a struct of fields to the log entry. All it does is call `WithField` for
-// each `Field`.
-func (logger *Logger) WithFields(fields Fields) *Entry {
- return NewEntry(logger).WithFields(fields)
-}
-
-func (logger *Logger) Debugf(format string, args ...interface{}) {
- NewEntry(logger).Debugf(format, args...)
-}
-
-func (logger *Logger) Infof(format string, args ...interface{}) {
- NewEntry(logger).Infof(format, args...)
-}
-
-func (logger *Logger) Printf(format string, args ...interface{}) {
- NewEntry(logger).Printf(format, args...)
-}
-
-func (logger *Logger) Warnf(format string, args ...interface{}) {
- NewEntry(logger).Warnf(format, args...)
-}
-
-func (logger *Logger) Warningf(format string, args ...interface{}) {
- NewEntry(logger).Warnf(format, args...)
-}
-
-func (logger *Logger) Errorf(format string, args ...interface{}) {
- NewEntry(logger).Errorf(format, args...)
-}
-
-func (logger *Logger) Fatalf(format string, args ...interface{}) {
- NewEntry(logger).Fatalf(format, args...)
-}
-
-func (logger *Logger) Panicf(format string, args ...interface{}) {
- NewEntry(logger).Panicf(format, args...)
-}
-
-func (logger *Logger) Debug(args ...interface{}) {
- NewEntry(logger).Debug(args...)
-}
-
-func (logger *Logger) Info(args ...interface{}) {
- NewEntry(logger).Info(args...)
-}
-
-func (logger *Logger) Print(args ...interface{}) {
- NewEntry(logger).Info(args...)
-}
-
-func (logger *Logger) Warn(args ...interface{}) {
- NewEntry(logger).Warn(args...)
-}
-
-func (logger *Logger) Warning(args ...interface{}) {
- NewEntry(logger).Warn(args...)
-}
-
-func (logger *Logger) Error(args ...interface{}) {
- NewEntry(logger).Error(args...)
-}
-
-func (logger *Logger) Fatal(args ...interface{}) {
- NewEntry(logger).Fatal(args...)
-}
-
-func (logger *Logger) Panic(args ...interface{}) {
- NewEntry(logger).Panic(args...)
-}
-
-func (logger *Logger) Debugln(args ...interface{}) {
- NewEntry(logger).Debugln(args...)
-}
-
-func (logger *Logger) Infoln(args ...interface{}) {
- NewEntry(logger).Infoln(args...)
-}
-
-func (logger *Logger) Println(args ...interface{}) {
- NewEntry(logger).Println(args...)
-}
-
-func (logger *Logger) Warnln(args ...interface{}) {
- NewEntry(logger).Warnln(args...)
-}
-
-func (logger *Logger) Warningln(args ...interface{}) {
- NewEntry(logger).Warnln(args...)
-}
-
-func (logger *Logger) Errorln(args ...interface{}) {
- NewEntry(logger).Errorln(args...)
-}
-
-func (logger *Logger) Fatalln(args ...interface{}) {
- NewEntry(logger).Fatalln(args...)
-}
-
-func (logger *Logger) Panicln(args ...interface{}) {
- NewEntry(logger).Panicln(args...)
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/logrus.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/logrus.go
deleted file mode 100644
index 43ee12e90e..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/logrus.go
+++ /dev/null
@@ -1,94 +0,0 @@
-package logrus
-
-import (
- "fmt"
- "log"
-)
-
-// Fields type, used to pass to `WithFields`.
-type Fields map[string]interface{}
-
-// Level type
-type Level uint8
-
-// Convert the Level to a string. E.g. PanicLevel becomes "panic".
-func (level Level) String() string {
- switch level {
- case DebugLevel:
- return "debug"
- case InfoLevel:
- return "info"
- case WarnLevel:
- return "warning"
- case ErrorLevel:
- return "error"
- case FatalLevel:
- return "fatal"
- case PanicLevel:
- return "panic"
- }
-
- return "unknown"
-}
-
-// ParseLevel takes a string level and returns the Logrus log level constant.
-func ParseLevel(lvl string) (Level, error) {
- switch lvl {
- case "panic":
- return PanicLevel, nil
- case "fatal":
- return FatalLevel, nil
- case "error":
- return ErrorLevel, nil
- case "warn", "warning":
- return WarnLevel, nil
- case "info":
- return InfoLevel, nil
- case "debug":
- return DebugLevel, nil
- }
-
- var l Level
- return l, fmt.Errorf("not a valid logrus Level: %q", lvl)
-}
-
-// These are the different logging levels. You can set the logging level to log
-// on your instance of logger, obtained with `logrus.New()`.
-const (
- // PanicLevel level, highest level of severity. Logs and then calls panic with the
- // message passed to Debug, Info, ...
- PanicLevel Level = iota
- // FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the
- // logging level is set to Panic.
- FatalLevel
- // ErrorLevel level. Logs. Used for errors that should definitely be noted.
- // Commonly used for hooks to send errors to an error tracking service.
- ErrorLevel
- // WarnLevel level. Non-critical entries that deserve eyes.
- WarnLevel
- // InfoLevel level. General operational entries about what's going on inside the
- // application.
- InfoLevel
- // DebugLevel level. Usually only enabled when debugging. Very verbose logging.
- DebugLevel
-)
-
-// Won't compile if StdLogger can't be realized by a log.Logger
-var _ StdLogger = &log.Logger{}
-
-// StdLogger is what your logrus-enabled library should take, that way
-// it'll accept a stdlib logger and a logrus logger. There's no standard
-// interface, this is the closest we get, unfortunately.
-type StdLogger interface {
- Print(...interface{})
- Printf(string, ...interface{})
- Println(...interface{})
-
- Fatal(...interface{})
- Fatalf(string, ...interface{})
- Fatalln(...interface{})
-
- Panic(...interface{})
- Panicf(string, ...interface{})
- Panicln(...interface{})
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/logrus_test.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/logrus_test.go
deleted file mode 100644
index 15157d172d..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/logrus_test.go
+++ /dev/null
@@ -1,247 +0,0 @@
-package logrus
-
-import (
- "bytes"
- "encoding/json"
- "strconv"
- "strings"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func LogAndAssertJSON(t *testing.T, log func(*Logger), assertions func(fields Fields)) {
- var buffer bytes.Buffer
- var fields Fields
-
- logger := New()
- logger.Out = &buffer
- logger.Formatter = new(JSONFormatter)
-
- log(logger)
-
- err := json.Unmarshal(buffer.Bytes(), &fields)
- assert.Nil(t, err)
-
- assertions(fields)
-}
-
-func LogAndAssertText(t *testing.T, log func(*Logger), assertions func(fields map[string]string)) {
- var buffer bytes.Buffer
-
- logger := New()
- logger.Out = &buffer
- logger.Formatter = &TextFormatter{
- DisableColors: true,
- }
-
- log(logger)
-
- fields := make(map[string]string)
- for _, kv := range strings.Split(buffer.String(), " ") {
- if !strings.Contains(kv, "=") {
- continue
- }
- kvArr := strings.Split(kv, "=")
- key := strings.TrimSpace(kvArr[0])
- val, err := strconv.Unquote(kvArr[1])
- assert.NoError(t, err)
- fields[key] = val
- }
- assertions(fields)
-}
-
-func TestPrint(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.Print("test")
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "test")
- assert.Equal(t, fields["level"], "info")
- })
-}
-
-func TestInfo(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.Info("test")
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "test")
- assert.Equal(t, fields["level"], "info")
- })
-}
-
-func TestWarn(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.Warn("test")
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "test")
- assert.Equal(t, fields["level"], "warning")
- })
-}
-
-func TestInfolnShouldAddSpacesBetweenStrings(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.Infoln("test", "test")
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "test test")
- })
-}
-
-func TestInfolnShouldAddSpacesBetweenStringAndNonstring(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.Infoln("test", 10)
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "test 10")
- })
-}
-
-func TestInfolnShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.Infoln(10, 10)
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "10 10")
- })
-}
-
-func TestInfoShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.Infoln(10, 10)
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "10 10")
- })
-}
-
-func TestInfoShouldNotAddSpacesBetweenStringAndNonstring(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.Info("test", 10)
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "test10")
- })
-}
-
-func TestInfoShouldNotAddSpacesBetweenStrings(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.Info("test", "test")
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "testtest")
- })
-}
-
-func TestWithFieldsShouldAllowAssignments(t *testing.T) {
- var buffer bytes.Buffer
- var fields Fields
-
- logger := New()
- logger.Out = &buffer
- logger.Formatter = new(JSONFormatter)
-
- localLog := logger.WithFields(Fields{
- "key1": "value1",
- })
-
- localLog.WithField("key2", "value2").Info("test")
- err := json.Unmarshal(buffer.Bytes(), &fields)
- assert.Nil(t, err)
-
- assert.Equal(t, "value2", fields["key2"])
- assert.Equal(t, "value1", fields["key1"])
-
- buffer = bytes.Buffer{}
- fields = Fields{}
- localLog.Info("test")
- err = json.Unmarshal(buffer.Bytes(), &fields)
- assert.Nil(t, err)
-
- _, ok := fields["key2"]
- assert.Equal(t, false, ok)
- assert.Equal(t, "value1", fields["key1"])
-}
-
-func TestUserSuppliedFieldDoesNotOverwriteDefaults(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.WithField("msg", "hello").Info("test")
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "test")
- })
-}
-
-func TestUserSuppliedMsgFieldHasPrefix(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.WithField("msg", "hello").Info("test")
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "test")
- assert.Equal(t, fields["fields.msg"], "hello")
- })
-}
-
-func TestUserSuppliedTimeFieldHasPrefix(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.WithField("time", "hello").Info("test")
- }, func(fields Fields) {
- assert.Equal(t, fields["fields.time"], "hello")
- })
-}
-
-func TestUserSuppliedLevelFieldHasPrefix(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.WithField("level", 1).Info("test")
- }, func(fields Fields) {
- assert.Equal(t, fields["level"], "info")
- assert.Equal(t, fields["fields.level"], 1)
- })
-}
-
-func TestDefaultFieldsAreNotPrefixed(t *testing.T) {
- LogAndAssertText(t, func(log *Logger) {
- ll := log.WithField("herp", "derp")
- ll.Info("hello")
- ll.Info("bye")
- }, func(fields map[string]string) {
- for _, fieldName := range []string{"fields.level", "fields.time", "fields.msg"} {
- if _, ok := fields[fieldName]; ok {
- t.Fatalf("should not have prefixed %q: %v", fieldName, fields)
- }
- }
- })
-}
-
-func TestConvertLevelToString(t *testing.T) {
- assert.Equal(t, "debug", DebugLevel.String())
- assert.Equal(t, "info", InfoLevel.String())
- assert.Equal(t, "warning", WarnLevel.String())
- assert.Equal(t, "error", ErrorLevel.String())
- assert.Equal(t, "fatal", FatalLevel.String())
- assert.Equal(t, "panic", PanicLevel.String())
-}
-
-func TestParseLevel(t *testing.T) {
- l, err := ParseLevel("panic")
- assert.Nil(t, err)
- assert.Equal(t, PanicLevel, l)
-
- l, err = ParseLevel("fatal")
- assert.Nil(t, err)
- assert.Equal(t, FatalLevel, l)
-
- l, err = ParseLevel("error")
- assert.Nil(t, err)
- assert.Equal(t, ErrorLevel, l)
-
- l, err = ParseLevel("warn")
- assert.Nil(t, err)
- assert.Equal(t, WarnLevel, l)
-
- l, err = ParseLevel("warning")
- assert.Nil(t, err)
- assert.Equal(t, WarnLevel, l)
-
- l, err = ParseLevel("info")
- assert.Nil(t, err)
- assert.Equal(t, InfoLevel, l)
-
- l, err = ParseLevel("debug")
- assert.Nil(t, err)
- assert.Equal(t, DebugLevel, l)
-
- l, err = ParseLevel("invalid")
- assert.Equal(t, "not a valid logrus Level: \"invalid\"", err.Error())
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_darwin.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_darwin.go
deleted file mode 100644
index 8fe02a4aec..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_darwin.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// Based on ssh/terminal:
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package logrus
-
-import "syscall"
-
-const ioctlReadTermios = syscall.TIOCGETA
-
-type Termios syscall.Termios
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_freebsd.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_freebsd.go
deleted file mode 100644
index 0428ee5d52..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_freebsd.go
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- Go 1.2 doesn't include Termios for FreeBSD. This should be added in 1.3 and this could be merged with terminal_darwin.
-*/
-package logrus
-
-import (
- "syscall"
-)
-
-const ioctlReadTermios = syscall.TIOCGETA
-
-type Termios struct {
- Iflag uint32
- Oflag uint32
- Cflag uint32
- Lflag uint32
- Cc [20]uint8
- Ispeed uint32
- Ospeed uint32
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_linux.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_linux.go
deleted file mode 100644
index a2c0b40db6..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_linux.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// Based on ssh/terminal:
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package logrus
-
-import "syscall"
-
-const ioctlReadTermios = syscall.TCGETS
-
-type Termios syscall.Termios
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_notwindows.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_notwindows.go
deleted file mode 100644
index 276447bd5c..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_notwindows.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Based on ssh/terminal:
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build linux,!appengine darwin freebsd
-
-package logrus
-
-import (
- "syscall"
- "unsafe"
-)
-
-// IsTerminal returns true if the given file descriptor is a terminal.
-func IsTerminal() bool {
- fd := syscall.Stdout
- var termios Termios
- _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
- return err == 0
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_windows.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_windows.go
deleted file mode 100644
index 2e09f6f7e3..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_windows.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// Based on ssh/terminal:
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build windows
-
-package logrus
-
-import (
- "syscall"
- "unsafe"
-)
-
-var kernel32 = syscall.NewLazyDLL("kernel32.dll")
-
-var (
- procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
-)
-
-// IsTerminal returns true if the given file descriptor is a terminal.
-func IsTerminal() bool {
- fd := syscall.Stdout
- var st uint32
- r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
- return r != 0 && e == 0
-}
diff --git a/Godeps/_workspace/src/github.com/Sirupsen/logrus/text_formatter.go b/Godeps/_workspace/src/github.com/Sirupsen/logrus/text_formatter.go
deleted file mode 100644
index fc0a4082a7..0000000000
--- a/Godeps/_workspace/src/github.com/Sirupsen/logrus/text_formatter.go
+++ /dev/null
@@ -1,95 +0,0 @@
-package logrus
-
-import (
- "bytes"
- "fmt"
- "sort"
- "strings"
- "time"
-)
-
-const (
- nocolor = 0
- red = 31
- green = 32
- yellow = 33
- blue = 34
-)
-
-var (
- baseTimestamp time.Time
- isTerminal bool
-)
-
-func init() {
- baseTimestamp = time.Now()
- isTerminal = IsTerminal()
-}
-
-func miniTS() int {
- return int(time.Since(baseTimestamp) / time.Second)
-}
-
-type TextFormatter struct {
- // Set to true to bypass checking for a TTY before outputting colors.
- ForceColors bool
- DisableColors bool
-}
-
-func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
-
- var keys []string
- for k := range entry.Data {
- keys = append(keys, k)
- }
- sort.Strings(keys)
-
- b := &bytes.Buffer{}
-
- prefixFieldClashes(entry)
-
- isColored := (f.ForceColors || isTerminal) && !f.DisableColors
-
- if isColored {
- printColored(b, entry, keys)
- } else {
- f.appendKeyValue(b, "time", entry.Time.Format(time.RFC3339))
- f.appendKeyValue(b, "level", entry.Level.String())
- f.appendKeyValue(b, "msg", entry.Message)
- for _, key := range keys {
- f.appendKeyValue(b, key, entry.Data[key])
- }
- }
-
- b.WriteByte('\n')
- return b.Bytes(), nil
-}
-
-func printColored(b *bytes.Buffer, entry *Entry, keys []string) {
- var levelColor int
- switch entry.Level {
- case WarnLevel:
- levelColor = yellow
- case ErrorLevel, FatalLevel, PanicLevel:
- levelColor = red
- default:
- levelColor = blue
- }
-
- levelText := strings.ToUpper(entry.Level.String())[0:4]
-
- fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message)
- for _, k := range keys {
- v := entry.Data[k]
- fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%v", levelColor, k, v)
- }
-}
-
-func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key, value interface{}) {
- switch value.(type) {
- case string, error:
- fmt.Fprintf(b, "%v=%q ", key, value)
- default:
- fmt.Fprintf(b, "%v=%v ", key, value)
- }
-}
diff --git a/Godeps/_workspace/src/github.com/docker/docker/api/MAINTAINERS b/Godeps/_workspace/src/github.com/docker/docker/api/MAINTAINERS
deleted file mode 100644
index 96abeae570..0000000000
--- a/Godeps/_workspace/src/github.com/docker/docker/api/MAINTAINERS
+++ /dev/null
@@ -1,2 +0,0 @@
-Victor Vieux (@vieux)
-Jessie Frazelle (@jfrazelle)
diff --git a/Godeps/_workspace/src/github.com/docker/docker/api/README.md b/Godeps/_workspace/src/github.com/docker/docker/api/README.md
deleted file mode 100644
index 453f61a1a1..0000000000
--- a/Godeps/_workspace/src/github.com/docker/docker/api/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-This directory contains code pertaining to the Docker API:
-
- - Used by the docker client when communicating with the docker daemon
-
- - Used by third party tools wishing to interface with the docker daemon
diff --git a/Godeps/_workspace/src/github.com/docker/docker/api/api_unit_test.go b/Godeps/_workspace/src/github.com/docker/docker/api/api_unit_test.go
deleted file mode 100644
index 678331d369..0000000000
--- a/Godeps/_workspace/src/github.com/docker/docker/api/api_unit_test.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package api
-
-import (
- "testing"
-)
-
-func TestJsonContentType(t *testing.T) {
- if !MatchesContentType("application/json", "application/json") {
- t.Fail()
- }
-
- if !MatchesContentType("application/json; charset=utf-8", "application/json") {
- t.Fail()
- }
-
- if MatchesContentType("dockerapplication/json", "application/json") {
- t.Fail()
- }
-}
diff --git a/Godeps/_workspace/src/github.com/docker/docker/api/client/cli.go b/Godeps/_workspace/src/github.com/docker/docker/api/client/cli.go
deleted file mode 100644
index 5e1ccb3291..0000000000
--- a/Godeps/_workspace/src/github.com/docker/docker/api/client/cli.go
+++ /dev/null
@@ -1,188 +0,0 @@
-package client
-
-import (
- "crypto/tls"
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "net"
- "net/http"
- "os"
- "reflect"
- "strings"
- "text/template"
- "time"
-
- flag "github.com/docker/docker/pkg/mflag"
- "github.com/docker/docker/pkg/term"
- "github.com/docker/docker/registry"
-)
-
-type DockerCli struct {
- proto string
- addr string
- configFile *registry.ConfigFile
- in io.ReadCloser
- out io.Writer
- err io.Writer
- keyFile string
- tlsConfig *tls.Config
- scheme string
- // inFd holds file descriptor of the client's STDIN, if it's a valid file
- inFd uintptr
- // outFd holds file descriptor of the client's STDOUT, if it's a valid file
- outFd uintptr
- // isTerminalIn describes if client's STDIN is a TTY
- isTerminalIn bool
- // isTerminalOut describes if client's STDOUT is a TTY
- isTerminalOut bool
- transport *http.Transport
-}
-
-var funcMap = template.FuncMap{
- "json": func(v interface{}) string {
- a, _ := json.Marshal(v)
- return string(a)
- },
-}
-
-func (cli *DockerCli) getMethod(args ...string) (func(...string) error, bool) {
- camelArgs := make([]string, len(args))
- for i, s := range args {
- if len(s) == 0 {
- return nil, false
- }
- camelArgs[i] = strings.ToUpper(s[:1]) + strings.ToLower(s[1:])
- }
- methodName := "Cmd" + strings.Join(camelArgs, "")
- method := reflect.ValueOf(cli).MethodByName(methodName)
- if !method.IsValid() {
- return nil, false
- }
- return method.Interface().(func(...string) error), true
-}
-
-// Cmd executes the specified command
-func (cli *DockerCli) Cmd(args ...string) error {
- if len(args) > 1 {
- method, exists := cli.getMethod(args[:2]...)
- if exists {
- return method(args[2:]...)
- }
- }
- if len(args) > 0 {
- method, exists := cli.getMethod(args[0])
- if !exists {
- fmt.Fprintf(cli.err, "docker: '%s' is not a docker command. See 'docker --help'.\n", args[0])
- os.Exit(1)
- }
- return method(args[1:]...)
- }
- return cli.CmdHelp()
-}
-
-func (cli *DockerCli) Subcmd(name, signature, description string, exitOnError bool) *flag.FlagSet {
- var errorHandling flag.ErrorHandling
- if exitOnError {
- errorHandling = flag.ExitOnError
- } else {
- errorHandling = flag.ContinueOnError
- }
- flags := flag.NewFlagSet(name, errorHandling)
- flags.Usage = func() {
- options := ""
- if flags.FlagCountUndeprecated() > 0 {
- options = "[OPTIONS] "
- }
- fmt.Fprintf(cli.out, "\nUsage: docker %s %s%s\n\n%s\n\n", name, options, signature, description)
- flags.SetOutput(cli.out)
- flags.PrintDefaults()
- os.Exit(0)
- }
- return flags
-}
-
-func (cli *DockerCli) LoadConfigFile() (err error) {
- cli.configFile, err = registry.LoadConfig(os.Getenv("HOME"))
- if err != nil {
- fmt.Fprintf(cli.err, "WARNING: %s\n", err)
- }
- return err
-}
-
-func (cli *DockerCli) CheckTtyInput(attachStdin, ttyMode bool) error {
- // In order to attach to a container tty, input stream for the client must
- // be a tty itself: redirecting or piping the client standard input is
- // incompatible with `docker run -t`, `docker exec -t` or `docker attach`.
- if ttyMode && attachStdin && !cli.isTerminalIn {
- return errors.New("cannot enable tty mode on non tty input")
- }
- return nil
-}
-
-func NewDockerCli(in io.ReadCloser, out, err io.Writer, keyFile string, proto, addr string, tlsConfig *tls.Config) *DockerCli {
- var (
- inFd uintptr
- outFd uintptr
- isTerminalIn = false
- isTerminalOut = false
- scheme = "http"
- )
-
- if tlsConfig != nil {
- scheme = "https"
- }
-
- if in != nil {
- if file, ok := in.(*os.File); ok {
- inFd = file.Fd()
- isTerminalIn = term.IsTerminal(inFd)
- }
- }
-
- if out != nil {
- if file, ok := out.(*os.File); ok {
- outFd = file.Fd()
- isTerminalOut = term.IsTerminal(outFd)
- }
- }
-
- if err == nil {
- err = out
- }
-
- // The transport is created here for reuse during the client session
- tr := &http.Transport{
- Proxy: http.ProxyFromEnvironment,
- TLSClientConfig: tlsConfig,
- }
-
- // Why 32? See issue 8035
- timeout := 32 * time.Second
- if proto == "unix" {
- // no need in compressing for local communications
- tr.DisableCompression = true
- tr.Dial = func(_, _ string) (net.Conn, error) {
- return net.DialTimeout(proto, addr, timeout)
- }
- } else {
- tr.Dial = (&net.Dialer{Timeout: timeout}).Dial
- }
-
- return &DockerCli{
- proto: proto,
- addr: addr,
- in: in,
- out: out,
- err: err,
- keyFile: keyFile,
- inFd: inFd,
- outFd: outFd,
- isTerminalIn: isTerminalIn,
- isTerminalOut: isTerminalOut,
- tlsConfig: tlsConfig,
- scheme: scheme,
- transport: tr,
- }
-}
diff --git a/Godeps/_workspace/src/github.com/docker/docker/api/client/commands.go b/Godeps/_workspace/src/github.com/docker/docker/api/client/commands.go
deleted file mode 100644
index c4ce5e01f3..0000000000
--- a/Godeps/_workspace/src/github.com/docker/docker/api/client/commands.go
+++ /dev/null
@@ -1,2764 +0,0 @@
-package client
-
-import (
- "bufio"
- "bytes"
- "encoding/base64"
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "io/ioutil"
- "net/http"
- "net/url"
- "os"
- "os/exec"
- "path"
- "path/filepath"
- "runtime"
- "sort"
- "strconv"
- "strings"
- "sync"
- "text/tabwriter"
- "text/template"
- "time"
-
- log "github.com/Sirupsen/logrus"
- "github.com/docker/docker/api"
- "github.com/docker/docker/api/stats"
- "github.com/docker/docker/dockerversion"
- "github.com/docker/docker/engine"
- "github.com/docker/docker/graph"
- "github.com/docker/docker/nat"
- "github.com/docker/docker/opts"
- "github.com/docker/docker/pkg/archive"
- "github.com/docker/docker/pkg/fileutils"
- flag "github.com/docker/docker/pkg/mflag"
- "github.com/docker/docker/pkg/parsers"
- "github.com/docker/docker/pkg/parsers/filters"
- "github.com/docker/docker/pkg/promise"
- "github.com/docker/docker/pkg/signal"
- "github.com/docker/docker/pkg/symlink"
- "github.com/docker/docker/pkg/term"
- "github.com/docker/docker/pkg/timeutils"
- "github.com/docker/docker/pkg/units"
- "github.com/docker/docker/pkg/urlutil"
- "github.com/docker/docker/registry"
- "github.com/docker/docker/runconfig"
- "github.com/docker/docker/utils"
-)
-
-const (
- tarHeaderSize = 512
-)
-
-func (cli *DockerCli) CmdHelp(args ...string) error {
- if len(args) > 1 {
- method, exists := cli.getMethod(args[:2]...)
- if exists {
- method("--help")
- return nil
- }
- }
- if len(args) > 0 {
- method, exists := cli.getMethod(args[0])
- if !exists {
- fmt.Fprintf(cli.err, "docker: '%s' is not a docker command. See 'docker --help'.\n", args[0])
- os.Exit(1)
- } else {
- method("--help")
- return nil
- }
- }
-
- flag.Usage()
-
- return nil
-}
-
-func (cli *DockerCli) CmdBuild(args ...string) error {
- cmd := cli.Subcmd("build", "PATH | URL | -", "Build a new image from the source code at PATH", true)
- tag := cmd.String([]string{"t", "-tag"}, "", "Repository name (and optionally a tag) to be applied to the resulting image in case of success")
- suppressOutput := cmd.Bool([]string{"q", "-quiet"}, false, "Suppress the verbose output generated by the containers")
- noCache := cmd.Bool([]string{"#no-cache", "-no-cache"}, false, "Do not use cache when building the image")
- rm := cmd.Bool([]string{"#rm", "-rm"}, true, "Remove intermediate containers after a successful build")
- forceRm := cmd.Bool([]string{"-force-rm"}, false, "Always remove intermediate containers, even after unsuccessful builds")
- pull := cmd.Bool([]string{"-pull"}, false, "Always attempt to pull a newer version of the image")
- dockerfileName := cmd.String([]string{"f", "-file"}, "", "Name of the Dockerfile(Default is 'Dockerfile' at context root)")
-
- cmd.Require(flag.Exact, 1)
-
- utils.ParseFlags(cmd, args, true)
-
- var (
- context archive.Archive
- isRemote bool
- err error
- )
-
- _, err = exec.LookPath("git")
- hasGit := err == nil
- if cmd.Arg(0) == "-" {
- // As a special case, 'docker build -' will build from either an empty context with the
- // contents of stdin as a Dockerfile, or a tar-ed context from stdin.
- buf := bufio.NewReader(cli.in)
- magic, err := buf.Peek(tarHeaderSize)
- if err != nil && err != io.EOF {
- return fmt.Errorf("failed to peek context header from STDIN: %v", err)
- }
- if !archive.IsArchive(magic) {
- dockerfile, err := ioutil.ReadAll(buf)
- if err != nil {
- return fmt.Errorf("failed to read Dockerfile from STDIN: %v", err)
- }
- if *dockerfileName == "" {
- *dockerfileName = api.DefaultDockerfileName
- }
- context, err = archive.Generate(*dockerfileName, string(dockerfile))
- } else {
- context = ioutil.NopCloser(buf)
- }
- } else if urlutil.IsURL(cmd.Arg(0)) && (!urlutil.IsGitURL(cmd.Arg(0)) || !hasGit) {
- isRemote = true
- } else {
- root := cmd.Arg(0)
- if urlutil.IsGitURL(root) {
- remoteURL := cmd.Arg(0)
- if !urlutil.IsGitTransport(remoteURL) {
- remoteURL = "https://" + remoteURL
- }
-
- root, err = ioutil.TempDir("", "docker-build-git")
- if err != nil {
- return err
- }
- defer os.RemoveAll(root)
-
- if output, err := exec.Command("git", "clone", "--recursive", remoteURL, root).CombinedOutput(); err != nil {
- return fmt.Errorf("Error trying to use git: %s (%s)", err, output)
- }
- }
- if _, err := os.Stat(root); err != nil {
- return err
- }
-
- absRoot, err := filepath.Abs(root)
- if err != nil {
- return err
- }
-
- filename := *dockerfileName // path to Dockerfile
-
- if *dockerfileName == "" {
- // No -f/--file was specified so use the default
- *dockerfileName = api.DefaultDockerfileName
- filename = path.Join(absRoot, *dockerfileName)
- }
-
- origDockerfile := *dockerfileName // used for error msg
-
- if filename, err = filepath.Abs(filename); err != nil {
- return err
- }
-
- // Verify that 'filename' is within the build context
- filename, err = symlink.FollowSymlinkInScope(filename, absRoot)
- if err != nil {
- return fmt.Errorf("The Dockerfile (%s) must be within the build context (%s)", origDockerfile, root)
- }
-
- // Now reset the dockerfileName to be relative to the build context
- *dockerfileName, err = filepath.Rel(absRoot, filename)
- if err != nil {
- return err
- }
-
- if _, err = os.Lstat(filename); os.IsNotExist(err) {
- return fmt.Errorf("Cannot locate Dockerfile: %s", origDockerfile)
- }
- var includes = []string{"."}
-
- excludes, err := utils.ReadDockerIgnore(path.Join(root, ".dockerignore"))
- if err != nil {
- return err
- }
-
- // If .dockerignore mentions .dockerignore or the Dockerfile
- // then make sure we send both files over to the daemon
- // because Dockerfile is, obviously, needed no matter what, and
- // .dockerignore is needed to know if either one needs to be
- // removed. The deamon will remove them for us, if needed, after it
- // parses the Dockerfile.
- keepThem1, _ := fileutils.Matches(".dockerignore", excludes)
- keepThem2, _ := fileutils.Matches(*dockerfileName, excludes)
- if keepThem1 || keepThem2 {
- includes = append(includes, ".dockerignore", *dockerfileName)
- }
-
- if err = utils.ValidateContextDirectory(root, excludes); err != nil {
- return fmt.Errorf("Error checking context is accessible: '%s'. Please check permissions and try again.", err)
- }
- options := &archive.TarOptions{
- Compression: archive.Uncompressed,
- ExcludePatterns: excludes,
- IncludeFiles: includes,
- }
- context, err = archive.TarWithOptions(root, options)
- if err != nil {
- return err
- }
- }
- var body io.Reader
- // Setup an upload progress bar
- // FIXME: ProgressReader shouldn't be this annoying to use
- if context != nil {
- sf := utils.NewStreamFormatter(false)
- body = utils.ProgressReader(context, 0, cli.out, sf, true, "", "Sending build context to Docker daemon")
- }
- // Send the build context
- v := &url.Values{}
-
- //Check if the given image name can be resolved
- if *tag != "" {
- repository, tag := parsers.ParseRepositoryTag(*tag)
- if err := registry.ValidateRepositoryName(repository); err != nil {
- return err
- }
- if len(tag) > 0 {
- if err := graph.ValidateTagName(tag); err != nil {
- return err
- }
- }
- }
-
- v.Set("t", *tag)
-
- if *suppressOutput {
- v.Set("q", "1")
- }
- if isRemote {
- v.Set("remote", cmd.Arg(0))
- }
- if *noCache {
- v.Set("nocache", "1")
- }
- if *rm {
- v.Set("rm", "1")
- } else {
- v.Set("rm", "0")
- }
-
- if *forceRm {
- v.Set("forcerm", "1")
- }
-
- if *pull {
- v.Set("pull", "1")
- }
-
- v.Set("dockerfile", *dockerfileName)
-
- cli.LoadConfigFile()
-
- headers := http.Header(make(map[string][]string))
- buf, err := json.Marshal(cli.configFile)
- if err != nil {
- return err
- }
- headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
-
- if context != nil {
- headers.Set("Content-Type", "application/tar")
- }
- err = cli.stream("POST", fmt.Sprintf("/build?%s", v.Encode()), body, cli.out, headers)
- if jerr, ok := err.(*utils.JSONError); ok {
- // If no error code is set, default to 1
- if jerr.Code == 0 {
- jerr.Code = 1
- }
- return &utils.StatusError{Status: jerr.Message, StatusCode: jerr.Code}
- }
- return err
-}
-
-// 'docker login': login / register a user to registry service.
-func (cli *DockerCli) CmdLogin(args ...string) error {
- cmd := cli.Subcmd("login", "[SERVER]", "Register or log in to a Docker registry server, if no server is specified \""+registry.IndexServerAddress()+"\" is the default.", true)
- cmd.Require(flag.Max, 1)
-
- var username, password, email string
-
- cmd.StringVar(&username, []string{"u", "-username"}, "", "Username")
- cmd.StringVar(&password, []string{"p", "-password"}, "", "Password")
- cmd.StringVar(&email, []string{"e", "-email"}, "", "Email")
-
- utils.ParseFlags(cmd, args, true)
-
- serverAddress := registry.IndexServerAddress()
- if len(cmd.Args()) > 0 {
- serverAddress = cmd.Arg(0)
- }
-
- promptDefault := func(prompt string, configDefault string) {
- if configDefault == "" {
- fmt.Fprintf(cli.out, "%s: ", prompt)
- } else {
- fmt.Fprintf(cli.out, "%s (%s): ", prompt, configDefault)
- }
- }
-
- readInput := func(in io.Reader, out io.Writer) string {
- reader := bufio.NewReader(in)
- line, _, err := reader.ReadLine()
- if err != nil {
- fmt.Fprintln(out, err.Error())
- os.Exit(1)
- }
- return string(line)
- }
-
- cli.LoadConfigFile()
- authconfig, ok := cli.configFile.Configs[serverAddress]
- if !ok {
- authconfig = registry.AuthConfig{}
- }
-
- if username == "" {
- promptDefault("Username", authconfig.Username)
- username = readInput(cli.in, cli.out)
- if username == "" {
- username = authconfig.Username
- }
- }
- // Assume that a different username means they may not want to use
- // the password or email from the config file, so prompt them
- if username != authconfig.Username {
- if password == "" {
- oldState, err := term.SaveState(cli.inFd)
- if err != nil {
- return err
- }
- fmt.Fprintf(cli.out, "Password: ")
- term.DisableEcho(cli.inFd, oldState)
-
- password = readInput(cli.in, cli.out)
- fmt.Fprint(cli.out, "\n")
-
- term.RestoreTerminal(cli.inFd, oldState)
- if password == "" {
- return fmt.Errorf("Error : Password Required")
- }
- }
-
- if email == "" {
- promptDefault("Email", authconfig.Email)
- email = readInput(cli.in, cli.out)
- if email == "" {
- email = authconfig.Email
- }
- }
- } else {
- // However, if they don't override the username use the
- // password or email from the cmd line if specified. IOW, allow
- // then to change/overide them. And if not specified, just
- // use what's in the config file
- if password == "" {
- password = authconfig.Password
- }
- if email == "" {
- email = authconfig.Email
- }
- }
- authconfig.Username = username
- authconfig.Password = password
- authconfig.Email = email
- authconfig.ServerAddress = serverAddress
- cli.configFile.Configs[serverAddress] = authconfig
-
- stream, statusCode, err := cli.call("POST", "/auth", cli.configFile.Configs[serverAddress], false)
- if statusCode == 401 {
- delete(cli.configFile.Configs, serverAddress)
- registry.SaveConfig(cli.configFile)
- return err
- }
- if err != nil {
- return err
- }
- var out2 engine.Env
- err = out2.Decode(stream)
- if err != nil {
- cli.configFile, _ = registry.LoadConfig(os.Getenv("HOME"))
- return err
- }
- registry.SaveConfig(cli.configFile)
- if out2.Get("Status") != "" {
- fmt.Fprintf(cli.out, "%s\n", out2.Get("Status"))
- }
- return nil
-}
-
-// log out from a Docker registry
-func (cli *DockerCli) CmdLogout(args ...string) error {
- cmd := cli.Subcmd("logout", "[SERVER]", "Log out from a Docker registry, if no server is specified \""+registry.IndexServerAddress()+"\" is the default.", true)
- cmd.Require(flag.Max, 1)
-
- utils.ParseFlags(cmd, args, false)
- serverAddress := registry.IndexServerAddress()
- if len(cmd.Args()) > 0 {
- serverAddress = cmd.Arg(0)
- }
-
- cli.LoadConfigFile()
- if _, ok := cli.configFile.Configs[serverAddress]; !ok {
- fmt.Fprintf(cli.out, "Not logged in to %s\n", serverAddress)
- } else {
- fmt.Fprintf(cli.out, "Remove login credentials for %s\n", serverAddress)
- delete(cli.configFile.Configs, serverAddress)
-
- if err := registry.SaveConfig(cli.configFile); err != nil {
- return fmt.Errorf("Failed to save docker config: %v", err)
- }
- }
- return nil
-}
-
-// 'docker wait': block until a container stops
-func (cli *DockerCli) CmdWait(args ...string) error {
- cmd := cli.Subcmd("wait", "CONTAINER [CONTAINER...]", "Block until a container stops, then print its exit code.", true)
- cmd.Require(flag.Min, 1)
-
- utils.ParseFlags(cmd, args, true)
-
- var encounteredError error
- for _, name := range cmd.Args() {
- status, err := waitForExit(cli, name)
- if err != nil {
- fmt.Fprintf(cli.err, "%s\n", err)
- encounteredError = fmt.Errorf("Error: failed to wait one or more containers")
- } else {
- fmt.Fprintf(cli.out, "%d\n", status)
- }
- }
- return encounteredError
-}
-
-// 'docker version': show version information
-func (cli *DockerCli) CmdVersion(args ...string) error {
- cmd := cli.Subcmd("version", "", "Show the Docker version information.", true)
- cmd.Require(flag.Exact, 0)
-
- utils.ParseFlags(cmd, args, false)
-
- if dockerversion.VERSION != "" {
- fmt.Fprintf(cli.out, "Client version: %s\n", dockerversion.VERSION)
- }
- fmt.Fprintf(cli.out, "Client API version: %s\n", api.APIVERSION)
- fmt.Fprintf(cli.out, "Go version (client): %s\n", runtime.Version())
- if dockerversion.GITCOMMIT != "" {
- fmt.Fprintf(cli.out, "Git commit (client): %s\n", dockerversion.GITCOMMIT)
- }
- fmt.Fprintf(cli.out, "OS/Arch (client): %s/%s\n", runtime.GOOS, runtime.GOARCH)
-
- body, _, err := readBody(cli.call("GET", "/version", nil, false))
- if err != nil {
- return err
- }
-
- out := engine.NewOutput()
- remoteVersion, err := out.AddEnv()
- if err != nil {
- log.Errorf("Error reading remote version: %s", err)
- return err
- }
- if _, err := out.Write(body); err != nil {
- log.Errorf("Error reading remote version: %s", err)
- return err
- }
- out.Close()
- fmt.Fprintf(cli.out, "Server version: %s\n", remoteVersion.Get("Version"))
- if apiVersion := remoteVersion.Get("ApiVersion"); apiVersion != "" {
- fmt.Fprintf(cli.out, "Server API version: %s\n", apiVersion)
- }
- fmt.Fprintf(cli.out, "Go version (server): %s\n", remoteVersion.Get("GoVersion"))
- fmt.Fprintf(cli.out, "Git commit (server): %s\n", remoteVersion.Get("GitCommit"))
- return nil
-}
-
-// 'docker info': display system-wide information.
-func (cli *DockerCli) CmdInfo(args ...string) error {
- cmd := cli.Subcmd("info", "", "Display system-wide information", true)
- cmd.Require(flag.Exact, 0)
- utils.ParseFlags(cmd, args, false)
-
- body, _, err := readBody(cli.call("GET", "/info", nil, false))
- if err != nil {
- return err
- }
-
- out := engine.NewOutput()
- remoteInfo, err := out.AddEnv()
- if err != nil {
- return err
- }
-
- if _, err := out.Write(body); err != nil {
- log.Errorf("Error reading remote info: %s", err)
- return err
- }
- out.Close()
-
- if remoteInfo.Exists("Containers") {
- fmt.Fprintf(cli.out, "Containers: %d\n", remoteInfo.GetInt("Containers"))
- }
- if remoteInfo.Exists("Images") {
- fmt.Fprintf(cli.out, "Images: %d\n", remoteInfo.GetInt("Images"))
- }
- if remoteInfo.Exists("Driver") {
- fmt.Fprintf(cli.out, "Storage Driver: %s\n", remoteInfo.Get("Driver"))
- }
- if remoteInfo.Exists("DriverStatus") {
- var driverStatus [][2]string
- if err := remoteInfo.GetJson("DriverStatus", &driverStatus); err != nil {
- return err
- }
- for _, pair := range driverStatus {
- fmt.Fprintf(cli.out, " %s: %s\n", pair[0], pair[1])
- }
- }
- if remoteInfo.Exists("ExecutionDriver") {
- fmt.Fprintf(cli.out, "Execution Driver: %s\n", remoteInfo.Get("ExecutionDriver"))
- }
- if remoteInfo.Exists("KernelVersion") {
- fmt.Fprintf(cli.out, "Kernel Version: %s\n", remoteInfo.Get("KernelVersion"))
- }
- if remoteInfo.Exists("OperatingSystem") {
- fmt.Fprintf(cli.out, "Operating System: %s\n", remoteInfo.Get("OperatingSystem"))
- }
- if remoteInfo.Exists("NCPU") {
- fmt.Fprintf(cli.out, "CPUs: %d\n", remoteInfo.GetInt("NCPU"))
- }
- if remoteInfo.Exists("MemTotal") {
- fmt.Fprintf(cli.out, "Total Memory: %s\n", units.BytesSize(float64(remoteInfo.GetInt64("MemTotal"))))
- }
- if remoteInfo.Exists("Name") {
- fmt.Fprintf(cli.out, "Name: %s\n", remoteInfo.Get("Name"))
- }
- if remoteInfo.Exists("ID") {
- fmt.Fprintf(cli.out, "ID: %s\n", remoteInfo.Get("ID"))
- }
-
- if remoteInfo.GetBool("Debug") || os.Getenv("DEBUG") != "" {
- if remoteInfo.Exists("Debug") {
- fmt.Fprintf(cli.out, "Debug mode (server): %v\n", remoteInfo.GetBool("Debug"))
- }
- fmt.Fprintf(cli.out, "Debug mode (client): %v\n", os.Getenv("DEBUG") != "")
- if remoteInfo.Exists("NFd") {
- fmt.Fprintf(cli.out, "Fds: %d\n", remoteInfo.GetInt("NFd"))
- }
- if remoteInfo.Exists("NGoroutines") {
- fmt.Fprintf(cli.out, "Goroutines: %d\n", remoteInfo.GetInt("NGoroutines"))
- }
- if remoteInfo.Exists("NEventsListener") {
- fmt.Fprintf(cli.out, "EventsListeners: %d\n", remoteInfo.GetInt("NEventsListener"))
- }
- if initSha1 := remoteInfo.Get("InitSha1"); initSha1 != "" {
- fmt.Fprintf(cli.out, "Init SHA1: %s\n", initSha1)
- }
- if initPath := remoteInfo.Get("InitPath"); initPath != "" {
- fmt.Fprintf(cli.out, "Init Path: %s\n", initPath)
- }
- if root := remoteInfo.Get("DockerRootDir"); root != "" {
- fmt.Fprintf(cli.out, "Docker Root Dir: %s\n", root)
- }
- }
-
- if len(remoteInfo.GetList("IndexServerAddress")) != 0 {
- cli.LoadConfigFile()
- u := cli.configFile.Configs[remoteInfo.Get("IndexServerAddress")].Username
- if len(u) > 0 {
- fmt.Fprintf(cli.out, "Username: %v\n", u)
- fmt.Fprintf(cli.out, "Registry: %v\n", remoteInfo.GetList("IndexServerAddress"))
- }
- }
- if remoteInfo.Exists("MemoryLimit") && !remoteInfo.GetBool("MemoryLimit") {
- fmt.Fprintf(cli.err, "WARNING: No memory limit support\n")
- }
- if remoteInfo.Exists("SwapLimit") && !remoteInfo.GetBool("SwapLimit") {
- fmt.Fprintf(cli.err, "WARNING: No swap limit support\n")
- }
- if remoteInfo.Exists("IPv4Forwarding") && !remoteInfo.GetBool("IPv4Forwarding") {
- fmt.Fprintf(cli.err, "WARNING: IPv4 forwarding is disabled.\n")
- }
- if remoteInfo.Exists("Labels") {
- fmt.Fprintln(cli.out, "Labels:")
- for _, attribute := range remoteInfo.GetList("Labels") {
- fmt.Fprintf(cli.out, " %s\n", attribute)
- }
- }
-
- return nil
-}
-
-func (cli *DockerCli) CmdStop(args ...string) error {
- cmd := cli.Subcmd("stop", "CONTAINER [CONTAINER...]", "Stop a running container by sending SIGTERM and then SIGKILL after a grace period", true)
- nSeconds := cmd.Int([]string{"t", "-time"}, 10, "Number of seconds to wait for the container to stop before killing it. Default is 10 seconds.")
- cmd.Require(flag.Min, 1)
-
- utils.ParseFlags(cmd, args, true)
-
- v := url.Values{}
- v.Set("t", strconv.Itoa(*nSeconds))
-
- var encounteredError error
- for _, name := range cmd.Args() {
- _, _, err := readBody(cli.call("POST", "/containers/"+name+"/stop?"+v.Encode(), nil, false))
- if err != nil {
- fmt.Fprintf(cli.err, "%s\n", err)
- encounteredError = fmt.Errorf("Error: failed to stop one or more containers")
- } else {
- fmt.Fprintf(cli.out, "%s\n", name)
- }
- }
- return encounteredError
-}
-
-func (cli *DockerCli) CmdRestart(args ...string) error {
- cmd := cli.Subcmd("restart", "CONTAINER [CONTAINER...]", "Restart a running container", true)
- nSeconds := cmd.Int([]string{"t", "-time"}, 10, "Number of seconds to try to stop for before killing the container. Once killed it will then be restarted. Default is 10 seconds.")
- cmd.Require(flag.Min, 1)
-
- utils.ParseFlags(cmd, args, true)
-
- v := url.Values{}
- v.Set("t", strconv.Itoa(*nSeconds))
-
- var encounteredError error
- for _, name := range cmd.Args() {
- _, _, err := readBody(cli.call("POST", "/containers/"+name+"/restart?"+v.Encode(), nil, false))
- if err != nil {
- fmt.Fprintf(cli.err, "%s\n", err)
- encounteredError = fmt.Errorf("Error: failed to restart one or more containers")
- } else {
- fmt.Fprintf(cli.out, "%s\n", name)
- }
- }
- return encounteredError
-}
-
-func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal {
- sigc := make(chan os.Signal, 128)
- signal.CatchAll(sigc)
- go func() {
- for s := range sigc {
- if s == signal.SIGCHLD {
- continue
- }
- var sig string
- for sigStr, sigN := range signal.SignalMap {
- if sigN == s {
- sig = sigStr
- break
- }
- }
- if sig == "" {
- log.Errorf("Unsupported signal: %v. Discarding.", s)
- }
- if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%s", cid, sig), nil, false)); err != nil {
- log.Debugf("Error sending signal: %s", err)
- }
- }
- }()
- return sigc
-}
-
-func (cli *DockerCli) CmdStart(args ...string) error {
- var (
- cErr chan error
- tty bool
-
- cmd = cli.Subcmd("start", "CONTAINER [CONTAINER...]", "Restart a stopped container", true)
- attach = cmd.Bool([]string{"a", "-attach"}, false, "Attach container's STDOUT and STDERR and forward all signals to the process")
- openStdin = cmd.Bool([]string{"i", "-interactive"}, false, "Attach container's STDIN")
- )
-
- cmd.Require(flag.Min, 1)
- utils.ParseFlags(cmd, args, true)
-
- hijacked := make(chan io.Closer)
-
- if *attach || *openStdin {
- if cmd.NArg() > 1 {
- return fmt.Errorf("You cannot start and attach multiple containers at once.")
- }
-
- stream, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/json", nil, false)
- if err != nil {
- return err
- }
-
- env := engine.Env{}
- if err := env.Decode(stream); err != nil {
- return err
- }
- config := env.GetSubEnv("Config")
- tty = config.GetBool("Tty")
-
- if !tty {
- sigc := cli.forwardAllSignals(cmd.Arg(0))
- defer signal.StopCatch(sigc)
- }
-
- var in io.ReadCloser
-
- v := url.Values{}
- v.Set("stream", "1")
-
- if *openStdin && config.GetBool("OpenStdin") {
- v.Set("stdin", "1")
- in = cli.in
- }
-
- v.Set("stdout", "1")
- v.Set("stderr", "1")
-
- cErr = promise.Go(func() error {
- return cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), tty, in, cli.out, cli.err, hijacked, nil)
- })
- } else {
- close(hijacked)
- }
-
- // Acknowledge the hijack before starting
- select {
- case closer := <-hijacked:
- // Make sure that the hijack gets closed when returning (results
- // in closing the hijack chan and freeing server's goroutines)
- if closer != nil {
- defer closer.Close()
- }
- case err := <-cErr:
- if err != nil {
- return err
- }
- }
-
- var encounteredError error
- for _, name := range cmd.Args() {
- _, _, err := readBody(cli.call("POST", "/containers/"+name+"/start", nil, false))
- if err != nil {
- if !*attach && !*openStdin {
- fmt.Fprintf(cli.err, "%s\n", err)
- }
- encounteredError = fmt.Errorf("Error: failed to start one or more containers")
- } else {
- if !*attach && !*openStdin {
- fmt.Fprintf(cli.out, "%s\n", name)
- }
- }
- }
- if encounteredError != nil {
- if *openStdin || *attach {
- cli.in.Close()
- }
- return encounteredError
- }
-
- if *openStdin || *attach {
- if tty && cli.isTerminalOut {
- if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil {
- log.Errorf("Error monitoring TTY size: %s", err)
- }
- }
- if attchErr := <-cErr; attchErr != nil {
- return attchErr
- }
- _, status, err := getExitCode(cli, cmd.Arg(0))
- if err != nil {
- return err
- }
- if status != 0 {
- return &utils.StatusError{StatusCode: status}
- }
- }
- return nil
-}
-
-func (cli *DockerCli) CmdUnpause(args ...string) error {
- cmd := cli.Subcmd("unpause", "CONTAINER", "Unpause all processes within a container", true)
- cmd.Require(flag.Exact, 1)
- utils.ParseFlags(cmd, args, false)
-
- var encounteredError error
- for _, name := range cmd.Args() {
- if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/unpause", name), nil, false)); err != nil {
- fmt.Fprintf(cli.err, "%s\n", err)
- encounteredError = fmt.Errorf("Error: failed to unpause container named %s", name)
- } else {
- fmt.Fprintf(cli.out, "%s\n", name)
- }
- }
- return encounteredError
-}
-
-func (cli *DockerCli) CmdPause(args ...string) error {
- cmd := cli.Subcmd("pause", "CONTAINER", "Pause all processes within a container", true)
- cmd.Require(flag.Exact, 1)
- utils.ParseFlags(cmd, args, false)
-
- var encounteredError error
- for _, name := range cmd.Args() {
- if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/pause", name), nil, false)); err != nil {
- fmt.Fprintf(cli.err, "%s\n", err)
- encounteredError = fmt.Errorf("Error: failed to pause container named %s", name)
- } else {
- fmt.Fprintf(cli.out, "%s\n", name)
- }
- }
- return encounteredError
-}
-
-func (cli *DockerCli) CmdRename(args ...string) error {
- cmd := cli.Subcmd("rename", "OLD_NAME NEW_NAME", "Rename a container", true)
- if err := cmd.Parse(args); err != nil {
- return nil
- }
-
- if cmd.NArg() != 2 {
- cmd.Usage()
- return nil
- }
- old_name := cmd.Arg(0)
- new_name := cmd.Arg(1)
-
- if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/rename?name=%s", old_name, new_name), nil, false)); err != nil {
- fmt.Fprintf(cli.err, "%s\n", err)
- return fmt.Errorf("Error: failed to rename container named %s", old_name)
- }
- return nil
-}
-
-func (cli *DockerCli) CmdInspect(args ...string) error {
- cmd := cli.Subcmd("inspect", "CONTAINER|IMAGE [CONTAINER|IMAGE...]", "Return low-level information on a container or image", true)
- tmplStr := cmd.String([]string{"f", "#format", "-format"}, "", "Format the output using the given go template.")
- cmd.Require(flag.Min, 1)
-
- utils.ParseFlags(cmd, args, true)
-
- var tmpl *template.Template
- if *tmplStr != "" {
- var err error
- if tmpl, err = template.New("").Funcs(funcMap).Parse(*tmplStr); err != nil {
- fmt.Fprintf(cli.err, "Template parsing error: %v\n", err)
- return &utils.StatusError{StatusCode: 64,
- Status: "Template parsing error: " + err.Error()}
- }
- }
-
- indented := new(bytes.Buffer)
- indented.WriteByte('[')
- status := 0
-
- for _, name := range cmd.Args() {
- obj, _, err := readBody(cli.call("GET", "/containers/"+name+"/json", nil, false))
- if err != nil {
- obj, _, err = readBody(cli.call("GET", "/images/"+name+"/json", nil, false))
- if err != nil {
- if strings.Contains(err.Error(), "No such") {
- fmt.Fprintf(cli.err, "Error: No such image or container: %s\n", name)
- } else {
- fmt.Fprintf(cli.err, "%s", err)
- }
- status = 1
- continue
- }
- }
-
- if tmpl == nil {
- if err = json.Indent(indented, obj, "", " "); err != nil {
- fmt.Fprintf(cli.err, "%s\n", err)
- status = 1
- continue
- }
- } else {
- // Has template, will render
- var value interface{}
- if err := json.Unmarshal(obj, &value); err != nil {
- fmt.Fprintf(cli.err, "%s\n", err)
- status = 1
- continue
- }
- if err := tmpl.Execute(cli.out, value); err != nil {
- return err
- }
- cli.out.Write([]byte{'\n'})
- }
- indented.WriteString(",")
- }
-
- if indented.Len() > 1 {
- // Remove trailing ','
- indented.Truncate(indented.Len() - 1)
- }
- indented.WriteString("]\n")
-
- if tmpl == nil {
- if _, err := io.Copy(cli.out, indented); err != nil {
- return err
- }
- }
-
- if status != 0 {
- return &utils.StatusError{StatusCode: status}
- }
- return nil
-}
-
-func (cli *DockerCli) CmdTop(args ...string) error {
- cmd := cli.Subcmd("top", "CONTAINER [ps OPTIONS]", "Display the running processes of a container", true)
- cmd.Require(flag.Min, 1)
-
- utils.ParseFlags(cmd, args, true)
-
- val := url.Values{}
- if cmd.NArg() > 1 {
- val.Set("ps_args", strings.Join(cmd.Args()[1:], " "))
- }
-
- stream, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/top?"+val.Encode(), nil, false)
- if err != nil {
- return err
- }
- var procs engine.Env
- if err := procs.Decode(stream); err != nil {
- return err
- }
- w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
- fmt.Fprintln(w, strings.Join(procs.GetList("Titles"), "\t"))
- processes := [][]string{}
- if err := procs.GetJson("Processes", &processes); err != nil {
- return err
- }
- for _, proc := range processes {
- fmt.Fprintln(w, strings.Join(proc, "\t"))
- }
- w.Flush()
- return nil
-}
-
-func (cli *DockerCli) CmdPort(args ...string) error {
- cmd := cli.Subcmd("port", "CONTAINER [PRIVATE_PORT[/PROTO]]", "List port mappings for the CONTAINER, or lookup the public-facing port that is NAT-ed to the PRIVATE_PORT", true)
- cmd.Require(flag.Min, 1)
- utils.ParseFlags(cmd, args, true)
-
- stream, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/json", nil, false)
- if err != nil {
- return err
- }
-
- env := engine.Env{}
- if err := env.Decode(stream); err != nil {
- return err
- }
- ports := nat.PortMap{}
- if err := env.GetSubEnv("NetworkSettings").GetJson("Ports", &ports); err != nil {
- return err
- }
-
- if cmd.NArg() == 2 {
- var (
- port = cmd.Arg(1)
- proto = "tcp"
- parts = strings.SplitN(port, "/", 2)
- )
-
- if len(parts) == 2 && len(parts[1]) != 0 {
- port = parts[0]
- proto = parts[1]
- }
- natPort := port + "/" + proto
- if frontends, exists := ports[nat.Port(port+"/"+proto)]; exists && frontends != nil {
- for _, frontend := range frontends {
- fmt.Fprintf(cli.out, "%s:%s\n", frontend.HostIp, frontend.HostPort)
- }
- return nil
- }
- return fmt.Errorf("Error: No public port '%s' published for %s", natPort, cmd.Arg(0))
- }
-
- for from, frontends := range ports {
- for _, frontend := range frontends {
- fmt.Fprintf(cli.out, "%s -> %s:%s\n", from, frontend.HostIp, frontend.HostPort)
- }
- }
-
- return nil
-}
-
-// 'docker rmi IMAGE' removes all images with the name IMAGE
-func (cli *DockerCli) CmdRmi(args ...string) error {
- var (
- cmd = cli.Subcmd("rmi", "IMAGE [IMAGE...]", "Remove one or more images", true)
- force = cmd.Bool([]string{"f", "-force"}, false, "Force removal of the image")
- noprune = cmd.Bool([]string{"-no-prune"}, false, "Do not delete untagged parents")
- )
- cmd.Require(flag.Min, 1)
-
- utils.ParseFlags(cmd, args, true)
-
- v := url.Values{}
- if *force {
- v.Set("force", "1")
- }
- if *noprune {
- v.Set("noprune", "1")
- }
-
- var encounteredError error
- for _, name := range cmd.Args() {
- body, _, err := readBody(cli.call("DELETE", "/images/"+name+"?"+v.Encode(), nil, false))
- if err != nil {
- fmt.Fprintf(cli.err, "%s\n", err)
- encounteredError = fmt.Errorf("Error: failed to remove one or more images")
- } else {
- outs := engine.NewTable("Created", 0)
- if _, err := outs.ReadListFrom(body); err != nil {
- fmt.Fprintf(cli.err, "%s\n", err)
- encounteredError = fmt.Errorf("Error: failed to remove one or more images")
- continue
- }
- for _, out := range outs.Data {
- if out.Get("Deleted") != "" {
- fmt.Fprintf(cli.out, "Deleted: %s\n", out.Get("Deleted"))
- } else {
- fmt.Fprintf(cli.out, "Untagged: %s\n", out.Get("Untagged"))
- }
- }
- }
- }
- return encounteredError
-}
-
-func (cli *DockerCli) CmdHistory(args ...string) error {
- cmd := cli.Subcmd("history", "IMAGE", "Show the history of an image", true)
- quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only show numeric IDs")
- noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output")
- cmd.Require(flag.Exact, 1)
-
- utils.ParseFlags(cmd, args, true)
-
- body, _, err := readBody(cli.call("GET", "/images/"+cmd.Arg(0)+"/history", nil, false))
- if err != nil {
- return err
- }
-
- outs := engine.NewTable("Created", 0)
- if _, err := outs.ReadListFrom(body); err != nil {
- return err
- }
-
- w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
- if !*quiet {
- fmt.Fprintln(w, "IMAGE\tCREATED\tCREATED BY\tSIZE")
- }
-
- for _, out := range outs.Data {
- outID := out.Get("Id")
- if !*quiet {
- if *noTrunc {
- fmt.Fprintf(w, "%s\t", outID)
- } else {
- fmt.Fprintf(w, "%s\t", utils.TruncateID(outID))
- }
-
- fmt.Fprintf(w, "%s ago\t", units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))))
-
- if *noTrunc {
- fmt.Fprintf(w, "%s\t", out.Get("CreatedBy"))
- } else {
- fmt.Fprintf(w, "%s\t", utils.Trunc(out.Get("CreatedBy"), 45))
- }
- fmt.Fprintf(w, "%s\n", units.HumanSize(float64(out.GetInt64("Size"))))
- } else {
- if *noTrunc {
- fmt.Fprintln(w, outID)
- } else {
- fmt.Fprintln(w, utils.TruncateID(outID))
- }
- }
- }
- w.Flush()
- return nil
-}
-
-func (cli *DockerCli) CmdRm(args ...string) error {
- cmd := cli.Subcmd("rm", "CONTAINER [CONTAINER...]", "Remove one or more containers", true)
- v := cmd.Bool([]string{"v", "-volumes"}, false, "Remove the volumes associated with the container")
- link := cmd.Bool([]string{"l", "#link", "-link"}, false, "Remove the specified link and not the underlying container")
- force := cmd.Bool([]string{"f", "-force"}, false, "Force the removal of a running container (uses SIGKILL)")
- cmd.Require(flag.Min, 1)
-
- utils.ParseFlags(cmd, args, true)
-
- val := url.Values{}
- if *v {
- val.Set("v", "1")
- }
- if *link {
- val.Set("link", "1")
- }
-
- if *force {
- val.Set("force", "1")
- }
-
- var encounteredError error
- for _, name := range cmd.Args() {
- _, _, err := readBody(cli.call("DELETE", "/containers/"+name+"?"+val.Encode(), nil, false))
- if err != nil {
- fmt.Fprintf(cli.err, "%s\n", err)
- encounteredError = fmt.Errorf("Error: failed to remove one or more containers")
- } else {
- fmt.Fprintf(cli.out, "%s\n", name)
- }
- }
- return encounteredError
-}
-
-// 'docker kill NAME' kills a running container
-func (cli *DockerCli) CmdKill(args ...string) error {
- cmd := cli.Subcmd("kill", "CONTAINER [CONTAINER...]", "Kill a running container using SIGKILL or a specified signal", true)
- signal := cmd.String([]string{"s", "-signal"}, "KILL", "Signal to send to the container")
- cmd.Require(flag.Min, 1)
-
- utils.ParseFlags(cmd, args, true)
-
- var encounteredError error
- for _, name := range cmd.Args() {
- if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%s", name, *signal), nil, false)); err != nil {
- fmt.Fprintf(cli.err, "%s\n", err)
- encounteredError = fmt.Errorf("Error: failed to kill one or more containers")
- } else {
- fmt.Fprintf(cli.out, "%s\n", name)
- }
- }
- return encounteredError
-}
-
-func (cli *DockerCli) CmdImport(args ...string) error {
- cmd := cli.Subcmd("import", "URL|- [REPOSITORY[:TAG]]", "Create an empty filesystem image and import the contents of the tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) into it, then optionally tag it.", true)
- cmd.Require(flag.Min, 1)
-
- utils.ParseFlags(cmd, args, true)
-
- var (
- v = url.Values{}
- src = cmd.Arg(0)
- repository = cmd.Arg(1)
- )
-
- v.Set("fromSrc", src)
- v.Set("repo", repository)
-
- if cmd.NArg() == 3 {
- fmt.Fprintf(cli.err, "[DEPRECATED] The format 'URL|- [REPOSITORY [TAG]]' has been deprecated. Please use URL|- [REPOSITORY[:TAG]]\n")
- v.Set("tag", cmd.Arg(2))
- }
-
- if repository != "" {
- //Check if the given image name can be resolved
- repo, _ := parsers.ParseRepositoryTag(repository)
- if err := registry.ValidateRepositoryName(repo); err != nil {
- return err
- }
- }
-
- var in io.Reader
-
- if src == "-" {
- in = cli.in
- }
-
- return cli.stream("POST", "/images/create?"+v.Encode(), in, cli.out, nil)
-}
-
-func (cli *DockerCli) CmdPush(args ...string) error {
- cmd := cli.Subcmd("push", "NAME[:TAG]", "Push an image or a repository to the registry", true)
- cmd.Require(flag.Exact, 1)
-
- utils.ParseFlags(cmd, args, true)
-
- name := cmd.Arg(0)
-
- cli.LoadConfigFile()
-
- remote, tag := parsers.ParseRepositoryTag(name)
-
- // Resolve the Repository name from fqn to RepositoryInfo
- repoInfo, err := registry.ParseRepositoryInfo(remote)
- if err != nil {
- return err
- }
- // Resolve the Auth config relevant for this server
- authConfig := cli.configFile.ResolveAuthConfig(repoInfo.Index)
- // If we're not using a custom registry, we know the restrictions
- // applied to repository names and can warn the user in advance.
- // Custom repositories can have different rules, and we must also
- // allow pushing by image ID.
- if repoInfo.Official {
- username := authConfig.Username
- if username == "" {
- username = ""
- }
- return fmt.Errorf("You cannot push a \"root\" repository. Please rename your repository to / (ex: %s/%s)", username, repoInfo.LocalName)
- }
-
- v := url.Values{}
- v.Set("tag", tag)
-
- push := func(authConfig registry.AuthConfig) error {
- buf, err := json.Marshal(authConfig)
- if err != nil {
- return err
- }
- registryAuthHeader := []string{
- base64.URLEncoding.EncodeToString(buf),
- }
-
- return cli.stream("POST", "/images/"+remote+"/push?"+v.Encode(), nil, cli.out, map[string][]string{
- "X-Registry-Auth": registryAuthHeader,
- })
- }
-
- if err := push(authConfig); err != nil {
- if strings.Contains(err.Error(), "Status 401") {
- fmt.Fprintln(cli.out, "\nPlease login prior to push:")
- if err := cli.CmdLogin(repoInfo.Index.GetAuthConfigKey()); err != nil {
- return err
- }
- authConfig := cli.configFile.ResolveAuthConfig(repoInfo.Index)
- return push(authConfig)
- }
- return err
- }
- return nil
-}
-
-func (cli *DockerCli) CmdPull(args ...string) error {
- cmd := cli.Subcmd("pull", "NAME[:TAG]", "Pull an image or a repository from the registry", true)
- allTags := cmd.Bool([]string{"a", "-all-tags"}, false, "Download all tagged images in the repository")
- cmd.Require(flag.Exact, 1)
-
- utils.ParseFlags(cmd, args, true)
-
- var (
- v = url.Values{}
- remote = cmd.Arg(0)
- newRemote = remote
- )
- taglessRemote, tag := parsers.ParseRepositoryTag(remote)
- if tag == "" && !*allTags {
- newRemote = taglessRemote + ":" + graph.DEFAULTTAG
- }
- if tag != "" && *allTags {
- return fmt.Errorf("tag can't be used with --all-tags/-a")
- }
-
- v.Set("fromImage", newRemote)
-
- // Resolve the Repository name from fqn to RepositoryInfo
- repoInfo, err := registry.ParseRepositoryInfo(taglessRemote)
- if err != nil {
- return err
- }
-
- cli.LoadConfigFile()
-
- // Resolve the Auth config relevant for this server
- authConfig := cli.configFile.ResolveAuthConfig(repoInfo.Index)
-
- pull := func(authConfig registry.AuthConfig) error {
- buf, err := json.Marshal(authConfig)
- if err != nil {
- return err
- }
- registryAuthHeader := []string{
- base64.URLEncoding.EncodeToString(buf),
- }
-
- return cli.stream("POST", "/images/create?"+v.Encode(), nil, cli.out, map[string][]string{
- "X-Registry-Auth": registryAuthHeader,
- })
- }
-
- if err := pull(authConfig); err != nil {
- if strings.Contains(err.Error(), "Status 401") {
- fmt.Fprintln(cli.out, "\nPlease login prior to pull:")
- if err := cli.CmdLogin(repoInfo.Index.GetAuthConfigKey()); err != nil {
- return err
- }
- authConfig := cli.configFile.ResolveAuthConfig(repoInfo.Index)
- return pull(authConfig)
- }
- return err
- }
-
- return nil
-}
-
-func (cli *DockerCli) CmdImages(args ...string) error {
- cmd := cli.Subcmd("images", "[REPOSITORY]", "List images", true)
- quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only show numeric IDs")
- all := cmd.Bool([]string{"a", "-all"}, false, "Show all images (by default filter out the intermediate image layers)")
- noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output")
- // FIXME: --viz and --tree are deprecated. Remove them in a future version.
- flViz := cmd.Bool([]string{"#v", "#viz", "#-viz"}, false, "Output graph in graphviz format")
- flTree := cmd.Bool([]string{"#t", "#tree", "#-tree"}, false, "Output graph in tree format")
-
- flFilter := opts.NewListOpts(nil)
- cmd.Var(&flFilter, []string{"f", "-filter"}, "Provide filter values (i.e., 'dangling=true')")
- cmd.Require(flag.Max, 1)
-
- utils.ParseFlags(cmd, args, true)
-
- // Consolidate all filter flags, and sanity check them early.
- // They'll get process in the daemon/server.
- imageFilterArgs := filters.Args{}
- for _, f := range flFilter.GetAll() {
- var err error
- imageFilterArgs, err = filters.ParseFlag(f, imageFilterArgs)
- if err != nil {
- return err
- }
- }
-
- matchName := cmd.Arg(0)
- // FIXME: --viz and --tree are deprecated. Remove them in a future version.
- if *flViz || *flTree {
- v := url.Values{
- "all": []string{"1"},
- }
- if len(imageFilterArgs) > 0 {
- filterJson, err := filters.ToParam(imageFilterArgs)
- if err != nil {
- return err
- }
- v.Set("filters", filterJson)
- }
-
- body, _, err := readBody(cli.call("GET", "/images/json?"+v.Encode(), nil, false))
- if err != nil {
- return err
- }
-
- outs := engine.NewTable("Created", 0)
- if _, err := outs.ReadListFrom(body); err != nil {
- return err
- }
-
- var (
- printNode func(cli *DockerCli, noTrunc bool, image *engine.Env, prefix string)
- startImage *engine.Env
-
- roots = engine.NewTable("Created", outs.Len())
- byParent = make(map[string]*engine.Table)
- )
-
- for _, image := range outs.Data {
- if image.Get("ParentId") == "" {
- roots.Add(image)
- } else {
- if children, exists := byParent[image.Get("ParentId")]; exists {
- children.Add(image)
- } else {
- byParent[image.Get("ParentId")] = engine.NewTable("Created", 1)
- byParent[image.Get("ParentId")].Add(image)
- }
- }
-
- if matchName != "" {
- if matchName == image.Get("Id") || matchName == utils.TruncateID(image.Get("Id")) {
- startImage = image
- }
-
- for _, repotag := range image.GetList("RepoTags") {
- if repotag == matchName {
- startImage = image
- }
- }
- }
- }
-
- if *flViz {
- fmt.Fprintf(cli.out, "digraph docker {\n")
- printNode = (*DockerCli).printVizNode
- } else {
- printNode = (*DockerCli).printTreeNode
- }
-
- if startImage != nil {
- root := engine.NewTable("Created", 1)
- root.Add(startImage)
- cli.WalkTree(*noTrunc, root, byParent, "", printNode)
- } else if matchName == "" {
- cli.WalkTree(*noTrunc, roots, byParent, "", printNode)
- }
- if *flViz {
- fmt.Fprintf(cli.out, " base [style=invisible]\n}\n")
- }
- } else {
- v := url.Values{}
- if len(imageFilterArgs) > 0 {
- filterJson, err := filters.ToParam(imageFilterArgs)
- if err != nil {
- return err
- }
- v.Set("filters", filterJson)
- }
-
- if cmd.NArg() == 1 {
- // FIXME rename this parameter, to not be confused with the filters flag
- v.Set("filter", matchName)
- }
- if *all {
- v.Set("all", "1")
- }
-
- body, _, err := readBody(cli.call("GET", "/images/json?"+v.Encode(), nil, false))
-
- if err != nil {
- return err
- }
-
- outs := engine.NewTable("Created", 0)
- if _, err := outs.ReadListFrom(body); err != nil {
- return err
- }
-
- w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
- if !*quiet {
- fmt.Fprintln(w, "REPOSITORY\tTAG\tIMAGE ID\tCREATED\tVIRTUAL SIZE")
- }
-
- for _, out := range outs.Data {
- for _, repotag := range out.GetList("RepoTags") {
-
- repo, tag := parsers.ParseRepositoryTag(repotag)
- outID := out.Get("Id")
- if !*noTrunc {
- outID = utils.TruncateID(outID)
- }
-
- if !*quiet {
- fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\n", repo, tag, outID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), units.HumanSize(float64(out.GetInt64("VirtualSize"))))
- } else {
- fmt.Fprintln(w, outID)
- }
- }
- }
-
- if !*quiet {
- w.Flush()
- }
- }
- return nil
-}
-
-// FIXME: --viz and --tree are deprecated. Remove them in a future version.
-func (cli *DockerCli) WalkTree(noTrunc bool, images *engine.Table, byParent map[string]*engine.Table, prefix string, printNode func(cli *DockerCli, noTrunc bool, image *engine.Env, prefix string)) {
- length := images.Len()
- if length > 1 {
- for index, image := range images.Data {
- if index+1 == length {
- printNode(cli, noTrunc, image, prefix+"└─")
- if subimages, exists := byParent[image.Get("Id")]; exists {
- cli.WalkTree(noTrunc, subimages, byParent, prefix+" ", printNode)
- }
- } else {
- printNode(cli, noTrunc, image, prefix+"\u251C─")
- if subimages, exists := byParent[image.Get("Id")]; exists {
- cli.WalkTree(noTrunc, subimages, byParent, prefix+"\u2502 ", printNode)
- }
- }
- }
- } else {
- for _, image := range images.Data {
- printNode(cli, noTrunc, image, prefix+"└─")
- if subimages, exists := byParent[image.Get("Id")]; exists {
- cli.WalkTree(noTrunc, subimages, byParent, prefix+" ", printNode)
- }
- }
- }
-}
-
-// FIXME: --viz and --tree are deprecated. Remove them in a future version.
-func (cli *DockerCli) printVizNode(noTrunc bool, image *engine.Env, prefix string) {
- var (
- imageID string
- parentID string
- )
- if noTrunc {
- imageID = image.Get("Id")
- parentID = image.Get("ParentId")
- } else {
- imageID = utils.TruncateID(image.Get("Id"))
- parentID = utils.TruncateID(image.Get("ParentId"))
- }
- if parentID == "" {
- fmt.Fprintf(cli.out, " base -> \"%s\" [style=invis]\n", imageID)
- } else {
- fmt.Fprintf(cli.out, " \"%s\" -> \"%s\"\n", parentID, imageID)
- }
- if image.GetList("RepoTags")[0] != ":" {
- fmt.Fprintf(cli.out, " \"%s\" [label=\"%s\\n%s\",shape=box,fillcolor=\"paleturquoise\",style=\"filled,rounded\"];\n",
- imageID, imageID, strings.Join(image.GetList("RepoTags"), "\\n"))
- }
-}
-
-// FIXME: --viz and --tree are deprecated. Remove them in a future version.
-func (cli *DockerCli) printTreeNode(noTrunc bool, image *engine.Env, prefix string) {
- var imageID string
- if noTrunc {
- imageID = image.Get("Id")
- } else {
- imageID = utils.TruncateID(image.Get("Id"))
- }
-
- fmt.Fprintf(cli.out, "%s%s Virtual Size: %s", prefix, imageID, units.HumanSize(float64(image.GetInt64("VirtualSize"))))
- if image.GetList("RepoTags")[0] != ":" {
- fmt.Fprintf(cli.out, " Tags: %s\n", strings.Join(image.GetList("RepoTags"), ", "))
- } else {
- fmt.Fprint(cli.out, "\n")
- }
-}
-
-func (cli *DockerCli) CmdPs(args ...string) error {
- var (
- err error
-
- psFilterArgs = filters.Args{}
- v = url.Values{}
-
- cmd = cli.Subcmd("ps", "", "List containers", true)
- quiet = cmd.Bool([]string{"q", "-quiet"}, false, "Only display numeric IDs")
- size = cmd.Bool([]string{"s", "-size"}, false, "Display total file sizes")
- all = cmd.Bool([]string{"a", "-all"}, false, "Show all containers. Only running containers are shown by default.")
- noTrunc = cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output")
- nLatest = cmd.Bool([]string{"l", "-latest"}, false, "Show only the latest created container, include non-running ones.")
- since = cmd.String([]string{"#sinceId", "#-since-id", "-since"}, "", "Show only containers created since Id or Name, include non-running ones.")
- before = cmd.String([]string{"#beforeId", "#-before-id", "-before"}, "", "Show only container created before Id or Name, include non-running ones.")
- last = cmd.Int([]string{"n"}, -1, "Show n last created containers, include non-running ones.")
- flFilter = opts.NewListOpts(nil)
- )
- cmd.Require(flag.Exact, 0)
-
- cmd.Var(&flFilter, []string{"f", "-filter"}, "Provide filter values. Valid filters:\nexited= - containers with exit code of \nstatus=(restarting|running|paused|exited)")
-
- utils.ParseFlags(cmd, args, true)
- if *last == -1 && *nLatest {
- *last = 1
- }
-
- if *all {
- v.Set("all", "1")
- }
-
- if *last != -1 {
- v.Set("limit", strconv.Itoa(*last))
- }
-
- if *since != "" {
- v.Set("since", *since)
- }
-
- if *before != "" {
- v.Set("before", *before)
- }
-
- if *size {
- v.Set("size", "1")
- }
-
- // Consolidate all filter flags, and sanity check them.
- // They'll get processed in the daemon/server.
- for _, f := range flFilter.GetAll() {
- if psFilterArgs, err = filters.ParseFlag(f, psFilterArgs); err != nil {
- return err
- }
- }
-
- if len(psFilterArgs) > 0 {
- filterJson, err := filters.ToParam(psFilterArgs)
- if err != nil {
- return err
- }
-
- v.Set("filters", filterJson)
- }
-
- body, _, err := readBody(cli.call("GET", "/containers/json?"+v.Encode(), nil, false))
- if err != nil {
- return err
- }
-
- outs := engine.NewTable("Created", 0)
- if _, err := outs.ReadListFrom(body); err != nil {
- return err
- }
-
- w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
- if !*quiet {
- fmt.Fprint(w, "CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES")
-
- if *size {
- fmt.Fprintln(w, "\tSIZE")
- } else {
- fmt.Fprint(w, "\n")
- }
- }
-
- stripNamePrefix := func(ss []string) []string {
- for i, s := range ss {
- ss[i] = s[1:]
- }
-
- return ss
- }
-
- for _, out := range outs.Data {
- outID := out.Get("Id")
-
- if !*noTrunc {
- outID = utils.TruncateID(outID)
- }
-
- if *quiet {
- fmt.Fprintln(w, outID)
-
- continue
- }
-
- var (
- outNames = stripNamePrefix(out.GetList("Names"))
- outCommand = strconv.Quote(out.Get("Command"))
- ports = engine.NewTable("", 0)
- )
-
- if !*noTrunc {
- outCommand = utils.Trunc(outCommand, 20)
-
- // only display the default name for the container with notrunc is passed
- for _, name := range outNames {
- if len(strings.Split(name, "/")) == 1 {
- outNames = []string{name}
-
- break
- }
- }
- }
-
- ports.ReadListFrom([]byte(out.Get("Ports")))
-
- image := out.Get("Image")
- if image == "" {
- image = ""
- }
-
- fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\t%s\t", outID, image, outCommand,
- units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))),
- out.Get("Status"), api.DisplayablePorts(ports), strings.Join(outNames, ","))
-
- if *size {
- if out.GetInt("SizeRootFs") > 0 {
- fmt.Fprintf(w, "%s (virtual %s)\n", units.HumanSize(float64(out.GetInt64("SizeRw"))), units.HumanSize(float64(out.GetInt64("SizeRootFs"))))
- } else {
- fmt.Fprintf(w, "%s\n", units.HumanSize(float64(out.GetInt64("SizeRw"))))
- }
-
- continue
- }
-
- fmt.Fprint(w, "\n")
- }
-
- if !*quiet {
- w.Flush()
- }
-
- return nil
-}
-
-func (cli *DockerCli) CmdCommit(args ...string) error {
- cmd := cli.Subcmd("commit", "CONTAINER [REPOSITORY[:TAG]]", "Create a new image from a container's changes", true)
- flPause := cmd.Bool([]string{"p", "-pause"}, true, "Pause container during commit")
- flComment := cmd.String([]string{"m", "-message"}, "", "Commit message")
- flAuthor := cmd.String([]string{"a", "#author", "-author"}, "", "Author (e.g., \"John Hannibal Smith \")")
- // FIXME: --run is deprecated, it will be replaced with inline Dockerfile commands.
- flConfig := cmd.String([]string{"#run", "#-run"}, "", "This option is deprecated and will be removed in a future version in favor of inline Dockerfile-compatible commands")
- cmd.Require(flag.Max, 2)
- cmd.Require(flag.Min, 1)
- utils.ParseFlags(cmd, args, true)
-
- var (
- name = cmd.Arg(0)
- repository, tag = parsers.ParseRepositoryTag(cmd.Arg(1))
- )
-
- //Check if the given image name can be resolved
- if repository != "" {
- if err := registry.ValidateRepositoryName(repository); err != nil {
- return err
- }
- }
-
- v := url.Values{}
- v.Set("container", name)
- v.Set("repo", repository)
- v.Set("tag", tag)
- v.Set("comment", *flComment)
- v.Set("author", *flAuthor)
-
- if *flPause != true {
- v.Set("pause", "0")
- }
-
- var (
- config *runconfig.Config
- env engine.Env
- )
- if *flConfig != "" {
- config = &runconfig.Config{}
- if err := json.Unmarshal([]byte(*flConfig), config); err != nil {
- return err
- }
- }
- stream, _, err := cli.call("POST", "/commit?"+v.Encode(), config, false)
- if err != nil {
- return err
- }
- if err := env.Decode(stream); err != nil {
- return err
- }
-
- fmt.Fprintf(cli.out, "%s\n", env.Get("Id"))
- return nil
-}
-
-func (cli *DockerCli) CmdEvents(args ...string) error {
- cmd := cli.Subcmd("events", "", "Get real time events from the server", true)
- since := cmd.String([]string{"#since", "-since"}, "", "Show all events created since timestamp")
- until := cmd.String([]string{"-until"}, "", "Stream events until this timestamp")
- flFilter := opts.NewListOpts(nil)
- cmd.Var(&flFilter, []string{"f", "-filter"}, "Provide filter values (i.e., 'event=stop')")
- cmd.Require(flag.Exact, 0)
-
- utils.ParseFlags(cmd, args, true)
-
- var (
- v = url.Values{}
- loc = time.FixedZone(time.Now().Zone())
- eventFilterArgs = filters.Args{}
- )
-
- // Consolidate all filter flags, and sanity check them early.
- // They'll get process in the daemon/server.
- for _, f := range flFilter.GetAll() {
- var err error
- eventFilterArgs, err = filters.ParseFlag(f, eventFilterArgs)
- if err != nil {
- return err
- }
- }
- var setTime = func(key, value string) {
- format := timeutils.RFC3339NanoFixed
- if len(value) < len(format) {
- format = format[:len(value)]
- }
- if t, err := time.ParseInLocation(format, value, loc); err == nil {
- v.Set(key, strconv.FormatInt(t.Unix(), 10))
- } else {
- v.Set(key, value)
- }
- }
- if *since != "" {
- setTime("since", *since)
- }
- if *until != "" {
- setTime("until", *until)
- }
- if len(eventFilterArgs) > 0 {
- filterJson, err := filters.ToParam(eventFilterArgs)
- if err != nil {
- return err
- }
- v.Set("filters", filterJson)
- }
- if err := cli.stream("GET", "/events?"+v.Encode(), nil, cli.out, nil); err != nil {
- return err
- }
- return nil
-}
-
-func (cli *DockerCli) CmdExport(args ...string) error {
- cmd := cli.Subcmd("export", "CONTAINER", "Export the contents of a filesystem as a tar archive to STDOUT", true)
- cmd.Require(flag.Exact, 1)
-
- utils.ParseFlags(cmd, args, true)
-
- if err := cli.stream("GET", "/containers/"+cmd.Arg(0)+"/export", nil, cli.out, nil); err != nil {
- return err
- }
- return nil
-}
-
-func (cli *DockerCli) CmdDiff(args ...string) error {
- cmd := cli.Subcmd("diff", "CONTAINER", "Inspect changes on a container's filesystem", true)
- cmd.Require(flag.Exact, 1)
-
- utils.ParseFlags(cmd, args, true)
-
- body, _, err := readBody(cli.call("GET", "/containers/"+cmd.Arg(0)+"/changes", nil, false))
-
- if err != nil {
- return err
- }
-
- outs := engine.NewTable("", 0)
- if _, err := outs.ReadListFrom(body); err != nil {
- return err
- }
- for _, change := range outs.Data {
- var kind string
- switch change.GetInt("Kind") {
- case archive.ChangeModify:
- kind = "C"
- case archive.ChangeAdd:
- kind = "A"
- case archive.ChangeDelete:
- kind = "D"
- }
- fmt.Fprintf(cli.out, "%s %s\n", kind, change.Get("Path"))
- }
- return nil
-}
-
-func (cli *DockerCli) CmdLogs(args ...string) error {
- var (
- cmd = cli.Subcmd("logs", "CONTAINER", "Fetch the logs of a container", true)
- follow = cmd.Bool([]string{"f", "-follow"}, false, "Follow log output")
- times = cmd.Bool([]string{"t", "-timestamps"}, false, "Show timestamps")
- tail = cmd.String([]string{"-tail"}, "all", "Output the specified number of lines at the end of logs (defaults to all logs)")
- )
- cmd.Require(flag.Exact, 1)
-
- utils.ParseFlags(cmd, args, true)
-
- name := cmd.Arg(0)
-
- stream, _, err := cli.call("GET", "/containers/"+name+"/json", nil, false)
- if err != nil {
- return err
- }
-
- env := engine.Env{}
- if err := env.Decode(stream); err != nil {
- return err
- }
-
- v := url.Values{}
- v.Set("stdout", "1")
- v.Set("stderr", "1")
-
- if *times {
- v.Set("timestamps", "1")
- }
-
- if *follow {
- v.Set("follow", "1")
- }
- v.Set("tail", *tail)
-
- return cli.streamHelper("GET", "/containers/"+name+"/logs?"+v.Encode(), env.GetSubEnv("Config").GetBool("Tty"), nil, cli.out, cli.err, nil)
-}
-
-func (cli *DockerCli) CmdAttach(args ...string) error {
- var (
- cmd = cli.Subcmd("attach", "CONTAINER", "Attach to a running container", true)
- noStdin = cmd.Bool([]string{"#nostdin", "-no-stdin"}, false, "Do not attach STDIN")
- proxy = cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxy all received signals to the process (non-TTY mode only). SIGCHLD, SIGKILL, and SIGSTOP are not proxied.")
- )
- cmd.Require(flag.Exact, 1)
-
- utils.ParseFlags(cmd, args, true)
- name := cmd.Arg(0)
-
- stream, _, err := cli.call("GET", "/containers/"+name+"/json", nil, false)
- if err != nil {
- return err
- }
-
- env := engine.Env{}
- if err := env.Decode(stream); err != nil {
- return err
- }
-
- if !env.GetSubEnv("State").GetBool("Running") {
- return fmt.Errorf("You cannot attach to a stopped container, start it first")
- }
-
- var (
- config = env.GetSubEnv("Config")
- tty = config.GetBool("Tty")
- )
-
- if err := cli.CheckTtyInput(!*noStdin, tty); err != nil {
- return err
- }
-
- if tty && cli.isTerminalOut {
- if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil {
- log.Debugf("Error monitoring TTY size: %s", err)
- }
- }
-
- var in io.ReadCloser
-
- v := url.Values{}
- v.Set("stream", "1")
- if !*noStdin && config.GetBool("OpenStdin") {
- v.Set("stdin", "1")
- in = cli.in
- }
-
- v.Set("stdout", "1")
- v.Set("stderr", "1")
-
- if *proxy && !tty {
- sigc := cli.forwardAllSignals(cmd.Arg(0))
- defer signal.StopCatch(sigc)
- }
-
- if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), tty, in, cli.out, cli.err, nil, nil); err != nil {
- return err
- }
-
- _, status, err := getExitCode(cli, cmd.Arg(0))
- if err != nil {
- return err
- }
- if status != 0 {
- return &utils.StatusError{StatusCode: status}
- }
-
- return nil
-}
-
-func (cli *DockerCli) CmdSearch(args ...string) error {
- cmd := cli.Subcmd("search", "TERM", "Search the Docker Hub for images", true)
- noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output")
- trusted := cmd.Bool([]string{"#t", "#trusted", "#-trusted"}, false, "Only show trusted builds")
- automated := cmd.Bool([]string{"-automated"}, false, "Only show automated builds")
- stars := cmd.Int([]string{"s", "#stars", "-stars"}, 0, "Only displays with at least x stars")
- cmd.Require(flag.Exact, 1)
-
- utils.ParseFlags(cmd, args, true)
-
- v := url.Values{}
- v.Set("term", cmd.Arg(0))
-
- body, _, err := readBody(cli.call("GET", "/images/search?"+v.Encode(), nil, true))
-
- if err != nil {
- return err
- }
- outs := engine.NewTable("star_count", 0)
- if _, err := outs.ReadListFrom(body); err != nil {
- return err
- }
- w := tabwriter.NewWriter(cli.out, 10, 1, 3, ' ', 0)
- fmt.Fprintf(w, "NAME\tDESCRIPTION\tSTARS\tOFFICIAL\tAUTOMATED\n")
- for _, out := range outs.Data {
- if ((*automated || *trusted) && (!out.GetBool("is_trusted") && !out.GetBool("is_automated"))) || (*stars > out.GetInt("star_count")) {
- continue
- }
- desc := strings.Replace(out.Get("description"), "\n", " ", -1)
- desc = strings.Replace(desc, "\r", " ", -1)
- if !*noTrunc && len(desc) > 45 {
- desc = utils.Trunc(desc, 42) + "..."
- }
- fmt.Fprintf(w, "%s\t%s\t%d\t", out.Get("name"), desc, out.GetInt("star_count"))
- if out.GetBool("is_official") {
- fmt.Fprint(w, "[OK]")
-
- }
- fmt.Fprint(w, "\t")
- if out.GetBool("is_automated") || out.GetBool("is_trusted") {
- fmt.Fprint(w, "[OK]")
- }
- fmt.Fprint(w, "\n")
- }
- w.Flush()
- return nil
-}
-
-// Ports type - Used to parse multiple -p flags
-type ports []int
-
-func (cli *DockerCli) CmdTag(args ...string) error {
- cmd := cli.Subcmd("tag", "IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]", "Tag an image into a repository", true)
- force := cmd.Bool([]string{"f", "#force", "-force"}, false, "Force")
- cmd.Require(flag.Exact, 2)
-
- utils.ParseFlags(cmd, args, true)
-
- var (
- repository, tag = parsers.ParseRepositoryTag(cmd.Arg(1))
- v = url.Values{}
- )
-
- //Check if the given image name can be resolved
- if err := registry.ValidateRepositoryName(repository); err != nil {
- return err
- }
- v.Set("repo", repository)
- v.Set("tag", tag)
-
- if *force {
- v.Set("force", "1")
- }
-
- if _, _, err := readBody(cli.call("POST", "/images/"+cmd.Arg(0)+"/tag?"+v.Encode(), nil, false)); err != nil {
- return err
- }
- return nil
-}
-
-func (cli *DockerCli) pullImage(image string) error {
- return cli.pullImageCustomOut(image, cli.out)
-}
-
-func (cli *DockerCli) pullImageCustomOut(image string, out io.Writer) error {
- v := url.Values{}
- repos, tag := parsers.ParseRepositoryTag(image)
- // pull only the image tagged 'latest' if no tag was specified
- if tag == "" {
- tag = graph.DEFAULTTAG
- }
- v.Set("fromImage", repos)
- v.Set("tag", tag)
-
- // Resolve the Repository name from fqn to RepositoryInfo
- repoInfo, err := registry.ParseRepositoryInfo(repos)
- if err != nil {
- return err
- }
-
- // Load the auth config file, to be able to pull the image
- cli.LoadConfigFile()
-
- // Resolve the Auth config relevant for this server
- authConfig := cli.configFile.ResolveAuthConfig(repoInfo.Index)
- buf, err := json.Marshal(authConfig)
- if err != nil {
- return err
- }
-
- registryAuthHeader := []string{
- base64.URLEncoding.EncodeToString(buf),
- }
- if err = cli.stream("POST", "/images/create?"+v.Encode(), nil, out, map[string][]string{"X-Registry-Auth": registryAuthHeader}); err != nil {
- return err
- }
- return nil
-}
-
-type cidFile struct {
- path string
- file *os.File
- written bool
-}
-
-func newCIDFile(path string) (*cidFile, error) {
- if _, err := os.Stat(path); err == nil {
- return nil, fmt.Errorf("Container ID file found, make sure the other container isn't running or delete %s", path)
- }
-
- f, err := os.Create(path)
- if err != nil {
- return nil, fmt.Errorf("Failed to create the container ID file: %s", err)
- }
-
- return &cidFile{path: path, file: f}, nil
-}
-
-func (cid *cidFile) Close() error {
- cid.file.Close()
-
- if !cid.written {
- if err := os.Remove(cid.path); err != nil {
- return fmt.Errorf("failed to remove the CID file '%s': %s \n", cid.path, err)
- }
- }
-
- return nil
-}
-
-func (cid *cidFile) Write(id string) error {
- if _, err := cid.file.Write([]byte(id)); err != nil {
- return fmt.Errorf("Failed to write the container ID to the file: %s", err)
- }
- cid.written = true
- return nil
-}
-
-func (cli *DockerCli) createContainer(config *runconfig.Config, hostConfig *runconfig.HostConfig, cidfile, name string) (engine.Env, error) {
- containerValues := url.Values{}
- if name != "" {
- containerValues.Set("name", name)
- }
-
- mergedConfig := runconfig.MergeConfigs(config, hostConfig)
-
- var containerIDFile *cidFile
- if cidfile != "" {
- var err error
- if containerIDFile, err = newCIDFile(cidfile); err != nil {
- return nil, err
- }
- defer containerIDFile.Close()
- }
-
- //create the container
- stream, statusCode, err := cli.call("POST", "/containers/create?"+containerValues.Encode(), mergedConfig, false)
- //if image not found try to pull it
- if statusCode == 404 {
- repo, tag := parsers.ParseRepositoryTag(config.Image)
- if tag == "" {
- tag = graph.DEFAULTTAG
- }
- fmt.Fprintf(cli.err, "Unable to find image '%s:%s' locally\n", repo, tag)
-
- // we don't want to write to stdout anything apart from container.ID
- if err = cli.pullImageCustomOut(config.Image, cli.err); err != nil {
- return nil, err
- }
- // Retry
- if stream, _, err = cli.call("POST", "/containers/create?"+containerValues.Encode(), mergedConfig, false); err != nil {
- return nil, err
- }
- } else if err != nil {
- return nil, err
- }
-
- var result engine.Env
- if err := result.Decode(stream); err != nil {
- return nil, err
- }
-
- for _, warning := range result.GetList("Warnings") {
- fmt.Fprintf(cli.err, "WARNING: %s\n", warning)
- }
-
- if containerIDFile != nil {
- if err = containerIDFile.Write(result.Get("Id")); err != nil {
- return nil, err
- }
- }
-
- return result, nil
-
-}
-
-func (cli *DockerCli) CmdCreate(args ...string) error {
- cmd := cli.Subcmd("create", "IMAGE [COMMAND] [ARG...]", "Create a new container", true)
-
- // These are flags not stored in Config/HostConfig
- var (
- flName = cmd.String([]string{"-name"}, "", "Assign a name to the container")
- )
-
- config, hostConfig, cmd, err := runconfig.Parse(cmd, args)
- if err != nil {
- utils.ReportError(cmd, err.Error(), true)
- }
- if config.Image == "" {
- cmd.Usage()
- return nil
- }
-
- createResult, err := cli.createContainer(config, hostConfig, hostConfig.ContainerIDFile, *flName)
- if err != nil {
- return err
- }
-
- fmt.Fprintf(cli.out, "%s\n", createResult.Get("Id"))
-
- return nil
-}
-
-func (cli *DockerCli) CmdRun(args ...string) error {
- // FIXME: just use runconfig.Parse already
- cmd := cli.Subcmd("run", "IMAGE [COMMAND] [ARG...]", "Run a command in a new container", true)
-
- // These are flags not stored in Config/HostConfig
- var (
- flAutoRemove = cmd.Bool([]string{"#rm", "-rm"}, false, "Automatically remove the container when it exits (incompatible with -d)")
- flDetach = cmd.Bool([]string{"d", "-detach"}, false, "Detached mode: run the container in the background and print the new container ID")
- flSigProxy = cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxy received signals to the process (non-TTY mode only). SIGCHLD, SIGSTOP, and SIGKILL are not proxied.")
- flName = cmd.String([]string{"#name", "-name"}, "", "Assign a name to the container")
- flAttach *opts.ListOpts
-
- ErrConflictAttachDetach = fmt.Errorf("Conflicting options: -a and -d")
- ErrConflictRestartPolicyAndAutoRemove = fmt.Errorf("Conflicting options: --restart and --rm")
- ErrConflictDetachAutoRemove = fmt.Errorf("Conflicting options: --rm and -d")
- )
-
- config, hostConfig, cmd, err := runconfig.Parse(cmd, args)
- // just in case the Parse does not exit
- if err != nil {
- utils.ReportError(cmd, err.Error(), true)
- }
- if config.Image == "" {
- cmd.Usage()
- return nil
- }
-
- if !*flDetach {
- if err := cli.CheckTtyInput(config.AttachStdin, config.Tty); err != nil {
- return err
- }
- } else {
- if fl := cmd.Lookup("attach"); fl != nil {
- flAttach = fl.Value.(*opts.ListOpts)
- if flAttach.Len() != 0 {
- return ErrConflictAttachDetach
- }
- }
- if *flAutoRemove {
- return ErrConflictDetachAutoRemove
- }
-
- config.AttachStdin = false
- config.AttachStdout = false
- config.AttachStderr = false
- config.StdinOnce = false
- }
-
- // Disable flSigProxy when in TTY mode
- sigProxy := *flSigProxy
- if config.Tty {
- sigProxy = false
- }
-
- runResult, err := cli.createContainer(config, hostConfig, hostConfig.ContainerIDFile, *flName)
- if err != nil {
- return err
- }
-
- if sigProxy {
- sigc := cli.forwardAllSignals(runResult.Get("Id"))
- defer signal.StopCatch(sigc)
- }
-
- var (
- waitDisplayId chan struct{}
- errCh chan error
- )
-
- if !config.AttachStdout && !config.AttachStderr {
- // Make this asynchronous to allow the client to write to stdin before having to read the ID
- waitDisplayId = make(chan struct{})
- go func() {
- defer close(waitDisplayId)
- fmt.Fprintf(cli.out, "%s\n", runResult.Get("Id"))
- }()
- }
-
- if *flAutoRemove && (hostConfig.RestartPolicy.Name == "always" || hostConfig.RestartPolicy.Name == "on-failure") {
- return ErrConflictRestartPolicyAndAutoRemove
- }
-
- // We need to instantiate the chan because the select needs it. It can
- // be closed but can't be uninitialized.
- hijacked := make(chan io.Closer)
-
- // Block the return until the chan gets closed
- defer func() {
- log.Debugf("End of CmdRun(), Waiting for hijack to finish.")
- if _, ok := <-hijacked; ok {
- log.Errorf("Hijack did not finish (chan still open)")
- }
- }()
-
- if config.AttachStdin || config.AttachStdout || config.AttachStderr {
- var (
- out, stderr io.Writer
- in io.ReadCloser
- v = url.Values{}
- )
- v.Set("stream", "1")
-
- if config.AttachStdin {
- v.Set("stdin", "1")
- in = cli.in
- }
- if config.AttachStdout {
- v.Set("stdout", "1")
- out = cli.out
- }
- if config.AttachStderr {
- v.Set("stderr", "1")
- if config.Tty {
- stderr = cli.out
- } else {
- stderr = cli.err
- }
- }
-
- errCh = promise.Go(func() error {
- return cli.hijack("POST", "/containers/"+runResult.Get("Id")+"/attach?"+v.Encode(), config.Tty, in, out, stderr, hijacked, nil)
- })
- } else {
- close(hijacked)
- }
-
- // Acknowledge the hijack before starting
- select {
- case closer := <-hijacked:
- // Make sure that the hijack gets closed when returning (results
- // in closing the hijack chan and freeing server's goroutines)
- if closer != nil {
- defer closer.Close()
- }
- case err := <-errCh:
- if err != nil {
- log.Debugf("Error hijack: %s", err)
- return err
- }
- }
-
- //start the container
- if _, _, err = readBody(cli.call("POST", "/containers/"+runResult.Get("Id")+"/start", nil, false)); err != nil {
- return err
- }
-
- if (config.AttachStdin || config.AttachStdout || config.AttachStderr) && config.Tty && cli.isTerminalOut {
- if err := cli.monitorTtySize(runResult.Get("Id"), false); err != nil {
- log.Errorf("Error monitoring TTY size: %s", err)
- }
- }
-
- if errCh != nil {
- if err := <-errCh; err != nil {
- log.Debugf("Error hijack: %s", err)
- return err
- }
- }
-
- // Detached mode: wait for the id to be displayed and return.
- if !config.AttachStdout && !config.AttachStderr {
- // Detached mode
- <-waitDisplayId
- return nil
- }
-
- var status int
-
- // Attached mode
- if *flAutoRemove {
- // Autoremove: wait for the container to finish, retrieve
- // the exit code and remove the container
- if _, _, err := readBody(cli.call("POST", "/containers/"+runResult.Get("Id")+"/wait", nil, false)); err != nil {
- return err
- }
- if _, status, err = getExitCode(cli, runResult.Get("Id")); err != nil {
- return err
- }
- if _, _, err := readBody(cli.call("DELETE", "/containers/"+runResult.Get("Id")+"?v=1", nil, false)); err != nil {
- return err
- }
- } else {
- // No Autoremove: Simply retrieve the exit code
- if !config.Tty {
- // In non-TTY mode, we can't detach, so we must wait for container exit
- if status, err = waitForExit(cli, runResult.Get("Id")); err != nil {
- return err
- }
- } else {
- // In TTY mode, there is a race: if the process dies too slowly, the state could
- // be updated after the getExitCode call and result in the wrong exit code being reported
- if _, status, err = getExitCode(cli, runResult.Get("Id")); err != nil {
- return err
- }
- }
- }
- if status != 0 {
- return &utils.StatusError{StatusCode: status}
- }
- return nil
-}
-
-func (cli *DockerCli) CmdCp(args ...string) error {
- cmd := cli.Subcmd("cp", "CONTAINER:PATH HOSTPATH", "Copy files/folders from the PATH to the HOSTPATH", true)
- cmd.Require(flag.Exact, 2)
-
- utils.ParseFlags(cmd, args, true)
-
- var copyData engine.Env
- info := strings.Split(cmd.Arg(0), ":")
-
- if len(info) != 2 {
- return fmt.Errorf("Error: Path not specified")
- }
-
- copyData.Set("Resource", info[1])
- copyData.Set("HostPath", cmd.Arg(1))
-
- stream, statusCode, err := cli.call("POST", "/containers/"+info[0]+"/copy", copyData, false)
- if stream != nil {
- defer stream.Close()
- }
- if statusCode == 404 {
- return fmt.Errorf("No such container: %v", info[0])
- }
- if err != nil {
- return err
- }
-
- if statusCode == 200 {
- if err := archive.Untar(stream, copyData.Get("HostPath"), &archive.TarOptions{NoLchown: true}); err != nil {
- return err
- }
- }
- return nil
-}
-
-func (cli *DockerCli) CmdSave(args ...string) error {
- cmd := cli.Subcmd("save", "IMAGE [IMAGE...]", "Save an image(s) to a tar archive (streamed to STDOUT by default)", true)
- outfile := cmd.String([]string{"o", "-output"}, "", "Write to an file, instead of STDOUT")
- cmd.Require(flag.Min, 1)
-
- utils.ParseFlags(cmd, args, true)
-
- var (
- output io.Writer = cli.out
- err error
- )
- if *outfile != "" {
- output, err = os.Create(*outfile)
- if err != nil {
- return err
- }
- } else if cli.isTerminalOut {
- return errors.New("Cowardly refusing to save to a terminal. Use the -o flag or redirect.")
- }
-
- if len(cmd.Args()) == 1 {
- image := cmd.Arg(0)
- if err := cli.stream("GET", "/images/"+image+"/get", nil, output, nil); err != nil {
- return err
- }
- } else {
- v := url.Values{}
- for _, arg := range cmd.Args() {
- v.Add("names", arg)
- }
- if err := cli.stream("GET", "/images/get?"+v.Encode(), nil, output, nil); err != nil {
- return err
- }
- }
- return nil
-}
-
-func (cli *DockerCli) CmdLoad(args ...string) error {
- cmd := cli.Subcmd("load", "", "Load an image from a tar archive on STDIN", true)
- infile := cmd.String([]string{"i", "-input"}, "", "Read from a tar archive file, instead of STDIN")
- cmd.Require(flag.Exact, 0)
-
- utils.ParseFlags(cmd, args, true)
-
- var (
- input io.Reader = cli.in
- err error
- )
- if *infile != "" {
- input, err = os.Open(*infile)
- if err != nil {
- return err
- }
- }
- if err := cli.stream("POST", "/images/load", input, cli.out, nil); err != nil {
- return err
- }
- return nil
-}
-
-func (cli *DockerCli) CmdExec(args ...string) error {
- cmd := cli.Subcmd("exec", "CONTAINER COMMAND [ARG...]", "Run a command in a running container", true)
-
- execConfig, err := runconfig.ParseExec(cmd, args)
- // just in case the ParseExec does not exit
- if execConfig.Container == "" || err != nil {
- return &utils.StatusError{StatusCode: 1}
- }
-
- stream, _, err := cli.call("POST", "/containers/"+execConfig.Container+"/exec", execConfig, false)
- if err != nil {
- return err
- }
-
- var execResult engine.Env
- if err := execResult.Decode(stream); err != nil {
- return err
- }
-
- execID := execResult.Get("Id")
-
- if execID == "" {
- fmt.Fprintf(cli.out, "exec ID empty")
- return nil
- }
-
- if !execConfig.Detach {
- if err := cli.CheckTtyInput(execConfig.AttachStdin, execConfig.Tty); err != nil {
- return err
- }
- } else {
- if _, _, err := readBody(cli.call("POST", "/exec/"+execID+"/start", execConfig, false)); err != nil {
- return err
- }
- // For now don't print this - wait for when we support exec wait()
- // fmt.Fprintf(cli.out, "%s\n", execID)
- return nil
- }
-
- // Interactive exec requested.
- var (
- out, stderr io.Writer
- in io.ReadCloser
- hijacked = make(chan io.Closer)
- errCh chan error
- )
-
- // Block the return until the chan gets closed
- defer func() {
- log.Debugf("End of CmdExec(), Waiting for hijack to finish.")
- if _, ok := <-hijacked; ok {
- log.Errorf("Hijack did not finish (chan still open)")
- }
- }()
-
- if execConfig.AttachStdin {
- in = cli.in
- }
- if execConfig.AttachStdout {
- out = cli.out
- }
- if execConfig.AttachStderr {
- if execConfig.Tty {
- stderr = cli.out
- } else {
- stderr = cli.err
- }
- }
- errCh = promise.Go(func() error {
- return cli.hijack("POST", "/exec/"+execID+"/start", execConfig.Tty, in, out, stderr, hijacked, execConfig)
- })
-
- // Acknowledge the hijack before starting
- select {
- case closer := <-hijacked:
- // Make sure that hijack gets closed when returning. (result
- // in closing hijack chan and freeing server's goroutines.
- if closer != nil {
- defer closer.Close()
- }
- case err := <-errCh:
- if err != nil {
- log.Debugf("Error hijack: %s", err)
- return err
- }
- }
-
- if execConfig.Tty && cli.isTerminalIn {
- if err := cli.monitorTtySize(execID, true); err != nil {
- log.Errorf("Error monitoring TTY size: %s", err)
- }
- }
-
- if err := <-errCh; err != nil {
- log.Debugf("Error hijack: %s", err)
- return err
- }
-
- var status int
- if _, status, err = getExecExitCode(cli, execID); err != nil {
- return err
- }
-
- if status != 0 {
- return &utils.StatusError{StatusCode: status}
- }
-
- return nil
-}
-
-type containerStats struct {
- Name string
- CpuPercentage float64
- Memory float64
- MemoryLimit float64
- MemoryPercentage float64
- NetworkRx float64
- NetworkTx float64
- mu sync.RWMutex
- err error
-}
-
-func (s *containerStats) Collect(cli *DockerCli) {
- stream, _, err := cli.call("GET", "/containers/"+s.Name+"/stats", nil, false)
- if err != nil {
- s.err = err
- return
- }
- defer stream.Close()
- var (
- previousCpu uint64
- previousSystem uint64
- start = true
- dec = json.NewDecoder(stream)
- u = make(chan error, 1)
- )
- go func() {
- for {
- var v *stats.Stats
- if err := dec.Decode(&v); err != nil {
- u <- err
- return
- }
- var (
- memPercent = float64(v.MemoryStats.Usage) / float64(v.MemoryStats.Limit) * 100.0
- cpuPercent = 0.0
- )
- if !start {
- cpuPercent = calcuateCpuPercent(previousCpu, previousSystem, v)
- }
- start = false
- s.mu.Lock()
- s.CpuPercentage = cpuPercent
- s.Memory = float64(v.MemoryStats.Usage)
- s.MemoryLimit = float64(v.MemoryStats.Limit)
- s.MemoryPercentage = memPercent
- s.NetworkRx = float64(v.Network.RxBytes)
- s.NetworkTx = float64(v.Network.TxBytes)
- s.mu.Unlock()
- previousCpu = v.CpuStats.CpuUsage.TotalUsage
- previousSystem = v.CpuStats.SystemUsage
- u <- nil
- }
- }()
- for {
- select {
- case <-time.After(2 * time.Second):
- // zero out the values if we have not received an update within
- // the specified duration.
- s.mu.Lock()
- s.CpuPercentage = 0
- s.Memory = 0
- s.MemoryPercentage = 0
- s.mu.Unlock()
- case err := <-u:
- if err != nil {
- s.mu.Lock()
- s.err = err
- s.mu.Unlock()
- return
- }
- }
- }
-}
-
-func (s *containerStats) Display(w io.Writer) error {
- s.mu.RLock()
- defer s.mu.RUnlock()
- if s.err != nil {
- return s.err
- }
- fmt.Fprintf(w, "%s\t%.2f%%\t%s/%s\t%.2f%%\t%s/%s\n",
- s.Name,
- s.CpuPercentage,
- units.BytesSize(s.Memory), units.BytesSize(s.MemoryLimit),
- s.MemoryPercentage,
- units.BytesSize(s.NetworkRx), units.BytesSize(s.NetworkTx))
- return nil
-}
-
-func (cli *DockerCli) CmdStats(args ...string) error {
- cmd := cli.Subcmd("stats", "CONTAINER", "Display a live stream of one or more containers' resource usage statistics", true)
- cmd.Require(flag.Min, 1)
- utils.ParseFlags(cmd, args, true)
-
- names := cmd.Args()
- sort.Strings(names)
- var (
- cStats []*containerStats
- w = tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
- )
- printHeader := func() {
- fmt.Fprint(cli.out, "\033[2J")
- fmt.Fprint(cli.out, "\033[H")
- fmt.Fprintln(w, "CONTAINER\tCPU %\tMEM USAGE/LIMIT\tMEM %\tNET I/O")
- }
- for _, n := range names {
- s := &containerStats{Name: n}
- cStats = append(cStats, s)
- go s.Collect(cli)
- }
- // do a quick pause so that any failed connections for containers that do not exist are able to be
- // evicted before we display the initial or default values.
- time.Sleep(500 * time.Millisecond)
- var errs []string
- for _, c := range cStats {
- c.mu.Lock()
- if c.err != nil {
- errs = append(errs, fmt.Sprintf("%s: %s", c.Name, c.err.Error()))
- }
- c.mu.Unlock()
- }
- if len(errs) > 0 {
- return fmt.Errorf("%s", strings.Join(errs, ", "))
- }
- for _ = range time.Tick(500 * time.Millisecond) {
- printHeader()
- toRemove := []int{}
- for i, s := range cStats {
- if err := s.Display(w); err != nil {
- toRemove = append(toRemove, i)
- }
- }
- for j := len(toRemove) - 1; j >= 0; j-- {
- i := toRemove[j]
- cStats = append(cStats[:i], cStats[i+1:]...)
- }
- if len(cStats) == 0 {
- return nil
- }
- w.Flush()
- }
- return nil
-}
-
-func calcuateCpuPercent(previousCpu, previousSystem uint64, v *stats.Stats) float64 {
- var (
- cpuPercent = 0.0
- // calculate the change for the cpu usage of the container in between readings
- cpuDelta = float64(v.CpuStats.CpuUsage.TotalUsage - previousCpu)
- // calculate the change for the entire system between readings
- systemDelta = float64(v.CpuStats.SystemUsage - previousSystem)
- )
-
- if systemDelta > 0.0 && cpuDelta > 0.0 {
- cpuPercent = (cpuDelta / systemDelta) * float64(len(v.CpuStats.CpuUsage.PercpuUsage)) * 100.0
- }
- return cpuPercent
-}
diff --git a/Godeps/_workspace/src/github.com/docker/docker/api/client/hijack.go b/Godeps/_workspace/src/github.com/docker/docker/api/client/hijack.go
deleted file mode 100644
index bb902405c0..0000000000
--- a/Godeps/_workspace/src/github.com/docker/docker/api/client/hijack.go
+++ /dev/null
@@ -1,250 +0,0 @@
-package client
-
-import (
- "crypto/tls"
- "errors"
- "fmt"
- "io"
- "net"
- "net/http"
- "net/http/httputil"
- "os"
- "runtime"
- "strings"
- "time"
-
- log "github.com/Sirupsen/logrus"
- "github.com/docker/docker/api"
- "github.com/docker/docker/dockerversion"
- "github.com/docker/docker/pkg/promise"
- "github.com/docker/docker/pkg/stdcopy"
- "github.com/docker/docker/pkg/term"
-)
-
-type tlsClientCon struct {
- *tls.Conn
- rawConn net.Conn
-}
-
-func (c *tlsClientCon) CloseWrite() error {
- // Go standard tls.Conn doesn't provide the CloseWrite() method so we do it
- // on its underlying connection.
- if cwc, ok := c.rawConn.(interface {
- CloseWrite() error
- }); ok {
- return cwc.CloseWrite()
- }
- return nil
-}
-
-func tlsDial(network, addr string, config *tls.Config) (net.Conn, error) {
- return tlsDialWithDialer(new(net.Dialer), network, addr, config)
-}
-
-// We need to copy Go's implementation of tls.Dial (pkg/cryptor/tls/tls.go) in
-// order to return our custom tlsClientCon struct which holds both the tls.Conn
-// object _and_ its underlying raw connection. The rationale for this is that
-// we need to be able to close the write end of the connection when attaching,
-// which tls.Conn does not provide.
-func tlsDialWithDialer(dialer *net.Dialer, network, addr string, config *tls.Config) (net.Conn, error) {
- // We want the Timeout and Deadline values from dialer to cover the
- // whole process: TCP connection and TLS handshake. This means that we
- // also need to start our own timers now.
- timeout := dialer.Timeout
-
- if !dialer.Deadline.IsZero() {
- deadlineTimeout := dialer.Deadline.Sub(time.Now())
- if timeout == 0 || deadlineTimeout < timeout {
- timeout = deadlineTimeout
- }
- }
-
- var errChannel chan error
-
- if timeout != 0 {
- errChannel = make(chan error, 2)
- time.AfterFunc(timeout, func() {
- errChannel <- errors.New("")
- })
- }
-
- rawConn, err := dialer.Dial(network, addr)
- if err != nil {
- return nil, err
- }
- // When we set up a TCP connection for hijack, there could be long periods
- // of inactivity (a long running command with no output) that in certain
- // network setups may cause ECONNTIMEOUT, leaving the client in an unknown
- // state. Setting TCP KeepAlive on the socket connection will prohibit
- // ECONNTIMEOUT unless the socket connection truly is broken
- if tcpConn, ok := rawConn.(*net.TCPConn); ok {
- tcpConn.SetKeepAlive(true)
- tcpConn.SetKeepAlivePeriod(30 * time.Second)
- }
-
- colonPos := strings.LastIndex(addr, ":")
- if colonPos == -1 {
- colonPos = len(addr)
- }
- hostname := addr[:colonPos]
-
- // If no ServerName is set, infer the ServerName
- // from the hostname we're connecting to.
- if config.ServerName == "" {
- // Make a copy to avoid polluting argument or default.
- c := *config
- c.ServerName = hostname
- config = &c
- }
-
- conn := tls.Client(rawConn, config)
-
- if timeout == 0 {
- err = conn.Handshake()
- } else {
- go func() {
- errChannel <- conn.Handshake()
- }()
-
- err = <-errChannel
- }
-
- if err != nil {
- rawConn.Close()
- return nil, err
- }
-
- // This is Docker difference with standard's crypto/tls package: returned a
- // wrapper which holds both the TLS and raw connections.
- return &tlsClientCon{conn, rawConn}, nil
-}
-
-func (cli *DockerCli) dial() (net.Conn, error) {
- if cli.tlsConfig != nil && cli.proto != "unix" {
- // Notice this isn't Go standard's tls.Dial function
- return tlsDial(cli.proto, cli.addr, cli.tlsConfig)
- }
- return net.Dial(cli.proto, cli.addr)
-}
-
-func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.ReadCloser, stdout, stderr io.Writer, started chan io.Closer, data interface{}) error {
- defer func() {
- if started != nil {
- close(started)
- }
- }()
-
- params, err := cli.encodeData(data)
- if err != nil {
- return err
- }
- req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.APIVERSION, path), params)
- if err != nil {
- return err
- }
- req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION)
- req.Header.Set("Content-Type", "text/plain")
- req.Header.Set("Connection", "Upgrade")
- req.Header.Set("Upgrade", "tcp")
- req.Host = cli.addr
-
- dial, err := cli.dial()
- // When we set up a TCP connection for hijack, there could be long periods
- // of inactivity (a long running command with no output) that in certain
- // network setups may cause ECONNTIMEOUT, leaving the client in an unknown
- // state. Setting TCP KeepAlive on the socket connection will prohibit
- // ECONNTIMEOUT unless the socket connection truly is broken
- if tcpConn, ok := dial.(*net.TCPConn); ok {
- tcpConn.SetKeepAlive(true)
- tcpConn.SetKeepAlivePeriod(30 * time.Second)
- }
- if err != nil {
- if strings.Contains(err.Error(), "connection refused") {
- return fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?")
- }
- return err
- }
- clientconn := httputil.NewClientConn(dial, nil)
- defer clientconn.Close()
-
- // Server hijacks the connection, error 'connection closed' expected
- clientconn.Do(req)
-
- rwc, br := clientconn.Hijack()
- defer rwc.Close()
-
- if started != nil {
- started <- rwc
- }
-
- var receiveStdout chan error
-
- var oldState *term.State
-
- if in != nil && setRawTerminal && cli.isTerminalIn && os.Getenv("NORAW") == "" {
- oldState, err = term.SetRawTerminal(cli.inFd)
- if err != nil {
- return err
- }
- defer term.RestoreTerminal(cli.inFd, oldState)
- }
-
- if stdout != nil || stderr != nil {
- receiveStdout = promise.Go(func() (err error) {
- defer func() {
- if in != nil {
- if setRawTerminal && cli.isTerminalIn {
- term.RestoreTerminal(cli.inFd, oldState)
- }
- // For some reason this Close call blocks on darwin..
- // As the client exists right after, simply discard the close
- // until we find a better solution.
- if runtime.GOOS != "darwin" {
- in.Close()
- }
- }
- }()
-
- // When TTY is ON, use regular copy
- if setRawTerminal && stdout != nil {
- _, err = io.Copy(stdout, br)
- } else {
- _, err = stdcopy.StdCopy(stdout, stderr, br)
- }
- log.Debugf("[hijack] End of stdout")
- return err
- })
- }
-
- sendStdin := promise.Go(func() error {
- if in != nil {
- io.Copy(rwc, in)
- log.Debugf("[hijack] End of stdin")
- }
-
- if conn, ok := rwc.(interface {
- CloseWrite() error
- }); ok {
- if err := conn.CloseWrite(); err != nil {
- log.Debugf("Couldn't send EOF: %s", err)
- }
- }
- // Discard errors due to pipe interruption
- return nil
- })
-
- if stdout != nil || stderr != nil {
- if err := <-receiveStdout; err != nil {
- log.Debugf("Error receiveStdout: %s", err)
- return err
- }
- }
-
- if !cli.isTerminalIn {
- if err := <-sendStdin; err != nil {
- log.Debugf("Error sendStdin: %s", err)
- return err
- }
- }
- return nil
-}
diff --git a/Godeps/_workspace/src/github.com/docker/docker/api/client/utils.go b/Godeps/_workspace/src/github.com/docker/docker/api/client/utils.go
deleted file mode 100644
index 86e221ebf4..0000000000
--- a/Godeps/_workspace/src/github.com/docker/docker/api/client/utils.go
+++ /dev/null
@@ -1,296 +0,0 @@
-package client
-
-import (
- "bytes"
- "encoding/base64"
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "io/ioutil"
- "net/http"
- "net/url"
- "os"
- gosignal "os/signal"
- "strconv"
- "strings"
-
- log "github.com/Sirupsen/logrus"
- "github.com/docker/docker/api"
- "github.com/docker/docker/dockerversion"
- "github.com/docker/docker/engine"
- "github.com/docker/docker/pkg/signal"
- "github.com/docker/docker/pkg/stdcopy"
- "github.com/docker/docker/pkg/term"
- "github.com/docker/docker/registry"
- "github.com/docker/docker/utils"
-)
-
-var (
- ErrConnectionRefused = errors.New("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?")
-)
-
-func (cli *DockerCli) HTTPClient() *http.Client {
- return &http.Client{Transport: cli.transport}
-}
-
-func (cli *DockerCli) encodeData(data interface{}) (*bytes.Buffer, error) {
- params := bytes.NewBuffer(nil)
- if data != nil {
- if env, ok := data.(engine.Env); ok {
- if err := env.Encode(params); err != nil {
- return nil, err
- }
- } else {
- buf, err := json.Marshal(data)
- if err != nil {
- return nil, err
- }
- if _, err := params.Write(buf); err != nil {
- return nil, err
- }
- }
- }
- return params, nil
-}
-
-func (cli *DockerCli) call(method, path string, data interface{}, passAuthInfo bool) (io.ReadCloser, int, error) {
- params, err := cli.encodeData(data)
- if err != nil {
- return nil, -1, err
- }
- req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.APIVERSION, path), params)
- if err != nil {
- return nil, -1, err
- }
- if passAuthInfo {
- cli.LoadConfigFile()
- // Resolve the Auth config relevant for this server
- authConfig := cli.configFile.Configs[registry.IndexServerAddress()]
- getHeaders := func(authConfig registry.AuthConfig) (map[string][]string, error) {
- buf, err := json.Marshal(authConfig)
- if err != nil {
- return nil, err
- }
- registryAuthHeader := []string{
- base64.URLEncoding.EncodeToString(buf),
- }
- return map[string][]string{"X-Registry-Auth": registryAuthHeader}, nil
- }
- if headers, err := getHeaders(authConfig); err == nil && headers != nil {
- for k, v := range headers {
- req.Header[k] = v
- }
- }
- }
- req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION)
- req.URL.Host = cli.addr
- req.URL.Scheme = cli.scheme
- if data != nil {
- req.Header.Set("Content-Type", "application/json")
- } else if method == "POST" {
- req.Header.Set("Content-Type", "text/plain")
- }
- resp, err := cli.HTTPClient().Do(req)
- if err != nil {
- if strings.Contains(err.Error(), "connection refused") {
- return nil, -1, ErrConnectionRefused
- }
-
- if cli.tlsConfig == nil {
- return nil, -1, fmt.Errorf("%v. Are you trying to connect to a TLS-enabled daemon without TLS?", err)
- }
- return nil, -1, fmt.Errorf("An error occurred trying to connect: %v", err)
-
- }
-
- if resp.StatusCode < 200 || resp.StatusCode >= 400 {
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return nil, -1, err
- }
- if len(body) == 0 {
- return nil, resp.StatusCode, fmt.Errorf("Error: request returned %s for API route and version %s, check if the server supports the requested API version", http.StatusText(resp.StatusCode), req.URL)
- }
- return nil, resp.StatusCode, fmt.Errorf("Error response from daemon: %s", bytes.TrimSpace(body))
- }
-
- return resp.Body, resp.StatusCode, nil
-}
-
-func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer, headers map[string][]string) error {
- return cli.streamHelper(method, path, true, in, out, nil, headers)
-}
-
-func (cli *DockerCli) streamHelper(method, path string, setRawTerminal bool, in io.Reader, stdout, stderr io.Writer, headers map[string][]string) error {
- if (method == "POST" || method == "PUT") && in == nil {
- in = bytes.NewReader([]byte{})
- }
-
- req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.APIVERSION, path), in)
- if err != nil {
- return err
- }
- req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION)
- req.URL.Host = cli.addr
- req.URL.Scheme = cli.scheme
- if method == "POST" {
- req.Header.Set("Content-Type", "text/plain")
- }
-
- if headers != nil {
- for k, v := range headers {
- req.Header[k] = v
- }
- }
- resp, err := cli.HTTPClient().Do(req)
- if err != nil {
- if strings.Contains(err.Error(), "connection refused") {
- return fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?")
- }
- return err
- }
- defer resp.Body.Close()
-
- if resp.StatusCode < 200 || resp.StatusCode >= 400 {
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return err
- }
- if len(body) == 0 {
- return fmt.Errorf("Error :%s", http.StatusText(resp.StatusCode))
- }
- return fmt.Errorf("Error: %s", bytes.TrimSpace(body))
- }
-
- if api.MatchesContentType(resp.Header.Get("Content-Type"), "application/json") {
- return utils.DisplayJSONMessagesStream(resp.Body, stdout, cli.outFd, cli.isTerminalOut)
- }
- if stdout != nil || stderr != nil {
- // When TTY is ON, use regular copy
- if setRawTerminal {
- _, err = io.Copy(stdout, resp.Body)
- } else {
- _, err = stdcopy.StdCopy(stdout, stderr, resp.Body)
- }
- log.Debugf("[stream] End of stdout")
- return err
- }
- return nil
-}
-
-func (cli *DockerCli) resizeTty(id string, isExec bool) {
- height, width := cli.getTtySize()
- if height == 0 && width == 0 {
- return
- }
- v := url.Values{}
- v.Set("h", strconv.Itoa(height))
- v.Set("w", strconv.Itoa(width))
-
- path := ""
- if !isExec {
- path = "/containers/" + id + "/resize?"
- } else {
- path = "/exec/" + id + "/resize?"
- }
-
- if _, _, err := readBody(cli.call("POST", path+v.Encode(), nil, false)); err != nil {
- log.Debugf("Error resize: %s", err)
- }
-}
-
-func waitForExit(cli *DockerCli, containerId string) (int, error) {
- stream, _, err := cli.call("POST", "/containers/"+containerId+"/wait", nil, false)
- if err != nil {
- return -1, err
- }
-
- var out engine.Env
- if err := out.Decode(stream); err != nil {
- return -1, err
- }
- return out.GetInt("StatusCode"), nil
-}
-
-// getExitCode perform an inspect on the container. It returns
-// the running state and the exit code.
-func getExitCode(cli *DockerCli, containerId string) (bool, int, error) {
- stream, _, err := cli.call("GET", "/containers/"+containerId+"/json", nil, false)
- if err != nil {
- // If we can't connect, then the daemon probably died.
- if err != ErrConnectionRefused {
- return false, -1, err
- }
- return false, -1, nil
- }
-
- var result engine.Env
- if err := result.Decode(stream); err != nil {
- return false, -1, err
- }
-
- state := result.GetSubEnv("State")
- return state.GetBool("Running"), state.GetInt("ExitCode"), nil
-}
-
-// getExecExitCode perform an inspect on the exec command. It returns
-// the running state and the exit code.
-func getExecExitCode(cli *DockerCli, execId string) (bool, int, error) {
- stream, _, err := cli.call("GET", "/exec/"+execId+"/json", nil, false)
- if err != nil {
- // If we can't connect, then the daemon probably died.
- if err != ErrConnectionRefused {
- return false, -1, err
- }
- return false, -1, nil
- }
-
- var result engine.Env
- if err := result.Decode(stream); err != nil {
- return false, -1, err
- }
-
- return result.GetBool("Running"), result.GetInt("ExitCode"), nil
-}
-
-func (cli *DockerCli) monitorTtySize(id string, isExec bool) error {
- cli.resizeTty(id, isExec)
-
- sigchan := make(chan os.Signal, 1)
- gosignal.Notify(sigchan, signal.SIGWINCH)
- go func() {
- for _ = range sigchan {
- cli.resizeTty(id, isExec)
- }
- }()
- return nil
-}
-
-func (cli *DockerCli) getTtySize() (int, int) {
- if !cli.isTerminalOut {
- return 0, 0
- }
- ws, err := term.GetWinsize(cli.outFd)
- if err != nil {
- log.Debugf("Error getting size: %s", err)
- if ws == nil {
- return 0, 0
- }
- }
- return int(ws.Height), int(ws.Width)
-}
-
-func readBody(stream io.ReadCloser, statusCode int, err error) ([]byte, int, error) {
- if stream != nil {
- defer stream.Close()
- }
- if err != nil {
- return nil, statusCode, err
- }
- body, err := ioutil.ReadAll(stream)
- if err != nil {
- return nil, -1, err
- }
- return body, statusCode, nil
-}
diff --git a/Godeps/_workspace/src/github.com/docker/docker/api/common.go b/Godeps/_workspace/src/github.com/docker/docker/api/common.go
deleted file mode 100644
index 1bbb6d3937..0000000000
--- a/Godeps/_workspace/src/github.com/docker/docker/api/common.go
+++ /dev/null
@@ -1,75 +0,0 @@
-package api
-
-import (
- "fmt"
- "mime"
- "os"
- "path/filepath"
- "strings"
-
- log "github.com/Sirupsen/logrus"
- "github.com/docker/docker/engine"
- "github.com/docker/docker/pkg/parsers"
- "github.com/docker/docker/pkg/version"
- "github.com/docker/libtrust"
-)
-
-const (
- APIVERSION version.Version = "1.17"
- DEFAULTHTTPHOST = "127.0.0.1"
- DEFAULTUNIXSOCKET = "/var/run/docker.sock"
- DefaultDockerfileName string = "Dockerfile"
-)
-
-func ValidateHost(val string) (string, error) {
- host, err := parsers.ParseHost(DEFAULTHTTPHOST, DEFAULTUNIXSOCKET, val)
- if err != nil {
- return val, err
- }
- return host, nil
-}
-
-//TODO remove, used on < 1.5 in getContainersJSON
-func DisplayablePorts(ports *engine.Table) string {
- result := []string{}
- ports.SetKey("PublicPort")
- ports.Sort()
- for _, port := range ports.Data {
- if port.Get("IP") == "" {
- result = append(result, fmt.Sprintf("%d/%s", port.GetInt("PrivatePort"), port.Get("Type")))
- } else {
- result = append(result, fmt.Sprintf("%s:%d->%d/%s", port.Get("IP"), port.GetInt("PublicPort"), port.GetInt("PrivatePort"), port.Get("Type")))
- }
- }
- return strings.Join(result, ", ")
-}
-
-func MatchesContentType(contentType, expectedType string) bool {
- mimetype, _, err := mime.ParseMediaType(contentType)
- if err != nil {
- log.Errorf("Error parsing media type: %s error: %s", contentType, err.Error())
- }
- return err == nil && mimetype == expectedType
-}
-
-// LoadOrCreateTrustKey attempts to load the libtrust key at the given path,
-// otherwise generates a new one
-func LoadOrCreateTrustKey(trustKeyPath string) (libtrust.PrivateKey, error) {
- err := os.MkdirAll(filepath.Dir(trustKeyPath), 0700)
- if err != nil {
- return nil, err
- }
- trustKey, err := libtrust.LoadKeyFile(trustKeyPath)
- if err == libtrust.ErrKeyFileDoesNotExist {
- trustKey, err = libtrust.GenerateECP256PrivateKey()
- if err != nil {
- return nil, fmt.Errorf("Error generating key: %s", err)
- }
- if err := libtrust.SaveKey(trustKeyPath, trustKey); err != nil {
- return nil, fmt.Errorf("Error saving key file: %s", err)
- }
- } else if err != nil {
- return nil, fmt.Errorf("Error loading key file %s: %s", trustKeyPath, err)
- }
- return trustKey, nil
-}
diff --git a/Godeps/_workspace/src/github.com/docker/docker/api/server/MAINTAINERS b/Godeps/_workspace/src/github.com/docker/docker/api/server/MAINTAINERS
deleted file mode 100644
index dee1eec042..0000000000
--- a/Godeps/_workspace/src/github.com/docker/docker/api/server/MAINTAINERS
+++ /dev/null
@@ -1,2 +0,0 @@
-Victor Vieux (@vieux)
-# Johan Euphrosine (@proppy)
diff --git a/Godeps/_workspace/src/github.com/docker/docker/api/server/server.go b/Godeps/_workspace/src/github.com/docker/docker/api/server/server.go
deleted file mode 100644
index 9bb42f6c87..0000000000
--- a/Godeps/_workspace/src/github.com/docker/docker/api/server/server.go
+++ /dev/null
@@ -1,1653 +0,0 @@
-package server
-
-import (
- "bufio"
- "bytes"
-
- "encoding/base64"
- "encoding/json"
- "expvar"
- "fmt"
- "io"
- "io/ioutil"
- "net"
- "net/http"
- "net/http/pprof"
- "os"
- "strconv"
- "strings"
- "syscall"
-
- "crypto/tls"
- "crypto/x509"
-
- "code.google.com/p/go.net/websocket"
- "github.com/docker/libcontainer/user"
- "github.com/gorilla/mux"
-
- log "github.com/Sirupsen/logrus"
- "github.com/docker/docker/api"
- "github.com/docker/docker/daemon/networkdriver/portallocator"
- "github.com/docker/docker/engine"
- "github.com/docker/docker/pkg/listenbuffer"
- "github.com/docker/docker/pkg/parsers"
- "github.com/docker/docker/pkg/stdcopy"
- "github.com/docker/docker/pkg/systemd"
- "github.com/docker/docker/pkg/version"
- "github.com/docker/docker/registry"
- "github.com/docker/docker/utils"
-)
-
-var (
- activationLock chan struct{}
-)
-
-type HttpServer struct {
- srv *http.Server
- l net.Listener
-}
-
-func (s *HttpServer) Serve() error {
- return s.srv.Serve(s.l)
-}
-func (s *HttpServer) Close() error {
- return s.l.Close()
-}
-
-type HttpApiFunc func(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error
-
-func hijackServer(w http.ResponseWriter) (io.ReadCloser, io.Writer, error) {
- conn, _, err := w.(http.Hijacker).Hijack()
- if err != nil {
- return nil, nil, err
- }
- // Flush the options to make sure the client sets the raw mode
- conn.Write([]byte{})
- return conn, conn, nil
-}
-
-func closeStreams(streams ...interface{}) {
- for _, stream := range streams {
- if tcpc, ok := stream.(interface {
- CloseWrite() error
- }); ok {
- tcpc.CloseWrite()
- } else if closer, ok := stream.(io.Closer); ok {
- closer.Close()
- }
- }
-}
-
-// Check to make sure request's Content-Type is application/json
-func checkForJson(r *http.Request) error {
- ct := r.Header.Get("Content-Type")
-
- // No Content-Type header is ok as long as there's no Body
- if ct == "" {
- if r.Body == nil || r.ContentLength == 0 {
- return nil
- }
- }
-
- // Otherwise it better be json
- if api.MatchesContentType(ct, "application/json") {
- return nil
- }
- return fmt.Errorf("Content-Type specified (%s) must be 'application/json'", ct)
-}
-
-//If we don't do this, POST method without Content-type (even with empty body) will fail
-func parseForm(r *http.Request) error {
- if r == nil {
- return nil
- }
- if err := r.ParseForm(); err != nil && !strings.HasPrefix(err.Error(), "mime:") {
- return err
- }
- return nil
-}
-
-func parseMultipartForm(r *http.Request) error {
- if err := r.ParseMultipartForm(4096); err != nil && !strings.HasPrefix(err.Error(), "mime:") {
- return err
- }
- return nil
-}
-
-func httpError(w http.ResponseWriter, err error) {
- statusCode := http.StatusInternalServerError
- // FIXME: this is brittle and should not be necessary.
- // If we need to differentiate between different possible error types, we should
- // create appropriate error types with clearly defined meaning.
- errStr := strings.ToLower(err.Error())
- if strings.Contains(errStr, "no such") {
- statusCode = http.StatusNotFound
- } else if strings.Contains(errStr, "bad parameter") {
- statusCode = http.StatusBadRequest
- } else if strings.Contains(errStr, "conflict") {
- statusCode = http.StatusConflict
- } else if strings.Contains(errStr, "impossible") {
- statusCode = http.StatusNotAcceptable
- } else if strings.Contains(errStr, "wrong login/password") {
- statusCode = http.StatusUnauthorized
- } else if strings.Contains(errStr, "hasn't been activated") {
- statusCode = http.StatusForbidden
- }
-
- if err != nil {
- log.Errorf("HTTP Error: statusCode=%d %s", statusCode, err.Error())
- http.Error(w, err.Error(), statusCode)
- }
-}
-
-func writeJSON(w http.ResponseWriter, code int, v engine.Env) error {
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(code)
- return v.Encode(w)
-}
-
-func streamJSON(job *engine.Job, w http.ResponseWriter, flush bool) {
- w.Header().Set("Content-Type", "application/json")
- if flush {
- job.Stdout.Add(utils.NewWriteFlusher(w))
- } else {
- job.Stdout.Add(w)
- }
-}
-
-func getBoolParam(value string) (bool, error) {
- if value == "" {
- return false, nil
- }
- ret, err := strconv.ParseBool(value)
- if err != nil {
- return false, fmt.Errorf("Bad parameter")
- }
- return ret, nil
-}
-
-func postAuth(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- var (
- authConfig, err = ioutil.ReadAll(r.Body)
- job = eng.Job("auth")
- stdoutBuffer = bytes.NewBuffer(nil)
- )
- if err != nil {
- return err
- }
- job.Setenv("authConfig", string(authConfig))
- job.Stdout.Add(stdoutBuffer)
- if err = job.Run(); err != nil {
- return err
- }
- if status := engine.Tail(stdoutBuffer, 1); status != "" {
- var env engine.Env
- env.Set("Status", status)
- return writeJSON(w, http.StatusOK, env)
- }
- w.WriteHeader(http.StatusNoContent)
- return nil
-}
-
-func getVersion(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- w.Header().Set("Content-Type", "application/json")
- eng.ServeHTTP(w, r)
- return nil
-}
-
-func postContainersKill(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
- if err := parseForm(r); err != nil {
- return err
- }
- job := eng.Job("kill", vars["name"])
- if sig := r.Form.Get("signal"); sig != "" {
- job.Args = append(job.Args, sig)
- }
- if err := job.Run(); err != nil {
- return err
- }
- w.WriteHeader(http.StatusNoContent)
- return nil
-}
-
-func postContainersPause(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
- if err := parseForm(r); err != nil {
- return err
- }
- job := eng.Job("pause", vars["name"])
- if err := job.Run(); err != nil {
- return err
- }
- w.WriteHeader(http.StatusNoContent)
- return nil
-}
-
-func postContainersUnpause(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
- if err := parseForm(r); err != nil {
- return err
- }
- job := eng.Job("unpause", vars["name"])
- if err := job.Run(); err != nil {
- return err
- }
- w.WriteHeader(http.StatusNoContent)
- return nil
-}
-
-func getContainersExport(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
- job := eng.Job("export", vars["name"])
- job.Stdout.Add(w)
- if err := job.Run(); err != nil {
- return err
- }
- return nil
-}
-
-func getImagesJSON(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return err
- }
-
- var (
- err error
- outs *engine.Table
- job = eng.Job("images")
- )
-
- job.Setenv("filters", r.Form.Get("filters"))
- // FIXME this parameter could just be a match filter
- job.Setenv("filter", r.Form.Get("filter"))
- job.Setenv("all", r.Form.Get("all"))
-
- if version.GreaterThanOrEqualTo("1.7") {
- streamJSON(job, w, false)
- } else if outs, err = job.Stdout.AddListTable(); err != nil {
- return err
- }
-
- if err := job.Run(); err != nil {
- return err
- }
-
- if version.LessThan("1.7") && outs != nil { // Convert to legacy format
- outsLegacy := engine.NewTable("Created", 0)
- for _, out := range outs.Data {
- for _, repoTag := range out.GetList("RepoTags") {
- repo, tag := parsers.ParseRepositoryTag(repoTag)
- outLegacy := &engine.Env{}
- outLegacy.Set("Repository", repo)
- outLegacy.SetJson("Tag", tag)
- outLegacy.Set("Id", out.Get("Id"))
- outLegacy.SetInt64("Created", out.GetInt64("Created"))
- outLegacy.SetInt64("Size", out.GetInt64("Size"))
- outLegacy.SetInt64("VirtualSize", out.GetInt64("VirtualSize"))
- outsLegacy.Add(outLegacy)
- }
- }
- w.Header().Set("Content-Type", "application/json")
- if _, err := outsLegacy.WriteListTo(w); err != nil {
- return err
- }
- }
- return nil
-}
-
-func getImagesViz(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if version.GreaterThan("1.6") {
- w.WriteHeader(http.StatusNotFound)
- return fmt.Errorf("This is now implemented in the client.")
- }
- eng.ServeHTTP(w, r)
- return nil
-}
-
-func getInfo(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- w.Header().Set("Content-Type", "application/json")
- eng.ServeHTTP(w, r)
- return nil
-}
-
-func getEvents(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return err
- }
-
- var job = eng.Job("events")
- streamJSON(job, w, true)
- job.Setenv("since", r.Form.Get("since"))
- job.Setenv("until", r.Form.Get("until"))
- job.Setenv("filters", r.Form.Get("filters"))
- return job.Run()
-}
-
-func getImagesHistory(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
-
- var job = eng.Job("history", vars["name"])
- streamJSON(job, w, false)
-
- if err := job.Run(); err != nil {
- return err
- }
- return nil
-}
-
-func getContainersChanges(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
- var job = eng.Job("container_changes", vars["name"])
- streamJSON(job, w, false)
-
- return job.Run()
-}
-
-func getContainersTop(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if version.LessThan("1.4") {
- return fmt.Errorf("top was improved a lot since 1.3, Please upgrade your docker client.")
- }
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
- if err := parseForm(r); err != nil {
- return err
- }
-
- job := eng.Job("top", vars["name"], r.Form.Get("ps_args"))
- streamJSON(job, w, false)
- return job.Run()
-}
-
-func getContainersJSON(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return err
- }
- var (
- err error
- outs *engine.Table
- job = eng.Job("containers")
- )
-
- job.Setenv("all", r.Form.Get("all"))
- job.Setenv("size", r.Form.Get("size"))
- job.Setenv("since", r.Form.Get("since"))
- job.Setenv("before", r.Form.Get("before"))
- job.Setenv("limit", r.Form.Get("limit"))
- job.Setenv("filters", r.Form.Get("filters"))
-
- if version.GreaterThanOrEqualTo("1.5") {
- streamJSON(job, w, false)
- } else if outs, err = job.Stdout.AddTable(); err != nil {
- return err
- }
- if err = job.Run(); err != nil {
- return err
- }
- if version.LessThan("1.5") { // Convert to legacy format
- for _, out := range outs.Data {
- ports := engine.NewTable("", 0)
- ports.ReadListFrom([]byte(out.Get("Ports")))
- out.Set("Ports", api.DisplayablePorts(ports))
- }
- w.Header().Set("Content-Type", "application/json")
- if _, err = outs.WriteListTo(w); err != nil {
- return err
- }
- }
- return nil
-}
-
-func getContainersStats(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return err
- }
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
- name := vars["name"]
- job := eng.Job("container_stats", name)
- streamJSON(job, w, true)
- return job.Run()
-}
-
-func getContainersLogs(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return err
- }
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
-
- var (
- inspectJob = eng.Job("container_inspect", vars["name"])
- logsJob = eng.Job("logs", vars["name"])
- c, err = inspectJob.Stdout.AddEnv()
- )
- if err != nil {
- return err
- }
- logsJob.Setenv("follow", r.Form.Get("follow"))
- logsJob.Setenv("tail", r.Form.Get("tail"))
- logsJob.Setenv("stdout", r.Form.Get("stdout"))
- logsJob.Setenv("stderr", r.Form.Get("stderr"))
- logsJob.Setenv("timestamps", r.Form.Get("timestamps"))
- // Validate args here, because we can't return not StatusOK after job.Run() call
- stdout, stderr := logsJob.GetenvBool("stdout"), logsJob.GetenvBool("stderr")
- if !(stdout || stderr) {
- return fmt.Errorf("Bad parameters: you must choose at least one stream")
- }
- if err = inspectJob.Run(); err != nil {
- return err
- }
-
- var outStream, errStream io.Writer
- outStream = utils.NewWriteFlusher(w)
-
- if c.GetSubEnv("Config") != nil && !c.GetSubEnv("Config").GetBool("Tty") && version.GreaterThanOrEqualTo("1.6") {
- errStream = stdcopy.NewStdWriter(outStream, stdcopy.Stderr)
- outStream = stdcopy.NewStdWriter(outStream, stdcopy.Stdout)
- } else {
- errStream = outStream
- }
-
- logsJob.Stdout.Add(outStream)
- logsJob.Stderr.Set(errStream)
- if err := logsJob.Run(); err != nil {
- fmt.Fprintf(outStream, "Error running logs job: %s\n", err)
- }
- return nil
-}
-
-func postImagesTag(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return err
- }
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
-
- job := eng.Job("tag", vars["name"], r.Form.Get("repo"), r.Form.Get("tag"))
- job.Setenv("force", r.Form.Get("force"))
- if err := job.Run(); err != nil {
- return err
- }
- w.WriteHeader(http.StatusCreated)
- return nil
-}
-
-func postCommit(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return err
- }
- var (
- config engine.Env
- env engine.Env
- job = eng.Job("commit", r.Form.Get("container"))
- stdoutBuffer = bytes.NewBuffer(nil)
- )
-
- if err := checkForJson(r); err != nil {
- return err
- }
-
- if err := config.Decode(r.Body); err != nil {
- log.Errorf("%s", err)
- }
-
- if r.FormValue("pause") == "" && version.GreaterThanOrEqualTo("1.13") {
- job.Setenv("pause", "1")
- } else {
- job.Setenv("pause", r.FormValue("pause"))
- }
-
- job.Setenv("repo", r.Form.Get("repo"))
- job.Setenv("tag", r.Form.Get("tag"))
- job.Setenv("author", r.Form.Get("author"))
- job.Setenv("comment", r.Form.Get("comment"))
- job.SetenvSubEnv("config", &config)
-
- job.Stdout.Add(stdoutBuffer)
- if err := job.Run(); err != nil {
- return err
- }
- env.Set("Id", engine.Tail(stdoutBuffer, 1))
- return writeJSON(w, http.StatusCreated, env)
-}
-
-// Creates an image from Pull or from Import
-func postImagesCreate(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return err
- }
-
- var (
- image = r.Form.Get("fromImage")
- repo = r.Form.Get("repo")
- tag = r.Form.Get("tag")
- job *engine.Job
- )
- authEncoded := r.Header.Get("X-Registry-Auth")
- authConfig := ®istry.AuthConfig{}
- if authEncoded != "" {
- authJson := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
- if err := json.NewDecoder(authJson).Decode(authConfig); err != nil {
- // for a pull it is not an error if no auth was given
- // to increase compatibility with the existing api it is defaulting to be empty
- authConfig = ®istry.AuthConfig{}
- }
- }
- if image != "" { //pull
- if tag == "" {
- image, tag = parsers.ParseRepositoryTag(image)
- }
- metaHeaders := map[string][]string{}
- for k, v := range r.Header {
- if strings.HasPrefix(k, "X-Meta-") {
- metaHeaders[k] = v
- }
- }
- job = eng.Job("pull", image, tag)
- job.SetenvBool("parallel", version.GreaterThan("1.3"))
- job.SetenvJson("metaHeaders", metaHeaders)
- job.SetenvJson("authConfig", authConfig)
- } else { //import
- if tag == "" {
- repo, tag = parsers.ParseRepositoryTag(repo)
- }
- job = eng.Job("import", r.Form.Get("fromSrc"), repo, tag)
- job.Stdin.Add(r.Body)
- }
-
- if version.GreaterThan("1.0") {
- job.SetenvBool("json", true)
- streamJSON(job, w, true)
- } else {
- job.Stdout.Add(utils.NewWriteFlusher(w))
- }
- if err := job.Run(); err != nil {
- if !job.Stdout.Used() {
- return err
- }
- sf := utils.NewStreamFormatter(version.GreaterThan("1.0"))
- w.Write(sf.FormatError(err))
- }
-
- return nil
-}
-
-func getImagesSearch(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return err
- }
- var (
- authEncoded = r.Header.Get("X-Registry-Auth")
- authConfig = ®istry.AuthConfig{}
- metaHeaders = map[string][]string{}
- )
-
- if authEncoded != "" {
- authJson := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
- if err := json.NewDecoder(authJson).Decode(authConfig); err != nil {
- // for a search it is not an error if no auth was given
- // to increase compatibility with the existing api it is defaulting to be empty
- authConfig = ®istry.AuthConfig{}
- }
- }
- for k, v := range r.Header {
- if strings.HasPrefix(k, "X-Meta-") {
- metaHeaders[k] = v
- }
- }
-
- var job = eng.Job("search", r.Form.Get("term"))
- job.SetenvJson("metaHeaders", metaHeaders)
- job.SetenvJson("authConfig", authConfig)
- streamJSON(job, w, false)
-
- return job.Run()
-}
-
-func postImagesPush(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
-
- metaHeaders := map[string][]string{}
- for k, v := range r.Header {
- if strings.HasPrefix(k, "X-Meta-") {
- metaHeaders[k] = v
- }
- }
- if err := parseForm(r); err != nil {
- return err
- }
- authConfig := ®istry.AuthConfig{}
-
- authEncoded := r.Header.Get("X-Registry-Auth")
- if authEncoded != "" {
- // the new format is to handle the authConfig as a header
- authJson := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
- if err := json.NewDecoder(authJson).Decode(authConfig); err != nil {
- // to increase compatibility to existing api it is defaulting to be empty
- authConfig = ®istry.AuthConfig{}
- }
- } else {
- // the old format is supported for compatibility if there was no authConfig header
- if err := json.NewDecoder(r.Body).Decode(authConfig); err != nil {
- return err
- }
- }
-
- job := eng.Job("push", vars["name"])
- job.SetenvJson("metaHeaders", metaHeaders)
- job.SetenvJson("authConfig", authConfig)
- job.Setenv("tag", r.Form.Get("tag"))
- if version.GreaterThan("1.0") {
- job.SetenvBool("json", true)
- streamJSON(job, w, true)
- } else {
- job.Stdout.Add(utils.NewWriteFlusher(w))
- }
-
- if err := job.Run(); err != nil {
- if !job.Stdout.Used() {
- return err
- }
- sf := utils.NewStreamFormatter(version.GreaterThan("1.0"))
- w.Write(sf.FormatError(err))
- }
- return nil
-}
-
-func getImagesGet(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
- if err := parseForm(r); err != nil {
- return err
- }
- if version.GreaterThan("1.0") {
- w.Header().Set("Content-Type", "application/x-tar")
- }
- var job *engine.Job
- if name, ok := vars["name"]; ok {
- job = eng.Job("image_export", name)
- } else {
- job = eng.Job("image_export", r.Form["names"]...)
- }
- job.Stdout.Add(w)
- return job.Run()
-}
-
-func postImagesLoad(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- job := eng.Job("load")
- job.Stdin.Add(r.Body)
- return job.Run()
-}
-
-func postContainersCreate(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return nil
- }
- var (
- out engine.Env
- job = eng.Job("create", r.Form.Get("name"))
- outWarnings []string
- stdoutBuffer = bytes.NewBuffer(nil)
- warnings = bytes.NewBuffer(nil)
- )
-
- if err := checkForJson(r); err != nil {
- return err
- }
-
- if err := job.DecodeEnv(r.Body); err != nil {
- return err
- }
- // Read container ID from the first line of stdout
- job.Stdout.Add(stdoutBuffer)
- // Read warnings from stderr
- job.Stderr.Add(warnings)
- if err := job.Run(); err != nil {
- return err
- }
- // Parse warnings from stderr
- scanner := bufio.NewScanner(warnings)
- for scanner.Scan() {
- outWarnings = append(outWarnings, scanner.Text())
- }
- out.Set("Id", engine.Tail(stdoutBuffer, 1))
- out.SetList("Warnings", outWarnings)
-
- return writeJSON(w, http.StatusCreated, out)
-}
-
-func postContainersRestart(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return err
- }
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
- job := eng.Job("restart", vars["name"])
- job.Setenv("t", r.Form.Get("t"))
- if err := job.Run(); err != nil {
- return err
- }
- w.WriteHeader(http.StatusNoContent)
- return nil
-}
-
-func postContainerRename(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return err
- }
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
-
- newName := r.URL.Query().Get("name")
- job := eng.Job("container_rename", vars["name"], newName)
- job.Setenv("t", r.Form.Get("t"))
- if err := job.Run(); err != nil {
- return err
- }
- w.WriteHeader(http.StatusNoContent)
- return nil
-}
-
-func deleteContainers(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return err
- }
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
- job := eng.Job("rm", vars["name"])
-
- job.Setenv("forceRemove", r.Form.Get("force"))
-
- job.Setenv("removeVolume", r.Form.Get("v"))
- job.Setenv("removeLink", r.Form.Get("link"))
- if err := job.Run(); err != nil {
- return err
- }
- w.WriteHeader(http.StatusNoContent)
- return nil
-}
-
-func deleteImages(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return err
- }
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
- var job = eng.Job("image_delete", vars["name"])
- streamJSON(job, w, false)
- job.Setenv("force", r.Form.Get("force"))
- job.Setenv("noprune", r.Form.Get("noprune"))
-
- return job.Run()
-}
-
-func postContainersStart(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
- var (
- name = vars["name"]
- job = eng.Job("start", name)
- )
-
- // If contentLength is -1, we can assumed chunked encoding
- // or more technically that the length is unknown
- // http://golang.org/src/pkg/net/http/request.go#L139
- // net/http otherwise seems to swallow any headers related to chunked encoding
- // including r.TransferEncoding
- // allow a nil body for backwards compatibility
- if r.Body != nil && (r.ContentLength > 0 || r.ContentLength == -1) {
- if err := checkForJson(r); err != nil {
- return err
- }
-
- if err := job.DecodeEnv(r.Body); err != nil {
- return err
- }
- }
-
- if err := job.Run(); err != nil {
- if err.Error() == "Container already started" {
- w.WriteHeader(http.StatusNotModified)
- return nil
- }
- return err
- }
- w.WriteHeader(http.StatusNoContent)
- return nil
-}
-
-func postContainersStop(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return err
- }
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
- job := eng.Job("stop", vars["name"])
- job.Setenv("t", r.Form.Get("t"))
- if err := job.Run(); err != nil {
- if err.Error() == "Container already stopped" {
- w.WriteHeader(http.StatusNotModified)
- return nil
- }
- return err
- }
- w.WriteHeader(http.StatusNoContent)
- return nil
-}
-
-func postContainersWait(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
- var (
- env engine.Env
- stdoutBuffer = bytes.NewBuffer(nil)
- job = eng.Job("wait", vars["name"])
- )
- job.Stdout.Add(stdoutBuffer)
- if err := job.Run(); err != nil {
- return err
- }
-
- env.Set("StatusCode", engine.Tail(stdoutBuffer, 1))
- return writeJSON(w, http.StatusOK, env)
-}
-
-func postContainersResize(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return err
- }
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
- if err := eng.Job("resize", vars["name"], r.Form.Get("h"), r.Form.Get("w")).Run(); err != nil {
- return err
- }
- return nil
-}
-
-func postContainersAttach(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return err
- }
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
-
- var (
- job = eng.Job("container_inspect", vars["name"])
- c, err = job.Stdout.AddEnv()
- )
- if err != nil {
- return err
- }
- if err = job.Run(); err != nil {
- return err
- }
-
- inStream, outStream, err := hijackServer(w)
- if err != nil {
- return err
- }
- defer closeStreams(inStream, outStream)
-
- var errStream io.Writer
-
- if _, ok := r.Header["Upgrade"]; ok {
- fmt.Fprintf(outStream, "HTTP/1.1 101 UPGRADED\r\nContent-Type: application/vnd.docker.raw-stream\r\nConnection: Upgrade\r\nUpgrade: tcp\r\n\r\n")
- } else {
- fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
- }
-
- if c.GetSubEnv("Config") != nil && !c.GetSubEnv("Config").GetBool("Tty") && version.GreaterThanOrEqualTo("1.6") {
- errStream = stdcopy.NewStdWriter(outStream, stdcopy.Stderr)
- outStream = stdcopy.NewStdWriter(outStream, stdcopy.Stdout)
- } else {
- errStream = outStream
- }
-
- job = eng.Job("attach", vars["name"])
- job.Setenv("logs", r.Form.Get("logs"))
- job.Setenv("stream", r.Form.Get("stream"))
- job.Setenv("stdin", r.Form.Get("stdin"))
- job.Setenv("stdout", r.Form.Get("stdout"))
- job.Setenv("stderr", r.Form.Get("stderr"))
- job.Stdin.Add(inStream)
- job.Stdout.Add(outStream)
- job.Stderr.Set(errStream)
- if err := job.Run(); err != nil {
- fmt.Fprintf(outStream, "Error attaching: %s\n", err)
-
- }
- return nil
-}
-
-func wsContainersAttach(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return err
- }
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
-
- if err := eng.Job("container_inspect", vars["name"]).Run(); err != nil {
- return err
- }
-
- h := websocket.Handler(func(ws *websocket.Conn) {
- defer ws.Close()
- job := eng.Job("attach", vars["name"])
- job.Setenv("logs", r.Form.Get("logs"))
- job.Setenv("stream", r.Form.Get("stream"))
- job.Setenv("stdin", r.Form.Get("stdin"))
- job.Setenv("stdout", r.Form.Get("stdout"))
- job.Setenv("stderr", r.Form.Get("stderr"))
- job.Stdin.Add(ws)
- job.Stdout.Add(ws)
- job.Stderr.Set(ws)
- if err := job.Run(); err != nil {
- log.Errorf("Error attaching websocket: %s", err)
- }
- })
- h.ServeHTTP(w, r)
-
- return nil
-}
-
-func getContainersByName(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
- var job = eng.Job("container_inspect", vars["name"])
- if version.LessThan("1.12") {
- job.SetenvBool("raw", true)
- }
- streamJSON(job, w, false)
- return job.Run()
-}
-
-func getExecByID(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if vars == nil {
- return fmt.Errorf("Missing parameter 'id'")
- }
- var job = eng.Job("execInspect", vars["id"])
- streamJSON(job, w, false)
- return job.Run()
-}
-
-func getImagesByName(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
- var job = eng.Job("image_inspect", vars["name"])
- if version.LessThan("1.12") {
- job.SetenvBool("raw", true)
- }
- streamJSON(job, w, false)
- return job.Run()
-}
-
-func postBuild(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if version.LessThan("1.3") {
- return fmt.Errorf("Multipart upload for build is no longer supported. Please upgrade your docker client.")
- }
- var (
- authEncoded = r.Header.Get("X-Registry-Auth")
- authConfig = ®istry.AuthConfig{}
- configFileEncoded = r.Header.Get("X-Registry-Config")
- configFile = ®istry.ConfigFile{}
- job = eng.Job("build")
- )
-
- // This block can be removed when API versions prior to 1.9 are deprecated.
- // Both headers will be parsed and sent along to the daemon, but if a non-empty
- // ConfigFile is present, any value provided as an AuthConfig directly will
- // be overridden. See BuildFile::CmdFrom for details.
- if version.LessThan("1.9") && authEncoded != "" {
- authJson := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
- if err := json.NewDecoder(authJson).Decode(authConfig); err != nil {
- // for a pull it is not an error if no auth was given
- // to increase compatibility with the existing api it is defaulting to be empty
- authConfig = ®istry.AuthConfig{}
- }
- }
-
- if configFileEncoded != "" {
- configFileJson := base64.NewDecoder(base64.URLEncoding, strings.NewReader(configFileEncoded))
- if err := json.NewDecoder(configFileJson).Decode(configFile); err != nil {
- // for a pull it is not an error if no auth was given
- // to increase compatibility with the existing api it is defaulting to be empty
- configFile = ®istry.ConfigFile{}
- }
- }
-
- if version.GreaterThanOrEqualTo("1.8") {
- job.SetenvBool("json", true)
- streamJSON(job, w, true)
- } else {
- job.Stdout.Add(utils.NewWriteFlusher(w))
- }
-
- if r.FormValue("forcerm") == "1" && version.GreaterThanOrEqualTo("1.12") {
- job.Setenv("rm", "1")
- } else if r.FormValue("rm") == "" && version.GreaterThanOrEqualTo("1.12") {
- job.Setenv("rm", "1")
- } else {
- job.Setenv("rm", r.FormValue("rm"))
- }
- if r.FormValue("pull") == "1" && version.GreaterThanOrEqualTo("1.16") {
- job.Setenv("pull", "1")
- }
- job.Stdin.Add(r.Body)
- job.Setenv("remote", r.FormValue("remote"))
- job.Setenv("dockerfile", r.FormValue("dockerfile"))
- job.Setenv("t", r.FormValue("t"))
- job.Setenv("q", r.FormValue("q"))
- job.Setenv("nocache", r.FormValue("nocache"))
- job.Setenv("forcerm", r.FormValue("forcerm"))
- job.SetenvJson("authConfig", authConfig)
- job.SetenvJson("configFile", configFile)
-
- if err := job.Run(); err != nil {
- if !job.Stdout.Used() {
- return err
- }
- sf := utils.NewStreamFormatter(version.GreaterThanOrEqualTo("1.8"))
- w.Write(sf.FormatError(err))
- }
- return nil
-}
-
-func postContainersCopy(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
-
- var copyData engine.Env
-
- if err := checkForJson(r); err != nil {
- return err
- }
-
- if err := copyData.Decode(r.Body); err != nil {
- return err
- }
-
- if copyData.Get("Resource") == "" {
- return fmt.Errorf("Path cannot be empty")
- }
-
- origResource := copyData.Get("Resource")
-
- if copyData.Get("Resource")[0] == '/' {
- copyData.Set("Resource", copyData.Get("Resource")[1:])
- }
-
- job := eng.Job("container_copy", vars["name"], copyData.Get("Resource"))
- job.Stdout.Add(w)
- w.Header().Set("Content-Type", "application/x-tar")
- if err := job.Run(); err != nil {
- log.Errorf("%s", err.Error())
- if strings.Contains(strings.ToLower(err.Error()), "no such container") {
- w.WriteHeader(http.StatusNotFound)
- } else if strings.Contains(err.Error(), "no such file or directory") {
- return fmt.Errorf("Could not find the file %s in container %s", origResource, vars["name"])
- }
- }
- return nil
-}
-
-func postContainerExecCreate(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return nil
- }
- var (
- out engine.Env
- name = vars["name"]
- job = eng.Job("execCreate", name)
- stdoutBuffer = bytes.NewBuffer(nil)
- )
-
- if err := job.DecodeEnv(r.Body); err != nil {
- return err
- }
-
- job.Stdout.Add(stdoutBuffer)
- // Register an instance of Exec in container.
- if err := job.Run(); err != nil {
- fmt.Fprintf(os.Stderr, "Error setting up exec command in container %s: %s\n", name, err)
- return err
- }
- // Return the ID
- out.Set("Id", engine.Tail(stdoutBuffer, 1))
-
- return writeJSON(w, http.StatusCreated, out)
-}
-
-// TODO(vishh): Refactor the code to avoid having to specify stream config as part of both create and start.
-func postContainerExecStart(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return nil
- }
- var (
- name = vars["name"]
- job = eng.Job("execStart", name)
- errOut io.Writer = os.Stderr
- )
-
- if err := job.DecodeEnv(r.Body); err != nil {
- return err
- }
- if !job.GetenvBool("Detach") {
- // Setting up the streaming http interface.
- inStream, outStream, err := hijackServer(w)
- if err != nil {
- return err
- }
- defer closeStreams(inStream, outStream)
-
- var errStream io.Writer
-
- if _, ok := r.Header["Upgrade"]; ok {
- fmt.Fprintf(outStream, "HTTP/1.1 101 UPGRADED\r\nContent-Type: application/vnd.docker.raw-stream\r\nConnection: Upgrade\r\nUpgrade: tcp\r\n\r\n")
- } else {
- fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
- }
-
- if !job.GetenvBool("Tty") && version.GreaterThanOrEqualTo("1.6") {
- errStream = stdcopy.NewStdWriter(outStream, stdcopy.Stderr)
- outStream = stdcopy.NewStdWriter(outStream, stdcopy.Stdout)
- } else {
- errStream = outStream
- }
- job.Stdin.Add(inStream)
- job.Stdout.Add(outStream)
- job.Stderr.Set(errStream)
- errOut = outStream
- }
- // Now run the user process in container.
- job.SetCloseIO(false)
- if err := job.Run(); err != nil {
- fmt.Fprintf(errOut, "Error starting exec command in container %s: %s\n", name, err)
- return err
- }
- w.WriteHeader(http.StatusNoContent)
-
- return nil
-}
-
-func postContainerExecResize(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- if err := parseForm(r); err != nil {
- return err
- }
- if vars == nil {
- return fmt.Errorf("Missing parameter")
- }
- if err := eng.Job("execResize", vars["name"], r.Form.Get("h"), r.Form.Get("w")).Run(); err != nil {
- return err
- }
- return nil
-}
-
-func optionsHandler(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- w.WriteHeader(http.StatusOK)
- return nil
-}
-func writeCorsHeaders(w http.ResponseWriter, r *http.Request) {
- w.Header().Add("Access-Control-Allow-Origin", "*")
- w.Header().Add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Registry-Auth")
- w.Header().Add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS")
-}
-
-func ping(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- _, err := w.Write([]byte{'O', 'K'})
- return err
-}
-
-func makeHttpHandler(eng *engine.Engine, logging bool, localMethod string, localRoute string, handlerFunc HttpApiFunc, enableCors bool, dockerVersion version.Version) http.HandlerFunc {
- return func(w http.ResponseWriter, r *http.Request) {
- // log the request
- log.Debugf("Calling %s %s", localMethod, localRoute)
-
- if logging {
- log.Infof("%s %s", r.Method, r.RequestURI)
- }
-
- if strings.Contains(r.Header.Get("User-Agent"), "Docker-Client/") {
- userAgent := strings.Split(r.Header.Get("User-Agent"), "/")
- if len(userAgent) == 2 && !dockerVersion.Equal(version.Version(userAgent[1])) {
- log.Debugf("Warning: client and server don't have the same version (client: %s, server: %s)", userAgent[1], dockerVersion)
- }
- }
- version := version.Version(mux.Vars(r)["version"])
- if version == "" {
- version = api.APIVERSION
- }
- if enableCors {
- writeCorsHeaders(w, r)
- }
-
- if version.GreaterThan(api.APIVERSION) {
- http.Error(w, fmt.Errorf("client and server don't have same version (client : %s, server: %s)", version, api.APIVERSION).Error(), http.StatusNotFound)
- return
- }
-
- if err := handlerFunc(eng, version, w, r, mux.Vars(r)); err != nil {
- log.Errorf("Handler for %s %s returned error: %s", localMethod, localRoute, err)
- httpError(w, err)
- }
- }
-}
-
-// Replicated from expvar.go as not public.
-func expvarHandler(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json; charset=utf-8")
- fmt.Fprintf(w, "{\n")
- first := true
- expvar.Do(func(kv expvar.KeyValue) {
- if !first {
- fmt.Fprintf(w, ",\n")
- }
- first = false
- fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value)
- })
- fmt.Fprintf(w, "\n}\n")
-}
-
-func AttachProfiler(router *mux.Router) {
- router.HandleFunc("/debug/vars", expvarHandler)
- router.HandleFunc("/debug/pprof/", pprof.Index)
- router.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
- router.HandleFunc("/debug/pprof/profile", pprof.Profile)
- router.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
- router.HandleFunc("/debug/pprof/block", pprof.Handler("block").ServeHTTP)
- router.HandleFunc("/debug/pprof/heap", pprof.Handler("heap").ServeHTTP)
- router.HandleFunc("/debug/pprof/goroutine", pprof.Handler("goroutine").ServeHTTP)
- router.HandleFunc("/debug/pprof/threadcreate", pprof.Handler("threadcreate").ServeHTTP)
-}
-
-func createRouter(eng *engine.Engine, logging, enableCors bool, dockerVersion string) *mux.Router {
- r := mux.NewRouter()
- if os.Getenv("DEBUG") != "" {
- AttachProfiler(r)
- }
- m := map[string]map[string]HttpApiFunc{
- "GET": {
- "/_ping": ping,
- "/events": getEvents,
- "/info": getInfo,
- "/version": getVersion,
- "/images/json": getImagesJSON,
- "/images/viz": getImagesViz,
- "/images/search": getImagesSearch,
- "/images/get": getImagesGet,
- "/images/{name:.*}/get": getImagesGet,
- "/images/{name:.*}/history": getImagesHistory,
- "/images/{name:.*}/json": getImagesByName,
- "/containers/ps": getContainersJSON,
- "/containers/json": getContainersJSON,
- "/containers/{name:.*}/export": getContainersExport,
- "/containers/{name:.*}/changes": getContainersChanges,
- "/containers/{name:.*}/json": getContainersByName,
- "/containers/{name:.*}/top": getContainersTop,
- "/containers/{name:.*}/logs": getContainersLogs,
- "/containers/{name:.*}/stats": getContainersStats,
- "/containers/{name:.*}/attach/ws": wsContainersAttach,
- "/exec/{id:.*}/json": getExecByID,
- },
- "POST": {
- "/auth": postAuth,
- "/commit": postCommit,
- "/build": postBuild,
- "/images/create": postImagesCreate,
- "/images/load": postImagesLoad,
- "/images/{name:.*}/push": postImagesPush,
- "/images/{name:.*}/tag": postImagesTag,
- "/containers/create": postContainersCreate,
- "/containers/{name:.*}/kill": postContainersKill,
- "/containers/{name:.*}/pause": postContainersPause,
- "/containers/{name:.*}/unpause": postContainersUnpause,
- "/containers/{name:.*}/restart": postContainersRestart,
- "/containers/{name:.*}/start": postContainersStart,
- "/containers/{name:.*}/stop": postContainersStop,
- "/containers/{name:.*}/wait": postContainersWait,
- "/containers/{name:.*}/resize": postContainersResize,
- "/containers/{name:.*}/attach": postContainersAttach,
- "/containers/{name:.*}/copy": postContainersCopy,
- "/containers/{name:.*}/exec": postContainerExecCreate,
- "/exec/{name:.*}/start": postContainerExecStart,
- "/exec/{name:.*}/resize": postContainerExecResize,
- "/containers/{name:.*}/rename": postContainerRename,
- },
- "DELETE": {
- "/containers/{name:.*}": deleteContainers,
- "/images/{name:.*}": deleteImages,
- },
- "OPTIONS": {
- "": optionsHandler,
- },
- }
-
- for method, routes := range m {
- for route, fct := range routes {
- log.Debugf("Registering %s, %s", method, route)
- // NOTE: scope issue, make sure the variables are local and won't be changed
- localRoute := route
- localFct := fct
- localMethod := method
-
- // build the handler function
- f := makeHttpHandler(eng, logging, localMethod, localRoute, localFct, enableCors, version.Version(dockerVersion))
-
- // add the new route
- if localRoute == "" {
- r.Methods(localMethod).HandlerFunc(f)
- } else {
- r.Path("/v{version:[0-9.]+}" + localRoute).Methods(localMethod).HandlerFunc(f)
- r.Path(localRoute).Methods(localMethod).HandlerFunc(f)
- }
- }
- }
-
- return r
-}
-
-// ServeRequest processes a single http request to the docker remote api.
-// FIXME: refactor this to be part of Server and not require re-creating a new
-// router each time. This requires first moving ListenAndServe into Server.
-func ServeRequest(eng *engine.Engine, apiversion version.Version, w http.ResponseWriter, req *http.Request) {
- router := createRouter(eng, false, true, "")
- // Insert APIVERSION into the request as a convenience
- req.URL.Path = fmt.Sprintf("/v%s%s", apiversion, req.URL.Path)
- router.ServeHTTP(w, req)
-}
-
-// serveFd creates an http.Server and sets it up to serve given a socket activated
-// argument.
-func serveFd(addr string, job *engine.Job) error {
- r := createRouter(job.Eng, job.GetenvBool("Logging"), job.GetenvBool("EnableCors"), job.Getenv("Version"))
-
- ls, e := systemd.ListenFD(addr)
- if e != nil {
- return e
- }
-
- chErrors := make(chan error, len(ls))
-
- // We don't want to start serving on these sockets until the
- // daemon is initialized and installed. Otherwise required handlers
- // won't be ready.
- <-activationLock
-
- // Since ListenFD will return one or more sockets we have
- // to create a go func to spawn off multiple serves
- for i := range ls {
- listener := ls[i]
- go func() {
- httpSrv := http.Server{Handler: r}
- chErrors <- httpSrv.Serve(listener)
- }()
- }
-
- for i := 0; i < len(ls); i++ {
- err := <-chErrors
- if err != nil {
- return err
- }
- }
-
- return nil
-}
-
-func lookupGidByName(nameOrGid string) (int, error) {
- groupFile, err := user.GetGroupPath()
- if err != nil {
- return -1, err
- }
- groups, err := user.ParseGroupFileFilter(groupFile, func(g user.Group) bool {
- return g.Name == nameOrGid || strconv.Itoa(g.Gid) == nameOrGid
- })
- if err != nil {
- return -1, err
- }
- if groups != nil && len(groups) > 0 {
- return groups[0].Gid, nil
- }
- return -1, fmt.Errorf("Group %s not found", nameOrGid)
-}
-
-func setupTls(cert, key, ca string, l net.Listener) (net.Listener, error) {
- tlsCert, err := tls.LoadX509KeyPair(cert, key)
- if err != nil {
- return nil, fmt.Errorf("Couldn't load X509 key pair (%s, %s): %s. Key encrypted?",
- cert, key, err)
- }
- tlsConfig := &tls.Config{
- NextProtos: []string{"http/1.1"},
- Certificates: []tls.Certificate{tlsCert},
- // Avoid fallback on insecure SSL protocols
- MinVersion: tls.VersionTLS10,
- }
-
- if ca != "" {
- certPool := x509.NewCertPool()
- file, err := ioutil.ReadFile(ca)
- if err != nil {
- return nil, fmt.Errorf("Couldn't read CA certificate: %s", err)
- }
- certPool.AppendCertsFromPEM(file)
- tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
- tlsConfig.ClientCAs = certPool
- }
-
- return tls.NewListener(l, tlsConfig), nil
-}
-
-func newListener(proto, addr string, bufferRequests bool) (net.Listener, error) {
- if bufferRequests {
- return listenbuffer.NewListenBuffer(proto, addr, activationLock)
- }
-
- return net.Listen(proto, addr)
-}
-
-func changeGroup(addr string, nameOrGid string) error {
- gid, err := lookupGidByName(nameOrGid)
- if err != nil {
- return err
- }
-
- log.Debugf("%s group found. gid: %d", nameOrGid, gid)
- return os.Chown(addr, 0, gid)
-}
-
-func setSocketGroup(addr, group string) error {
- if group == "" {
- return nil
- }
-
- if err := changeGroup(addr, group); err != nil {
- if group != "docker" {
- return err
- }
- log.Debugf("Warning: could not chgrp %s to docker: %v", addr, err)
- }
-
- return nil
-}
-
-func setupUnixHttp(addr string, job *engine.Job) (*HttpServer, error) {
- r := createRouter(job.Eng, job.GetenvBool("Logging"), job.GetenvBool("EnableCors"), job.Getenv("Version"))
-
- if err := syscall.Unlink(addr); err != nil && !os.IsNotExist(err) {
- return nil, err
- }
- mask := syscall.Umask(0777)
- defer syscall.Umask(mask)
-
- l, err := newListener("unix", addr, job.GetenvBool("BufferRequests"))
- if err != nil {
- return nil, err
- }
-
- if err := setSocketGroup(addr, job.Getenv("SocketGroup")); err != nil {
- return nil, err
- }
-
- if err := os.Chmod(addr, 0660); err != nil {
- return nil, err
- }
-
- return &HttpServer{&http.Server{Addr: addr, Handler: r}, l}, nil
-}
-
-func allocateDaemonPort(addr string) error {
- host, port, err := net.SplitHostPort(addr)
- if err != nil {
- return err
- }
-
- intPort, err := strconv.Atoi(port)
- if err != nil {
- return err
- }
-
- var hostIPs []net.IP
- if parsedIP := net.ParseIP(host); parsedIP != nil {
- hostIPs = append(hostIPs, parsedIP)
- } else if hostIPs, err = net.LookupIP(host); err != nil {
- return fmt.Errorf("failed to lookup %s address in host specification", host)
- }
-
- for _, hostIP := range hostIPs {
- if _, err := portallocator.RequestPort(hostIP, "tcp", intPort); err != nil {
- return fmt.Errorf("failed to allocate daemon listening port %d (err: %v)", intPort, err)
- }
- }
- return nil
-}
-
-func setupTcpHttp(addr string, job *engine.Job) (*HttpServer, error) {
- if !strings.HasPrefix(addr, "127.0.0.1") && !job.GetenvBool("TlsVerify") {
- log.Infof("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
- }
-
- r := createRouter(job.Eng, job.GetenvBool("Logging"), job.GetenvBool("EnableCors"), job.Getenv("Version"))
-
- l, err := newListener("tcp", addr, job.GetenvBool("BufferRequests"))
- if err != nil {
- return nil, err
- }
-
- if err := allocateDaemonPort(addr); err != nil {
- return nil, err
- }
-
- if job.GetenvBool("Tls") || job.GetenvBool("TlsVerify") {
- var tlsCa string
- if job.GetenvBool("TlsVerify") {
- tlsCa = job.Getenv("TlsCa")
- }
- l, err = setupTls(job.Getenv("TlsCert"), job.Getenv("TlsKey"), tlsCa, l)
- if err != nil {
- return nil, err
- }
- }
- return &HttpServer{&http.Server{Addr: addr, Handler: r}, l}, nil
-}
-
-// NewServer sets up the required Server and does protocol specific checking.
-func NewServer(proto, addr string, job *engine.Job) (Server, error) {
- // Basic error and sanity checking
- switch proto {
- case "fd":
- return nil, serveFd(addr, job)
- case "tcp":
- return setupTcpHttp(addr, job)
- case "unix":
- return setupUnixHttp(addr, job)
- default:
- return nil, fmt.Errorf("Invalid protocol format.")
- }
-}
-
-type Server interface {
- Serve() error
- Close() error
-}
-
-// ServeApi loops through all of the protocols sent in to docker and spawns
-// off a go routine to setup a serving http.Server for each.
-func ServeApi(job *engine.Job) engine.Status {
- if len(job.Args) == 0 {
- return job.Errorf("usage: %s PROTO://ADDR [PROTO://ADDR ...]", job.Name)
- }
- var (
- protoAddrs = job.Args
- chErrors = make(chan error, len(protoAddrs))
- )
- activationLock = make(chan struct{})
-
- for _, protoAddr := range protoAddrs {
- protoAddrParts := strings.SplitN(protoAddr, "://", 2)
- if len(protoAddrParts) != 2 {
- return job.Errorf("usage: %s PROTO://ADDR [PROTO://ADDR ...]", job.Name)
- }
- go func() {
- log.Infof("Listening for HTTP on %s (%s)", protoAddrParts[0], protoAddrParts[1])
- srv, err := NewServer(protoAddrParts[0], protoAddrParts[1], job)
- if err != nil {
- chErrors <- err
- return
- }
- chErrors <- srv.Serve()
- }()
- }
-
- for i := 0; i < len(protoAddrs); i++ {
- err := <-chErrors
- if err != nil {
- return job.Error(err)
- }
- }
-
- return engine.StatusOK
-}
-
-func AcceptConnections(job *engine.Job) engine.Status {
- // Tell the init daemon we are accepting requests
- go systemd.SdNotify("READY=1")
-
- // close the lock so the listeners start accepting connections
- if activationLock != nil {
- close(activationLock)
- }
-
- return engine.StatusOK
-}
diff --git a/Godeps/_workspace/src/github.com/docker/docker/api/server/server_unit_test.go b/Godeps/_workspace/src/github.com/docker/docker/api/server/server_unit_test.go
deleted file mode 100644
index b5ec7c8964..0000000000
--- a/Godeps/_workspace/src/github.com/docker/docker/api/server/server_unit_test.go
+++ /dev/null
@@ -1,553 +0,0 @@
-package server
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "io"
- "net/http"
- "net/http/httptest"
- "reflect"
- "strings"
- "testing"
-
- "github.com/docker/docker/api"
- "github.com/docker/docker/engine"
- "github.com/docker/docker/pkg/version"
-)
-
-func TestGetBoolParam(t *testing.T) {
- if ret, err := getBoolParam("true"); err != nil || !ret {
- t.Fatalf("true -> true, nil | got %t %s", ret, err)
- }
- if ret, err := getBoolParam("True"); err != nil || !ret {
- t.Fatalf("True -> true, nil | got %t %s", ret, err)
- }
- if ret, err := getBoolParam("1"); err != nil || !ret {
- t.Fatalf("1 -> true, nil | got %t %s", ret, err)
- }
- if ret, err := getBoolParam(""); err != nil || ret {
- t.Fatalf("\"\" -> false, nil | got %t %s", ret, err)
- }
- if ret, err := getBoolParam("false"); err != nil || ret {
- t.Fatalf("false -> false, nil | got %t %s", ret, err)
- }
- if ret, err := getBoolParam("0"); err != nil || ret {
- t.Fatalf("0 -> false, nil | got %t %s", ret, err)
- }
- if ret, err := getBoolParam("faux"); err == nil || ret {
- t.Fatalf("faux -> false, err | got %t %s", ret, err)
-
- }
-}
-
-func TesthttpError(t *testing.T) {
- r := httptest.NewRecorder()
-
- httpError(r, fmt.Errorf("No such method"))
- if r.Code != http.StatusNotFound {
- t.Fatalf("Expected %d, got %d", http.StatusNotFound, r.Code)
- }
-
- httpError(r, fmt.Errorf("This accound hasn't been activated"))
- if r.Code != http.StatusForbidden {
- t.Fatalf("Expected %d, got %d", http.StatusForbidden, r.Code)
- }
-
- httpError(r, fmt.Errorf("Some error"))
- if r.Code != http.StatusInternalServerError {
- t.Fatalf("Expected %d, got %d", http.StatusInternalServerError, r.Code)
- }
-}
-
-func TestGetVersion(t *testing.T) {
- eng := engine.New()
- var called bool
- eng.Register("version", func(job *engine.Job) engine.Status {
- called = true
- v := &engine.Env{}
- v.SetJson("Version", "42.1")
- v.Set("ApiVersion", "1.1.1.1.1")
- v.Set("GoVersion", "2.42")
- v.Set("Os", "Linux")
- v.Set("Arch", "x86_64")
- if _, err := v.WriteTo(job.Stdout); err != nil {
- return job.Error(err)
- }
- return engine.StatusOK
- })
- r := serveRequest("GET", "/version", nil, eng, t)
- if !called {
- t.Fatalf("handler was not called")
- }
- v := readEnv(r.Body, t)
- if v.Get("Version") != "42.1" {
- t.Fatalf("%#v\n", v)
- }
- if r.HeaderMap.Get("Content-Type") != "application/json" {
- t.Fatalf("%#v\n", r)
- }
-}
-
-func TestGetInfo(t *testing.T) {
- eng := engine.New()
- var called bool
- eng.Register("info", func(job *engine.Job) engine.Status {
- called = true
- v := &engine.Env{}
- v.SetInt("Containers", 1)
- v.SetInt("Images", 42000)
- if _, err := v.WriteTo(job.Stdout); err != nil {
- return job.Error(err)
- }
- return engine.StatusOK
- })
- r := serveRequest("GET", "/info", nil, eng, t)
- if !called {
- t.Fatalf("handler was not called")
- }
- v := readEnv(r.Body, t)
- if v.GetInt("Images") != 42000 {
- t.Fatalf("%#v\n", v)
- }
- if v.GetInt("Containers") != 1 {
- t.Fatalf("%#v\n", v)
- }
- assertContentType(r, "application/json", t)
-}
-
-func TestGetImagesJSON(t *testing.T) {
- eng := engine.New()
- var called bool
- eng.Register("images", func(job *engine.Job) engine.Status {
- called = true
- v := createEnvFromGetImagesJSONStruct(sampleImage)
- if _, err := v.WriteTo(job.Stdout); err != nil {
- return job.Error(err)
- }
- return engine.StatusOK
- })
- r := serveRequest("GET", "/images/json", nil, eng, t)
- if !called {
- t.Fatal("handler was not called")
- }
- assertHttpNotError(r, t)
- assertContentType(r, "application/json", t)
- var observed getImagesJSONStruct
- if err := json.Unmarshal(r.Body.Bytes(), &observed); err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(observed, sampleImage) {
- t.Errorf("Expected %#v but got %#v", sampleImage, observed)
- }
-}
-
-func TestGetImagesJSONFilter(t *testing.T) {
- eng := engine.New()
- filter := "nothing"
- eng.Register("images", func(job *engine.Job) engine.Status {
- filter = job.Getenv("filter")
- return engine.StatusOK
- })
- serveRequest("GET", "/images/json?filter=aaaa", nil, eng, t)
- if filter != "aaaa" {
- t.Errorf("%#v", filter)
- }
-}
-
-func TestGetImagesJSONFilters(t *testing.T) {
- eng := engine.New()
- filter := "nothing"
- eng.Register("images", func(job *engine.Job) engine.Status {
- filter = job.Getenv("filters")
- return engine.StatusOK
- })
- serveRequest("GET", "/images/json?filters=nnnn", nil, eng, t)
- if filter != "nnnn" {
- t.Errorf("%#v", filter)
- }
-}
-
-func TestGetImagesJSONAll(t *testing.T) {
- eng := engine.New()
- allFilter := "-1"
- eng.Register("images", func(job *engine.Job) engine.Status {
- allFilter = job.Getenv("all")
- return engine.StatusOK
- })
- serveRequest("GET", "/images/json?all=1", nil, eng, t)
- if allFilter != "1" {
- t.Errorf("%#v", allFilter)
- }
-}
-
-func TestGetImagesJSONLegacyFormat(t *testing.T) {
- eng := engine.New()
- var called bool
- eng.Register("images", func(job *engine.Job) engine.Status {
- called = true
- outsLegacy := engine.NewTable("Created", 0)
- outsLegacy.Add(createEnvFromGetImagesJSONStruct(sampleImage))
- if _, err := outsLegacy.WriteListTo(job.Stdout); err != nil {
- return job.Error(err)
- }
- return engine.StatusOK
- })
- r := serveRequestUsingVersion("GET", "/images/json", "1.6", nil, eng, t)
- if !called {
- t.Fatal("handler was not called")
- }
- assertHttpNotError(r, t)
- assertContentType(r, "application/json", t)
- images := engine.NewTable("Created", 0)
- if _, err := images.ReadListFrom(r.Body.Bytes()); err != nil {
- t.Fatal(err)
- }
- if images.Len() != 1 {
- t.Fatalf("Expected 1 image, %d found", images.Len())
- }
- image := images.Data[0]
- if image.Get("Tag") != "test-tag" {
- t.Errorf("Expected tag 'test-tag', found '%s'", image.Get("Tag"))
- }
- if image.Get("Repository") != "test-name" {
- t.Errorf("Expected repository 'test-name', found '%s'", image.Get("Repository"))
- }
-}
-
-func TestGetContainersByName(t *testing.T) {
- eng := engine.New()
- name := "container_name"
- var called bool
- eng.Register("container_inspect", func(job *engine.Job) engine.Status {
- called = true
- if job.Args[0] != name {
- t.Errorf("name != '%s': %#v", name, job.Args[0])
- }
- if api.APIVERSION.LessThan("1.12") && !job.GetenvBool("dirty") {
- t.Errorf("dirty env variable not set")
- } else if api.APIVERSION.GreaterThanOrEqualTo("1.12") && job.GetenvBool("dirty") {
- t.Errorf("dirty env variable set when it shouldn't")
- }
- v := &engine.Env{}
- v.SetBool("dirty", true)
- if _, err := v.WriteTo(job.Stdout); err != nil {
- return job.Error(err)
- }
- return engine.StatusOK
- })
- r := serveRequest("GET", "/containers/"+name+"/json", nil, eng, t)
- if !called {
- t.Fatal("handler was not called")
- }
- assertContentType(r, "application/json", t)
- var stdoutJson interface{}
- if err := json.Unmarshal(r.Body.Bytes(), &stdoutJson); err != nil {
- t.Fatalf("%#v", err)
- }
- if stdoutJson.(map[string]interface{})["dirty"].(float64) != 1 {
- t.Fatalf("%#v", stdoutJson)
- }
-}
-
-func TestGetEvents(t *testing.T) {
- eng := engine.New()
- var called bool
- eng.Register("events", func(job *engine.Job) engine.Status {
- called = true
- since := job.Getenv("since")
- if since != "1" {
- t.Fatalf("'since' should be 1, found %#v instead", since)
- }
- until := job.Getenv("until")
- if until != "0" {
- t.Fatalf("'until' should be 0, found %#v instead", until)
- }
- v := &engine.Env{}
- v.Set("since", since)
- v.Set("until", until)
- if _, err := v.WriteTo(job.Stdout); err != nil {
- return job.Error(err)
- }
- return engine.StatusOK
- })
- r := serveRequest("GET", "/events?since=1&until=0", nil, eng, t)
- if !called {
- t.Fatal("handler was not called")
- }
- assertContentType(r, "application/json", t)
- var stdout_json struct {
- Since int
- Until int
- }
- if err := json.Unmarshal(r.Body.Bytes(), &stdout_json); err != nil {
- t.Fatal(err)
- }
- if stdout_json.Since != 1 {
- t.Errorf("since != 1: %#v", stdout_json.Since)
- }
- if stdout_json.Until != 0 {
- t.Errorf("until != 0: %#v", stdout_json.Until)
- }
-}
-
-func TestLogs(t *testing.T) {
- eng := engine.New()
- var inspect bool
- var logs bool
- eng.Register("container_inspect", func(job *engine.Job) engine.Status {
- inspect = true
- if len(job.Args) == 0 {
- t.Fatal("Job arguments is empty")
- }
- if job.Args[0] != "test" {
- t.Fatalf("Container name %s, must be test", job.Args[0])
- }
- return engine.StatusOK
- })
- expected := "logs"
- eng.Register("logs", func(job *engine.Job) engine.Status {
- logs = true
- if len(job.Args) == 0 {
- t.Fatal("Job arguments is empty")
- }
- if job.Args[0] != "test" {
- t.Fatalf("Container name %s, must be test", job.Args[0])
- }
- follow := job.Getenv("follow")
- if follow != "1" {
- t.Fatalf("follow: %s, must be 1", follow)
- }
- stdout := job.Getenv("stdout")
- if stdout != "1" {
- t.Fatalf("stdout %s, must be 1", stdout)
- }
- stderr := job.Getenv("stderr")
- if stderr != "" {
- t.Fatalf("stderr %s, must be empty", stderr)
- }
- timestamps := job.Getenv("timestamps")
- if timestamps != "1" {
- t.Fatalf("timestamps %s, must be 1", timestamps)
- }
- job.Stdout.Write([]byte(expected))
- return engine.StatusOK
- })
- r := serveRequest("GET", "/containers/test/logs?follow=1&stdout=1×tamps=1", nil, eng, t)
- if r.Code != http.StatusOK {
- t.Fatalf("Got status %d, expected %d", r.Code, http.StatusOK)
- }
- if !inspect {
- t.Fatal("container_inspect job was not called")
- }
- if !logs {
- t.Fatal("logs job was not called")
- }
- res := r.Body.String()
- if res != expected {
- t.Fatalf("Output %s, expected %s", res, expected)
- }
-}
-
-func TestLogsNoStreams(t *testing.T) {
- eng := engine.New()
- var inspect bool
- var logs bool
- eng.Register("container_inspect", func(job *engine.Job) engine.Status {
- inspect = true
- if len(job.Args) == 0 {
- t.Fatal("Job arguments is empty")
- }
- if job.Args[0] != "test" {
- t.Fatalf("Container name %s, must be test", job.Args[0])
- }
- return engine.StatusOK
- })
- eng.Register("logs", func(job *engine.Job) engine.Status {
- logs = true
- return engine.StatusOK
- })
- r := serveRequest("GET", "/containers/test/logs", nil, eng, t)
- if r.Code != http.StatusBadRequest {
- t.Fatalf("Got status %d, expected %d", r.Code, http.StatusBadRequest)
- }
- if inspect {
- t.Fatal("container_inspect job was called, but it shouldn't")
- }
- if logs {
- t.Fatal("logs job was called, but it shouldn't")
- }
- res := strings.TrimSpace(r.Body.String())
- expected := "Bad parameters: you must choose at least one stream"
- if !strings.Contains(res, expected) {
- t.Fatalf("Output %s, expected %s in it", res, expected)
- }
-}
-
-func TestGetImagesHistory(t *testing.T) {
- eng := engine.New()
- imageName := "docker-test-image"
- var called bool
- eng.Register("history", func(job *engine.Job) engine.Status {
- called = true
- if len(job.Args) == 0 {
- t.Fatal("Job arguments is empty")
- }
- if job.Args[0] != imageName {
- t.Fatalf("name != '%s': %#v", imageName, job.Args[0])
- }
- v := &engine.Env{}
- if _, err := v.WriteTo(job.Stdout); err != nil {
- return job.Error(err)
- }
- return engine.StatusOK
- })
- r := serveRequest("GET", "/images/"+imageName+"/history", nil, eng, t)
- if !called {
- t.Fatalf("handler was not called")
- }
- if r.Code != http.StatusOK {
- t.Fatalf("Got status %d, expected %d", r.Code, http.StatusOK)
- }
- if r.HeaderMap.Get("Content-Type") != "application/json" {
- t.Fatalf("%#v\n", r)
- }
-}
-
-func TestGetImagesByName(t *testing.T) {
- eng := engine.New()
- name := "image_name"
- var called bool
- eng.Register("image_inspect", func(job *engine.Job) engine.Status {
- called = true
- if job.Args[0] != name {
- t.Fatalf("name != '%s': %#v", name, job.Args[0])
- }
- if api.APIVERSION.LessThan("1.12") && !job.GetenvBool("dirty") {
- t.Fatal("dirty env variable not set")
- } else if api.APIVERSION.GreaterThanOrEqualTo("1.12") && job.GetenvBool("dirty") {
- t.Fatal("dirty env variable set when it shouldn't")
- }
- v := &engine.Env{}
- v.SetBool("dirty", true)
- if _, err := v.WriteTo(job.Stdout); err != nil {
- return job.Error(err)
- }
- return engine.StatusOK
- })
- r := serveRequest("GET", "/images/"+name+"/json", nil, eng, t)
- if !called {
- t.Fatal("handler was not called")
- }
- if r.HeaderMap.Get("Content-Type") != "application/json" {
- t.Fatalf("%#v\n", r)
- }
- var stdoutJson interface{}
- if err := json.Unmarshal(r.Body.Bytes(), &stdoutJson); err != nil {
- t.Fatalf("%#v", err)
- }
- if stdoutJson.(map[string]interface{})["dirty"].(float64) != 1 {
- t.Fatalf("%#v", stdoutJson)
- }
-}
-
-func TestDeleteContainers(t *testing.T) {
- eng := engine.New()
- name := "foo"
- var called bool
- eng.Register("rm", func(job *engine.Job) engine.Status {
- called = true
- if len(job.Args) == 0 {
- t.Fatalf("Job arguments is empty")
- }
- if job.Args[0] != name {
- t.Fatalf("name != '%s': %#v", name, job.Args[0])
- }
- return engine.StatusOK
- })
- r := serveRequest("DELETE", "/containers/"+name, nil, eng, t)
- if !called {
- t.Fatalf("handler was not called")
- }
- if r.Code != http.StatusNoContent {
- t.Fatalf("Got status %d, expected %d", r.Code, http.StatusNoContent)
- }
-}
-
-func serveRequest(method, target string, body io.Reader, eng *engine.Engine, t *testing.T) *httptest.ResponseRecorder {
- return serveRequestUsingVersion(method, target, api.APIVERSION, body, eng, t)
-}
-
-func serveRequestUsingVersion(method, target string, version version.Version, body io.Reader, eng *engine.Engine, t *testing.T) *httptest.ResponseRecorder {
- r := httptest.NewRecorder()
- req, err := http.NewRequest(method, target, body)
- if err != nil {
- t.Fatal(err)
- }
- ServeRequest(eng, version, r, req)
- return r
-}
-
-func readEnv(src io.Reader, t *testing.T) *engine.Env {
- out := engine.NewOutput()
- v, err := out.AddEnv()
- if err != nil {
- t.Fatal(err)
- }
- if _, err := io.Copy(out, src); err != nil {
- t.Fatal(err)
- }
- out.Close()
- return v
-}
-
-func toJson(data interface{}, t *testing.T) io.Reader {
- var buf bytes.Buffer
- if err := json.NewEncoder(&buf).Encode(data); err != nil {
- t.Fatal(err)
- }
- return &buf
-}
-
-func assertContentType(recorder *httptest.ResponseRecorder, content_type string, t *testing.T) {
- if recorder.HeaderMap.Get("Content-Type") != content_type {
- t.Fatalf("%#v\n", recorder)
- }
-}
-
-// XXX: Duplicated from integration/utils_test.go, but maybe that's OK as that
-// should die as soon as we converted all integration tests?
-// assertHttpNotError expect the given response to not have an error.
-// Otherwise the it causes the test to fail.
-func assertHttpNotError(r *httptest.ResponseRecorder, t *testing.T) {
- // Non-error http status are [200, 400)
- if r.Code < http.StatusOK || r.Code >= http.StatusBadRequest {
- t.Fatal(fmt.Errorf("Unexpected http error: %v", r.Code))
- }
-}
-
-func createEnvFromGetImagesJSONStruct(data getImagesJSONStruct) *engine.Env {
- v := &engine.Env{}
- v.SetList("RepoTags", data.RepoTags)
- v.Set("Id", data.Id)
- v.SetInt64("Created", data.Created)
- v.SetInt64("Size", data.Size)
- v.SetInt64("VirtualSize", data.VirtualSize)
- return v
-}
-
-type getImagesJSONStruct struct {
- RepoTags []string
- Id string
- Created int64
- Size int64
- VirtualSize int64
-}
-
-var sampleImage getImagesJSONStruct = getImagesJSONStruct{
- RepoTags: []string{"test-name:test-tag"},
- Id: "ID",
- Created: 999,
- Size: 777,
- VirtualSize: 666,
-}
diff --git a/Godeps/_workspace/src/github.com/docker/docker/api/stats/stats.go b/Godeps/_workspace/src/github.com/docker/docker/api/stats/stats.go
deleted file mode 100644
index 8edf18fe0e..0000000000
--- a/Godeps/_workspace/src/github.com/docker/docker/api/stats/stats.go
+++ /dev/null
@@ -1,87 +0,0 @@
-// This package is used for API stability in the types and response to the
-// consumers of the API stats endpoint.
-package stats
-
-import "time"
-
-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"`
-}
-
-// All CPU stats are aggregated since container inception.
-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 MemoryStats struct {
- // current res_counter usage for memory
- Usage uint64 `json:"usage"`
- // maximum usage ever recorded.
- MaxUsage uint64 `json:"max_usage"`
- // TODO(vishh): Export these as stronger types.
- // all the stats exported via memory.stat.
- Stats map[string]uint64 `json:"stats"`
- // number of times memory usage hits limits.
- 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 Network 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 Stats struct {
- Read time.Time `json:"read"`
- Network Network `json:"network,omitempty"`
- CpuStats CpuStats `json:"cpu_stats,omitempty"`
- MemoryStats MemoryStats `json:"memory_stats,omitempty"`
- BlkioStats BlkioStats `json:"blkio_stats,omitempty"`
-}
diff --git a/commands/active.go b/commands/active.go
index 6840806a67..7bebc37ac4 100644
--- a/commands/active.go
+++ b/commands/active.go
@@ -3,9 +3,8 @@ package commands
import (
"fmt"
- log "github.com/Sirupsen/logrus"
-
"github.com/codegangsta/cli"
+ "github.com/docker/machine/log"
)
func cmdActive(c *cli.Context) {
diff --git a/commands/commands.go b/commands/commands.go
index 03740c7afb..a4dadb3075 100644
--- a/commands/commands.go
+++ b/commands/commands.go
@@ -9,7 +9,6 @@ import (
"sort"
"strings"
- log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/skarademir/naturalsort"
@@ -31,6 +30,7 @@ import (
"github.com/docker/machine/libmachine"
"github.com/docker/machine/libmachine/auth"
"github.com/docker/machine/libmachine/swarm"
+ "github.com/docker/machine/log"
"github.com/docker/machine/state"
"github.com/docker/machine/utils"
)
diff --git a/commands/config.go b/commands/config.go
index fdfa9fe0e6..e77cfc4043 100644
--- a/commands/config.go
+++ b/commands/config.go
@@ -5,9 +5,8 @@ import (
"net/url"
"strings"
- log "github.com/Sirupsen/logrus"
-
"github.com/codegangsta/cli"
+ "github.com/docker/machine/log"
"github.com/docker/machine/utils"
)
diff --git a/commands/create.go b/commands/create.go
index 23d2d07e4e..9b27cd0dbe 100644
--- a/commands/create.go
+++ b/commands/create.go
@@ -4,7 +4,7 @@ import (
"fmt"
"path/filepath"
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
"github.com/codegangsta/cli"
"github.com/docker/machine/drivers"
diff --git a/commands/env.go b/commands/env.go
index 79059c7c12..81a52eec72 100644
--- a/commands/env.go
+++ b/commands/env.go
@@ -7,7 +7,7 @@ import (
"strings"
"text/template"
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
"github.com/codegangsta/cli"
"github.com/docker/machine/utils"
diff --git a/commands/inspect.go b/commands/inspect.go
index 6d5787c0a9..760773e8f7 100644
--- a/commands/inspect.go
+++ b/commands/inspect.go
@@ -6,7 +6,7 @@ import (
"os"
"text/template"
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
"github.com/codegangsta/cli"
)
diff --git a/commands/ip.go b/commands/ip.go
index b6b9fb5c71..5a8f68aece 100644
--- a/commands/ip.go
+++ b/commands/ip.go
@@ -1,9 +1,8 @@
package commands
import (
- log "github.com/Sirupsen/logrus"
-
"github.com/codegangsta/cli"
+ "github.com/docker/machine/log"
)
func cmdIp(c *cli.Context) {
diff --git a/commands/kill.go b/commands/kill.go
index 8bed899f10..607b3475b8 100644
--- a/commands/kill.go
+++ b/commands/kill.go
@@ -1,7 +1,7 @@
package commands
import (
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
"github.com/codegangsta/cli"
)
diff --git a/commands/ls.go b/commands/ls.go
index 6bf5a1927f..aafebdcc8a 100644
--- a/commands/ls.go
+++ b/commands/ls.go
@@ -5,7 +5,7 @@ import (
"os"
"text/tabwriter"
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
"github.com/codegangsta/cli"
)
diff --git a/commands/regeneratecerts.go b/commands/regeneratecerts.go
index 0a4b35f2d2..930178fa04 100644
--- a/commands/regeneratecerts.go
+++ b/commands/regeneratecerts.go
@@ -1,8 +1,8 @@
package commands
import (
- log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
+ "github.com/docker/machine/log"
)
func cmdRegenerateCerts(c *cli.Context) {
diff --git a/commands/restart.go b/commands/restart.go
index 99b8365315..9b1cb4cd38 100644
--- a/commands/restart.go
+++ b/commands/restart.go
@@ -1,7 +1,7 @@
package commands
import (
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
"github.com/codegangsta/cli"
)
diff --git a/commands/rm.go b/commands/rm.go
index 0d181fb8ba..b8ce7ea9ee 100644
--- a/commands/rm.go
+++ b/commands/rm.go
@@ -1,8 +1,8 @@
package commands
import (
- log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
+ "github.com/docker/machine/log"
)
func cmdRm(c *cli.Context) {
diff --git a/commands/ssh.go b/commands/ssh.go
index 35a7206487..392d3e3f40 100644
--- a/commands/ssh.go
+++ b/commands/ssh.go
@@ -5,7 +5,7 @@ import (
"os"
"strings"
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
"github.com/codegangsta/cli"
"github.com/docker/machine/drivers"
diff --git a/commands/start.go b/commands/start.go
index d82ed69c00..161e67ae7a 100644
--- a/commands/start.go
+++ b/commands/start.go
@@ -1,7 +1,7 @@
package commands
import (
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
"github.com/codegangsta/cli"
)
diff --git a/commands/stop.go b/commands/stop.go
index f5d51751f4..7a47818a85 100644
--- a/commands/stop.go
+++ b/commands/stop.go
@@ -1,7 +1,7 @@
package commands
import (
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
"github.com/codegangsta/cli"
)
diff --git a/commands/upgrade.go b/commands/upgrade.go
index 5326aefee9..6e22c00cea 100644
--- a/commands/upgrade.go
+++ b/commands/upgrade.go
@@ -1,7 +1,7 @@
package commands
import (
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
"github.com/codegangsta/cli"
)
diff --git a/commands/url.go b/commands/url.go
index 60f6377af5..a714c1c486 100644
--- a/commands/url.go
+++ b/commands/url.go
@@ -3,7 +3,7 @@ package commands
import (
"fmt"
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
"github.com/codegangsta/cli"
)
diff --git a/drivers/amazonec2/amazonec2.go b/drivers/amazonec2/amazonec2.go
index e9781acc61..4b379c554b 100644
--- a/drivers/amazonec2/amazonec2.go
+++ b/drivers/amazonec2/amazonec2.go
@@ -12,10 +12,10 @@ import (
"strings"
"time"
- log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/docker/machine/drivers"
"github.com/docker/machine/drivers/amazonec2/amz"
+ "github.com/docker/machine/log"
"github.com/docker/machine/provider"
"github.com/docker/machine/ssh"
"github.com/docker/machine/state"
diff --git a/drivers/azure/azure.go b/drivers/azure/azure.go
index 3726c008b1..0dee97b62e 100644
--- a/drivers/azure/azure.go
+++ b/drivers/azure/azure.go
@@ -11,13 +11,13 @@ import (
azure "github.com/MSOpenTech/azure-sdk-for-go"
"github.com/MSOpenTech/azure-sdk-for-go/clients/vmClient"
- log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
- "github.com/docker/docker/utils"
"github.com/docker/machine/drivers"
+ "github.com/docker/machine/log"
"github.com/docker/machine/provider"
"github.com/docker/machine/ssh"
"github.com/docker/machine/state"
+ "github.com/docker/machine/utils"
)
type Driver struct {
diff --git a/drivers/digitalocean/digitalocean.go b/drivers/digitalocean/digitalocean.go
index 7348af2b76..7aa0baf3b3 100644
--- a/drivers/digitalocean/digitalocean.go
+++ b/drivers/digitalocean/digitalocean.go
@@ -7,10 +7,10 @@ import (
"time"
"code.google.com/p/goauth2/oauth"
- log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/digitalocean/godo"
"github.com/docker/machine/drivers"
+ "github.com/docker/machine/log"
"github.com/docker/machine/provider"
"github.com/docker/machine/ssh"
"github.com/docker/machine/state"
diff --git a/drivers/drivers.go b/drivers/drivers.go
index 2b432624be..6b43f501cd 100644
--- a/drivers/drivers.go
+++ b/drivers/drivers.go
@@ -5,8 +5,8 @@ import (
"fmt"
"sort"
- log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
+ "github.com/docker/machine/log"
"github.com/docker/machine/provider"
"github.com/docker/machine/ssh"
"github.com/docker/machine/state"
diff --git a/drivers/google/auth_util.go b/drivers/google/auth_util.go
index 14122b0a52..b8d5bd0869 100644
--- a/drivers/google/auth_util.go
+++ b/drivers/google/auth_util.go
@@ -12,7 +12,7 @@ import (
"time"
"code.google.com/p/goauth2/oauth"
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
raw "google.golang.org/api/compute/v1"
)
diff --git a/drivers/google/compute_util.go b/drivers/google/compute_util.go
index ddf309259c..015dc8ed65 100644
--- a/drivers/google/compute_util.go
+++ b/drivers/google/compute_util.go
@@ -7,7 +7,7 @@ import (
"strings"
"time"
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
"github.com/docker/machine/ssh"
raw "google.golang.org/api/compute/v1"
)
diff --git a/drivers/google/google.go b/drivers/google/google.go
index ace15d33dc..b5863ca9ad 100644
--- a/drivers/google/google.go
+++ b/drivers/google/google.go
@@ -4,9 +4,9 @@ import (
"fmt"
"path/filepath"
- log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/docker/machine/drivers"
+ "github.com/docker/machine/log"
"github.com/docker/machine/provider"
"github.com/docker/machine/ssh"
"github.com/docker/machine/state"
diff --git a/drivers/hyperv/hyperv_windows.go b/drivers/hyperv/hyperv_windows.go
index a9ca9b5628..1d719392c0 100644
--- a/drivers/hyperv/hyperv_windows.go
+++ b/drivers/hyperv/hyperv_windows.go
@@ -9,9 +9,9 @@ import (
"path/filepath"
"time"
- log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/docker/machine/drivers"
+ "github.com/docker/machine/log"
"github.com/docker/machine/provider"
"github.com/docker/machine/ssh"
"github.com/docker/machine/state"
diff --git a/drivers/hyperv/powershell_windows.go b/drivers/hyperv/powershell_windows.go
index a0bd4a2d3b..781175586e 100644
--- a/drivers/hyperv/powershell_windows.go
+++ b/drivers/hyperv/powershell_windows.go
@@ -9,7 +9,7 @@ import (
"path/filepath"
"strings"
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
)
var powershell string
diff --git a/drivers/none/none.go b/drivers/none/none.go
index 1b8a275fb3..e923aa7d2d 100644
--- a/drivers/none/none.go
+++ b/drivers/none/none.go
@@ -4,7 +4,6 @@ import (
"fmt"
"github.com/codegangsta/cli"
- "github.com/docker/docker/api"
"github.com/docker/machine/drivers"
"github.com/docker/machine/provider"
"github.com/docker/machine/state"
@@ -112,12 +111,8 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
if url == "" {
return fmt.Errorf("--url option is required when no driver is selected")
}
- validatedUrl, err := api.ValidateHost(url)
- if err != nil {
- return err
- }
- d.URL = validatedUrl
+ d.URL = url
return nil
}
diff --git a/drivers/openstack/client.go b/drivers/openstack/client.go
index 711329652f..e464a5674c 100644
--- a/drivers/openstack/client.go
+++ b/drivers/openstack/client.go
@@ -5,7 +5,7 @@ import (
"fmt"
"net/http"
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
"github.com/docker/machine/version"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack"
diff --git a/drivers/openstack/openstack.go b/drivers/openstack/openstack.go
index 3714fb1a93..3349b33264 100644
--- a/drivers/openstack/openstack.go
+++ b/drivers/openstack/openstack.go
@@ -7,13 +7,13 @@ import (
"strings"
"time"
- log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
- "github.com/docker/docker/utils"
"github.com/docker/machine/drivers"
+ "github.com/docker/machine/log"
"github.com/docker/machine/provider"
"github.com/docker/machine/ssh"
"github.com/docker/machine/state"
+ "github.com/docker/machine/utils"
)
type Driver struct {
diff --git a/drivers/rackspace/client.go b/drivers/rackspace/client.go
index 79c3241d5d..bca5a784cf 100644
--- a/drivers/rackspace/client.go
+++ b/drivers/rackspace/client.go
@@ -3,8 +3,8 @@ package rackspace
import (
"fmt"
- log "github.com/Sirupsen/logrus"
"github.com/docker/machine/drivers/openstack"
+ "github.com/docker/machine/log"
"github.com/docker/machine/version"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/rackspace"
diff --git a/drivers/rackspace/rackspace.go b/drivers/rackspace/rackspace.go
index ff9d0cc32b..cbb7cedaf5 100644
--- a/drivers/rackspace/rackspace.go
+++ b/drivers/rackspace/rackspace.go
@@ -3,10 +3,10 @@ package rackspace
import (
"fmt"
- log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/docker/machine/drivers"
"github.com/docker/machine/drivers/openstack"
+ "github.com/docker/machine/log"
)
// Driver is a machine driver for Rackspace. It's a specialization of the generic OpenStack one.
diff --git a/drivers/softlayer/driver.go b/drivers/softlayer/driver.go
index 3d13193673..b223986c47 100644
--- a/drivers/softlayer/driver.go
+++ b/drivers/softlayer/driver.go
@@ -8,9 +8,9 @@ import (
"regexp"
"time"
- log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/docker/machine/drivers"
+ "github.com/docker/machine/log"
"github.com/docker/machine/provider"
"github.com/docker/machine/ssh"
"github.com/docker/machine/state"
diff --git a/drivers/virtualbox/vbm.go b/drivers/virtualbox/vbm.go
index 21a94e3172..a6f9434adf 100644
--- a/drivers/virtualbox/vbm.go
+++ b/drivers/virtualbox/vbm.go
@@ -11,7 +11,7 @@ import (
"runtime"
"strings"
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
)
var (
diff --git a/drivers/virtualbox/virtualbox.go b/drivers/virtualbox/virtualbox.go
index dcaa0c5171..109090fc82 100644
--- a/drivers/virtualbox/virtualbox.go
+++ b/drivers/virtualbox/virtualbox.go
@@ -16,9 +16,9 @@ import (
"strings"
"time"
- log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/docker/machine/drivers"
+ "github.com/docker/machine/log"
"github.com/docker/machine/provider"
"github.com/docker/machine/ssh"
"github.com/docker/machine/state"
diff --git a/drivers/vmwarefusion/fusion_darwin.go b/drivers/vmwarefusion/fusion_darwin.go
index 3cc9c92e32..99ebffc80a 100644
--- a/drivers/vmwarefusion/fusion_darwin.go
+++ b/drivers/vmwarefusion/fusion_darwin.go
@@ -19,9 +19,9 @@ import (
"text/template"
"time"
- log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/docker/machine/drivers"
+ "github.com/docker/machine/log"
"github.com/docker/machine/provider"
"github.com/docker/machine/ssh"
"github.com/docker/machine/state"
diff --git a/drivers/vmwarefusion/vmrun_darwin.go b/drivers/vmwarefusion/vmrun_darwin.go
index 4850a81b06..917c1347fd 100644
--- a/drivers/vmwarefusion/vmrun_darwin.go
+++ b/drivers/vmwarefusion/vmrun_darwin.go
@@ -12,7 +12,7 @@ import (
"os/exec"
"strings"
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
)
var (
diff --git a/drivers/vmwarevcloudair/vcloudair.go b/drivers/vmwarevcloudair/vcloudair.go
index 3b6df907cd..8ee2ce6b86 100644
--- a/drivers/vmwarevcloudair/vcloudair.go
+++ b/drivers/vmwarevcloudair/vcloudair.go
@@ -12,13 +12,13 @@ import (
"github.com/vmware/govcloudair"
- log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
- "github.com/docker/docker/utils"
"github.com/docker/machine/drivers"
+ "github.com/docker/machine/log"
"github.com/docker/machine/provider"
"github.com/docker/machine/ssh"
"github.com/docker/machine/state"
+ "github.com/docker/machine/utils"
)
type Driver struct {
diff --git a/drivers/vmwarevsphere/govc.go b/drivers/vmwarevsphere/govc.go
index 6a7165e7fa..c8612e8fec 100644
--- a/drivers/vmwarevsphere/govc.go
+++ b/drivers/vmwarevsphere/govc.go
@@ -9,7 +9,7 @@ import (
"os/exec"
"strings"
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
)
var (
diff --git a/drivers/vmwarevsphere/vc_conn.go b/drivers/vmwarevsphere/vc_conn.go
index 02f838645f..ba62d1f2ff 100644
--- a/drivers/vmwarevsphere/vc_conn.go
+++ b/drivers/vmwarevsphere/vc_conn.go
@@ -9,8 +9,8 @@ import (
"strconv"
"strings"
- log "github.com/Sirupsen/logrus"
"github.com/docker/machine/drivers/vmwarevsphere/errors"
+ "github.com/docker/machine/log"
)
type VcConn struct {
diff --git a/drivers/vmwarevsphere/vsphere.go b/drivers/vmwarevsphere/vsphere.go
index 4df158ad93..c4b6ce1b0a 100644
--- a/drivers/vmwarevsphere/vsphere.go
+++ b/drivers/vmwarevsphere/vsphere.go
@@ -16,7 +16,7 @@ import (
"strings"
"time"
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
"github.com/codegangsta/cli"
"github.com/docker/machine/drivers"
diff --git a/libmachine/filestore.go b/libmachine/filestore.go
index b5965f7f21..a9fde8fbaf 100644
--- a/libmachine/filestore.go
+++ b/libmachine/filestore.go
@@ -7,7 +7,7 @@ import (
"path/filepath"
"strings"
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
"github.com/docker/machine/utils"
)
diff --git a/libmachine/host.go b/libmachine/host.go
index 5c04e0fd64..a44c8508a8 100644
--- a/libmachine/host.go
+++ b/libmachine/host.go
@@ -8,13 +8,13 @@ import (
"path/filepath"
"regexp"
- log "github.com/Sirupsen/logrus"
"github.com/docker/machine/drivers"
"github.com/docker/machine/libmachine/auth"
"github.com/docker/machine/libmachine/engine"
"github.com/docker/machine/libmachine/provision"
"github.com/docker/machine/libmachine/provision/pkgaction"
"github.com/docker/machine/libmachine/swarm"
+ "github.com/docker/machine/log"
"github.com/docker/machine/ssh"
"github.com/docker/machine/state"
"github.com/docker/machine/utils"
diff --git a/libmachine/provision/boot2docker.go b/libmachine/provision/boot2docker.go
index 3f2a32d30c..9677364e3b 100644
--- a/libmachine/provision/boot2docker.go
+++ b/libmachine/provision/boot2docker.go
@@ -7,12 +7,12 @@ import (
"path"
"text/template"
- log "github.com/Sirupsen/logrus"
"github.com/docker/machine/drivers"
"github.com/docker/machine/libmachine/auth"
"github.com/docker/machine/libmachine/engine"
"github.com/docker/machine/libmachine/provision/pkgaction"
"github.com/docker/machine/libmachine/swarm"
+ "github.com/docker/machine/log"
"github.com/docker/machine/ssh"
"github.com/docker/machine/state"
"github.com/docker/machine/utils"
diff --git a/libmachine/provision/os_release.go b/libmachine/provision/os_release.go
index 464f435317..f61083021b 100644
--- a/libmachine/provision/os_release.go
+++ b/libmachine/provision/os_release.go
@@ -7,7 +7,7 @@ import (
"reflect"
"strings"
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
)
// The /etc/os-release file contains operating system identification data
diff --git a/libmachine/provision/ubuntu.go b/libmachine/provision/ubuntu.go
index b803afbf17..82c5a1ee23 100644
--- a/libmachine/provision/ubuntu.go
+++ b/libmachine/provision/ubuntu.go
@@ -5,12 +5,12 @@ import (
"fmt"
"text/template"
- log "github.com/Sirupsen/logrus"
"github.com/docker/machine/drivers"
"github.com/docker/machine/libmachine/auth"
"github.com/docker/machine/libmachine/engine"
"github.com/docker/machine/libmachine/provision/pkgaction"
"github.com/docker/machine/libmachine/swarm"
+ "github.com/docker/machine/log"
"github.com/docker/machine/ssh"
"github.com/docker/machine/utils"
)
diff --git a/libmachine/provision/utils.go b/libmachine/provision/utils.go
index 4429a97a6e..9214b8e06b 100644
--- a/libmachine/provision/utils.go
+++ b/libmachine/provision/utils.go
@@ -10,10 +10,10 @@ import (
"strconv"
"strings"
- log "github.com/Sirupsen/logrus"
"github.com/docker/machine/libmachine/auth"
"github.com/docker/machine/libmachine/provision/pkgaction"
"github.com/docker/machine/libmachine/swarm"
+ "github.com/docker/machine/log"
"github.com/docker/machine/utils"
)
diff --git a/log.go b/log.go
deleted file mode 100644
index cdbbd4408f..0000000000
--- a/log.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package main
-
-import (
- "os"
-
- log "github.com/Sirupsen/logrus"
-)
-
-func initLogging(lvl log.Level) {
- log.SetOutput(os.Stderr)
- log.SetLevel(lvl)
-}
diff --git a/log/log.go b/log/log.go
new file mode 100644
index 0000000000..e7e900c032
--- /dev/null
+++ b/log/log.go
@@ -0,0 +1,123 @@
+package log
+
+import (
+ "fmt"
+ "os"
+ "strconv"
+)
+
+// Why the interface? We may only want to print to STDOUT and STDERR for now,
+// but it won't neccessarily be that way forever. This interface is intended
+// to provide a "framework" for a variety of different logging types in the
+// future (log to file, log to logstash, etc.) There could be a driver model
+// similar to what is done with OS or machine providers.
+type Logger interface {
+ Debug(...interface{})
+ Debugf(string, ...interface{})
+
+ Error(...interface{})
+ Errorf(string, ...interface{})
+ Errorln(...interface{})
+
+ Info(...interface{})
+ Infof(string, ...interface{})
+ Infoln(...interface{})
+
+ Fatal(...interface{})
+ Fatalf(string, ...interface{})
+
+ Print(...interface{})
+ Printf(string, ...interface{})
+
+ Warn(...interface{})
+ Warnf(string, ...interface{})
+
+ WithFields(Fields) Logger
+}
+
+var (
+ l = TerminalLogger{}
+)
+
+// TODO: I think this is superflous and can be replaced by one check for if
+// debug is on that sets a variable in this module.
+func isDebug() bool {
+ debugEnv := os.Getenv("DEBUG")
+ if debugEnv != "" {
+ showDebug, err := strconv.ParseBool(debugEnv)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, "Error parsing boolean value from DEBUG: %s", err)
+ os.Exit(1)
+ }
+ return showDebug
+ }
+ return false
+}
+
+type Fields map[string]interface{}
+
+func Debug(args ...interface{}) {
+ l.Debug(args...)
+}
+
+func Debugf(fmtString string, args ...interface{}) {
+ l.Debugf(fmtString, args...)
+}
+
+func Error(args ...interface{}) {
+ l.Error(args...)
+}
+
+func Errorf(fmtString string, args ...interface{}) {
+ l.Errorf(fmtString, args...)
+}
+
+func Errorln(args ...interface{}) {
+ l.Errorln(args...)
+}
+
+func Info(args ...interface{}) {
+ l.Info(args...)
+}
+
+func Infof(fmtString string, args ...interface{}) {
+ l.Infof(fmtString, args...)
+}
+
+func Infoln(args ...interface{}) {
+ l.Infoln(args...)
+}
+
+func Fatal(args ...interface{}) {
+ l.Fatal(args...)
+}
+
+func Fatalf(fmtString string, args ...interface{}) {
+ l.Fatalf(fmtString, args...)
+}
+
+func Print(args ...interface{}) {
+ l.Print(args...)
+}
+
+func Printf(fmtString string, args ...interface{}) {
+ l.Printf(fmtString, args...)
+}
+
+func Warn(args ...interface{}) {
+ l.Warn(args...)
+}
+
+func Warnf(fmtString string, args ...interface{}) {
+ l.Warnf(fmtString, args...)
+}
+
+func WithField(fieldName string, field interface{}) Logger {
+ return l.WithFields(Fields{
+ fieldName: field,
+ })
+}
+
+func WithFields(fields Fields) Logger {
+ return l.WithFields(fields)
+}
diff --git a/log/log_test.go b/log/log_test.go
new file mode 100644
index 0000000000..349ffe6e0e
--- /dev/null
+++ b/log/log_test.go
@@ -0,0 +1,19 @@
+package log
+
+import "testing"
+
+func TestTerminalLoggerWithFields(t *testing.T) {
+ logger := TerminalLogger{}
+ withFieldsLogger := logger.WithFields(Fields{
+ "foo": "bar",
+ "spam": "eggs",
+ })
+ withFieldsTerminalLogger, ok := withFieldsLogger.(TerminalLogger)
+ if !ok {
+ t.Fatal("Type assertion to TerminalLogger failed")
+ }
+ expectedOutFields := "\t\t foo=bar spam=eggs"
+ if withFieldsTerminalLogger.fieldOut != expectedOutFields {
+ t.Fatalf("Expected %q, got %q", expectedOutFields, withFieldsTerminalLogger.fieldOut)
+ }
+}
diff --git a/log/terminal.go b/log/terminal.go
new file mode 100644
index 0000000000..57f26fdb36
--- /dev/null
+++ b/log/terminal.go
@@ -0,0 +1,129 @@
+package log
+
+import (
+ "fmt"
+ "os"
+ "sort"
+)
+
+type TerminalLogger struct {
+ // fieldOut is used to do log.WithFields correctly
+ fieldOut string
+}
+
+func (t TerminalLogger) log(args ...interface{}) {
+ fmt.Print(args...)
+ fmt.Print(t.fieldOut, "\n")
+ t.fieldOut = ""
+}
+
+func (t TerminalLogger) logf(fmtString string, args ...interface{}) {
+ fmt.Printf(fmtString, args...)
+ fmt.Print(t.fieldOut, "\n")
+ t.fieldOut = ""
+}
+
+func (t TerminalLogger) err(args ...interface{}) {
+ fmt.Fprint(os.Stderr, args...)
+ fmt.Fprint(os.Stderr, t.fieldOut, "\n")
+ t.fieldOut = ""
+}
+
+func (t TerminalLogger) errf(fmtString string, args ...interface{}) {
+ fmt.Fprintf(os.Stderr, fmtString, args...)
+ fmt.Print(t.fieldOut, "\n")
+ t.fieldOut = ""
+}
+
+func (t TerminalLogger) Debug(args ...interface{}) {
+ if isDebug() {
+ t.log(args...)
+ }
+}
+
+func (t TerminalLogger) Debugf(fmtString string, args ...interface{}) {
+ if isDebug() {
+ t.logf(fmtString, args...)
+ }
+}
+
+func (t TerminalLogger) Error(args ...interface{}) {
+ t.err(args...)
+}
+
+func (t TerminalLogger) Errorf(fmtString string, args ...interface{}) {
+ t.errf(fmtString, args...)
+}
+
+func (t TerminalLogger) Errorln(args ...interface{}) {
+ t.err(args...)
+}
+
+func (t TerminalLogger) Info(args ...interface{}) {
+ t.log(args...)
+}
+
+func (t TerminalLogger) Infof(fmtString string, args ...interface{}) {
+ t.logf(fmtString, args...)
+}
+
+func (t TerminalLogger) Infoln(args ...interface{}) {
+ t.log(args...)
+}
+
+func (t TerminalLogger) Fatal(args ...interface{}) {
+ t.err(args...)
+ os.Exit(1)
+}
+
+func (t TerminalLogger) Fatalf(fmtString string, args ...interface{}) {
+ t.errf(fmtString, args...)
+ os.Exit(1)
+}
+
+func (t TerminalLogger) Print(args ...interface{}) {
+ t.log(args...)
+}
+
+func (t TerminalLogger) Printf(fmtString string, args ...interface{}) {
+ t.logf(fmtString, args...)
+}
+
+func (t TerminalLogger) Warn(args ...interface{}) {
+ t.log(args...)
+}
+
+func (t TerminalLogger) Warnf(fmtString string, args ...interface{}) {
+ t.logf(fmtString, args...)
+}
+
+func (t TerminalLogger) WithFields(fields Fields) Logger {
+ // When the user calls WithFields, we make a string which gets appended
+ // to the output of the final [Info|Warn|Error] call for the
+ // descriptive fields. Because WithFields returns the proper Logger
+ // (with the fieldOut string set correctly), the logrus syntax will
+ // still work.
+ kvpairs := []string{}
+
+ // Why the string slice song and dance? Because Go's map iteration
+ // order is random, we will get inconsistent results if we don't sort
+ // the fields (or their resulting string K/V pairs, like we have here).
+ // Otherwise, we couldn't test this reliably.
+ for k, v := range fields {
+ kvpairs = append(kvpairs, fmt.Sprintf("%s=%v", k, v))
+ }
+
+ sort.Strings(kvpairs)
+
+ // TODO:
+ // 1. Is this thread-safe?
+ // 2. Add more tabs?
+ t.fieldOut = "\t\t"
+
+ for _, s := range kvpairs {
+ // TODO: Is %v the correct format string here?
+ t.fieldOut = fmt.Sprintf("%s %s", t.fieldOut, s)
+ }
+
+ return t
+}
diff --git a/main.go b/main.go
index 1b0b4473be..ba1e6b2f50 100644
--- a/main.go
+++ b/main.go
@@ -4,10 +4,10 @@ import (
"os"
"path"
- log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/docker/machine/commands"
+ "github.com/docker/machine/log"
"github.com/docker/machine/utils"
"github.com/docker/machine/version"
)
@@ -49,7 +49,6 @@ func main() {
for _, f := range os.Args {
if f == "-D" || f == "--debug" || f == "-debug" {
os.Setenv("DEBUG", "1")
- initLogging(log.DebugLevel)
}
}
diff --git a/ssh/ssh.go b/ssh/ssh.go
index cd3f6b74f9..baaf92443a 100644
--- a/ssh/ssh.go
+++ b/ssh/ssh.go
@@ -1,8 +1,6 @@
package ssh
-import (
- "net"
-)
+import "net"
func WaitForTCP(addr string) error {
for {
diff --git a/utils/b2d.go b/utils/b2d.go
index 38df28870c..853880a831 100644
--- a/utils/b2d.go
+++ b/utils/b2d.go
@@ -12,7 +12,7 @@ import (
"path/filepath"
"time"
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
)
const (
diff --git a/utils/utils.go b/utils/utils.go
index c4899ef906..1ee33828b3 100644
--- a/utils/utils.go
+++ b/utils/utils.go
@@ -1,6 +1,8 @@
package utils
import (
+ "crypto/rand"
+ "encoding/hex"
"encoding/json"
"fmt"
"io"
@@ -8,9 +10,10 @@ import (
"os"
"path/filepath"
"runtime"
+ "strconv"
"time"
- log "github.com/Sirupsen/logrus"
+ "github.com/docker/machine/log"
)
func GetHomeDir() string {
@@ -126,3 +129,32 @@ func DumpVal(vals ...interface{}) {
log.Debug(string(prettyJSON))
}
}
+
+// Following two functions are from github.com/docker/docker/utils module. It
+// was way overkill to include the whole module, so we just have these bits
+// that we're using here.
+func TruncateID(id string) string {
+ shortLen := 12
+ if len(id) < shortLen {
+ shortLen = len(id)
+ }
+ return id[:shortLen]
+}
+
+// GenerateRandomID returns an unique id
+func GenerateRandomID() string {
+ for {
+ id := make([]byte, 32)
+ if _, err := io.ReadFull(rand.Reader, id); err != nil {
+ panic(err) // This shouldn't happen
+ }
+ value := hex.EncodeToString(id)
+ // if we try to parse the truncated for as an int and we don't have
+ // an error then the value is all numberic and causes issues when
+ // used as a hostname. ref #3869
+ if _, err := strconv.ParseInt(TruncateID(value), 10, 64); err == nil {
+ continue
+ }
+ return value
+ }
+}