diff --git a/vendor/github.com/Sirupsen/logrus/examples/basic/basic.go b/vendor/github.com/Sirupsen/logrus/examples/basic/basic.go deleted file mode 100644 index a1623ec0..00000000 --- a/vendor/github.com/Sirupsen/logrus/examples/basic/basic.go +++ /dev/null @@ -1,50 +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 - log.Level = logrus.DebugLevel -} - -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", - "number": 8, - }).Debug("Started observing beach") - - 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{ - "temperature": -4, - }).Debug("Temperature changes") - - log.WithFields(logrus.Fields{ - "animal": "orca", - "size": 9009, - }).Panic("It's over 9000!") -} diff --git a/vendor/github.com/Sirupsen/logrus/examples/hook/hook.go b/vendor/github.com/Sirupsen/logrus/examples/hook/hook.go deleted file mode 100644 index cb5759a3..00000000 --- a/vendor/github.com/Sirupsen/logrus/examples/hook/hook.go +++ /dev/null @@ -1,30 +0,0 @@ -package main - -import ( - "github.com/Sirupsen/logrus" - "github.com/Sirupsen/logrus/hooks/airbrake" -) - -var log = logrus.New() - -func init() { - log.Formatter = new(logrus.TextFormatter) // default - log.Hooks.Add(airbrake.NewHook("https://example.com", "xyz", "development")) -} - -func main() { - 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/vendor/github.com/Sirupsen/logrus/formatters/logstash/logstash.go b/vendor/github.com/Sirupsen/logrus/formatters/logstash/logstash.go deleted file mode 100644 index 8ea93ddf..00000000 --- a/vendor/github.com/Sirupsen/logrus/formatters/logstash/logstash.go +++ /dev/null @@ -1,56 +0,0 @@ -package logstash - -import ( - "encoding/json" - "fmt" - - "github.com/Sirupsen/logrus" -) - -// Formatter generates json in logstash format. -// Logstash site: http://logstash.net/ -type LogstashFormatter struct { - Type string // if not empty use for logstash type field. - - // TimestampFormat sets the format used for timestamps. - TimestampFormat string -} - -func (f *LogstashFormatter) Format(entry *logrus.Entry) ([]byte, error) { - entry.Data["@version"] = 1 - - if f.TimestampFormat == "" { - f.TimestampFormat = logrus.DefaultTimestampFormat - } - - entry.Data["@timestamp"] = entry.Time.Format(f.TimestampFormat) - - // set message field - v, ok := entry.Data["message"] - if ok { - entry.Data["fields.message"] = v - } - entry.Data["message"] = entry.Message - - // set level field - v, ok = entry.Data["level"] - if ok { - entry.Data["fields.level"] = v - } - entry.Data["level"] = entry.Level.String() - - // set type field - if f.Type != "" { - v, ok = entry.Data["type"] - if ok { - entry.Data["fields.type"] = v - } - entry.Data["type"] = f.Type - } - - 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/vendor/github.com/Sirupsen/logrus/formatters/logstash/logstash_test.go b/vendor/github.com/Sirupsen/logrus/formatters/logstash/logstash_test.go deleted file mode 100644 index d8814a0e..00000000 --- a/vendor/github.com/Sirupsen/logrus/formatters/logstash/logstash_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package logstash - -import ( - "bytes" - "encoding/json" - "github.com/Sirupsen/logrus" - "github.com/stretchr/testify/assert" - "testing" -) - -func TestLogstashFormatter(t *testing.T) { - assert := assert.New(t) - - lf := LogstashFormatter{Type: "abc"} - - fields := logrus.Fields{ - "message": "def", - "level": "ijk", - "type": "lmn", - "one": 1, - "pi": 3.14, - "bool": true, - } - - entry := logrus.WithFields(fields) - entry.Message = "msg" - entry.Level = logrus.InfoLevel - - b, _ := lf.Format(entry) - - var data map[string]interface{} - dec := json.NewDecoder(bytes.NewReader(b)) - dec.UseNumber() - dec.Decode(&data) - - // base fields - assert.Equal(json.Number("1"), data["@version"]) - assert.NotEmpty(data["@timestamp"]) - assert.Equal("abc", data["type"]) - assert.Equal("msg", data["message"]) - assert.Equal("info", data["level"]) - - // substituted fields - assert.Equal("def", data["fields.message"]) - assert.Equal("ijk", data["fields.level"]) - assert.Equal("lmn", data["fields.type"]) - - // formats - assert.Equal(json.Number("1"), data["one"]) - assert.Equal(json.Number("3.14"), data["pi"]) - assert.Equal(true, data["bool"]) -} diff --git a/vendor/github.com/Sirupsen/logrus/hooks/airbrake/airbrake.go b/vendor/github.com/Sirupsen/logrus/hooks/airbrake/airbrake.go deleted file mode 100644 index b0502c33..00000000 --- a/vendor/github.com/Sirupsen/logrus/hooks/airbrake/airbrake.go +++ /dev/null @@ -1,54 +0,0 @@ -package airbrake - -import ( - "errors" - "fmt" - - "github.com/Sirupsen/logrus" - "github.com/tobi/airbrake-go" -) - -// AirbrakeHook to send exceptions to an exception-tracking service compatible -// with the Airbrake API. -type airbrakeHook struct { - APIKey string - Endpoint string - Environment string -} - -func NewHook(endpoint, apiKey, env string) *airbrakeHook { - return &airbrakeHook{ - APIKey: apiKey, - Endpoint: endpoint, - Environment: env, - } -} - -func (hook *airbrakeHook) Fire(entry *logrus.Entry) error { - airbrake.ApiKey = hook.APIKey - airbrake.Endpoint = hook.Endpoint - airbrake.Environment = hook.Environment - - var notifyErr error - err, ok := entry.Data["error"].(error) - if ok { - notifyErr = err - } else { - notifyErr = errors.New(entry.Message) - } - - airErr := airbrake.Notify(notifyErr) - if airErr != nil { - return fmt.Errorf("Failed to send error to Airbrake: %s", airErr) - } - - return nil -} - -func (hook *airbrakeHook) Levels() []logrus.Level { - return []logrus.Level{ - logrus.ErrorLevel, - logrus.FatalLevel, - logrus.PanicLevel, - } -} diff --git a/vendor/github.com/Sirupsen/logrus/hooks/airbrake/airbrake_test.go b/vendor/github.com/Sirupsen/logrus/hooks/airbrake/airbrake_test.go deleted file mode 100644 index 058a91e3..00000000 --- a/vendor/github.com/Sirupsen/logrus/hooks/airbrake/airbrake_test.go +++ /dev/null @@ -1,133 +0,0 @@ -package airbrake - -import ( - "encoding/xml" - "net/http" - "net/http/httptest" - "testing" - "time" - - "github.com/Sirupsen/logrus" -) - -type notice struct { - Error NoticeError `xml:"error"` -} -type NoticeError struct { - Class string `xml:"class"` - Message string `xml:"message"` -} - -type customErr struct { - msg string -} - -func (e *customErr) Error() string { - return e.msg -} - -const ( - testAPIKey = "abcxyz" - testEnv = "development" - expectedClass = "*airbrake.customErr" - expectedMsg = "foo" - unintendedMsg = "Airbrake will not see this string" -) - -var ( - noticeError = make(chan NoticeError, 1) -) - -// TestLogEntryMessageReceived checks if invoking Logrus' log.Error -// method causes an XML payload containing the log entry message is received -// by a HTTP server emulating an Airbrake-compatible endpoint. -func TestLogEntryMessageReceived(t *testing.T) { - log := logrus.New() - ts := startAirbrakeServer(t) - defer ts.Close() - - hook := NewHook(ts.URL, testAPIKey, "production") - log.Hooks.Add(hook) - - log.Error(expectedMsg) - - select { - case received := <-noticeError: - if received.Message != expectedMsg { - t.Errorf("Unexpected message received: %s", received.Message) - } - case <-time.After(time.Second): - t.Error("Timed out; no notice received by Airbrake API") - } -} - -// TestLogEntryMessageReceived confirms that, when passing an error type using -// logrus.Fields, a HTTP server emulating an Airbrake endpoint receives the -// error message returned by the Error() method on the error interface -// rather than the logrus.Entry.Message string. -func TestLogEntryWithErrorReceived(t *testing.T) { - log := logrus.New() - ts := startAirbrakeServer(t) - defer ts.Close() - - hook := NewHook(ts.URL, testAPIKey, "production") - log.Hooks.Add(hook) - - log.WithFields(logrus.Fields{ - "error": &customErr{expectedMsg}, - }).Error(unintendedMsg) - - select { - case received := <-noticeError: - if received.Message != expectedMsg { - t.Errorf("Unexpected message received: %s", received.Message) - } - if received.Class != expectedClass { - t.Errorf("Unexpected error class: %s", received.Class) - } - case <-time.After(time.Second): - t.Error("Timed out; no notice received by Airbrake API") - } -} - -// TestLogEntryWithNonErrorTypeNotReceived confirms that, when passing a -// non-error type using logrus.Fields, a HTTP server emulating an Airbrake -// endpoint receives the logrus.Entry.Message string. -// -// Only error types are supported when setting the 'error' field using -// logrus.WithFields(). -func TestLogEntryWithNonErrorTypeNotReceived(t *testing.T) { - log := logrus.New() - ts := startAirbrakeServer(t) - defer ts.Close() - - hook := NewHook(ts.URL, testAPIKey, "production") - log.Hooks.Add(hook) - - log.WithFields(logrus.Fields{ - "error": expectedMsg, - }).Error(unintendedMsg) - - select { - case received := <-noticeError: - if received.Message != unintendedMsg { - t.Errorf("Unexpected message received: %s", received.Message) - } - case <-time.After(time.Second): - t.Error("Timed out; no notice received by Airbrake API") - } -} - -func startAirbrakeServer(t *testing.T) *httptest.Server { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - var notice notice - if err := xml.NewDecoder(r.Body).Decode(¬ice); err != nil { - t.Error(err) - } - r.Body.Close() - - noticeError <- notice.Error - })) - - return ts -} diff --git a/vendor/github.com/Sirupsen/logrus/hooks/bugsnag/bugsnag.go b/vendor/github.com/Sirupsen/logrus/hooks/bugsnag/bugsnag.go deleted file mode 100644 index d20a0f54..00000000 --- a/vendor/github.com/Sirupsen/logrus/hooks/bugsnag/bugsnag.go +++ /dev/null @@ -1,68 +0,0 @@ -package logrus_bugsnag - -import ( - "errors" - - "github.com/Sirupsen/logrus" - "github.com/bugsnag/bugsnag-go" -) - -type bugsnagHook struct{} - -// ErrBugsnagUnconfigured is returned if NewBugsnagHook is called before -// bugsnag.Configure. Bugsnag must be configured before the hook. -var ErrBugsnagUnconfigured = errors.New("bugsnag must be configured before installing this logrus hook") - -// ErrBugsnagSendFailed indicates that the hook failed to submit an error to -// bugsnag. The error was successfully generated, but `bugsnag.Notify()` -// failed. -type ErrBugsnagSendFailed struct { - err error -} - -func (e ErrBugsnagSendFailed) Error() string { - return "failed to send error to Bugsnag: " + e.err.Error() -} - -// NewBugsnagHook initializes a logrus hook which sends exceptions to an -// exception-tracking service compatible with the Bugsnag API. Before using -// this hook, you must call bugsnag.Configure(). The returned object should be -// registered with a log via `AddHook()` -// -// Entries that trigger an Error, Fatal or Panic should now include an "error" -// field to send to Bugsnag. -func NewBugsnagHook() (*bugsnagHook, error) { - if bugsnag.Config.APIKey == "" { - return nil, ErrBugsnagUnconfigured - } - return &bugsnagHook{}, nil -} - -// Fire forwards an error to Bugsnag. Given a logrus.Entry, it extracts the -// "error" field (or the Message if the error isn't present) and sends it off. -func (hook *bugsnagHook) Fire(entry *logrus.Entry) error { - var notifyErr error - err, ok := entry.Data["error"].(error) - if ok { - notifyErr = err - } else { - notifyErr = errors.New(entry.Message) - } - - bugsnagErr := bugsnag.Notify(notifyErr) - if bugsnagErr != nil { - return ErrBugsnagSendFailed{bugsnagErr} - } - - return nil -} - -// Levels enumerates the log levels on which the error should be forwarded to -// bugsnag: everything at or above the "Error" level. -func (hook *bugsnagHook) Levels() []logrus.Level { - return []logrus.Level{ - logrus.ErrorLevel, - logrus.FatalLevel, - logrus.PanicLevel, - } -} diff --git a/vendor/github.com/Sirupsen/logrus/hooks/bugsnag/bugsnag_test.go b/vendor/github.com/Sirupsen/logrus/hooks/bugsnag/bugsnag_test.go deleted file mode 100644 index e9ea298d..00000000 --- a/vendor/github.com/Sirupsen/logrus/hooks/bugsnag/bugsnag_test.go +++ /dev/null @@ -1,64 +0,0 @@ -package logrus_bugsnag - -import ( - "encoding/json" - "errors" - "io/ioutil" - "net/http" - "net/http/httptest" - "testing" - "time" - - "github.com/Sirupsen/logrus" - "github.com/bugsnag/bugsnag-go" -) - -type notice struct { - Events []struct { - Exceptions []struct { - Message string `json:"message"` - } `json:"exceptions"` - } `json:"events"` -} - -func TestNoticeReceived(t *testing.T) { - msg := make(chan string, 1) - expectedMsg := "foo" - - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - var notice notice - data, _ := ioutil.ReadAll(r.Body) - if err := json.Unmarshal(data, ¬ice); err != nil { - t.Error(err) - } - _ = r.Body.Close() - - msg <- notice.Events[0].Exceptions[0].Message - })) - defer ts.Close() - - hook := &bugsnagHook{} - - bugsnag.Configure(bugsnag.Configuration{ - Endpoint: ts.URL, - ReleaseStage: "production", - APIKey: "12345678901234567890123456789012", - Synchronous: true, - }) - - log := logrus.New() - log.Hooks.Add(hook) - - log.WithFields(logrus.Fields{ - "error": errors.New(expectedMsg), - }).Error("Bugsnag will not see this string") - - select { - case received := <-msg: - if received != expectedMsg { - t.Errorf("Unexpected message received: %s", received) - } - case <-time.After(time.Second): - t.Error("Timed out; no notice received by Bugsnag API") - } -} diff --git a/vendor/github.com/Sirupsen/logrus/hooks/papertrail/README.md b/vendor/github.com/Sirupsen/logrus/hooks/papertrail/README.md deleted file mode 100644 index ae61e922..00000000 --- a/vendor/github.com/Sirupsen/logrus/hooks/papertrail/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# Papertrail Hook for Logrus :walrus: - -[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/vendor/github.com/Sirupsen/logrus/hooks/papertrail/papertrail.go b/vendor/github.com/Sirupsen/logrus/hooks/papertrail/papertrail.go deleted file mode 100644 index c0f10c1b..00000000 --- a/vendor/github.com/Sirupsen/logrus/hooks/papertrail/papertrail.go +++ /dev/null @@ -1,55 +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) - msg, _ := entry.String() - payload := fmt.Sprintf("<22> %s %s: %s", date, hook.AppName, msg) - - 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/vendor/github.com/Sirupsen/logrus/hooks/papertrail/papertrail_test.go b/vendor/github.com/Sirupsen/logrus/hooks/papertrail/papertrail_test.go deleted file mode 100644 index 96318d00..00000000 --- a/vendor/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/vendor/github.com/Sirupsen/logrus/hooks/sentry/README.md b/vendor/github.com/Sirupsen/logrus/hooks/sentry/README.md deleted file mode 100644 index 31de6540..00000000 --- a/vendor/github.com/Sirupsen/logrus/hooks/sentry/README.md +++ /dev/null @@ -1,111 +0,0 @@ -# Sentry Hook for Logrus :walrus: - -[Sentry](https://getsentry.com) provides both self-hosted and hosted -solutions for exception tracking. -Both client and server are -[open source](https://github.com/getsentry/sentry). - -## Usage - -Every sentry application defined on the server gets a different -[DSN](https://www.getsentry.com/docs/). In the example below replace -`YOUR_DSN` with the one created for your application. - -```go -import ( - "github.com/Sirupsen/logrus" - "github.com/Sirupsen/logrus/hooks/sentry" -) - -func main() { - log := logrus.New() - hook, err := logrus_sentry.NewSentryHook(YOUR_DSN, []logrus.Level{ - logrus.PanicLevel, - logrus.FatalLevel, - logrus.ErrorLevel, - }) - - if err == nil { - log.Hooks.Add(hook) - } -} -``` - -If you wish to initialize a SentryHook with tags, you can use the `NewWithTagsSentryHook` constructor to provide default tags: - -```go -tags := map[string]string{ - "site": "example.com", -} -levels := []logrus.Level{ - logrus.PanicLevel, - logrus.FatalLevel, - logrus.ErrorLevel, -} -hook, err := logrus_sentry.NewWithTagsSentryHook(YOUR_DSN, tags, levels) - -``` - -If you wish to initialize a SentryHook with an already initialized raven client, you can use -the `NewWithClientSentryHook` constructor: - -```go -import ( - "github.com/Sirupsen/logrus" - "github.com/Sirupsen/logrus/hooks/sentry" - "github.com/getsentry/raven-go" -) - -func main() { - log := logrus.New() - - client, err := raven.New(YOUR_DSN) - if err != nil { - log.Fatal(err) - } - - hook, err := logrus_sentry.NewWithClientSentryHook(client, []logrus.Level{ - logrus.PanicLevel, - logrus.FatalLevel, - logrus.ErrorLevel, - }) - - if err == nil { - log.Hooks.Add(hook) - } -} - -hook, err := NewWithClientSentryHook(client, []logrus.Level{ - logrus.ErrorLevel, -}) -``` - -## Special fields - -Some logrus fields have a special meaning in this hook, -these are `server_name`, `logger` and `http_request`. -When logs are sent to sentry these fields are treated differently. -- `server_name` (also known as hostname) is the name of the server which -is logging the event (hostname.example.com) -- `logger` is the part of the application which is logging the event. -In go this usually means setting it to the name of the package. -- `http_request` is the in-coming request(*http.Request). The detailed request data are sent to Sentry. - -## Timeout - -`Timeout` is the time the sentry hook will wait for a response -from the sentry server. - -If this time elapses with no response from -the server an error will be returned. - -If `Timeout` is set to 0 the SentryHook will not wait for a reply -and will assume a correct delivery. - -The SentryHook has a default timeout of `100 milliseconds` when created -with a call to `NewSentryHook`. This can be changed by assigning a value to the `Timeout` field: - -```go -hook, _ := logrus_sentry.NewSentryHook(...) -hook.Timeout = 20*time.Second -``` diff --git a/vendor/github.com/Sirupsen/logrus/hooks/sentry/sentry.go b/vendor/github.com/Sirupsen/logrus/hooks/sentry/sentry.go deleted file mode 100644 index cf88098a..00000000 --- a/vendor/github.com/Sirupsen/logrus/hooks/sentry/sentry.go +++ /dev/null @@ -1,137 +0,0 @@ -package logrus_sentry - -import ( - "fmt" - "net/http" - "time" - - "github.com/Sirupsen/logrus" - "github.com/getsentry/raven-go" -) - -var ( - severityMap = map[logrus.Level]raven.Severity{ - logrus.DebugLevel: raven.DEBUG, - logrus.InfoLevel: raven.INFO, - logrus.WarnLevel: raven.WARNING, - logrus.ErrorLevel: raven.ERROR, - logrus.FatalLevel: raven.FATAL, - logrus.PanicLevel: raven.FATAL, - } -) - -func getAndDel(d logrus.Fields, key string) (string, bool) { - var ( - ok bool - v interface{} - val string - ) - if v, ok = d[key]; !ok { - return "", false - } - - if val, ok = v.(string); !ok { - return "", false - } - delete(d, key) - return val, true -} - -func getAndDelRequest(d logrus.Fields, key string) (*http.Request, bool) { - var ( - ok bool - v interface{} - req *http.Request - ) - if v, ok = d[key]; !ok { - return nil, false - } - if req, ok = v.(*http.Request); !ok || req == nil { - return nil, false - } - delete(d, key) - return req, true -} - -// SentryHook delivers logs to a sentry server. -type SentryHook struct { - // Timeout sets the time to wait for a delivery error from the sentry server. - // If this is set to zero the server will not wait for any response and will - // consider the message correctly sent - Timeout time.Duration - - client *raven.Client - levels []logrus.Level -} - -// NewSentryHook creates a hook to be added to an instance of logger -// and initializes the raven client. -// This method sets the timeout to 100 milliseconds. -func NewSentryHook(DSN string, levels []logrus.Level) (*SentryHook, error) { - client, err := raven.New(DSN) - if err != nil { - return nil, err - } - return &SentryHook{100 * time.Millisecond, client, levels}, nil -} - -// NewWithTagsSentryHook creates a hook with tags to be added to an instance -// of logger and initializes the raven client. This method sets the timeout to -// 100 milliseconds. -func NewWithTagsSentryHook(DSN string, tags map[string]string, levels []logrus.Level) (*SentryHook, error) { - client, err := raven.NewWithTags(DSN, tags) - if err != nil { - return nil, err - } - return &SentryHook{100 * time.Millisecond, client, levels}, nil -} - -// NewWithClientSentryHook creates a hook using an initialized raven client. -// This method sets the timeout to 100 milliseconds. -func NewWithClientSentryHook(client *raven.Client, levels []logrus.Level) (*SentryHook, error) { - return &SentryHook{100 * time.Millisecond, client, levels}, nil -} - -// Called when an event should be sent to sentry -// Special fields that sentry uses to give more information to the server -// are extracted from entry.Data (if they are found) -// These fields are: logger, server_name and http_request -func (hook *SentryHook) Fire(entry *logrus.Entry) error { - packet := &raven.Packet{ - Message: entry.Message, - Timestamp: raven.Timestamp(entry.Time), - Level: severityMap[entry.Level], - Platform: "go", - } - - d := entry.Data - - if logger, ok := getAndDel(d, "logger"); ok { - packet.Logger = logger - } - if serverName, ok := getAndDel(d, "server_name"); ok { - packet.ServerName = serverName - } - if req, ok := getAndDelRequest(d, "http_request"); ok { - packet.Interfaces = append(packet.Interfaces, raven.NewHttp(req)) - } - packet.Extra = map[string]interface{}(d) - - _, errCh := hook.client.Capture(packet, nil) - timeout := hook.Timeout - if timeout != 0 { - timeoutCh := time.After(timeout) - select { - case err := <-errCh: - return err - case <-timeoutCh: - return fmt.Errorf("no response from sentry server in %s", timeout) - } - } - return nil -} - -// Levels returns the available logging levels. -func (hook *SentryHook) Levels() []logrus.Level { - return hook.levels -} diff --git a/vendor/github.com/Sirupsen/logrus/hooks/sentry/sentry_test.go b/vendor/github.com/Sirupsen/logrus/hooks/sentry/sentry_test.go deleted file mode 100644 index 4a97bc63..00000000 --- a/vendor/github.com/Sirupsen/logrus/hooks/sentry/sentry_test.go +++ /dev/null @@ -1,154 +0,0 @@ -package logrus_sentry - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "net/http/httptest" - "reflect" - "strings" - "testing" - - "github.com/Sirupsen/logrus" - "github.com/getsentry/raven-go" -) - -const ( - message = "error message" - server_name = "testserver.internal" - logger_name = "test.logger" -) - -func getTestLogger() *logrus.Logger { - l := logrus.New() - l.Out = ioutil.Discard - return l -} - -func WithTestDSN(t *testing.T, tf func(string, <-chan *raven.Packet)) { - pch := make(chan *raven.Packet, 1) - s := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - defer req.Body.Close() - d := json.NewDecoder(req.Body) - p := &raven.Packet{} - err := d.Decode(p) - if err != nil { - t.Fatal(err.Error()) - } - - pch <- p - })) - defer s.Close() - - fragments := strings.SplitN(s.URL, "://", 2) - dsn := fmt.Sprintf( - "%s://public:secret@%s/sentry/project-id", - fragments[0], - fragments[1], - ) - tf(dsn, pch) -} - -func TestSpecialFields(t *testing.T) { - WithTestDSN(t, func(dsn string, pch <-chan *raven.Packet) { - logger := getTestLogger() - - hook, err := NewSentryHook(dsn, []logrus.Level{ - logrus.ErrorLevel, - }) - - if err != nil { - t.Fatal(err.Error()) - } - logger.Hooks.Add(hook) - - req, _ := http.NewRequest("GET", "url", nil) - logger.WithFields(logrus.Fields{ - "server_name": server_name, - "logger": logger_name, - "http_request": req, - }).Error(message) - - packet := <-pch - if packet.Logger != logger_name { - t.Errorf("logger should have been %s, was %s", logger_name, packet.Logger) - } - - if packet.ServerName != server_name { - t.Errorf("server_name should have been %s, was %s", server_name, packet.ServerName) - } - }) -} - -func TestSentryHandler(t *testing.T) { - WithTestDSN(t, func(dsn string, pch <-chan *raven.Packet) { - logger := getTestLogger() - hook, err := NewSentryHook(dsn, []logrus.Level{ - logrus.ErrorLevel, - }) - if err != nil { - t.Fatal(err.Error()) - } - logger.Hooks.Add(hook) - - logger.Error(message) - packet := <-pch - if packet.Message != message { - t.Errorf("message should have been %s, was %s", message, packet.Message) - } - }) -} - -func TestSentryWithClient(t *testing.T) { - WithTestDSN(t, func(dsn string, pch <-chan *raven.Packet) { - logger := getTestLogger() - - client, _ := raven.New(dsn) - - hook, err := NewWithClientSentryHook(client, []logrus.Level{ - logrus.ErrorLevel, - }) - if err != nil { - t.Fatal(err.Error()) - } - logger.Hooks.Add(hook) - - logger.Error(message) - packet := <-pch - if packet.Message != message { - t.Errorf("message should have been %s, was %s", message, packet.Message) - } - }) -} - -func TestSentryTags(t *testing.T) { - WithTestDSN(t, func(dsn string, pch <-chan *raven.Packet) { - logger := getTestLogger() - tags := map[string]string{ - "site": "test", - } - levels := []logrus.Level{ - logrus.ErrorLevel, - } - - hook, err := NewWithTagsSentryHook(dsn, tags, levels) - if err != nil { - t.Fatal(err.Error()) - } - - logger.Hooks.Add(hook) - - logger.Error(message) - packet := <-pch - expected := raven.Tags{ - raven.Tag{ - Key: "site", - Value: "test", - }, - } - if !reflect.DeepEqual(packet.Tags, expected) { - t.Errorf("message should have been %s, was %s", message, packet.Message) - } - }) -} diff --git a/vendor/github.com/Sirupsen/logrus/hooks/syslog/README.md b/vendor/github.com/Sirupsen/logrus/hooks/syslog/README.md deleted file mode 100644 index 4dbb8e72..00000000 --- a/vendor/github.com/Sirupsen/logrus/hooks/syslog/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Syslog Hooks for Logrus :walrus: - -## Usage - -```go -import ( - "log/syslog" - "github.com/Sirupsen/logrus" - logrus_syslog "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) - } -} -``` diff --git a/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog.go b/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog.go deleted file mode 100644 index b6fa3746..00000000 --- a/vendor/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/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog_test.go b/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog_test.go deleted file mode 100644 index 42762dc1..00000000 --- a/vendor/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/vendor/github.com/codegangsta/cli/autocomplete/bash_autocomplete b/vendor/github.com/codegangsta/cli/autocomplete/bash_autocomplete deleted file mode 100644 index 21a232f1..00000000 --- a/vendor/github.com/codegangsta/cli/autocomplete/bash_autocomplete +++ /dev/null @@ -1,14 +0,0 @@ -#! /bin/bash - -: ${PROG:=$(basename ${BASH_SOURCE})} - -_cli_bash_autocomplete() { - local cur opts base - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion ) - COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) - return 0 - } - - complete -F _cli_bash_autocomplete $PROG diff --git a/vendor/github.com/codegangsta/cli/autocomplete/zsh_autocomplete b/vendor/github.com/codegangsta/cli/autocomplete/zsh_autocomplete deleted file mode 100644 index 5430a18f..00000000 --- a/vendor/github.com/codegangsta/cli/autocomplete/zsh_autocomplete +++ /dev/null @@ -1,5 +0,0 @@ -autoload -U compinit && compinit -autoload -U bashcompinit && bashcompinit - -script_dir=$(dirname $0) -source ${script_dir}/bash_autocomplete diff --git a/vendor/github.com/coreos/coreos-cloudinit/config/validate/context.go b/vendor/github.com/coreos/coreos-cloudinit/config/validate/context.go deleted file mode 100644 index 53083a48..00000000 --- a/vendor/github.com/coreos/coreos-cloudinit/config/validate/context.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package validate - -import ( - "strings" -) - -// context represents the current position within a newline-delimited string. -// Each line is loaded, one by one, into currentLine (newline omitted) and -// lineNumber keeps track of its position within the original string. -type context struct { - currentLine string - remainingLines string - lineNumber int -} - -// Increment moves the context to the next line (if available). -func (c *context) Increment() { - if c.currentLine == "" && c.remainingLines == "" { - return - } - - lines := strings.SplitN(c.remainingLines, "\n", 2) - c.currentLine = lines[0] - if len(lines) == 2 { - c.remainingLines = lines[1] - } else { - c.remainingLines = "" - } - c.lineNumber++ -} - -// NewContext creates a context from the provided data. It strips out all -// carriage returns and moves to the first line (if available). -func NewContext(content []byte) context { - c := context{remainingLines: strings.Replace(string(content), "\r", "", -1)} - c.Increment() - return c -} diff --git a/vendor/github.com/coreos/coreos-cloudinit/config/validate/context_test.go b/vendor/github.com/coreos/coreos-cloudinit/config/validate/context_test.go deleted file mode 100644 index 335b4230..00000000 --- a/vendor/github.com/coreos/coreos-cloudinit/config/validate/context_test.go +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package validate - -import ( - "reflect" - "testing" -) - -func TestNewContext(t *testing.T) { - tests := []struct { - in string - - out context - }{ - { - out: context{ - currentLine: "", - remainingLines: "", - lineNumber: 0, - }, - }, - { - in: "this\r\nis\r\na\r\ntest", - out: context{ - currentLine: "this", - remainingLines: "is\na\ntest", - lineNumber: 1, - }, - }, - } - - for _, tt := range tests { - if out := NewContext([]byte(tt.in)); !reflect.DeepEqual(tt.out, out) { - t.Errorf("bad context (%q): want %#v, got %#v", tt.in, tt.out, out) - } - } -} - -func TestIncrement(t *testing.T) { - tests := []struct { - init context - op func(c *context) - - res context - }{ - { - init: context{ - currentLine: "", - remainingLines: "", - lineNumber: 0, - }, - res: context{ - currentLine: "", - remainingLines: "", - lineNumber: 0, - }, - op: func(c *context) { - c.Increment() - }, - }, - { - init: context{ - currentLine: "test", - remainingLines: "", - lineNumber: 1, - }, - res: context{ - currentLine: "", - remainingLines: "", - lineNumber: 2, - }, - op: func(c *context) { - c.Increment() - c.Increment() - c.Increment() - }, - }, - { - init: context{ - currentLine: "this", - remainingLines: "is\na\ntest", - lineNumber: 1, - }, - res: context{ - currentLine: "is", - remainingLines: "a\ntest", - lineNumber: 2, - }, - op: func(c *context) { - c.Increment() - }, - }, - { - init: context{ - currentLine: "this", - remainingLines: "is\na\ntest", - lineNumber: 1, - }, - res: context{ - currentLine: "test", - remainingLines: "", - lineNumber: 4, - }, - op: func(c *context) { - c.Increment() - c.Increment() - c.Increment() - }, - }, - } - - for i, tt := range tests { - res := tt.init - if tt.op(&res); !reflect.DeepEqual(tt.res, res) { - t.Errorf("bad context (%d, %#v): want %#v, got %#v", i, tt.init, tt.res, res) - } - } -} diff --git a/vendor/github.com/coreos/coreos-cloudinit/config/validate/node.go b/vendor/github.com/coreos/coreos-cloudinit/config/validate/node.go deleted file mode 100644 index 892be459..00000000 --- a/vendor/github.com/coreos/coreos-cloudinit/config/validate/node.go +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package validate - -import ( - "fmt" - "reflect" - "regexp" -) - -var ( - yamlKey = regexp.MustCompile(`^ *-? ?(?P.*?):`) - yamlElem = regexp.MustCompile(`^ *-`) -) - -type node struct { - name string - line int - children []node - field reflect.StructField - reflect.Value -} - -// Child attempts to find the child with the given name in the node's list of -// children. If no such child is found, an invalid node is returned. -func (n node) Child(name string) node { - for _, c := range n.children { - if c.name == name { - return c - } - } - return node{} -} - -// HumanType returns the human-consumable string representation of the type of -// the node. -func (n node) HumanType() string { - switch k := n.Kind(); k { - case reflect.Slice: - c := n.Type().Elem() - return "[]" + node{Value: reflect.New(c).Elem()}.HumanType() - default: - return k.String() - } -} - -// NewNode returns the node representation of the given value. The context -// will be used in an attempt to determine line numbers for the given value. -func NewNode(value interface{}, context context) node { - var n node - toNode(value, context, &n) - return n -} - -// toNode converts the given value into a node and then recursively processes -// each of the nodes components (e.g. fields, array elements, keys). -func toNode(v interface{}, c context, n *node) { - vv := reflect.ValueOf(v) - if !vv.IsValid() { - return - } - - n.Value = vv - switch vv.Kind() { - case reflect.Struct: - // Walk over each field in the structure, skipping unexported fields, - // and create a node for it. - for i := 0; i < vv.Type().NumField(); i++ { - ft := vv.Type().Field(i) - k := ft.Tag.Get("yaml") - if k == "-" || k == "" { - continue - } - - cn := node{name: k, field: ft} - c, ok := findKey(cn.name, c) - if ok { - cn.line = c.lineNumber - } - toNode(vv.Field(i).Interface(), c, &cn) - n.children = append(n.children, cn) - } - case reflect.Map: - // Walk over each key in the map and create a node for it. - v := v.(map[interface{}]interface{}) - for k, cv := range v { - cn := node{name: fmt.Sprintf("%s", k)} - c, ok := findKey(cn.name, c) - if ok { - cn.line = c.lineNumber - } - toNode(cv, c, &cn) - n.children = append(n.children, cn) - } - case reflect.Slice: - // Walk over each element in the slice and create a node for it. - // While iterating over the slice, preserve the context after it - // is modified. This allows the line numbers to reflect the current - // element instead of the first. - for i := 0; i < vv.Len(); i++ { - cn := node{ - name: fmt.Sprintf("%s[%d]", n.name, i), - field: n.field, - } - var ok bool - c, ok = findElem(c) - if ok { - cn.line = c.lineNumber - } - toNode(vv.Index(i).Interface(), c, &cn) - n.children = append(n.children, cn) - c.Increment() - } - case reflect.String, reflect.Int, reflect.Bool, reflect.Float64: - default: - panic(fmt.Sprintf("toNode(): unhandled kind %s", vv.Kind())) - } -} - -// findKey attempts to find the requested key within the provided context. -// A modified copy of the context is returned with every line up to the key -// incremented past. A boolean, true if the key was found, is also returned. -func findKey(key string, context context) (context, bool) { - return find(yamlKey, key, context) -} - -// findElem attempts to find an array element within the provided context. -// A modified copy of the context is returned with every line up to the array -// element incremented past. A boolean, true if the key was found, is also -// returned. -func findElem(context context) (context, bool) { - return find(yamlElem, "", context) -} - -func find(exp *regexp.Regexp, key string, context context) (context, bool) { - for len(context.currentLine) > 0 || len(context.remainingLines) > 0 { - matches := exp.FindStringSubmatch(context.currentLine) - if len(matches) > 0 && (key == "" || matches[1] == key) { - return context, true - } - - context.Increment() - } - return context, false -} diff --git a/vendor/github.com/coreos/coreos-cloudinit/config/validate/node_test.go b/vendor/github.com/coreos/coreos-cloudinit/config/validate/node_test.go deleted file mode 100644 index 1a347c1c..00000000 --- a/vendor/github.com/coreos/coreos-cloudinit/config/validate/node_test.go +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package validate - -import ( - "reflect" - "testing" -) - -func TestChild(t *testing.T) { - tests := []struct { - parent node - name string - - child node - }{ - {}, - { - name: "c1", - }, - { - parent: node{ - children: []node{ - node{name: "c1"}, - node{name: "c2"}, - node{name: "c3"}, - }, - }, - }, - { - parent: node{ - children: []node{ - node{name: "c1"}, - node{name: "c2"}, - node{name: "c3"}, - }, - }, - name: "c2", - child: node{name: "c2"}, - }, - } - - for _, tt := range tests { - if child := tt.parent.Child(tt.name); !reflect.DeepEqual(tt.child, child) { - t.Errorf("bad child (%q): want %#v, got %#v", tt.name, tt.child, child) - } - } -} - -func TestHumanType(t *testing.T) { - tests := []struct { - node node - - humanType string - }{ - { - humanType: "invalid", - }, - { - node: node{Value: reflect.ValueOf("hello")}, - humanType: "string", - }, - { - node: node{ - Value: reflect.ValueOf([]int{1, 2}), - children: []node{ - node{Value: reflect.ValueOf(1)}, - node{Value: reflect.ValueOf(2)}, - }}, - humanType: "[]int", - }, - } - - for _, tt := range tests { - if humanType := tt.node.HumanType(); tt.humanType != humanType { - t.Errorf("bad type (%q): want %q, got %q", tt.node, tt.humanType, humanType) - } - } -} - -func TestToNode(t *testing.T) { - tests := []struct { - value interface{} - context context - - node node - }{ - {}, - { - value: struct{}{}, - node: node{Value: reflect.ValueOf(struct{}{})}, - }, - { - value: struct { - A int `yaml:"a"` - }{}, - node: node{ - children: []node{ - node{ - name: "a", - field: reflect.TypeOf(struct { - A int `yaml:"a"` - }{}).Field(0), - }, - }, - }, - }, - { - value: struct { - A []int `yaml:"a"` - }{}, - node: node{ - children: []node{ - node{ - name: "a", - field: reflect.TypeOf(struct { - A []int `yaml:"a"` - }{}).Field(0), - }, - }, - }, - }, - { - value: map[interface{}]interface{}{ - "a": map[interface{}]interface{}{ - "b": 2, - }, - }, - context: NewContext([]byte("a:\n b: 2")), - node: node{ - children: []node{ - node{ - line: 1, - name: "a", - children: []node{ - node{name: "b", line: 2}, - }, - }, - }, - }, - }, - { - value: struct { - A struct { - Jon bool `yaml:"b"` - } `yaml:"a"` - }{}, - node: node{ - children: []node{ - node{ - name: "a", - children: []node{ - node{ - name: "b", - field: reflect.TypeOf(struct { - Jon bool `yaml:"b"` - }{}).Field(0), - Value: reflect.ValueOf(false), - }, - }, - field: reflect.TypeOf(struct { - A struct { - Jon bool `yaml:"b"` - } `yaml:"a"` - }{}).Field(0), - Value: reflect.ValueOf(struct { - Jon bool `yaml:"b"` - }{}), - }, - }, - Value: reflect.ValueOf(struct { - A struct { - Jon bool `yaml:"b"` - } `yaml:"a"` - }{}), - }, - }, - } - - for _, tt := range tests { - var node node - toNode(tt.value, tt.context, &node) - if !nodesEqual(tt.node, node) { - t.Errorf("bad node (%#v): want %#v, got %#v", tt.value, tt.node, node) - } - } -} - -func TestFindKey(t *testing.T) { - tests := []struct { - key string - context context - - found bool - }{ - {}, - { - key: "key1", - context: NewContext([]byte("key1: hi")), - found: true, - }, - { - key: "key2", - context: NewContext([]byte("key1: hi")), - found: false, - }, - { - key: "key3", - context: NewContext([]byte("key1:\n key2:\n key3: hi")), - found: true, - }, - { - key: "key4", - context: NewContext([]byte("key1:\n - key4: hi")), - found: true, - }, - { - key: "key5", - context: NewContext([]byte("#key5")), - found: false, - }, - } - - for _, tt := range tests { - if _, found := findKey(tt.key, tt.context); tt.found != found { - t.Errorf("bad find (%q): want %t, got %t", tt.key, tt.found, found) - } - } -} - -func TestFindElem(t *testing.T) { - tests := []struct { - context context - - found bool - }{ - {}, - { - context: NewContext([]byte("test: hi")), - found: false, - }, - { - context: NewContext([]byte("test:\n - a\n -b")), - found: true, - }, - { - context: NewContext([]byte("test:\n -\n a")), - found: true, - }, - } - - for _, tt := range tests { - if _, found := findElem(tt.context); tt.found != found { - t.Errorf("bad find (%q): want %t, got %t", tt.context, tt.found, found) - } - } -} - -func nodesEqual(a, b node) bool { - if a.name != b.name || - a.line != b.line || - !reflect.DeepEqual(a.field, b.field) || - len(a.children) != len(b.children) { - return false - } - for i := 0; i < len(a.children); i++ { - if !nodesEqual(a.children[i], b.children[i]) { - return false - } - } - return true -} diff --git a/vendor/github.com/coreos/coreos-cloudinit/config/validate/report.go b/vendor/github.com/coreos/coreos-cloudinit/config/validate/report.go deleted file mode 100644 index 2eff7d96..00000000 --- a/vendor/github.com/coreos/coreos-cloudinit/config/validate/report.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package validate - -import ( - "encoding/json" - "fmt" -) - -// Report represents the list of entries resulting from validation. -type Report struct { - entries []Entry -} - -// Error adds an error entry to the report. -func (r *Report) Error(line int, message string) { - r.entries = append(r.entries, Entry{entryError, message, line}) -} - -// Warning adds a warning entry to the report. -func (r *Report) Warning(line int, message string) { - r.entries = append(r.entries, Entry{entryWarning, message, line}) -} - -// Info adds an info entry to the report. -func (r *Report) Info(line int, message string) { - r.entries = append(r.entries, Entry{entryInfo, message, line}) -} - -// Entries returns the list of entries in the report. -func (r *Report) Entries() []Entry { - return r.entries -} - -// Entry represents a single generic item in the report. -type Entry struct { - kind entryKind - message string - line int -} - -// String returns a human-readable representation of the entry. -func (e Entry) String() string { - return fmt.Sprintf("line %d: %s: %s", e.line, e.kind, e.message) -} - -// MarshalJSON satisfies the json.Marshaler interface, returning the entry -// encoded as a JSON object. -func (e Entry) MarshalJSON() ([]byte, error) { - return json.Marshal(map[string]interface{}{ - "kind": e.kind.String(), - "message": e.message, - "line": e.line, - }) -} - -type entryKind int - -const ( - entryError entryKind = iota - entryWarning - entryInfo -) - -func (k entryKind) String() string { - switch k { - case entryError: - return "error" - case entryWarning: - return "warning" - case entryInfo: - return "info" - default: - panic(fmt.Sprintf("invalid kind %d", k)) - } -} diff --git a/vendor/github.com/coreos/coreos-cloudinit/config/validate/report_test.go b/vendor/github.com/coreos/coreos-cloudinit/config/validate/report_test.go deleted file mode 100644 index ba640064..00000000 --- a/vendor/github.com/coreos/coreos-cloudinit/config/validate/report_test.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package validate - -import ( - "bytes" - "reflect" - "testing" -) - -func TestEntry(t *testing.T) { - tests := []struct { - entry Entry - - str string - json []byte - }{ - { - Entry{entryInfo, "test info", 1}, - "line 1: info: test info", - []byte(`{"kind":"info","line":1,"message":"test info"}`), - }, - { - Entry{entryWarning, "test warning", 1}, - "line 1: warning: test warning", - []byte(`{"kind":"warning","line":1,"message":"test warning"}`), - }, - { - Entry{entryError, "test error", 2}, - "line 2: error: test error", - []byte(`{"kind":"error","line":2,"message":"test error"}`), - }, - } - - for _, tt := range tests { - if str := tt.entry.String(); tt.str != str { - t.Errorf("bad string (%q): want %q, got %q", tt.entry, tt.str, str) - } - json, err := tt.entry.MarshalJSON() - if err != nil { - t.Errorf("bad error (%q): want %v, got %q", tt.entry, nil, err) - } - if !bytes.Equal(tt.json, json) { - t.Errorf("bad JSON (%q): want %q, got %q", tt.entry, tt.json, json) - } - } -} - -func TestReport(t *testing.T) { - type reportFunc struct { - fn func(*Report, int, string) - line int - message string - } - - tests := []struct { - fs []reportFunc - - es []Entry - }{ - { - []reportFunc{ - {(*Report).Warning, 1, "test warning 1"}, - {(*Report).Error, 2, "test error 2"}, - {(*Report).Info, 10, "test info 10"}, - }, - []Entry{ - Entry{entryWarning, "test warning 1", 1}, - Entry{entryError, "test error 2", 2}, - Entry{entryInfo, "test info 10", 10}, - }, - }, - } - - for _, tt := range tests { - r := Report{} - for _, f := range tt.fs { - f.fn(&r, f.line, f.message) - } - if es := r.Entries(); !reflect.DeepEqual(tt.es, es) { - t.Errorf("bad entries (%v): want %#v, got %#v", tt.fs, tt.es, es) - } - } -} diff --git a/vendor/github.com/coreos/coreos-cloudinit/config/validate/rules.go b/vendor/github.com/coreos/coreos-cloudinit/config/validate/rules.go deleted file mode 100644 index 1f65114d..00000000 --- a/vendor/github.com/coreos/coreos-cloudinit/config/validate/rules.go +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package validate - -import ( - "fmt" - "net/url" - "path" - "reflect" - "strings" - - "github.com/coreos/coreos-cloudinit/config" -) - -type rule func(config node, report *Report) - -// Rules contains all of the validation rules. -var Rules []rule = []rule{ - checkDiscoveryUrl, - checkEncoding, - checkStructure, - checkValidity, - checkWriteFiles, - checkWriteFilesUnderCoreos, -} - -// checkDiscoveryUrl verifies that the string is a valid url. -func checkDiscoveryUrl(cfg node, report *Report) { - c := cfg.Child("coreos").Child("etcd").Child("discovery") - if !c.IsValid() { - return - } - - if _, err := url.ParseRequestURI(c.String()); err != nil { - report.Warning(c.line, "discovery URL is not valid") - } -} - -// checkEncoding validates that, for each file under 'write_files', the -// content can be decoded given the specified encoding. -func checkEncoding(cfg node, report *Report) { - for _, f := range cfg.Child("write_files").children { - e := f.Child("encoding") - if !e.IsValid() { - continue - } - - c := f.Child("content") - if _, err := config.DecodeContent(c.String(), e.String()); err != nil { - report.Error(c.line, fmt.Sprintf("content cannot be decoded as %q", e.String())) - } - } -} - -// checkStructure compares the provided config to the empty config.CloudConfig -// structure. Each node is checked to make sure that it exists in the known -// structure and that its type is compatible. -func checkStructure(cfg node, report *Report) { - g := NewNode(config.CloudConfig{}, NewContext([]byte{})) - checkNodeStructure(cfg, g, report) -} - -func checkNodeStructure(n, g node, r *Report) { - if !isCompatible(n.Kind(), g.Kind()) { - r.Warning(n.line, fmt.Sprintf("incorrect type for %q (want %s)", n.name, g.HumanType())) - return - } - - switch g.Kind() { - case reflect.Struct: - for _, cn := range n.children { - if cg := g.Child(cn.name); cg.IsValid() { - checkNodeStructure(cn, cg, r) - } else { - r.Warning(cn.line, fmt.Sprintf("unrecognized key %q", cn.name)) - } - } - case reflect.Slice: - for _, cn := range n.children { - var cg node - c := g.Type().Elem() - toNode(reflect.New(c).Elem().Interface(), context{}, &cg) - checkNodeStructure(cn, cg, r) - } - case reflect.String, reflect.Int, reflect.Float64, reflect.Bool: - default: - panic(fmt.Sprintf("checkNodeStructure(): unhandled kind %s", g.Kind())) - } -} - -// isCompatible determines if the type of kind n can be converted to the type -// of kind g in the context of YAML. This is not an exhaustive list, but its -// enough for the purposes of cloud-config validation. -func isCompatible(n, g reflect.Kind) bool { - switch g { - case reflect.String: - return n == reflect.String || n == reflect.Int || n == reflect.Float64 || n == reflect.Bool - case reflect.Struct: - return n == reflect.Struct || n == reflect.Map - case reflect.Float64: - return n == reflect.Float64 || n == reflect.Int - case reflect.Bool, reflect.Slice, reflect.Int: - return n == g - default: - panic(fmt.Sprintf("isCompatible(): unhandled kind %s", g)) - } -} - -// checkValidity checks the value of every node in the provided config by -// running config.AssertValid() on it. -func checkValidity(cfg node, report *Report) { - g := NewNode(config.CloudConfig{}, NewContext([]byte{})) - checkNodeValidity(cfg, g, report) -} - -func checkNodeValidity(n, g node, r *Report) { - if err := config.AssertValid(n.Value, g.field.Tag.Get("valid")); err != nil { - r.Error(n.line, fmt.Sprintf("invalid value %v", n.Value.Interface())) - } - switch g.Kind() { - case reflect.Struct: - for _, cn := range n.children { - if cg := g.Child(cn.name); cg.IsValid() { - checkNodeValidity(cn, cg, r) - } - } - case reflect.Slice: - for _, cn := range n.children { - var cg node - c := g.Type().Elem() - toNode(reflect.New(c).Elem().Interface(), context{}, &cg) - checkNodeValidity(cn, cg, r) - } - case reflect.String, reflect.Int, reflect.Float64, reflect.Bool: - default: - panic(fmt.Sprintf("checkNodeValidity(): unhandled kind %s", g.Kind())) - } -} - -// checkWriteFiles checks to make sure that the target file can actually be -// written. Note that this check is approximate (it only checks to see if the file -// is under /usr). -func checkWriteFiles(cfg node, report *Report) { - for _, f := range cfg.Child("write_files").children { - c := f.Child("path") - if !c.IsValid() { - continue - } - - d := path.Dir(c.String()) - switch { - case strings.HasPrefix(d, "/usr"): - report.Error(c.line, "file cannot be written to a read-only filesystem") - } - } -} - -// checkWriteFilesUnderCoreos checks to see if the 'write_files' node is a -// child of 'coreos' (it shouldn't be). -func checkWriteFilesUnderCoreos(cfg node, report *Report) { - c := cfg.Child("coreos").Child("write_files") - if c.IsValid() { - report.Info(c.line, "write_files doesn't belong under coreos") - } -} diff --git a/vendor/github.com/coreos/coreos-cloudinit/config/validate/rules_test.go b/vendor/github.com/coreos/coreos-cloudinit/config/validate/rules_test.go deleted file mode 100644 index 01d42316..00000000 --- a/vendor/github.com/coreos/coreos-cloudinit/config/validate/rules_test.go +++ /dev/null @@ -1,399 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package validate - -import ( - "reflect" - "testing" -) - -func TestCheckDiscoveryUrl(t *testing.T) { - tests := []struct { - config string - - entries []Entry - }{ - {}, - { - config: "coreos:\n etcd:\n discovery: https://discovery.etcd.io/00000000000000000000000000000000", - }, - { - config: "coreos:\n etcd:\n discovery: http://custom.domain/mytoken", - }, - { - config: "coreos:\n etcd:\n discovery: disco", - entries: []Entry{{entryWarning, "discovery URL is not valid", 3}}, - }, - } - - for i, tt := range tests { - r := Report{} - n, err := parseCloudConfig([]byte(tt.config), &r) - if err != nil { - panic(err) - } - checkDiscoveryUrl(n, &r) - - if e := r.Entries(); !reflect.DeepEqual(tt.entries, e) { - t.Errorf("bad report (%d, %q): want %#v, got %#v", i, tt.config, tt.entries, e) - } - } -} - -func TestCheckEncoding(t *testing.T) { - tests := []struct { - config string - - entries []Entry - }{ - {}, - { - config: "write_files:\n - encoding: base64\n content: aGVsbG8K", - }, - { - config: "write_files:\n - content: !!binary aGVsbG8K", - }, - { - config: "write_files:\n - encoding: base64\n content: !!binary aGVsbG8K", - entries: []Entry{{entryError, `content cannot be decoded as "base64"`, 3}}, - }, - { - config: "write_files:\n - encoding: base64\n content: !!binary YUdWc2JHOEsK", - }, - { - config: "write_files:\n - encoding: gzip\n content: !!binary H4sIAOC3tVQAA8tIzcnJ5wIAIDA6NgYAAAA=", - }, - { - config: "write_files:\n - encoding: gzip+base64\n content: H4sIAOC3tVQAA8tIzcnJ5wIAIDA6NgYAAAA=", - }, - { - config: "write_files:\n - encoding: custom\n content: hello", - entries: []Entry{{entryError, `content cannot be decoded as "custom"`, 3}}, - }, - } - - for i, tt := range tests { - r := Report{} - n, err := parseCloudConfig([]byte(tt.config), &r) - if err != nil { - panic(err) - } - checkEncoding(n, &r) - - if e := r.Entries(); !reflect.DeepEqual(tt.entries, e) { - t.Errorf("bad report (%d, %q): want %#v, got %#v", i, tt.config, tt.entries, e) - } - } -} - -func TestCheckStructure(t *testing.T) { - tests := []struct { - config string - - entries []Entry - }{ - {}, - - // Test for unrecognized keys - { - config: "test:", - entries: []Entry{{entryWarning, "unrecognized key \"test\"", 1}}, - }, - { - config: "coreos:\n etcd:\n bad:", - entries: []Entry{{entryWarning, "unrecognized key \"bad\"", 3}}, - }, - { - config: "coreos:\n etcd:\n discovery: good", - }, - - // Test for error on list of nodes - { - config: "coreos:\n units:\n - hello\n - goodbye", - entries: []Entry{ - {entryWarning, "incorrect type for \"units[0]\" (want struct)", 3}, - {entryWarning, "incorrect type for \"units[1]\" (want struct)", 4}, - }, - }, - - // Test for incorrect types - // Want boolean - { - config: "coreos:\n units:\n - enable: true", - }, - { - config: "coreos:\n units:\n - enable: 4", - entries: []Entry{{entryWarning, "incorrect type for \"enable\" (want bool)", 3}}, - }, - { - config: "coreos:\n units:\n - enable: bad", - entries: []Entry{{entryWarning, "incorrect type for \"enable\" (want bool)", 3}}, - }, - { - config: "coreos:\n units:\n - enable:\n bad:", - entries: []Entry{{entryWarning, "incorrect type for \"enable\" (want bool)", 3}}, - }, - { - config: "coreos:\n units:\n - enable:\n - bad", - entries: []Entry{{entryWarning, "incorrect type for \"enable\" (want bool)", 3}}, - }, - // Want string - { - config: "hostname: true", - }, - { - config: "hostname: 4", - }, - { - config: "hostname: host", - }, - { - config: "hostname:\n name:", - entries: []Entry{{entryWarning, "incorrect type for \"hostname\" (want string)", 1}}, - }, - { - config: "hostname:\n - name", - entries: []Entry{{entryWarning, "incorrect type for \"hostname\" (want string)", 1}}, - }, - // Want struct - { - config: "coreos: true", - entries: []Entry{{entryWarning, "incorrect type for \"coreos\" (want struct)", 1}}, - }, - { - config: "coreos: 4", - entries: []Entry{{entryWarning, "incorrect type for \"coreos\" (want struct)", 1}}, - }, - { - config: "coreos: hello", - entries: []Entry{{entryWarning, "incorrect type for \"coreos\" (want struct)", 1}}, - }, - { - config: "coreos:\n etcd:\n discovery: fire in the disco", - }, - { - config: "coreos:\n - hello", - entries: []Entry{{entryWarning, "incorrect type for \"coreos\" (want struct)", 1}}, - }, - // Want []string - { - config: "ssh_authorized_keys: true", - entries: []Entry{{entryWarning, "incorrect type for \"ssh_authorized_keys\" (want []string)", 1}}, - }, - { - config: "ssh_authorized_keys: 4", - entries: []Entry{{entryWarning, "incorrect type for \"ssh_authorized_keys\" (want []string)", 1}}, - }, - { - config: "ssh_authorized_keys: key", - entries: []Entry{{entryWarning, "incorrect type for \"ssh_authorized_keys\" (want []string)", 1}}, - }, - { - config: "ssh_authorized_keys:\n key: value", - entries: []Entry{{entryWarning, "incorrect type for \"ssh_authorized_keys\" (want []string)", 1}}, - }, - { - config: "ssh_authorized_keys:\n - key", - }, - { - config: "ssh_authorized_keys:\n - key: value", - entries: []Entry{{entryWarning, "incorrect type for \"ssh_authorized_keys[0]\" (want string)", 2}}, - }, - // Want []struct - { - config: "users:\n true", - entries: []Entry{{entryWarning, "incorrect type for \"users\" (want []struct)", 1}}, - }, - { - config: "users:\n 4", - entries: []Entry{{entryWarning, "incorrect type for \"users\" (want []struct)", 1}}, - }, - { - config: "users:\n bad", - entries: []Entry{{entryWarning, "incorrect type for \"users\" (want []struct)", 1}}, - }, - { - config: "users:\n bad:", - entries: []Entry{{entryWarning, "incorrect type for \"users\" (want []struct)", 1}}, - }, - { - config: "users:\n - name: good", - }, - // Want struct within array - { - config: "users:\n - true", - entries: []Entry{{entryWarning, "incorrect type for \"users[0]\" (want struct)", 2}}, - }, - { - config: "users:\n - name: hi\n - true", - entries: []Entry{{entryWarning, "incorrect type for \"users[1]\" (want struct)", 3}}, - }, - { - config: "users:\n - 4", - entries: []Entry{{entryWarning, "incorrect type for \"users[0]\" (want struct)", 2}}, - }, - { - config: "users:\n - bad", - entries: []Entry{{entryWarning, "incorrect type for \"users[0]\" (want struct)", 2}}, - }, - { - config: "users:\n - - bad", - entries: []Entry{{entryWarning, "incorrect type for \"users[0]\" (want struct)", 2}}, - }, - } - - for i, tt := range tests { - r := Report{} - n, err := parseCloudConfig([]byte(tt.config), &r) - if err != nil { - panic(err) - } - checkStructure(n, &r) - - if e := r.Entries(); !reflect.DeepEqual(tt.entries, e) { - t.Errorf("bad report (%d, %q): want %#v, got %#v", i, tt.config, tt.entries, e) - } - } -} - -func TestCheckValidity(t *testing.T) { - tests := []struct { - config string - - entries []Entry - }{ - // string - { - config: "hostname: test", - }, - - // int - { - config: "coreos:\n fleet:\n verbosity: 2", - }, - - // bool - { - config: "coreos:\n units:\n - enable: true", - }, - - // slice - { - config: "coreos:\n units:\n - command: start\n - name: stop", - }, - { - config: "coreos:\n units:\n - command: lol", - entries: []Entry{{entryError, "invalid value lol", 3}}, - }, - - // struct - { - config: "coreos:\n update:\n reboot_strategy: off", - }, - { - config: "coreos:\n update:\n reboot_strategy: always", - entries: []Entry{{entryError, "invalid value always", 3}}, - }, - - // unknown - { - config: "unknown: hi", - }, - } - - for i, tt := range tests { - r := Report{} - n, err := parseCloudConfig([]byte(tt.config), &r) - if err != nil { - panic(err) - } - checkValidity(n, &r) - - if e := r.Entries(); !reflect.DeepEqual(tt.entries, e) { - t.Errorf("bad report (%d, %q): want %#v, got %#v", i, tt.config, tt.entries, e) - } - } -} - -func TestCheckWriteFiles(t *testing.T) { - tests := []struct { - config string - - entries []Entry - }{ - {}, - { - config: "write_files:\n - path: /valid", - }, - { - config: "write_files:\n - path: /tmp/usr/valid", - }, - { - config: "write_files:\n - path: /usr/invalid", - entries: []Entry{{entryError, "file cannot be written to a read-only filesystem", 2}}, - }, - { - config: "write-files:\n - path: /tmp/../usr/invalid", - entries: []Entry{{entryError, "file cannot be written to a read-only filesystem", 2}}, - }, - } - - for i, tt := range tests { - r := Report{} - n, err := parseCloudConfig([]byte(tt.config), &r) - if err != nil { - panic(err) - } - checkWriteFiles(n, &r) - - if e := r.Entries(); !reflect.DeepEqual(tt.entries, e) { - t.Errorf("bad report (%d, %q): want %#v, got %#v", i, tt.config, tt.entries, e) - } - } -} - -func TestCheckWriteFilesUnderCoreos(t *testing.T) { - tests := []struct { - config string - - entries []Entry - }{ - {}, - { - config: "write_files:\n - path: /hi", - }, - { - config: "coreos:\n write_files:\n - path: /hi", - entries: []Entry{{entryInfo, "write_files doesn't belong under coreos", 2}}, - }, - { - config: "coreos:\n write-files:\n - path: /hyphen", - entries: []Entry{{entryInfo, "write_files doesn't belong under coreos", 2}}, - }, - } - - for i, tt := range tests { - r := Report{} - n, err := parseCloudConfig([]byte(tt.config), &r) - if err != nil { - panic(err) - } - checkWriteFilesUnderCoreos(n, &r) - - if e := r.Entries(); !reflect.DeepEqual(tt.entries, e) { - t.Errorf("bad report (%d, %q): want %#v, got %#v", i, tt.config, tt.entries, e) - } - } -} diff --git a/vendor/github.com/coreos/coreos-cloudinit/config/validate/validate.go b/vendor/github.com/coreos/coreos-cloudinit/config/validate/validate.go deleted file mode 100644 index d1ecc726..00000000 --- a/vendor/github.com/coreos/coreos-cloudinit/config/validate/validate.go +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package validate - -import ( - "errors" - "fmt" - "regexp" - "strconv" - "strings" - - "github.com/coreos/coreos-cloudinit/config" - - "github.com/coreos/yaml" -) - -var ( - yamlLineError = regexp.MustCompile(`^YAML error: line (?P[[:digit:]]+): (?P.*)$`) - yamlError = regexp.MustCompile(`^YAML error: (?P.*)$`) -) - -// Validate runs a series of validation tests against the given userdata and -// returns a report detailing all of the issues. Presently, only cloud-configs -// can be validated. -func Validate(userdataBytes []byte) (Report, error) { - switch { - case len(userdataBytes) == 0: - return Report{}, nil - case config.IsScript(string(userdataBytes)): - return Report{}, nil - case config.IsCloudConfig(string(userdataBytes)): - return validateCloudConfig(userdataBytes, Rules) - default: - return Report{entries: []Entry{ - Entry{kind: entryError, message: `must be "#cloud-config" or begin with "#!"`, line: 1}, - }}, nil - } -} - -// validateCloudConfig runs all of the validation rules in Rules and returns -// the resulting report and any errors encountered. -func validateCloudConfig(config []byte, rules []rule) (report Report, err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("%v", r) - } - }() - - c, err := parseCloudConfig(config, &report) - if err != nil { - return report, err - } - - for _, r := range rules { - r(c, &report) - } - return report, nil -} - -// parseCloudConfig parses the provided config into a node structure and logs -// any parsing issues into the provided report. Unrecoverable errors are -// returned as an error. -func parseCloudConfig(cfg []byte, report *Report) (node, error) { - yaml.UnmarshalMappingKeyTransform = func(nameIn string) (nameOut string) { - return nameIn - } - // unmarshal the config into an implicitly-typed form. The yaml library - // will implicitly convert types into their normalized form - // (e.g. 0744 -> 484, off -> false). - var weak map[interface{}]interface{} - if err := yaml.Unmarshal(cfg, &weak); err != nil { - matches := yamlLineError.FindStringSubmatch(err.Error()) - if len(matches) == 3 { - line, err := strconv.Atoi(matches[1]) - if err != nil { - return node{}, err - } - msg := matches[2] - report.Error(line, msg) - return node{}, nil - } - - matches = yamlError.FindStringSubmatch(err.Error()) - if len(matches) == 2 { - report.Error(1, matches[1]) - return node{}, nil - } - - return node{}, errors.New("couldn't parse yaml error") - } - w := NewNode(weak, NewContext(cfg)) - w = normalizeNodeNames(w, report) - - // unmarshal the config into the explicitly-typed form. - yaml.UnmarshalMappingKeyTransform = func(nameIn string) (nameOut string) { - return strings.Replace(nameIn, "-", "_", -1) - } - var strong config.CloudConfig - if err := yaml.Unmarshal([]byte(cfg), &strong); err != nil { - return node{}, err - } - s := NewNode(strong, NewContext(cfg)) - - // coerceNodes weak nodes and strong nodes. strong nodes replace weak nodes - // if they are compatible types (this happens when the yaml library - // converts the input). - // (e.g. weak 484 is replaced by strong 0744, weak 4 is not replaced by - // strong false) - return coerceNodes(w, s), nil -} - -// coerceNodes recursively evaluates two nodes, returning a new node containing -// either the weak or strong node's value and its recursively processed -// children. The strong node's value is used if the two nodes are leafs, are -// both valid, and are compatible types (defined by isCompatible()). The weak -// node is returned in all other cases. coerceNodes is used to counteract the -// effects of yaml's automatic type conversion. The weak node is the one -// resulting from unmarshalling into an empty interface{} (the type is -// inferred). The strong node is the one resulting from unmarshalling into a -// struct. If the two nodes are of compatible types, the yaml library correctly -// parsed the value into the strongly typed unmarshalling. In this case, we -// prefer the strong node because its actually the type we are expecting. -func coerceNodes(w, s node) node { - n := w - n.children = nil - if len(w.children) == 0 && len(s.children) == 0 && - w.IsValid() && s.IsValid() && - isCompatible(w.Kind(), s.Kind()) { - n.Value = s.Value - } - - for _, cw := range w.children { - n.children = append(n.children, coerceNodes(cw, s.Child(cw.name))) - } - return n -} - -// normalizeNodeNames replaces all occurences of '-' with '_' within key names -// and makes a note of each replacement in the report. -func normalizeNodeNames(node node, report *Report) node { - if strings.Contains(node.name, "-") { - // TODO(crawford): Enable this message once the new validator hits stable. - //report.Info(node.line, fmt.Sprintf("%q uses '-' instead of '_'", node.name)) - node.name = strings.Replace(node.name, "-", "_", -1) - } - for i := range node.children { - node.children[i] = normalizeNodeNames(node.children[i], report) - } - return node -} diff --git a/vendor/github.com/coreos/coreos-cloudinit/config/validate/validate_test.go b/vendor/github.com/coreos/coreos-cloudinit/config/validate/validate_test.go deleted file mode 100644 index dee79ade..00000000 --- a/vendor/github.com/coreos/coreos-cloudinit/config/validate/validate_test.go +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package validate - -import ( - "errors" - "reflect" - "testing" -) - -func TestParseCloudConfig(t *testing.T) { - tests := []struct { - config string - - entries []Entry - }{ - {}, - { - config: " ", - entries: []Entry{{entryError, "found character that cannot start any token", 1}}, - }, - { - config: "a:\na", - entries: []Entry{{entryError, "could not find expected ':'", 2}}, - }, - { - config: "#hello\na:\na", - entries: []Entry{{entryError, "could not find expected ':'", 3}}, - }, - } - - for _, tt := range tests { - r := Report{} - parseCloudConfig([]byte(tt.config), &r) - - if e := r.Entries(); !reflect.DeepEqual(tt.entries, e) { - t.Errorf("bad report (%s): want %#v, got %#v", tt.config, tt.entries, e) - } - } -} - -func TestValidateCloudConfig(t *testing.T) { - tests := []struct { - config string - rules []rule - - report Report - err error - }{ - { - rules: []rule{func(_ node, _ *Report) { panic("something happened") }}, - err: errors.New("something happened"), - }, - { - config: "write_files:\n - permissions: 0744", - rules: Rules, - }, - { - config: "write_files:\n - permissions: '0744'", - rules: Rules, - }, - { - config: "write_files:\n - permissions: 744", - rules: Rules, - }, - { - config: "write_files:\n - permissions: '744'", - rules: Rules, - }, - { - config: "coreos:\n update:\n reboot-strategy: off", - rules: Rules, - }, - { - config: "coreos:\n update:\n reboot-strategy: false", - rules: Rules, - report: Report{entries: []Entry{{entryError, "invalid value false", 3}}}, - }, - } - - for _, tt := range tests { - r, err := validateCloudConfig([]byte(tt.config), tt.rules) - if !reflect.DeepEqual(tt.err, err) { - t.Errorf("bad error (%s): want %v, got %v", tt.config, tt.err, err) - } - if !reflect.DeepEqual(tt.report, r) { - t.Errorf("bad report (%s): want %+v, got %+v", tt.config, tt.report, r) - } - } -} - -func TestValidate(t *testing.T) { - tests := []struct { - config string - - report Report - }{ - {}, - { - config: "#!/bin/bash\necho hey", - }, - } - - for i, tt := range tests { - r, err := Validate([]byte(tt.config)) - if err != nil { - t.Errorf("bad error (case #%d): want %v, got %v", i, nil, err) - } - if !reflect.DeepEqual(tt.report, r) { - t.Errorf("bad report (case #%d): want %+v, got %+v", i, tt.report, r) - } - } -} - -func BenchmarkValidate(b *testing.B) { - config := `#cloud-config -hostname: test - -coreos: - etcd: - name: node001 - discovery: https://discovery.etcd.io/disco - addr: $public_ipv4:4001 - peer-addr: $private_ipv4:7001 - fleet: - verbosity: 2 - metadata: "hi" - update: - reboot-strategy: off - units: - - name: hi.service - command: start - enable: true - - name: bye.service - command: stop - -ssh_authorized_keys: - - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0g+ZTxC7weoIJLUafOgrm+h... - - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0g+ZTxC7weoIJLUafOgrm+h... - -users: - - name: me - -write_files: - - path: /etc/yes - content: "Hi" - -manage_etc_hosts: localhost` - - for i := 0; i < b.N; i++ { - if _, err := Validate([]byte(config)); err != nil { - panic(err) - } - } -} diff --git a/vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/cloudsigma/server_context.go b/vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/cloudsigma/server_context.go deleted file mode 100644 index d26e90d4..00000000 --- a/vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/cloudsigma/server_context.go +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cloudsigma - -import ( - "bytes" - "encoding/base64" - "encoding/json" - "errors" - "io/ioutil" - "net" - "os" - "strings" - - "github.com/coreos/coreos-cloudinit/datasource" - - "github.com/cloudsigma/cepgo" -) - -const ( - userDataFieldName = "cloudinit-user-data" -) - -type serverContextService struct { - client interface { - All() (interface{}, error) - Key(string) (interface{}, error) - Meta() (map[string]string, error) - FetchRaw(string) ([]byte, error) - } -} - -func NewServerContextService() *serverContextService { - return &serverContextService{ - client: cepgo.NewCepgo(), - } -} - -func (_ *serverContextService) IsAvailable() bool { - productNameFile, err := os.Open("/sys/class/dmi/id/product_name") - if err != nil { - return false - } - productName := make([]byte, 10) - _, err = productNameFile.Read(productName) - - return err == nil && string(productName) == "CloudSigma" && hasDHCPLeases() -} - -func (_ *serverContextService) AvailabilityChanges() bool { - return true -} - -func (_ *serverContextService) ConfigRoot() string { - return "" -} - -func (_ *serverContextService) Type() string { - return "server-context" -} - -func (scs *serverContextService) FetchMetadata() (metadata datasource.Metadata, err error) { - var ( - inputMetadata struct { - Name string `json:"name"` - UUID string `json:"uuid"` - Meta map[string]string `json:"meta"` - Nics []struct { - Mac string `json:"mac"` - IPv4Conf struct { - InterfaceType string `json:"interface_type"` - IP struct { - UUID string `json:"uuid"` - } `json:"ip"` - } `json:"ip_v4_conf"` - VLAN struct { - UUID string `json:"uuid"` - } `json:"vlan"` - } `json:"nics"` - } - rawMetadata []byte - ) - - if rawMetadata, err = scs.client.FetchRaw(""); err != nil { - return - } - - if err = json.Unmarshal(rawMetadata, &inputMetadata); err != nil { - return - } - - if inputMetadata.Name != "" { - metadata.Hostname = inputMetadata.Name - } else { - metadata.Hostname = inputMetadata.UUID - } - - metadata.SSHPublicKeys = map[string]string{} - if key, ok := inputMetadata.Meta["ssh_public_key"]; ok { - splitted := strings.Split(key, " ") - metadata.SSHPublicKeys[splitted[len(splitted)-1]] = key - } - - for _, nic := range inputMetadata.Nics { - if nic.IPv4Conf.IP.UUID != "" { - metadata.PublicIPv4 = net.ParseIP(nic.IPv4Conf.IP.UUID) - } - if nic.VLAN.UUID != "" { - if localIP, err := scs.findLocalIP(nic.Mac); err == nil { - metadata.PrivateIPv4 = localIP - } - } - } - - return -} - -func (scs *serverContextService) FetchUserdata() ([]byte, error) { - metadata, err := scs.client.Meta() - if err != nil { - return []byte{}, err - } - - userData, ok := metadata[userDataFieldName] - if ok && isBase64Encoded(userDataFieldName, metadata) { - if decodedUserData, err := base64.StdEncoding.DecodeString(userData); err == nil { - return decodedUserData, nil - } else { - return []byte{}, nil - } - } - - return []byte(userData), nil -} - -func (scs *serverContextService) findLocalIP(mac string) (net.IP, error) { - ifaces, err := net.Interfaces() - if err != nil { - return nil, err - } - ifaceMac, err := net.ParseMAC(mac) - if err != nil { - return nil, err - } - for _, iface := range ifaces { - if !bytes.Equal(iface.HardwareAddr, ifaceMac) { - continue - } - addrs, err := iface.Addrs() - if err != nil { - continue - } - - for _, addr := range addrs { - switch ip := addr.(type) { - case *net.IPNet: - if ip.IP.To4() != nil { - return ip.IP.To4(), nil - } - } - } - } - return nil, errors.New("Local IP not found") -} - -func isBase64Encoded(field string, userdata map[string]string) bool { - base64Fields, ok := userdata["base64_fields"] - if !ok { - return false - } - - for _, base64Field := range strings.Split(base64Fields, ",") { - if field == base64Field { - return true - } - } - return false -} - -func hasDHCPLeases() bool { - files, err := ioutil.ReadDir("/run/systemd/netif/leases/") - return err == nil && len(files) > 0 -} diff --git a/vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/cloudsigma/server_context_test.go b/vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/cloudsigma/server_context_test.go deleted file mode 100644 index 726425bc..00000000 --- a/vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/cloudsigma/server_context_test.go +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cloudsigma - -import ( - "net" - "reflect" - "testing" -) - -type fakeCepgoClient struct { - raw []byte - meta map[string]string - keys map[string]interface{} - err error -} - -func (f *fakeCepgoClient) All() (interface{}, error) { - return f.keys, f.err -} - -func (f *fakeCepgoClient) Key(key string) (interface{}, error) { - return f.keys[key], f.err -} - -func (f *fakeCepgoClient) Meta() (map[string]string, error) { - return f.meta, f.err -} - -func (f *fakeCepgoClient) FetchRaw(key string) ([]byte, error) { - return f.raw, f.err -} - -func TestServerContextFetchMetadata(t *testing.T) { - client := new(fakeCepgoClient) - scs := NewServerContextService() - scs.client = client - client.raw = []byte(`{ - "context": true, - "cpu": 4000, - "cpu_model": null, - "cpus_instead_of_cores": false, - "enable_numa": false, - "grantees": [], - "hv_relaxed": false, - "hv_tsc": false, - "jobs": [], - "mem": 4294967296, - "meta": { - "base64_fields": "cloudinit-user-data", - "cloudinit-user-data": "I2Nsb3VkLWNvbmZpZwoKaG9zdG5hbWU6IGNvcmVvczE=", - "ssh_public_key": "ssh-rsa AAAAB3NzaC1yc2E.../hQ5D5 john@doe" - }, - "name": "coreos", - "nics": [ - { - "boot_order": null, - "ip_v4_conf": { - "conf": "dhcp", - "ip": { - "gateway": "31.171.244.1", - "meta": {}, - "nameservers": [ - "178.22.66.167", - "178.22.71.56", - "8.8.8.8" - ], - "netmask": 22, - "tags": [], - "uuid": "31.171.251.74" - } - }, - "ip_v6_conf": null, - "mac": "22:3d:09:6b:90:f3", - "model": "virtio", - "vlan": null - }, - { - "boot_order": null, - "ip_v4_conf": null, - "ip_v6_conf": null, - "mac": "22:ae:4a:fb:8f:31", - "model": "virtio", - "vlan": { - "meta": { - "description": "", - "name": "CoreOS" - }, - "tags": [], - "uuid": "5dec030e-25b8-4621-a5a4-a3302c9d9619" - } - } - ], - "smp": 2, - "status": "running", - "uuid": "20a0059b-041e-4d0c-bcc6-9b2852de48b3" - }`) - - metadata, err := scs.FetchMetadata() - if err != nil { - t.Error(err.Error()) - } - - if metadata.Hostname != "coreos" { - t.Errorf("Hostname is not 'coreos' but %s instead", metadata.Hostname) - } - - if metadata.SSHPublicKeys["john@doe"] != "ssh-rsa AAAAB3NzaC1yc2E.../hQ5D5 john@doe" { - t.Error("Public SSH Keys are not being read properly") - } - - if !metadata.PublicIPv4.Equal(net.ParseIP("31.171.251.74")) { - t.Errorf("Public IP is not 31.171.251.74 but %s instead", metadata.PublicIPv4) - } -} - -func TestServerContextFetchUserdata(t *testing.T) { - client := new(fakeCepgoClient) - scs := NewServerContextService() - scs.client = client - userdataSets := []struct { - in map[string]string - err bool - out []byte - }{ - {map[string]string{ - "base64_fields": "cloudinit-user-data", - "cloudinit-user-data": "aG9zdG5hbWU6IGNvcmVvc190ZXN0", - }, false, []byte("hostname: coreos_test")}, - {map[string]string{ - "cloudinit-user-data": "#cloud-config\\nhostname: coreos1", - }, false, []byte("#cloud-config\\nhostname: coreos1")}, - {map[string]string{}, false, []byte{}}, - } - - for i, set := range userdataSets { - client.meta = set.in - got, err := scs.FetchUserdata() - if (err != nil) != set.err { - t.Errorf("case %d: bad error state (got %t, want %t)", i, err != nil, set.err) - } - - if !reflect.DeepEqual(got, set.out) { - t.Errorf("case %d: got %s, want %s", i, got, set.out) - } - } -} - -func TestServerContextDecodingBase64UserData(t *testing.T) { - base64Sets := []struct { - in string - out bool - }{ - {"cloudinit-user-data,foo,bar", true}, - {"bar,cloudinit-user-data,foo,bar", true}, - {"cloudinit-user-data", true}, - {"", false}, - {"foo", false}, - } - - for _, set := range base64Sets { - userdata := map[string]string{"base64_fields": set.in} - if isBase64Encoded("cloudinit-user-data", userdata) != set.out { - t.Errorf("isBase64Encoded(cloudinit-user-data, %s) should be %t", userdata, set.out) - } - } -} diff --git a/vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/test/test.go b/vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/test/test.go deleted file mode 100644 index 3be08f3b..00000000 --- a/vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/test/test.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package test - -import ( - "fmt" - - "github.com/coreos/coreos-cloudinit/pkg" -) - -type HttpClient struct { - Resources map[string]string - Err error -} - -func (t *HttpClient) GetRetry(url string) ([]byte, error) { - if t.Err != nil { - return nil, t.Err - } - if val, ok := t.Resources[url]; ok { - return []byte(val), nil - } else { - return nil, pkg.ErrNotFound{fmt.Errorf("not found: %q", url)} - } -} - -func (t *HttpClient) Get(url string) ([]byte, error) { - return t.GetRetry(url) -} diff --git a/vendor/github.com/coreos/coreos-cloudinit/datasource/test/filesystem.go b/vendor/github.com/coreos/coreos-cloudinit/datasource/test/filesystem.go deleted file mode 100644 index 95d6fb27..00000000 --- a/vendor/github.com/coreos/coreos-cloudinit/datasource/test/filesystem.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package test - -import ( - "fmt" - "os" - "path" -) - -type MockFilesystem map[string]File - -type File struct { - Path string - Contents string - Directory bool -} - -func (m MockFilesystem) ReadFile(filename string) ([]byte, error) { - if f, ok := m[path.Clean(filename)]; ok { - if f.Directory { - return nil, fmt.Errorf("read %s: is a directory", filename) - } - return []byte(f.Contents), nil - } - return nil, os.ErrNotExist -} - -func NewMockFilesystem(files ...File) MockFilesystem { - fs := MockFilesystem{} - for _, file := range files { - fs[file.Path] = file - - // Create the directories leading up to the file - p := path.Dir(file.Path) - for p != "/" && p != "." { - if f, ok := fs[p]; ok && !f.Directory { - panic(fmt.Sprintf("%q already exists and is not a directory (%#v)", p, f)) - } - fs[p] = File{Path: p, Directory: true} - p = path.Dir(p) - } - } - return fs -} diff --git a/vendor/github.com/coreos/coreos-cloudinit/datasource/test/filesystem_test.go b/vendor/github.com/coreos/coreos-cloudinit/datasource/test/filesystem_test.go deleted file mode 100644 index 547c51f1..00000000 --- a/vendor/github.com/coreos/coreos-cloudinit/datasource/test/filesystem_test.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package test - -import ( - "errors" - "os" - "reflect" - "testing" -) - -func TestReadFile(t *testing.T) { - tests := []struct { - filesystem MockFilesystem - - filename string - contents string - err error - }{ - { - filename: "dne", - err: os.ErrNotExist, - }, - { - filesystem: MockFilesystem{ - "exists": File{Contents: "hi"}, - }, - filename: "exists", - contents: "hi", - }, - { - filesystem: MockFilesystem{ - "dir": File{Directory: true}, - }, - filename: "dir", - err: errors.New("read dir: is a directory"), - }, - } - - for i, tt := range tests { - contents, err := tt.filesystem.ReadFile(tt.filename) - if tt.contents != string(contents) { - t.Errorf("bad contents (test %d): want %q, got %q", i, tt.contents, string(contents)) - } - if !reflect.DeepEqual(tt.err, err) { - t.Errorf("bad error (test %d): want %v, got %v", i, tt.err, err) - } - } -} - -func TestNewMockFilesystem(t *testing.T) { - tests := []struct { - files []File - - filesystem MockFilesystem - }{ - { - filesystem: MockFilesystem{}, - }, - { - files: []File{File{Path: "file"}}, - filesystem: MockFilesystem{ - "file": File{Path: "file"}, - }, - }, - { - files: []File{File{Path: "/file"}}, - filesystem: MockFilesystem{ - "/file": File{Path: "/file"}, - }, - }, - { - files: []File{File{Path: "/dir/file"}}, - filesystem: MockFilesystem{ - "/dir": File{Path: "/dir", Directory: true}, - "/dir/file": File{Path: "/dir/file"}, - }, - }, - { - files: []File{File{Path: "/dir/dir/file"}}, - filesystem: MockFilesystem{ - "/dir": File{Path: "/dir", Directory: true}, - "/dir/dir": File{Path: "/dir/dir", Directory: true}, - "/dir/dir/file": File{Path: "/dir/dir/file"}, - }, - }, - { - files: []File{File{Path: "/dir/dir/dir", Directory: true}}, - filesystem: MockFilesystem{ - "/dir": File{Path: "/dir", Directory: true}, - "/dir/dir": File{Path: "/dir/dir", Directory: true}, - "/dir/dir/dir": File{Path: "/dir/dir/dir", Directory: true}, - }, - }, - } - - for i, tt := range tests { - filesystem := NewMockFilesystem(tt.files...) - if !reflect.DeepEqual(tt.filesystem, filesystem) { - t.Errorf("bad filesystem (test %d): want %#v, got %#v", i, tt.filesystem, filesystem) - } - } -} diff --git a/vendor/github.com/coreos/coreos-cloudinit/datasource/waagent/waagent.go b/vendor/github.com/coreos/coreos-cloudinit/datasource/waagent/waagent.go deleted file mode 100644 index d0460b93..00000000 --- a/vendor/github.com/coreos/coreos-cloudinit/datasource/waagent/waagent.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package waagent - -import ( - "encoding/xml" - "fmt" - "io/ioutil" - "net" - "os" - "path" - - "github.com/coreos/coreos-cloudinit/datasource" -) - -type waagent struct { - root string - readFile func(filename string) ([]byte, error) -} - -func NewDatasource(root string) *waagent { - return &waagent{root, ioutil.ReadFile} -} - -func (a *waagent) IsAvailable() bool { - _, err := os.Stat(path.Join(a.root, "provisioned")) - return !os.IsNotExist(err) -} - -func (a *waagent) AvailabilityChanges() bool { - return true -} - -func (a *waagent) ConfigRoot() string { - return a.root -} - -func (a *waagent) FetchMetadata() (metadata datasource.Metadata, err error) { - var metadataBytes []byte - if metadataBytes, err = a.tryReadFile(path.Join(a.root, "SharedConfig.xml")); err != nil { - return - } - if len(metadataBytes) == 0 { - return - } - - type Instance struct { - Id string `xml:"id,attr"` - Address string `xml:"address,attr"` - InputEndpoints struct { - Endpoints []struct { - LoadBalancedPublicAddress string `xml:"loadBalancedPublicAddress,attr"` - } `xml:"Endpoint"` - } - } - - type SharedConfig struct { - Incarnation struct { - Instance string `xml:"instance,attr"` - } - Instances struct { - Instances []Instance `xml:"Instance"` - } - } - - var m SharedConfig - if err = xml.Unmarshal(metadataBytes, &m); err != nil { - return - } - - var instance Instance - for _, i := range m.Instances.Instances { - if i.Id == m.Incarnation.Instance { - instance = i - break - } - } - - metadata.PrivateIPv4 = net.ParseIP(instance.Address) - for _, e := range instance.InputEndpoints.Endpoints { - host, _, err := net.SplitHostPort(e.LoadBalancedPublicAddress) - if err == nil { - metadata.PublicIPv4 = net.ParseIP(host) - break - } - } - return -} - -func (a *waagent) FetchUserdata() ([]byte, error) { - return a.tryReadFile(path.Join(a.root, "CustomData")) -} - -func (a *waagent) Type() string { - return "waagent" -} - -func (a *waagent) tryReadFile(filename string) ([]byte, error) { - fmt.Printf("Attempting to read from %q\n", filename) - data, err := a.readFile(filename) - if os.IsNotExist(err) { - err = nil - } - return data, err -} diff --git a/vendor/github.com/coreos/coreos-cloudinit/datasource/waagent/waagent_test.go b/vendor/github.com/coreos/coreos-cloudinit/datasource/waagent/waagent_test.go deleted file mode 100644 index f60a4c2b..00000000 --- a/vendor/github.com/coreos/coreos-cloudinit/datasource/waagent/waagent_test.go +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package waagent - -import ( - "net" - "reflect" - "testing" - - "github.com/coreos/coreos-cloudinit/datasource" - "github.com/coreos/coreos-cloudinit/datasource/test" -) - -func TestFetchMetadata(t *testing.T) { - for _, tt := range []struct { - root string - files test.MockFilesystem - metadata datasource.Metadata - }{ - { - root: "/", - files: test.NewMockFilesystem(), - }, - { - root: "/", - files: test.NewMockFilesystem(test.File{Path: "/SharedConfig.xml", Contents: ""}), - }, - { - root: "/var/lib/waagent", - files: test.NewMockFilesystem(test.File{Path: "/var/lib/waagent/SharedConfig.xml", Contents: ""}), - }, - { - root: "/var/lib/waagent", - files: test.NewMockFilesystem(test.File{Path: "/var/lib/waagent/SharedConfig.xml", Contents: ` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -`}), - metadata: datasource.Metadata{ - PrivateIPv4: net.ParseIP("100.73.202.64"), - PublicIPv4: net.ParseIP("191.239.39.77"), - }, - }, - } { - a := waagent{tt.root, tt.files.ReadFile} - metadata, err := a.FetchMetadata() - if err != nil { - t.Fatalf("bad error for %+v: want %v, got %q", tt, nil, err) - } - if !reflect.DeepEqual(tt.metadata, metadata) { - t.Fatalf("bad metadata for %+v: want %#v, got %#v", tt, tt.metadata, metadata) - } - } -} - -func TestFetchUserdata(t *testing.T) { - for _, tt := range []struct { - root string - files test.MockFilesystem - }{ - { - "/", - test.NewMockFilesystem(), - }, - { - "/", - test.NewMockFilesystem(test.File{Path: "/CustomData", Contents: ""}), - }, - { - "/var/lib/waagent/", - test.NewMockFilesystem(test.File{Path: "/var/lib/waagent/CustomData", Contents: ""}), - }, - } { - a := waagent{tt.root, tt.files.ReadFile} - _, err := a.FetchUserdata() - if err != nil { - t.Fatalf("bad error for %+v: want %v, got %q", tt, nil, err) - } - } -} - -func TestConfigRoot(t *testing.T) { - for _, tt := range []struct { - root string - configRoot string - }{ - { - "/", - "/", - }, - { - "/var/lib/waagent", - "/var/lib/waagent", - }, - } { - a := waagent{tt.root, nil} - if configRoot := a.ConfigRoot(); configRoot != tt.configRoot { - t.Fatalf("bad config root for %q: want %q, got %q", tt, tt.configRoot, configRoot) - } - } -} - -func TestNewDatasource(t *testing.T) { - for _, tt := range []struct { - root string - expectRoot string - }{ - { - root: "", - expectRoot: "", - }, - { - root: "/var/lib/waagent", - expectRoot: "/var/lib/waagent", - }, - } { - service := NewDatasource(tt.root) - if service.root != tt.expectRoot { - t.Fatalf("bad root (%q): want %q, got %q", tt.root, tt.expectRoot, service.root) - } - } -} diff --git a/vendor/github.com/davecgh/go-spew/spew/testdata/dumpcgo.go b/vendor/github.com/davecgh/go-spew/spew/testdata/dumpcgo.go deleted file mode 100644 index 5c87dd45..00000000 --- a/vendor/github.com/davecgh/go-spew/spew/testdata/dumpcgo.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2013 Dave Collins -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -// NOTE: Due to the following build constraints, this file will only be compiled -// when both cgo is supported and "-tags testcgo" is added to the go test -// command line. This code should really only be in the dumpcgo_test.go file, -// but unfortunately Go will not allow cgo in test files, so this is a -// workaround to allow cgo types to be tested. This configuration is used -// because spew itself does not require cgo to run even though it does handle -// certain cgo types specially. Rather than forcing all clients to require cgo -// and an external C compiler just to run the tests, this scheme makes them -// optional. -// +build cgo,testcgo - -package testdata - -/* -#include -typedef unsigned char custom_uchar_t; - -char *ncp = 0; -char *cp = "test"; -char ca[6] = {'t', 'e', 's', 't', '2', '\0'}; -unsigned char uca[6] = {'t', 'e', 's', 't', '3', '\0'}; -signed char sca[6] = {'t', 'e', 's', 't', '4', '\0'}; -uint8_t ui8ta[6] = {'t', 'e', 's', 't', '5', '\0'}; -custom_uchar_t tuca[6] = {'t', 'e', 's', 't', '6', '\0'}; -*/ -import "C" - -// GetCgoNullCharPointer returns a null char pointer via cgo. This is only -// used for tests. -func GetCgoNullCharPointer() interface{} { - return C.ncp -} - -// GetCgoCharPointer returns a char pointer via cgo. This is only used for -// tests. -func GetCgoCharPointer() interface{} { - return C.cp -} - -// GetCgoCharArray returns a char array via cgo and the array's len and cap. -// This is only used for tests. -func GetCgoCharArray() (interface{}, int, int) { - return C.ca, len(C.ca), cap(C.ca) -} - -// GetCgoUnsignedCharArray returns an unsigned char array via cgo and the -// array's len and cap. This is only used for tests. -func GetCgoUnsignedCharArray() (interface{}, int, int) { - return C.uca, len(C.uca), cap(C.uca) -} - -// GetCgoSignedCharArray returns a signed char array via cgo and the array's len -// and cap. This is only used for tests. -func GetCgoSignedCharArray() (interface{}, int, int) { - return C.sca, len(C.sca), cap(C.sca) -} - -// GetCgoUint8tArray returns a uint8_t array via cgo and the array's len and -// cap. This is only used for tests. -func GetCgoUint8tArray() (interface{}, int, int) { - return C.ui8ta, len(C.ui8ta), cap(C.ui8ta) -} - -// GetCgoTypdefedUnsignedCharArray returns a typedefed unsigned char array via -// cgo and the array's len and cap. This is only used for tests. -func GetCgoTypdefedUnsignedCharArray() (interface{}, int, int) { - return C.tuca, len(C.tuca), cap(C.tuca) -} diff --git a/vendor/github.com/docker/distribution/registry/storage/cache/cachecheck/suite.go b/vendor/github.com/docker/distribution/registry/storage/cache/cachecheck/suite.go deleted file mode 100644 index ed0f95fd..00000000 --- a/vendor/github.com/docker/distribution/registry/storage/cache/cachecheck/suite.go +++ /dev/null @@ -1,179 +0,0 @@ -package cachecheck - -import ( - "testing" - - "github.com/docker/distribution" - "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" - "github.com/docker/distribution/registry/storage/cache" -) - -// CheckBlobDescriptorCache takes a cache implementation through a common set -// of operations. If adding new tests, please add them here so new -// implementations get the benefit. This should be used for unit tests. -func CheckBlobDescriptorCache(t *testing.T, provider cache.BlobDescriptorCacheProvider) { - ctx := context.Background() - - checkBlobDescriptorCacheEmptyRepository(t, ctx, provider) - checkBlobDescriptorCacheSetAndRead(t, ctx, provider) -} - -func checkBlobDescriptorCacheEmptyRepository(t *testing.T, ctx context.Context, provider cache.BlobDescriptorCacheProvider) { - if _, err := provider.Stat(ctx, "sha384:abc"); err != distribution.ErrBlobUnknown { - t.Fatalf("expected unknown blob error with empty store: %v", err) - } - - cache, err := provider.RepositoryScoped("") - if err == nil { - t.Fatalf("expected an error when asking for invalid repo") - } - - cache, err = provider.RepositoryScoped("foo/bar") - if err != nil { - t.Fatalf("unexpected error getting repository: %v", err) - } - - if err := cache.SetDescriptor(ctx, "", distribution.Descriptor{ - Digest: "sha384:abc", - Size: 10, - MediaType: "application/octet-stream"}); err != digest.ErrDigestInvalidFormat { - t.Fatalf("expected error with invalid digest: %v", err) - } - - if err := cache.SetDescriptor(ctx, "sha384:abc", distribution.Descriptor{ - Digest: "", - Size: 10, - MediaType: "application/octet-stream"}); err == nil { - t.Fatalf("expected error setting value on invalid descriptor") - } - - if _, err := cache.Stat(ctx, ""); err != digest.ErrDigestInvalidFormat { - t.Fatalf("expected error checking for cache item with empty digest: %v", err) - } - - if _, err := cache.Stat(ctx, "sha384:abc"); err != distribution.ErrBlobUnknown { - t.Fatalf("expected unknown blob error with empty repo: %v", err) - } -} - -func checkBlobDescriptorCacheSetAndRead(t *testing.T, ctx context.Context, provider cache.BlobDescriptorCacheProvider) { - localDigest := digest.Digest("sha384:abc") - expected := distribution.Descriptor{ - Digest: "sha256:abc", - Size: 10, - MediaType: "application/octet-stream"} - - cache, err := provider.RepositoryScoped("foo/bar") - if err != nil { - t.Fatalf("unexpected error getting scoped cache: %v", err) - } - - if err := cache.SetDescriptor(ctx, localDigest, expected); err != nil { - t.Fatalf("error setting descriptor: %v", err) - } - - desc, err := cache.Stat(ctx, localDigest) - if err != nil { - t.Fatalf("unexpected error statting fake2:abc: %v", err) - } - - if expected != desc { - t.Fatalf("unexpected descriptor: %#v != %#v", expected, desc) - } - - // also check that we set the canonical key ("fake:abc") - desc, err = cache.Stat(ctx, localDigest) - if err != nil { - t.Fatalf("descriptor not returned for canonical key: %v", err) - } - - if expected != desc { - t.Fatalf("unexpected descriptor: %#v != %#v", expected, desc) - } - - // ensure that global gets extra descriptor mapping - desc, err = provider.Stat(ctx, localDigest) - if err != nil { - t.Fatalf("expected blob unknown in global cache: %v, %v", err, desc) - } - - if desc != expected { - t.Fatalf("unexpected descriptor: %#v != %#v", expected, desc) - } - - // get at it through canonical descriptor - desc, err = provider.Stat(ctx, expected.Digest) - if err != nil { - t.Fatalf("unexpected error checking glboal descriptor: %v", err) - } - - if desc != expected { - t.Fatalf("unexpected descriptor: %#v != %#v", expected, desc) - } - - // now, we set the repo local mediatype to something else and ensure it - // doesn't get changed in the provider cache. - expected.MediaType = "application/json" - - if err := cache.SetDescriptor(ctx, localDigest, expected); err != nil { - t.Fatalf("unexpected error setting descriptor: %v", err) - } - - desc, err = cache.Stat(ctx, localDigest) - if err != nil { - t.Fatalf("unexpected error getting descriptor: %v", err) - } - - if desc != expected { - t.Fatalf("unexpected descriptor: %#v != %#v", desc, expected) - } - - desc, err = provider.Stat(ctx, localDigest) - if err != nil { - t.Fatalf("unexpected error getting global descriptor: %v", err) - } - - expected.MediaType = "application/octet-stream" // expect original mediatype in global - - if desc != expected { - t.Fatalf("unexpected descriptor: %#v != %#v", desc, expected) - } -} - -func checkBlobDescriptorClear(t *testing.T, ctx context.Context, provider cache.BlobDescriptorCacheProvider) { - localDigest := digest.Digest("sha384:abc") - expected := distribution.Descriptor{ - Digest: "sha256:abc", - Size: 10, - MediaType: "application/octet-stream"} - - cache, err := provider.RepositoryScoped("foo/bar") - if err != nil { - t.Fatalf("unexpected error getting scoped cache: %v", err) - } - - if err := cache.SetDescriptor(ctx, localDigest, expected); err != nil { - t.Fatalf("error setting descriptor: %v", err) - } - - desc, err := cache.Stat(ctx, localDigest) - if err != nil { - t.Fatalf("unexpected error statting fake2:abc: %v", err) - } - - if expected != desc { - t.Fatalf("unexpected descriptor: %#v != %#v", expected, desc) - } - - err = cache.Clear(ctx, localDigest) - if err != nil { - t.Fatalf("unexpected error deleting descriptor") - } - - nonExistantDigest := digest.Digest("sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") - err = cache.Clear(ctx, nonExistantDigest) - if err == nil { - t.Fatalf("expected error deleting unknown descriptor") - } -} diff --git a/vendor/github.com/docker/distribution/registry/storage/cache/redis/redis.go b/vendor/github.com/docker/distribution/registry/storage/cache/redis/redis.go deleted file mode 100644 index 1736756e..00000000 --- a/vendor/github.com/docker/distribution/registry/storage/cache/redis/redis.go +++ /dev/null @@ -1,268 +0,0 @@ -package redis - -import ( - "fmt" - - "github.com/docker/distribution" - "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" - "github.com/docker/distribution/reference" - "github.com/docker/distribution/registry/storage/cache" - "github.com/garyburd/redigo/redis" -) - -// redisBlobStatService provides an implementation of -// BlobDescriptorCacheProvider based on redis. Blob descriptors are stored in -// two parts. The first provide fast access to repository membership through a -// redis set for each repo. The second is a redis hash keyed by the digest of -// the layer, providing path, length and mediatype information. There is also -// a per-repository redis hash of the blob descriptor, allowing override of -// data. This is currently used to override the mediatype on a per-repository -// basis. -// -// Note that there is no implied relationship between these two caches. The -// layer may exist in one, both or none and the code must be written this way. -type redisBlobDescriptorService struct { - pool *redis.Pool - - // TODO(stevvooe): We use a pool because we don't have great control over - // the cache lifecycle to manage connections. A new connection if fetched - // for each operation. Once we have better lifecycle management of the - // request objects, we can change this to a connection. -} - -// NewRedisBlobDescriptorCacheProvider returns a new redis-based -// BlobDescriptorCacheProvider using the provided redis connection pool. -func NewRedisBlobDescriptorCacheProvider(pool *redis.Pool) cache.BlobDescriptorCacheProvider { - return &redisBlobDescriptorService{ - pool: pool, - } -} - -// RepositoryScoped returns the scoped cache. -func (rbds *redisBlobDescriptorService) RepositoryScoped(repo string) (distribution.BlobDescriptorService, error) { - if _, err := reference.ParseNamed(repo); err != nil { - return nil, err - } - - return &repositoryScopedRedisBlobDescriptorService{ - repo: repo, - upstream: rbds, - }, nil -} - -// Stat retrieves the descriptor data from the redis hash entry. -func (rbds *redisBlobDescriptorService) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) { - if err := dgst.Validate(); err != nil { - return distribution.Descriptor{}, err - } - - conn := rbds.pool.Get() - defer conn.Close() - - return rbds.stat(ctx, conn, dgst) -} - -func (rbds *redisBlobDescriptorService) Clear(ctx context.Context, dgst digest.Digest) error { - if err := dgst.Validate(); err != nil { - return err - } - - conn := rbds.pool.Get() - defer conn.Close() - - // Not atomic in redis <= 2.3 - reply, err := conn.Do("HDEL", rbds.blobDescriptorHashKey(dgst), "digest", "length", "mediatype") - if err != nil { - return err - } - - if reply == 0 { - return distribution.ErrBlobUnknown - } - - return nil -} - -// stat provides an internal stat call that takes a connection parameter. This -// allows some internal management of the connection scope. -func (rbds *redisBlobDescriptorService) stat(ctx context.Context, conn redis.Conn, dgst digest.Digest) (distribution.Descriptor, error) { - reply, err := redis.Values(conn.Do("HMGET", rbds.blobDescriptorHashKey(dgst), "digest", "size", "mediatype")) - if err != nil { - return distribution.Descriptor{}, err - } - - // NOTE(stevvooe): The "size" field used to be "length". We treat a - // missing "size" field here as an unknown blob, which causes a cache - // miss, effectively migrating the field. - if len(reply) < 3 || reply[0] == nil || reply[1] == nil { // don't care if mediatype is nil - return distribution.Descriptor{}, distribution.ErrBlobUnknown - } - - var desc distribution.Descriptor - if _, err := redis.Scan(reply, &desc.Digest, &desc.Size, &desc.MediaType); err != nil { - return distribution.Descriptor{}, err - } - - return desc, nil -} - -// SetDescriptor sets the descriptor data for the given digest using a redis -// hash. A hash is used here since we may store unrelated fields about a layer -// in the future. -func (rbds *redisBlobDescriptorService) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error { - if err := dgst.Validate(); err != nil { - return err - } - - if err := cache.ValidateDescriptor(desc); err != nil { - return err - } - - conn := rbds.pool.Get() - defer conn.Close() - - return rbds.setDescriptor(ctx, conn, dgst, desc) -} - -func (rbds *redisBlobDescriptorService) setDescriptor(ctx context.Context, conn redis.Conn, dgst digest.Digest, desc distribution.Descriptor) error { - if _, err := conn.Do("HMSET", rbds.blobDescriptorHashKey(dgst), - "digest", desc.Digest, - "size", desc.Size); err != nil { - return err - } - - // Only set mediatype if not already set. - if _, err := conn.Do("HSETNX", rbds.blobDescriptorHashKey(dgst), - "mediatype", desc.MediaType); err != nil { - return err - } - - return nil -} - -func (rbds *redisBlobDescriptorService) blobDescriptorHashKey(dgst digest.Digest) string { - return "blobs::" + dgst.String() -} - -type repositoryScopedRedisBlobDescriptorService struct { - repo string - upstream *redisBlobDescriptorService -} - -var _ distribution.BlobDescriptorService = &repositoryScopedRedisBlobDescriptorService{} - -// Stat ensures that the digest is a member of the specified repository and -// forwards the descriptor request to the global blob store. If the media type -// differs for the repository, we override it. -func (rsrbds *repositoryScopedRedisBlobDescriptorService) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) { - if err := dgst.Validate(); err != nil { - return distribution.Descriptor{}, err - } - - conn := rsrbds.upstream.pool.Get() - defer conn.Close() - - // Check membership to repository first - member, err := redis.Bool(conn.Do("SISMEMBER", rsrbds.repositoryBlobSetKey(rsrbds.repo), dgst)) - if err != nil { - return distribution.Descriptor{}, err - } - - if !member { - return distribution.Descriptor{}, distribution.ErrBlobUnknown - } - - upstream, err := rsrbds.upstream.stat(ctx, conn, dgst) - if err != nil { - return distribution.Descriptor{}, err - } - - // We allow a per repository mediatype, let's look it up here. - mediatype, err := redis.String(conn.Do("HGET", rsrbds.blobDescriptorHashKey(dgst), "mediatype")) - if err != nil { - return distribution.Descriptor{}, err - } - - if mediatype != "" { - upstream.MediaType = mediatype - } - - return upstream, nil -} - -// Clear removes the descriptor from the cache and forwards to the upstream descriptor store -func (rsrbds *repositoryScopedRedisBlobDescriptorService) Clear(ctx context.Context, dgst digest.Digest) error { - if err := dgst.Validate(); err != nil { - return err - } - - conn := rsrbds.upstream.pool.Get() - defer conn.Close() - - // Check membership to repository first - member, err := redis.Bool(conn.Do("SISMEMBER", rsrbds.repositoryBlobSetKey(rsrbds.repo), dgst)) - if err != nil { - return err - } - - if !member { - return distribution.ErrBlobUnknown - } - - return rsrbds.upstream.Clear(ctx, dgst) -} - -func (rsrbds *repositoryScopedRedisBlobDescriptorService) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error { - if err := dgst.Validate(); err != nil { - return err - } - - if err := cache.ValidateDescriptor(desc); err != nil { - return err - } - - if dgst != desc.Digest { - if dgst.Algorithm() == desc.Digest.Algorithm() { - return fmt.Errorf("redis cache: digest for descriptors differ but algorthim does not: %q != %q", dgst, desc.Digest) - } - } - - conn := rsrbds.upstream.pool.Get() - defer conn.Close() - - return rsrbds.setDescriptor(ctx, conn, dgst, desc) -} - -func (rsrbds *repositoryScopedRedisBlobDescriptorService) setDescriptor(ctx context.Context, conn redis.Conn, dgst digest.Digest, desc distribution.Descriptor) error { - if _, err := conn.Do("SADD", rsrbds.repositoryBlobSetKey(rsrbds.repo), dgst); err != nil { - return err - } - - if err := rsrbds.upstream.setDescriptor(ctx, conn, dgst, desc); err != nil { - return err - } - - // Override repository mediatype. - if _, err := conn.Do("HSET", rsrbds.blobDescriptorHashKey(dgst), "mediatype", desc.MediaType); err != nil { - return err - } - - // Also set the values for the primary descriptor, if they differ by - // algorithm (ie sha256 vs tarsum). - if desc.Digest != "" && dgst != desc.Digest && dgst.Algorithm() != desc.Digest.Algorithm() { - if err := rsrbds.setDescriptor(ctx, conn, desc.Digest, desc); err != nil { - return err - } - } - - return nil -} - -func (rsrbds *repositoryScopedRedisBlobDescriptorService) blobDescriptorHashKey(dgst digest.Digest) string { - return "repository::" + rsrbds.repo + "::blobs::" + dgst.String() -} - -func (rsrbds *repositoryScopedRedisBlobDescriptorService) repositoryBlobSetKey(repo string) string { - return "repository::" + rsrbds.repo + "::blobs" -} diff --git a/vendor/github.com/docker/distribution/registry/storage/cache/redis/redis_test.go b/vendor/github.com/docker/distribution/registry/storage/cache/redis/redis_test.go deleted file mode 100644 index 81bcaddd..00000000 --- a/vendor/github.com/docker/distribution/registry/storage/cache/redis/redis_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package redis - -import ( - "flag" - "os" - "testing" - "time" - - "github.com/docker/distribution/registry/storage/cache/cachecheck" - "github.com/garyburd/redigo/redis" -) - -var redisAddr string - -func init() { - flag.StringVar(&redisAddr, "test.registry.storage.cache.redis.addr", "", "configure the address of a test instance of redis") -} - -// TestRedisLayerInfoCache exercises a live redis instance using the cache -// implementation. -func TestRedisBlobDescriptorCacheProvider(t *testing.T) { - if redisAddr == "" { - // fallback to an environement variable - redisAddr = os.Getenv("TEST_REGISTRY_STORAGE_CACHE_REDIS_ADDR") - } - - if redisAddr == "" { - // skip if still not set - t.Skip("please set -registry.storage.cache.redis to test layer info cache against redis") - } - - pool := &redis.Pool{ - Dial: func() (redis.Conn, error) { - return redis.Dial("tcp", redisAddr) - }, - MaxIdle: 1, - MaxActive: 2, - TestOnBorrow: func(c redis.Conn, t time.Time) error { - _, err := c.Do("PING") - return err - }, - Wait: false, // if a connection is not avialable, proceed without cache. - } - - // Clear the database - if _, err := pool.Get().Do("FLUSHDB"); err != nil { - t.Fatalf("unexpected error flushing redis db: %v", err) - } - - cachecheck.CheckBlobDescriptorCache(t, NewRedisBlobDescriptorCacheProvider(pool)) -} diff --git a/vendor/github.com/docker/docker/api/README.md b/vendor/github.com/docker/docker/api/README.md deleted file mode 100644 index 453f61a1..00000000 --- a/vendor/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/vendor/github.com/docker/docker/api/client/attach.go b/vendor/github.com/docker/docker/api/client/attach.go deleted file mode 100644 index 825543d4..00000000 --- a/vendor/github.com/docker/docker/api/client/attach.go +++ /dev/null @@ -1,88 +0,0 @@ -package client - -import ( - "encoding/json" - "fmt" - "io" - "net/url" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/signal" -) - -// CmdAttach attaches to a running container. -// -// Usage: docker attach [OPTIONS] CONTAINER -func (cli *DockerCli) CmdAttach(args ...string) error { - cmd := Cli.Subcmd("attach", []string{"CONTAINER"}, Cli.DockerCommands["attach"].Description, 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") - - cmd.Require(flag.Exact, 1) - - cmd.ParseFlags(args, true) - - serverResp, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/json", nil, nil) - if err != nil { - return err - } - - defer serverResp.body.Close() - - var c types.ContainerJSON - if err := json.NewDecoder(serverResp.body).Decode(&c); err != nil { - return err - } - - if !c.State.Running { - return fmt.Errorf("You cannot attach to a stopped container, start it first") - } - - if c.State.Paused { - return fmt.Errorf("You cannot attach to a paused container, unpause it first") - } - - if err := cli.CheckTtyInput(!*noStdin, c.Config.Tty); err != nil { - return err - } - - if c.Config.Tty && cli.isTerminalOut { - if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil { - logrus.Debugf("Error monitoring TTY size: %s", err) - } - } - - var in io.ReadCloser - - v := url.Values{} - v.Set("stream", "1") - if !*noStdin && c.Config.OpenStdin { - v.Set("stdin", "1") - in = cli.in - } - - v.Set("stdout", "1") - v.Set("stderr", "1") - - if *proxy && !c.Config.Tty { - sigc := cli.forwardAllSignals(cmd.Arg(0)) - defer signal.StopCatch(sigc) - } - - if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), c.Config.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 Cli.StatusError{StatusCode: status} - } - - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/build.go b/vendor/github.com/docker/docker/api/client/build.go deleted file mode 100644 index 44e95fb9..00000000 --- a/vendor/github.com/docker/docker/api/client/build.go +++ /dev/null @@ -1,685 +0,0 @@ -package client - -import ( - "archive/tar" - "bufio" - "encoding/base64" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "os" - "os/exec" - "path/filepath" - "regexp" - "runtime" - "strconv" - "strings" - - "github.com/docker/docker/api" - Cli "github.com/docker/docker/cli" - "github.com/docker/docker/graph/tags" - "github.com/docker/docker/opts" - "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/fileutils" - "github.com/docker/docker/pkg/httputils" - "github.com/docker/docker/pkg/jsonmessage" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/parsers" - "github.com/docker/docker/pkg/progressreader" - "github.com/docker/docker/pkg/streamformatter" - "github.com/docker/docker/pkg/ulimit" - "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 -) - -// CmdBuild builds a new image from the source code at a given path. -// -// If '-' is provided instead of a path or URL, Docker will build an image from either a Dockerfile or tar archive read from STDIN. -// -// Usage: docker build [OPTIONS] PATH | URL | - -func (cli *DockerCli) CmdBuild(args ...string) error { - cmd := Cli.Subcmd("build", []string{"PATH | URL | -"}, Cli.DockerCommands["build"].Description, true) - flTags := opts.NewListOpts(validateTag) - cmd.Var(&flTags, []string{"t", "-tag"}, "Name and optionally a tag in the 'name:tag' format") - 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") - 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 'PATH/Dockerfile')") - flMemoryString := cmd.String([]string{"m", "-memory"}, "", "Memory limit") - flMemorySwap := cmd.String([]string{"-memory-swap"}, "", "Total memory (memory + swap), '-1' to disable swap") - flCPUShares := cmd.Int64([]string{"#c", "-cpu-shares"}, 0, "CPU shares (relative weight)") - flCPUPeriod := cmd.Int64([]string{"-cpu-period"}, 0, "Limit the CPU CFS (Completely Fair Scheduler) period") - flCPUQuota := cmd.Int64([]string{"-cpu-quota"}, 0, "Limit the CPU CFS (Completely Fair Scheduler) quota") - flCPUSetCpus := cmd.String([]string{"-cpuset-cpus"}, "", "CPUs in which to allow execution (0-3, 0,1)") - flCPUSetMems := cmd.String([]string{"-cpuset-mems"}, "", "MEMs in which to allow execution (0-3, 0,1)") - flCgroupParent := cmd.String([]string{"-cgroup-parent"}, "", "Optional parent cgroup for the container") - flBuildArg := opts.NewListOpts(opts.ValidateEnv) - cmd.Var(&flBuildArg, []string{"-build-arg"}, "Set build-time variables") - isolation := cmd.String([]string{"-isolation"}, "", "Container isolation level") - - ulimits := make(map[string]*ulimit.Ulimit) - flUlimits := opts.NewUlimitOpt(&ulimits) - cmd.Var(flUlimits, []string{"-ulimit"}, "Ulimit options") - - cmd.Require(flag.Exact, 1) - - // For trusted pull on "FROM " instruction. - addTrustedFlags(cmd, true) - - cmd.ParseFlags(args, true) - - var ( - context io.ReadCloser - isRemote bool - err error - ) - - _, err = exec.LookPath("git") - hasGit := err == nil - - specifiedContext := cmd.Arg(0) - - var ( - contextDir string - tempDir string - relDockerfile string - ) - - switch { - case specifiedContext == "-": - tempDir, relDockerfile, err = getContextFromReader(cli.in, *dockerfileName) - case urlutil.IsGitURL(specifiedContext) && hasGit: - tempDir, relDockerfile, err = getContextFromGitURL(specifiedContext, *dockerfileName) - case urlutil.IsURL(specifiedContext): - tempDir, relDockerfile, err = getContextFromURL(cli.out, specifiedContext, *dockerfileName) - default: - contextDir, relDockerfile, err = getContextFromLocalDir(specifiedContext, *dockerfileName) - } - - if err != nil { - return fmt.Errorf("unable to prepare context: %s", err) - } - - if tempDir != "" { - defer os.RemoveAll(tempDir) - contextDir = tempDir - } - - // Resolve the FROM lines in the Dockerfile to trusted digest references - // using Notary. On a successful build, we must tag the resolved digests - // to the original name specified in the Dockerfile. - newDockerfile, resolvedTags, err := rewriteDockerfileFrom(filepath.Join(contextDir, relDockerfile), cli.trustedReference) - if err != nil { - return fmt.Errorf("unable to process Dockerfile: %v", err) - } - defer newDockerfile.Close() - - // And canonicalize dockerfile name to a platform-independent one - relDockerfile, err = archive.CanonicalTarNameForPath(relDockerfile) - if err != nil { - return fmt.Errorf("cannot canonicalize dockerfile path %s: %v", relDockerfile, err) - } - - f, err := os.Open(filepath.Join(contextDir, ".dockerignore")) - if err != nil && !os.IsNotExist(err) { - return err - } - - var excludes []string - if err == nil { - excludes, err = utils.ReadDockerIgnore(f) - if err != nil { - return err - } - } - - if err := utils.ValidateContextDirectory(contextDir, excludes); err != nil { - return fmt.Errorf("Error checking context: '%s'.", 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. Ignore errors here, as they will have been - // caught by ValidateContextDirectory above. - var includes = []string{"."} - keepThem1, _ := fileutils.Matches(".dockerignore", excludes) - keepThem2, _ := fileutils.Matches(relDockerfile, excludes) - if keepThem1 || keepThem2 { - includes = append(includes, ".dockerignore", relDockerfile) - } - - context, err = archive.TarWithOptions(contextDir, &archive.TarOptions{ - Compression: archive.Uncompressed, - ExcludePatterns: excludes, - IncludeFiles: includes, - }) - if err != nil { - return err - } - - // Wrap the tar archive to replace the Dockerfile entry with the rewritten - // Dockerfile which uses trusted pulls. - context = replaceDockerfileTarWrapper(context, newDockerfile, relDockerfile) - - // Setup an upload progress bar - // FIXME: ProgressReader shouldn't be this annoying to use - sf := streamformatter.NewStreamFormatter() - var body io.Reader = progressreader.New(progressreader.Config{ - In: context, - Out: cli.out, - Formatter: sf, - NewLines: true, - ID: "", - Action: "Sending build context to Docker daemon", - }) - - var memory int64 - if *flMemoryString != "" { - parsedMemory, err := units.RAMInBytes(*flMemoryString) - if err != nil { - return err - } - memory = parsedMemory - } - - var memorySwap int64 - if *flMemorySwap != "" { - if *flMemorySwap == "-1" { - memorySwap = -1 - } else { - parsedMemorySwap, err := units.RAMInBytes(*flMemorySwap) - if err != nil { - return err - } - memorySwap = parsedMemorySwap - } - } - - // Send the build context - v := url.Values{ - "t": flTags.GetAll(), - } - 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") - } - - if !runconfig.IsolationLevel.IsDefault(runconfig.IsolationLevel(*isolation)) { - v.Set("isolation", *isolation) - } - - v.Set("cpusetcpus", *flCPUSetCpus) - v.Set("cpusetmems", *flCPUSetMems) - v.Set("cpushares", strconv.FormatInt(*flCPUShares, 10)) - v.Set("cpuquota", strconv.FormatInt(*flCPUQuota, 10)) - v.Set("cpuperiod", strconv.FormatInt(*flCPUPeriod, 10)) - v.Set("memory", strconv.FormatInt(memory, 10)) - v.Set("memswap", strconv.FormatInt(memorySwap, 10)) - v.Set("cgroupparent", *flCgroupParent) - - v.Set("dockerfile", relDockerfile) - - ulimitsVar := flUlimits.GetList() - ulimitsJSON, err := json.Marshal(ulimitsVar) - if err != nil { - return err - } - v.Set("ulimits", string(ulimitsJSON)) - - // collect all the build-time environment variables for the container - buildArgs := runconfig.ConvertKVStringsToMap(flBuildArg.GetAll()) - buildArgsJSON, err := json.Marshal(buildArgs) - if err != nil { - return err - } - v.Set("buildargs", string(buildArgsJSON)) - - headers := http.Header(make(map[string][]string)) - buf, err := json.Marshal(cli.configFile.AuthConfigs) - if err != nil { - return err - } - headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf)) - headers.Set("Content-Type", "application/tar") - - sopts := &streamOpts{ - rawTerminal: true, - in: body, - out: cli.out, - headers: headers, - } - - serverResp, err := cli.stream("POST", fmt.Sprintf("/build?%s", v.Encode()), sopts) - - // Windows: show error message about modified file permissions. - if runtime.GOOS == "windows" { - h, err := httputils.ParseServerHeader(serverResp.header.Get("Server")) - if err == nil { - if h.OS != "windows" { - fmt.Fprintln(cli.err, `SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.`) - } - } - } - - if jerr, ok := err.(*jsonmessage.JSONError); ok { - // If no error code is set, default to 1 - if jerr.Code == 0 { - jerr.Code = 1 - } - return Cli.StatusError{Status: jerr.Message, StatusCode: jerr.Code} - } - - if err != nil { - return err - } - - // Since the build was successful, now we must tag any of the resolved - // images from the above Dockerfile rewrite. - for _, resolved := range resolvedTags { - if err := cli.tagTrusted(resolved.repoInfo, resolved.digestRef, resolved.tagRef); err != nil { - return err - } - } - - return nil -} - -// validateTag checks if the given image name can be resolved. -func validateTag(rawRepo string) (string, error) { - repository, tag := parsers.ParseRepositoryTag(rawRepo) - if err := registry.ValidateRepositoryName(repository); err != nil { - return "", err - } - - if len(tag) == 0 { - return rawRepo, nil - } - - if err := tags.ValidateTagName(tag); err != nil { - return "", err - } - - return rawRepo, nil -} - -// isUNC returns true if the path is UNC (one starting \\). It always returns -// false on Linux. -func isUNC(path string) bool { - return runtime.GOOS == "windows" && strings.HasPrefix(path, `\\`) -} - -// getDockerfileRelPath uses the given context directory for a `docker build` -// and returns the absolute path to the context directory, the relative path of -// the dockerfile in that context directory, and a non-nil error on success. -func getDockerfileRelPath(givenContextDir, givenDockerfile string) (absContextDir, relDockerfile string, err error) { - if absContextDir, err = filepath.Abs(givenContextDir); err != nil { - return "", "", fmt.Errorf("unable to get absolute context directory: %v", err) - } - - // The context dir might be a symbolic link, so follow it to the actual - // target directory. - // - // FIXME. We use isUNC (always false on non-Windows platforms) to workaround - // an issue in golang. On Windows, EvalSymLinks does not work on UNC file - // paths (those starting with \\). This hack means that when using links - // on UNC paths, they will not be followed. - if !isUNC(absContextDir) { - absContextDir, err = filepath.EvalSymlinks(absContextDir) - if err != nil { - return "", "", fmt.Errorf("unable to evaluate symlinks in context path: %v", err) - } - } - - stat, err := os.Lstat(absContextDir) - if err != nil { - return "", "", fmt.Errorf("unable to stat context directory %q: %v", absContextDir, err) - } - - if !stat.IsDir() { - return "", "", fmt.Errorf("context must be a directory: %s", absContextDir) - } - - absDockerfile := givenDockerfile - if absDockerfile == "" { - // No -f/--file was specified so use the default relative to the - // context directory. - absDockerfile = filepath.Join(absContextDir, api.DefaultDockerfileName) - - // Just to be nice ;-) look for 'dockerfile' too but only - // use it if we found it, otherwise ignore this check - if _, err = os.Lstat(absDockerfile); os.IsNotExist(err) { - altPath := filepath.Join(absContextDir, strings.ToLower(api.DefaultDockerfileName)) - if _, err = os.Lstat(altPath); err == nil { - absDockerfile = altPath - } - } - } - - // If not already an absolute path, the Dockerfile path should be joined to - // the base directory. - if !filepath.IsAbs(absDockerfile) { - absDockerfile = filepath.Join(absContextDir, absDockerfile) - } - - // Evaluate symlinks in the path to the Dockerfile too. - // - // FIXME. We use isUNC (always false on non-Windows platforms) to workaround - // an issue in golang. On Windows, EvalSymLinks does not work on UNC file - // paths (those starting with \\). This hack means that when using links - // on UNC paths, they will not be followed. - if !isUNC(absDockerfile) { - absDockerfile, err = filepath.EvalSymlinks(absDockerfile) - if err != nil { - return "", "", fmt.Errorf("unable to evaluate symlinks in Dockerfile path: %v", err) - } - } - - if _, err := os.Lstat(absDockerfile); err != nil { - if os.IsNotExist(err) { - return "", "", fmt.Errorf("Cannot locate Dockerfile: %q", absDockerfile) - } - return "", "", fmt.Errorf("unable to stat Dockerfile: %v", err) - } - - if relDockerfile, err = filepath.Rel(absContextDir, absDockerfile); err != nil { - return "", "", fmt.Errorf("unable to get relative Dockerfile path: %v", err) - } - - if strings.HasPrefix(relDockerfile, ".."+string(filepath.Separator)) { - return "", "", fmt.Errorf("The Dockerfile (%s) must be within the build context (%s)", givenDockerfile, givenContextDir) - } - - return absContextDir, relDockerfile, nil -} - -// writeToFile copies from the given reader and writes it to a file with the -// given filename. -func writeToFile(r io.Reader, filename string) error { - file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600)) - if err != nil { - return fmt.Errorf("unable to create file: %v", err) - } - defer file.Close() - - if _, err := io.Copy(file, r); err != nil { - return fmt.Errorf("unable to write file: %v", err) - } - - return nil -} - -// getContextFromReader will read the contents of the given reader as either a -// Dockerfile or tar archive to be extracted to a temporary directory used as -// the context directory. Returns the absolute path to the temporary context -// directory, the relative path of the dockerfile in that context directory, -// and a non-nil error on success. -func getContextFromReader(r io.Reader, dockerfileName string) (absContextDir, relDockerfile string, err error) { - buf := bufio.NewReader(r) - - magic, err := buf.Peek(tarHeaderSize) - if err != nil && err != io.EOF { - return "", "", fmt.Errorf("failed to peek context header from STDIN: %v", err) - } - - if absContextDir, err = ioutil.TempDir("", "docker-build-context-"); err != nil { - return "", "", fmt.Errorf("unbale to create temporary context directory: %v", err) - } - - defer func(d string) { - if err != nil { - os.RemoveAll(d) - } - }(absContextDir) - - if !archive.IsArchive(magic) { // Input should be read as a Dockerfile. - // -f option has no meaning when we're reading it from stdin, - // so just use our default Dockerfile name - relDockerfile = api.DefaultDockerfileName - - return absContextDir, relDockerfile, writeToFile(buf, filepath.Join(absContextDir, relDockerfile)) - } - - if err := archive.Untar(buf, absContextDir, nil); err != nil { - return "", "", fmt.Errorf("unable to extract stdin to temporary context directory: %v", err) - } - - return getDockerfileRelPath(absContextDir, dockerfileName) -} - -// getContextFromGitURL uses a Git URL as context for a `docker build`. The -// git repo is cloned into a temporary directory used as the context directory. -// Returns the absolute path to the temporary context directory, the relative -// path of the dockerfile in that context directory, and a non-nil error on -// success. -func getContextFromGitURL(gitURL, dockerfileName string) (absContextDir, relDockerfile string, err error) { - if absContextDir, err = utils.GitClone(gitURL); err != nil { - return "", "", fmt.Errorf("unable to 'git clone' to temporary context directory: %v", err) - } - - return getDockerfileRelPath(absContextDir, dockerfileName) -} - -// getContextFromURL uses a remote URL as context for a `docker build`. The -// remote resource is downloaded as either a Dockerfile or a context tar -// archive and stored in a temporary directory used as the context directory. -// Returns the absolute path to the temporary context directory, the relative -// path of the dockerfile in that context directory, and a non-nil error on -// success. -func getContextFromURL(out io.Writer, remoteURL, dockerfileName string) (absContextDir, relDockerfile string, err error) { - response, err := httputils.Download(remoteURL) - if err != nil { - return "", "", fmt.Errorf("unable to download remote context %s: %v", remoteURL, err) - } - defer response.Body.Close() - - // Pass the response body through a progress reader. - progReader := &progressreader.Config{ - In: response.Body, - Out: out, - Formatter: streamformatter.NewStreamFormatter(), - Size: response.ContentLength, - NewLines: true, - ID: "", - Action: fmt.Sprintf("Downloading build context from remote url: %s", remoteURL), - } - - return getContextFromReader(progReader, dockerfileName) -} - -// getContextFromLocalDir uses the given local directory as context for a -// `docker build`. Returns the absolute path to the local context directory, -// the relative path of the dockerfile in that context directory, and a non-nil -// error on success. -func getContextFromLocalDir(localDir, dockerfileName string) (absContextDir, relDockerfile string, err error) { - // When using a local context directory, when the Dockerfile is specified - // with the `-f/--file` option then it is considered relative to the - // current directory and not the context directory. - if dockerfileName != "" { - if dockerfileName, err = filepath.Abs(dockerfileName); err != nil { - return "", "", fmt.Errorf("unable to get absolute path to Dockerfile: %v", err) - } - } - - return getDockerfileRelPath(localDir, dockerfileName) -} - -var dockerfileFromLinePattern = regexp.MustCompile(`(?i)^[\s]*FROM[ \f\r\t\v]+(?P[^ \f\r\t\v\n#]+)`) - -type trustedDockerfile struct { - *os.File - size int64 -} - -func (td *trustedDockerfile) Close() error { - td.File.Close() - return os.Remove(td.File.Name()) -} - -// resolvedTag records the repository, tag, and resolved digest reference -// from a Dockerfile rewrite. -type resolvedTag struct { - repoInfo *registry.RepositoryInfo - digestRef, tagRef registry.Reference -} - -// rewriteDockerfileFrom rewrites the given Dockerfile by resolving images in -// "FROM " instructions to a digest reference. `translator` is a -// function that takes a repository name and tag reference and returns a -// trusted digest reference. -func rewriteDockerfileFrom(dockerfileName string, translator func(string, registry.Reference) (registry.Reference, error)) (newDockerfile *trustedDockerfile, resolvedTags []*resolvedTag, err error) { - dockerfile, err := os.Open(dockerfileName) - if err != nil { - return nil, nil, fmt.Errorf("unable to open Dockerfile: %v", err) - } - defer dockerfile.Close() - - scanner := bufio.NewScanner(dockerfile) - - // Make a tempfile to store the rewritten Dockerfile. - tempFile, err := ioutil.TempFile("", "trusted-dockerfile-") - if err != nil { - return nil, nil, fmt.Errorf("unable to make temporary trusted Dockerfile: %v", err) - } - - trustedFile := &trustedDockerfile{ - File: tempFile, - } - - defer func() { - if err != nil { - // Close the tempfile if there was an error during Notary lookups. - // Otherwise the caller should close it. - trustedFile.Close() - } - }() - - // Scan the lines of the Dockerfile, looking for a "FROM" line. - for scanner.Scan() { - line := scanner.Text() - - matches := dockerfileFromLinePattern.FindStringSubmatch(line) - if matches != nil && matches[1] != "scratch" { - // Replace the line with a resolved "FROM repo@digest" - repo, tag := parsers.ParseRepositoryTag(matches[1]) - if tag == "" { - tag = tags.DefaultTag - } - - repoInfo, err := registry.ParseRepositoryInfo(repo) - if err != nil { - return nil, nil, fmt.Errorf("unable to parse repository info %q: %v", repo, err) - } - - ref := registry.ParseReference(tag) - - if !ref.HasDigest() && isTrusted() { - trustedRef, err := translator(repo, ref) - if err != nil { - return nil, nil, err - } - - line = dockerfileFromLinePattern.ReplaceAllLiteralString(line, fmt.Sprintf("FROM %s", trustedRef.ImageName(repo))) - resolvedTags = append(resolvedTags, &resolvedTag{ - repoInfo: repoInfo, - digestRef: trustedRef, - tagRef: ref, - }) - } - } - - n, err := fmt.Fprintln(tempFile, line) - if err != nil { - return nil, nil, err - } - - trustedFile.size += int64(n) - } - - tempFile.Seek(0, os.SEEK_SET) - - return trustedFile, resolvedTags, scanner.Err() -} - -// replaceDockerfileTarWrapper wraps the given input tar archive stream and -// replaces the entry with the given Dockerfile name with the contents of the -// new Dockerfile. Returns a new tar archive stream with the replaced -// Dockerfile. -func replaceDockerfileTarWrapper(inputTarStream io.ReadCloser, newDockerfile *trustedDockerfile, dockerfileName string) io.ReadCloser { - pipeReader, pipeWriter := io.Pipe() - - go func() { - tarReader := tar.NewReader(inputTarStream) - tarWriter := tar.NewWriter(pipeWriter) - - defer inputTarStream.Close() - - for { - hdr, err := tarReader.Next() - if err == io.EOF { - // Signals end of archive. - tarWriter.Close() - pipeWriter.Close() - return - } - if err != nil { - pipeWriter.CloseWithError(err) - return - } - - var content io.Reader = tarReader - - if hdr.Name == dockerfileName { - // This entry is the Dockerfile. Since the tar archive was - // generated from a directory on the local filesystem, the - // Dockerfile will only appear once in the archive. - hdr.Size = newDockerfile.size - content = newDockerfile - } - - if err := tarWriter.WriteHeader(hdr); err != nil { - pipeWriter.CloseWithError(err) - return - } - - if _, err := io.Copy(tarWriter, content); err != nil { - pipeWriter.CloseWithError(err) - return - } - } - }() - - return pipeReader -} diff --git a/vendor/github.com/docker/docker/api/client/cli.go b/vendor/github.com/docker/docker/api/client/cli.go deleted file mode 100644 index 834c47a4..00000000 --- a/vendor/github.com/docker/docker/api/client/cli.go +++ /dev/null @@ -1,169 +0,0 @@ -package client - -import ( - "crypto/tls" - "errors" - "fmt" - "io" - "net/http" - "net/url" - "os" - "strings" - - "github.com/docker/docker/cli" - "github.com/docker/docker/cliconfig" - "github.com/docker/docker/opts" - "github.com/docker/docker/pkg/sockets" - "github.com/docker/docker/pkg/term" - "github.com/docker/docker/pkg/tlsconfig" -) - -// DockerCli represents the docker command line client. -// Instances of the client can be returned from NewDockerCli. -type DockerCli struct { - // initializing closure - init func() error - - // proto holds the client protocol i.e. unix. - proto string - // addr holds the client address. - addr string - // basePath holds the path to prepend to the requests - basePath string - - // configFile has the client configuration file - configFile *cliconfig.ConfigFile - // in holds the input stream and closer (io.ReadCloser) for the client. - in io.ReadCloser - // out holds the output stream (io.Writer) for the client. - out io.Writer - // err holds the error stream (io.Writer) for the client. - err io.Writer - // keyFile holds the key file as a string. - keyFile string - // tlsConfig holds the TLS configuration for the client, and will - // set the scheme to https in NewDockerCli if present. - tlsConfig *tls.Config - // scheme holds the scheme of the client i.e. https. - scheme string - // inFd holds the file descriptor of the client's STDIN (if valid). - inFd uintptr - // outFd holds file descriptor of the client's STDOUT (if valid). - outFd uintptr - // isTerminalIn indicates whether the client's STDIN is a TTY - isTerminalIn bool - // isTerminalOut indicates whether the client's STDOUT is a TTY - isTerminalOut bool - // transport holds the client transport instance. - transport *http.Transport -} - -// Initialize calls the init function that will setup the configuration for the client -// such as the TLS, tcp and other parameters used to run the client. -func (cli *DockerCli) Initialize() error { - if cli.init == nil { - return nil - } - return cli.init() -} - -// CheckTtyInput checks if we are trying to attach to a container tty -// from a non-tty client input stream, and if so, returns an error. -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 -} - -// PsFormat returns the format string specified in the configuration. -// String contains columns and format specification, for example {{ID}\t{{Name}}. -func (cli *DockerCli) PsFormat() string { - return cli.configFile.PsFormat -} - -// NewDockerCli returns a DockerCli instance with IO output and error streams set by in, out and err. -// The key file, protocol (i.e. unix) and address are passed in as strings, along with the tls.Config. If the tls.Config -// is set the client scheme will be set to https. -// The client will be given a 32-second timeout (see https://github.com/docker/docker/pull/8035). -func NewDockerCli(in io.ReadCloser, out, err io.Writer, clientFlags *cli.ClientFlags) *DockerCli { - cli := &DockerCli{ - in: in, - out: out, - err: err, - keyFile: clientFlags.Common.TrustKey, - } - - cli.init = func() error { - - clientFlags.PostParse() - - hosts := clientFlags.Common.Hosts - - switch len(hosts) { - case 0: - hosts = []string{os.Getenv("DOCKER_HOST")} - case 1: - // only accept one host to talk to - default: - return errors.New("Please specify only one -H") - } - - defaultHost := opts.DefaultTCPHost - if clientFlags.Common.TLSOptions != nil { - defaultHost = opts.DefaultTLSHost - } - - var e error - if hosts[0], e = opts.ParseHost(defaultHost, hosts[0]); e != nil { - return e - } - - protoAddrParts := strings.SplitN(hosts[0], "://", 2) - cli.proto, cli.addr = protoAddrParts[0], protoAddrParts[1] - - if cli.proto == "tcp" { - // error is checked in pkg/parsers already - parsed, _ := url.Parse("tcp://" + cli.addr) - cli.addr = parsed.Host - cli.basePath = parsed.Path - } - - if clientFlags.Common.TLSOptions != nil { - cli.scheme = "https" - var e error - cli.tlsConfig, e = tlsconfig.Client(*clientFlags.Common.TLSOptions) - if e != nil { - return e - } - } else { - cli.scheme = "http" - } - - if cli.in != nil { - cli.inFd, cli.isTerminalIn = term.GetFdInfo(cli.in) - } - if cli.out != nil { - cli.outFd, cli.isTerminalOut = term.GetFdInfo(cli.out) - } - - // The transport is created here for reuse during the client session. - cli.transport = &http.Transport{ - TLSClientConfig: cli.tlsConfig, - } - sockets.ConfigureTCPTransport(cli.transport, cli.proto, cli.addr) - - configFile, e := cliconfig.Load(cliconfig.ConfigDir()) - if e != nil { - fmt.Fprintf(cli.err, "WARNING: Error loading config file:%v\n", e) - } - cli.configFile = configFile - - return nil - } - - return cli -} diff --git a/vendor/github.com/docker/docker/api/client/client.go b/vendor/github.com/docker/docker/api/client/client.go deleted file mode 100644 index 4cfce5f6..00000000 --- a/vendor/github.com/docker/docker/api/client/client.go +++ /dev/null @@ -1,5 +0,0 @@ -// Package client provides a command-line interface for Docker. -// -// Run "docker help SUBCOMMAND" or "docker SUBCOMMAND --help" to see more information on any Docker subcommand, including the full list of options supported for the subcommand. -// See https://docs.docker.com/installation/ for instructions on installing Docker. -package client diff --git a/vendor/github.com/docker/docker/api/client/commit.go b/vendor/github.com/docker/docker/api/client/commit.go deleted file mode 100644 index 6a837881..00000000 --- a/vendor/github.com/docker/docker/api/client/commit.go +++ /dev/null @@ -1,84 +0,0 @@ -package client - -import ( - "encoding/json" - "fmt" - "net/url" - - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - "github.com/docker/docker/opts" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/parsers" - "github.com/docker/docker/registry" - "github.com/docker/docker/runconfig" -) - -// CmdCommit creates a new image from a container's changes. -// -// Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] -func (cli *DockerCli) CmdCommit(args ...string) error { - cmd := Cli.Subcmd("commit", []string{"CONTAINER [REPOSITORY[:TAG]]"}, Cli.DockerCommands["commit"].Description, 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 \")") - flChanges := opts.NewListOpts(nil) - cmd.Var(&flChanges, []string{"c", "-change"}, "Apply Dockerfile instruction to the created image") - // 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) - - cmd.ParseFlags(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) - for _, change := range flChanges.GetAll() { - v.Add("changes", change) - } - - if *flPause != true { - v.Set("pause", "0") - } - - var ( - config *runconfig.Config - response types.ContainerCommitResponse - ) - - if *flConfig != "" { - config = &runconfig.Config{} - if err := json.Unmarshal([]byte(*flConfig), config); err != nil { - return err - } - } - serverResp, err := cli.call("POST", "/commit?"+v.Encode(), config, nil) - if err != nil { - return err - } - - defer serverResp.body.Close() - - if err := json.NewDecoder(serverResp.body).Decode(&response); err != nil { - return err - } - - fmt.Fprintln(cli.out, response.ID) - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/cp.go b/vendor/github.com/docker/docker/api/client/cp.go deleted file mode 100644 index c055fced..00000000 --- a/vendor/github.com/docker/docker/api/client/cp.go +++ /dev/null @@ -1,325 +0,0 @@ -package client - -import ( - "encoding/base64" - "encoding/json" - "fmt" - "io" - "net/http" - "net/url" - "os" - "path/filepath" - "strings" - - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - "github.com/docker/docker/pkg/archive" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/system" -) - -type copyDirection int - -const ( - fromContainer copyDirection = (1 << iota) - toContainer - acrossContainers = fromContainer | toContainer -) - -// CmdCp copies files/folders to or from a path in a container. -// -// When copying from a container, if LOCALPATH is '-' the data is written as a -// tar archive file to STDOUT. -// -// When copying to a container, if LOCALPATH is '-' the data is read as a tar -// archive file from STDIN, and the destination CONTAINER:PATH, must specify -// a directory. -// -// Usage: -// docker cp CONTAINER:PATH LOCALPATH|- -// docker cp LOCALPATH|- CONTAINER:PATH -func (cli *DockerCli) CmdCp(args ...string) error { - cmd := Cli.Subcmd( - "cp", - []string{"CONTAINER:PATH LOCALPATH|-", "LOCALPATH|- CONTAINER:PATH"}, - strings.Join([]string{ - Cli.DockerCommands["cp"].Description, - "\nUse '-' as the source to read a tar archive from stdin\n", - "and extract it to a directory destination in a container.\n", - "Use '-' as the destination to stream a tar archive of a\n", - "container source to stdout.", - }, ""), - true, - ) - - cmd.Require(flag.Exact, 2) - cmd.ParseFlags(args, true) - - if cmd.Arg(0) == "" { - return fmt.Errorf("source can not be empty") - } - if cmd.Arg(1) == "" { - return fmt.Errorf("destination can not be empty") - } - - srcContainer, srcPath := splitCpArg(cmd.Arg(0)) - dstContainer, dstPath := splitCpArg(cmd.Arg(1)) - - var direction copyDirection - if srcContainer != "" { - direction |= fromContainer - } - if dstContainer != "" { - direction |= toContainer - } - - switch direction { - case fromContainer: - return cli.copyFromContainer(srcContainer, srcPath, dstPath) - case toContainer: - return cli.copyToContainer(srcPath, dstContainer, dstPath) - case acrossContainers: - // Copying between containers isn't supported. - return fmt.Errorf("copying between containers is not supported") - default: - // User didn't specify any container. - return fmt.Errorf("must specify at least one container source") - } -} - -// We use `:` as a delimiter between CONTAINER and PATH, but `:` could also be -// in a valid LOCALPATH, like `file:name.txt`. We can resolve this ambiguity by -// requiring a LOCALPATH with a `:` to be made explicit with a relative or -// absolute path: -// `/path/to/file:name.txt` or `./file:name.txt` -// -// This is apparently how `scp` handles this as well: -// http://www.cyberciti.biz/faq/rsync-scp-file-name-with-colon-punctuation-in-it/ -// -// We can't simply check for a filepath separator because container names may -// have a separator, e.g., "host0/cname1" if container is in a Docker cluster, -// so we have to check for a `/` or `.` prefix. Also, in the case of a Windows -// client, a `:` could be part of an absolute Windows path, in which case it -// is immediately proceeded by a backslash. -func splitCpArg(arg string) (container, path string) { - if system.IsAbs(arg) { - // Explicit local absolute path, e.g., `C:\foo` or `/foo`. - return "", arg - } - - parts := strings.SplitN(arg, ":", 2) - - if len(parts) == 1 || strings.HasPrefix(parts[0], ".") { - // Either there's no `:` in the arg - // OR it's an explicit local relative path like `./file:name.txt`. - return "", arg - } - - return parts[0], parts[1] -} - -func (cli *DockerCli) statContainerPath(containerName, path string) (types.ContainerPathStat, error) { - var stat types.ContainerPathStat - - query := make(url.Values, 1) - query.Set("path", filepath.ToSlash(path)) // Normalize the paths used in the API. - - urlStr := fmt.Sprintf("/containers/%s/archive?%s", containerName, query.Encode()) - - response, err := cli.call("HEAD", urlStr, nil, nil) - if err != nil { - return stat, err - } - defer response.body.Close() - - if response.statusCode != http.StatusOK { - return stat, fmt.Errorf("unexpected status code from daemon: %d", response.statusCode) - } - - return getContainerPathStatFromHeader(response.header) -} - -func getContainerPathStatFromHeader(header http.Header) (types.ContainerPathStat, error) { - var stat types.ContainerPathStat - - encodedStat := header.Get("X-Docker-Container-Path-Stat") - statDecoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(encodedStat)) - - err := json.NewDecoder(statDecoder).Decode(&stat) - if err != nil { - err = fmt.Errorf("unable to decode container path stat header: %s", err) - } - - return stat, err -} - -func resolveLocalPath(localPath string) (absPath string, err error) { - if absPath, err = filepath.Abs(localPath); err != nil { - return - } - - return archive.PreserveTrailingDotOrSeparator(absPath, localPath), nil -} - -func (cli *DockerCli) copyFromContainer(srcContainer, srcPath, dstPath string) (err error) { - if dstPath != "-" { - // Get an absolute destination path. - dstPath, err = resolveLocalPath(dstPath) - if err != nil { - return err - } - } - - query := make(url.Values, 1) - query.Set("path", filepath.ToSlash(srcPath)) // Normalize the paths used in the API. - - urlStr := fmt.Sprintf("/containers/%s/archive?%s", srcContainer, query.Encode()) - - response, err := cli.call("GET", urlStr, nil, nil) - if err != nil { - return err - } - defer response.body.Close() - - if response.statusCode != http.StatusOK { - return fmt.Errorf("unexpected status code from daemon: %d", response.statusCode) - } - - if dstPath == "-" { - // Send the response to STDOUT. - _, err = io.Copy(os.Stdout, response.body) - - return err - } - - // In order to get the copy behavior right, we need to know information - // about both the source and the destination. The response headers include - // stat info about the source that we can use in deciding exactly how to - // copy it locally. Along with the stat info about the local destination, - // we have everything we need to handle the multiple possibilities there - // can be when copying a file/dir from one location to another file/dir. - stat, err := getContainerPathStatFromHeader(response.header) - if err != nil { - return fmt.Errorf("unable to get resource stat from response: %s", err) - } - - // Prepare source copy info. - srcInfo := archive.CopyInfo{ - Path: srcPath, - Exists: true, - IsDir: stat.Mode.IsDir(), - } - - // See comments in the implementation of `archive.CopyTo` for exactly what - // goes into deciding how and whether the source archive needs to be - // altered for the correct copy behavior. - return archive.CopyTo(response.body, srcInfo, dstPath) -} - -func (cli *DockerCli) copyToContainer(srcPath, dstContainer, dstPath string) (err error) { - if srcPath != "-" { - // Get an absolute source path. - srcPath, err = resolveLocalPath(srcPath) - if err != nil { - return err - } - } - - // In order to get the copy behavior right, we need to know information - // about both the source and destination. The API is a simple tar - // archive/extract API but we can use the stat info header about the - // destination to be more informed about exactly what the destination is. - - // Prepare destination copy info by stat-ing the container path. - dstInfo := archive.CopyInfo{Path: dstPath} - dstStat, err := cli.statContainerPath(dstContainer, dstPath) - - // If the destination is a symbolic link, we should evaluate it. - if err == nil && dstStat.Mode&os.ModeSymlink != 0 { - linkTarget := dstStat.LinkTarget - if !system.IsAbs(linkTarget) { - // Join with the parent directory. - dstParent, _ := archive.SplitPathDirEntry(dstPath) - linkTarget = filepath.Join(dstParent, linkTarget) - } - - dstInfo.Path = linkTarget - dstStat, err = cli.statContainerPath(dstContainer, linkTarget) - } - - // Ignore any error and assume that the parent directory of the destination - // path exists, in which case the copy may still succeed. If there is any - // type of conflict (e.g., non-directory overwriting an existing directory - // or vice versia) the extraction will fail. If the destination simply did - // not exist, but the parent directory does, the extraction will still - // succeed. - if err == nil { - dstInfo.Exists, dstInfo.IsDir = true, dstStat.Mode.IsDir() - } - - var ( - content io.Reader - resolvedDstPath string - ) - - if srcPath == "-" { - // Use STDIN. - content = os.Stdin - resolvedDstPath = dstInfo.Path - if !dstInfo.IsDir { - return fmt.Errorf("destination %q must be a directory", fmt.Sprintf("%s:%s", dstContainer, dstPath)) - } - } else { - // Prepare source copy info. - srcInfo, err := archive.CopyInfoSourcePath(srcPath) - if err != nil { - return err - } - - srcArchive, err := archive.TarResource(srcInfo) - if err != nil { - return err - } - defer srcArchive.Close() - - // With the stat info about the local source as well as the - // destination, we have enough information to know whether we need to - // alter the archive that we upload so that when the server extracts - // it to the specified directory in the container we get the disired - // copy behavior. - - // See comments in the implementation of `archive.PrepareArchiveCopy` - // for exactly what goes into deciding how and whether the source - // archive needs to be altered for the correct copy behavior when it is - // extracted. This function also infers from the source and destination - // info which directory to extract to, which may be the parent of the - // destination that the user specified. - dstDir, preparedArchive, err := archive.PrepareArchiveCopy(srcArchive, srcInfo, dstInfo) - if err != nil { - return err - } - defer preparedArchive.Close() - - resolvedDstPath = dstDir - content = preparedArchive - } - - query := make(url.Values, 2) - query.Set("path", filepath.ToSlash(resolvedDstPath)) // Normalize the paths used in the API. - // Do not allow for an existing directory to be overwritten by a non-directory and vice versa. - query.Set("noOverwriteDirNonDir", "true") - - urlStr := fmt.Sprintf("/containers/%s/archive?%s", dstContainer, query.Encode()) - - response, err := cli.stream("PUT", urlStr, &streamOpts{in: content}) - if err != nil { - return err - } - defer response.body.Close() - - if response.statusCode != http.StatusOK { - return fmt.Errorf("unexpected status code from daemon: %d", response.statusCode) - } - - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/create.go b/vendor/github.com/docker/docker/api/client/create.go deleted file mode 100644 index 9ef0edab..00000000 --- a/vendor/github.com/docker/docker/api/client/create.go +++ /dev/null @@ -1,185 +0,0 @@ -package client - -import ( - "encoding/base64" - "encoding/json" - "fmt" - "io" - "net/url" - "os" - "strings" - - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - "github.com/docker/docker/graph/tags" - "github.com/docker/docker/pkg/parsers" - "github.com/docker/docker/registry" - "github.com/docker/docker/runconfig" -) - -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 = tags.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 - } - - // Resolve the Auth config relevant for this server - authConfig := registry.ResolveAuthConfig(cli.configFile, repoInfo.Index) - buf, err := json.Marshal(authConfig) - if err != nil { - return err - } - - registryAuthHeader := []string{ - base64.URLEncoding.EncodeToString(buf), - } - sopts := &streamOpts{ - rawTerminal: true, - out: out, - headers: map[string][]string{"X-Registry-Auth": registryAuthHeader}, - } - if _, err := cli.stream("POST", "/images/create?"+v.Encode(), sopts); 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 (cli *DockerCli) createContainer(config *runconfig.Config, hostConfig *runconfig.HostConfig, cidfile, name string) (*types.ContainerCreateResponse, 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() - } - - repo, tag := parsers.ParseRepositoryTag(config.Image) - if tag == "" { - tag = tags.DefaultTag - } - - ref := registry.ParseReference(tag) - var trustedRef registry.Reference - - if isTrusted() && !ref.HasDigest() { - var err error - trustedRef, err = cli.trustedReference(repo, ref) - if err != nil { - return nil, err - } - config.Image = trustedRef.ImageName(repo) - } - - //create the container - serverResp, err := cli.call("POST", "/containers/create?"+containerValues.Encode(), mergedConfig, nil) - //if image not found try to pull it - if serverResp.statusCode == 404 && strings.Contains(err.Error(), config.Image) { - fmt.Fprintf(cli.err, "Unable to find image '%s' locally\n", ref.ImageName(repo)) - - // 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 - } - if trustedRef != nil && !ref.HasDigest() { - repoInfo, err := registry.ParseRepositoryInfo(repo) - if err != nil { - return nil, err - } - if err := cli.tagTrusted(repoInfo, trustedRef, ref); err != nil { - return nil, err - } - } - // Retry - if serverResp, err = cli.call("POST", "/containers/create?"+containerValues.Encode(), mergedConfig, nil); err != nil { - return nil, err - } - } else if err != nil { - return nil, err - } - - defer serverResp.body.Close() - - var response types.ContainerCreateResponse - if err := json.NewDecoder(serverResp.body).Decode(&response); err != nil { - return nil, err - } - for _, warning := range response.Warnings { - fmt.Fprintf(cli.err, "WARNING: %s\n", warning) - } - if containerIDFile != nil { - if err = containerIDFile.Write(response.ID); err != nil { - return nil, err - } - } - return &response, nil -} - -// CmdCreate creates a new container from a given image. -// -// Usage: docker create [OPTIONS] IMAGE [COMMAND] [ARG...] -func (cli *DockerCli) CmdCreate(args ...string) error { - cmd := Cli.Subcmd("create", []string{"IMAGE [COMMAND] [ARG...]"}, Cli.DockerCommands["create"].Description, true) - addTrustedFlags(cmd, 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 { - cmd.ReportError(err.Error(), true) - os.Exit(1) - } - if config.Image == "" { - cmd.Usage() - return nil - } - response, err := cli.createContainer(config, hostConfig, hostConfig.ContainerIDFile, *flName) - if err != nil { - return err - } - fmt.Fprintf(cli.out, "%s\n", response.ID) - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/diff.go b/vendor/github.com/docker/docker/api/client/diff.go deleted file mode 100644 index 24350a04..00000000 --- a/vendor/github.com/docker/docker/api/client/diff.go +++ /dev/null @@ -1,56 +0,0 @@ -package client - -import ( - "encoding/json" - "fmt" - - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - "github.com/docker/docker/pkg/archive" - flag "github.com/docker/docker/pkg/mflag" -) - -// CmdDiff shows changes on a container's filesystem. -// -// Each changed file is printed on a separate line, prefixed with a single -// character that indicates the status of the file: C (modified), A (added), -// or D (deleted). -// -// Usage: docker diff CONTAINER -func (cli *DockerCli) CmdDiff(args ...string) error { - cmd := Cli.Subcmd("diff", []string{"CONTAINER"}, Cli.DockerCommands["diff"].Description, true) - cmd.Require(flag.Exact, 1) - - cmd.ParseFlags(args, true) - - if cmd.Arg(0) == "" { - return fmt.Errorf("Container name cannot be empty") - } - - serverResp, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/changes", nil, nil) - if err != nil { - return err - } - - defer serverResp.body.Close() - - changes := []types.ContainerChange{} - if err := json.NewDecoder(serverResp.body).Decode(&changes); err != nil { - return err - } - - for _, change := range changes { - var kind string - switch change.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.Path) - } - - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/events.go b/vendor/github.com/docker/docker/api/client/events.go deleted file mode 100644 index 435b13e6..00000000 --- a/vendor/github.com/docker/docker/api/client/events.go +++ /dev/null @@ -1,63 +0,0 @@ -package client - -import ( - "net/url" - "time" - - Cli "github.com/docker/docker/cli" - "github.com/docker/docker/opts" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/parsers/filters" - "github.com/docker/docker/pkg/timeutils" -) - -// CmdEvents prints a live stream of real time events from the server. -// -// Usage: docker events [OPTIONS] -func (cli *DockerCli) CmdEvents(args ...string) error { - cmd := Cli.Subcmd("events", nil, Cli.DockerCommands["events"].Description, 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"}, "Filter output based on conditions provided") - cmd.Require(flag.Exact, 0) - - cmd.ParseFlags(args, true) - - var ( - v = url.Values{} - 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 - } - } - ref := time.Now() - if *since != "" { - v.Set("since", timeutils.GetTimestamp(*since, ref)) - } - if *until != "" { - v.Set("until", timeutils.GetTimestamp(*until, ref)) - } - if len(eventFilterArgs) > 0 { - filterJSON, err := filters.ToParam(eventFilterArgs) - if err != nil { - return err - } - v.Set("filters", filterJSON) - } - sopts := &streamOpts{ - rawTerminal: true, - out: cli.out, - } - if _, err := cli.stream("GET", "/events?"+v.Encode(), sopts); err != nil { - return err - } - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/exec.go b/vendor/github.com/docker/docker/api/client/exec.go deleted file mode 100644 index a9c836c9..00000000 --- a/vendor/github.com/docker/docker/api/client/exec.go +++ /dev/null @@ -1,134 +0,0 @@ -package client - -import ( - "encoding/json" - "fmt" - "io" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - "github.com/docker/docker/pkg/promise" - "github.com/docker/docker/runconfig" -) - -// CmdExec runs a command in a running container. -// -// Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...] -func (cli *DockerCli) CmdExec(args ...string) error { - cmd := Cli.Subcmd("exec", []string{"CONTAINER COMMAND [ARG...]"}, Cli.DockerCommands["exec"].Description, true) - - execConfig, err := runconfig.ParseExec(cmd, args) - // just in case the ParseExec does not exit - if execConfig.Container == "" || err != nil { - return Cli.StatusError{StatusCode: 1} - } - - serverResp, err := cli.call("POST", "/containers/"+execConfig.Container+"/exec", execConfig, nil) - if err != nil { - return err - } - - defer serverResp.body.Close() - - var response types.ContainerExecCreateResponse - if err := json.NewDecoder(serverResp.body).Decode(&response); err != nil { - return err - } - - execID := response.ID - - if execID == "" { - fmt.Fprintf(cli.out, "exec ID empty") - return nil - } - - //Temp struct for execStart so that we don't need to transfer all the execConfig - execStartCheck := &types.ExecStartCheck{ - Detach: execConfig.Detach, - Tty: execConfig.Tty, - } - - 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", execStartCheck, nil)); 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() { - logrus.Debugf("End of CmdExec(), Waiting for hijack to finish.") - if _, ok := <-hijacked; ok { - fmt.Fprintln(cli.err, "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.hijackWithContentType("POST", "/exec/"+execID+"/start", "application/json", 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 { - logrus.Debugf("Error hijack: %s", err) - return err - } - } - - if execConfig.Tty && cli.isTerminalIn { - if err := cli.monitorTtySize(execID, true); err != nil { - fmt.Fprintf(cli.err, "Error monitoring TTY size: %s\n", err) - } - } - - if err := <-errCh; err != nil { - logrus.Debugf("Error hijack: %s", err) - return err - } - - var status int - if _, status, err = getExecExitCode(cli, execID); err != nil { - return err - } - - if status != 0 { - return Cli.StatusError{StatusCode: status} - } - - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/export.go b/vendor/github.com/docker/docker/api/client/export.go deleted file mode 100644 index 2763b7b0..00000000 --- a/vendor/github.com/docker/docker/api/client/export.go +++ /dev/null @@ -1,46 +0,0 @@ -package client - -import ( - "errors" - "os" - - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" -) - -// CmdExport exports a filesystem as a tar archive. -// -// The tar archive is streamed to STDOUT by default or written to a file. -// -// Usage: docker export [OPTIONS] CONTAINER -func (cli *DockerCli) CmdExport(args ...string) error { - cmd := Cli.Subcmd("export", []string{"CONTAINER"}, Cli.DockerCommands["export"].Description, true) - outfile := cmd.String([]string{"o", "-output"}, "", "Write to a file, instead of STDOUT") - cmd.Require(flag.Exact, 1) - - cmd.ParseFlags(args, true) - - var ( - output = 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.") - } - - image := cmd.Arg(0) - sopts := &streamOpts{ - rawTerminal: true, - out: output, - } - if _, err := cli.stream("GET", "/containers/"+image+"/export", sopts); err != nil { - return err - } - - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/hijack.go b/vendor/github.com/docker/docker/api/client/hijack.go deleted file mode 100644 index bf152c6a..00000000 --- a/vendor/github.com/docker/docker/api/client/hijack.go +++ /dev/null @@ -1,258 +0,0 @@ -package client - -import ( - "crypto/tls" - "errors" - "fmt" - "io" - "net" - "net/http" - "net/http/httputil" - "os" - "runtime" - "strings" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/api" - "github.com/docker/docker/dockerversion" - "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 { - return cli.hijackWithContentType(method, path, "text/plain", setRawTerminal, in, stdout, stderr, started, data) -} - -func (cli *DockerCli) hijackWithContentType(method, path, contentType 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("%s/v%s%s", cli.basePath, api.Version, path), params) - if err != nil { - return err - } - - // Add CLI Config's HTTP Headers BEFORE we set the Docker headers - // then the user can't change OUR headers - for k, v := range cli.configFile.HTTPHeaders { - req.Header.Set(k, v) - } - - req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.Version+" ("+runtime.GOOS+")") - req.Header.Set("Content-Type", contentType) - req.Header.Set("Connection", "Upgrade") - req.Header.Set("Upgrade", "tcp") - req.Host = cli.addr - - dial, err := cli.dial() - if err != nil { - if strings.Contains(err.Error(), "connection refused") { - return fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker daemon' running on this host?") - } - return 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 := dial.(*net.TCPConn); ok { - tcpConn.SetKeepAlive(true) - tcpConn.SetKeepAlivePeriod(30 * time.Second) - } - - 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 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) - } - - receiveStdout := make(chan error, 1) - if stdout != nil || stderr != nil { - go func() { - defer func() { - if in != nil { - if setRawTerminal && cli.isTerminalIn { - term.RestoreTerminal(cli.inFd, oldState) - } - 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) - } - logrus.Debugf("[hijack] End of stdout") - receiveStdout <- err - }() - } - - stdinDone := make(chan struct{}) - go func() { - if in != nil { - io.Copy(rwc, in) - logrus.Debugf("[hijack] End of stdin") - } - - if conn, ok := rwc.(interface { - CloseWrite() error - }); ok { - if err := conn.CloseWrite(); err != nil { - logrus.Debugf("Couldn't send EOF: %s", err) - } - } - close(stdinDone) - }() - - select { - case err := <-receiveStdout: - if err != nil { - logrus.Debugf("Error receiveStdout: %s", err) - return err - } - case <-stdinDone: - if stdout != nil || stderr != nil { - if err := <-receiveStdout; err != nil { - logrus.Debugf("Error receiveStdout: %s", err) - return err - } - } - } - - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/history.go b/vendor/github.com/docker/docker/api/client/history.go deleted file mode 100644 index 37472bad..00000000 --- a/vendor/github.com/docker/docker/api/client/history.go +++ /dev/null @@ -1,83 +0,0 @@ -package client - -import ( - "encoding/json" - "fmt" - "strconv" - "strings" - "text/tabwriter" - "time" - - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/pkg/stringutils" - "github.com/docker/docker/pkg/units" -) - -// CmdHistory shows the history of an image. -// -// Usage: docker history [OPTIONS] IMAGE -func (cli *DockerCli) CmdHistory(args ...string) error { - cmd := Cli.Subcmd("history", []string{"IMAGE"}, Cli.DockerCommands["history"].Description, true) - human := cmd.Bool([]string{"H", "-human"}, true, "Print sizes and dates in human readable format") - 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) - - cmd.ParseFlags(args, true) - - serverResp, err := cli.call("GET", "/images/"+cmd.Arg(0)+"/history", nil, nil) - if err != nil { - return err - } - - defer serverResp.body.Close() - - history := []types.ImageHistory{} - if err := json.NewDecoder(serverResp.body).Decode(&history); err != nil { - return err - } - - w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) - - if *quiet { - for _, entry := range history { - if *noTrunc { - fmt.Fprintf(w, "%s\n", entry.ID) - } else { - fmt.Fprintf(w, "%s\n", stringid.TruncateID(entry.ID)) - } - } - w.Flush() - return nil - } - - var imageID string - var createdBy string - var created string - var size string - - fmt.Fprintln(w, "IMAGE\tCREATED\tCREATED BY\tSIZE\tCOMMENT") - for _, entry := range history { - imageID = entry.ID - createdBy = strings.Replace(entry.CreatedBy, "\t", " ", -1) - if *noTrunc == false { - createdBy = stringutils.Truncate(createdBy, 45) - imageID = stringid.TruncateID(entry.ID) - } - - if *human { - created = units.HumanDuration(time.Now().UTC().Sub(time.Unix(entry.Created, 0))) + " ago" - size = units.HumanSize(float64(entry.Size)) - } else { - created = time.Unix(entry.Created, 0).Format(time.RFC3339) - size = strconv.FormatInt(entry.Size, 10) - } - - fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", imageID, created, createdBy, size, entry.Comment) - } - w.Flush() - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/images.go b/vendor/github.com/docker/docker/api/client/images.go deleted file mode 100644 index ed001de7..00000000 --- a/vendor/github.com/docker/docker/api/client/images.go +++ /dev/null @@ -1,130 +0,0 @@ -package client - -import ( - "encoding/json" - "fmt" - "net/url" - "text/tabwriter" - "time" - - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - "github.com/docker/docker/opts" - 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/stringid" - "github.com/docker/docker/pkg/units" - "github.com/docker/docker/utils" -) - -// CmdImages lists the images in a specified repository, or all top-level images if no repository is specified. -// -// Usage: docker images [OPTIONS] [REPOSITORY] -func (cli *DockerCli) CmdImages(args ...string) error { - cmd := Cli.Subcmd("images", []string{"[REPOSITORY[:TAG]]"}, Cli.DockerCommands["images"].Description, true) - quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only show numeric IDs") - all := cmd.Bool([]string{"a", "-all"}, false, "Show all images (default hides intermediate images)") - noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output") - showDigests := cmd.Bool([]string{"-digests"}, false, "Show digests") - - flFilter := opts.NewListOpts(nil) - cmd.Var(&flFilter, []string{"f", "-filter"}, "Filter output based on conditions provided") - cmd.Require(flag.Max, 1) - - cmd.ParseFlags(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) - 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") - } - - serverResp, err := cli.call("GET", "/images/json?"+v.Encode(), nil, nil) - if err != nil { - return err - } - - defer serverResp.body.Close() - - images := []types.Image{} - if err := json.NewDecoder(serverResp.body).Decode(&images); err != nil { - return err - } - - w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) - if !*quiet { - if *showDigests { - fmt.Fprintln(w, "REPOSITORY\tTAG\tDIGEST\tIMAGE ID\tCREATED\tVIRTUAL SIZE") - } else { - fmt.Fprintln(w, "REPOSITORY\tTAG\tIMAGE ID\tCREATED\tVIRTUAL SIZE") - } - } - - for _, image := range images { - ID := image.ID - if !*noTrunc { - ID = stringid.TruncateID(ID) - } - - repoTags := image.RepoTags - repoDigests := image.RepoDigests - - if len(repoTags) == 1 && repoTags[0] == ":" && len(repoDigests) == 1 && repoDigests[0] == "@" { - // dangling image - clear out either repoTags or repoDigsts so we only show it once below - repoDigests = []string{} - } - - // combine the tags and digests lists - tagsAndDigests := append(repoTags, repoDigests...) - for _, repoAndRef := range tagsAndDigests { - repo, ref := parsers.ParseRepositoryTag(repoAndRef) - // default tag and digest to none - if there's a value, it'll be set below - tag := "" - digest := "" - if utils.DigestReference(ref) { - digest = ref - } else { - tag = ref - } - - if !*quiet { - if *showDigests { - fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\n", repo, tag, digest, ID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(int64(image.Created), 0))), units.HumanSize(float64(image.VirtualSize))) - } else { - fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\n", repo, tag, ID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(int64(image.Created), 0))), units.HumanSize(float64(image.VirtualSize))) - } - } else { - fmt.Fprintln(w, ID) - } - } - } - - if !*quiet { - w.Flush() - } - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/import.go b/vendor/github.com/docker/docker/api/client/import.go deleted file mode 100644 index c64e88d3..00000000 --- a/vendor/github.com/docker/docker/api/client/import.go +++ /dev/null @@ -1,79 +0,0 @@ -package client - -import ( - "fmt" - "io" - "net/url" - "os" - - Cli "github.com/docker/docker/cli" - "github.com/docker/docker/opts" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/parsers" - "github.com/docker/docker/pkg/urlutil" - "github.com/docker/docker/registry" -) - -// CmdImport creates an empty filesystem image, imports the contents of the tarball into the image, and optionally tags the image. -// -// The URL argument is the address of a tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) file or a path to local file relative to docker client. If the URL is '-', then the tar file is read from STDIN. -// -// Usage: docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]] -func (cli *DockerCli) CmdImport(args ...string) error { - cmd := Cli.Subcmd("import", []string{"file|URL|- [REPOSITORY[:TAG]]"}, Cli.DockerCommands["import"].Description, true) - flChanges := opts.NewListOpts(nil) - cmd.Var(&flChanges, []string{"c", "-change"}, "Apply Dockerfile instruction to the created image") - message := cmd.String([]string{"m", "-message"}, "", "Set commit message for imported image") - cmd.Require(flag.Min, 1) - - cmd.ParseFlags(args, true) - - var ( - v = url.Values{} - src = cmd.Arg(0) - repository = cmd.Arg(1) - ) - - v.Set("fromSrc", src) - v.Set("repo", repository) - v.Set("message", *message) - for _, change := range flChanges.GetAll() { - v.Add("changes", change) - } - if cmd.NArg() == 3 { - fmt.Fprintf(cli.err, "[DEPRECATED] The format 'file|URL|- [REPOSITORY [TAG]]' has been deprecated. Please use file|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 - } else if !urlutil.IsURL(src) { - v.Set("fromSrc", "-") - file, err := os.Open(src) - if err != nil { - return err - } - defer file.Close() - in = file - - } - - sopts := &streamOpts{ - rawTerminal: true, - in: in, - out: cli.out, - } - - _, err := cli.stream("POST", "/images/create?"+v.Encode(), sopts) - return err -} diff --git a/vendor/github.com/docker/docker/api/client/info.go b/vendor/github.com/docker/docker/api/client/info.go deleted file mode 100644 index ebed2452..00000000 --- a/vendor/github.com/docker/docker/api/client/info.go +++ /dev/null @@ -1,114 +0,0 @@ -package client - -import ( - "encoding/json" - "fmt" - - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - "github.com/docker/docker/pkg/httputils" - "github.com/docker/docker/pkg/ioutils" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/units" -) - -// CmdInfo displays system-wide information. -// -// Usage: docker info -func (cli *DockerCli) CmdInfo(args ...string) error { - cmd := Cli.Subcmd("info", nil, Cli.DockerCommands["info"].Description, true) - cmd.Require(flag.Exact, 0) - - cmd.ParseFlags(args, true) - - serverResp, err := cli.call("GET", "/info", nil, nil) - if err != nil { - return err - } - - defer serverResp.body.Close() - - info := &types.Info{} - if err := json.NewDecoder(serverResp.body).Decode(info); err != nil { - return fmt.Errorf("Error reading remote info: %v", err) - } - - fmt.Fprintf(cli.out, "Containers: %d\n", info.Containers) - fmt.Fprintf(cli.out, "Images: %d\n", info.Images) - ioutils.FprintfIfNotEmpty(cli.out, "Server Version: %s\n", info.ServerVersion) - ioutils.FprintfIfNotEmpty(cli.out, "Storage Driver: %s\n", info.Driver) - if info.DriverStatus != nil { - for _, pair := range info.DriverStatus { - fmt.Fprintf(cli.out, " %s: %s\n", pair[0], pair[1]) - } - } - ioutils.FprintfIfNotEmpty(cli.out, "Execution Driver: %s\n", info.ExecutionDriver) - ioutils.FprintfIfNotEmpty(cli.out, "Logging Driver: %s\n", info.LoggingDriver) - ioutils.FprintfIfNotEmpty(cli.out, "Kernel Version: %s\n", info.KernelVersion) - ioutils.FprintfIfNotEmpty(cli.out, "Operating System: %s\n", info.OperatingSystem) - fmt.Fprintf(cli.out, "CPUs: %d\n", info.NCPU) - fmt.Fprintf(cli.out, "Total Memory: %s\n", units.BytesSize(float64(info.MemTotal))) - ioutils.FprintfIfNotEmpty(cli.out, "Name: %s\n", info.Name) - ioutils.FprintfIfNotEmpty(cli.out, "ID: %s\n", info.ID) - - if info.Debug { - fmt.Fprintf(cli.out, "Debug mode (server): %v\n", info.Debug) - fmt.Fprintf(cli.out, " File Descriptors: %d\n", info.NFd) - fmt.Fprintf(cli.out, " Goroutines: %d\n", info.NGoroutines) - fmt.Fprintf(cli.out, " System Time: %s\n", info.SystemTime) - fmt.Fprintf(cli.out, " EventsListeners: %d\n", info.NEventsListener) - fmt.Fprintf(cli.out, " Init SHA1: %s\n", info.InitSha1) - fmt.Fprintf(cli.out, " Init Path: %s\n", info.InitPath) - fmt.Fprintf(cli.out, " Docker Root Dir: %s\n", info.DockerRootDir) - } - - ioutils.FprintfIfNotEmpty(cli.out, "Http Proxy: %s\n", info.HTTPProxy) - ioutils.FprintfIfNotEmpty(cli.out, "Https Proxy: %s\n", info.HTTPSProxy) - ioutils.FprintfIfNotEmpty(cli.out, "No Proxy: %s\n", info.NoProxy) - - if info.IndexServerAddress != "" { - u := cli.configFile.AuthConfigs[info.IndexServerAddress].Username - if len(u) > 0 { - fmt.Fprintf(cli.out, "Username: %v\n", u) - fmt.Fprintf(cli.out, "Registry: %v\n", info.IndexServerAddress) - } - } - - // Only output these warnings if the server does not support these features - if h, err := httputils.ParseServerHeader(serverResp.header.Get("Server")); err == nil { - if h.OS != "windows" { - if !info.MemoryLimit { - fmt.Fprintf(cli.err, "WARNING: No memory limit support\n") - } - if !info.SwapLimit { - fmt.Fprintf(cli.err, "WARNING: No swap limit support\n") - } - if !info.IPv4Forwarding { - fmt.Fprintf(cli.err, "WARNING: IPv4 forwarding is disabled\n") - } - if !info.BridgeNfIptables { - fmt.Fprintf(cli.err, "WARNING: bridge-nf-call-iptables is disabled\n") - } - if !info.BridgeNfIP6tables { - fmt.Fprintf(cli.err, "WARNING: bridge-nf-call-ip6tables is disabled\n") - } - } - } - - if info.Labels != nil { - fmt.Fprintln(cli.out, "Labels:") - for _, attribute := range info.Labels { - fmt.Fprintf(cli.out, " %s\n", attribute) - } - } - - ioutils.FprintfIfTrue(cli.out, "Experimental: %v\n", info.ExperimentalBuild) - if info.ClusterStore != "" { - fmt.Fprintf(cli.out, "Cluster store: %s\n", info.ClusterStore) - } - - if info.ClusterAdvertise != "" { - fmt.Fprintf(cli.out, "Cluster advertise: %s\n", info.ClusterAdvertise) - } - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/inspect.go b/vendor/github.com/docker/docker/api/client/inspect.go deleted file mode 100644 index 37a3bd40..00000000 --- a/vendor/github.com/docker/docker/api/client/inspect.go +++ /dev/null @@ -1,203 +0,0 @@ -package client - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "net/url" - "strings" - "text/template" - - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" -) - -var funcMap = template.FuncMap{ - "json": func(v interface{}) string { - a, _ := json.Marshal(v) - return string(a) - }, -} - -// CmdInspect displays low-level information on one or more containers or images. -// -// Usage: docker inspect [OPTIONS] CONTAINER|IMAGE [CONTAINER|IMAGE...] -func (cli *DockerCli) CmdInspect(args ...string) error { - cmd := Cli.Subcmd("inspect", []string{"CONTAINER|IMAGE [CONTAINER|IMAGE...]"}, Cli.DockerCommands["inspect"].Description, true) - tmplStr := cmd.String([]string{"f", "#format", "-format"}, "", "Format the output using the given go template") - inspectType := cmd.String([]string{"-type"}, "", "Return JSON for specified type, (e.g image or container)") - size := cmd.Bool([]string{"s", "-size"}, false, "Display total file sizes if the type is container") - cmd.Require(flag.Min, 1) - - cmd.ParseFlags(args, true) - - var tmpl *template.Template - var err error - var obj []byte - - if *tmplStr != "" { - if tmpl, err = template.New("").Funcs(funcMap).Parse(*tmplStr); err != nil { - return Cli.StatusError{StatusCode: 64, - Status: "Template parsing error: " + err.Error()} - } - } - - if *inspectType != "" && *inspectType != "container" && *inspectType != "image" { - return fmt.Errorf("%q is not a valid value for --type", *inspectType) - } - - indented := new(bytes.Buffer) - indented.WriteString("[\n") - status := 0 - isImage := false - - v := url.Values{} - if *size { - v.Set("size", "1") - } - - for _, name := range cmd.Args() { - if *inspectType == "" || *inspectType == "container" { - obj, _, err = readBody(cli.call("GET", "/containers/"+name+"/json?"+v.Encode(), nil, nil)) - if err != nil { - if err == errConnectionFailed { - return err - } - if *inspectType == "container" { - if strings.Contains(err.Error(), "No such") { - fmt.Fprintf(cli.err, "Error: No such container: %s\n", name) - } else { - fmt.Fprintf(cli.err, "%s", err) - } - status = 1 - continue - } - } - } - - if obj == nil && (*inspectType == "" || *inspectType == "image") { - obj, _, err = readBody(cli.call("GET", "/images/"+name+"/json", nil, nil)) - isImage = true - if err != nil { - if err == errConnectionFailed { - return err - } - if strings.Contains(err.Error(), "No such") { - if *inspectType == "" { - fmt.Fprintf(cli.err, "Error: No such image or container: %s\n", name) - } else { - fmt.Fprintf(cli.err, "Error: No such image: %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 { - rdr := bytes.NewReader(obj) - dec := json.NewDecoder(rdr) - buf := bytes.NewBufferString("") - - if isImage { - inspPtr := types.ImageInspect{} - if err := dec.Decode(&inspPtr); err != nil { - fmt.Fprintf(cli.err, "Unable to read inspect data: %v\n", err) - status = 1 - break - } - if err := tmpl.Execute(buf, inspPtr); err != nil { - rdr.Seek(0, 0) - var ok bool - - if buf, ok = cli.decodeRawInspect(tmpl, dec); !ok { - fmt.Fprintf(cli.err, "Template parsing error: %v\n", err) - status = 1 - break - } - } - } else { - inspPtr := types.ContainerJSON{} - if err := dec.Decode(&inspPtr); err != nil { - fmt.Fprintf(cli.err, "Unable to read inspect data: %v\n", err) - status = 1 - break - } - if err := tmpl.Execute(buf, inspPtr); err != nil { - rdr.Seek(0, 0) - var ok bool - - if buf, ok = cli.decodeRawInspect(tmpl, dec); !ok { - fmt.Fprintf(cli.err, "Template parsing error: %v\n", err) - status = 1 - break - } - } - } - - cli.out.Write(buf.Bytes()) - cli.out.Write([]byte{'\n'}) - } - indented.WriteString(",") - } - - if indented.Len() > 1 { - // Remove trailing ',' - indented.Truncate(indented.Len() - 1) - } - indented.WriteString("]\n") - - if tmpl == nil { - // Note that we will always write "[]" when "-f" isn't specified, - // to make sure the output would always be array, see - // https://github.com/docker/docker/pull/9500#issuecomment-65846734 - if _, err := io.Copy(cli.out, indented); err != nil { - return err - } - } - - if status != 0 { - return Cli.StatusError{StatusCode: status} - } - return nil -} - -// decodeRawInspect executes the inspect template with a raw interface. -// This allows docker cli to parse inspect structs injected with Swarm fields. -// Unfortunately, go 1.4 doesn't fail executing invalid templates when the input is an interface. -// It doesn't allow to modify this behavior either, sending messages to the output. -// We assume that the template is invalid when there is a , if the template was valid -// we'd get or "" values. In that case we fail with the original error raised executing the -// template with the typed input. -// -// TODO: Go 1.5 allows to customize the error behavior, we can probably get rid of this as soon as -// we build Docker with that version: -// https://golang.org/pkg/text/template/#Template.Option -func (cli *DockerCli) decodeRawInspect(tmpl *template.Template, dec *json.Decoder) (*bytes.Buffer, bool) { - var raw interface{} - buf := bytes.NewBufferString("") - - if rawErr := dec.Decode(&raw); rawErr != nil { - fmt.Fprintf(cli.err, "Unable to read inspect data: %v\n", rawErr) - return buf, false - } - - if rawErr := tmpl.Execute(buf, raw); rawErr != nil { - return buf, false - } - - if strings.Contains(buf.String(), "") { - return buf, false - } - return buf, true -} diff --git a/vendor/github.com/docker/docker/api/client/kill.go b/vendor/github.com/docker/docker/api/client/kill.go deleted file mode 100644 index c4c355c7..00000000 --- a/vendor/github.com/docker/docker/api/client/kill.go +++ /dev/null @@ -1,33 +0,0 @@ -package client - -import ( - "fmt" - - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" -) - -// CmdKill kills one or more running container using SIGKILL or a specified signal. -// -// Usage: docker kill [OPTIONS] CONTAINER [CONTAINER...] -func (cli *DockerCli) CmdKill(args ...string) error { - cmd := Cli.Subcmd("kill", []string{"CONTAINER [CONTAINER...]"}, Cli.DockerCommands["kill"].Description, true) - signal := cmd.String([]string{"s", "-signal"}, "KILL", "Signal to send to the container") - cmd.Require(flag.Min, 1) - - cmd.ParseFlags(args, true) - - var errNames []string - for _, name := range cmd.Args() { - if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%s", name, *signal), nil, nil)); err != nil { - fmt.Fprintf(cli.err, "%s\n", err) - errNames = append(errNames, name) - } else { - fmt.Fprintf(cli.out, "%s\n", name) - } - } - if len(errNames) > 0 { - return fmt.Errorf("Error: failed to kill containers: %v", errNames) - } - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/load.go b/vendor/github.com/docker/docker/api/client/load.go deleted file mode 100644 index 378170e1..00000000 --- a/vendor/github.com/docker/docker/api/client/load.go +++ /dev/null @@ -1,42 +0,0 @@ -package client - -import ( - "io" - "os" - - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" -) - -// CmdLoad loads an image from a tar archive. -// -// The tar archive is read from STDIN by default, or from a tar archive file. -// -// Usage: docker load [OPTIONS] -func (cli *DockerCli) CmdLoad(args ...string) error { - cmd := Cli.Subcmd("load", nil, Cli.DockerCommands["load"].Description, true) - infile := cmd.String([]string{"i", "-input"}, "", "Read from a tar archive file, instead of STDIN") - cmd.Require(flag.Exact, 0) - - cmd.ParseFlags(args, true) - - var ( - input io.Reader = cli.in - err error - ) - if *infile != "" { - input, err = os.Open(*infile) - if err != nil { - return err - } - } - sopts := &streamOpts{ - rawTerminal: true, - in: input, - out: cli.out, - } - if _, err := cli.stream("POST", "/images/load", sopts); err != nil { - return err - } - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/login.go b/vendor/github.com/docker/docker/api/client/login.go deleted file mode 100644 index e941a14e..00000000 --- a/vendor/github.com/docker/docker/api/client/login.go +++ /dev/null @@ -1,153 +0,0 @@ -package client - -import ( - "bufio" - "encoding/json" - "fmt" - "io" - "os" - "runtime" - "strings" - - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - "github.com/docker/docker/cliconfig" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/term" - "github.com/docker/docker/registry" -) - -// CmdLogin logs in or registers a user to a Docker registry service. -// -// If no server is specified, the user will be logged into or registered to the registry's index server. -// -// Usage: docker login SERVER -func (cli *DockerCli) CmdLogin(args ...string) error { - cmd := Cli.Subcmd("login", []string{"[SERVER]"}, Cli.DockerCommands["login"].Description+".\nIf no server is specified \""+registry.IndexServer+"\" 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") - - cmd.ParseFlags(args, true) - - // On Windows, force the use of the regular OS stdin stream. Fixes #14336/#14210 - if runtime.GOOS == "windows" { - cli.in = os.Stdin - } - - serverAddress := registry.IndexServer - 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) - } - - authconfig, ok := cli.configFile.AuthConfigs[serverAddress] - if !ok { - authconfig = cliconfig.AuthConfig{} - } - - if username == "" { - promptDefault("Username", authconfig.Username) - username = readInput(cli.in, cli.out) - username = strings.TrimSpace(username) - 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/override 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.AuthConfigs[serverAddress] = authconfig - - serverResp, err := cli.call("POST", "/auth", cli.configFile.AuthConfigs[serverAddress], nil) - if serverResp.statusCode == 401 { - delete(cli.configFile.AuthConfigs, serverAddress) - if err2 := cli.configFile.Save(); err2 != nil { - fmt.Fprintf(cli.out, "WARNING: could not save config file: %v\n", err2) - } - return err - } - if err != nil { - return err - } - - defer serverResp.body.Close() - - var response types.AuthResponse - if err := json.NewDecoder(serverResp.body).Decode(&response); err != nil { - // Upon error, remove entry - delete(cli.configFile.AuthConfigs, serverAddress) - return err - } - - if err := cli.configFile.Save(); err != nil { - return fmt.Errorf("Error saving config file: %v", err) - } - fmt.Fprintf(cli.out, "WARNING: login credentials saved in %s\n", cli.configFile.Filename()) - - if response.Status != "" { - fmt.Fprintf(cli.out, "%s\n", response.Status) - } - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/logout.go b/vendor/github.com/docker/docker/api/client/logout.go deleted file mode 100644 index 3753cbbe..00000000 --- a/vendor/github.com/docker/docker/api/client/logout.go +++ /dev/null @@ -1,39 +0,0 @@ -package client - -import ( - "fmt" - - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/registry" -) - -// CmdLogout logs a user out from a Docker registry. -// -// If no server is specified, the user will be logged out from the registry's index server. -// -// Usage: docker logout [SERVER] -func (cli *DockerCli) CmdLogout(args ...string) error { - cmd := Cli.Subcmd("logout", []string{"[SERVER]"}, Cli.DockerCommands["logout"].Description+".\nIf no server is specified \""+registry.IndexServer+"\" is the default.", true) - cmd.Require(flag.Max, 1) - - cmd.ParseFlags(args, true) - - serverAddress := registry.IndexServer - if len(cmd.Args()) > 0 { - serverAddress = cmd.Arg(0) - } - - if _, ok := cli.configFile.AuthConfigs[serverAddress]; !ok { - fmt.Fprintf(cli.out, "Not logged in to %s\n", serverAddress) - return nil - } - - fmt.Fprintf(cli.out, "Remove login credentials for %s\n", serverAddress) - delete(cli.configFile.AuthConfigs, serverAddress) - if err := cli.configFile.Save(); err != nil { - return fmt.Errorf("Failed to save docker config: %v", err) - } - - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/logs.go b/vendor/github.com/docker/docker/api/client/logs.go deleted file mode 100644 index 6de7b133..00000000 --- a/vendor/github.com/docker/docker/api/client/logs.go +++ /dev/null @@ -1,74 +0,0 @@ -package client - -import ( - "encoding/json" - "fmt" - "net/url" - "time" - - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/timeutils" -) - -var validDrivers = map[string]bool{ - "json-file": true, - "journald": true, -} - -// CmdLogs fetches the logs of a given container. -// -// docker logs [OPTIONS] CONTAINER -func (cli *DockerCli) CmdLogs(args ...string) error { - cmd := Cli.Subcmd("logs", []string{"CONTAINER"}, Cli.DockerCommands["logs"].Description, true) - follow := cmd.Bool([]string{"f", "-follow"}, false, "Follow log output") - since := cmd.String([]string{"-since"}, "", "Show logs since timestamp") - times := cmd.Bool([]string{"t", "-timestamps"}, false, "Show timestamps") - tail := cmd.String([]string{"-tail"}, "all", "Number of lines to show from the end of the logs") - cmd.Require(flag.Exact, 1) - - cmd.ParseFlags(args, true) - - name := cmd.Arg(0) - - serverResp, err := cli.call("GET", "/containers/"+name+"/json", nil, nil) - if err != nil { - return err - } - - var c types.ContainerJSON - if err := json.NewDecoder(serverResp.body).Decode(&c); err != nil { - return err - } - - if !validDrivers[c.HostConfig.LogConfig.Type] { - return fmt.Errorf("\"logs\" command is supported only for \"json-file\" and \"journald\" logging drivers (got: %s)", c.HostConfig.LogConfig.Type) - } - - v := url.Values{} - v.Set("stdout", "1") - v.Set("stderr", "1") - - if *since != "" { - v.Set("since", timeutils.GetTimestamp(*since, time.Now())) - } - - if *times { - v.Set("timestamps", "1") - } - - if *follow { - v.Set("follow", "1") - } - v.Set("tail", *tail) - - sopts := &streamOpts{ - rawTerminal: c.Config.Tty, - out: cli.out, - err: cli.err, - } - - _, err = cli.stream("GET", "/containers/"+name+"/logs?"+v.Encode(), sopts) - return err -} diff --git a/vendor/github.com/docker/docker/api/client/network.go b/vendor/github.com/docker/docker/api/client/network.go deleted file mode 100644 index 62ee46e1..00000000 --- a/vendor/github.com/docker/docker/api/client/network.go +++ /dev/null @@ -1,381 +0,0 @@ -package client - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "net" - "strings" - "text/tabwriter" - - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - "github.com/docker/docker/daemon/network" - "github.com/docker/docker/opts" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/stringid" -) - -// CmdNetwork is the parent subcommand for all network commands -// -// Usage: docker network [OPTIONS] -func (cli *DockerCli) CmdNetwork(args ...string) error { - cmd := Cli.Subcmd("network", []string{"COMMAND [OPTIONS]"}, networkUsage(), false) - cmd.Require(flag.Min, 1) - err := cmd.ParseFlags(args, true) - cmd.Usage() - return err -} - -// CmdNetworkCreate creates a new network with a given name -// -// Usage: docker network create [OPTIONS] -func (cli *DockerCli) CmdNetworkCreate(args ...string) error { - cmd := Cli.Subcmd("network create", []string{"NETWORK-NAME"}, "Creates a new network with a name specified by the user", false) - flDriver := cmd.String([]string{"d", "-driver"}, "bridge", "Driver to manage the Network") - flOpts := opts.NewMapOpts(nil, nil) - - flIpamDriver := cmd.String([]string{"-ipam-driver"}, "default", "IP Address Management Driver") - flIpamSubnet := opts.NewListOpts(nil) - flIpamIPRange := opts.NewListOpts(nil) - flIpamGateway := opts.NewListOpts(nil) - flIpamAux := opts.NewMapOpts(nil, nil) - - cmd.Var(&flIpamSubnet, []string{"-subnet"}, "subnet in CIDR format that represents a network segment") - cmd.Var(&flIpamIPRange, []string{"-ip-range"}, "allocate container ip from a sub-range") - cmd.Var(&flIpamGateway, []string{"-gateway"}, "ipv4 or ipv6 Gateway for the master subnet") - cmd.Var(flIpamAux, []string{"-aux-address"}, "auxiliary ipv4 or ipv6 addresses used by Network driver") - cmd.Var(flOpts, []string{"o", "-opt"}, "set driver specific options") - - cmd.Require(flag.Exact, 1) - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - - // Set the default driver to "" if the user didn't set the value. - // That way we can know whether it was user input or not. - driver := *flDriver - if !cmd.IsSet("-driver") && !cmd.IsSet("d") { - driver = "" - } - - ipamCfg, err := consolidateIpam(flIpamSubnet.GetAll(), flIpamIPRange.GetAll(), flIpamGateway.GetAll(), flIpamAux.GetAll()) - if err != nil { - return err - } - - // Construct network create request body - nc := types.NetworkCreate{ - Name: cmd.Arg(0), - Driver: driver, - IPAM: network.IPAM{Driver: *flIpamDriver, Config: ipamCfg}, - Options: flOpts.GetAll(), - CheckDuplicate: true, - } - obj, _, err := readBody(cli.call("POST", "/networks/create", nc, nil)) - if err != nil { - return err - } - var resp types.NetworkCreateResponse - err = json.Unmarshal(obj, &resp) - if err != nil { - return err - } - fmt.Fprintf(cli.out, "%s\n", resp.ID) - return nil -} - -// CmdNetworkRm deletes a network -// -// Usage: docker network rm -func (cli *DockerCli) CmdNetworkRm(args ...string) error { - cmd := Cli.Subcmd("network rm", []string{"NETWORK"}, "Deletes a network", false) - cmd.Require(flag.Exact, 1) - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - _, _, err = readBody(cli.call("DELETE", "/networks/"+cmd.Arg(0), nil, nil)) - if err != nil { - return err - } - return nil -} - -// CmdNetworkConnect connects a container to a network -// -// Usage: docker network connect -func (cli *DockerCli) CmdNetworkConnect(args ...string) error { - cmd := Cli.Subcmd("network connect", []string{"NETWORK CONTAINER"}, "Connects a container to a network", false) - cmd.Require(flag.Exact, 2) - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - - nc := types.NetworkConnect{Container: cmd.Arg(1)} - _, _, err = readBody(cli.call("POST", "/networks/"+cmd.Arg(0)+"/connect", nc, nil)) - return err -} - -// CmdNetworkDisconnect disconnects a container from a network -// -// Usage: docker network disconnect -func (cli *DockerCli) CmdNetworkDisconnect(args ...string) error { - cmd := Cli.Subcmd("network disconnect", []string{"NETWORK CONTAINER"}, "Disconnects container from a network", false) - cmd.Require(flag.Exact, 2) - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - - nc := types.NetworkConnect{Container: cmd.Arg(1)} - _, _, err = readBody(cli.call("POST", "/networks/"+cmd.Arg(0)+"/disconnect", nc, nil)) - return err -} - -// CmdNetworkLs lists all the netorks managed by docker daemon -// -// Usage: docker network ls [OPTIONS] -func (cli *DockerCli) CmdNetworkLs(args ...string) error { - cmd := Cli.Subcmd("network ls", nil, "Lists networks", true) - quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only display numeric IDs") - noTrunc := cmd.Bool([]string{"-no-trunc"}, false, "Do not truncate the output") - - cmd.Require(flag.Exact, 0) - err := cmd.ParseFlags(args, true) - - if err != nil { - return err - } - obj, _, err := readBody(cli.call("GET", "/networks", nil, nil)) - if err != nil { - return err - } - - var networkResources []types.NetworkResource - err = json.Unmarshal(obj, &networkResources) - if err != nil { - return err - } - - wr := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) - - // unless quiet (-q) is specified, print field titles - if !*quiet { - fmt.Fprintln(wr, "NETWORK ID\tNAME\tDRIVER") - } - - for _, networkResource := range networkResources { - ID := networkResource.ID - netName := networkResource.Name - if !*noTrunc { - ID = stringid.TruncateID(ID) - } - if *quiet { - fmt.Fprintln(wr, ID) - continue - } - driver := networkResource.Driver - fmt.Fprintf(wr, "%s\t%s\t%s\t", - ID, - netName, - driver) - fmt.Fprint(wr, "\n") - } - wr.Flush() - return nil -} - -// CmdNetworkInspect inspects the network object for more details -// -// Usage: docker network inspect [OPTIONS] [NETWORK...] -func (cli *DockerCli) CmdNetworkInspect(args ...string) error { - cmd := Cli.Subcmd("network inspect", []string{"NETWORK [NETWORK...]"}, "Displays detailed information on a network", false) - cmd.Require(flag.Min, 1) - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - - status := 0 - var networks []*types.NetworkResource - for _, name := range cmd.Args() { - obj, _, err := readBody(cli.call("GET", "/networks/"+name, nil, nil)) - if err != nil { - if strings.Contains(err.Error(), "not found") { - fmt.Fprintf(cli.err, "Error: No such network: %s\n", name) - } else { - fmt.Fprintf(cli.err, "%s", err) - } - status = 1 - continue - } - networkResource := types.NetworkResource{} - if err := json.NewDecoder(bytes.NewReader(obj)).Decode(&networkResource); err != nil { - return err - } - - networks = append(networks, &networkResource) - } - - b, err := json.MarshalIndent(networks, "", " ") - if err != nil { - return err - } - - if _, err := io.Copy(cli.out, bytes.NewReader(b)); err != nil { - return err - } - io.WriteString(cli.out, "\n") - - if status != 0 { - return Cli.StatusError{StatusCode: status} - } - return nil -} - -// Consolidates the ipam configuration as a group from different related configurations -// user can configure network with multiple non-overlapping subnets and hence it is -// possible to corelate the various related parameters and consolidate them. -// consoidateIpam consolidates subnets, ip-ranges, gateways and auxilary addresses into -// structured ipam data. -func consolidateIpam(subnets, ranges, gateways []string, auxaddrs map[string]string) ([]network.IPAMConfig, error) { - if len(subnets) < len(ranges) || len(subnets) < len(gateways) { - return nil, fmt.Errorf("every ip-range or gateway must have a corresponding subnet") - } - iData := map[string]*network.IPAMConfig{} - - // Populate non-overlapping subnets into consolidation map - for _, s := range subnets { - for k := range iData { - ok1, err := subnetMatches(s, k) - if err != nil { - return nil, err - } - ok2, err := subnetMatches(k, s) - if err != nil { - return nil, err - } - if ok1 || ok2 { - return nil, fmt.Errorf("multiple overlapping subnet configuration is not supported") - } - } - iData[s] = &network.IPAMConfig{Subnet: s, AuxAddress: map[string]string{}} - } - - // Validate and add valid ip ranges - for _, r := range ranges { - match := false - for _, s := range subnets { - ok, err := subnetMatches(s, r) - if err != nil { - return nil, err - } - if !ok { - continue - } - if iData[s].IPRange != "" { - return nil, fmt.Errorf("cannot configure multiple ranges (%s, %s) on the same subnet (%s)", r, iData[s].IPRange, s) - } - d := iData[s] - d.IPRange = r - match = true - } - if !match { - return nil, fmt.Errorf("no matching subnet for range %s", r) - } - } - - // Validate and add valid gateways - for _, g := range gateways { - match := false - for _, s := range subnets { - ok, err := subnetMatches(s, g) - if err != nil { - return nil, err - } - if !ok { - continue - } - if iData[s].Gateway != "" { - return nil, fmt.Errorf("cannot configure multiple gateways (%s, %s) for the same subnet (%s)", g, iData[s].Gateway, s) - } - d := iData[s] - d.Gateway = g - match = true - } - if !match { - return nil, fmt.Errorf("no matching subnet for gateway %s", g) - } - } - - // Validate and add aux-addresses - for key, aa := range auxaddrs { - match := false - for _, s := range subnets { - ok, err := subnetMatches(s, aa) - if err != nil { - return nil, err - } - if !ok { - continue - } - iData[s].AuxAddress[key] = aa - match = true - } - if !match { - return nil, fmt.Errorf("no matching subnet for aux-address %s", aa) - } - } - - idl := []network.IPAMConfig{} - for _, v := range iData { - idl = append(idl, *v) - } - return idl, nil -} - -func subnetMatches(subnet, data string) (bool, error) { - var ( - ip net.IP - ) - - _, s, err := net.ParseCIDR(subnet) - if err != nil { - return false, fmt.Errorf("Invalid subnet %s : %v", s, err) - } - - if strings.Contains(data, "/") { - ip, _, err = net.ParseCIDR(data) - if err != nil { - return false, fmt.Errorf("Invalid cidr %s : %v", data, err) - } - } else { - ip = net.ParseIP(data) - } - - return s.Contains(ip), nil -} - -func networkUsage() string { - networkCommands := map[string]string{ - "create": "Create a network", - "connect": "Connect container to a network", - "disconnect": "Disconnect container from a network", - "inspect": "Display detailed network information", - "ls": "List all networks", - "rm": "Remove a network", - } - - help := "Commands:\n" - - for cmd, description := range networkCommands { - help += fmt.Sprintf(" %-25.25s%s\n", cmd, description) - } - - help += fmt.Sprintf("\nRun 'docker network COMMAND --help' for more information on a command.") - return help -} diff --git a/vendor/github.com/docker/docker/api/client/pause.go b/vendor/github.com/docker/docker/api/client/pause.go deleted file mode 100644 index e144a0bd..00000000 --- a/vendor/github.com/docker/docker/api/client/pause.go +++ /dev/null @@ -1,32 +0,0 @@ -package client - -import ( - "fmt" - - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" -) - -// CmdPause pauses all processes within one or more containers. -// -// Usage: docker pause CONTAINER [CONTAINER...] -func (cli *DockerCli) CmdPause(args ...string) error { - cmd := Cli.Subcmd("pause", []string{"CONTAINER [CONTAINER...]"}, Cli.DockerCommands["pause"].Description, true) - cmd.Require(flag.Min, 1) - - cmd.ParseFlags(args, true) - - var errNames []string - for _, name := range cmd.Args() { - if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/pause", name), nil, nil)); err != nil { - fmt.Fprintf(cli.err, "%s\n", err) - errNames = append(errNames, name) - } else { - fmt.Fprintf(cli.out, "%s\n", name) - } - } - if len(errNames) > 0 { - return fmt.Errorf("Error: failed to pause containers: %v", errNames) - } - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/port.go b/vendor/github.com/docker/docker/api/client/port.go deleted file mode 100644 index a981bc5e..00000000 --- a/vendor/github.com/docker/docker/api/client/port.go +++ /dev/null @@ -1,72 +0,0 @@ -package client - -import ( - "encoding/json" - "fmt" - "strings" - - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/nat" -) - -// CmdPort lists port mappings for a container. -// If a private port is specified, it also shows the public-facing port that is NATed to the private port. -// -// Usage: docker port CONTAINER [PRIVATE_PORT[/PROTO]] -func (cli *DockerCli) CmdPort(args ...string) error { - cmd := Cli.Subcmd("port", []string{"CONTAINER [PRIVATE_PORT[/PROTO]]"}, Cli.DockerCommands["port"].Description, true) - cmd.Require(flag.Min, 1) - - cmd.ParseFlags(args, true) - - serverResp, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/json", nil, nil) - if err != nil { - return err - } - - defer serverResp.body.Close() - - var c struct { - NetworkSettings struct { - Ports nat.PortMap - } - } - - if err := json.NewDecoder(serverResp.body).Decode(&c); 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 - newP, err := nat.NewPort(proto, port) - if err != nil { - return err - } - if frontends, exists := c.NetworkSettings.Ports[newP]; 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 c.NetworkSettings.Ports { - for _, frontend := range frontends { - fmt.Fprintf(cli.out, "%s -> %s:%s\n", from, frontend.HostIP, frontend.HostPort) - } - } - - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/ps.go b/vendor/github.com/docker/docker/api/client/ps.go deleted file mode 100644 index 50d76fbc..00000000 --- a/vendor/github.com/docker/docker/api/client/ps.go +++ /dev/null @@ -1,116 +0,0 @@ -package client - -import ( - "encoding/json" - "net/url" - "strconv" - - "github.com/docker/docker/api/client/ps" - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - "github.com/docker/docker/opts" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/parsers/filters" -) - -// CmdPs outputs a list of Docker containers. -// -// Usage: docker ps [OPTIONS] -func (cli *DockerCli) CmdPs(args ...string) error { - var ( - err error - - psFilterArgs = filters.Args{} - v = url.Values{} - - cmd = Cli.Subcmd("ps", nil, Cli.DockerCommands["ps"].Description, 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 (default shows just running)") - noTrunc = cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output") - nLatest = cmd.Bool([]string{"l", "-latest"}, false, "Show the latest created container, include non-running") - since = cmd.String([]string{"#sinceId", "#-since-id", "-since"}, "", "Show created since Id or Name, include non-running") - before = cmd.String([]string{"#beforeId", "#-before-id", "-before"}, "", "Show only container created before Id or Name") - last = cmd.Int([]string{"n"}, -1, "Show n last created containers, include non-running") - format = cmd.String([]string{"-format"}, "", "Pretty-print containers using a Go template") - flFilter = opts.NewListOpts(nil) - ) - cmd.Require(flag.Exact, 0) - - cmd.Var(&flFilter, []string{"f", "-filter"}, "Filter output based on conditions provided") - - cmd.ParseFlags(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) - } - - serverResp, err := cli.call("GET", "/containers/json?"+v.Encode(), nil, nil) - if err != nil { - return err - } - - defer serverResp.body.Close() - - containers := []types.Container{} - if err := json.NewDecoder(serverResp.body).Decode(&containers); err != nil { - return err - } - - f := *format - if len(f) == 0 { - if len(cli.PsFormat()) > 0 && !*quiet { - f = cli.PsFormat() - } else { - f = "table" - } - } - - psCtx := ps.Context{ - Output: cli.out, - Format: f, - Quiet: *quiet, - Size: *size, - Trunc: !*noTrunc, - } - - ps.Format(psCtx, containers) - - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/ps/custom.go b/vendor/github.com/docker/docker/api/client/ps/custom.go deleted file mode 100644 index 1739fd12..00000000 --- a/vendor/github.com/docker/docker/api/client/ps/custom.go +++ /dev/null @@ -1,160 +0,0 @@ -package ps - -import ( - "fmt" - "strconv" - "strings" - "time" - - "github.com/docker/docker/api" - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/pkg/stringutils" - "github.com/docker/docker/pkg/units" -) - -const ( - tableKey = "table" - - idHeader = "CONTAINER ID" - imageHeader = "IMAGE" - namesHeader = "NAMES" - commandHeader = "COMMAND" - createdAtHeader = "CREATED AT" - runningForHeader = "CREATED" - statusHeader = "STATUS" - portsHeader = "PORTS" - sizeHeader = "SIZE" - labelsHeader = "LABELS" -) - -type containerContext struct { - trunc bool - header []string - c types.Container -} - -func (c *containerContext) ID() string { - c.addHeader(idHeader) - if c.trunc { - return stringid.TruncateID(c.c.ID) - } - return c.c.ID -} - -func (c *containerContext) Names() string { - c.addHeader(namesHeader) - names := stripNamePrefix(c.c.Names) - if c.trunc { - for _, name := range names { - if len(strings.Split(name, "/")) == 1 { - names = []string{name} - break - } - } - } - return strings.Join(names, ",") -} - -func (c *containerContext) Image() string { - c.addHeader(imageHeader) - if c.c.Image == "" { - return "" - } - if c.trunc { - if stringid.TruncateID(c.c.ImageID) == stringid.TruncateID(c.c.Image) { - return stringutils.Truncate(c.c.Image, 12) - } - } - return c.c.Image -} - -func (c *containerContext) Command() string { - c.addHeader(commandHeader) - command := c.c.Command - if c.trunc { - command = stringutils.Truncate(command, 20) - } - return strconv.Quote(command) -} - -func (c *containerContext) CreatedAt() string { - c.addHeader(createdAtHeader) - return time.Unix(int64(c.c.Created), 0).String() -} - -func (c *containerContext) RunningFor() string { - c.addHeader(runningForHeader) - createdAt := time.Unix(int64(c.c.Created), 0) - return units.HumanDuration(time.Now().UTC().Sub(createdAt)) -} - -func (c *containerContext) Ports() string { - c.addHeader(portsHeader) - return api.DisplayablePorts(c.c.Ports) -} - -func (c *containerContext) Status() string { - c.addHeader(statusHeader) - return c.c.Status -} - -func (c *containerContext) Size() string { - c.addHeader(sizeHeader) - srw := units.HumanSize(float64(c.c.SizeRw)) - sv := units.HumanSize(float64(c.c.SizeRootFs)) - - sf := srw - if c.c.SizeRootFs > 0 { - sf = fmt.Sprintf("%s (virtual %s)", srw, sv) - } - return sf -} - -func (c *containerContext) Labels() string { - c.addHeader(labelsHeader) - if c.c.Labels == nil { - return "" - } - - var joinLabels []string - for k, v := range c.c.Labels { - joinLabels = append(joinLabels, fmt.Sprintf("%s=%s", k, v)) - } - return strings.Join(joinLabels, ",") -} - -func (c *containerContext) Label(name string) string { - n := strings.Split(name, ".") - r := strings.NewReplacer("-", " ", "_", " ") - h := r.Replace(n[len(n)-1]) - - c.addHeader(h) - - if c.c.Labels == nil { - return "" - } - return c.c.Labels[name] -} - -func (c *containerContext) fullHeader() string { - if c.header == nil { - return "" - } - return strings.Join(c.header, "\t") -} - -func (c *containerContext) addHeader(header string) { - if c.header == nil { - c.header = []string{} - } - c.header = append(c.header, strings.ToUpper(header)) -} - -func stripNamePrefix(ss []string) []string { - for i, s := range ss { - ss[i] = s[1:] - } - - return ss -} diff --git a/vendor/github.com/docker/docker/api/client/ps/custom_test.go b/vendor/github.com/docker/docker/api/client/ps/custom_test.go deleted file mode 100644 index c0b2eb2e..00000000 --- a/vendor/github.com/docker/docker/api/client/ps/custom_test.go +++ /dev/null @@ -1,126 +0,0 @@ -package ps - -import ( - "reflect" - "strings" - "testing" - "time" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/stringid" -) - -func TestContainerPsContext(t *testing.T) { - containerID := stringid.GenerateRandomID() - unix := time.Now().Unix() - - var ctx containerContext - cases := []struct { - container types.Container - trunc bool - expValue string - expHeader string - call func() string - }{ - {types.Container{ID: containerID}, true, stringid.TruncateID(containerID), idHeader, ctx.ID}, - {types.Container{ID: containerID}, false, containerID, idHeader, ctx.ID}, - {types.Container{Names: []string{"/foobar_baz"}}, true, "foobar_baz", namesHeader, ctx.Names}, - {types.Container{Image: "ubuntu"}, true, "ubuntu", imageHeader, ctx.Image}, - {types.Container{Image: "verylongimagename"}, true, "verylongimagename", imageHeader, ctx.Image}, - {types.Container{Image: "verylongimagename"}, false, "verylongimagename", imageHeader, ctx.Image}, - {types.Container{ - Image: "a5a665ff33eced1e0803148700880edab4", - ImageID: "a5a665ff33eced1e0803148700880edab4269067ed77e27737a708d0d293fbf5", - }, - true, - "a5a665ff33ec", - imageHeader, - ctx.Image, - }, - {types.Container{ - Image: "a5a665ff33eced1e0803148700880edab4", - ImageID: "a5a665ff33eced1e0803148700880edab4269067ed77e27737a708d0d293fbf5", - }, - false, - "a5a665ff33eced1e0803148700880edab4", - imageHeader, - ctx.Image, - }, - {types.Container{Image: ""}, true, "", imageHeader, ctx.Image}, - {types.Container{Command: "sh -c 'ls -la'"}, true, `"sh -c 'ls -la'"`, commandHeader, ctx.Command}, - {types.Container{Created: unix}, true, time.Unix(unix, 0).String(), createdAtHeader, ctx.CreatedAt}, - {types.Container{Ports: []types.Port{{PrivatePort: 8080, PublicPort: 8080, Type: "tcp"}}}, true, "8080/tcp", portsHeader, ctx.Ports}, - {types.Container{Status: "RUNNING"}, true, "RUNNING", statusHeader, ctx.Status}, - {types.Container{SizeRw: 10}, true, "10 B", sizeHeader, ctx.Size}, - {types.Container{SizeRw: 10, SizeRootFs: 20}, true, "10 B (virtual 20 B)", sizeHeader, ctx.Size}, - {types.Container{}, true, "", labelsHeader, ctx.Labels}, - {types.Container{Labels: map[string]string{"cpu": "6", "storage": "ssd"}}, true, "cpu=6,storage=ssd", labelsHeader, ctx.Labels}, - {types.Container{Created: unix}, true, "Less than a second", runningForHeader, ctx.RunningFor}, - } - - for _, c := range cases { - ctx = containerContext{c: c.container, trunc: c.trunc} - v := c.call() - if strings.Contains(v, ",") { - // comma-separated values means probably a map input, which won't - // be guaranteed to have the same order as our expected value - // We'll create maps and use reflect.DeepEquals to check instead: - entriesMap := make(map[string]string) - expMap := make(map[string]string) - entries := strings.Split(v, ",") - expectedEntries := strings.Split(c.expValue, ",") - for _, entry := range entries { - keyval := strings.Split(entry, "=") - entriesMap[keyval[0]] = keyval[1] - } - for _, expected := range expectedEntries { - keyval := strings.Split(expected, "=") - expMap[keyval[0]] = keyval[1] - } - if !reflect.DeepEqual(expMap, entriesMap) { - t.Fatalf("Expected entries: %v, got: %v", c.expValue, v) - } - } else if v != c.expValue { - t.Fatalf("Expected %s, was %s\n", c.expValue, v) - } - - h := ctx.fullHeader() - if h != c.expHeader { - t.Fatalf("Expected %s, was %s\n", c.expHeader, h) - } - } - - c1 := types.Container{Labels: map[string]string{"com.docker.swarm.swarm-id": "33", "com.docker.swarm.node_name": "ubuntu"}} - ctx = containerContext{c: c1, trunc: true} - - sid := ctx.Label("com.docker.swarm.swarm-id") - node := ctx.Label("com.docker.swarm.node_name") - if sid != "33" { - t.Fatalf("Expected 33, was %s\n", sid) - } - - if node != "ubuntu" { - t.Fatalf("Expected ubuntu, was %s\n", node) - } - - h := ctx.fullHeader() - if h != "SWARM ID\tNODE NAME" { - t.Fatalf("Expected %s, was %s\n", "SWARM ID\tNODE NAME", h) - - } - - c2 := types.Container{} - ctx = containerContext{c: c2, trunc: true} - - label := ctx.Label("anything.really") - if label != "" { - t.Fatalf("Expected an empty string, was %s", label) - } - - ctx = containerContext{c: c2, trunc: true} - fullHeader := ctx.fullHeader() - if fullHeader != "" { - t.Fatalf("Expected fullHeader to be empty, was %s", fullHeader) - } - -} diff --git a/vendor/github.com/docker/docker/api/client/ps/formatter.go b/vendor/github.com/docker/docker/api/client/ps/formatter.go deleted file mode 100644 index 2a45bfcf..00000000 --- a/vendor/github.com/docker/docker/api/client/ps/formatter.go +++ /dev/null @@ -1,140 +0,0 @@ -package ps - -import ( - "bytes" - "fmt" - "io" - "strings" - "text/tabwriter" - "text/template" - - "github.com/docker/docker/api/types" -) - -const ( - tableFormatKey = "table" - rawFormatKey = "raw" - - defaultTableFormat = "table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.RunningFor}} ago\t{{.Status}}\t{{.Ports}}\t{{.Names}}" - defaultQuietFormat = "{{.ID}}" -) - -// Context contains information required by the formatter to print the output as desired. -type Context struct { - // Output is the output stream to which the formatted string is written. - Output io.Writer - // Format is used to choose raw, table or custom format for the output. - Format string - // Size when set to true will display the size of the output. - Size bool - // Quiet when set to true will simply print minimal information. - Quiet bool - // Trunc when set to true will truncate the output of certain fields such as Container ID. - Trunc bool -} - -// Format helps to format the output using the parameters set in the Context. -// Currently Format allow to display in raw, table or custom format the output. -func Format(ctx Context, containers []types.Container) { - switch ctx.Format { - case tableFormatKey: - tableFormat(ctx, containers) - case rawFormatKey: - rawFormat(ctx, containers) - default: - customFormat(ctx, containers) - } -} - -func rawFormat(ctx Context, containers []types.Container) { - if ctx.Quiet { - ctx.Format = `container_id: {{.ID}}` - } else { - ctx.Format = `container_id: {{.ID}} -image: {{.Image}} -command: {{.Command}} -created_at: {{.CreatedAt}} -status: {{.Status}} -names: {{.Names}} -labels: {{.Labels}} -ports: {{.Ports}} -` - if ctx.Size { - ctx.Format += `size: {{.Size}} -` - } - } - - customFormat(ctx, containers) -} - -func tableFormat(ctx Context, containers []types.Container) { - ctx.Format = defaultTableFormat - if ctx.Quiet { - ctx.Format = defaultQuietFormat - } - - customFormat(ctx, containers) -} - -func customFormat(ctx Context, containers []types.Container) { - var ( - table bool - header string - format = ctx.Format - buffer = bytes.NewBufferString("") - ) - - if strings.HasPrefix(ctx.Format, tableKey) { - table = true - format = format[len(tableKey):] - } - - format = strings.Trim(format, " ") - r := strings.NewReplacer(`\t`, "\t", `\n`, "\n") - format = r.Replace(format) - - if table && ctx.Size { - format += "\t{{.Size}}" - } - - tmpl, err := template.New("").Parse(format) - if err != nil { - buffer.WriteString(fmt.Sprintf("Template parsing error: %v\n", err)) - buffer.WriteTo(ctx.Output) - return - } - - for _, container := range containers { - containerCtx := &containerContext{ - trunc: ctx.Trunc, - c: container, - } - if err := tmpl.Execute(buffer, containerCtx); err != nil { - buffer = bytes.NewBufferString(fmt.Sprintf("Template parsing error: %v\n", err)) - buffer.WriteTo(ctx.Output) - return - } - if table && len(header) == 0 { - header = containerCtx.fullHeader() - } - buffer.WriteString("\n") - } - - if table { - if len(header) == 0 { - // if we still don't have a header, we didn't have any containers so we need to fake it to get the right headers from the template - containerCtx := &containerContext{} - tmpl.Execute(bytes.NewBufferString(""), containerCtx) - header = containerCtx.fullHeader() - } - - t := tabwriter.NewWriter(ctx.Output, 20, 1, 3, ' ', 0) - t.Write([]byte(header)) - t.Write([]byte("\n")) - buffer.WriteTo(t) - t.Flush() - } else { - buffer.WriteTo(ctx.Output) - } -} diff --git a/vendor/github.com/docker/docker/api/client/ps/formatter_test.go b/vendor/github.com/docker/docker/api/client/ps/formatter_test.go deleted file mode 100644 index 6e7304c3..00000000 --- a/vendor/github.com/docker/docker/api/client/ps/formatter_test.go +++ /dev/null @@ -1,208 +0,0 @@ -package ps - -import ( - "bytes" - "testing" - - "github.com/docker/docker/api/types" -) - -func TestFormat(t *testing.T) { - contexts := []struct { - context Context - expected string - }{ - // Errors - { - Context{ - Format: "{{InvalidFunction}}", - }, - `Template parsing error: template: :1: function "InvalidFunction" not defined -`, - }, - { - Context{ - Format: "{{nil}}", - }, - `Template parsing error: template: :1:2: executing "" at : nil is not a command -`, - }, - // Table Format - { - Context{ - Format: "table", - }, - `CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -containerID1 ubuntu "" 45 years ago foobar_baz -containerID2 ubuntu "" 45 years ago foobar_bar -`, - }, - { - Context{ - Format: "table {{.Image}}", - }, - "IMAGE\nubuntu\nubuntu\n", - }, - { - Context{ - Format: "table {{.Image}}", - Size: true, - }, - "IMAGE SIZE\nubuntu 0 B\nubuntu 0 B\n", - }, - { - Context{ - Format: "table {{.Image}}", - Quiet: true, - }, - "IMAGE\nubuntu\nubuntu\n", - }, - { - Context{ - Format: "table", - Quiet: true, - }, - "containerID1\ncontainerID2\n", - }, - // Raw Format - { - Context{ - Format: "raw", - }, - `container_id: containerID1 -image: ubuntu -command: "" -created_at: 1970-01-01 00:00:00 +0000 UTC -status: -names: foobar_baz -labels: -ports: - -container_id: containerID2 -image: ubuntu -command: "" -created_at: 1970-01-01 00:00:00 +0000 UTC -status: -names: foobar_bar -labels: -ports: - -`, - }, - { - Context{ - Format: "raw", - Size: true, - }, - `container_id: containerID1 -image: ubuntu -command: "" -created_at: 1970-01-01 00:00:00 +0000 UTC -status: -names: foobar_baz -labels: -ports: -size: 0 B - -container_id: containerID2 -image: ubuntu -command: "" -created_at: 1970-01-01 00:00:00 +0000 UTC -status: -names: foobar_bar -labels: -ports: -size: 0 B - -`, - }, - { - Context{ - Format: "raw", - Quiet: true, - }, - "container_id: containerID1\ncontainer_id: containerID2\n", - }, - // Custom Format - { - Context{ - Format: "{{.Image}}", - }, - "ubuntu\nubuntu\n", - }, - { - Context{ - Format: "{{.Image}}", - Size: true, - }, - "ubuntu\nubuntu\n", - }, - } - - for _, context := range contexts { - containers := []types.Container{ - {ID: "containerID1", Names: []string{"/foobar_baz"}, Image: "ubuntu"}, - {ID: "containerID2", Names: []string{"/foobar_bar"}, Image: "ubuntu"}, - } - out := bytes.NewBufferString("") - context.context.Output = out - Format(context.context, containers) - actual := out.String() - if actual != context.expected { - t.Fatalf("Expected \n%s, got \n%s", context.expected, actual) - } - // Clean buffer - out.Reset() - } -} - -func TestCustomFormatNoContainers(t *testing.T) { - out := bytes.NewBufferString("") - containers := []types.Container{} - - contexts := []struct { - context Context - expected string - }{ - { - Context{ - Format: "{{.Image}}", - Output: out, - }, - "", - }, - { - Context{ - Format: "table {{.Image}}", - Output: out, - }, - "IMAGE\n", - }, - { - Context{ - Format: "{{.Image}}", - Output: out, - Size: true, - }, - "", - }, - { - Context{ - Format: "table {{.Image}}", - Output: out, - Size: true, - }, - "IMAGE SIZE\n", - }, - } - - for _, context := range contexts { - customFormat(context.context, containers) - actual := out.String() - if actual != context.expected { - t.Fatalf("Expected \n%s, got \n%s", context.expected, actual) - } - // Clean buffer - out.Reset() - } -} diff --git a/vendor/github.com/docker/docker/api/client/pull.go b/vendor/github.com/docker/docker/api/client/pull.go deleted file mode 100644 index dcb2ecb0..00000000 --- a/vendor/github.com/docker/docker/api/client/pull.go +++ /dev/null @@ -1,53 +0,0 @@ -package client - -import ( - "fmt" - "net/url" - - Cli "github.com/docker/docker/cli" - "github.com/docker/docker/graph/tags" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/parsers" - "github.com/docker/docker/registry" -) - -// CmdPull pulls an image or a repository from the registry. -// -// Usage: docker pull [OPTIONS] IMAGENAME[:TAG|@DIGEST] -func (cli *DockerCli) CmdPull(args ...string) error { - cmd := Cli.Subcmd("pull", []string{"NAME[:TAG|@DIGEST]"}, Cli.DockerCommands["pull"].Description, true) - allTags := cmd.Bool([]string{"a", "-all-tags"}, false, "Download all tagged images in the repository") - addTrustedFlags(cmd, true) - cmd.Require(flag.Exact, 1) - - cmd.ParseFlags(args, true) - remote := cmd.Arg(0) - - taglessRemote, tag := parsers.ParseRepositoryTag(remote) - if tag == "" && !*allTags { - tag = tags.DefaultTag - fmt.Fprintf(cli.out, "Using default tag: %s\n", tag) - } else if tag != "" && *allTags { - return fmt.Errorf("tag can't be used with --all-tags/-a") - } - - ref := registry.ParseReference(tag) - - // Resolve the Repository name from fqn to RepositoryInfo - repoInfo, err := registry.ParseRepositoryInfo(taglessRemote) - if err != nil { - return err - } - - if isTrusted() && !ref.HasDigest() { - // Check if tag is digest - authConfig := registry.ResolveAuthConfig(cli.configFile, repoInfo.Index) - return cli.trustedPull(repoInfo, ref, authConfig) - } - - v := url.Values{} - v.Set("fromImage", ref.ImageName(taglessRemote)) - - _, _, err = cli.clientRequestAttemptLogin("POST", "/images/create?"+v.Encode(), nil, cli.out, repoInfo.Index, "pull") - return err -} diff --git a/vendor/github.com/docker/docker/api/client/push.go b/vendor/github.com/docker/docker/api/client/push.go deleted file mode 100644 index 0c8823f0..00000000 --- a/vendor/github.com/docker/docker/api/client/push.go +++ /dev/null @@ -1,53 +0,0 @@ -package client - -import ( - "fmt" - "net/url" - - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/parsers" - "github.com/docker/docker/registry" -) - -// CmdPush pushes an image or repository to the registry. -// -// Usage: docker push NAME[:TAG] -func (cli *DockerCli) CmdPush(args ...string) error { - cmd := Cli.Subcmd("push", []string{"NAME[:TAG]"}, Cli.DockerCommands["push"].Description, true) - addTrustedFlags(cmd, false) - cmd.Require(flag.Exact, 1) - - cmd.ParseFlags(args, true) - - remote, tag := parsers.ParseRepositoryTag(cmd.Arg(0)) - - // 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 := registry.ResolveAuthConfig(cli.configFile, 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) - } - - if isTrusted() { - return cli.trustedPush(repoInfo, tag, authConfig) - } - - v := url.Values{} - v.Set("tag", tag) - - _, _, err = cli.clientRequestAttemptLogin("POST", "/images/"+remote+"/push?"+v.Encode(), nil, cli.out, repoInfo.Index, "push") - return err -} diff --git a/vendor/github.com/docker/docker/api/client/rename.go b/vendor/github.com/docker/docker/api/client/rename.go deleted file mode 100644 index 124ee1fc..00000000 --- a/vendor/github.com/docker/docker/api/client/rename.go +++ /dev/null @@ -1,32 +0,0 @@ -package client - -import ( - "fmt" - "strings" - - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" -) - -// CmdRename renames a container. -// -// Usage: docker rename OLD_NAME NEW_NAME -func (cli *DockerCli) CmdRename(args ...string) error { - cmd := Cli.Subcmd("rename", []string{"OLD_NAME NEW_NAME"}, Cli.DockerCommands["rename"].Description, true) - cmd.Require(flag.Exact, 2) - - cmd.ParseFlags(args, true) - - oldName := strings.TrimSpace(cmd.Arg(0)) - newName := strings.TrimSpace(cmd.Arg(1)) - - if oldName == "" || newName == "" { - return fmt.Errorf("Error: Neither old nor new names may be empty") - } - - if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/rename?name=%s", oldName, newName), nil, nil)); err != nil { - fmt.Fprintf(cli.err, "%s\n", err) - return fmt.Errorf("Error: failed to rename container named %s", oldName) - } - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/restart.go b/vendor/github.com/docker/docker/api/client/restart.go deleted file mode 100644 index 92c61292..00000000 --- a/vendor/github.com/docker/docker/api/client/restart.go +++ /dev/null @@ -1,39 +0,0 @@ -package client - -import ( - "fmt" - "net/url" - "strconv" - - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" -) - -// CmdRestart restarts one or more containers. -// -// Usage: docker restart [OPTIONS] CONTAINER [CONTAINER...] -func (cli *DockerCli) CmdRestart(args ...string) error { - cmd := Cli.Subcmd("restart", []string{"CONTAINER [CONTAINER...]"}, Cli.DockerCommands["restart"].Description, true) - nSeconds := cmd.Int([]string{"t", "-time"}, 10, "Seconds to wait for stop before killing the container") - cmd.Require(flag.Min, 1) - - cmd.ParseFlags(args, true) - - v := url.Values{} - v.Set("t", strconv.Itoa(*nSeconds)) - - var errNames []string - for _, name := range cmd.Args() { - _, _, err := readBody(cli.call("POST", "/containers/"+name+"/restart?"+v.Encode(), nil, nil)) - if err != nil { - fmt.Fprintf(cli.err, "%s\n", err) - errNames = append(errNames, name) - } else { - fmt.Fprintf(cli.out, "%s\n", name) - } - } - if len(errNames) > 0 { - return fmt.Errorf("Error: failed to restart containers: %v", errNames) - } - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/rm.go b/vendor/github.com/docker/docker/api/client/rm.go deleted file mode 100644 index 9f49a2fd..00000000 --- a/vendor/github.com/docker/docker/api/client/rm.go +++ /dev/null @@ -1,55 +0,0 @@ -package client - -import ( - "fmt" - "net/url" - "strings" - - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" -) - -// CmdRm removes one or more containers. -// -// Usage: docker rm [OPTIONS] CONTAINER [CONTAINER...] -func (cli *DockerCli) CmdRm(args ...string) error { - cmd := Cli.Subcmd("rm", []string{"CONTAINER [CONTAINER...]"}, Cli.DockerCommands["rm"].Description, 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") - force := cmd.Bool([]string{"f", "-force"}, false, "Force the removal of a running container (uses SIGKILL)") - cmd.Require(flag.Min, 1) - - cmd.ParseFlags(args, true) - - val := url.Values{} - if *v { - val.Set("v", "1") - } - if *link { - val.Set("link", "1") - } - - if *force { - val.Set("force", "1") - } - - var errNames []string - for _, name := range cmd.Args() { - if name == "" { - return fmt.Errorf("Container name cannot be empty") - } - name = strings.Trim(name, "/") - - _, _, err := readBody(cli.call("DELETE", "/containers/"+name+"?"+val.Encode(), nil, nil)) - if err != nil { - fmt.Fprintf(cli.err, "%s\n", err) - errNames = append(errNames, name) - } else { - fmt.Fprintf(cli.out, "%s\n", name) - } - } - if len(errNames) > 0 { - return fmt.Errorf("Error: failed to remove containers: %v", errNames) - } - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/rmi.go b/vendor/github.com/docker/docker/api/client/rmi.go deleted file mode 100644 index b4e37006..00000000 --- a/vendor/github.com/docker/docker/api/client/rmi.go +++ /dev/null @@ -1,61 +0,0 @@ -package client - -import ( - "encoding/json" - "fmt" - "net/url" - - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" -) - -// CmdRmi removes all images with the specified name(s). -// -// Usage: docker rmi [OPTIONS] IMAGE [IMAGE...] -func (cli *DockerCli) CmdRmi(args ...string) error { - cmd := Cli.Subcmd("rmi", []string{"IMAGE [IMAGE...]"}, Cli.DockerCommands["rmi"].Description, 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) - - cmd.ParseFlags(args, true) - - v := url.Values{} - if *force { - v.Set("force", "1") - } - if *noprune { - v.Set("noprune", "1") - } - - var errNames []string - for _, name := range cmd.Args() { - serverResp, err := cli.call("DELETE", "/images/"+name+"?"+v.Encode(), nil, nil) - if err != nil { - fmt.Fprintf(cli.err, "%s\n", err) - errNames = append(errNames, name) - } else { - defer serverResp.body.Close() - - dels := []types.ImageDelete{} - if err := json.NewDecoder(serverResp.body).Decode(&dels); err != nil { - fmt.Fprintf(cli.err, "%s\n", err) - errNames = append(errNames, name) - continue - } - - for _, del := range dels { - if del.Deleted != "" { - fmt.Fprintf(cli.out, "Deleted: %s\n", del.Deleted) - } else { - fmt.Fprintf(cli.out, "Untagged: %s\n", del.Untagged) - } - } - } - } - if len(errNames) > 0 { - return fmt.Errorf("Error: failed to remove images: %v", errNames) - } - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/run.go b/vendor/github.com/docker/docker/api/client/run.go deleted file mode 100644 index 205aeebc..00000000 --- a/vendor/github.com/docker/docker/api/client/run.go +++ /dev/null @@ -1,284 +0,0 @@ -package client - -import ( - "fmt" - "io" - "net/url" - "os" - "runtime" - "strings" - - "github.com/Sirupsen/logrus" - Cli "github.com/docker/docker/cli" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/opts" - "github.com/docker/docker/pkg/promise" - "github.com/docker/docker/pkg/signal" - "github.com/docker/docker/runconfig" - "github.com/docker/libnetwork/resolvconf/dns" -) - -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 -} - -// if container start fails with 'command not found' error, return 127 -// if container start fails with 'command cannot be invoked' error, return 126 -// return 125 for generic docker daemon failures -func runStartContainerErr(err error) error { - trimmedErr := strings.Trim(err.Error(), "Error response from daemon: ") - statusError := Cli.StatusError{} - derrCmdNotFound := derr.ErrorCodeCmdNotFound.Message() - derrCouldNotInvoke := derr.ErrorCodeCmdCouldNotBeInvoked.Message() - derrNoSuchImage := derr.ErrorCodeNoSuchImageHash.Message() - derrNoSuchImageTag := derr.ErrorCodeNoSuchImageTag.Message() - switch trimmedErr { - case derrCmdNotFound: - statusError = Cli.StatusError{StatusCode: 127} - case derrCouldNotInvoke: - statusError = Cli.StatusError{StatusCode: 126} - case derrNoSuchImage, derrNoSuchImageTag: - statusError = Cli.StatusError{StatusCode: 125} - default: - statusError = Cli.StatusError{StatusCode: 125} - } - return statusError -} - -// CmdRun runs a command in a new container. -// -// Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...] -func (cli *DockerCli) CmdRun(args ...string) error { - cmd := Cli.Subcmd("run", []string{"IMAGE [COMMAND] [ARG...]"}, Cli.DockerCommands["run"].Description, true) - addTrustedFlags(cmd, true) - - // These are flags not stored in Config/HostConfig - var ( - flAutoRemove = cmd.Bool([]string{"-rm"}, false, "Automatically remove the container when it exits") - flDetach = cmd.Bool([]string{"d", "-detach"}, false, "Run container in background and print container ID") - flSigProxy = cmd.Bool([]string{"-sig-proxy"}, true, "Proxy received signals to the process") - flName = cmd.String([]string{"-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 { - cmd.ReportError(err.Error(), true) - os.Exit(125) - } - - if len(hostConfig.DNS) > 0 { - // check the DNS settings passed via --dns against - // localhost regexp to warn if they are trying to - // set a DNS to a localhost address - for _, dnsIP := range hostConfig.DNS { - if dns.IsLocalhost(dnsIP) { - fmt.Fprintf(cli.err, "WARNING: Localhost DNS setting (--dns=%s) may fail in containers.\n", dnsIP) - break - } - } - } - 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 - } - - // Telling the Windows daemon the initial size of the tty during start makes - // a far better user experience rather than relying on subsequent resizes - // to cause things to catch up. - if runtime.GOOS == "windows" { - hostConfig.ConsoleSize[0], hostConfig.ConsoleSize[1] = cli.getTtySize() - } - - createResponse, err := cli.createContainer(config, hostConfig, hostConfig.ContainerIDFile, *flName) - if err != nil { - cmd.ReportError(err.Error(), true) - return runStartContainerErr(err) - } - if sigProxy { - sigc := cli.forwardAllSignals(createResponse.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", createResponse.ID) - }() - } - if *flAutoRemove && (hostConfig.RestartPolicy.IsAlways() || hostConfig.RestartPolicy.IsOnFailure()) { - 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() { - logrus.Debugf("End of CmdRun(), Waiting for hijack to finish.") - if _, ok := <-hijacked; ok { - fmt.Fprintln(cli.err, "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/"+createResponse.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 { - logrus.Debugf("Error hijack: %s", err) - return err - } - } - - defer func() { - if *flAutoRemove { - if _, _, err = readBody(cli.call("DELETE", "/containers/"+createResponse.ID+"?v=1", nil, nil)); err != nil { - fmt.Fprintf(cli.err, "Error deleting container: %s\n", err) - } - } - }() - - //start the container - if _, _, err := readBody(cli.call("POST", "/containers/"+createResponse.ID+"/start", nil, nil)); err != nil { - cmd.ReportError(err.Error(), false) - return runStartContainerErr(err) - } - - if (config.AttachStdin || config.AttachStdout || config.AttachStderr) && config.Tty && cli.isTerminalOut { - if err := cli.monitorTtySize(createResponse.ID, false); err != nil { - fmt.Fprintf(cli.err, "Error monitoring TTY size: %s\n", err) - } - } - - if errCh != nil { - if err := <-errCh; err != nil { - logrus.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/"+createResponse.ID+"/wait", nil, nil)); err != nil { - return runStartContainerErr(err) - } - if _, status, err = getExitCode(cli, createResponse.ID); 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, createResponse.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, createResponse.ID); err != nil { - return err - } - } - } - if status != 0 { - return Cli.StatusError{StatusCode: status} - } - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/save.go b/vendor/github.com/docker/docker/api/client/save.go deleted file mode 100644 index f14f9a45..00000000 --- a/vendor/github.com/docker/docker/api/client/save.go +++ /dev/null @@ -1,52 +0,0 @@ -package client - -import ( - "errors" - "net/url" - "os" - - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" -) - -// CmdSave saves one or more images to a tar archive. -// -// The tar archive is written to STDOUT by default, or written to a file. -// -// Usage: docker save [OPTIONS] IMAGE [IMAGE...] -func (cli *DockerCli) CmdSave(args ...string) error { - cmd := Cli.Subcmd("save", []string{"IMAGE [IMAGE...]"}, Cli.DockerCommands["save"].Description+" (streamed to STDOUT by default)", true) - outfile := cmd.String([]string{"o", "-output"}, "", "Write to a file, instead of STDOUT") - cmd.Require(flag.Min, 1) - - cmd.ParseFlags(args, true) - - var ( - output = cli.out - err error - ) - - if *outfile == "" && cli.isTerminalOut { - return errors.New("Cowardly refusing to save to a terminal. Use the -o flag or redirect.") - } - if *outfile != "" { - if output, err = os.Create(*outfile); err != nil { - return err - } - } - - sopts := &streamOpts{ - rawTerminal: true, - out: output, - } - - v := url.Values{} - for _, arg := range cmd.Args() { - v.Add("names", arg) - } - if _, err := cli.stream("GET", "/images/get?"+v.Encode(), sopts); err != nil { - return err - } - - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/search.go b/vendor/github.com/docker/docker/api/client/search.go deleted file mode 100644 index bf120cdd..00000000 --- a/vendor/github.com/docker/docker/api/client/search.go +++ /dev/null @@ -1,88 +0,0 @@ -package client - -import ( - "encoding/json" - "fmt" - "net/url" - "sort" - "strings" - "text/tabwriter" - - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/parsers" - "github.com/docker/docker/pkg/stringutils" - "github.com/docker/docker/registry" -) - -// ByStars sorts search results in ascending order by number of stars. -type ByStars []registry.SearchResult - -func (r ByStars) Len() int { return len(r) } -func (r ByStars) Swap(i, j int) { r[i], r[j] = r[j], r[i] } -func (r ByStars) Less(i, j int) bool { return r[i].StarCount < r[j].StarCount } - -// CmdSearch searches the Docker Hub for images. -// -// Usage: docker search [OPTIONS] TERM -func (cli *DockerCli) CmdSearch(args ...string) error { - cmd := Cli.Subcmd("search", []string{"TERM"}, Cli.DockerCommands["search"].Description, 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.Uint([]string{"s", "#stars", "-stars"}, 0, "Only displays with at least x stars") - cmd.Require(flag.Exact, 1) - - cmd.ParseFlags(args, true) - - name := cmd.Arg(0) - v := url.Values{} - v.Set("term", name) - - // Resolve the Repository name from fqn to hostname + name - taglessRemote, _ := parsers.ParseRepositoryTag(name) - - indexInfo, err := registry.ParseIndexInfo(taglessRemote) - if err != nil { - return err - } - - rdr, _, err := cli.clientRequestAttemptLogin("GET", "/images/search?"+v.Encode(), nil, nil, indexInfo, "search") - if err != nil { - return err - } - - defer rdr.Close() - - results := ByStars{} - if err := json.NewDecoder(rdr).Decode(&results); err != nil { - return err - } - - sort.Sort(sort.Reverse(results)) - - w := tabwriter.NewWriter(cli.out, 10, 1, 3, ' ', 0) - fmt.Fprintf(w, "NAME\tDESCRIPTION\tSTARS\tOFFICIAL\tAUTOMATED\n") - for _, res := range results { - if (*automated && !res.IsAutomated) || (int(*stars) > res.StarCount) || (*trusted && !res.IsTrusted) { - continue - } - desc := strings.Replace(res.Description, "\n", " ", -1) - desc = strings.Replace(desc, "\r", " ", -1) - if !*noTrunc && len(desc) > 45 { - desc = stringutils.Truncate(desc, 42) + "..." - } - fmt.Fprintf(w, "%s\t%s\t%d\t", res.Name, desc, res.StarCount) - if res.IsOfficial { - fmt.Fprint(w, "[OK]") - - } - fmt.Fprint(w, "\t") - if res.IsAutomated || res.IsTrusted { - fmt.Fprint(w, "[OK]") - } - fmt.Fprint(w, "\n") - } - w.Flush() - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/start.go b/vendor/github.com/docker/docker/api/client/start.go deleted file mode 100644 index bff9c30e..00000000 --- a/vendor/github.com/docker/docker/api/client/start.go +++ /dev/null @@ -1,171 +0,0 @@ -package client - -import ( - "encoding/json" - "fmt" - "io" - "net/url" - "os" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/promise" - "github.com/docker/docker/pkg/signal" -) - -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 == "" { - fmt.Fprintf(cli.err, "Unsupported signal: %v. Discarding.\n", s) - continue - } - if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%s", cid, sig), nil, nil)); err != nil { - logrus.Debugf("Error sending signal: %s", err) - } - } - }() - return sigc -} - -// CmdStart starts one or more containers. -// -// Usage: docker start [OPTIONS] CONTAINER [CONTAINER...] -func (cli *DockerCli) CmdStart(args ...string) error { - cmd := Cli.Subcmd("start", []string{"CONTAINER [CONTAINER...]"}, Cli.DockerCommands["start"].Description, true) - attach := cmd.Bool([]string{"a", "-attach"}, false, "Attach STDOUT/STDERR and forward signals") - openStdin := cmd.Bool([]string{"i", "-interactive"}, false, "Attach container's STDIN") - cmd.Require(flag.Min, 1) - - cmd.ParseFlags(args, true) - - var ( - cErr chan error - tty bool - ) - - if *attach || *openStdin { - if cmd.NArg() > 1 { - return fmt.Errorf("You cannot start and attach multiple containers at once.") - } - - serverResp, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/json", nil, nil) - if err != nil { - return err - } - - defer serverResp.body.Close() - - var c types.ContainerJSON - if err := json.NewDecoder(serverResp.body).Decode(&c); err != nil { - return err - } - - tty = c.Config.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 && c.Config.OpenStdin { - v.Set("stdin", "1") - in = cli.in - } - - v.Set("stdout", "1") - v.Set("stderr", "1") - - hijacked := make(chan io.Closer) - // Block the return until the chan gets closed - defer func() { - logrus.Debugf("CmdStart() returned, defer waiting for hijack to finish.") - if _, ok := <-hijacked; ok { - fmt.Fprintln(cli.err, "Hijack did not finish (chan still open)") - } - cli.in.Close() - }() - cErr = promise.Go(func() error { - return cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), tty, in, cli.out, cli.err, hijacked, nil) - }) - - // 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 - var errNames []string - for _, name := range cmd.Args() { - _, _, err := readBody(cli.call("POST", "/containers/"+name+"/start", nil, nil)) - if err != nil { - if !*attach && !*openStdin { - // attach and openStdin is false means it could be starting multiple containers - // when a container start failed, show the error message and start next - fmt.Fprintf(cli.err, "%s\n", err) - errNames = append(errNames, name) - } else { - encounteredError = err - } - } else { - if !*attach && !*openStdin { - fmt.Fprintf(cli.out, "%s\n", name) - } - } - } - - if len(errNames) > 0 { - encounteredError = fmt.Errorf("Error: failed to start containers: %v", errNames) - } - if encounteredError != nil { - return encounteredError - } - - if *openStdin || *attach { - if tty && cli.isTerminalOut { - if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil { - fmt.Fprintf(cli.err, "Error monitoring TTY size: %s\n", err) - } - } - if attchErr := <-cErr; attchErr != nil { - return attchErr - } - _, status, err := getExitCode(cli, cmd.Arg(0)) - if err != nil { - return err - } - if status != 0 { - return Cli.StatusError{StatusCode: status} - } - } - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/stats.go b/vendor/github.com/docker/docker/api/client/stats.go deleted file mode 100644 index 151e602e..00000000 --- a/vendor/github.com/docker/docker/api/client/stats.go +++ /dev/null @@ -1,351 +0,0 @@ -package client - -import ( - "encoding/json" - "fmt" - "io" - "net/url" - "sort" - "strings" - "sync" - "text/tabwriter" - "time" - - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/docker/docker/pkg/units" -) - -type containerStats struct { - Name string - CPUPercentage float64 - Memory float64 - MemoryLimit float64 - MemoryPercentage float64 - NetworkRx float64 - NetworkTx float64 - BlockRead float64 - BlockWrite float64 - mu sync.RWMutex - err error -} - -type stats struct { - mu sync.Mutex - cs []*containerStats -} - -func (s *containerStats) Collect(cli *DockerCli, streamStats bool) { - v := url.Values{} - if streamStats { - v.Set("stream", "1") - } else { - v.Set("stream", "0") - } - serverResp, err := cli.call("GET", "/containers/"+s.Name+"/stats?"+v.Encode(), nil, nil) - if err != nil { - s.mu.Lock() - s.err = err - s.mu.Unlock() - return - } - - defer serverResp.body.Close() - - var ( - previousCPU uint64 - previousSystem uint64 - dec = json.NewDecoder(serverResp.body) - u = make(chan error, 1) - ) - go func() { - for { - var v *types.StatsJSON - if err := dec.Decode(&v); err != nil { - u <- err - return - } - - var memPercent = 0.0 - var cpuPercent = 0.0 - - // MemoryStats.Limit will never be 0 unless the container is not running and we havn't - // got any data from cgroup - if v.MemoryStats.Limit != 0 { - memPercent = float64(v.MemoryStats.Usage) / float64(v.MemoryStats.Limit) * 100.0 - } - - previousCPU = v.PreCPUStats.CPUUsage.TotalUsage - previousSystem = v.PreCPUStats.SystemUsage - cpuPercent = calculateCPUPercent(previousCPU, previousSystem, v) - blkRead, blkWrite := calculateBlockIO(v.BlkioStats) - s.mu.Lock() - s.CPUPercentage = cpuPercent - s.Memory = float64(v.MemoryStats.Usage) - s.MemoryLimit = float64(v.MemoryStats.Limit) - s.MemoryPercentage = memPercent - s.NetworkRx, s.NetworkTx = calculateNetwork(v.Networks) - s.BlockRead = float64(blkRead) - s.BlockWrite = float64(blkWrite) - s.mu.Unlock() - u <- nil - if !streamStats { - return - } - } - }() - 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.MemoryLimit = 0 - s.NetworkRx = 0 - s.NetworkTx = 0 - s.BlockRead = 0 - s.BlockWrite = 0 - s.mu.Unlock() - case err := <-u: - if err != nil { - s.mu.Lock() - s.err = err - s.mu.Unlock() - return - } - } - if !streamStats { - 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\t%s / %s\n", - s.Name, - s.CPUPercentage, - units.HumanSize(s.Memory), units.HumanSize(s.MemoryLimit), - s.MemoryPercentage, - units.HumanSize(s.NetworkRx), units.HumanSize(s.NetworkTx), - units.HumanSize(s.BlockRead), units.HumanSize(s.BlockWrite)) - return nil -} - -// CmdStats displays a live stream of resource usage statistics for one or more containers. -// -// This shows real-time information on CPU usage, memory usage, and network I/O. -// -// Usage: docker stats [OPTIONS] [CONTAINER...] -func (cli *DockerCli) CmdStats(args ...string) error { - cmd := Cli.Subcmd("stats", []string{"[CONTAINER...]"}, Cli.DockerCommands["stats"].Description, true) - all := cmd.Bool([]string{"a", "-all"}, false, "Show all containers (default shows just running)") - noStream := cmd.Bool([]string{"-no-stream"}, false, "Disable streaming stats and only pull the first result") - - cmd.ParseFlags(args, true) - - names := cmd.Args() - showAll := len(names) == 0 - - if showAll { - v := url.Values{} - if *all { - v.Set("all", "1") - } - body, _, err := readBody(cli.call("GET", "/containers/json?"+v.Encode(), nil, nil)) - if err != nil { - return err - } - var cs []types.Container - if err := json.Unmarshal(body, &cs); err != nil { - return err - } - for _, c := range cs { - names = append(names, c.ID[:12]) - } - } - if len(names) == 0 && !showAll { - return fmt.Errorf("No containers found") - } - sort.Strings(names) - - var ( - cStats = stats{} - w = tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) - ) - printHeader := func() { - if !*noStream { - fmt.Fprint(cli.out, "\033[2J") - fmt.Fprint(cli.out, "\033[H") - } - io.WriteString(w, "CONTAINER\tCPU %\tMEM USAGE / LIMIT\tMEM %\tNET I/O\tBLOCK I/O\n") - } - for _, n := range names { - s := &containerStats{Name: n} - // no need to lock here since only the main goroutine is running here - cStats.cs = append(cStats.cs, s) - go s.Collect(cli, !*noStream) - } - closeChan := make(chan error) - if showAll { - type watch struct { - cid string - event string - err error - } - getNewContainers := func(c chan<- watch) { - res, err := cli.call("GET", "/events", nil, nil) - if err != nil { - c <- watch{err: err} - return - } - defer res.body.Close() - - dec := json.NewDecoder(res.body) - for { - var j *jsonmessage.JSONMessage - if err := dec.Decode(&j); err != nil { - c <- watch{err: err} - return - } - c <- watch{j.ID[:12], j.Status, nil} - } - } - go func(stopChan chan<- error) { - cChan := make(chan watch) - go getNewContainers(cChan) - for { - c := <-cChan - if c.err != nil { - stopChan <- c.err - return - } - switch c.event { - case "create": - s := &containerStats{Name: c.cid} - cStats.mu.Lock() - cStats.cs = append(cStats.cs, s) - cStats.mu.Unlock() - go s.Collect(cli, !*noStream) - case "stop": - case "die": - if !*all { - var remove int - // cStats cannot be O(1) with a map cause ranging over it would cause - // containers in stats to move up and down in the list...:( - cStats.mu.Lock() - for i, s := range cStats.cs { - if s.Name == c.cid { - remove = i - break - } - } - cStats.cs = append(cStats.cs[:remove], cStats.cs[remove+1:]...) - cStats.mu.Unlock() - } - } - } - }(closeChan) - } else { - close(closeChan) - } - // 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(1500 * time.Millisecond) - var errs []string - cStats.mu.Lock() - for _, c := range cStats.cs { - c.mu.Lock() - if c.err != nil { - errs = append(errs, fmt.Sprintf("%s: %v", c.Name, c.err)) - } - c.mu.Unlock() - } - cStats.mu.Unlock() - if len(errs) > 0 { - return fmt.Errorf("%s", strings.Join(errs, ", ")) - } - for range time.Tick(500 * time.Millisecond) { - printHeader() - toRemove := []int{} - cStats.mu.Lock() - for i, s := range cStats.cs { - if err := s.Display(w); err != nil && !*noStream { - toRemove = append(toRemove, i) - } - } - for j := len(toRemove) - 1; j >= 0; j-- { - i := toRemove[j] - cStats.cs = append(cStats.cs[:i], cStats.cs[i+1:]...) - } - if len(cStats.cs) == 0 && !showAll { - return nil - } - cStats.mu.Unlock() - w.Flush() - if *noStream { - break - } - select { - case err, ok := <-closeChan: - if ok { - if err != nil { - // this is suppressing "unexpected EOF" in the cli when the - // daemon restarts so it shudowns cleanly - if err == io.ErrUnexpectedEOF { - return nil - } - return err - } - } - default: - // just skip - } - } - return nil -} - -func calculateCPUPercent(previousCPU, previousSystem uint64, v *types.StatsJSON) 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 -} - -func calculateBlockIO(blkio types.BlkioStats) (blkRead uint64, blkWrite uint64) { - for _, bioEntry := range blkio.IoServiceBytesRecursive { - switch strings.ToLower(bioEntry.Op) { - case "read": - blkRead = blkRead + bioEntry.Value - case "write": - blkWrite = blkWrite + bioEntry.Value - } - } - return -} - -func calculateNetwork(network map[string]types.NetworkStats) (float64, float64) { - var rx, tx float64 - - for _, v := range network { - rx += float64(v.RxBytes) - tx += float64(v.TxBytes) - } - return rx, tx -} diff --git a/vendor/github.com/docker/docker/api/client/stats_unit_test.go b/vendor/github.com/docker/docker/api/client/stats_unit_test.go deleted file mode 100644 index 301e0a67..00000000 --- a/vendor/github.com/docker/docker/api/client/stats_unit_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package client - -import ( - "bytes" - "sync" - "testing" - - "github.com/docker/docker/api/types" -) - -func TestDisplay(t *testing.T) { - c := &containerStats{ - Name: "app", - CPUPercentage: 30.0, - Memory: 100 * 1024 * 1024.0, - MemoryLimit: 2048 * 1024 * 1024.0, - MemoryPercentage: 100.0 / 2048.0 * 100.0, - NetworkRx: 100 * 1024 * 1024, - NetworkTx: 800 * 1024 * 1024, - BlockRead: 100 * 1024 * 1024, - BlockWrite: 800 * 1024 * 1024, - mu: sync.RWMutex{}, - } - var b bytes.Buffer - if err := c.Display(&b); err != nil { - t.Fatalf("c.Display() gave error: %s", err) - } - got := b.String() - want := "app\t30.00%\t104.9 MB / 2.147 GB\t4.88%\t104.9 MB / 838.9 MB\t104.9 MB / 838.9 MB\n" - if got != want { - t.Fatalf("c.Display() = %q, want %q", got, want) - } -} - -func TestCalculBlockIO(t *testing.T) { - blkio := types.BlkioStats{ - IoServiceBytesRecursive: []types.BlkioStatEntry{{8, 0, "read", 1234}, {8, 1, "read", 4567}, {8, 0, "write", 123}, {8, 1, "write", 456}}, - } - blkRead, blkWrite := calculateBlockIO(blkio) - if blkRead != 5801 { - t.Fatalf("blkRead = %d, want 5801", blkRead) - } - if blkWrite != 579 { - t.Fatalf("blkWrite = %d, want 579", blkWrite) - } -} diff --git a/vendor/github.com/docker/docker/api/client/stop.go b/vendor/github.com/docker/docker/api/client/stop.go deleted file mode 100644 index 91f5e65b..00000000 --- a/vendor/github.com/docker/docker/api/client/stop.go +++ /dev/null @@ -1,41 +0,0 @@ -package client - -import ( - "fmt" - "net/url" - "strconv" - - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" -) - -// CmdStop stops one or more containers. -// -// A running container is stopped by first sending SIGTERM and then SIGKILL if the container fails to stop within a grace period (the default is 10 seconds). -// -// Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...] -func (cli *DockerCli) CmdStop(args ...string) error { - cmd := Cli.Subcmd("stop", []string{"CONTAINER [CONTAINER...]"}, Cli.DockerCommands["stop"].Description+".\nSending SIGTERM and then SIGKILL after a grace period", true) - nSeconds := cmd.Int([]string{"t", "-time"}, 10, "Seconds to wait for stop before killing it") - cmd.Require(flag.Min, 1) - - cmd.ParseFlags(args, true) - - v := url.Values{} - v.Set("t", strconv.Itoa(*nSeconds)) - - var errNames []string - for _, name := range cmd.Args() { - _, _, err := readBody(cli.call("POST", "/containers/"+name+"/stop?"+v.Encode(), nil, nil)) - if err != nil { - fmt.Fprintf(cli.err, "%s\n", err) - errNames = append(errNames, name) - } else { - fmt.Fprintf(cli.out, "%s\n", name) - } - } - if len(errNames) > 0 { - return fmt.Errorf("Error: failed to stop containers: %v", errNames) - } - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/tag.go b/vendor/github.com/docker/docker/api/client/tag.go deleted file mode 100644 index b2fd0592..00000000 --- a/vendor/github.com/docker/docker/api/client/tag.go +++ /dev/null @@ -1,42 +0,0 @@ -package client - -import ( - "net/url" - - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/parsers" - "github.com/docker/docker/registry" -) - -// CmdTag tags an image into a repository. -// -// Usage: docker tag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG] -func (cli *DockerCli) CmdTag(args ...string) error { - cmd := Cli.Subcmd("tag", []string{"IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]"}, Cli.DockerCommands["tag"].Description, true) - force := cmd.Bool([]string{"f", "#force", "-force"}, false, "Force") - cmd.Require(flag.Exact, 2) - - cmd.ParseFlags(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, nil)); err != nil { - return err - } - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/top.go b/vendor/github.com/docker/docker/api/client/top.go deleted file mode 100644 index 8327820a..00000000 --- a/vendor/github.com/docker/docker/api/client/top.go +++ /dev/null @@ -1,49 +0,0 @@ -package client - -import ( - "encoding/json" - "fmt" - "net/url" - "strings" - "text/tabwriter" - - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" -) - -// CmdTop displays the running processes of a container. -// -// Usage: docker top CONTAINER -func (cli *DockerCli) CmdTop(args ...string) error { - cmd := Cli.Subcmd("top", []string{"CONTAINER [ps OPTIONS]"}, Cli.DockerCommands["top"].Description, true) - cmd.Require(flag.Min, 1) - - cmd.ParseFlags(args, true) - - val := url.Values{} - if cmd.NArg() > 1 { - val.Set("ps_args", strings.Join(cmd.Args()[1:], " ")) - } - - serverResp, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/top?"+val.Encode(), nil, nil) - if err != nil { - return err - } - - defer serverResp.body.Close() - - procList := types.ContainerProcessList{} - if err := json.NewDecoder(serverResp.body).Decode(&procList); err != nil { - return err - } - - w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) - fmt.Fprintln(w, strings.Join(procList.Titles, "\t")) - - for _, proc := range procList.Processes { - fmt.Fprintln(w, strings.Join(proc, "\t")) - } - w.Flush() - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/trust.go b/vendor/github.com/docker/docker/api/client/trust.go deleted file mode 100644 index 5936ac93..00000000 --- a/vendor/github.com/docker/docker/api/client/trust.go +++ /dev/null @@ -1,479 +0,0 @@ -package client - -import ( - "bufio" - "encoding/hex" - "encoding/json" - "errors" - "fmt" - "io" - "net" - "net/http" - "net/url" - "os" - "path/filepath" - "regexp" - "sort" - "strconv" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/distribution/digest" - "github.com/docker/distribution/registry/client/auth" - "github.com/docker/distribution/registry/client/transport" - "github.com/docker/docker/cliconfig" - "github.com/docker/docker/pkg/ansiescape" - "github.com/docker/docker/pkg/ioutils" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/tlsconfig" - "github.com/docker/docker/registry" - "github.com/docker/notary/client" - "github.com/docker/notary/pkg/passphrase" - "github.com/docker/notary/trustmanager" - "github.com/endophage/gotuf/data" -) - -var untrusted bool - -func addTrustedFlags(fs *flag.FlagSet, verify bool) { - var trusted bool - if e := os.Getenv("DOCKER_CONTENT_TRUST"); e != "" { - if t, err := strconv.ParseBool(e); t || err != nil { - // treat any other value as true - trusted = true - } - } - message := "Skip image signing" - if verify { - message = "Skip image verification" - } - fs.BoolVar(&untrusted, []string{"-disable-content-trust"}, !trusted, message) -} - -func isTrusted() bool { - return !untrusted -} - -var targetRegexp = regexp.MustCompile(`([\S]+): digest: ([\S]+) size: ([\d]+)`) - -type target struct { - reference registry.Reference - digest digest.Digest - size int64 -} - -func (cli *DockerCli) trustDirectory() string { - return filepath.Join(cliconfig.ConfigDir(), "trust") -} - -// certificateDirectory returns the directory containing -// TLS certificates for the given server. An error is -// returned if there was an error parsing the server string. -func (cli *DockerCli) certificateDirectory(server string) (string, error) { - u, err := url.Parse(server) - if err != nil { - return "", err - } - - return filepath.Join(cliconfig.ConfigDir(), "tls", u.Host), nil -} - -func trustServer(index *registry.IndexInfo) (string, error) { - if s := os.Getenv("DOCKER_CONTENT_TRUST_SERVER"); s != "" { - urlObj, err := url.Parse(s) - if err != nil || urlObj.Scheme != "https" { - return "", fmt.Errorf("valid https URL required for trust server, got %s", s) - } - - return s, nil - } - if index.Official { - return registry.NotaryServer, nil - } - return "https://" + index.Name, nil -} - -type simpleCredentialStore struct { - auth cliconfig.AuthConfig -} - -func (scs simpleCredentialStore) Basic(u *url.URL) (string, string) { - return scs.auth.Username, scs.auth.Password -} - -func (cli *DockerCli) getNotaryRepository(repoInfo *registry.RepositoryInfo, authConfig cliconfig.AuthConfig) (*client.NotaryRepository, error) { - server, err := trustServer(repoInfo.Index) - if err != nil { - return nil, err - } - - var cfg = tlsconfig.ClientDefault - cfg.InsecureSkipVerify = !repoInfo.Index.Secure - - // Get certificate base directory - certDir, err := cli.certificateDirectory(server) - if err != nil { - return nil, err - } - logrus.Debugf("reading certificate directory: %s", certDir) - - if err := registry.ReadCertsDirectory(&cfg, certDir); err != nil { - return nil, err - } - - base := &http.Transport{ - Proxy: http.ProxyFromEnvironment, - Dial: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - DualStack: true, - }).Dial, - TLSHandshakeTimeout: 10 * time.Second, - TLSClientConfig: &cfg, - DisableKeepAlives: true, - } - - // Skip configuration headers since request is not going to Docker daemon - modifiers := registry.DockerHeaders(http.Header{}) - authTransport := transport.NewTransport(base, modifiers...) - pingClient := &http.Client{ - Transport: authTransport, - Timeout: 5 * time.Second, - } - endpointStr := server + "/v2/" - req, err := http.NewRequest("GET", endpointStr, nil) - if err != nil { - return nil, err - } - - challengeManager := auth.NewSimpleChallengeManager() - - resp, err := pingClient.Do(req) - if err != nil { - // Ignore error on ping to operate in offline mode - logrus.Debugf("Error pinging notary server %q: %s", endpointStr, err) - } else { - defer resp.Body.Close() - - // Add response to the challenge manager to parse out - // authentication header and register authentication method - if err := challengeManager.AddResponse(resp); err != nil { - return nil, err - } - } - - creds := simpleCredentialStore{auth: authConfig} - tokenHandler := auth.NewTokenHandler(authTransport, creds, repoInfo.CanonicalName, "push", "pull") - basicHandler := auth.NewBasicHandler(creds) - modifiers = append(modifiers, transport.RequestModifier(auth.NewAuthorizer(challengeManager, tokenHandler, basicHandler))) - tr := transport.NewTransport(base, modifiers...) - - return client.NewNotaryRepository(cli.trustDirectory(), repoInfo.CanonicalName, server, tr, cli.getPassphraseRetriever()) -} - -func convertTarget(t client.Target) (target, error) { - h, ok := t.Hashes["sha256"] - if !ok { - return target{}, errors.New("no valid hash, expecting sha256") - } - return target{ - reference: registry.ParseReference(t.Name), - digest: digest.NewDigestFromHex("sha256", hex.EncodeToString(h)), - size: t.Length, - }, nil -} - -func (cli *DockerCli) getPassphraseRetriever() passphrase.Retriever { - aliasMap := map[string]string{ - "root": "root", - "snapshot": "repository", - "targets": "repository", - } - baseRetriever := passphrase.PromptRetrieverWithInOut(cli.in, cli.out, aliasMap) - env := map[string]string{ - "root": os.Getenv("DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE"), - "snapshot": os.Getenv("DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE"), - "targets": os.Getenv("DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE"), - } - - // Backwards compatibility with old env names. We should remove this in 1.10 - if env["root"] == "" { - if passphrase := os.Getenv("DOCKER_CONTENT_TRUST_OFFLINE_PASSPHRASE"); passphrase != "" { - env["root"] = passphrase - fmt.Fprintf(cli.err, "[DEPRECATED] The environment variable DOCKER_CONTENT_TRUST_OFFLINE_PASSPHRASE has been deprecated and will be removed in v1.10. Please use DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE\n") - } - } - if env["snapshot"] == "" || env["targets"] == "" { - if passphrase := os.Getenv("DOCKER_CONTENT_TRUST_TAGGING_PASSPHRASE"); passphrase != "" { - env["snapshot"] = passphrase - env["targets"] = passphrase - fmt.Fprintf(cli.err, "[DEPRECATED] The environment variable DOCKER_CONTENT_TRUST_TAGGING_PASSPHRASE has been deprecated and will be removed in v1.10. Please use DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE\n") - } - } - - return func(keyName string, alias string, createNew bool, numAttempts int) (string, bool, error) { - if v := env[alias]; v != "" { - return v, numAttempts > 1, nil - } - return baseRetriever(keyName, alias, createNew, numAttempts) - } -} - -func (cli *DockerCli) trustedReference(repo string, ref registry.Reference) (registry.Reference, error) { - repoInfo, err := registry.ParseRepositoryInfo(repo) - if err != nil { - return nil, err - } - - // Resolve the Auth config relevant for this server - authConfig := registry.ResolveAuthConfig(cli.configFile, repoInfo.Index) - - notaryRepo, err := cli.getNotaryRepository(repoInfo, authConfig) - if err != nil { - fmt.Fprintf(cli.out, "Error establishing connection to trust repository: %s\n", err) - return nil, err - } - - t, err := notaryRepo.GetTargetByName(ref.String()) - if err != nil { - return nil, err - } - r, err := convertTarget(*t) - if err != nil { - return nil, err - - } - - return registry.DigestReference(r.digest), nil -} - -func (cli *DockerCli) tagTrusted(repoInfo *registry.RepositoryInfo, trustedRef, ref registry.Reference) error { - fullName := trustedRef.ImageName(repoInfo.LocalName) - fmt.Fprintf(cli.out, "Tagging %s as %s\n", fullName, ref.ImageName(repoInfo.LocalName)) - tv := url.Values{} - tv.Set("repo", repoInfo.LocalName) - tv.Set("tag", ref.String()) - tv.Set("force", "1") - - if _, _, err := readBody(cli.call("POST", "/images/"+fullName+"/tag?"+tv.Encode(), nil, nil)); err != nil { - return err - } - - return nil -} - -func notaryError(err error) error { - switch err.(type) { - case *json.SyntaxError: - logrus.Debugf("Notary syntax error: %s", err) - return errors.New("no trust data available for remote repository") - case client.ErrExpired: - return fmt.Errorf("remote repository out-of-date: %v", err) - case trustmanager.ErrKeyNotFound: - return fmt.Errorf("signing keys not found: %v", err) - case *net.OpError: - return fmt.Errorf("error contacting notary server: %v", err) - } - - return err -} - -func (cli *DockerCli) trustedPull(repoInfo *registry.RepositoryInfo, ref registry.Reference, authConfig cliconfig.AuthConfig) error { - var ( - v = url.Values{} - refs = []target{} - ) - - notaryRepo, err := cli.getNotaryRepository(repoInfo, authConfig) - if err != nil { - fmt.Fprintf(cli.out, "Error establishing connection to trust repository: %s\n", err) - return err - } - - if ref.String() == "" { - // List all targets - targets, err := notaryRepo.ListTargets() - if err != nil { - return notaryError(err) - } - for _, tgt := range targets { - t, err := convertTarget(*tgt) - if err != nil { - fmt.Fprintf(cli.out, "Skipping target for %q\n", repoInfo.LocalName) - continue - } - refs = append(refs, t) - } - } else { - t, err := notaryRepo.GetTargetByName(ref.String()) - if err != nil { - return notaryError(err) - } - r, err := convertTarget(*t) - if err != nil { - return err - - } - refs = append(refs, r) - } - - v.Set("fromImage", repoInfo.LocalName) - for i, r := range refs { - displayTag := r.reference.String() - if displayTag != "" { - displayTag = ":" + displayTag - } - fmt.Fprintf(cli.out, "Pull (%d of %d): %s%s@%s\n", i+1, len(refs), repoInfo.LocalName, displayTag, r.digest) - v.Set("tag", r.digest.String()) - - _, _, err = cli.clientRequestAttemptLogin("POST", "/images/create?"+v.Encode(), nil, cli.out, repoInfo.Index, "pull") - if err != nil { - return err - } - - // If reference is not trusted, tag by trusted reference - if !r.reference.HasDigest() { - if err := cli.tagTrusted(repoInfo, registry.DigestReference(r.digest), r.reference); err != nil { - return err - - } - } - } - return nil -} - -func selectKey(keys map[string]string) string { - if len(keys) == 0 { - return "" - } - - keyIDs := []string{} - for k := range keys { - keyIDs = append(keyIDs, k) - } - - // TODO(dmcgowan): let user choose if multiple keys, now pick consistently - sort.Strings(keyIDs) - - return keyIDs[0] -} - -func targetStream(in io.Writer) (io.WriteCloser, <-chan []target) { - r, w := io.Pipe() - out := io.MultiWriter(in, w) - targetChan := make(chan []target) - - go func() { - targets := []target{} - scanner := bufio.NewScanner(r) - scanner.Split(ansiescape.ScanANSILines) - for scanner.Scan() { - line := scanner.Bytes() - if matches := targetRegexp.FindSubmatch(line); len(matches) == 4 { - dgst, err := digest.ParseDigest(string(matches[2])) - if err != nil { - // Line does match what is expected, continue looking for valid lines - logrus.Debugf("Bad digest value %q in matched line, ignoring\n", string(matches[2])) - continue - } - s, err := strconv.ParseInt(string(matches[3]), 10, 64) - if err != nil { - // Line does match what is expected, continue looking for valid lines - logrus.Debugf("Bad size value %q in matched line, ignoring\n", string(matches[3])) - continue - } - - targets = append(targets, target{ - reference: registry.ParseReference(string(matches[1])), - digest: dgst, - size: s, - }) - } - } - targetChan <- targets - }() - - return ioutils.NewWriteCloserWrapper(out, w.Close), targetChan -} - -func (cli *DockerCli) trustedPush(repoInfo *registry.RepositoryInfo, tag string, authConfig cliconfig.AuthConfig) error { - streamOut, targetChan := targetStream(cli.out) - - v := url.Values{} - v.Set("tag", tag) - - _, _, err := cli.clientRequestAttemptLogin("POST", "/images/"+repoInfo.LocalName+"/push?"+v.Encode(), nil, streamOut, repoInfo.Index, "push") - // Close stream channel to finish target parsing - if err := streamOut.Close(); err != nil { - return err - } - // Check error from request - if err != nil { - return err - } - - // Get target results - targets := <-targetChan - - if tag == "" { - fmt.Fprintf(cli.out, "No tag specified, skipping trust metadata push\n") - return nil - } - if len(targets) == 0 { - fmt.Fprintf(cli.out, "No targets found, skipping trust metadata push\n") - return nil - } - - fmt.Fprintf(cli.out, "Signing and pushing trust metadata\n") - - repo, err := cli.getNotaryRepository(repoInfo, authConfig) - if err != nil { - fmt.Fprintf(cli.out, "Error establishing connection to notary repository: %s\n", err) - return err - } - - for _, target := range targets { - h, err := hex.DecodeString(target.digest.Hex()) - if err != nil { - return err - } - t := &client.Target{ - Name: target.reference.String(), - Hashes: data.Hashes{ - string(target.digest.Algorithm()): h, - }, - Length: int64(target.size), - } - if err := repo.AddTarget(t); err != nil { - return err - } - } - - err = repo.Publish() - if _, ok := err.(*client.ErrRepoNotInitialized); !ok { - return notaryError(err) - } - - ks := repo.KeyStoreManager - keys := ks.RootKeyStore().ListKeys() - - rootKey := selectKey(keys) - if rootKey == "" { - rootKey, err = ks.GenRootKey("ecdsa") - if err != nil { - return err - } - } - - cryptoService, err := ks.GetRootCryptoService(rootKey) - if err != nil { - return err - } - - if err := repo.Initialize(cryptoService); err != nil { - return notaryError(err) - } - fmt.Fprintf(cli.out, "Finished initializing %q\n", repoInfo.CanonicalName) - - return notaryError(repo.Publish()) -} diff --git a/vendor/github.com/docker/docker/api/client/trust_test.go b/vendor/github.com/docker/docker/api/client/trust_test.go deleted file mode 100644 index af198de2..00000000 --- a/vendor/github.com/docker/docker/api/client/trust_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package client - -import ( - "os" - "testing" - - "github.com/docker/docker/registry" -) - -func unsetENV() { - os.Unsetenv("DOCKER_CONTENT_TRUST") - os.Unsetenv("DOCKER_CONTENT_TRUST_SERVER") -} - -func TestENVTrustServer(t *testing.T) { - defer unsetENV() - indexInfo := ®istry.IndexInfo{Name: "testserver"} - if err := os.Setenv("DOCKER_CONTENT_TRUST_SERVER", "https://notary-test.com:5000"); err != nil { - t.Fatal("Failed to set ENV variable") - } - output, err := trustServer(indexInfo) - expectedStr := "https://notary-test.com:5000" - if err != nil || output != expectedStr { - t.Fatalf("Expected server to be %s, got %s", expectedStr, output) - } -} - -func TestHTTPENVTrustServer(t *testing.T) { - defer unsetENV() - indexInfo := ®istry.IndexInfo{Name: "testserver"} - if err := os.Setenv("DOCKER_CONTENT_TRUST_SERVER", "http://notary-test.com:5000"); err != nil { - t.Fatal("Failed to set ENV variable") - } - _, err := trustServer(indexInfo) - if err == nil { - t.Fatal("Expected error with invalid scheme") - } -} - -func TestOfficialTrustServer(t *testing.T) { - indexInfo := ®istry.IndexInfo{Name: "testserver", Official: true} - output, err := trustServer(indexInfo) - if err != nil || output != registry.NotaryServer { - t.Fatalf("Expected server to be %s, got %s", registry.NotaryServer, output) - } -} - -func TestNonOfficialTrustServer(t *testing.T) { - indexInfo := ®istry.IndexInfo{Name: "testserver", Official: false} - output, err := trustServer(indexInfo) - expectedStr := "https://" + indexInfo.Name - if err != nil || output != expectedStr { - t.Fatalf("Expected server to be %s, got %s", expectedStr, output) - } -} diff --git a/vendor/github.com/docker/docker/api/client/unpause.go b/vendor/github.com/docker/docker/api/client/unpause.go deleted file mode 100644 index 21e25857..00000000 --- a/vendor/github.com/docker/docker/api/client/unpause.go +++ /dev/null @@ -1,32 +0,0 @@ -package client - -import ( - "fmt" - - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" -) - -// CmdUnpause unpauses all processes within a container, for one or more containers. -// -// Usage: docker unpause CONTAINER [CONTAINER...] -func (cli *DockerCli) CmdUnpause(args ...string) error { - cmd := Cli.Subcmd("unpause", []string{"CONTAINER [CONTAINER...]"}, Cli.DockerCommands["unpause"].Description, true) - cmd.Require(flag.Min, 1) - - cmd.ParseFlags(args, true) - - var errNames []string - for _, name := range cmd.Args() { - if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/unpause", name), nil, nil)); err != nil { - fmt.Fprintf(cli.err, "%s\n", err) - errNames = append(errNames, name) - } else { - fmt.Fprintf(cli.out, "%s\n", name) - } - } - if len(errNames) > 0 { - return fmt.Errorf("Error: failed to unpause containers: %v", errNames) - } - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/utils.go b/vendor/github.com/docker/docker/api/client/utils.go deleted file mode 100644 index 7a8a7858..00000000 --- a/vendor/github.com/docker/docker/api/client/utils.go +++ /dev/null @@ -1,384 +0,0 @@ -package client - -import ( - "bytes" - "encoding/base64" - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "os" - gosignal "os/signal" - "runtime" - "strconv" - "strings" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/api" - "github.com/docker/docker/api/types" - "github.com/docker/docker/cliconfig" - "github.com/docker/docker/dockerversion" - "github.com/docker/docker/pkg/jsonmessage" - "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 ( - errConnectionFailed = errors.New("Cannot connect to the Docker daemon. Is the docker daemon running on this host?") -) - -type serverResponse struct { - body io.ReadCloser - header http.Header - statusCode int -} - -// HTTPClient creates a new HTTP client with the cli's client transport instance. -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 err := json.NewEncoder(params).Encode(data); err != nil { - return nil, err - } - } - return params, nil -} - -func (cli *DockerCli) clientRequest(method, path string, in io.Reader, headers map[string][]string) (*serverResponse, error) { - - serverResp := &serverResponse{ - body: nil, - statusCode: -1, - } - - expectedPayload := (method == "POST" || method == "PUT") - if expectedPayload && in == nil { - in = bytes.NewReader([]byte{}) - } - req, err := http.NewRequest(method, fmt.Sprintf("%s/v%s%s", cli.basePath, api.Version, path), in) - if err != nil { - return serverResp, err - } - - // Add CLI Config's HTTP Headers BEFORE we set the Docker headers - // then the user can't change OUR headers - for k, v := range cli.configFile.HTTPHeaders { - req.Header.Set(k, v) - } - - req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.Version+" ("+runtime.GOOS+")") - req.URL.Host = cli.addr - req.URL.Scheme = cli.scheme - - if headers != nil { - for k, v := range headers { - req.Header[k] = v - } - } - - if expectedPayload && req.Header.Get("Content-Type") == "" { - req.Header.Set("Content-Type", "text/plain") - } - - resp, err := cli.HTTPClient().Do(req) - if resp != nil { - serverResp.statusCode = resp.StatusCode - } - - if err != nil { - if utils.IsTimeout(err) || strings.Contains(err.Error(), "connection refused") || strings.Contains(err.Error(), "dial unix") { - return serverResp, errConnectionFailed - } - - if cli.tlsConfig == nil && strings.Contains(err.Error(), "malformed HTTP response") { - return serverResp, fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err) - } - if cli.tlsConfig != nil && strings.Contains(err.Error(), "remote error: bad certificate") { - return serverResp, fmt.Errorf("The server probably has client authentication (--tlsverify) enabled. Please check your TLS client certification settings: %v", err) - } - - return serverResp, fmt.Errorf("An error occurred trying to connect: %v", err) - } - - if serverResp.statusCode < 200 || serverResp.statusCode >= 400 { - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return serverResp, err - } - if len(body) == 0 { - return serverResp, fmt.Errorf("Error: request returned %s for API route and version %s, check if the server supports the requested API version", http.StatusText(serverResp.statusCode), req.URL) - } - return serverResp, fmt.Errorf("Error response from daemon: %s", bytes.TrimSpace(body)) - } - - serverResp.body = resp.Body - serverResp.header = resp.Header - return serverResp, nil -} - -// cmdAttempt builds the corresponding registry Auth Header from the given -// authConfig. It returns the servers body, status, error response -func (cli *DockerCli) cmdAttempt(authConfig cliconfig.AuthConfig, method, path string, in io.Reader, out io.Writer) (io.ReadCloser, int, error) { - buf, err := json.Marshal(authConfig) - if err != nil { - return nil, -1, err - } - registryAuthHeader := []string{ - base64.URLEncoding.EncodeToString(buf), - } - - // begin the request - serverResp, err := cli.clientRequest(method, path, in, map[string][]string{ - "X-Registry-Auth": registryAuthHeader, - }) - if err == nil && out != nil { - // If we are streaming output, complete the stream since - // errors may not appear until later. - err = cli.streamBody(serverResp.body, serverResp.header.Get("Content-Type"), true, out, nil) - } - if err != nil { - // Since errors in a stream appear after status 200 has been written, - // we may need to change the status code. - if strings.Contains(err.Error(), "Authentication is required") || - strings.Contains(err.Error(), "Status 401") || - strings.Contains(err.Error(), "401 Unauthorized") || - strings.Contains(err.Error(), "status code 401") { - serverResp.statusCode = http.StatusUnauthorized - } - } - return serverResp.body, serverResp.statusCode, err -} - -func (cli *DockerCli) clientRequestAttemptLogin(method, path string, in io.Reader, out io.Writer, index *registry.IndexInfo, cmdName string) (io.ReadCloser, int, error) { - - // Resolve the Auth config relevant for this server - authConfig := registry.ResolveAuthConfig(cli.configFile, index) - body, statusCode, err := cli.cmdAttempt(authConfig, method, path, in, out) - if statusCode == http.StatusUnauthorized { - fmt.Fprintf(cli.out, "\nPlease login prior to %s:\n", cmdName) - if err = cli.CmdLogin(index.GetAuthConfigKey()); err != nil { - return nil, -1, err - } - authConfig = registry.ResolveAuthConfig(cli.configFile, index) - return cli.cmdAttempt(authConfig, method, path, in, out) - } - return body, statusCode, err -} - -func (cli *DockerCli) callWrapper(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, http.Header, int, error) { - sr, err := cli.call(method, path, data, headers) - return sr.body, sr.header, sr.statusCode, err -} - -func (cli *DockerCli) call(method, path string, data interface{}, headers map[string][]string) (*serverResponse, error) { - params, err := cli.encodeData(data) - if err != nil { - sr := &serverResponse{ - body: nil, - header: nil, - statusCode: -1, - } - return sr, nil - } - - if data != nil { - if headers == nil { - headers = make(map[string][]string) - } - headers["Content-Type"] = []string{"application/json"} - } - - serverResp, err := cli.clientRequest(method, path, params, headers) - return serverResp, err -} - -type streamOpts struct { - rawTerminal bool - in io.Reader - out io.Writer - err io.Writer - headers map[string][]string -} - -func (cli *DockerCli) stream(method, path string, opts *streamOpts) (*serverResponse, error) { - serverResp, err := cli.clientRequest(method, path, opts.in, opts.headers) - if err != nil { - return serverResp, err - } - return serverResp, cli.streamBody(serverResp.body, serverResp.header.Get("Content-Type"), opts.rawTerminal, opts.out, opts.err) -} - -func (cli *DockerCli) streamBody(body io.ReadCloser, contentType string, rawTerminal bool, stdout, stderr io.Writer) error { - defer body.Close() - - if api.MatchesContentType(contentType, "application/json") { - return jsonmessage.DisplayJSONMessagesStream(body, stdout, cli.outFd, cli.isTerminalOut) - } - if stdout != nil || stderr != nil { - // When TTY is ON, use regular copy - var err error - if rawTerminal { - _, err = io.Copy(stdout, body) - } else { - _, err = stdcopy.StdCopy(stdout, stderr, body) - } - logrus.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, nil)); err != nil { - logrus.Debugf("Error resize: %s", err) - } -} - -func waitForExit(cli *DockerCli, containerID string) (int, error) { - serverResp, err := cli.call("POST", "/containers/"+containerID+"/wait", nil, nil) - if err != nil { - return -1, err - } - - defer serverResp.body.Close() - - var res types.ContainerWaitResponse - if err := json.NewDecoder(serverResp.body).Decode(&res); err != nil { - return -1, err - } - - return res.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) { - serverResp, err := cli.call("GET", "/containers/"+containerID+"/json", nil, nil) - if err != nil { - // If we can't connect, then the daemon probably died. - if err != errConnectionFailed { - return false, -1, err - } - return false, -1, nil - } - - defer serverResp.body.Close() - - var c types.ContainerJSON - if err := json.NewDecoder(serverResp.body).Decode(&c); err != nil { - return false, -1, err - } - - return c.State.Running, c.State.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) { - serverResp, err := cli.call("GET", "/exec/"+execID+"/json", nil, nil) - if err != nil { - // If we can't connect, then the daemon probably died. - if err != errConnectionFailed { - return false, -1, err - } - return false, -1, nil - } - - defer serverResp.body.Close() - - //TODO: Should we reconsider having a type in api/types? - //this is a response to exex/id/json not container - var c struct { - Running bool - ExitCode int - } - - if err := json.NewDecoder(serverResp.body).Decode(&c); err != nil { - return false, -1, err - } - - return c.Running, c.ExitCode, nil -} - -func (cli *DockerCli) monitorTtySize(id string, isExec bool) error { - cli.resizeTty(id, isExec) - - if runtime.GOOS == "windows" { - go func() { - prevH, prevW := cli.getTtySize() - for { - time.Sleep(time.Millisecond * 250) - h, w := cli.getTtySize() - - if prevW != w || prevH != h { - cli.resizeTty(id, isExec) - } - prevH = h - prevW = w - } - }() - } else { - 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 { - logrus.Debugf("Error getting size: %s", err) - if ws == nil { - return 0, 0 - } - } - return int(ws.Height), int(ws.Width) -} - -func readBody(serverResp *serverResponse, err error) ([]byte, int, error) { - if serverResp.body != nil { - defer serverResp.body.Close() - } - if err != nil { - return nil, serverResp.statusCode, err - } - body, err := ioutil.ReadAll(serverResp.body) - if err != nil { - return nil, -1, err - } - return body, serverResp.statusCode, nil -} diff --git a/vendor/github.com/docker/docker/api/client/version.go b/vendor/github.com/docker/docker/api/client/version.go deleted file mode 100644 index e14e0cab..00000000 --- a/vendor/github.com/docker/docker/api/client/version.go +++ /dev/null @@ -1,96 +0,0 @@ -package client - -import ( - "encoding/json" - "runtime" - "text/template" - - "github.com/docker/docker/api" - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - "github.com/docker/docker/dockerversion" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/utils" -) - -var versionTemplate = `Client: - Version: {{.Client.Version}} - API version: {{.Client.APIVersion}} - Go version: {{.Client.GoVersion}} - Git commit: {{.Client.GitCommit}} - Built: {{.Client.BuildTime}} - OS/Arch: {{.Client.Os}}/{{.Client.Arch}}{{if .Client.Experimental}} - Experimental: {{.Client.Experimental}}{{end}}{{if .ServerOK}} - -Server: - Version: {{.Server.Version}} - API version: {{.Server.APIVersion}} - Go version: {{.Server.GoVersion}} - Git commit: {{.Server.GitCommit}} - Built: {{.Server.BuildTime}} - OS/Arch: {{.Server.Os}}/{{.Server.Arch}}{{if .Server.Experimental}} - Experimental: {{.Server.Experimental}}{{end}}{{end}}` - -type versionData struct { - Client types.Version - ServerOK bool - Server types.Version -} - -// CmdVersion shows Docker version information. -// -// Available version information is shown for: client Docker version, client API version, client Go version, client Git commit, client OS/Arch, server Docker version, server API version, server Go version, server Git commit, and server OS/Arch. -// -// Usage: docker version -func (cli *DockerCli) CmdVersion(args ...string) (err error) { - cmd := Cli.Subcmd("version", nil, Cli.DockerCommands["version"].Description, true) - tmplStr := cmd.String([]string{"f", "#format", "-format"}, "", "Format the output using the given go template") - cmd.Require(flag.Exact, 0) - - cmd.ParseFlags(args, true) - if *tmplStr == "" { - *tmplStr = versionTemplate - } - - var tmpl *template.Template - if tmpl, err = template.New("").Funcs(funcMap).Parse(*tmplStr); err != nil { - return Cli.StatusError{StatusCode: 64, - Status: "Template parsing error: " + err.Error()} - } - - vd := versionData{ - Client: types.Version{ - Version: dockerversion.Version, - APIVersion: api.Version, - GoVersion: runtime.Version(), - GitCommit: dockerversion.GitCommit, - BuildTime: dockerversion.BuildTime, - Os: runtime.GOOS, - Arch: runtime.GOARCH, - Experimental: utils.ExperimentalBuild(), - }, - } - - defer func() { - if err2 := tmpl.Execute(cli.out, vd); err2 != nil && err == nil { - err = err2 - } - cli.out.Write([]byte{'\n'}) - }() - - serverResp, err := cli.call("GET", "/version", nil, nil) - if err != nil { - return err - } - - defer serverResp.body.Close() - - if err = json.NewDecoder(serverResp.body).Decode(&vd.Server); err != nil { - return Cli.StatusError{StatusCode: 1, - Status: "Error reading remote version: " + err.Error()} - } - - vd.ServerOK = true - - return -} diff --git a/vendor/github.com/docker/docker/api/client/volume.go b/vendor/github.com/docker/docker/api/client/volume.go deleted file mode 100644 index 1dc0ea2d..00000000 --- a/vendor/github.com/docker/docker/api/client/volume.go +++ /dev/null @@ -1,234 +0,0 @@ -package client - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "net/url" - "text/tabwriter" - "text/template" - - "github.com/docker/docker/api/types" - Cli "github.com/docker/docker/cli" - "github.com/docker/docker/opts" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/parsers/filters" -) - -// CmdVolume is the parent subcommand for all volume commands -// -// Usage: docker volume -func (cli *DockerCli) CmdVolume(args ...string) error { - description := Cli.DockerCommands["volume"].Description + "\n\nCommands:\n" - commands := [][]string{ - {"create", "Create a volume"}, - {"inspect", "Return low-level information on a volume"}, - {"ls", "List volumes"}, - {"rm", "Remove a volume"}, - } - - for _, cmd := range commands { - description += fmt.Sprintf(" %-25.25s%s\n", cmd[0], cmd[1]) - } - - description += "\nRun 'docker volume COMMAND --help' for more information on a command" - cmd := Cli.Subcmd("volume", []string{"[COMMAND]"}, description, false) - - cmd.Require(flag.Exact, 0) - err := cmd.ParseFlags(args, true) - cmd.Usage() - return err -} - -// CmdVolumeLs outputs a list of Docker volumes. -// -// Usage: docker volume ls [OPTIONS] -func (cli *DockerCli) CmdVolumeLs(args ...string) error { - cmd := Cli.Subcmd("volume ls", nil, "List volumes", true) - - quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only display volume names") - flFilter := opts.NewListOpts(nil) - cmd.Var(&flFilter, []string{"f", "-filter"}, "Provide filter values (i.e. 'dangling=true')") - - cmd.Require(flag.Exact, 0) - cmd.ParseFlags(args, true) - - volFilterArgs := filters.Args{} - for _, f := range flFilter.GetAll() { - var err error - volFilterArgs, err = filters.ParseFlag(f, volFilterArgs) - if err != nil { - return err - } - } - - v := url.Values{} - if len(volFilterArgs) > 0 { - filterJSON, err := filters.ToParam(volFilterArgs) - if err != nil { - return err - } - v.Set("filters", filterJSON) - } - - resp, err := cli.call("GET", "/volumes?"+v.Encode(), nil, nil) - if err != nil { - return err - } - - var volumes types.VolumesListResponse - if err := json.NewDecoder(resp.body).Decode(&volumes); err != nil { - return err - } - - w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) - if !*quiet { - fmt.Fprintf(w, "DRIVER \tVOLUME NAME") - fmt.Fprintf(w, "\n") - } - - for _, vol := range volumes.Volumes { - if *quiet { - fmt.Fprintln(w, vol.Name) - continue - } - fmt.Fprintf(w, "%s\t%s\n", vol.Driver, vol.Name) - } - w.Flush() - return nil -} - -// CmdVolumeInspect displays low-level information on one or more volumes. -// -// Usage: docker volume inspect [OPTIONS] VOLUME [VOLUME...] -func (cli *DockerCli) CmdVolumeInspect(args ...string) error { - cmd := Cli.Subcmd("volume inspect", []string{"VOLUME [VOLUME...]"}, "Return low-level information on a volume", true) - tmplStr := cmd.String([]string{"f", "-format"}, "", "Format the output using the given go template") - - cmd.Require(flag.Min, 1) - cmd.ParseFlags(args, true) - - if err := cmd.Parse(args); err != nil { - return nil - } - - var tmpl *template.Template - if *tmplStr != "" { - var err error - tmpl, err = template.New("").Funcs(funcMap).Parse(*tmplStr) - if err != nil { - return err - } - } - - var status = 0 - var volumes []*types.Volume - for _, name := range cmd.Args() { - resp, err := cli.call("GET", "/volumes/"+name, nil, nil) - if err != nil { - return err - } - - var volume types.Volume - if err := json.NewDecoder(resp.body).Decode(&volume); err != nil { - fmt.Fprintf(cli.err, "%s\n", err) - status = 1 - continue - } - - if tmpl == nil { - volumes = append(volumes, &volume) - continue - } - - if err := tmpl.Execute(cli.out, &volume); err != nil { - if err := tmpl.Execute(cli.out, &volume); err != nil { - fmt.Fprintf(cli.err, "%s\n", err) - status = 1 - continue - } - } - io.WriteString(cli.out, "\n") - } - - if tmpl != nil { - return nil - } - - b, err := json.MarshalIndent(volumes, "", " ") - if err != nil { - return err - } - _, err = io.Copy(cli.out, bytes.NewReader(b)) - if err != nil { - return err - } - io.WriteString(cli.out, "\n") - - if status != 0 { - return Cli.StatusError{StatusCode: status} - } - return nil -} - -// CmdVolumeCreate creates a new container from a given image. -// -// Usage: docker volume create [OPTIONS] -func (cli *DockerCli) CmdVolumeCreate(args ...string) error { - cmd := Cli.Subcmd("volume create", nil, "Create a volume", true) - flDriver := cmd.String([]string{"d", "-driver"}, "local", "Specify volume driver name") - flName := cmd.String([]string{"-name"}, "", "Specify volume name") - - flDriverOpts := opts.NewMapOpts(nil, nil) - cmd.Var(flDriverOpts, []string{"o", "-opt"}, "Set driver specific options") - - cmd.Require(flag.Exact, 0) - cmd.ParseFlags(args, true) - - volReq := &types.VolumeCreateRequest{ - Driver: *flDriver, - DriverOpts: flDriverOpts.GetAll(), - } - - if *flName != "" { - volReq.Name = *flName - } - - resp, err := cli.call("POST", "/volumes/create", volReq, nil) - if err != nil { - return err - } - - var vol types.Volume - if err := json.NewDecoder(resp.body).Decode(&vol); err != nil { - return err - } - fmt.Fprintf(cli.out, "%s\n", vol.Name) - return nil -} - -// CmdVolumeRm removes one or more containers. -// -// Usage: docker volume rm VOLUME [VOLUME...] -func (cli *DockerCli) CmdVolumeRm(args ...string) error { - cmd := Cli.Subcmd("volume rm", []string{"VOLUME [VOLUME...]"}, "Remove a volume", true) - cmd.Require(flag.Min, 1) - cmd.ParseFlags(args, true) - - var status = 0 - for _, name := range cmd.Args() { - _, err := cli.call("DELETE", "/volumes/"+name, nil, nil) - if err != nil { - fmt.Fprintf(cli.err, "%s\n", err) - status = 1 - continue - } - fmt.Fprintf(cli.out, "%s\n", name) - } - - if status != 0 { - return Cli.StatusError{StatusCode: status} - } - return nil -} diff --git a/vendor/github.com/docker/docker/api/client/wait.go b/vendor/github.com/docker/docker/api/client/wait.go deleted file mode 100644 index 3b03f706..00000000 --- a/vendor/github.com/docker/docker/api/client/wait.go +++ /dev/null @@ -1,35 +0,0 @@ -package client - -import ( - "fmt" - - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" -) - -// CmdWait blocks until a container stops, then prints its exit code. -// -// If more than one container is specified, this will wait synchronously on each container. -// -// Usage: docker wait CONTAINER [CONTAINER...] -func (cli *DockerCli) CmdWait(args ...string) error { - cmd := Cli.Subcmd("wait", []string{"CONTAINER [CONTAINER...]"}, Cli.DockerCommands["wait"].Description, true) - cmd.Require(flag.Min, 1) - - cmd.ParseFlags(args, true) - - var errNames []string - for _, name := range cmd.Args() { - status, err := waitForExit(cli, name) - if err != nil { - fmt.Fprintf(cli.err, "%s\n", err) - errNames = append(errNames, name) - } else { - fmt.Fprintf(cli.out, "%d\n", status) - } - } - if len(errNames) > 0 { - return fmt.Errorf("Error: failed to wait containers: %v", errNames) - } - return nil -} diff --git a/vendor/github.com/docker/docker/api/common.go b/vendor/github.com/docker/docker/api/common.go deleted file mode 100644 index 3a845028..00000000 --- a/vendor/github.com/docker/docker/api/common.go +++ /dev/null @@ -1,145 +0,0 @@ -package api - -import ( - "fmt" - "mime" - "path/filepath" - "sort" - "strconv" - "strings" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/system" - "github.com/docker/docker/pkg/version" - "github.com/docker/libtrust" -) - -// Common constants for daemon and client. -const ( - // Version of Current REST API - Version version.Version = "1.22" - - // MinVersion represents Minimun REST API version supported - MinVersion version.Version = "1.12" - - // DefaultDockerfileName is the Default filename with Docker commands, read by docker build - DefaultDockerfileName string = "Dockerfile" -) - -// byPortInfo is a temporary type used to sort types.Port by its fields -type byPortInfo []types.Port - -func (r byPortInfo) Len() int { return len(r) } -func (r byPortInfo) Swap(i, j int) { r[i], r[j] = r[j], r[i] } -func (r byPortInfo) Less(i, j int) bool { - if r[i].PrivatePort != r[j].PrivatePort { - return r[i].PrivatePort < r[j].PrivatePort - } - - if r[i].IP != r[j].IP { - return r[i].IP < r[j].IP - } - - if r[i].PublicPort != r[j].PublicPort { - return r[i].PublicPort < r[j].PublicPort - } - - return r[i].Type < r[j].Type -} - -// DisplayablePorts returns formatted string representing open ports of container -// e.g. "0.0.0.0:80->9090/tcp, 9988/tcp" -// it's used by command 'docker ps' -func DisplayablePorts(ports []types.Port) string { - type portGroup struct { - first int - last int - } - groupMap := make(map[string]*portGroup) - var result []string - var hostMappings []string - var groupMapKeys []string - sort.Sort(byPortInfo(ports)) - for _, port := range ports { - current := port.PrivatePort - portKey := port.Type - if port.IP != "" { - if port.PublicPort != current { - hostMappings = append(hostMappings, fmt.Sprintf("%s:%d->%d/%s", port.IP, port.PublicPort, port.PrivatePort, port.Type)) - continue - } - portKey = fmt.Sprintf("%s/%s", port.IP, port.Type) - } - group := groupMap[portKey] - - if group == nil { - groupMap[portKey] = &portGroup{first: current, last: current} - // record order that groupMap keys are created - groupMapKeys = append(groupMapKeys, portKey) - continue - } - if current == (group.last + 1) { - group.last = current - continue - } - - result = append(result, formGroup(portKey, group.first, group.last)) - groupMap[portKey] = &portGroup{first: current, last: current} - } - for _, portKey := range groupMapKeys { - g := groupMap[portKey] - result = append(result, formGroup(portKey, g.first, g.last)) - } - result = append(result, hostMappings...) - return strings.Join(result, ", ") -} - -func formGroup(key string, start, last int) string { - parts := strings.Split(key, "/") - groupType := parts[0] - var ip string - if len(parts) > 1 { - ip = parts[0] - groupType = parts[1] - } - group := strconv.Itoa(start) - if start != last { - group = fmt.Sprintf("%s-%d", group, last) - } - if ip != "" { - group = fmt.Sprintf("%s:%s->%s", ip, group, group) - } - return fmt.Sprintf("%s/%s", group, groupType) -} - -// MatchesContentType validates the content type against the expected one -func MatchesContentType(contentType, expectedType string) bool { - mimetype, _, err := mime.ParseMediaType(contentType) - if err != nil { - logrus.Errorf("Error parsing media type: %s error: %v", contentType, err) - } - 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 := system.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/vendor/github.com/docker/docker/api/common_test.go b/vendor/github.com/docker/docker/api/common_test.go deleted file mode 100644 index aa30099d..00000000 --- a/vendor/github.com/docker/docker/api/common_test.go +++ /dev/null @@ -1,340 +0,0 @@ -package api - -import ( - "io/ioutil" - "path/filepath" - "testing" - - "github.com/docker/docker/api/types" - "os" -) - -type ports struct { - ports []types.Port - expected string -} - -// DisplayablePorts -func TestDisplayablePorts(t *testing.T) { - cases := []ports{ - { - []types.Port{ - { - PrivatePort: 9988, - Type: "tcp", - }, - }, - "9988/tcp"}, - { - []types.Port{ - { - PrivatePort: 9988, - Type: "udp", - }, - }, - "9988/udp", - }, - { - []types.Port{ - { - IP: "0.0.0.0", - PrivatePort: 9988, - Type: "tcp", - }, - }, - "0.0.0.0:0->9988/tcp", - }, - { - []types.Port{ - { - PrivatePort: 9988, - PublicPort: 8899, - Type: "tcp", - }, - }, - "9988/tcp", - }, - { - []types.Port{ - { - IP: "4.3.2.1", - PrivatePort: 9988, - PublicPort: 8899, - Type: "tcp", - }, - }, - "4.3.2.1:8899->9988/tcp", - }, - { - []types.Port{ - { - IP: "4.3.2.1", - PrivatePort: 9988, - PublicPort: 9988, - Type: "tcp", - }, - }, - "4.3.2.1:9988->9988/tcp", - }, - { - []types.Port{ - { - PrivatePort: 9988, - Type: "udp", - }, { - PrivatePort: 9988, - Type: "udp", - }, - }, - "9988/udp, 9988/udp", - }, - { - []types.Port{ - { - IP: "1.2.3.4", - PublicPort: 9998, - PrivatePort: 9998, - Type: "udp", - }, { - IP: "1.2.3.4", - PublicPort: 9999, - PrivatePort: 9999, - Type: "udp", - }, - }, - "1.2.3.4:9998-9999->9998-9999/udp", - }, - { - []types.Port{ - { - IP: "1.2.3.4", - PublicPort: 8887, - PrivatePort: 9998, - Type: "udp", - }, { - IP: "1.2.3.4", - PublicPort: 8888, - PrivatePort: 9999, - Type: "udp", - }, - }, - "1.2.3.4:8887->9998/udp, 1.2.3.4:8888->9999/udp", - }, - { - []types.Port{ - { - PrivatePort: 9998, - Type: "udp", - }, { - PrivatePort: 9999, - Type: "udp", - }, - }, - "9998-9999/udp", - }, - { - []types.Port{ - { - IP: "1.2.3.4", - PrivatePort: 6677, - PublicPort: 7766, - Type: "tcp", - }, { - PrivatePort: 9988, - PublicPort: 8899, - Type: "udp", - }, - }, - "9988/udp, 1.2.3.4:7766->6677/tcp", - }, - { - []types.Port{ - { - IP: "1.2.3.4", - PrivatePort: 9988, - PublicPort: 8899, - Type: "udp", - }, { - IP: "1.2.3.4", - PrivatePort: 9988, - PublicPort: 8899, - Type: "tcp", - }, { - IP: "4.3.2.1", - PrivatePort: 2233, - PublicPort: 3322, - Type: "tcp", - }, - }, - "4.3.2.1:3322->2233/tcp, 1.2.3.4:8899->9988/tcp, 1.2.3.4:8899->9988/udp", - }, - { - []types.Port{ - { - PrivatePort: 9988, - PublicPort: 8899, - Type: "udp", - }, { - IP: "1.2.3.4", - PrivatePort: 6677, - PublicPort: 7766, - Type: "tcp", - }, { - IP: "4.3.2.1", - PrivatePort: 2233, - PublicPort: 3322, - Type: "tcp", - }, - }, - "9988/udp, 4.3.2.1:3322->2233/tcp, 1.2.3.4:7766->6677/tcp", - }, - { - []types.Port{ - { - PrivatePort: 80, - Type: "tcp", - }, { - PrivatePort: 1024, - Type: "tcp", - }, { - PrivatePort: 80, - Type: "udp", - }, { - PrivatePort: 1024, - Type: "udp", - }, { - IP: "1.1.1.1", - PublicPort: 80, - PrivatePort: 1024, - Type: "tcp", - }, { - IP: "1.1.1.1", - PublicPort: 80, - PrivatePort: 1024, - Type: "udp", - }, { - IP: "1.1.1.1", - PublicPort: 1024, - PrivatePort: 80, - Type: "tcp", - }, { - IP: "1.1.1.1", - PublicPort: 1024, - PrivatePort: 80, - Type: "udp", - }, { - IP: "2.1.1.1", - PublicPort: 80, - PrivatePort: 1024, - Type: "tcp", - }, { - IP: "2.1.1.1", - PublicPort: 80, - PrivatePort: 1024, - Type: "udp", - }, { - IP: "2.1.1.1", - PublicPort: 1024, - PrivatePort: 80, - Type: "tcp", - }, { - IP: "2.1.1.1", - PublicPort: 1024, - PrivatePort: 80, - Type: "udp", - }, - }, - "80/tcp, 80/udp, 1024/tcp, 1024/udp, 1.1.1.1:1024->80/tcp, 1.1.1.1:1024->80/udp, 2.1.1.1:1024->80/tcp, 2.1.1.1:1024->80/udp, 1.1.1.1:80->1024/tcp, 1.1.1.1:80->1024/udp, 2.1.1.1:80->1024/tcp, 2.1.1.1:80->1024/udp", - }, - } - - for _, port := range cases { - actual := DisplayablePorts(port.ports) - if port.expected != actual { - t.Fatalf("Expected %s, got %s.", port.expected, actual) - } - } -} - -// MatchesContentType -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() - } -} - -// LoadOrCreateTrustKey -func TestLoadOrCreateTrustKeyInvalidKeyFile(t *testing.T) { - tmpKeyFolderPath, err := ioutil.TempDir("", "api-trustkey-test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpKeyFolderPath) - - tmpKeyFile, err := ioutil.TempFile(tmpKeyFolderPath, "keyfile") - if err != nil { - t.Fatal(err) - } - - if _, err := LoadOrCreateTrustKey(tmpKeyFile.Name()); err == nil { - t.Fatalf("expected an error, got nothing.") - } - -} - -func TestLoadOrCreateTrustKeyCreateKey(t *testing.T) { - tmpKeyFolderPath, err := ioutil.TempDir("", "api-trustkey-test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpKeyFolderPath) - - // Without the need to create the folder hierarchy - tmpKeyFile := filepath.Join(tmpKeyFolderPath, "keyfile") - - if key, err := LoadOrCreateTrustKey(tmpKeyFile); err != nil || key == nil { - t.Fatalf("expected a new key file, got : %v and %v", err, key) - } - - if _, err := os.Stat(tmpKeyFile); err != nil { - t.Fatalf("Expected to find a file %s, got %v", tmpKeyFile, err) - } - - // With the need to create the folder hierarchy as tmpKeyFie is in a path - // where some folder do not exists. - tmpKeyFile = filepath.Join(tmpKeyFolderPath, "folder/hierarchy/keyfile") - - if key, err := LoadOrCreateTrustKey(tmpKeyFile); err != nil || key == nil { - t.Fatalf("expected a new key file, got : %v and %v", err, key) - } - - if _, err := os.Stat(tmpKeyFile); err != nil { - t.Fatalf("Expected to find a file %s, got %v", tmpKeyFile, err) - } - - // With no path at all - defer os.Remove("keyfile") - if key, err := LoadOrCreateTrustKey("keyfile"); err != nil || key == nil { - t.Fatalf("expected a new key file, got : %v and %v", err, key) - } - - if _, err := os.Stat("keyfile"); err != nil { - t.Fatalf("Expected to find a file keyfile, got %v", err) - } -} - -func TestLoadOrCreateTrustKeyLoadValidKey(t *testing.T) { - tmpKeyFile := filepath.Join("fixtures", "keyfile") - - if key, err := LoadOrCreateTrustKey(tmpKeyFile); err != nil || key == nil { - t.Fatalf("expected a key file, got : %v and %v", err, key) - } -} diff --git a/vendor/github.com/docker/docker/api/fixtures/keyfile b/vendor/github.com/docker/docker/api/fixtures/keyfile deleted file mode 100644 index 322f2544..00000000 --- a/vendor/github.com/docker/docker/api/fixtures/keyfile +++ /dev/null @@ -1,7 +0,0 @@ ------BEGIN EC PRIVATE KEY----- -keyID: AWX2:I27X:WQFX:IOMK:CNAK:O7PW:VYNB:ZLKC:CVAE:YJP2:SI4A:XXAY - -MHcCAQEEILHTRWdcpKWsnORxSFyBnndJ4ROU41hMtr/GCiLVvwBQoAoGCCqGSM49 -AwEHoUQDQgAElpVFbQ2V2UQKajqdE3fVxJ+/pE/YuEFOxWbOxF2be19BY209/iky -NzeFFK7SLpQ4CBJ7zDVXOHsMzrkY/GquGA== ------END EC PRIVATE KEY----- diff --git a/vendor/github.com/docker/docker/api/server/httputils/form.go b/vendor/github.com/docker/docker/api/server/httputils/form.go deleted file mode 100644 index 20188c12..00000000 --- a/vendor/github.com/docker/docker/api/server/httputils/form.go +++ /dev/null @@ -1,73 +0,0 @@ -package httputils - -import ( - "fmt" - "net/http" - "path/filepath" - "strconv" - "strings" -) - -// BoolValue transforms a form value in different formats into a boolean type. -func BoolValue(r *http.Request, k string) bool { - s := strings.ToLower(strings.TrimSpace(r.FormValue(k))) - return !(s == "" || s == "0" || s == "no" || s == "false" || s == "none") -} - -// BoolValueOrDefault returns the default bool passed if the query param is -// missing, otherwise it's just a proxy to boolValue above -func BoolValueOrDefault(r *http.Request, k string, d bool) bool { - if _, ok := r.Form[k]; !ok { - return d - } - return BoolValue(r, k) -} - -// Int64ValueOrZero parses a form value into an int64 type. -// It returns 0 if the parsing fails. -func Int64ValueOrZero(r *http.Request, k string) int64 { - val, err := Int64ValueOrDefault(r, k, 0) - if err != nil { - return 0 - } - return val -} - -// Int64ValueOrDefault parses a form value into an int64 type. If there is an -// error, returns the error. If there is no value returns the default value. -func Int64ValueOrDefault(r *http.Request, field string, def int64) (int64, error) { - if r.Form.Get(field) != "" { - value, err := strconv.ParseInt(r.Form.Get(field), 10, 64) - if err != nil { - return value, err - } - return value, nil - } - return def, nil -} - -// ArchiveOptions stores archive information for different operations. -type ArchiveOptions struct { - Name string - Path string -} - -// ArchiveFormValues parses form values and turns them into ArchiveOptions. -// It fails if the archive name and path are not in the request. -func ArchiveFormValues(r *http.Request, vars map[string]string) (ArchiveOptions, error) { - if err := ParseForm(r); err != nil { - return ArchiveOptions{}, err - } - - name := vars["name"] - path := filepath.FromSlash(r.Form.Get("path")) - - switch { - case name == "": - return ArchiveOptions{}, fmt.Errorf("bad parameter: 'name' cannot be empty") - case path == "": - return ArchiveOptions{}, fmt.Errorf("bad parameter: 'path' cannot be empty") - } - - return ArchiveOptions{name, path}, nil -} diff --git a/vendor/github.com/docker/docker/api/server/httputils/form_test.go b/vendor/github.com/docker/docker/api/server/httputils/form_test.go deleted file mode 100644 index c56f7c15..00000000 --- a/vendor/github.com/docker/docker/api/server/httputils/form_test.go +++ /dev/null @@ -1,105 +0,0 @@ -package httputils - -import ( - "net/http" - "net/url" - "testing" -) - -func TestBoolValue(t *testing.T) { - cases := map[string]bool{ - "": false, - "0": false, - "no": false, - "false": false, - "none": false, - "1": true, - "yes": true, - "true": true, - "one": true, - "100": true, - } - - for c, e := range cases { - v := url.Values{} - v.Set("test", c) - r, _ := http.NewRequest("POST", "", nil) - r.Form = v - - a := BoolValue(r, "test") - if a != e { - t.Fatalf("Value: %s, expected: %v, actual: %v", c, e, a) - } - } -} - -func TestBoolValueOrDefault(t *testing.T) { - r, _ := http.NewRequest("GET", "", nil) - if !BoolValueOrDefault(r, "queryparam", true) { - t.Fatal("Expected to get true default value, got false") - } - - v := url.Values{} - v.Set("param", "") - r, _ = http.NewRequest("GET", "", nil) - r.Form = v - if BoolValueOrDefault(r, "param", true) { - t.Fatal("Expected not to get true") - } -} - -func TestInt64ValueOrZero(t *testing.T) { - cases := map[string]int64{ - "": 0, - "asdf": 0, - "0": 0, - "1": 1, - } - - for c, e := range cases { - v := url.Values{} - v.Set("test", c) - r, _ := http.NewRequest("POST", "", nil) - r.Form = v - - a := Int64ValueOrZero(r, "test") - if a != e { - t.Fatalf("Value: %s, expected: %v, actual: %v", c, e, a) - } - } -} - -func TestInt64ValueOrDefault(t *testing.T) { - cases := map[string]int64{ - "": -1, - "-1": -1, - "42": 42, - } - - for c, e := range cases { - v := url.Values{} - v.Set("test", c) - r, _ := http.NewRequest("POST", "", nil) - r.Form = v - - a, err := Int64ValueOrDefault(r, "test", -1) - if a != e { - t.Fatalf("Value: %s, expected: %v, actual: %v", c, e, a) - } - if err != nil { - t.Fatalf("Error should be nil, but received: %s", err) - } - } -} - -func TestInt64ValueOrDefaultWithError(t *testing.T) { - v := url.Values{} - v.Set("test", "invalid") - r, _ := http.NewRequest("POST", "", nil) - r.Form = v - - _, err := Int64ValueOrDefault(r, "test", -1) - if err == nil { - t.Fatalf("Expected an error.") - } -} diff --git a/vendor/github.com/docker/docker/api/server/httputils/httputils.go b/vendor/github.com/docker/docker/api/server/httputils/httputils.go deleted file mode 100644 index 2997dc03..00000000 --- a/vendor/github.com/docker/docker/api/server/httputils/httputils.go +++ /dev/null @@ -1,180 +0,0 @@ -package httputils - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "strings" - - "golang.org/x/net/context" - - "github.com/Sirupsen/logrus" - "github.com/docker/distribution/registry/api/errcode" - "github.com/docker/docker/api" - "github.com/docker/docker/pkg/version" - "github.com/docker/docker/utils" -) - -// APIVersionKey is the client's requested API version. -const APIVersionKey = "api-version" - -// APIFunc is an adapter to allow the use of ordinary functions as Docker API endpoints. -// Any function that has the appropriate signature can be register as a API endpoint (e.g. getVersion). -type APIFunc func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error - -// HijackConnection interrupts the http response writer to get the -// underlying connection and operate with it. -func HijackConnection(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 -} - -// CloseStreams ensures that a list for http streams are properly closed. -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() - } - } -} - -// CheckForJSON makes sure that the 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) -} - -// ParseForm ensures the request form is parsed even with invalid content types. -// 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 -} - -// ParseMultipartForm ensure the request form is parsed, even with invalid content types. -func ParseMultipartForm(r *http.Request) error { - if err := r.ParseMultipartForm(4096); err != nil && !strings.HasPrefix(err.Error(), "mime:") { - return err - } - return nil -} - -// WriteError decodes a specific docker error and sends it in the response. -func WriteError(w http.ResponseWriter, err error) { - if err == nil || w == nil { - logrus.WithFields(logrus.Fields{"error": err, "writer": w}).Error("unexpected HTTP error handling") - return - } - - statusCode := http.StatusInternalServerError - errMsg := err.Error() - - // Based on the type of error we get we need to process things - // slightly differently to extract the error message. - // In the 'errcode.*' cases there are two different type of - // error that could be returned. errocode.ErrorCode is the base - // type of error object - it is just an 'int' that can then be - // used as the look-up key to find the message. errorcode.Error - // extends errorcode.Error by adding error-instance specific - // data, like 'details' or variable strings to be inserted into - // the message. - // - // Ideally, we should just be able to call err.Error() for all - // cases but the errcode package doesn't support that yet. - // - // Additionally, in both errcode cases, there might be an http - // status code associated with it, and if so use it. - switch err.(type) { - case errcode.ErrorCode: - daError, _ := err.(errcode.ErrorCode) - statusCode = daError.Descriptor().HTTPStatusCode - errMsg = daError.Message() - - case errcode.Error: - // For reference, if you're looking for a particular error - // then you can do something like : - // import ( derr "github.com/docker/docker/errors" ) - // if daError.ErrorCode() == derr.ErrorCodeNoSuchContainer { ... } - - daError, _ := err.(errcode.Error) - statusCode = daError.ErrorCode().Descriptor().HTTPStatusCode - errMsg = daError.Message - - default: - // This part of will be removed once we've - // converted everything over to use the errcode package - - // 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()) - for keyword, status := range map[string]int{ - "not found": http.StatusNotFound, - "no such": http.StatusNotFound, - "bad parameter": http.StatusBadRequest, - "conflict": http.StatusConflict, - "impossible": http.StatusNotAcceptable, - "wrong login/password": http.StatusUnauthorized, - "hasn't been activated": http.StatusForbidden, - } { - if strings.Contains(errStr, keyword) { - statusCode = status - break - } - } - } - - if statusCode == 0 { - statusCode = http.StatusInternalServerError - } - - logrus.WithFields(logrus.Fields{"statusCode": statusCode, "err": utils.GetErrorMessage(err)}).Error("HTTP Error") - http.Error(w, errMsg, statusCode) -} - -// WriteJSON writes the value v to the http response stream as json with standard json encoding. -func WriteJSON(w http.ResponseWriter, code int, v interface{}) error { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(code) - return json.NewEncoder(w).Encode(v) -} - -// VersionFromContext returns an API version from the context using APIVersionKey. -// It panics if the context value does not have version.Version type. -func VersionFromContext(ctx context.Context) (ver version.Version) { - if ctx == nil { - return - } - val := ctx.Value(APIVersionKey) - if val == nil { - return - } - return val.(version.Version) -} diff --git a/vendor/github.com/docker/docker/api/server/middleware.go b/vendor/github.com/docker/docker/api/server/middleware.go deleted file mode 100644 index 628d0a3b..00000000 --- a/vendor/github.com/docker/docker/api/server/middleware.go +++ /dev/null @@ -1,154 +0,0 @@ -package server - -import ( - "bytes" - "encoding/json" - "io/ioutil" - "net/http" - "runtime" - "strings" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/api" - "github.com/docker/docker/api/server/httputils" - "github.com/docker/docker/dockerversion" - "github.com/docker/docker/errors" - "github.com/docker/docker/pkg/version" - "golang.org/x/net/context" -) - -// middleware is an adapter to allow the use of ordinary functions as Docker API filters. -// Any function that has the appropriate signature can be register as a middleware. -type middleware func(handler httputils.APIFunc) httputils.APIFunc - -// loggingMiddleware logs each request when logging is enabled. -func (s *Server) loggingMiddleware(handler httputils.APIFunc) httputils.APIFunc { - return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if s.cfg.Logging { - logrus.Infof("%s %s", r.Method, r.RequestURI) - } - return handler(ctx, w, r, vars) - } -} - -// debugRequestMiddleware dumps the request to logger -// This is implemented separately from `loggingMiddleware` so that we don't have to -// check the logging level or have httputil.DumpRequest called on each request. -// Instead the middleware is only injected when the logging level is set to debug -func (s *Server) debugRequestMiddleware(handler httputils.APIFunc) httputils.APIFunc { - return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if s.cfg.Logging && r.Method == "POST" { - if err := httputils.CheckForJSON(r); err == nil { - var buf bytes.Buffer - if _, err := buf.ReadFrom(r.Body); err == nil { - r.Body.Close() - r.Body = ioutil.NopCloser(&buf) - var postForm map[string]interface{} - if err := json.Unmarshal(buf.Bytes(), &postForm); err == nil { - if _, exists := postForm["password"]; exists { - postForm["password"] = "*****" - } - logrus.Debugf("form data: %q", postForm) - } - } - } - } - return handler(ctx, w, r, vars) - } -} - -// userAgentMiddleware checks the User-Agent header looking for a valid docker client spec. -func (s *Server) userAgentMiddleware(handler httputils.APIFunc) httputils.APIFunc { - return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if strings.Contains(r.Header.Get("User-Agent"), "Docker-Client/") { - dockerVersion := version.Version(s.cfg.Version) - - userAgent := strings.Split(r.Header.Get("User-Agent"), "/") - - // v1.20 onwards includes the GOOS of the client after the version - // such as Docker/1.7.0 (linux) - if len(userAgent) == 2 && strings.Contains(userAgent[1], " ") { - userAgent[1] = strings.Split(userAgent[1], " ")[0] - } - - if len(userAgent) == 2 && !dockerVersion.Equal(version.Version(userAgent[1])) { - logrus.Debugf("Warning: client and server don't have the same version (client: %s, server: %s)", userAgent[1], dockerVersion) - } - } - return handler(ctx, w, r, vars) - } -} - -// corsMiddleware sets the CORS header expectations in the server. -func (s *Server) corsMiddleware(handler httputils.APIFunc) httputils.APIFunc { - return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - // If "api-cors-header" is not given, but "api-enable-cors" is true, we set cors to "*" - // otherwise, all head values will be passed to HTTP handler - corsHeaders := s.cfg.CorsHeaders - if corsHeaders == "" && s.cfg.EnableCors { - corsHeaders = "*" - } - - if corsHeaders != "" { - writeCorsHeaders(w, r, corsHeaders) - } - return handler(ctx, w, r, vars) - } -} - -// versionMiddleware checks the api version requirements before passing the request to the server handler. -func versionMiddleware(handler httputils.APIFunc) httputils.APIFunc { - return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - apiVersion := version.Version(vars["version"]) - if apiVersion == "" { - apiVersion = api.Version - } - - if apiVersion.GreaterThan(api.Version) { - return errors.ErrorCodeNewerClientVersion.WithArgs(apiVersion, api.Version) - } - if apiVersion.LessThan(api.MinVersion) { - return errors.ErrorCodeOldClientVersion.WithArgs(apiVersion, api.Version) - } - - w.Header().Set("Server", "Docker/"+dockerversion.Version+" ("+runtime.GOOS+")") - ctx = context.WithValue(ctx, httputils.APIVersionKey, apiVersion) - return handler(ctx, w, r, vars) - } -} - -// handleWithGlobalMiddlwares wraps the handler function for a request with -// the server's global middlewares. The order of the middlewares is backwards, -// meaning that the first in the list will be evaludated last. -// -// Example: handleWithGlobalMiddlewares(s.getContainersName) -// -// s.loggingMiddleware( -// s.userAgentMiddleware( -// s.corsMiddleware( -// versionMiddleware(s.getContainersName) -// ) -// ) -// ) -// ) -func (s *Server) handleWithGlobalMiddlewares(handler httputils.APIFunc) httputils.APIFunc { - middlewares := []middleware{ - versionMiddleware, - s.corsMiddleware, - s.userAgentMiddleware, - s.loggingMiddleware, - } - - // Only want this on debug level - // this is separate from the logging middleware so that we can do this check here once, - // rather than for each request. - if logrus.GetLevel() == logrus.DebugLevel { - middlewares = append(middlewares, s.debugRequestMiddleware) - } - - h := handler - for _, m := range middlewares { - h = m(h) - } - return h -} diff --git a/vendor/github.com/docker/docker/api/server/middleware_test.go b/vendor/github.com/docker/docker/api/server/middleware_test.go deleted file mode 100644 index 4f48b209..00000000 --- a/vendor/github.com/docker/docker/api/server/middleware_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package server - -import ( - "net/http" - "net/http/httptest" - "testing" - - "github.com/docker/distribution/registry/api/errcode" - "github.com/docker/docker/api/server/httputils" - "github.com/docker/docker/errors" - "golang.org/x/net/context" -) - -func TestVersionMiddleware(t *testing.T) { - handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if httputils.VersionFromContext(ctx) == "" { - t.Fatalf("Expected version, got empty string") - } - return nil - } - - h := versionMiddleware(handler) - - req, _ := http.NewRequest("GET", "/containers/json", nil) - resp := httptest.NewRecorder() - ctx := context.Background() - if err := h(ctx, resp, req, map[string]string{}); err != nil { - t.Fatal(err) - } -} - -func TestVersionMiddlewareWithErrors(t *testing.T) { - handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if httputils.VersionFromContext(ctx) == "" { - t.Fatalf("Expected version, got empty string") - } - return nil - } - - h := versionMiddleware(handler) - - req, _ := http.NewRequest("GET", "/containers/json", nil) - resp := httptest.NewRecorder() - ctx := context.Background() - - vars := map[string]string{"version": "0.1"} - err := h(ctx, resp, req, vars) - if derr, ok := err.(errcode.Error); !ok || derr.ErrorCode() != errors.ErrorCodeOldClientVersion { - t.Fatalf("Expected ErrorCodeOldClientVersion, got %v", err) - } - - vars["version"] = "100000" - err = h(ctx, resp, req, vars) - if derr, ok := err.(errcode.Error); !ok || derr.ErrorCode() != errors.ErrorCodeNewerClientVersion { - t.Fatalf("Expected ErrorCodeNewerClientVersion, got %v", err) - } -} diff --git a/vendor/github.com/docker/docker/api/server/profiler.go b/vendor/github.com/docker/docker/api/server/profiler.go deleted file mode 100644 index 766462bd..00000000 --- a/vendor/github.com/docker/docker/api/server/profiler.go +++ /dev/null @@ -1,38 +0,0 @@ -package server - -import ( - "expvar" - "fmt" - "net/http" - "net/http/pprof" - - "github.com/gorilla/mux" -) - -func profilerSetup(mainRouter *mux.Router, path string) { - var r = mainRouter.PathPrefix(path).Subrouter() - r.HandleFunc("/vars", expVars) - r.HandleFunc("/pprof/", pprof.Index) - r.HandleFunc("/pprof/cmdline", pprof.Cmdline) - r.HandleFunc("/pprof/profile", pprof.Profile) - r.HandleFunc("/pprof/symbol", pprof.Symbol) - r.HandleFunc("/pprof/block", pprof.Handler("block").ServeHTTP) - r.HandleFunc("/pprof/heap", pprof.Handler("heap").ServeHTTP) - r.HandleFunc("/pprof/goroutine", pprof.Handler("goroutine").ServeHTTP) - r.HandleFunc("/pprof/threadcreate", pprof.Handler("threadcreate").ServeHTTP) -} - -// Replicated from expvar.go as not public. -func expVars(w http.ResponseWriter, r *http.Request) { - first := true - w.Header().Set("Content-Type", "application/json; charset=utf-8") - fmt.Fprintf(w, "{\n") - 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") -} diff --git a/vendor/github.com/docker/docker/api/server/router/local/auth.go b/vendor/github.com/docker/docker/api/server/router/local/auth.go deleted file mode 100644 index 872124c9..00000000 --- a/vendor/github.com/docker/docker/api/server/router/local/auth.go +++ /dev/null @@ -1,27 +0,0 @@ -package local - -import ( - "encoding/json" - "net/http" - - "github.com/docker/docker/api/server/httputils" - "github.com/docker/docker/api/types" - "github.com/docker/docker/cliconfig" - "golang.org/x/net/context" -) - -func (s *router) postAuth(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - var config *cliconfig.AuthConfig - err := json.NewDecoder(r.Body).Decode(&config) - r.Body.Close() - if err != nil { - return err - } - status, err := s.daemon.AuthenticateToRegistry(config) - if err != nil { - return err - } - return httputils.WriteJSON(w, http.StatusOK, &types.AuthResponse{ - Status: status, - }) -} diff --git a/vendor/github.com/docker/docker/api/server/router/local/container.go b/vendor/github.com/docker/docker/api/server/router/local/container.go deleted file mode 100644 index bedcae01..00000000 --- a/vendor/github.com/docker/docker/api/server/router/local/container.go +++ /dev/null @@ -1,468 +0,0 @@ -package local - -import ( - "fmt" - "io" - "net/http" - "strconv" - "strings" - "syscall" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/distribution/registry/api/errcode" - "github.com/docker/docker/api/server/httputils" - "github.com/docker/docker/api/types" - "github.com/docker/docker/daemon" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/pkg/ioutils" - "github.com/docker/docker/pkg/signal" - "github.com/docker/docker/runconfig" - "github.com/docker/docker/utils" - "golang.org/x/net/context" - "golang.org/x/net/websocket" -) - -func (s *router) getContainersJSON(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - config := &daemon.ContainersConfig{ - All: httputils.BoolValue(r, "all"), - Size: httputils.BoolValue(r, "size"), - Since: r.Form.Get("since"), - Before: r.Form.Get("before"), - Filters: r.Form.Get("filters"), - } - - if tmpLimit := r.Form.Get("limit"); tmpLimit != "" { - limit, err := strconv.Atoi(tmpLimit) - if err != nil { - return err - } - config.Limit = limit - } - - containers, err := s.daemon.Containers(config) - if err != nil { - return err - } - - return httputils.WriteJSON(w, http.StatusOK, containers) -} - -func (s *router) getContainersStats(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - stream := httputils.BoolValueOrDefault(r, "stream", true) - var out io.Writer - if !stream { - w.Header().Set("Content-Type", "application/json") - out = w - } else { - wf := ioutils.NewWriteFlusher(w) - out = wf - defer wf.Close() - } - - var closeNotifier <-chan bool - if notifier, ok := w.(http.CloseNotifier); ok { - closeNotifier = notifier.CloseNotify() - } - - config := &daemon.ContainerStatsConfig{ - Stream: stream, - OutStream: out, - Stop: closeNotifier, - Version: httputils.VersionFromContext(ctx), - } - - return s.daemon.ContainerStats(vars["name"], config) -} - -func (s *router) getContainersLogs(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - // Args are validated before the stream starts because when it starts we're - // sending HTTP 200 by writing an empty chunk of data to tell the client that - // daemon is going to stream. By sending this initial HTTP 200 we can't report - // any error after the stream starts (i.e. container not found, wrong parameters) - // with the appropriate status code. - stdout, stderr := httputils.BoolValue(r, "stdout"), httputils.BoolValue(r, "stderr") - if !(stdout || stderr) { - return fmt.Errorf("Bad parameters: you must choose at least one stream") - } - - var since time.Time - if r.Form.Get("since") != "" { - s, err := strconv.ParseInt(r.Form.Get("since"), 10, 64) - if err != nil { - return err - } - since = time.Unix(s, 0) - } - - var closeNotifier <-chan bool - if notifier, ok := w.(http.CloseNotifier); ok { - closeNotifier = notifier.CloseNotify() - } - - containerName := vars["name"] - - if !s.daemon.Exists(containerName) { - return derr.ErrorCodeNoSuchContainer.WithArgs(containerName) - } - - // write an empty chunk of data (this is to ensure that the - // HTTP Response is sent immediately, even if the container has - // not yet produced any data) - w.WriteHeader(http.StatusOK) - if flusher, ok := w.(http.Flusher); ok { - flusher.Flush() - } - - output := ioutils.NewWriteFlusher(w) - defer output.Close() - - logsConfig := &daemon.ContainerLogsConfig{ - Follow: httputils.BoolValue(r, "follow"), - Timestamps: httputils.BoolValue(r, "timestamps"), - Since: since, - Tail: r.Form.Get("tail"), - UseStdout: stdout, - UseStderr: stderr, - OutStream: output, - Stop: closeNotifier, - } - - if err := s.daemon.ContainerLogs(containerName, logsConfig); err != nil { - // The client may be expecting all of the data we're sending to - // be multiplexed, so send it through OutStream, which will - // have been set up to handle that if needed. - fmt.Fprintf(logsConfig.OutStream, "Error running logs job: %s\n", utils.GetErrorMessage(err)) - } - - return nil -} - -func (s *router) getContainersExport(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - return s.daemon.ContainerExport(vars["name"], w) -} - -func (s *router) postContainersStart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - // If contentLength is -1, we can assumed chunked encoding - // or more technically that the length is unknown - // https://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 - var hostConfig *runconfig.HostConfig - if r.Body != nil && (r.ContentLength > 0 || r.ContentLength == -1) { - if err := httputils.CheckForJSON(r); err != nil { - return err - } - - c, err := runconfig.DecodeHostConfig(r.Body) - if err != nil { - return err - } - - hostConfig = c - } - - if err := s.daemon.ContainerStart(vars["name"], hostConfig); err != nil { - return err - } - w.WriteHeader(http.StatusNoContent) - return nil -} - -func (s *router) postContainersStop(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - seconds, _ := strconv.Atoi(r.Form.Get("t")) - - if err := s.daemon.ContainerStop(vars["name"], seconds); err != nil { - return err - } - w.WriteHeader(http.StatusNoContent) - - return nil -} - -func (s *router) postContainersKill(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - var sig syscall.Signal - name := vars["name"] - - // If we have a signal, look at it. Otherwise, do nothing - if sigStr := r.Form.Get("signal"); sigStr != "" { - var err error - if sig, err = signal.ParseSignal(sigStr); err != nil { - return err - } - } - - if err := s.daemon.ContainerKill(name, uint64(sig)); err != nil { - theErr, isDerr := err.(errcode.ErrorCoder) - isStopped := isDerr && theErr.ErrorCode() == derr.ErrorCodeNotRunning - - // Return error that's not caused because the container is stopped. - // Return error if the container is not running and the api is >= 1.20 - // to keep backwards compatibility. - version := httputils.VersionFromContext(ctx) - if version.GreaterThanOrEqualTo("1.20") || !isStopped { - return fmt.Errorf("Cannot kill container %s: %v", name, err) - } - } - - w.WriteHeader(http.StatusNoContent) - return nil -} - -func (s *router) postContainersRestart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - timeout, _ := strconv.Atoi(r.Form.Get("t")) - - if err := s.daemon.ContainerRestart(vars["name"], timeout); err != nil { - return err - } - - w.WriteHeader(http.StatusNoContent) - - return nil -} - -func (s *router) postContainersPause(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - if err := s.daemon.ContainerPause(vars["name"]); err != nil { - return err - } - - w.WriteHeader(http.StatusNoContent) - - return nil -} - -func (s *router) postContainersUnpause(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - if err := s.daemon.ContainerUnpause(vars["name"]); err != nil { - return err - } - - w.WriteHeader(http.StatusNoContent) - - return nil -} - -func (s *router) postContainersWait(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - status, err := s.daemon.ContainerWait(vars["name"], -1*time.Second) - if err != nil { - return err - } - - return httputils.WriteJSON(w, http.StatusOK, &types.ContainerWaitResponse{ - StatusCode: status, - }) -} - -func (s *router) getContainersChanges(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - changes, err := s.daemon.ContainerChanges(vars["name"]) - if err != nil { - return err - } - - return httputils.WriteJSON(w, http.StatusOK, changes) -} - -func (s *router) getContainersTop(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - procList, err := s.daemon.ContainerTop(vars["name"], r.Form.Get("ps_args")) - if err != nil { - return err - } - - return httputils.WriteJSON(w, http.StatusOK, procList) -} - -func (s *router) postContainerRename(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - name := vars["name"] - newName := r.Form.Get("name") - if err := s.daemon.ContainerRename(name, newName); err != nil { - return err - } - w.WriteHeader(http.StatusNoContent) - return nil -} - -func (s *router) postContainersCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - if err := httputils.CheckForJSON(r); err != nil { - return err - } - - name := r.Form.Get("name") - - config, hostConfig, err := runconfig.DecodeContainerConfig(r.Body) - if err != nil { - return err - } - version := httputils.VersionFromContext(ctx) - adjustCPUShares := version.LessThan("1.19") - - ccr, err := s.daemon.ContainerCreate(&daemon.ContainerCreateConfig{ - Name: name, - Config: config, - HostConfig: hostConfig, - AdjustCPUShares: adjustCPUShares, - }) - if err != nil { - return err - } - - return httputils.WriteJSON(w, http.StatusCreated, ccr) -} - -func (s *router) deleteContainers(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - name := vars["name"] - config := &daemon.ContainerRmConfig{ - ForceRemove: httputils.BoolValue(r, "force"), - RemoveVolume: httputils.BoolValue(r, "v"), - RemoveLink: httputils.BoolValue(r, "link"), - } - - if err := s.daemon.ContainerRm(name, config); err != nil { - // Force a 404 for the empty string - if strings.Contains(strings.ToLower(err.Error()), "prefix can't be empty") { - return fmt.Errorf("no such id: \"\"") - } - return err - } - - w.WriteHeader(http.StatusNoContent) - - return nil -} - -func (s *router) postContainersResize(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - height, err := strconv.Atoi(r.Form.Get("h")) - if err != nil { - return err - } - width, err := strconv.Atoi(r.Form.Get("w")) - if err != nil { - return err - } - - return s.daemon.ContainerResize(vars["name"], height, width) -} - -func (s *router) postContainersAttach(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - containerName := vars["name"] - - if !s.daemon.Exists(containerName) { - return derr.ErrorCodeNoSuchContainer.WithArgs(containerName) - } - - if s.daemon.IsPaused(containerName) { - return derr.ErrorCodePausedContainer.WithArgs(containerName) - } - - inStream, outStream, err := httputils.HijackConnection(w) - if err != nil { - return err - } - defer httputils.CloseStreams(inStream, outStream) - - 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") - } - - attachWithLogsConfig := &daemon.ContainerAttachWithLogsConfig{ - InStream: inStream, - OutStream: outStream, - UseStdin: httputils.BoolValue(r, "stdin"), - UseStdout: httputils.BoolValue(r, "stdout"), - UseStderr: httputils.BoolValue(r, "stderr"), - Logs: httputils.BoolValue(r, "logs"), - Stream: httputils.BoolValue(r, "stream"), - } - - if err := s.daemon.ContainerAttachWithLogs(containerName, attachWithLogsConfig); err != nil { - fmt.Fprintf(outStream, "Error attaching: %s\n", err) - } - - return nil -} - -func (s *router) wsContainersAttach(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - containerName := vars["name"] - - if !s.daemon.Exists(containerName) { - return derr.ErrorCodeNoSuchContainer.WithArgs(containerName) - } - - h := websocket.Handler(func(ws *websocket.Conn) { - defer ws.Close() - - wsAttachWithLogsConfig := &daemon.ContainerWsAttachWithLogsConfig{ - InStream: ws, - OutStream: ws, - ErrStream: ws, - Logs: httputils.BoolValue(r, "logs"), - Stream: httputils.BoolValue(r, "stream"), - } - - if err := s.daemon.ContainerWsAttachWithLogs(containerName, wsAttachWithLogsConfig); err != nil { - logrus.Errorf("Error attaching websocket: %s", err) - } - }) - ws := websocket.Server{Handler: h, Handshake: nil} - ws.ServeHTTP(w, r) - - return nil -} diff --git a/vendor/github.com/docker/docker/api/server/router/local/copy.go b/vendor/github.com/docker/docker/api/server/router/local/copy.go deleted file mode 100644 index ff749a02..00000000 --- a/vendor/github.com/docker/docker/api/server/router/local/copy.go +++ /dev/null @@ -1,112 +0,0 @@ -package local - -import ( - "encoding/base64" - "encoding/json" - "fmt" - "io" - "net/http" - "os" - "strings" - - "github.com/docker/docker/api/server/httputils" - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// postContainersCopy is deprecated in favor of getContainersArchive. -func (s *router) postContainersCopy(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.CheckForJSON(r); err != nil { - return err - } - - cfg := types.CopyConfig{} - if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil { - return err - } - - if cfg.Resource == "" { - return fmt.Errorf("Path cannot be empty") - } - - data, err := s.daemon.ContainerCopy(vars["name"], cfg.Resource) - if err != nil { - if strings.Contains(strings.ToLower(err.Error()), "no such id") { - w.WriteHeader(http.StatusNotFound) - return nil - } - if os.IsNotExist(err) { - return fmt.Errorf("Could not find the file %s in container %s", cfg.Resource, vars["name"]) - } - return err - } - defer data.Close() - - w.Header().Set("Content-Type", "application/x-tar") - if _, err := io.Copy(w, data); err != nil { - return err - } - - return nil -} - -// // Encode the stat to JSON, base64 encode, and place in a header. -func setContainerPathStatHeader(stat *types.ContainerPathStat, header http.Header) error { - statJSON, err := json.Marshal(stat) - if err != nil { - return err - } - - header.Set( - "X-Docker-Container-Path-Stat", - base64.StdEncoding.EncodeToString(statJSON), - ) - - return nil -} - -func (s *router) headContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - v, err := httputils.ArchiveFormValues(r, vars) - if err != nil { - return err - } - - stat, err := s.daemon.ContainerStatPath(v.Name, v.Path) - if err != nil { - return err - } - - return setContainerPathStatHeader(stat, w.Header()) -} - -func (s *router) getContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - v, err := httputils.ArchiveFormValues(r, vars) - if err != nil { - return err - } - - tarArchive, stat, err := s.daemon.ContainerArchivePath(v.Name, v.Path) - if err != nil { - return err - } - defer tarArchive.Close() - - if err := setContainerPathStatHeader(stat, w.Header()); err != nil { - return err - } - - w.Header().Set("Content-Type", "application/x-tar") - _, err = io.Copy(w, tarArchive) - - return err -} - -func (s *router) putContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - v, err := httputils.ArchiveFormValues(r, vars) - if err != nil { - return err - } - - noOverwriteDirNonDir := httputils.BoolValue(r, "noOverwriteDirNonDir") - return s.daemon.ContainerExtractToDir(v.Name, v.Path, noOverwriteDirNonDir, r.Body) -} diff --git a/vendor/github.com/docker/docker/api/server/router/local/exec.go b/vendor/github.com/docker/docker/api/server/router/local/exec.go deleted file mode 100644 index 14095d8e..00000000 --- a/vendor/github.com/docker/docker/api/server/router/local/exec.go +++ /dev/null @@ -1,135 +0,0 @@ -package local - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "strconv" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/api/server/httputils" - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/stdcopy" - "github.com/docker/docker/runconfig" - "golang.org/x/net/context" -) - -func (s *router) getExecByID(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - eConfig, err := s.daemon.ContainerExecInspect(vars["id"]) - if err != nil { - return err - } - - return httputils.WriteJSON(w, http.StatusOK, eConfig) -} - -func (s *router) postContainerExecCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - if err := httputils.CheckForJSON(r); err != nil { - return err - } - name := vars["name"] - - execConfig := &runconfig.ExecConfig{} - if err := json.NewDecoder(r.Body).Decode(execConfig); err != nil { - return err - } - execConfig.Container = name - - if len(execConfig.Cmd) == 0 { - return fmt.Errorf("No exec command specified") - } - - // Register an instance of Exec in container. - id, err := s.daemon.ContainerExecCreate(execConfig) - if err != nil { - logrus.Errorf("Error setting up exec command in container %s: %s", name, err) - return err - } - - return httputils.WriteJSON(w, http.StatusCreated, &types.ContainerExecCreateResponse{ - ID: id, - }) -} - -// TODO(vishh): Refactor the code to avoid having to specify stream config as part of both create and start. -func (s *router) postContainerExecStart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - version := httputils.VersionFromContext(ctx) - if version.GreaterThan("1.21") { - if err := httputils.CheckForJSON(r); err != nil { - return err - } - } - - var ( - execName = vars["name"] - stdin, inStream io.ReadCloser - stdout, stderr, outStream io.Writer - ) - - execStartCheck := &types.ExecStartCheck{} - if err := json.NewDecoder(r.Body).Decode(execStartCheck); err != nil { - return err - } - - if exists, err := s.daemon.ExecExists(execName); !exists { - return err - } - - if !execStartCheck.Detach { - var err error - // Setting up the streaming http interface. - inStream, outStream, err = httputils.HijackConnection(w) - if err != nil { - return err - } - defer httputils.CloseStreams(inStream, outStream) - - 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") - } - - stdin = inStream - stdout = outStream - if !execStartCheck.Tty { - stderr = stdcopy.NewStdWriter(outStream, stdcopy.Stderr) - stdout = stdcopy.NewStdWriter(outStream, stdcopy.Stdout) - } - } else { - outStream = w - } - - // Now run the user process in container. - if err := s.daemon.ContainerExecStart(execName, stdin, stdout, stderr); err != nil { - if execStartCheck.Detach { - return err - } - logrus.Errorf("Error running exec in container: %v\n", err) - } - return nil -} - -func (s *router) postContainerExecResize(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - height, err := strconv.Atoi(r.Form.Get("h")) - if err != nil { - return err - } - width, err := strconv.Atoi(r.Form.Get("w")) - if err != nil { - return err - } - - return s.daemon.ContainerExecResize(vars["name"], height, width) -} diff --git a/vendor/github.com/docker/docker/api/server/router/local/image.go b/vendor/github.com/docker/docker/api/server/router/local/image.go deleted file mode 100644 index fd78ee2c..00000000 --- a/vendor/github.com/docker/docker/api/server/router/local/image.go +++ /dev/null @@ -1,547 +0,0 @@ -package local - -import ( - "encoding/base64" - "encoding/json" - "errors" - "fmt" - "io" - "net/http" - "strings" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/api/server/httputils" - "github.com/docker/docker/api/types" - "github.com/docker/docker/builder" - "github.com/docker/docker/builder/dockerfile" - "github.com/docker/docker/cliconfig" - "github.com/docker/docker/daemon/daemonbuilder" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/graph" - "github.com/docker/docker/graph/tags" - "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/chrootarchive" - "github.com/docker/docker/pkg/ioutils" - "github.com/docker/docker/pkg/parsers" - "github.com/docker/docker/pkg/progressreader" - "github.com/docker/docker/pkg/streamformatter" - "github.com/docker/docker/pkg/ulimit" - "github.com/docker/docker/registry" - "github.com/docker/docker/runconfig" - "github.com/docker/docker/utils" - "golang.org/x/net/context" -) - -func (s *router) postCommit(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - if err := httputils.CheckForJSON(r); err != nil { - return err - } - - cname := r.Form.Get("container") - - pause := httputils.BoolValue(r, "pause") - version := httputils.VersionFromContext(ctx) - if r.FormValue("pause") == "" && version.GreaterThanOrEqualTo("1.13") { - pause = true - } - - c, _, err := runconfig.DecodeContainerConfig(r.Body) - if err != nil && err != io.EOF { //Do not fail if body is empty. - return err - } - - commitCfg := &dockerfile.CommitConfig{ - Pause: pause, - Repo: r.Form.Get("repo"), - Tag: r.Form.Get("tag"), - Author: r.Form.Get("author"), - Comment: r.Form.Get("comment"), - Changes: r.Form["changes"], - Config: c, - } - - if !s.daemon.Exists(cname) { - return derr.ErrorCodeNoSuchContainer.WithArgs(cname) - } - - imgID, err := dockerfile.Commit(cname, s.daemon, commitCfg) - if err != nil { - return err - } - - return httputils.WriteJSON(w, http.StatusCreated, &types.ContainerCommitResponse{ - ID: string(imgID), - }) -} - -// Creates an image from Pull or from Import -func (s *router) postImagesCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - var ( - image = r.Form.Get("fromImage") - repo = r.Form.Get("repo") - tag = r.Form.Get("tag") - message = r.Form.Get("message") - ) - authEncoded := r.Header.Get("X-Registry-Auth") - authConfig := &cliconfig.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 = &cliconfig.AuthConfig{} - } - } - - var ( - err error - output = ioutils.NewWriteFlusher(w) - ) - defer output.Close() - - w.Header().Set("Content-Type", "application/json") - - 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 - } - } - - imagePullConfig := &graph.ImagePullConfig{ - MetaHeaders: metaHeaders, - AuthConfig: authConfig, - OutStream: output, - } - - err = s.daemon.PullImage(image, tag, imagePullConfig) - } else { //import - if tag == "" { - repo, tag = parsers.ParseRepositoryTag(repo) - } - - src := r.Form.Get("fromSrc") - - // 'err' MUST NOT be defined within this block, we need any error - // generated from the download to be available to the output - // stream processing below - var newConfig *runconfig.Config - newConfig, err = dockerfile.BuildFromConfig(&runconfig.Config{}, r.Form["changes"]) - if err != nil { - return err - } - - err = s.daemon.ImportImage(src, repo, tag, message, r.Body, output, newConfig) - } - if err != nil { - if !output.Flushed() { - return err - } - sf := streamformatter.NewJSONStreamFormatter() - output.Write(sf.FormatError(err)) - } - - return nil -} - -func (s *router) postImagesPush(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - metaHeaders := map[string][]string{} - for k, v := range r.Header { - if strings.HasPrefix(k, "X-Meta-") { - metaHeaders[k] = v - } - } - if err := httputils.ParseForm(r); err != nil { - return err - } - authConfig := &cliconfig.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 = &cliconfig.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 fmt.Errorf("Bad parameters and missing X-Registry-Auth: %v", err) - } - } - - name := vars["name"] - output := ioutils.NewWriteFlusher(w) - defer output.Close() - imagePushConfig := &graph.ImagePushConfig{ - MetaHeaders: metaHeaders, - AuthConfig: authConfig, - Tag: r.Form.Get("tag"), - OutStream: output, - } - - w.Header().Set("Content-Type", "application/json") - - if err := s.daemon.PushImage(name, imagePushConfig); err != nil { - if !output.Flushed() { - return err - } - sf := streamformatter.NewJSONStreamFormatter() - output.Write(sf.FormatError(err)) - } - return nil -} - -func (s *router) getImagesGet(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - w.Header().Set("Content-Type", "application/x-tar") - - output := ioutils.NewWriteFlusher(w) - defer output.Close() - var names []string - if name, ok := vars["name"]; ok { - names = []string{name} - } else { - names = r.Form["names"] - } - - if err := s.daemon.ExportImage(names, output); err != nil { - if !output.Flushed() { - return err - } - sf := streamformatter.NewJSONStreamFormatter() - output.Write(sf.FormatError(err)) - } - return nil -} - -func (s *router) postImagesLoad(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - return s.daemon.LoadImage(r.Body, w) -} - -func (s *router) deleteImages(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - name := vars["name"] - - if strings.TrimSpace(name) == "" { - return fmt.Errorf("image name cannot be blank") - } - - force := httputils.BoolValue(r, "force") - prune := !httputils.BoolValue(r, "noprune") - - list, err := s.daemon.ImageDelete(name, force, prune) - if err != nil { - return err - } - - return httputils.WriteJSON(w, http.StatusOK, list) -} - -func (s *router) getImagesByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - imageInspect, err := s.daemon.LookupImage(vars["name"]) - if err != nil { - return err - } - - return httputils.WriteJSON(w, http.StatusOK, imageInspect) -} - -func (s *router) postBuild(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - var ( - authConfigs = map[string]cliconfig.AuthConfig{} - authConfigsEncoded = r.Header.Get("X-Registry-Config") - buildConfig = &dockerfile.Config{} - ) - - if authConfigsEncoded != "" { - authConfigsJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authConfigsEncoded)) - if err := json.NewDecoder(authConfigsJSON).Decode(&authConfigs); 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. - } - } - - w.Header().Set("Content-Type", "application/json") - - version := httputils.VersionFromContext(ctx) - output := ioutils.NewWriteFlusher(w) - defer output.Close() - sf := streamformatter.NewJSONStreamFormatter() - errf := func(err error) error { - // Do not write the error in the http output if it's still empty. - // This prevents from writing a 200(OK) when there is an interal error. - if !output.Flushed() { - return err - } - _, err = w.Write(sf.FormatError(errors.New(utils.GetErrorMessage(err)))) - if err != nil { - logrus.Warnf("could not write error response: %v", err) - } - return nil - } - - if httputils.BoolValue(r, "forcerm") && version.GreaterThanOrEqualTo("1.12") { - buildConfig.Remove = true - } else if r.FormValue("rm") == "" && version.GreaterThanOrEqualTo("1.12") { - buildConfig.Remove = true - } else { - buildConfig.Remove = httputils.BoolValue(r, "rm") - } - if httputils.BoolValue(r, "pull") && version.GreaterThanOrEqualTo("1.16") { - buildConfig.Pull = true - } - - repoAndTags, err := sanitizeRepoAndTags(r.Form["t"]) - if err != nil { - return errf(err) - } - - buildConfig.DockerfileName = r.FormValue("dockerfile") - buildConfig.Verbose = !httputils.BoolValue(r, "q") - buildConfig.UseCache = !httputils.BoolValue(r, "nocache") - buildConfig.ForceRemove = httputils.BoolValue(r, "forcerm") - buildConfig.MemorySwap = httputils.Int64ValueOrZero(r, "memswap") - buildConfig.Memory = httputils.Int64ValueOrZero(r, "memory") - buildConfig.CPUShares = httputils.Int64ValueOrZero(r, "cpushares") - buildConfig.CPUPeriod = httputils.Int64ValueOrZero(r, "cpuperiod") - buildConfig.CPUQuota = httputils.Int64ValueOrZero(r, "cpuquota") - buildConfig.CPUSetCpus = r.FormValue("cpusetcpus") - buildConfig.CPUSetMems = r.FormValue("cpusetmems") - buildConfig.CgroupParent = r.FormValue("cgroupparent") - - if i := runconfig.IsolationLevel(r.FormValue("isolation")); i != "" { - if !runconfig.IsolationLevel.IsValid(i) { - return errf(fmt.Errorf("Unsupported isolation: %q", i)) - } - buildConfig.Isolation = i - } - - var buildUlimits = []*ulimit.Ulimit{} - ulimitsJSON := r.FormValue("ulimits") - if ulimitsJSON != "" { - if err := json.NewDecoder(strings.NewReader(ulimitsJSON)).Decode(&buildUlimits); err != nil { - return errf(err) - } - buildConfig.Ulimits = buildUlimits - } - - var buildArgs = map[string]string{} - buildArgsJSON := r.FormValue("buildargs") - if buildArgsJSON != "" { - if err := json.NewDecoder(strings.NewReader(buildArgsJSON)).Decode(&buildArgs); err != nil { - return errf(err) - } - buildConfig.BuildArgs = buildArgs - } - - remoteURL := r.FormValue("remote") - - // Currently, only used if context is from a remote url. - // The field `In` is set by DetectContextFromRemoteURL. - // Look at code in DetectContextFromRemoteURL for more information. - pReader := &progressreader.Config{ - // TODO: make progressreader streamformatter-agnostic - Out: output, - Formatter: sf, - Size: r.ContentLength, - NewLines: true, - ID: "Downloading context", - Action: remoteURL, - } - - var ( - context builder.ModifiableContext - dockerfileName string - ) - context, dockerfileName, err = daemonbuilder.DetectContextFromRemoteURL(r.Body, remoteURL, pReader) - if err != nil { - return errf(err) - } - defer func() { - if err := context.Close(); err != nil { - logrus.Debugf("[BUILDER] failed to remove temporary context: %v", err) - } - }() - - uidMaps, gidMaps := s.daemon.GetUIDGIDMaps() - defaultArchiver := &archive.Archiver{ - Untar: chrootarchive.Untar, - UIDMaps: uidMaps, - GIDMaps: gidMaps, - } - docker := &daemonbuilder.Docker{ - Daemon: s.daemon, - OutOld: output, - AuthConfigs: authConfigs, - Archiver: defaultArchiver, - } - - b, err := dockerfile.NewBuilder(buildConfig, docker, builder.DockerIgnoreContext{ModifiableContext: context}, nil) - if err != nil { - return errf(err) - } - b.Stdout = &streamformatter.StdoutFormatter{Writer: output, StreamFormatter: sf} - b.Stderr = &streamformatter.StderrFormatter{Writer: output, StreamFormatter: sf} - - if closeNotifier, ok := w.(http.CloseNotifier); ok { - finished := make(chan struct{}) - defer close(finished) - go func() { - select { - case <-finished: - case <-closeNotifier.CloseNotify(): - logrus.Infof("Client disconnected, cancelling job: build") - b.Cancel() - } - }() - } - - if len(dockerfileName) > 0 { - b.DockerfileName = dockerfileName - } - - imgID, err := b.Build() - if err != nil { - return errf(err) - } - - for _, rt := range repoAndTags { - if err := s.daemon.TagImage(rt.repo, rt.tag, string(imgID), true); err != nil { - return errf(err) - } - } - - return nil -} - -// repoAndTag is a helper struct for holding the parsed repositories and tags of -// the input "t" argument. -type repoAndTag struct { - repo, tag string -} - -// sanitizeRepoAndTags parses the raw "t" parameter received from the client -// to a slice of repoAndTag. -// It also validates each repoName and tag. -func sanitizeRepoAndTags(names []string) ([]repoAndTag, error) { - var ( - repoAndTags []repoAndTag - // This map is used for deduplicating the "-t" paramter. - uniqNames = make(map[string]struct{}) - ) - for _, repo := range names { - name, tag := parsers.ParseRepositoryTag(repo) - if name == "" { - continue - } - - if err := registry.ValidateRepositoryName(name); err != nil { - return nil, err - } - - nameWithTag := name - if len(tag) > 0 { - if err := tags.ValidateTagName(tag); err != nil { - return nil, err - } - nameWithTag += ":" + tag - } else { - nameWithTag += ":" + tags.DefaultTag - } - if _, exists := uniqNames[nameWithTag]; !exists { - uniqNames[nameWithTag] = struct{}{} - repoAndTags = append(repoAndTags, repoAndTag{repo: name, tag: tag}) - } - } - return repoAndTags, nil -} - -func (s *router) getImagesJSON(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - // FIXME: The filter parameter could just be a match filter - images, err := s.daemon.ListImages(r.Form.Get("filters"), r.Form.Get("filter"), httputils.BoolValue(r, "all")) - if err != nil { - return err - } - - return httputils.WriteJSON(w, http.StatusOK, images) -} - -func (s *router) getImagesHistory(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - name := vars["name"] - history, err := s.daemon.ImageHistory(name) - if err != nil { - return err - } - - return httputils.WriteJSON(w, http.StatusOK, history) -} - -func (s *router) postImagesTag(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - repo := r.Form.Get("repo") - tag := r.Form.Get("tag") - name := vars["name"] - force := httputils.BoolValue(r, "force") - if err := s.daemon.TagImage(repo, tag, name, force); err != nil { - return err - } - w.WriteHeader(http.StatusCreated) - return nil -} - -func (s *router) getImagesSearch(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - var ( - config *cliconfig.AuthConfig - authEncoded = r.Header.Get("X-Registry-Auth") - headers = map[string][]string{} - ) - - if authEncoded != "" { - authJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded)) - if err := json.NewDecoder(authJSON).Decode(&config); 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 - config = &cliconfig.AuthConfig{} - } - } - for k, v := range r.Header { - if strings.HasPrefix(k, "X-Meta-") { - headers[k] = v - } - } - query, err := s.daemon.SearchRegistryForImages(r.Form.Get("term"), config, headers) - if err != nil { - return err - } - return httputils.WriteJSON(w, http.StatusOK, query.Results) -} diff --git a/vendor/github.com/docker/docker/api/server/router/local/info.go b/vendor/github.com/docker/docker/api/server/router/local/info.go deleted file mode 100644 index 06228a50..00000000 --- a/vendor/github.com/docker/docker/api/server/router/local/info.go +++ /dev/null @@ -1,141 +0,0 @@ -package local - -import ( - "encoding/json" - "net/http" - "runtime" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/api" - "github.com/docker/docker/api/server/httputils" - "github.com/docker/docker/api/types" - "github.com/docker/docker/dockerversion" - "github.com/docker/docker/pkg/ioutils" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/docker/docker/pkg/parsers/filters" - "github.com/docker/docker/pkg/parsers/kernel" - "github.com/docker/docker/utils" - "golang.org/x/net/context" -) - -func (s *router) getVersion(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - v := &types.Version{ - Version: dockerversion.Version, - APIVersion: api.Version, - GitCommit: dockerversion.GitCommit, - GoVersion: runtime.Version(), - Os: runtime.GOOS, - Arch: runtime.GOARCH, - BuildTime: dockerversion.BuildTime, - } - - version := httputils.VersionFromContext(ctx) - - if version.GreaterThanOrEqualTo("1.19") { - v.Experimental = utils.ExperimentalBuild() - } - - if kernelVersion, err := kernel.GetKernelVersion(); err == nil { - v.KernelVersion = kernelVersion.String() - } - - return httputils.WriteJSON(w, http.StatusOK, v) -} - -func (s *router) getInfo(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - info, err := s.daemon.SystemInfo() - if err != nil { - return err - } - - return httputils.WriteJSON(w, http.StatusOK, info) -} - -func (s *router) getEvents(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - since, err := httputils.Int64ValueOrDefault(r, "since", -1) - if err != nil { - return err - } - until, err := httputils.Int64ValueOrDefault(r, "until", -1) - if err != nil { - return err - } - - timer := time.NewTimer(0) - timer.Stop() - if until > 0 { - dur := time.Unix(until, 0).Sub(time.Now()) - timer = time.NewTimer(dur) - } - - ef, err := filters.FromParam(r.Form.Get("filters")) - if err != nil { - return err - } - - w.Header().Set("Content-Type", "application/json") - - // This is to ensure that the HTTP status code is sent immediately, - // so that it will not block the receiver. - w.WriteHeader(http.StatusOK) - if flusher, ok := w.(http.Flusher); ok { - flusher.Flush() - } - - output := ioutils.NewWriteFlusher(w) - defer output.Close() - - enc := json.NewEncoder(output) - - current, l, cancel := s.daemon.SubscribeToEvents() - defer cancel() - - eventFilter := s.daemon.GetEventFilter(ef) - handleEvent := func(ev *jsonmessage.JSONMessage) error { - if eventFilter.Include(ev) { - if err := enc.Encode(ev); err != nil { - return err - } - } - return nil - } - - if since == -1 { - current = nil - } - for _, ev := range current { - if ev.Time < since { - continue - } - if err := handleEvent(ev); err != nil { - return err - } - } - - var closeNotify <-chan bool - if closeNotifier, ok := w.(http.CloseNotifier); ok { - closeNotify = closeNotifier.CloseNotify() - } - - for { - select { - case ev := <-l: - jev, ok := ev.(*jsonmessage.JSONMessage) - if !ok { - continue - } - if err := handleEvent(jev); err != nil { - return err - } - case <-timer.C: - return nil - case <-closeNotify: - logrus.Debug("Client disconnected, stop sending events") - return nil - } - } -} diff --git a/vendor/github.com/docker/docker/api/server/router/local/inspect.go b/vendor/github.com/docker/docker/api/server/router/local/inspect.go deleted file mode 100644 index 8b2a058e..00000000 --- a/vendor/github.com/docker/docker/api/server/router/local/inspect.go +++ /dev/null @@ -1,33 +0,0 @@ -package local - -import ( - "net/http" - - "github.com/docker/docker/api/server/httputils" - "golang.org/x/net/context" -) - -// getContainersByName inspects containers configuration and serializes it as json. -func (s *router) getContainersByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - displaySize := httputils.BoolValue(r, "size") - - var json interface{} - var err error - - version := httputils.VersionFromContext(ctx) - - switch { - case version.LessThan("1.20"): - json, err = s.daemon.ContainerInspectPre120(vars["name"]) - case version.Equal("1.20"): - json, err = s.daemon.ContainerInspect120(vars["name"]) - default: - json, err = s.daemon.ContainerInspect(vars["name"], displaySize) - } - - if err != nil { - return err - } - - return httputils.WriteJSON(w, http.StatusOK, json) -} diff --git a/vendor/github.com/docker/docker/api/server/router/local/local.go b/vendor/github.com/docker/docker/api/server/router/local/local.go deleted file mode 100644 index b27031bd..00000000 --- a/vendor/github.com/docker/docker/api/server/router/local/local.go +++ /dev/null @@ -1,158 +0,0 @@ -package local - -import ( - "net/http" - - "golang.org/x/net/context" - - "github.com/docker/docker/api/server/httputils" - dkrouter "github.com/docker/docker/api/server/router" - "github.com/docker/docker/daemon" -) - -// router is a docker router that talks with the local docker daemon. -type router struct { - daemon *daemon.Daemon - routes []dkrouter.Route -} - -// localRoute defines an individual API route to connect with the docker daemon. -// It implements router.Route. -type localRoute struct { - method string - path string - handler httputils.APIFunc -} - -// Handler returns the APIFunc to let the server wrap it in middlewares -func (l localRoute) Handler() httputils.APIFunc { - return l.handler -} - -// Method returns the http method that the route responds to. -func (l localRoute) Method() string { - return l.method -} - -// Path returns the subpath where the route responds to. -func (l localRoute) Path() string { - return l.path -} - -// NewRoute initialies a new local route for the reouter -func NewRoute(method, path string, handler httputils.APIFunc) dkrouter.Route { - return localRoute{method, path, handler} -} - -// NewGetRoute initializes a new route with the http method GET. -func NewGetRoute(path string, handler httputils.APIFunc) dkrouter.Route { - return NewRoute("GET", path, handler) -} - -// NewPostRoute initializes a new route with the http method POST. -func NewPostRoute(path string, handler httputils.APIFunc) dkrouter.Route { - return NewRoute("POST", path, handler) -} - -// NewPutRoute initializes a new route with the http method PUT. -func NewPutRoute(path string, handler httputils.APIFunc) dkrouter.Route { - return NewRoute("PUT", path, handler) -} - -// NewDeleteRoute initializes a new route with the http method DELETE. -func NewDeleteRoute(path string, handler httputils.APIFunc) dkrouter.Route { - return NewRoute("DELETE", path, handler) -} - -// NewOptionsRoute initializes a new route with the http method OPTIONS -func NewOptionsRoute(path string, handler httputils.APIFunc) dkrouter.Route { - return NewRoute("OPTIONS", path, handler) -} - -// NewHeadRoute initializes a new route with the http method HEAD. -func NewHeadRoute(path string, handler httputils.APIFunc) dkrouter.Route { - return NewRoute("HEAD", path, handler) -} - -// NewRouter initializes a local router with a new daemon. -func NewRouter(daemon *daemon.Daemon) dkrouter.Router { - r := &router{ - daemon: daemon, - } - r.initRoutes() - return r -} - -// Routes returns the list of routes registered in the router. -func (r *router) Routes() []dkrouter.Route { - return r.routes -} - -// initRoutes initializes the routes in this router -func (r *router) initRoutes() { - r.routes = []dkrouter.Route{ - // HEAD - NewHeadRoute("/containers/{name:.*}/archive", r.headContainersArchive), - // OPTIONS - NewOptionsRoute("/", optionsHandler), - // GET - NewGetRoute("/_ping", pingHandler), - NewGetRoute("/events", r.getEvents), - NewGetRoute("/info", r.getInfo), - NewGetRoute("/version", r.getVersion), - NewGetRoute("/images/json", r.getImagesJSON), - NewGetRoute("/images/search", r.getImagesSearch), - NewGetRoute("/images/get", r.getImagesGet), - NewGetRoute("/images/{name:.*}/get", r.getImagesGet), - NewGetRoute("/images/{name:.*}/history", r.getImagesHistory), - NewGetRoute("/images/{name:.*}/json", r.getImagesByName), - NewGetRoute("/containers/json", r.getContainersJSON), - NewGetRoute("/containers/{name:.*}/export", r.getContainersExport), - NewGetRoute("/containers/{name:.*}/changes", r.getContainersChanges), - NewGetRoute("/containers/{name:.*}/json", r.getContainersByName), - NewGetRoute("/containers/{name:.*}/top", r.getContainersTop), - NewGetRoute("/containers/{name:.*}/logs", r.getContainersLogs), - NewGetRoute("/containers/{name:.*}/stats", r.getContainersStats), - NewGetRoute("/containers/{name:.*}/attach/ws", r.wsContainersAttach), - NewGetRoute("/exec/{id:.*}/json", r.getExecByID), - NewGetRoute("/containers/{name:.*}/archive", r.getContainersArchive), - // POST - NewPostRoute("/auth", r.postAuth), - NewPostRoute("/commit", r.postCommit), - NewPostRoute("/build", r.postBuild), - NewPostRoute("/images/create", r.postImagesCreate), - NewPostRoute("/images/load", r.postImagesLoad), - NewPostRoute("/images/{name:.*}/push", r.postImagesPush), - NewPostRoute("/images/{name:.*}/tag", r.postImagesTag), - NewPostRoute("/containers/create", r.postContainersCreate), - NewPostRoute("/containers/{name:.*}/kill", r.postContainersKill), - NewPostRoute("/containers/{name:.*}/pause", r.postContainersPause), - NewPostRoute("/containers/{name:.*}/unpause", r.postContainersUnpause), - NewPostRoute("/containers/{name:.*}/restart", r.postContainersRestart), - NewPostRoute("/containers/{name:.*}/start", r.postContainersStart), - NewPostRoute("/containers/{name:.*}/stop", r.postContainersStop), - NewPostRoute("/containers/{name:.*}/wait", r.postContainersWait), - NewPostRoute("/containers/{name:.*}/resize", r.postContainersResize), - NewPostRoute("/containers/{name:.*}/attach", r.postContainersAttach), - NewPostRoute("/containers/{name:.*}/copy", r.postContainersCopy), - NewPostRoute("/containers/{name:.*}/exec", r.postContainerExecCreate), - NewPostRoute("/exec/{name:.*}/start", r.postContainerExecStart), - NewPostRoute("/exec/{name:.*}/resize", r.postContainerExecResize), - NewPostRoute("/containers/{name:.*}/rename", r.postContainerRename), - // PUT - NewPutRoute("/containers/{name:.*}/archive", r.putContainersArchive), - // DELETE - NewDeleteRoute("/containers/{name:.*}", r.deleteContainers), - NewDeleteRoute("/images/{name:.*}", r.deleteImages), - } -} - -func optionsHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - w.WriteHeader(http.StatusOK) - return nil -} - -func pingHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - _, err := w.Write([]byte{'O', 'K'}) - return err -} diff --git a/vendor/github.com/docker/docker/api/server/router/network/backend.go b/vendor/github.com/docker/docker/api/server/router/network/backend.go deleted file mode 100644 index 8e069a4c..00000000 --- a/vendor/github.com/docker/docker/api/server/router/network/backend.go +++ /dev/null @@ -1,23 +0,0 @@ -package network - -import ( - // TODO: network config needs to be refactored out to a - // different location - "github.com/docker/docker/daemon/network" - - "github.com/docker/libnetwork" -) - -// Backend is all the methods that need to be implemented to provide -// network specific functionality -type Backend interface { - FindNetwork(idName string) (libnetwork.Network, error) - GetNetwork(idName string, by int) (libnetwork.Network, error) - GetNetworksByID(partialID string) []libnetwork.Network - CreateNetwork(name, driver string, ipam network.IPAM, - options map[string]string) (libnetwork.Network, error) - ConnectContainerToNetwork(containerName, networkName string) error - DisconnectContainerFromNetwork(containerName string, - network libnetwork.Network) error - NetworkControllerEnabled() bool -} diff --git a/vendor/github.com/docker/docker/api/server/router/network/network.go b/vendor/github.com/docker/docker/api/server/router/network/network.go deleted file mode 100644 index 5fcb252c..00000000 --- a/vendor/github.com/docker/docker/api/server/router/network/network.go +++ /dev/null @@ -1,56 +0,0 @@ -package network - -import ( - "net/http" - - "github.com/docker/docker/api/server/httputils" - "github.com/docker/docker/api/server/router" - "github.com/docker/docker/api/server/router/local" - "github.com/docker/docker/errors" - "golang.org/x/net/context" -) - -// networkRouter is a router to talk with the network controller -type networkRouter struct { - backend Backend - routes []router.Route -} - -// NewRouter initializes a new network router -func NewRouter(b Backend) router.Router { - r := &networkRouter{ - backend: b, - } - r.initRoutes() - return r -} - -// Routes returns the available routes to the network controller -func (r *networkRouter) Routes() []router.Route { - return r.routes -} - -func (r *networkRouter) initRoutes() { - r.routes = []router.Route{ - // GET - local.NewGetRoute("/networks", r.controllerEnabledMiddleware(r.getNetworksList)), - local.NewGetRoute("/networks/{id:.*}", r.controllerEnabledMiddleware(r.getNetwork)), - // POST - local.NewPostRoute("/networks/create", r.controllerEnabledMiddleware(r.postNetworkCreate)), - local.NewPostRoute("/networks/{id:.*}/connect", r.controllerEnabledMiddleware(r.postNetworkConnect)), - local.NewPostRoute("/networks/{id:.*}/disconnect", r.controllerEnabledMiddleware(r.postNetworkDisconnect)), - // DELETE - local.NewDeleteRoute("/networks/{id:.*}", r.controllerEnabledMiddleware(r.deleteNetwork)), - } -} - -func (r *networkRouter) controllerEnabledMiddleware(handler httputils.APIFunc) httputils.APIFunc { - if r.backend.NetworkControllerEnabled() { - return handler - } - return networkControllerDisabled -} - -func networkControllerDisabled(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - return errors.ErrorNetworkControllerNotEnabled.WithArgs() -} diff --git a/vendor/github.com/docker/docker/api/server/router/network/network_routes.go b/vendor/github.com/docker/docker/api/server/router/network/network_routes.go deleted file mode 100644 index e4b5d740..00000000 --- a/vendor/github.com/docker/docker/api/server/router/network/network_routes.go +++ /dev/null @@ -1,258 +0,0 @@ -package network - -import ( - "encoding/json" - "fmt" - "net/http" - - "golang.org/x/net/context" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/api/server/httputils" - "github.com/docker/docker/api/types" - "github.com/docker/docker/daemon" - "github.com/docker/docker/daemon/network" - "github.com/docker/docker/pkg/parsers/filters" - "github.com/docker/docker/runconfig" - "github.com/docker/libnetwork" -) - -func (n *networkRouter) getNetworksList(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - filter := r.Form.Get("filters") - netFilters, err := filters.FromParam(filter) - if err != nil { - return err - } - - list := []*types.NetworkResource{} - var nameFilter, idFilter bool - var names, ids []string - if names, nameFilter = netFilters["name"]; nameFilter { - for _, name := range names { - if nw, err := n.backend.GetNetwork(name, daemon.NetworkByName); err == nil { - list = append(list, buildNetworkResource(nw)) - } else { - logrus.Errorf("failed to get network for filter=%s : %v", name, err) - } - } - } - - if ids, idFilter = netFilters["id"]; idFilter { - for _, id := range ids { - for _, nw := range n.backend.GetNetworksByID(id) { - list = append(list, buildNetworkResource(nw)) - } - } - } - - if !nameFilter && !idFilter { - nwList := n.backend.GetNetworksByID("") - for _, nw := range nwList { - list = append(list, buildNetworkResource(nw)) - } - } - return httputils.WriteJSON(w, http.StatusOK, list) -} - -func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - nw, err := n.backend.FindNetwork(vars["id"]) - if err != nil { - return err - } - return httputils.WriteJSON(w, http.StatusOK, buildNetworkResource(nw)) -} - -func (n *networkRouter) postNetworkCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - var create types.NetworkCreate - var warning string - - if err := httputils.ParseForm(r); err != nil { - return err - } - - if err := httputils.CheckForJSON(r); err != nil { - return err - } - - if err := json.NewDecoder(r.Body).Decode(&create); err != nil { - return err - } - - if runconfig.IsPreDefinedNetwork(create.Name) { - return httputils.WriteJSON(w, http.StatusForbidden, - fmt.Sprintf("%s is a pre-defined network and cannot be created", create.Name)) - } - - nw, err := n.backend.GetNetwork(create.Name, daemon.NetworkByName) - if _, ok := err.(libnetwork.ErrNoSuchNetwork); err != nil && !ok { - return err - } - if nw != nil { - if create.CheckDuplicate { - return libnetwork.NetworkNameError(create.Name) - } - warning = fmt.Sprintf("Network with name %s (id : %s) already exists", nw.Name(), nw.ID()) - } - - nw, err = n.backend.CreateNetwork(create.Name, create.Driver, create.IPAM, create.Options) - if err != nil { - return err - } - - return httputils.WriteJSON(w, http.StatusCreated, &types.NetworkCreateResponse{ - ID: nw.ID(), - Warning: warning, - }) -} - -func (n *networkRouter) postNetworkConnect(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - var connect types.NetworkConnect - if err := httputils.ParseForm(r); err != nil { - return err - } - - if err := httputils.CheckForJSON(r); err != nil { - return err - } - - if err := json.NewDecoder(r.Body).Decode(&connect); err != nil { - return err - } - - nw, err := n.backend.FindNetwork(vars["id"]) - if err != nil { - return err - } - - return n.backend.ConnectContainerToNetwork(connect.Container, nw.Name()) -} - -func (n *networkRouter) postNetworkDisconnect(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - var disconnect types.NetworkDisconnect - if err := httputils.ParseForm(r); err != nil { - return err - } - - if err := httputils.CheckForJSON(r); err != nil { - return err - } - - if err := json.NewDecoder(r.Body).Decode(&disconnect); err != nil { - return err - } - - nw, err := n.backend.FindNetwork(vars["id"]) - if err != nil { - return err - } - - return n.backend.DisconnectContainerFromNetwork(disconnect.Container, nw) -} - -func (n *networkRouter) deleteNetwork(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - nw, err := n.backend.FindNetwork(vars["id"]) - if err != nil { - return err - } - - if runconfig.IsPreDefinedNetwork(nw.Name()) { - return httputils.WriteJSON(w, http.StatusForbidden, - fmt.Sprintf("%s is a pre-defined network and cannot be removed", nw.Name())) - } - - return nw.Delete() -} - -func buildNetworkResource(nw libnetwork.Network) *types.NetworkResource { - r := &types.NetworkResource{} - if nw == nil { - return r - } - - r.Name = nw.Name() - r.ID = nw.ID() - r.Scope = nw.Info().Scope() - r.Driver = nw.Type() - r.Options = nw.Info().DriverOptions() - r.Containers = make(map[string]types.EndpointResource) - buildIpamResources(r, nw) - - epl := nw.Endpoints() - for _, e := range epl { - ei := e.Info() - if ei == nil { - continue - } - sb := ei.Sandbox() - if sb == nil { - continue - } - - r.Containers[sb.ContainerID()] = buildEndpointResource(e) - } - return r -} - -func buildIpamResources(r *types.NetworkResource, nw libnetwork.Network) { - id, ipv4conf, ipv6conf := nw.Info().IpamConfig() - - r.IPAM.Driver = id - - r.IPAM.Config = []network.IPAMConfig{} - for _, ip4 := range ipv4conf { - iData := network.IPAMConfig{} - iData.Subnet = ip4.PreferredPool - iData.IPRange = ip4.SubPool - iData.Gateway = ip4.Gateway - iData.AuxAddress = ip4.AuxAddresses - r.IPAM.Config = append(r.IPAM.Config, iData) - } - - for _, ip6 := range ipv6conf { - iData := network.IPAMConfig{} - iData.Subnet = ip6.PreferredPool - iData.IPRange = ip6.SubPool - iData.Gateway = ip6.Gateway - iData.AuxAddress = ip6.AuxAddresses - r.IPAM.Config = append(r.IPAM.Config, iData) - } -} - -func buildEndpointResource(e libnetwork.Endpoint) types.EndpointResource { - er := types.EndpointResource{} - if e == nil { - return er - } - - er.EndpointID = e.ID() - ei := e.Info() - if ei == nil { - return er - } - - if iface := ei.Iface(); iface != nil { - if mac := iface.MacAddress(); mac != nil { - er.MacAddress = mac.String() - } - if ip := iface.Address(); ip != nil && len(ip.IP) > 0 { - er.IPv4Address = ip.String() - } - - if ipv6 := iface.AddressIPv6(); ipv6 != nil && len(ipv6.IP) > 0 { - er.IPv6Address = ipv6.String() - } - } - return er -} diff --git a/vendor/github.com/docker/docker/api/server/router/router.go b/vendor/github.com/docker/docker/api/server/router/router.go deleted file mode 100644 index f3efa82f..00000000 --- a/vendor/github.com/docker/docker/api/server/router/router.go +++ /dev/null @@ -1,18 +0,0 @@ -package router - -import "github.com/docker/docker/api/server/httputils" - -// Router defines an interface to specify a group of routes to add the the docker server. -type Router interface { - Routes() []Route -} - -// Route defines an individual API route in the docker server. -type Route interface { - // Handler returns the raw function to create the http handler. - Handler() httputils.APIFunc - // Method returns the http method that the route responds to. - Method() string - // Path returns the subpath where the route responds to. - Path() string -} diff --git a/vendor/github.com/docker/docker/api/server/router/volume/backend.go b/vendor/github.com/docker/docker/api/server/router/volume/backend.go deleted file mode 100644 index aa69972c..00000000 --- a/vendor/github.com/docker/docker/api/server/router/volume/backend.go +++ /dev/null @@ -1,16 +0,0 @@ -package volume - -import ( - // TODO return types need to be refactored into pkg - "github.com/docker/docker/api/types" -) - -// Backend is the methods that need to be implemented to provide -// volume specific functionality -type Backend interface { - Volumes(filter string) ([]*types.Volume, error) - VolumeInspect(name string) (*types.Volume, error) - VolumeCreate(name, driverName string, - opts map[string]string) (*types.Volume, error) - VolumeRm(name string) error -} diff --git a/vendor/github.com/docker/docker/api/server/router/volume/volume.go b/vendor/github.com/docker/docker/api/server/router/volume/volume.go deleted file mode 100644 index 8bd5c129..00000000 --- a/vendor/github.com/docker/docker/api/server/router/volume/volume.go +++ /dev/null @@ -1,38 +0,0 @@ -package volume - -import ( - "github.com/docker/docker/api/server/router" - "github.com/docker/docker/api/server/router/local" -) - -// volumeRouter is a router to talk with the volumes controller -type volumeRouter struct { - backend Backend - routes []router.Route -} - -// NewRouter initializes a new volumeRouter -func NewRouter(b Backend) router.Router { - r := &volumeRouter{ - backend: b, - } - r.initRoutes() - return r -} - -//Routes returns the available routers to the volumes controller -func (r *volumeRouter) Routes() []router.Route { - return r.routes -} - -func (r *volumeRouter) initRoutes() { - r.routes = []router.Route{ - // GET - local.NewGetRoute("/volumes", r.getVolumesList), - local.NewGetRoute("/volumes/{name:.*}", r.getVolumeByName), - // POST - local.NewPostRoute("/volumes/create", r.postVolumesCreate), - // DELETE - local.NewDeleteRoute("/volumes/{name:.*}", r.deleteVolumes), - } -} diff --git a/vendor/github.com/docker/docker/api/server/router/volume/volume_routes.go b/vendor/github.com/docker/docker/api/server/router/volume/volume_routes.go deleted file mode 100644 index 5b0787c5..00000000 --- a/vendor/github.com/docker/docker/api/server/router/volume/volume_routes.go +++ /dev/null @@ -1,66 +0,0 @@ -package volume - -import ( - "encoding/json" - "net/http" - - "github.com/docker/docker/api/server/httputils" - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -func (v *volumeRouter) getVolumesList(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - volumes, err := v.backend.Volumes(r.Form.Get("filters")) - if err != nil { - return err - } - return httputils.WriteJSON(w, http.StatusOK, &types.VolumesListResponse{Volumes: volumes}) -} - -func (v *volumeRouter) getVolumeByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - volume, err := v.backend.VolumeInspect(vars["name"]) - if err != nil { - return err - } - return httputils.WriteJSON(w, http.StatusOK, volume) -} - -func (v *volumeRouter) postVolumesCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - - if err := httputils.CheckForJSON(r); err != nil { - return err - } - - var req types.VolumeCreateRequest - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return err - } - - volume, err := v.backend.VolumeCreate(req.Name, req.Driver, req.DriverOpts) - if err != nil { - return err - } - return httputils.WriteJSON(w, http.StatusCreated, volume) -} - -func (v *volumeRouter) deleteVolumes(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := httputils.ParseForm(r); err != nil { - return err - } - if err := v.backend.VolumeRm(vars["name"]); err != nil { - return err - } - w.WriteHeader(http.StatusNoContent) - return nil -} diff --git a/vendor/github.com/docker/docker/api/server/server.go b/vendor/github.com/docker/docker/api/server/server.go deleted file mode 100644 index b90d704c..00000000 --- a/vendor/github.com/docker/docker/api/server/server.go +++ /dev/null @@ -1,218 +0,0 @@ -package server - -import ( - "crypto/tls" - "net" - "net/http" - "os" - "strings" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/api/server/httputils" - "github.com/docker/docker/api/server/router" - "github.com/docker/docker/api/server/router/local" - "github.com/docker/docker/api/server/router/network" - "github.com/docker/docker/api/server/router/volume" - "github.com/docker/docker/daemon" - "github.com/docker/docker/pkg/sockets" - "github.com/docker/docker/utils" - "github.com/gorilla/mux" - "golang.org/x/net/context" -) - -// versionMatcher defines a variable matcher to be parsed by the router -// when a request is about to be served. -const versionMatcher = "/v{version:[0-9.]+}" - -// Config provides the configuration for the API server -type Config struct { - Logging bool - EnableCors bool - CorsHeaders string - Version string - SocketGroup string - TLSConfig *tls.Config - Addrs []Addr -} - -// Server contains instance details for the server -type Server struct { - cfg *Config - start chan struct{} - servers []*HTTPServer - routers []router.Router -} - -// Addr contains string representation of address and its protocol (tcp, unix...). -type Addr struct { - Proto string - Addr string -} - -// New returns a new instance of the server based on the specified configuration. -// It allocates resources which will be needed for ServeAPI(ports, unix-sockets). -func New(cfg *Config) (*Server, error) { - s := &Server{ - cfg: cfg, - start: make(chan struct{}), - } - for _, addr := range cfg.Addrs { - srv, err := s.newServer(addr.Proto, addr.Addr) - if err != nil { - return nil, err - } - logrus.Debugf("Server created for HTTP on %s (%s)", addr.Proto, addr.Addr) - s.servers = append(s.servers, srv...) - } - return s, nil -} - -// Close closes servers and thus stop receiving requests -func (s *Server) Close() { - for _, srv := range s.servers { - if err := srv.Close(); err != nil { - logrus.Error(err) - } - } -} - -// ServeAPI loops through all initialized servers and spawns goroutine -// with Serve() method for each. -func (s *Server) ServeAPI() error { - var chErrors = make(chan error, len(s.servers)) - for _, srv := range s.servers { - go func(srv *HTTPServer) { - var err error - logrus.Infof("API listen on %s", srv.l.Addr()) - if err = srv.Serve(); err != nil && strings.Contains(err.Error(), "use of closed network connection") { - err = nil - } - chErrors <- err - }(srv) - } - - for i := 0; i < len(s.servers); i++ { - err := <-chErrors - if err != nil { - return err - } - } - - return nil -} - -// HTTPServer contains an instance of http server and the listener. -// srv *http.Server, contains configuration to create a http server and a mux router with all api end points. -// l net.Listener, is a TCP or Socket listener that dispatches incoming request to the router. -type HTTPServer struct { - srv *http.Server - l net.Listener -} - -// Serve starts listening for inbound requests. -func (s *HTTPServer) Serve() error { - return s.srv.Serve(s.l) -} - -// Close closes the HTTPServer from listening for the inbound requests. -func (s *HTTPServer) Close() error { - return s.l.Close() -} - -func writeCorsHeaders(w http.ResponseWriter, r *http.Request, corsHeaders string) { - logrus.Debugf("CORS header is enabled and set to: %s", corsHeaders) - w.Header().Add("Access-Control-Allow-Origin", corsHeaders) - w.Header().Add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Registry-Auth") - w.Header().Add("Access-Control-Allow-Methods", "HEAD, GET, POST, DELETE, PUT, OPTIONS") -} - -func (s *Server) initTCPSocket(addr string) (l net.Listener, err error) { - if s.cfg.TLSConfig == nil || s.cfg.TLSConfig.ClientAuth != tls.RequireAndVerifyClientCert { - logrus.Warn("/!\\ DON'T BIND ON ANY IP ADDRESS WITHOUT setting -tlsverify IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\") - } - if l, err = sockets.NewTCPSocket(addr, s.cfg.TLSConfig, s.start); err != nil { - return nil, err - } - if err := allocateDaemonPort(addr); err != nil { - return nil, err - } - return -} - -func (s *Server) makeHTTPHandler(handler httputils.APIFunc) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - // log the handler call - logrus.Debugf("Calling %s %s", r.Method, r.URL.Path) - - // Define the context that we'll pass around to share info - // like the docker-request-id. - // - // The 'context' will be used for global data that should - // apply to all requests. Data that is specific to the - // immediate function being called should still be passed - // as 'args' on the function call. - ctx := context.Background() - handlerFunc := s.handleWithGlobalMiddlewares(handler) - - vars := mux.Vars(r) - if vars == nil { - vars = make(map[string]string) - } - - if err := handlerFunc(ctx, w, r, vars); err != nil { - logrus.Errorf("Handler for %s %s returned error: %s", r.Method, r.URL.Path, utils.GetErrorMessage(err)) - httputils.WriteError(w, err) - } - } -} - -// InitRouters initializes a list of routers for the server. -// Sets those routers as Handler for each server. -func (s *Server) InitRouters(d *daemon.Daemon) { - s.addRouter(local.NewRouter(d)) - s.addRouter(network.NewRouter(d)) - s.addRouter(volume.NewRouter(d)) - - for _, srv := range s.servers { - srv.srv.Handler = s.CreateMux() - } -} - -// addRouter adds a new router to the server. -func (s *Server) addRouter(r router.Router) { - s.routers = append(s.routers, r) -} - -// CreateMux initializes the main router the server uses. -// we keep enableCors just for legacy usage, need to be removed in the future -func (s *Server) CreateMux() *mux.Router { - m := mux.NewRouter() - if os.Getenv("DEBUG") != "" { - profilerSetup(m, "/debug/") - } - - logrus.Debugf("Registering routers") - for _, apiRouter := range s.routers { - for _, r := range apiRouter.Routes() { - f := s.makeHTTPHandler(r.Handler()) - - logrus.Debugf("Registering %s, %s", r.Method(), r.Path()) - m.Path(versionMatcher + r.Path()).Methods(r.Method()).Handler(f) - m.Path(r.Path()).Methods(r.Method()).Handler(f) - } - } - - return m -} - -// AcceptConnections allows clients to connect to the API server. -// Referenced Daemon is notified about this server, and waits for the -// daemon acknowledgement before the incoming connections are accepted. -func (s *Server) AcceptConnections() { - // close the lock so the listeners start accepting connections - select { - case <-s.start: - default: - close(s.start) - } -} diff --git a/vendor/github.com/docker/docker/api/server/server_test.go b/vendor/github.com/docker/docker/api/server/server_test.go deleted file mode 100644 index f3256c31..00000000 --- a/vendor/github.com/docker/docker/api/server/server_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package server - -import ( - "net/http" - "net/http/httptest" - "testing" - - "github.com/docker/docker/api/server/httputils" - - "golang.org/x/net/context" -) - -func TestMiddlewares(t *testing.T) { - cfg := &Config{} - srv := &Server{ - cfg: cfg, - } - - req, _ := http.NewRequest("GET", "/containers/json", nil) - resp := httptest.NewRecorder() - ctx := context.Background() - - localHandler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if httputils.VersionFromContext(ctx) == "" { - t.Fatalf("Expected version, got empty string") - } - return nil - } - - handlerFunc := srv.handleWithGlobalMiddlewares(localHandler) - if err := handlerFunc(ctx, resp, req, map[string]string{}); err != nil { - t.Fatal(err) - } -} diff --git a/vendor/github.com/docker/docker/api/server/server_unix.go b/vendor/github.com/docker/docker/api/server/server_unix.go deleted file mode 100644 index c3d4def8..00000000 --- a/vendor/github.com/docker/docker/api/server/server_unix.go +++ /dev/null @@ -1,123 +0,0 @@ -// +build freebsd linux - -package server - -import ( - "fmt" - "net" - "net/http" - "strconv" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/pkg/sockets" - "github.com/docker/libnetwork/portallocator" - - systemdActivation "github.com/coreos/go-systemd/activation" -) - -// newServer sets up the required HTTPServers and does protocol specific checking. -// newServer does not set any muxers, you should set it later to Handler field -func (s *Server) newServer(proto, addr string) ([]*HTTPServer, error) { - var ( - err error - ls []net.Listener - ) - switch proto { - case "fd": - ls, err = listenFD(addr) - if err != nil { - return nil, err - } - case "tcp": - l, err := s.initTCPSocket(addr) - if err != nil { - return nil, err - } - ls = append(ls, l) - case "unix": - l, err := sockets.NewUnixSocket(addr, s.cfg.SocketGroup, s.start) - if err != nil { - return nil, err - } - ls = append(ls, l) - default: - return nil, fmt.Errorf("Invalid protocol format: %q", proto) - } - var res []*HTTPServer - for _, l := range ls { - res = append(res, &HTTPServer{ - &http.Server{ - Addr: addr, - }, - l, - }) - } - return res, 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) - } - - pa := portallocator.Get() - for _, hostIP := range hostIPs { - if _, err := pa.RequestPort(hostIP, "tcp", intPort); err != nil { - return fmt.Errorf("failed to allocate daemon listening port %d (err: %v)", intPort, err) - } - } - return nil -} - -// listenFD returns the specified socket activated files as a slice of -// net.Listeners or all of the activated files if "*" is given. -func listenFD(addr string) ([]net.Listener, error) { - // socket activation - listeners, err := systemdActivation.Listeners(false) - if err != nil { - return nil, err - } - - if len(listeners) == 0 { - return nil, fmt.Errorf("No sockets found") - } - - // default to all fds just like unix:// and tcp:// - if addr == "" || addr == "*" { - return listeners, nil - } - - fdNum, err := strconv.Atoi(addr) - if err != nil { - return nil, fmt.Errorf("failed to parse systemd address, should be number: %v", err) - } - fdOffset := fdNum - 3 - if len(listeners) < int(fdOffset)+1 { - return nil, fmt.Errorf("Too few socket activated files passed in") - } - if listeners[fdOffset] == nil { - return nil, fmt.Errorf("failed to listen on systemd activated file at fd %d", fdOffset+3) - } - for i, ls := range listeners { - if i == fdOffset || ls == nil { - continue - } - if err := ls.Close(); err != nil { - logrus.Errorf("Failed to close systemd activated file at fd %d: %v", fdOffset+3, err) - } - } - return []net.Listener{listeners[fdOffset]}, nil -} diff --git a/vendor/github.com/docker/docker/api/server/server_windows.go b/vendor/github.com/docker/docker/api/server/server_windows.go deleted file mode 100644 index 826dd2e0..00000000 --- a/vendor/github.com/docker/docker/api/server/server_windows.go +++ /dev/null @@ -1,43 +0,0 @@ -// +build windows - -package server - -import ( - "errors" - "net" - "net/http" -) - -// NewServer sets up the required Server and does protocol specific checking. -func (s *Server) newServer(proto, addr string) ([]*HTTPServer, error) { - var ( - ls []net.Listener - ) - switch proto { - case "tcp": - l, err := s.initTCPSocket(addr) - if err != nil { - return nil, err - } - ls = append(ls, l) - - default: - return nil, errors.New("Invalid protocol format. Windows only supports tcp.") - } - - var res []*HTTPServer - for _, l := range ls { - res = append(res, &HTTPServer{ - &http.Server{ - Addr: addr, - }, - l, - }) - } - return res, nil - -} - -func allocateDaemonPort(addr string) error { - return nil -} diff --git a/vendor/github.com/docker/docker/api/types/stats.go b/vendor/github.com/docker/docker/api/types/stats.go deleted file mode 100644 index ecc144f6..00000000 --- a/vendor/github.com/docker/docker/api/types/stats.go +++ /dev/null @@ -1,105 +0,0 @@ -// Package types is used for API stability in the types and response to the -// consumers of the API stats endpoint. -package types - -import "time" - -// ThrottlingData stores CPU throttling stats of one running container -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"` -} - -// CPUUsage stores All CPU stats 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"` -} - -// CPUStats aggregates and wraps all CPU related info of container -type CPUStats struct { - CPUUsage CPUUsage `json:"cpu_usage"` - SystemUsage uint64 `json:"system_cpu_usage"` - ThrottlingData ThrottlingData `json:"throttling_data,omitempty"` -} - -// MemoryStats aggregates All memory stats since container inception -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"` -} - -// BlkioStatEntry is one small entity to store a piece of Blkio stats -// TODO Windows: This can be factored out -type BlkioStatEntry struct { - Major uint64 `json:"major"` - Minor uint64 `json:"minor"` - Op string `json:"op"` - Value uint64 `json:"value"` -} - -// BlkioStats stores All IO service stats for data read and write -// TODO Windows: This can be factored out -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"` -} - -// NetworkStats aggregates All network stats of one container -// TODO Windows: This will require refactoring -type NetworkStats struct { - RxBytes uint64 `json:"rx_bytes"` - RxPackets uint64 `json:"rx_packets"` - RxErrors uint64 `json:"rx_errors"` - RxDropped uint64 `json:"rx_dropped"` - TxBytes uint64 `json:"tx_bytes"` - TxPackets uint64 `json:"tx_packets"` - TxErrors uint64 `json:"tx_errors"` - TxDropped uint64 `json:"tx_dropped"` -} - -// Stats is Ultimate struct aggregating all types of stats of one container -type Stats struct { - Read time.Time `json:"read"` - PreCPUStats CPUStats `json:"precpu_stats,omitempty"` - CPUStats CPUStats `json:"cpu_stats,omitempty"` - MemoryStats MemoryStats `json:"memory_stats,omitempty"` - BlkioStats BlkioStats `json:"blkio_stats,omitempty"` -} - -// StatsJSON is newly used Networks -type StatsJSON struct { - Stats - - // Networks request version >=1.21 - Networks map[string]NetworkStats `json:"networks,omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/types.go b/vendor/github.com/docker/docker/api/types/types.go deleted file mode 100644 index a6cec44a..00000000 --- a/vendor/github.com/docker/docker/api/types/types.go +++ /dev/null @@ -1,392 +0,0 @@ -package types - -import ( - "os" - "time" - - "github.com/docker/docker/daemon/network" - "github.com/docker/docker/pkg/nat" - "github.com/docker/docker/pkg/version" - "github.com/docker/docker/registry" - "github.com/docker/docker/runconfig" -) - -// ContainerCreateResponse contains the information returned to a client on the -// creation of a new container. -type ContainerCreateResponse struct { - // ID is the ID of the created container. - ID string `json:"Id"` - - // Warnings are any warnings encountered during the creation of the container. - Warnings []string `json:"Warnings"` -} - -// ContainerExecCreateResponse contains response of Remote API: -// POST "/containers/{name:.*}/exec" -type ContainerExecCreateResponse struct { - // ID is the exec ID. - ID string `json:"Id"` -} - -// AuthResponse contains response of Remote API: -// POST "/auth" -type AuthResponse struct { - // Status is the authentication status - Status string `json:"Status"` -} - -// ContainerWaitResponse contains response of Remote API: -// POST "/containers/"+containerID+"/wait" -type ContainerWaitResponse struct { - // StatusCode is the status code of the wait job - StatusCode int `json:"StatusCode"` -} - -// ContainerCommitResponse contains response of Remote API: -// POST "/commit?container="+containerID -type ContainerCommitResponse struct { - ID string `json:"Id"` -} - -// ContainerChange contains response of Remote API: -// GET "/containers/{name:.*}/changes" -type ContainerChange struct { - Kind int - Path string -} - -// ImageHistory contains response of Remote API: -// GET "/images/{name:.*}/history" -type ImageHistory struct { - ID string `json:"Id"` - Created int64 - CreatedBy string - Tags []string - Size int64 - Comment string -} - -// ImageDelete contains response of Remote API: -// DELETE "/images/{name:.*}" -type ImageDelete struct { - Untagged string `json:",omitempty"` - Deleted string `json:",omitempty"` -} - -// Image contains response of Remote API: -// GET "/images/json" -type Image struct { - ID string `json:"Id"` - ParentID string `json:"ParentId"` - RepoTags []string - RepoDigests []string - Created int64 - Size int64 - VirtualSize int64 - Labels map[string]string -} - -// GraphDriverData returns Image's graph driver config info -// when calling inspect command -type GraphDriverData struct { - Name string - Data map[string]string -} - -// ImageInspect contains response of Remote API: -// GET "/images/{name:.*}/json" -type ImageInspect struct { - ID string `json:"Id"` - RepoTags []string - RepoDigests []string - Parent string - Comment string - Created string - Container string - ContainerConfig *runconfig.Config - DockerVersion string - Author string - Config *runconfig.Config - Architecture string - Os string - Size int64 - VirtualSize int64 - GraphDriver GraphDriverData -} - -// Port stores open ports info of container -// e.g. {"PrivatePort": 8080, "PublicPort": 80, "Type": "tcp"} -type Port struct { - IP string `json:",omitempty"` - PrivatePort int - PublicPort int `json:",omitempty"` - Type string -} - -// Container contains response of Remote API: -// GET "/containers/json" -type Container struct { - ID string `json:"Id"` - Names []string - Image string - ImageID string - Command string - Created int64 - Ports []Port - SizeRw int64 `json:",omitempty"` - SizeRootFs int64 `json:",omitempty"` - Labels map[string]string - Status string - HostConfig struct { - NetworkMode string `json:",omitempty"` - } -} - -// CopyConfig contains request body of Remote API: -// POST "/containers/"+containerID+"/copy" -type CopyConfig struct { - Resource string -} - -// ContainerPathStat is used to encode the header from -// GET "/containers/{name:.*}/archive" -// "Name" is the file or directory name. -type ContainerPathStat struct { - Name string `json:"name"` - Size int64 `json:"size"` - Mode os.FileMode `json:"mode"` - Mtime time.Time `json:"mtime"` - LinkTarget string `json:"linkTarget"` -} - -// ContainerProcessList contains response of Remote API: -// GET "/containers/{name:.*}/top" -type ContainerProcessList struct { - Processes [][]string - Titles []string -} - -// Version contains response of Remote API: -// GET "/version" -type Version struct { - Version string - APIVersion version.Version `json:"ApiVersion"` - GitCommit string - GoVersion string - Os string - Arch string - KernelVersion string `json:",omitempty"` - Experimental bool `json:",omitempty"` - BuildTime string `json:",omitempty"` -} - -// Info contains response of Remote API: -// GET "/info" -type Info struct { - ID string - Containers int - Images int - Driver string - DriverStatus [][2]string - MemoryLimit bool - SwapLimit bool - CPUCfsPeriod bool `json:"CpuCfsPeriod"` - CPUCfsQuota bool `json:"CpuCfsQuota"` - IPv4Forwarding bool - BridgeNfIptables bool - BridgeNfIP6tables bool `json:"BridgeNfIp6tables"` - Debug bool - NFd int - OomKillDisable bool - NGoroutines int - SystemTime string - ExecutionDriver string - LoggingDriver string - NEventsListener int - KernelVersion string - OperatingSystem string - IndexServerAddress string - RegistryConfig *registry.ServiceConfig - InitSha1 string - InitPath string - NCPU int - MemTotal int64 - DockerRootDir string - HTTPProxy string `json:"HttpProxy"` - HTTPSProxy string `json:"HttpsProxy"` - NoProxy string - Name string - Labels []string - ExperimentalBuild bool - ServerVersion string - ClusterStore string - ClusterAdvertise string -} - -// ExecStartCheck is a temp struct used by execStart -// Config fields is part of ExecConfig in runconfig package -type ExecStartCheck struct { - // ExecStart will first check if it's detached - Detach bool - // Check if there's a tty - Tty bool -} - -// ContainerState stores container's running state -// it's part of ContainerJSONBase and will return by "inspect" command -type ContainerState struct { - Status string - Running bool - Paused bool - Restarting bool - OOMKilled bool - Dead bool - Pid int - ExitCode int - Error string - StartedAt string - FinishedAt string -} - -// ContainerJSONBase contains response of Remote API: -// GET "/containers/{name:.*}/json" -type ContainerJSONBase struct { - ID string `json:"Id"` - Created string - Path string - Args []string - State *ContainerState - Image string - ResolvConfPath string - HostnamePath string - HostsPath string - LogPath string - Name string - RestartCount int - Driver string - MountLabel string - ProcessLabel string - AppArmorProfile string - ExecIDs []string - HostConfig *runconfig.HostConfig - GraphDriver GraphDriverData - SizeRw *int64 `json:",omitempty"` - SizeRootFs *int64 `json:",omitempty"` -} - -// ContainerJSON is newly used struct along with MountPoint -type ContainerJSON struct { - *ContainerJSONBase - Mounts []MountPoint - Config *runconfig.Config - NetworkSettings *NetworkSettings -} - -// NetworkSettings exposes the network settings in the api -type NetworkSettings struct { - NetworkSettingsBase - DefaultNetworkSettings - Networks map[string]*network.EndpointSettings -} - -// NetworkSettingsBase holds basic information about networks -type NetworkSettingsBase struct { - Bridge string - SandboxID string - HairpinMode bool - LinkLocalIPv6Address string - LinkLocalIPv6PrefixLen int - Ports nat.PortMap - SandboxKey string - SecondaryIPAddresses []network.Address - SecondaryIPv6Addresses []network.Address -} - -// DefaultNetworkSettings holds network information -// during the 2 release deprecation period. -// It will be removed in Docker 1.11. -type DefaultNetworkSettings struct { - EndpointID string - Gateway string - GlobalIPv6Address string - GlobalIPv6PrefixLen int - IPAddress string - IPPrefixLen int - IPv6Gateway string - MacAddress string -} - -// MountPoint represents a mount point configuration inside the container. -type MountPoint struct { - Name string `json:",omitempty"` - Source string - Destination string - Driver string `json:",omitempty"` - Mode string - RW bool -} - -// Volume represents the configuration of a volume for the remote API -type Volume struct { - Name string // Name is the name of the volume - Driver string // Driver is the Driver name used to create the volume - Mountpoint string // Mountpoint is the location on disk of the volume -} - -// VolumesListResponse contains the response for the remote API: -// GET "/volumes" -type VolumesListResponse struct { - Volumes []*Volume // Volumes is the list of volumes being returned -} - -// VolumeCreateRequest contains the response for the remote API: -// POST "/volumes/create" -type VolumeCreateRequest struct { - Name string // Name is the requested name of the volume - Driver string // Driver is the name of the driver that should be used to create the volume - DriverOpts map[string]string // DriverOpts holds the driver specific options to use for when creating the volume. -} - -// NetworkResource is the body of the "get network" http response message -type NetworkResource struct { - Name string - ID string `json:"Id"` - Scope string - Driver string - IPAM network.IPAM - Containers map[string]EndpointResource - Options map[string]string -} - -// EndpointResource contains network resources allocated and used for a container in a network -type EndpointResource struct { - EndpointID string - MacAddress string - IPv4Address string - IPv6Address string -} - -// NetworkCreate is the expected body of the "create network" http request message -type NetworkCreate struct { - Name string - CheckDuplicate bool - Driver string - IPAM network.IPAM - Options map[string]string -} - -// NetworkCreateResponse is the response message sent by the server for network create call -type NetworkCreateResponse struct { - ID string `json:"Id"` - Warning string -} - -// NetworkConnect represents the data to be used to connect a container to the network -type NetworkConnect struct { - Container string -} - -// NetworkDisconnect represents the data to be used to disconnect a container from the network -type NetworkDisconnect struct { - Container string -} diff --git a/vendor/github.com/docker/docker/api/types/versions/README.md b/vendor/github.com/docker/docker/api/types/versions/README.md deleted file mode 100644 index 76c516e6..00000000 --- a/vendor/github.com/docker/docker/api/types/versions/README.md +++ /dev/null @@ -1,14 +0,0 @@ -## Legacy API type versions - -This package includes types for legacy API versions. The stable version of the API types live in `api/types/*.go`. - -Consider moving a type here when you need to keep backwards compatibility in the API. This legacy types are organized by the latest API version they appear in. For instance, types in the `v1p19` package are valid for API versions below or equal `1.19`. Types in the `v1p20` package are valid for the API version `1.20`, since the versions below that will use the legacy types in `v1p19`. - -### Package name conventions - -The package name convention is to use `v` as a prefix for the version number and `p`(patch) as a separator. We use this nomenclature due to a few restrictions in the Go package name convention: - -1. We cannot use `.` because it's interpreted by the language, think of `v1.20.CallFunction`. -2. We cannot use `_` because golint complains abount it. The code is actually valid, but it looks probably more weird: `v1_20.CallFunction`. - -For instance, if you want to modify a type that was available in the version `1.21` of the API but it will have different fields in the version `1.22`, you want to create a new package under `api/types/versions/v1p21`. diff --git a/vendor/github.com/docker/docker/api/types/versions/v1p19/types.go b/vendor/github.com/docker/docker/api/types/versions/v1p19/types.go deleted file mode 100644 index a66aa9d5..00000000 --- a/vendor/github.com/docker/docker/api/types/versions/v1p19/types.go +++ /dev/null @@ -1,35 +0,0 @@ -// Package v1p19 provides specific API types for the API version 1, patch 19. -package v1p19 - -import ( - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/versions/v1p20" - "github.com/docker/docker/pkg/nat" - "github.com/docker/docker/runconfig" -) - -// ContainerJSON is a backcompatibility struct for APIs prior to 1.20. -// Note this is not used by the Windows daemon. -type ContainerJSON struct { - *types.ContainerJSONBase - Volumes map[string]string - VolumesRW map[string]bool - Config *ContainerConfig - NetworkSettings *v1p20.NetworkSettings -} - -// ContainerConfig is a backcompatibility struct for APIs prior to 1.20. -type ContainerConfig struct { - *runconfig.Config - - MacAddress string - NetworkDisabled bool - ExposedPorts map[nat.Port]struct{} - - // backward compatibility, they now live in HostConfig - VolumeDriver string - Memory int64 - MemorySwap int64 - CPUShares int64 `json:"CpuShares"` - CPUSet string `json:"Cpuset"` -} diff --git a/vendor/github.com/docker/docker/api/types/versions/v1p20/types.go b/vendor/github.com/docker/docker/api/types/versions/v1p20/types.go deleted file mode 100644 index 0facbb66..00000000 --- a/vendor/github.com/docker/docker/api/types/versions/v1p20/types.go +++ /dev/null @@ -1,40 +0,0 @@ -// Package v1p20 provides specific API types for the API version 1, patch 20. -package v1p20 - -import ( - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/nat" - "github.com/docker/docker/runconfig" -) - -// ContainerJSON is a backcompatibility struct for the API 1.20 -type ContainerJSON struct { - *types.ContainerJSONBase - Mounts []types.MountPoint - Config *ContainerConfig - NetworkSettings *NetworkSettings -} - -// ContainerConfig is a backcompatibility struct used in ContainerJSON for the API 1.20 -type ContainerConfig struct { - *runconfig.Config - - MacAddress string - NetworkDisabled bool - ExposedPorts map[nat.Port]struct{} - - // backward compatibility, they now live in HostConfig - VolumeDriver string -} - -// StatsJSON is a backcompatibility struct used in Stats for API prior to 1.21 -type StatsJSON struct { - types.Stats - Network types.NetworkStats `json:"network,omitempty"` -} - -// NetworkSettings is a backward compatible struct for APIs prior to 1.21 -type NetworkSettings struct { - types.NetworkSettingsBase - types.DefaultNetworkSettings -} diff --git a/vendor/github.com/docker/docker/daemon/README.md b/vendor/github.com/docker/docker/daemon/README.md deleted file mode 100644 index 1778983f..00000000 --- a/vendor/github.com/docker/docker/daemon/README.md +++ /dev/null @@ -1,9 +0,0 @@ -This directory contains code pertaining to running containers and storing images - -Code pertaining to running containers: - - - execdriver - -Code pertaining to storing images: - - - graphdriver diff --git a/vendor/github.com/docker/docker/daemon/archive.go b/vendor/github.com/docker/docker/daemon/archive.go deleted file mode 100644 index f4a82478..00000000 --- a/vendor/github.com/docker/docker/daemon/archive.go +++ /dev/null @@ -1,389 +0,0 @@ -package daemon - -import ( - "errors" - "io" - "os" - "path/filepath" - "strings" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/chrootarchive" - "github.com/docker/docker/pkg/ioutils" -) - -// ErrExtractPointNotDirectory is used to convey that the operation to extract -// a tar archive to a directory in a container has failed because the specified -// path does not refer to a directory. -var ErrExtractPointNotDirectory = errors.New("extraction point is not a directory") - -// ContainerCopy performs a deprecated operation of archiving the resource at -// the specified path in the conatiner identified by the given name. -func (daemon *Daemon) ContainerCopy(name string, res string) (io.ReadCloser, error) { - container, err := daemon.Get(name) - if err != nil { - return nil, err - } - - if res[0] == '/' || res[0] == '\\' { - res = res[1:] - } - - return daemon.containerCopy(container, res) -} - -// ContainerStatPath stats the filesystem resource at the specified path in the -// container identified by the given name. -func (daemon *Daemon) ContainerStatPath(name string, path string) (stat *types.ContainerPathStat, err error) { - container, err := daemon.Get(name) - if err != nil { - return nil, err - } - - return daemon.containerStatPath(container, path) -} - -// ContainerArchivePath creates an archive of the filesystem resource at the -// specified path in the container identified by the given name. Returns a -// tar archive of the resource and whether it was a directory or a single file. -func (daemon *Daemon) ContainerArchivePath(name string, path string) (content io.ReadCloser, stat *types.ContainerPathStat, err error) { - container, err := daemon.Get(name) - if err != nil { - return nil, nil, err - } - - return daemon.containerArchivePath(container, path) -} - -// ContainerExtractToDir extracts the given archive to the specified location -// in the filesystem of the container identified by the given name. The given -// path must be of a directory in the container. If it is not, the error will -// be ErrExtractPointNotDirectory. If noOverwriteDirNonDir is true then it will -// be an error if unpacking the given content would cause an existing directory -// to be replaced with a non-directory and vice versa. -func (daemon *Daemon) ContainerExtractToDir(name, path string, noOverwriteDirNonDir bool, content io.Reader) error { - container, err := daemon.Get(name) - if err != nil { - return err - } - - return daemon.containerExtractToDir(container, path, noOverwriteDirNonDir, content) -} - -// resolvePath resolves the given path in the container to a resource on the -// host. Returns a resolved path (absolute path to the resource on the host), -// the absolute path to the resource relative to the container's rootfs, and -// a error if the path points to outside the container's rootfs. -func (container *Container) resolvePath(path string) (resolvedPath, absPath string, err error) { - // Consider the given path as an absolute path in the container. - absPath = archive.PreserveTrailingDotOrSeparator(filepath.Join(string(filepath.Separator), path), path) - - // Split the absPath into its Directory and Base components. We will - // resolve the dir in the scope of the container then append the base. - dirPath, basePath := filepath.Split(absPath) - - resolvedDirPath, err := container.GetResourcePath(dirPath) - if err != nil { - return "", "", err - } - - // resolvedDirPath will have been cleaned (no trailing path separators) so - // we can manually join it with the base path element. - resolvedPath = resolvedDirPath + string(filepath.Separator) + basePath - - return resolvedPath, absPath, nil -} - -// statPath is the unexported version of StatPath. Locks and mounts should -// be acquired before calling this method and the given path should be fully -// resolved to a path on the host corresponding to the given absolute path -// inside the container. -func (container *Container) statPath(resolvedPath, absPath string) (stat *types.ContainerPathStat, err error) { - lstat, err := os.Lstat(resolvedPath) - if err != nil { - return nil, err - } - - var linkTarget string - if lstat.Mode()&os.ModeSymlink != 0 { - // Fully evaluate the symlink in the scope of the container rootfs. - hostPath, err := container.GetResourcePath(absPath) - if err != nil { - return nil, err - } - - linkTarget, err = filepath.Rel(container.basefs, hostPath) - if err != nil { - return nil, err - } - - // Make it an absolute path. - linkTarget = filepath.Join(string(filepath.Separator), linkTarget) - } - - return &types.ContainerPathStat{ - Name: filepath.Base(absPath), - Size: lstat.Size(), - Mode: lstat.Mode(), - Mtime: lstat.ModTime(), - LinkTarget: linkTarget, - }, nil -} - -// containerStatPath stats the filesystem resource at the specified path in this -// container. Returns stat info about the resource. -func (daemon *Daemon) containerStatPath(container *Container, path string) (stat *types.ContainerPathStat, err error) { - container.Lock() - defer container.Unlock() - - if err = daemon.Mount(container); err != nil { - return nil, err - } - defer daemon.Unmount(container) - - err = daemon.mountVolumes(container) - defer container.unmountVolumes(true) - if err != nil { - return nil, err - } - - resolvedPath, absPath, err := container.resolvePath(path) - if err != nil { - return nil, err - } - - return container.statPath(resolvedPath, absPath) -} - -// containerArchivePath creates an archive of the filesystem resource at the specified -// path in this container. Returns a tar archive of the resource and stat info -// about the resource. -func (daemon *Daemon) containerArchivePath(container *Container, path string) (content io.ReadCloser, stat *types.ContainerPathStat, err error) { - container.Lock() - - defer func() { - if err != nil { - // Wait to unlock the container until the archive is fully read - // (see the ReadCloseWrapper func below) or if there is an error - // before that occurs. - container.Unlock() - } - }() - - if err = daemon.Mount(container); err != nil { - return nil, nil, err - } - - defer func() { - if err != nil { - // unmount any volumes - container.unmountVolumes(true) - // unmount the container's rootfs - daemon.Unmount(container) - } - }() - - if err = daemon.mountVolumes(container); err != nil { - return nil, nil, err - } - - resolvedPath, absPath, err := container.resolvePath(path) - if err != nil { - return nil, nil, err - } - - stat, err = container.statPath(resolvedPath, absPath) - if err != nil { - return nil, nil, err - } - - // We need to rebase the archive entries if the last element of the - // resolved path was a symlink that was evaluated and is now different - // than the requested path. For example, if the given path was "/foo/bar/", - // but it resolved to "/var/lib/docker/containers/{id}/foo/baz/", we want - // to ensure that the archive entries start with "bar" and not "baz". This - // also catches the case when the root directory of the container is - // requested: we want the archive entries to start with "/" and not the - // container ID. - data, err := archive.TarResourceRebase(resolvedPath, filepath.Base(absPath)) - if err != nil { - return nil, nil, err - } - - content = ioutils.NewReadCloserWrapper(data, func() error { - err := data.Close() - container.unmountVolumes(true) - daemon.Unmount(container) - container.Unlock() - return err - }) - - daemon.LogContainerEvent(container, "archive-path") - - return content, stat, nil -} - -// containerExtractToDir extracts the given tar archive to the specified location in the -// filesystem of this container. The given path must be of a directory in the -// container. If it is not, the error will be ErrExtractPointNotDirectory. If -// noOverwriteDirNonDir is true then it will be an error if unpacking the -// given content would cause an existing directory to be replaced with a non- -// directory and vice versa. -func (daemon *Daemon) containerExtractToDir(container *Container, path string, noOverwriteDirNonDir bool, content io.Reader) (err error) { - container.Lock() - defer container.Unlock() - - if err = daemon.Mount(container); err != nil { - return err - } - defer daemon.Unmount(container) - - err = daemon.mountVolumes(container) - defer container.unmountVolumes(true) - if err != nil { - return err - } - - // The destination path needs to be resolved to a host path, with all - // symbolic links followed in the scope of the container's rootfs. Note - // that we do not use `container.resolvePath(path)` here because we need - // to also evaluate the last path element if it is a symlink. This is so - // that you can extract an archive to a symlink that points to a directory. - - // Consider the given path as an absolute path in the container. - absPath := archive.PreserveTrailingDotOrSeparator(filepath.Join(string(filepath.Separator), path), path) - - // This will evaluate the last path element if it is a symlink. - resolvedPath, err := container.GetResourcePath(absPath) - if err != nil { - return err - } - - stat, err := os.Lstat(resolvedPath) - if err != nil { - return err - } - - if !stat.IsDir() { - return ErrExtractPointNotDirectory - } - - // Need to check if the path is in a volume. If it is, it cannot be in a - // read-only volume. If it is not in a volume, the container cannot be - // configured with a read-only rootfs. - - // Use the resolved path relative to the container rootfs as the new - // absPath. This way we fully follow any symlinks in a volume that may - // lead back outside the volume. - // - // The Windows implementation of filepath.Rel in golang 1.4 does not - // support volume style file path semantics. On Windows when using the - // filter driver, we are guaranteed that the path will always be - // a volume file path. - var baseRel string - if strings.HasPrefix(resolvedPath, `\\?\Volume{`) { - if strings.HasPrefix(resolvedPath, container.basefs) { - baseRel = resolvedPath[len(container.basefs):] - if baseRel[:1] == `\` { - baseRel = baseRel[1:] - } - } - } else { - baseRel, err = filepath.Rel(container.basefs, resolvedPath) - } - if err != nil { - return err - } - // Make it an absolute path. - absPath = filepath.Join(string(filepath.Separator), baseRel) - - toVolume, err := checkIfPathIsInAVolume(container, absPath) - if err != nil { - return err - } - - if !toVolume && container.hostConfig.ReadonlyRootfs { - return ErrRootFSReadOnly - } - - options := &archive.TarOptions{ - ChownOpts: &archive.TarChownOptions{ - UID: 0, GID: 0, // TODO: use config.User? Remap to userns root? - }, - NoOverwriteDirNonDir: noOverwriteDirNonDir, - } - - if err := chrootarchive.Untar(content, resolvedPath, options); err != nil { - return err - } - - daemon.LogContainerEvent(container, "extract-to-dir") - - return nil -} - -func (daemon *Daemon) containerCopy(container *Container, resource string) (rc io.ReadCloser, err error) { - container.Lock() - - defer func() { - if err != nil { - // Wait to unlock the container until the archive is fully read - // (see the ReadCloseWrapper func below) or if there is an error - // before that occurs. - container.Unlock() - } - }() - - if err := daemon.Mount(container); err != nil { - return nil, err - } - - defer func() { - if err != nil { - // unmount any volumes - container.unmountVolumes(true) - // unmount the container's rootfs - daemon.Unmount(container) - } - }() - - if err := daemon.mountVolumes(container); err != nil { - return nil, err - } - - basePath, err := container.GetResourcePath(resource) - if err != nil { - return nil, err - } - stat, err := os.Stat(basePath) - if err != nil { - return nil, err - } - var filter []string - if !stat.IsDir() { - d, f := filepath.Split(basePath) - basePath = d - filter = []string{f} - } else { - filter = []string{filepath.Base(basePath)} - basePath = filepath.Dir(basePath) - } - archive, err := archive.TarWithOptions(basePath, &archive.TarOptions{ - Compression: archive.Uncompressed, - IncludeFiles: filter, - }) - if err != nil { - return nil, err - } - - reader := ioutils.NewReadCloserWrapper(archive, func() error { - err := archive.Close() - container.unmountVolumes(true) - daemon.Unmount(container) - container.Unlock() - return err - }) - daemon.LogContainerEvent(container, "copy") - return reader, nil -} diff --git a/vendor/github.com/docker/docker/daemon/archive_unix.go b/vendor/github.com/docker/docker/daemon/archive_unix.go deleted file mode 100644 index 7588d76d..00000000 --- a/vendor/github.com/docker/docker/daemon/archive_unix.go +++ /dev/null @@ -1,19 +0,0 @@ -// +build !windows - -package daemon - -// checkIfPathIsInAVolume checks if the path is in a volume. If it is, it -// cannot be in a read-only volume. If it is not in a volume, the container -// cannot be configured with a read-only rootfs. -func checkIfPathIsInAVolume(container *Container, absPath string) (bool, error) { - var toVolume bool - for _, mnt := range container.MountPoints { - if toVolume = mnt.HasResource(absPath); toVolume { - if mnt.RW { - break - } - return false, ErrVolumeReadonly - } - } - return toVolume, nil -} diff --git a/vendor/github.com/docker/docker/daemon/archive_windows.go b/vendor/github.com/docker/docker/daemon/archive_windows.go deleted file mode 100644 index 4e6c48a1..00000000 --- a/vendor/github.com/docker/docker/daemon/archive_windows.go +++ /dev/null @@ -1,10 +0,0 @@ -package daemon - -// checkIfPathIsInAVolume checks if the path is in a volume. If it is, it -// cannot be in a read-only volume. If it is not in a volume, the container -// cannot be configured with a read-only rootfs. -// -// This is a no-op on Windows which does not support volumes. -func checkIfPathIsInAVolume(container *Container, absPath string) (bool, error) { - return false, nil -} diff --git a/vendor/github.com/docker/docker/daemon/attach.go b/vendor/github.com/docker/docker/daemon/attach.go deleted file mode 100644 index 047828b1..00000000 --- a/vendor/github.com/docker/docker/daemon/attach.go +++ /dev/null @@ -1,123 +0,0 @@ -package daemon - -import ( - "io" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/daemon/logger" - "github.com/docker/docker/pkg/stdcopy" -) - -// ContainerAttachWithLogsConfig holds the streams to use when connecting to a container to view logs. -type ContainerAttachWithLogsConfig struct { - InStream io.ReadCloser - OutStream io.Writer - UseStdin, UseStdout, UseStderr bool - Logs, Stream bool -} - -// ContainerAttachWithLogs attaches to logs according to the config passed in. See ContainerAttachWithLogsConfig. -func (daemon *Daemon) ContainerAttachWithLogs(prefixOrName string, c *ContainerAttachWithLogsConfig) error { - container, err := daemon.Get(prefixOrName) - if err != nil { - return err - } - - var errStream io.Writer - - if !container.Config.Tty { - errStream = stdcopy.NewStdWriter(c.OutStream, stdcopy.Stderr) - c.OutStream = stdcopy.NewStdWriter(c.OutStream, stdcopy.Stdout) - } else { - errStream = c.OutStream - } - - var stdin io.ReadCloser - var stdout, stderr io.Writer - - if c.UseStdin { - stdin = c.InStream - } - if c.UseStdout { - stdout = c.OutStream - } - if c.UseStderr { - stderr = errStream - } - - return daemon.attachWithLogs(container, stdin, stdout, stderr, c.Logs, c.Stream) -} - -// ContainerWsAttachWithLogsConfig attach with websockets, since all -// stream data is delegated to the websocket to handle there. -type ContainerWsAttachWithLogsConfig struct { - InStream io.ReadCloser - OutStream, ErrStream io.Writer - Logs, Stream bool -} - -// ContainerWsAttachWithLogs websocket connection -func (daemon *Daemon) ContainerWsAttachWithLogs(prefixOrName string, c *ContainerWsAttachWithLogsConfig) error { - container, err := daemon.Get(prefixOrName) - if err != nil { - return err - } - return daemon.attachWithLogs(container, c.InStream, c.OutStream, c.ErrStream, c.Logs, c.Stream) -} - -func (daemon *Daemon) attachWithLogs(container *Container, stdin io.ReadCloser, stdout, stderr io.Writer, logs, stream bool) error { - if logs { - logDriver, err := daemon.getLogger(container) - if err != nil { - return err - } - cLog, ok := logDriver.(logger.LogReader) - if !ok { - return logger.ErrReadLogsNotSupported - } - logs := cLog.ReadLogs(logger.ReadConfig{Tail: -1}) - - LogLoop: - for { - select { - case msg, ok := <-logs.Msg: - if !ok { - break LogLoop - } - if msg.Source == "stdout" && stdout != nil { - stdout.Write(msg.Line) - } - if msg.Source == "stderr" && stderr != nil { - stderr.Write(msg.Line) - } - case err := <-logs.Err: - logrus.Errorf("Error streaming logs: %v", err) - break LogLoop - } - } - } - - daemon.LogContainerEvent(container, "attach") - - //stream - if stream { - var stdinPipe io.ReadCloser - if stdin != nil { - r, w := io.Pipe() - go func() { - defer w.Close() - defer logrus.Debugf("Closing buffered stdin pipe") - io.Copy(w, stdin) - }() - stdinPipe = r - } - <-container.Attach(stdinPipe, stdout, stderr) - // If we are in stdinonce mode, wait for the process to end - // otherwise, simply return - if container.Config.StdinOnce && !container.Config.Tty { - container.WaitStop(-1 * time.Second) - } - } - return nil -} diff --git a/vendor/github.com/docker/docker/daemon/changes.go b/vendor/github.com/docker/docker/daemon/changes.go deleted file mode 100644 index 181ac5a9..00000000 --- a/vendor/github.com/docker/docker/daemon/changes.go +++ /dev/null @@ -1,15 +0,0 @@ -package daemon - -import "github.com/docker/docker/pkg/archive" - -// ContainerChanges returns a list of container fs changes -func (daemon *Daemon) ContainerChanges(name string) ([]archive.Change, error) { - container, err := daemon.Get(name) - if err != nil { - return nil, err - } - - container.Lock() - defer container.Unlock() - return daemon.changes(container) -} diff --git a/vendor/github.com/docker/docker/daemon/commit.go b/vendor/github.com/docker/docker/daemon/commit.go deleted file mode 100644 index 61808eab..00000000 --- a/vendor/github.com/docker/docker/daemon/commit.go +++ /dev/null @@ -1,87 +0,0 @@ -package daemon - -import ( - "fmt" - "runtime" - - "github.com/docker/docker/image" - "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/ioutils" - "github.com/docker/docker/runconfig" -) - -// ContainerCommitConfig contains build configs for commit operation, -// and is used when making a commit with the current state of the container. -type ContainerCommitConfig struct { - Pause bool - Repo string - Tag string - Author string - Comment string - // merge container config into commit config before commit - MergeConfigs bool - Config *runconfig.Config -} - -// Commit creates a new filesystem image from the current state of a container. -// The image can optionally be tagged into a repository. -func (daemon *Daemon) Commit(name string, c *ContainerCommitConfig) (*image.Image, error) { - container, err := daemon.Get(name) - if err != nil { - return nil, err - } - - // It is not possible to commit a running container on Windows - if runtime.GOOS == "windows" && container.IsRunning() { - return nil, fmt.Errorf("Windows does not support commit of a running container") - } - - if c.Pause && !container.isPaused() { - daemon.containerPause(container) - defer daemon.containerUnpause(container) - } - - if c.MergeConfigs { - if err := runconfig.Merge(c.Config, container.Config); err != nil { - return nil, err - } - } - - rwTar, err := daemon.exportContainerRw(container) - if err != nil { - return nil, err - } - defer func() { - if rwTar != nil { - rwTar.Close() - } - }() - - // Create a new image from the container's base layers + a new layer from container changes - img, err := daemon.graph.Create(rwTar, container.ID, container.ImageID, c.Comment, c.Author, container.Config, c.Config) - if err != nil { - return nil, err - } - - // Register the image if needed - if c.Repo != "" { - if err := daemon.repositories.Tag(c.Repo, c.Tag, img.ID, true); err != nil { - return img, err - } - } - - daemon.LogContainerEvent(container, "commit") - return img, nil -} - -func (daemon *Daemon) exportContainerRw(container *Container) (archive.Archive, error) { - archive, err := daemon.diff(container) - if err != nil { - return nil, err - } - return ioutils.NewReadCloserWrapper(archive, func() error { - err := archive.Close() - return err - }), - nil -} diff --git a/vendor/github.com/docker/docker/daemon/config.go b/vendor/github.com/docker/docker/daemon/config.go deleted file mode 100644 index bc301a53..00000000 --- a/vendor/github.com/docker/docker/daemon/config.go +++ /dev/null @@ -1,75 +0,0 @@ -package daemon - -import ( - "github.com/docker/docker/opts" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/runconfig" -) - -const ( - defaultNetworkMtu = 1500 - disableNetworkBridge = "none" -) - -// CommonConfig defines the configuration of a docker daemon which are -// common across platforms. -type CommonConfig struct { - AutoRestart bool - Bridge bridgeConfig // Bridge holds bridge network specific configuration. - Context map[string][]string - DisableBridge bool - DNS []string - DNSOptions []string - DNSSearch []string - ExecOptions []string - ExecRoot string - GraphDriver string - GraphOptions []string - Labels []string - LogConfig runconfig.LogConfig - Mtu int - Pidfile string - RemappedRoot string - Root string - TrustKeyPath string - DefaultNetwork string - - // ClusterStore is the storage backend used for the cluster information. It is used by both - // multihost networking (to store networks and endpoints information) and by the node discovery - // mechanism. - ClusterStore string - - // ClusterOpts is used to pass options to the discovery package for tuning libkv settings, such - // as TLS configuration settings. - ClusterOpts map[string]string - - // ClusterAdvertise is the network endpoint that the Engine advertises for the purpose of node - // discovery. This should be a 'host:port' combination on which that daemon instance is - // reachable by other hosts. - ClusterAdvertise string -} - -// InstallCommonFlags adds command-line options to the top-level flag parser for -// the current process. -// Subsequent calls to `flag.Parse` will populate config with values parsed -// from the command-line. -func (config *Config) InstallCommonFlags(cmd *flag.FlagSet, usageFn func(string) string) { - cmd.Var(opts.NewListOptsRef(&config.GraphOptions, nil), []string{"-storage-opt"}, usageFn("Set storage driver options")) - cmd.Var(opts.NewListOptsRef(&config.ExecOptions, nil), []string{"-exec-opt"}, usageFn("Set exec driver options")) - cmd.StringVar(&config.Pidfile, []string{"p", "-pidfile"}, defaultPidFile, usageFn("Path to use for daemon PID file")) - cmd.StringVar(&config.Root, []string{"g", "-graph"}, defaultGraph, usageFn("Root of the Docker runtime")) - cmd.StringVar(&config.ExecRoot, []string{"-exec-root"}, "/var/run/docker", usageFn("Root of the Docker execdriver")) - cmd.BoolVar(&config.AutoRestart, []string{"#r", "#-restart"}, true, usageFn("--restart on the daemon has been deprecated in favor of --restart policies on docker run")) - cmd.StringVar(&config.GraphDriver, []string{"s", "-storage-driver"}, "", usageFn("Storage driver to use")) - cmd.IntVar(&config.Mtu, []string{"#mtu", "-mtu"}, 0, usageFn("Set the containers network MTU")) - // FIXME: why the inconsistency between "hosts" and "sockets"? - cmd.Var(opts.NewListOptsRef(&config.DNS, opts.ValidateIPAddress), []string{"#dns", "-dns"}, usageFn("DNS server to use")) - cmd.Var(opts.NewListOptsRef(&config.DNSOptions, nil), []string{"-dns-opt"}, usageFn("DNS options to use")) - cmd.Var(opts.NewListOptsRef(&config.DNSSearch, opts.ValidateDNSSearch), []string{"-dns-search"}, usageFn("DNS search domains to use")) - cmd.Var(opts.NewListOptsRef(&config.Labels, opts.ValidateLabel), []string{"-label"}, usageFn("Set key=value labels to the daemon")) - cmd.StringVar(&config.LogConfig.Type, []string{"-log-driver"}, "json-file", usageFn("Default driver for container logs")) - cmd.Var(opts.NewMapOpts(config.LogConfig.Config, nil), []string{"-log-opt"}, usageFn("Set log driver options")) - cmd.StringVar(&config.ClusterAdvertise, []string{"-cluster-advertise"}, "", usageFn("Address or interface name to advertise")) - cmd.StringVar(&config.ClusterStore, []string{"-cluster-store"}, "", usageFn("Set the cluster store")) - cmd.Var(opts.NewMapOpts(config.ClusterOpts, nil), []string{"-cluster-store-opt"}, usageFn("Set cluster store options")) -} diff --git a/vendor/github.com/docker/docker/daemon/config_experimental.go b/vendor/github.com/docker/docker/daemon/config_experimental.go deleted file mode 100644 index f1c4bb92..00000000 --- a/vendor/github.com/docker/docker/daemon/config_experimental.go +++ /dev/null @@ -1,119 +0,0 @@ -// +build experimental - -package daemon - -import ( - "fmt" - "strconv" - "strings" - - "github.com/docker/docker/pkg/idtools" - flag "github.com/docker/docker/pkg/mflag" - "github.com/opencontainers/runc/libcontainer/user" -) - -func (config *Config) attachExperimentalFlags(cmd *flag.FlagSet, usageFn func(string) string) { - cmd.StringVar(&config.RemappedRoot, []string{"-userns-remap"}, "", usageFn("User/Group setting for user namespaces")) -} - -const ( - defaultIDSpecifier string = "default" - defaultRemappedID string = "dockremap" -) - -// Parse the remapped root (user namespace) option, which can be one of: -// username - valid username from /etc/passwd -// username:groupname - valid username; valid groupname from /etc/group -// uid - 32-bit unsigned int valid Linux UID value -// uid:gid - uid value; 32-bit unsigned int Linux GID value -// -// If no groupname is specified, and a username is specified, an attempt -// will be made to lookup a gid for that username as a groupname -// -// If names are used, they are verified to exist in passwd/group -func parseRemappedRoot(usergrp string) (string, string, error) { - - var ( - userID, groupID int - username, groupname string - ) - - idparts := strings.Split(usergrp, ":") - if len(idparts) > 2 { - return "", "", fmt.Errorf("Invalid user/group specification in --userns-remap: %q", usergrp) - } - - if uid, err := strconv.ParseInt(idparts[0], 10, 32); err == nil { - // must be a uid; take it as valid - userID = int(uid) - luser, err := user.LookupUid(userID) - if err != nil { - return "", "", fmt.Errorf("Uid %d has no entry in /etc/passwd: %v", userID, err) - } - username = luser.Name - if len(idparts) == 1 { - // if the uid was numeric and no gid was specified, take the uid as the gid - groupID = userID - lgrp, err := user.LookupGid(groupID) - if err != nil { - return "", "", fmt.Errorf("Gid %d has no entry in /etc/group: %v", groupID, err) - } - groupname = lgrp.Name - } - } else { - lookupName := idparts[0] - // special case: if the user specified "default", they want Docker to create or - // use (after creation) the "dockremap" user/group for root remapping - if lookupName == defaultIDSpecifier { - lookupName = defaultRemappedID - } - luser, err := user.LookupUser(lookupName) - if err != nil && idparts[0] != defaultIDSpecifier { - // error if the name requested isn't the special "dockremap" ID - return "", "", fmt.Errorf("Error during uid lookup for %q: %v", lookupName, err) - } else if err != nil { - // special case-- if the username == "default", then we have been asked - // to create a new entry pair in /etc/{passwd,group} for which the /etc/sub{uid,gid} - // ranges will be used for the user and group mappings in user namespaced containers - _, _, err := idtools.AddNamespaceRangesUser(defaultRemappedID) - if err == nil { - return defaultRemappedID, defaultRemappedID, nil - } - return "", "", fmt.Errorf("Error during %q user creation: %v", defaultRemappedID, err) - } - userID = luser.Uid - username = luser.Name - if len(idparts) == 1 { - // we only have a string username, and no group specified; look up gid from username as group - group, err := user.LookupGroup(lookupName) - if err != nil { - return "", "", fmt.Errorf("Error during gid lookup for %q: %v", lookupName, err) - } - groupID = group.Gid - groupname = group.Name - } - } - - if len(idparts) == 2 { - // groupname or gid is separately specified and must be resolved - // to a unsigned 32-bit gid - if gid, err := strconv.ParseInt(idparts[1], 10, 32); err == nil { - // must be a gid, take it as valid - groupID = int(gid) - lgrp, err := user.LookupGid(groupID) - if err != nil { - return "", "", fmt.Errorf("Gid %d has no entry in /etc/passwd: %v", groupID, err) - } - groupname = lgrp.Name - } else { - // not a number; attempt a lookup - group, err := user.LookupGroup(idparts[1]) - if err != nil { - return "", "", fmt.Errorf("Error during gid lookup for %q: %v", idparts[1], err) - } - groupID = group.Gid - groupname = idparts[1] - } - } - return username, groupname, nil -} diff --git a/vendor/github.com/docker/docker/daemon/config_stub.go b/vendor/github.com/docker/docker/daemon/config_stub.go deleted file mode 100644 index 796e6b6e..00000000 --- a/vendor/github.com/docker/docker/daemon/config_stub.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !experimental - -package daemon - -import flag "github.com/docker/docker/pkg/mflag" - -func (config *Config) attachExperimentalFlags(cmd *flag.FlagSet, usageFn func(string) string) { -} diff --git a/vendor/github.com/docker/docker/daemon/config_unix.go b/vendor/github.com/docker/docker/daemon/config_unix.go deleted file mode 100644 index 8772aad9..00000000 --- a/vendor/github.com/docker/docker/daemon/config_unix.go +++ /dev/null @@ -1,81 +0,0 @@ -// +build linux freebsd - -package daemon - -import ( - "net" - - "github.com/docker/docker/opts" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/ulimit" -) - -var ( - defaultPidFile = "/var/run/docker.pid" - defaultGraph = "/var/lib/docker" - defaultExec = "native" -) - -// Config defines the configuration of a docker daemon. -type Config struct { - CommonConfig - - // Fields below here are platform specific. - - CorsHeaders string - EnableCors bool - EnableSelinuxSupport bool - RemappedRoot string - SocketGroup string - Ulimits map[string]*ulimit.Ulimit -} - -// bridgeConfig stores all the bridge driver specific -// configuration. -type bridgeConfig struct { - EnableIPv6 bool - EnableIPTables bool - EnableIPForward bool - EnableIPMasq bool - EnableUserlandProxy bool - DefaultIP net.IP - Iface string - IP string - FixedCIDR string - FixedCIDRv6 string - DefaultGatewayIPv4 net.IP - DefaultGatewayIPv6 net.IP - InterContainerCommunication bool -} - -// InstallFlags adds command-line options to the top-level flag parser for -// the current process. -// Subsequent calls to `flag.Parse` will populate config with values parsed -// from the command-line. -func (config *Config) InstallFlags(cmd *flag.FlagSet, usageFn func(string) string) { - // First handle install flags which are consistent cross-platform - config.InstallCommonFlags(cmd, usageFn) - - // Then platform-specific install flags - cmd.BoolVar(&config.EnableSelinuxSupport, []string{"-selinux-enabled"}, false, usageFn("Enable selinux support")) - cmd.StringVar(&config.SocketGroup, []string{"G", "-group"}, "docker", usageFn("Group for the unix socket")) - config.Ulimits = make(map[string]*ulimit.Ulimit) - cmd.Var(opts.NewUlimitOpt(&config.Ulimits), []string{"-default-ulimit"}, usageFn("Set default ulimits for containers")) - cmd.BoolVar(&config.Bridge.EnableIPTables, []string{"#iptables", "-iptables"}, true, usageFn("Enable addition of iptables rules")) - cmd.BoolVar(&config.Bridge.EnableIPForward, []string{"#ip-forward", "-ip-forward"}, true, usageFn("Enable net.ipv4.ip_forward")) - cmd.BoolVar(&config.Bridge.EnableIPMasq, []string{"-ip-masq"}, true, usageFn("Enable IP masquerading")) - cmd.BoolVar(&config.Bridge.EnableIPv6, []string{"-ipv6"}, false, usageFn("Enable IPv6 networking")) - cmd.StringVar(&config.Bridge.IP, []string{"#bip", "-bip"}, "", usageFn("Specify network bridge IP")) - cmd.StringVar(&config.Bridge.Iface, []string{"b", "-bridge"}, "", usageFn("Attach containers to a network bridge")) - cmd.StringVar(&config.Bridge.FixedCIDR, []string{"-fixed-cidr"}, "", usageFn("IPv4 subnet for fixed IPs")) - cmd.StringVar(&config.Bridge.FixedCIDRv6, []string{"-fixed-cidr-v6"}, "", usageFn("IPv6 subnet for fixed IPs")) - cmd.Var(opts.NewIPOpt(&config.Bridge.DefaultGatewayIPv4, ""), []string{"-default-gateway"}, usageFn("Container default gateway IPv4 address")) - cmd.Var(opts.NewIPOpt(&config.Bridge.DefaultGatewayIPv6, ""), []string{"-default-gateway-v6"}, usageFn("Container default gateway IPv6 address")) - cmd.BoolVar(&config.Bridge.InterContainerCommunication, []string{"#icc", "-icc"}, true, usageFn("Enable inter-container communication")) - cmd.Var(opts.NewIPOpt(&config.Bridge.DefaultIP, "0.0.0.0"), []string{"#ip", "-ip"}, usageFn("Default IP when binding container ports")) - cmd.BoolVar(&config.Bridge.EnableUserlandProxy, []string{"-userland-proxy"}, true, usageFn("Use userland proxy for loopback traffic")) - cmd.BoolVar(&config.EnableCors, []string{"#api-enable-cors", "#-api-enable-cors"}, false, usageFn("Enable CORS headers in the remote API, this is deprecated by --api-cors-header")) - cmd.StringVar(&config.CorsHeaders, []string{"-api-cors-header"}, "", usageFn("Set CORS headers in the remote API")) - - config.attachExperimentalFlags(cmd, usageFn) -} diff --git a/vendor/github.com/docker/docker/daemon/config_windows.go b/vendor/github.com/docker/docker/daemon/config_windows.go deleted file mode 100644 index bc0833aa..00000000 --- a/vendor/github.com/docker/docker/daemon/config_windows.go +++ /dev/null @@ -1,41 +0,0 @@ -package daemon - -import ( - "os" - - flag "github.com/docker/docker/pkg/mflag" -) - -var ( - defaultPidFile = os.Getenv("programdata") + string(os.PathSeparator) + "docker.pid" - defaultGraph = os.Getenv("programdata") + string(os.PathSeparator) + "docker" - defaultExec = "windows" -) - -// bridgeConfig stores all the bridge driver specific -// configuration. -type bridgeConfig struct { - VirtualSwitchName string -} - -// Config defines the configuration of a docker daemon. -// These are the configuration settings that you pass -// to the docker daemon when you launch it with say: `docker daemon -e windows` -type Config struct { - CommonConfig - - // Fields below here are platform specific. (There are none presently - // for the Windows daemon.) -} - -// InstallFlags adds command-line options to the top-level flag parser for -// the current process. -// Subsequent calls to `flag.Parse` will populate config with values parsed -// from the command-line. -func (config *Config) InstallFlags(cmd *flag.FlagSet, usageFn func(string) string) { - // First handle install flags which are consistent cross-platform - config.InstallCommonFlags(cmd, usageFn) - - // Then platform-specific install flags. - cmd.StringVar(&config.Bridge.VirtualSwitchName, []string{"b", "-bridge"}, "", "Attach containers to a virtual switch") -} diff --git a/vendor/github.com/docker/docker/daemon/container.go b/vendor/github.com/docker/docker/daemon/container.go deleted file mode 100644 index fc64d0ee..00000000 --- a/vendor/github.com/docker/docker/daemon/container.go +++ /dev/null @@ -1,609 +0,0 @@ -package daemon - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "os" - "path/filepath" - "sync" - "syscall" - "time" - - "github.com/opencontainers/runc/libcontainer/label" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/daemon/execdriver" - "github.com/docker/docker/daemon/logger" - "github.com/docker/docker/daemon/logger/jsonfilelog" - "github.com/docker/docker/daemon/network" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/pkg/broadcaster" - "github.com/docker/docker/pkg/fileutils" - "github.com/docker/docker/pkg/ioutils" - "github.com/docker/docker/pkg/mount" - "github.com/docker/docker/pkg/nat" - "github.com/docker/docker/pkg/promise" - "github.com/docker/docker/pkg/signal" - "github.com/docker/docker/pkg/symlink" - "github.com/docker/docker/pkg/system" - "github.com/docker/docker/runconfig" - "github.com/docker/docker/volume" -) - -var ( - // ErrRootFSReadOnly is returned when a container - // rootfs is marked readonly. - ErrRootFSReadOnly = errors.New("container rootfs is marked read-only") -) - -type streamConfig struct { - stdout *broadcaster.Unbuffered - stderr *broadcaster.Unbuffered - stdin io.ReadCloser - stdinPipe io.WriteCloser -} - -// CommonContainer holds the fields for a container which are -// applicable across all platforms supported by the daemon. -type CommonContainer struct { - streamConfig - // embed for Container to support states directly. - *State `json:"State"` // Needed for remote api version <= 1.11 - root string // Path to the "home" of the container, including metadata. - basefs string // Path to the graphdriver mountpoint - ID string - Created time.Time - Path string - Args []string - Config *runconfig.Config - ImageID string `json:"Image"` - NetworkSettings *network.Settings - LogPath string - Name string - Driver string - // MountLabel contains the options for the 'mount' command - MountLabel string - ProcessLabel string - RestartCount int - HasBeenStartedBefore bool - HasBeenManuallyStopped bool // used for unless-stopped restart policy - MountPoints map[string]*volume.MountPoint - hostConfig *runconfig.HostConfig - command *execdriver.Command - monitor *containerMonitor - execCommands *execStore - // logDriver for closing - logDriver logger.Logger - logCopier *logger.Copier -} - -func (container *Container) fromDisk() error { - pth, err := container.jsonPath() - if err != nil { - return err - } - - jsonSource, err := os.Open(pth) - if err != nil { - return err - } - defer jsonSource.Close() - - dec := json.NewDecoder(jsonSource) - - // Load container settings - if err := dec.Decode(container); err != nil { - return err - } - - if err := label.ReserveLabel(container.ProcessLabel); err != nil { - return err - } - return container.readHostConfig() -} - -func (container *Container) toDisk() error { - pth, err := container.jsonPath() - if err != nil { - return err - } - - jsonSource, err := os.Create(pth) - if err != nil { - return err - } - defer jsonSource.Close() - - enc := json.NewEncoder(jsonSource) - - // Save container settings - if err := enc.Encode(container); err != nil { - return err - } - - return container.writeHostConfig() -} - -func (container *Container) toDiskLocking() error { - container.Lock() - err := container.toDisk() - container.Unlock() - return err -} - -func (container *Container) readHostConfig() error { - container.hostConfig = &runconfig.HostConfig{} - // If the hostconfig file does not exist, do not read it. - // (We still have to initialize container.hostConfig, - // but that's OK, since we just did that above.) - pth, err := container.hostConfigPath() - if err != nil { - return err - } - - f, err := os.Open(pth) - if err != nil { - if os.IsNotExist(err) { - return nil - } - return err - } - defer f.Close() - - return json.NewDecoder(f).Decode(&container.hostConfig) -} - -func (container *Container) writeHostConfig() error { - pth, err := container.hostConfigPath() - if err != nil { - return err - } - - f, err := os.Create(pth) - if err != nil { - return err - } - defer f.Close() - - return json.NewEncoder(f).Encode(&container.hostConfig) -} - -// GetResourcePath evaluates `path` in the scope of the container's basefs, with proper path -// sanitisation. Symlinks are all scoped to the basefs of the container, as -// though the container's basefs was `/`. -// -// The basefs of a container is the host-facing path which is bind-mounted as -// `/` inside the container. This method is essentially used to access a -// particular path inside the container as though you were a process in that -// container. -// -// NOTE: The returned path is *only* safely scoped inside the container's basefs -// if no component of the returned path changes (such as a component -// symlinking to a different path) between using this method and using the -// path. See symlink.FollowSymlinkInScope for more details. -func (container *Container) GetResourcePath(path string) (string, error) { - // IMPORTANT - These are paths on the OS where the daemon is running, hence - // any filepath operations must be done in an OS agnostic way. - cleanPath := filepath.Join(string(os.PathSeparator), path) - r, e := symlink.FollowSymlinkInScope(filepath.Join(container.basefs, cleanPath), container.basefs) - return r, e -} - -// Evaluates `path` in the scope of the container's root, with proper path -// sanitisation. Symlinks are all scoped to the root of the container, as -// though the container's root was `/`. -// -// The root of a container is the host-facing configuration metadata directory. -// Only use this method to safely access the container's `container.json` or -// other metadata files. If in doubt, use container.GetResourcePath. -// -// NOTE: The returned path is *only* safely scoped inside the container's root -// if no component of the returned path changes (such as a component -// symlinking to a different path) between using this method and using the -// path. See symlink.FollowSymlinkInScope for more details. -func (container *Container) getRootResourcePath(path string) (string, error) { - // IMPORTANT - These are paths on the OS where the daemon is running, hence - // any filepath operations must be done in an OS agnostic way. - cleanPath := filepath.Join(string(os.PathSeparator), path) - return symlink.FollowSymlinkInScope(filepath.Join(container.root, cleanPath), container.root) -} - -// streamConfig.StdinPipe returns a WriteCloser which can be used to feed data -// to the standard input of the container's active process. -// Container.StdoutPipe and Container.StderrPipe each return a ReadCloser -// which can be used to retrieve the standard output (and error) generated -// by the container's active process. The output (and error) are actually -// copied and delivered to all StdoutPipe and StderrPipe consumers, using -// a kind of "broadcaster". - -func (streamConfig *streamConfig) StdinPipe() io.WriteCloser { - return streamConfig.stdinPipe -} - -func (streamConfig *streamConfig) StdoutPipe() io.ReadCloser { - reader, writer := io.Pipe() - streamConfig.stdout.Add(writer) - return ioutils.NewBufReader(reader) -} - -func (streamConfig *streamConfig) StderrPipe() io.ReadCloser { - reader, writer := io.Pipe() - streamConfig.stderr.Add(writer) - return ioutils.NewBufReader(reader) -} - -// ExitOnNext signals to the monitor that it should not restart the container -// after we send the kill signal. -func (container *Container) ExitOnNext() { - container.monitor.ExitOnNext() -} - -// Resize changes the TTY of the process running inside the container -// to the given height and width. The container must be running. -func (container *Container) Resize(h, w int) error { - if err := container.command.ProcessConfig.Terminal.Resize(h, w); err != nil { - return err - } - return nil -} - -func (container *Container) hostConfigPath() (string, error) { - return container.getRootResourcePath("hostconfig.json") -} - -func (container *Container) jsonPath() (string, error) { - return container.getRootResourcePath("config.json") -} - -// This directory is only usable when the container is running -func (container *Container) rootfsPath() string { - return container.basefs -} - -func validateID(id string) error { - if id == "" { - return derr.ErrorCodeEmptyID - } - return nil -} - -// Returns true if the container exposes a certain port -func (container *Container) exposes(p nat.Port) bool { - _, exists := container.Config.ExposedPorts[p] - return exists -} - -func (container *Container) getLogConfig(defaultConfig runconfig.LogConfig) runconfig.LogConfig { - cfg := container.hostConfig.LogConfig - if cfg.Type != "" || len(cfg.Config) > 0 { // container has log driver configured - if cfg.Type == "" { - cfg.Type = jsonfilelog.Name - } - return cfg - } - // Use daemon's default log config for containers - return defaultConfig -} - -// StartLogger starts a new logger driver for the container. -func (container *Container) StartLogger(cfg runconfig.LogConfig) (logger.Logger, error) { - c, err := logger.GetLogDriver(cfg.Type) - if err != nil { - return nil, derr.ErrorCodeLoggingFactory.WithArgs(err) - } - ctx := logger.Context{ - Config: cfg.Config, - ContainerID: container.ID, - ContainerName: container.Name, - ContainerEntrypoint: container.Path, - ContainerArgs: container.Args, - ContainerImageID: container.ImageID, - ContainerImageName: container.Config.Image, - ContainerCreated: container.Created, - ContainerEnv: container.Config.Env, - ContainerLabels: container.Config.Labels, - } - - // Set logging file for "json-logger" - if cfg.Type == jsonfilelog.Name { - ctx.LogPath, err = container.getRootResourcePath(fmt.Sprintf("%s-json.log", container.ID)) - if err != nil { - return nil, err - } - } - return c(ctx) -} - -func (container *Container) getProcessLabel() string { - // even if we have a process label return "" if we are running - // in privileged mode - if container.hostConfig.Privileged { - return "" - } - return container.ProcessLabel -} - -func (container *Container) getMountLabel() string { - if container.hostConfig.Privileged { - return "" - } - return container.MountLabel -} - -func (container *Container) getExecIDs() []string { - return container.execCommands.List() -} - -// Attach connects to the container's TTY, delegating to standard -// streams or websockets depending on the configuration. -func (container *Container) Attach(stdin io.ReadCloser, stdout io.Writer, stderr io.Writer) chan error { - return attach(&container.streamConfig, container.Config.OpenStdin, container.Config.StdinOnce, container.Config.Tty, stdin, stdout, stderr) -} - -func attach(streamConfig *streamConfig, openStdin, stdinOnce, tty bool, stdin io.ReadCloser, stdout io.Writer, stderr io.Writer) chan error { - var ( - cStdout, cStderr io.ReadCloser - cStdin io.WriteCloser - wg sync.WaitGroup - errors = make(chan error, 3) - ) - - if stdin != nil && openStdin { - cStdin = streamConfig.StdinPipe() - wg.Add(1) - } - - if stdout != nil { - cStdout = streamConfig.StdoutPipe() - wg.Add(1) - } - - if stderr != nil { - cStderr = streamConfig.StderrPipe() - wg.Add(1) - } - - // Connect stdin of container to the http conn. - go func() { - if stdin == nil || !openStdin { - return - } - logrus.Debugf("attach: stdin: begin") - defer func() { - if stdinOnce && !tty { - cStdin.Close() - } else { - // No matter what, when stdin is closed (io.Copy unblock), close stdout and stderr - if cStdout != nil { - cStdout.Close() - } - if cStderr != nil { - cStderr.Close() - } - } - wg.Done() - logrus.Debugf("attach: stdin: end") - }() - - var err error - if tty { - _, err = copyEscapable(cStdin, stdin) - } else { - _, err = io.Copy(cStdin, stdin) - - } - if err == io.ErrClosedPipe { - err = nil - } - if err != nil { - logrus.Errorf("attach: stdin: %s", err) - errors <- err - return - } - }() - - attachStream := func(name string, stream io.Writer, streamPipe io.ReadCloser) { - if stream == nil { - return - } - defer func() { - // Make sure stdin gets closed - if stdin != nil { - stdin.Close() - } - streamPipe.Close() - wg.Done() - logrus.Debugf("attach: %s: end", name) - }() - - logrus.Debugf("attach: %s: begin", name) - _, err := io.Copy(stream, streamPipe) - if err == io.ErrClosedPipe { - err = nil - } - if err != nil { - logrus.Errorf("attach: %s: %v", name, err) - errors <- err - } - } - - go attachStream("stdout", stdout, cStdout) - go attachStream("stderr", stderr, cStderr) - - return promise.Go(func() error { - wg.Wait() - close(errors) - for err := range errors { - if err != nil { - return err - } - } - return nil - }) -} - -// Code c/c from io.Copy() modified to handle escape sequence -func copyEscapable(dst io.Writer, src io.ReadCloser) (written int64, err error) { - buf := make([]byte, 32*1024) - for { - nr, er := src.Read(buf) - if nr > 0 { - // ---- Docker addition - // char 16 is C-p - if nr == 1 && buf[0] == 16 { - nr, er = src.Read(buf) - // char 17 is C-q - if nr == 1 && buf[0] == 17 { - if err := src.Close(); err != nil { - return 0, err - } - return 0, nil - } - } - // ---- End of docker - nw, ew := dst.Write(buf[0:nr]) - if nw > 0 { - written += int64(nw) - } - if ew != nil { - err = ew - break - } - if nr != nw { - err = io.ErrShortWrite - break - } - } - if er == io.EOF { - break - } - if er != nil { - err = er - break - } - } - return written, err -} - -func (container *Container) shouldRestart() bool { - return container.hostConfig.RestartPolicy.Name == "always" || - (container.hostConfig.RestartPolicy.Name == "unless-stopped" && !container.HasBeenManuallyStopped) || - (container.hostConfig.RestartPolicy.Name == "on-failure" && container.ExitCode != 0) -} - -func (daemon *Daemon) mountVolumes(container *Container) error { - mounts, err := daemon.setupMounts(container) - if err != nil { - return err - } - - for _, m := range mounts { - dest, err := container.GetResourcePath(m.Destination) - if err != nil { - return err - } - - var stat os.FileInfo - stat, err = os.Stat(m.Source) - if err != nil { - return err - } - if err = fileutils.CreateIfNotExists(dest, stat.IsDir()); err != nil { - return err - } - - opts := "rbind,ro" - if m.Writable { - opts = "rbind,rw" - } - - if err := mount.Mount(m.Source, dest, "bind", opts); err != nil { - return err - } - } - - return nil -} - -func (container *Container) unmountVolumes(forceSyscall bool) error { - var ( - volumeMounts []volume.MountPoint - err error - ) - - for _, mntPoint := range container.MountPoints { - dest, err := container.GetResourcePath(mntPoint.Destination) - if err != nil { - return err - } - - volumeMounts = append(volumeMounts, volume.MountPoint{Destination: dest, Volume: mntPoint.Volume}) - } - - // Append any network mounts to the list (this is a no-op on Windows) - if volumeMounts, err = appendNetworkMounts(container, volumeMounts); err != nil { - return err - } - - for _, volumeMount := range volumeMounts { - if forceSyscall { - if err := system.Unmount(volumeMount.Destination); err != nil { - logrus.Warnf("%s unmountVolumes: Failed to force umount %v", container.ID, err) - } - } - - if volumeMount.Volume != nil { - if err := volumeMount.Volume.Unmount(); err != nil { - return err - } - } - } - - return nil -} - -func (container *Container) addBindMountPoint(name, source, destination string, rw bool) { - container.MountPoints[destination] = &volume.MountPoint{ - Name: name, - Source: source, - Destination: destination, - RW: rw, - } -} - -func (container *Container) addLocalMountPoint(name, destination string, rw bool) { - container.MountPoints[destination] = &volume.MountPoint{ - Name: name, - Driver: volume.DefaultDriverName, - Destination: destination, - RW: rw, - } -} - -func (container *Container) addMountPointWithVolume(destination string, vol volume.Volume, rw bool) { - container.MountPoints[destination] = &volume.MountPoint{ - Name: vol.Name(), - Driver: vol.DriverName(), - Destination: destination, - RW: rw, - Volume: vol, - } -} - -func (container *Container) isDestinationMounted(destination string) bool { - return container.MountPoints[destination] != nil -} - -func (container *Container) stopSignal() int { - var stopSignal syscall.Signal - if container.Config.StopSignal != "" { - stopSignal, _ = signal.ParseSignal(container.Config.StopSignal) - } - - if int(stopSignal) == 0 { - stopSignal, _ = signal.ParseSignal(signal.DefaultStopSignal) - } - return int(stopSignal) -} diff --git a/vendor/github.com/docker/docker/daemon/container_unit_test.go b/vendor/github.com/docker/docker/daemon/container_unit_test.go deleted file mode 100644 index 71d37cf4..00000000 --- a/vendor/github.com/docker/docker/daemon/container_unit_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package daemon - -import ( - "testing" - - "github.com/docker/docker/pkg/signal" - "github.com/docker/docker/runconfig" -) - -func TestGetFullName(t *testing.T) { - name, err := GetFullContainerName("testing") - if err != nil { - t.Fatal(err) - } - if name != "/testing" { - t.Fatalf("Expected /testing got %s", name) - } - if _, err := GetFullContainerName(""); err == nil { - t.Fatal("Error should not be nil") - } -} - -func TestValidContainerNames(t *testing.T) { - invalidNames := []string{"-rm", "&sdfsfd", "safd%sd"} - validNames := []string{"word-word", "word_word", "1weoid"} - - for _, name := range invalidNames { - if validContainerNamePattern.MatchString(name) { - t.Fatalf("%q is not a valid container name and was returned as valid.", name) - } - } - - for _, name := range validNames { - if !validContainerNamePattern.MatchString(name) { - t.Fatalf("%q is a valid container name and was returned as invalid.", name) - } - } -} - -func TestContainerStopSignal(t *testing.T) { - c := &Container{ - CommonContainer: CommonContainer{ - Config: &runconfig.Config{}, - }, - } - - def, err := signal.ParseSignal(signal.DefaultStopSignal) - if err != nil { - t.Fatal(err) - } - - s := c.stopSignal() - if s != int(def) { - t.Fatalf("Expected %v, got %v", def, s) - } - - c = &Container{ - CommonContainer: CommonContainer{ - Config: &runconfig.Config{StopSignal: "SIGKILL"}, - }, - } - s = c.stopSignal() - if s != 9 { - t.Fatalf("Expected 9, got %v", s) - } -} diff --git a/vendor/github.com/docker/docker/daemon/container_unix.go b/vendor/github.com/docker/docker/daemon/container_unix.go deleted file mode 100644 index c797059e..00000000 --- a/vendor/github.com/docker/docker/daemon/container_unix.go +++ /dev/null @@ -1,1429 +0,0 @@ -// +build linux freebsd - -package daemon - -import ( - "fmt" - "io/ioutil" - "net" - "os" - "path" - "path/filepath" - "strconv" - "strings" - "syscall" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/daemon/execdriver" - "github.com/docker/docker/daemon/links" - "github.com/docker/docker/daemon/network" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/pkg/directory" - "github.com/docker/docker/pkg/idtools" - "github.com/docker/docker/pkg/nat" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/pkg/symlink" - "github.com/docker/docker/pkg/system" - "github.com/docker/docker/pkg/ulimit" - "github.com/docker/docker/runconfig" - "github.com/docker/docker/utils" - "github.com/docker/docker/volume" - "github.com/docker/libnetwork" - "github.com/docker/libnetwork/netlabel" - "github.com/docker/libnetwork/options" - "github.com/docker/libnetwork/types" - "github.com/opencontainers/runc/libcontainer/configs" - "github.com/opencontainers/runc/libcontainer/devices" - "github.com/opencontainers/runc/libcontainer/label" -) - -// DefaultPathEnv is unix style list of directories to search for -// executables. Each directory is separated from the next by a colon -// ':' character . -const DefaultPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - -// Container holds the fields specific to unixen implementations. See -// CommonContainer for standard fields common to all containers. -type Container struct { - CommonContainer - - // Fields below here are platform specific. - activeLinks map[string]*links.Link - AppArmorProfile string - HostnamePath string - HostsPath string - ShmPath string // TODO Windows - Factor this out (GH15862) - MqueuePath string // TODO Windows - Factor this out (GH15862) - ResolvConfPath string - - Volumes map[string]string // Deprecated since 1.7, kept for backwards compatibility - VolumesRW map[string]bool // Deprecated since 1.7, kept for backwards compatibility -} - -func killProcessDirectly(container *Container) error { - if _, err := container.WaitStop(10 * time.Second); err != nil { - // Ensure that we don't kill ourselves - if pid := container.GetPID(); pid != 0 { - logrus.Infof("Container %s failed to exit within 10 seconds of kill - trying direct SIGKILL", stringid.TruncateID(container.ID)) - if err := syscall.Kill(pid, 9); err != nil { - if err != syscall.ESRCH { - return err - } - logrus.Debugf("Cannot kill process (pid=%d) with signal 9: no such process.", pid) - } - } - } - return nil -} - -func (daemon *Daemon) setupLinkedContainers(container *Container) ([]string, error) { - var env []string - children, err := daemon.children(container.Name) - if err != nil { - return nil, err - } - - bridgeSettings := container.NetworkSettings.Networks["bridge"] - if bridgeSettings == nil { - return nil, nil - } - - if len(children) > 0 { - for linkAlias, child := range children { - if !child.IsRunning() { - return nil, derr.ErrorCodeLinkNotRunning.WithArgs(child.Name, linkAlias) - } - - childBridgeSettings := child.NetworkSettings.Networks["bridge"] - if childBridgeSettings == nil { - return nil, fmt.Errorf("container %s not attached to default bridge network", child.ID) - } - - link := links.NewLink( - bridgeSettings.IPAddress, - childBridgeSettings.IPAddress, - linkAlias, - child.Config.Env, - child.Config.ExposedPorts, - ) - - for _, envVar := range link.ToEnv() { - env = append(env, envVar) - } - } - } - return env, nil -} - -func (container *Container) createDaemonEnvironment(linkedEnv []string) []string { - // if a domain name was specified, append it to the hostname (see #7851) - fullHostname := container.Config.Hostname - if container.Config.Domainname != "" { - fullHostname = fmt.Sprintf("%s.%s", fullHostname, container.Config.Domainname) - } - // Setup environment - env := []string{ - "PATH=" + DefaultPathEnv, - "HOSTNAME=" + fullHostname, - // Note: we don't set HOME here because it'll get autoset intelligently - // based on the value of USER inside dockerinit, but only if it isn't - // set already (ie, that can be overridden by setting HOME via -e or ENV - // in a Dockerfile). - } - if container.Config.Tty { - env = append(env, "TERM=xterm") - } - env = append(env, linkedEnv...) - // because the env on the container can override certain default values - // we need to replace the 'env' keys where they match and append anything - // else. - env = utils.ReplaceOrAppendEnvValues(env, container.Config.Env) - - return env -} - -func getDevicesFromPath(deviceMapping runconfig.DeviceMapping) (devs []*configs.Device, err error) { - device, err := devices.DeviceFromPath(deviceMapping.PathOnHost, deviceMapping.CgroupPermissions) - // if there was no error, return the device - if err == nil { - device.Path = deviceMapping.PathInContainer - return append(devs, device), nil - } - - // if the device is not a device node - // try to see if it's a directory holding many devices - if err == devices.ErrNotADevice { - - // check if it is a directory - if src, e := os.Stat(deviceMapping.PathOnHost); e == nil && src.IsDir() { - - // mount the internal devices recursively - filepath.Walk(deviceMapping.PathOnHost, func(dpath string, f os.FileInfo, e error) error { - childDevice, e := devices.DeviceFromPath(dpath, deviceMapping.CgroupPermissions) - if e != nil { - // ignore the device - return nil - } - - // add the device to userSpecified devices - childDevice.Path = strings.Replace(dpath, deviceMapping.PathOnHost, deviceMapping.PathInContainer, 1) - devs = append(devs, childDevice) - - return nil - }) - } - } - - if len(devs) > 0 { - return devs, nil - } - - return devs, derr.ErrorCodeDeviceInfo.WithArgs(deviceMapping.PathOnHost, err) -} - -func (daemon *Daemon) populateCommand(c *Container, env []string) error { - var en *execdriver.Network - if !c.Config.NetworkDisabled { - en = &execdriver.Network{} - if !daemon.execDriver.SupportsHooks() || c.hostConfig.NetworkMode.IsHost() { - en.NamespacePath = c.NetworkSettings.SandboxKey - } - - if c.hostConfig.NetworkMode.IsContainer() { - nc, err := daemon.getNetworkedContainer(c.ID, c.hostConfig.NetworkMode.ConnectedContainer()) - if err != nil { - return err - } - en.ContainerID = nc.ID - } - } - - ipc := &execdriver.Ipc{} - var err error - c.ShmPath, err = c.shmPath() - if err != nil { - return err - } - - c.MqueuePath, err = c.mqueuePath() - if err != nil { - return err - } - - if c.hostConfig.IpcMode.IsContainer() { - ic, err := daemon.getIpcContainer(c) - if err != nil { - return err - } - ipc.ContainerID = ic.ID - c.ShmPath = ic.ShmPath - c.MqueuePath = ic.MqueuePath - } else { - ipc.HostIpc = c.hostConfig.IpcMode.IsHost() - if ipc.HostIpc { - if _, err := os.Stat("/dev/shm"); err != nil { - return fmt.Errorf("/dev/shm is not mounted, but must be for --ipc=host") - } - if _, err := os.Stat("/dev/mqueue"); err != nil { - return fmt.Errorf("/dev/mqueue is not mounted, but must be for --ipc=host") - } - c.ShmPath = "/dev/shm" - c.MqueuePath = "/dev/mqueue" - } - } - - pid := &execdriver.Pid{} - pid.HostPid = c.hostConfig.PidMode.IsHost() - - uts := &execdriver.UTS{ - HostUTS: c.hostConfig.UTSMode.IsHost(), - } - - // Build lists of devices allowed and created within the container. - var userSpecifiedDevices []*configs.Device - for _, deviceMapping := range c.hostConfig.Devices { - devs, err := getDevicesFromPath(deviceMapping) - if err != nil { - return err - } - - userSpecifiedDevices = append(userSpecifiedDevices, devs...) - } - - allowedDevices := mergeDevices(configs.DefaultAllowedDevices, userSpecifiedDevices) - - autoCreatedDevices := mergeDevices(configs.DefaultAutoCreatedDevices, userSpecifiedDevices) - - var rlimits []*ulimit.Rlimit - ulimits := c.hostConfig.Ulimits - - // Merge ulimits with daemon defaults - ulIdx := make(map[string]*ulimit.Ulimit) - for _, ul := range ulimits { - ulIdx[ul.Name] = ul - } - for name, ul := range daemon.configStore.Ulimits { - if _, exists := ulIdx[name]; !exists { - ulimits = append(ulimits, ul) - } - } - - for _, limit := range ulimits { - rl, err := limit.GetRlimit() - if err != nil { - return err - } - rlimits = append(rlimits, rl) - } - - resources := &execdriver.Resources{ - CommonResources: execdriver.CommonResources{ - Memory: c.hostConfig.Memory, - MemoryReservation: c.hostConfig.MemoryReservation, - CPUShares: c.hostConfig.CPUShares, - BlkioWeight: c.hostConfig.BlkioWeight, - }, - MemorySwap: c.hostConfig.MemorySwap, - KernelMemory: c.hostConfig.KernelMemory, - CpusetCpus: c.hostConfig.CpusetCpus, - CpusetMems: c.hostConfig.CpusetMems, - CPUPeriod: c.hostConfig.CPUPeriod, - CPUQuota: c.hostConfig.CPUQuota, - Rlimits: rlimits, - OomKillDisable: c.hostConfig.OomKillDisable, - MemorySwappiness: -1, - } - - if c.hostConfig.MemorySwappiness != nil { - resources.MemorySwappiness = *c.hostConfig.MemorySwappiness - } - - processConfig := execdriver.ProcessConfig{ - Privileged: c.hostConfig.Privileged, - Entrypoint: c.Path, - Arguments: c.Args, - Tty: c.Config.Tty, - User: c.Config.User, - } - - processConfig.SysProcAttr = &syscall.SysProcAttr{Setsid: true} - processConfig.Env = env - - remappedRoot := &execdriver.User{} - rootUID, rootGID := daemon.GetRemappedUIDGID() - if rootUID != 0 { - remappedRoot.UID = rootUID - remappedRoot.GID = rootGID - } - uidMap, gidMap := daemon.GetUIDGIDMaps() - - c.command = &execdriver.Command{ - CommonCommand: execdriver.CommonCommand{ - ID: c.ID, - InitPath: "/.dockerinit", - MountLabel: c.getMountLabel(), - Network: en, - ProcessConfig: processConfig, - ProcessLabel: c.getProcessLabel(), - Rootfs: c.rootfsPath(), - Resources: resources, - WorkingDir: c.Config.WorkingDir, - }, - AllowedDevices: allowedDevices, - AppArmorProfile: c.AppArmorProfile, - AutoCreatedDevices: autoCreatedDevices, - CapAdd: c.hostConfig.CapAdd.Slice(), - CapDrop: c.hostConfig.CapDrop.Slice(), - CgroupParent: c.hostConfig.CgroupParent, - GIDMapping: gidMap, - GroupAdd: c.hostConfig.GroupAdd, - Ipc: ipc, - Pid: pid, - ReadonlyRootfs: c.hostConfig.ReadonlyRootfs, - RemappedRoot: remappedRoot, - UIDMapping: uidMap, - UTS: uts, - } - - return nil -} - -func mergeDevices(defaultDevices, userDevices []*configs.Device) []*configs.Device { - if len(userDevices) == 0 { - return defaultDevices - } - - paths := map[string]*configs.Device{} - for _, d := range userDevices { - paths[d.Path] = d - } - - var devs []*configs.Device - for _, d := range defaultDevices { - if _, defined := paths[d.Path]; !defined { - devs = append(devs, d) - } - } - return append(devs, userDevices...) -} - -// getSize returns the real size & virtual size of the container. -func (daemon *Daemon) getSize(container *Container) (int64, int64) { - var ( - sizeRw, sizeRootfs int64 - err error - ) - - if err := daemon.Mount(container); err != nil { - logrus.Errorf("Failed to compute size of container rootfs %s: %s", container.ID, err) - return sizeRw, sizeRootfs - } - defer daemon.Unmount(container) - - initID := fmt.Sprintf("%s-init", container.ID) - sizeRw, err = daemon.driver.DiffSize(container.ID, initID) - if err != nil { - logrus.Errorf("Driver %s couldn't return diff size of container %s: %s", daemon.driver, container.ID, err) - // FIXME: GetSize should return an error. Not changing it now in case - // there is a side-effect. - sizeRw = -1 - } - - if _, err = os.Stat(container.basefs); err == nil { - if sizeRootfs, err = directory.Size(container.basefs); err != nil { - sizeRootfs = -1 - } - } - return sizeRw, sizeRootfs -} - -// Attempt to set the network mounts given a provided destination and -// the path to use for it; return true if the given destination was a -// network mount file -func (container *Container) trySetNetworkMount(destination string, path string) bool { - if destination == "/etc/resolv.conf" { - container.ResolvConfPath = path - return true - } - if destination == "/etc/hostname" { - container.HostnamePath = path - return true - } - if destination == "/etc/hosts" { - container.HostsPath = path - return true - } - - return false -} - -func (container *Container) buildHostnameFile() error { - hostnamePath, err := container.getRootResourcePath("hostname") - if err != nil { - return err - } - container.HostnamePath = hostnamePath - - if container.Config.Domainname != "" { - return ioutil.WriteFile(container.HostnamePath, []byte(fmt.Sprintf("%s.%s\n", container.Config.Hostname, container.Config.Domainname)), 0644) - } - return ioutil.WriteFile(container.HostnamePath, []byte(container.Config.Hostname+"\n"), 0644) -} - -func (daemon *Daemon) buildSandboxOptions(container *Container, n libnetwork.Network) ([]libnetwork.SandboxOption, error) { - var ( - sboxOptions []libnetwork.SandboxOption - err error - dns []string - dnsSearch []string - dnsOptions []string - ) - - sboxOptions = append(sboxOptions, libnetwork.OptionHostname(container.Config.Hostname), - libnetwork.OptionDomainname(container.Config.Domainname)) - - if container.hostConfig.NetworkMode.IsHost() { - sboxOptions = append(sboxOptions, libnetwork.OptionUseDefaultSandbox()) - sboxOptions = append(sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts")) - sboxOptions = append(sboxOptions, libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf")) - } else if daemon.execDriver.SupportsHooks() { - // OptionUseExternalKey is mandatory for userns support. - // But optional for non-userns support - sboxOptions = append(sboxOptions, libnetwork.OptionUseExternalKey()) - } - - container.HostsPath, err = container.getRootResourcePath("hosts") - if err != nil { - return nil, err - } - sboxOptions = append(sboxOptions, libnetwork.OptionHostsPath(container.HostsPath)) - - container.ResolvConfPath, err = container.getRootResourcePath("resolv.conf") - if err != nil { - return nil, err - } - sboxOptions = append(sboxOptions, libnetwork.OptionResolvConfPath(container.ResolvConfPath)) - - if len(container.hostConfig.DNS) > 0 { - dns = container.hostConfig.DNS - } else if len(daemon.configStore.DNS) > 0 { - dns = daemon.configStore.DNS - } - - for _, d := range dns { - sboxOptions = append(sboxOptions, libnetwork.OptionDNS(d)) - } - - if len(container.hostConfig.DNSSearch) > 0 { - dnsSearch = container.hostConfig.DNSSearch - } else if len(daemon.configStore.DNSSearch) > 0 { - dnsSearch = daemon.configStore.DNSSearch - } - - for _, ds := range dnsSearch { - sboxOptions = append(sboxOptions, libnetwork.OptionDNSSearch(ds)) - } - - if len(container.hostConfig.DNSOptions) > 0 { - dnsOptions = container.hostConfig.DNSOptions - } else if len(daemon.configStore.DNSOptions) > 0 { - dnsOptions = daemon.configStore.DNSOptions - } - - for _, ds := range dnsOptions { - sboxOptions = append(sboxOptions, libnetwork.OptionDNSOptions(ds)) - } - - if container.NetworkSettings.SecondaryIPAddresses != nil { - name := container.Config.Hostname - if container.Config.Domainname != "" { - name = name + "." + container.Config.Domainname - } - - for _, a := range container.NetworkSettings.SecondaryIPAddresses { - sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(name, a.Addr)) - } - } - - for _, extraHost := range container.hostConfig.ExtraHosts { - // allow IPv6 addresses in extra hosts; only split on first ":" - parts := strings.SplitN(extraHost, ":", 2) - sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(parts[0], parts[1])) - } - - // Link feature is supported only for the default bridge network. - // return if this call to build join options is not for default bridge network - if n.Name() != "bridge" { - return sboxOptions, nil - } - - ep, _ := container.getEndpointInNetwork(n) - if ep == nil { - return sboxOptions, nil - } - - var childEndpoints, parentEndpoints []string - - children, err := daemon.children(container.Name) - if err != nil { - return nil, err - } - - for linkAlias, child := range children { - if !isLinkable(child) { - return nil, fmt.Errorf("Cannot link to %s, as it does not belong to the default network", child.Name) - } - _, alias := path.Split(linkAlias) - // allow access to the linked container via the alias, real name, and container hostname - aliasList := alias + " " + child.Config.Hostname - // only add the name if alias isn't equal to the name - if alias != child.Name[1:] { - aliasList = aliasList + " " + child.Name[1:] - } - sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(aliasList, child.NetworkSettings.Networks["bridge"].IPAddress)) - cEndpoint, _ := child.getEndpointInNetwork(n) - if cEndpoint != nil && cEndpoint.ID() != "" { - childEndpoints = append(childEndpoints, cEndpoint.ID()) - } - } - - bridgeSettings := container.NetworkSettings.Networks["bridge"] - refs := daemon.containerGraph().RefPaths(container.ID) - for _, ref := range refs { - if ref.ParentID == "0" { - continue - } - - c, err := daemon.Get(ref.ParentID) - if err != nil { - logrus.Error(err) - } - - if c != nil && !daemon.configStore.DisableBridge && container.hostConfig.NetworkMode.IsPrivate() { - logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", c.ID, ref.Name, bridgeSettings.IPAddress) - sboxOptions = append(sboxOptions, libnetwork.OptionParentUpdate(c.ID, ref.Name, bridgeSettings.IPAddress)) - if ep.ID() != "" { - parentEndpoints = append(parentEndpoints, ep.ID()) - } - } - } - - linkOptions := options.Generic{ - netlabel.GenericData: options.Generic{ - "ParentEndpoints": parentEndpoints, - "ChildEndpoints": childEndpoints, - }, - } - - sboxOptions = append(sboxOptions, libnetwork.OptionGeneric(linkOptions)) - - return sboxOptions, nil -} - -func isLinkable(child *Container) bool { - // A container is linkable only if it belongs to the default network - _, ok := child.NetworkSettings.Networks["bridge"] - return ok -} - -func (container *Container) getEndpointInNetwork(n libnetwork.Network) (libnetwork.Endpoint, error) { - endpointName := strings.TrimPrefix(container.Name, "/") - return n.EndpointByName(endpointName) -} - -func (container *Container) buildPortMapInfo(ep libnetwork.Endpoint, networkSettings *network.Settings) (*network.Settings, error) { - if ep == nil { - return nil, derr.ErrorCodeEmptyEndpoint - } - - if networkSettings == nil { - return nil, derr.ErrorCodeEmptyNetwork - } - - driverInfo, err := ep.DriverInfo() - if err != nil { - return nil, err - } - - if driverInfo == nil { - // It is not an error for epInfo to be nil - return networkSettings, nil - } - - networkSettings.Ports = nat.PortMap{} - - if expData, ok := driverInfo[netlabel.ExposedPorts]; ok { - if exposedPorts, ok := expData.([]types.TransportPort); ok { - for _, tp := range exposedPorts { - natPort, err := nat.NewPort(tp.Proto.String(), strconv.Itoa(int(tp.Port))) - if err != nil { - return nil, derr.ErrorCodeParsingPort.WithArgs(tp.Port, err) - } - networkSettings.Ports[natPort] = nil - } - } - } - - mapData, ok := driverInfo[netlabel.PortMap] - if !ok { - return networkSettings, nil - } - - if portMapping, ok := mapData.([]types.PortBinding); ok { - for _, pp := range portMapping { - natPort, err := nat.NewPort(pp.Proto.String(), strconv.Itoa(int(pp.Port))) - if err != nil { - return nil, err - } - natBndg := nat.PortBinding{HostIP: pp.HostIP.String(), HostPort: strconv.Itoa(int(pp.HostPort))} - networkSettings.Ports[natPort] = append(networkSettings.Ports[natPort], natBndg) - } - } - - return networkSettings, nil -} - -func (container *Container) buildEndpointInfo(n libnetwork.Network, ep libnetwork.Endpoint, networkSettings *network.Settings) (*network.Settings, error) { - if ep == nil { - return nil, derr.ErrorCodeEmptyEndpoint - } - - if networkSettings == nil { - return nil, derr.ErrorCodeEmptyNetwork - } - - epInfo := ep.Info() - if epInfo == nil { - // It is not an error to get an empty endpoint info - return networkSettings, nil - } - - if _, ok := networkSettings.Networks[n.Name()]; !ok { - networkSettings.Networks[n.Name()] = new(network.EndpointSettings) - } - networkSettings.Networks[n.Name()].EndpointID = ep.ID() - - iface := epInfo.Iface() - if iface == nil { - return networkSettings, nil - } - - if iface.MacAddress() != nil { - networkSettings.Networks[n.Name()].MacAddress = iface.MacAddress().String() - } - - if iface.Address() != nil { - ones, _ := iface.Address().Mask.Size() - networkSettings.Networks[n.Name()].IPAddress = iface.Address().IP.String() - networkSettings.Networks[n.Name()].IPPrefixLen = ones - } - - if iface.AddressIPv6() != nil && iface.AddressIPv6().IP.To16() != nil { - onesv6, _ := iface.AddressIPv6().Mask.Size() - networkSettings.Networks[n.Name()].GlobalIPv6Address = iface.AddressIPv6().IP.String() - networkSettings.Networks[n.Name()].GlobalIPv6PrefixLen = onesv6 - } - - return networkSettings, nil -} - -func (container *Container) updateJoinInfo(n libnetwork.Network, ep libnetwork.Endpoint) error { - if _, err := container.buildPortMapInfo(ep, container.NetworkSettings); err != nil { - return err - } - - epInfo := ep.Info() - if epInfo == nil { - // It is not an error to get an empty endpoint info - return nil - } - if epInfo.Gateway() != nil { - container.NetworkSettings.Networks[n.Name()].Gateway = epInfo.Gateway().String() - } - if epInfo.GatewayIPv6().To16() != nil { - container.NetworkSettings.Networks[n.Name()].IPv6Gateway = epInfo.GatewayIPv6().String() - } - - return nil -} - -func (daemon *Daemon) updateNetworkSettings(container *Container, n libnetwork.Network) error { - if container.NetworkSettings == nil { - container.NetworkSettings = &network.Settings{Networks: make(map[string]*network.EndpointSettings)} - } - - for s := range container.NetworkSettings.Networks { - sn, err := daemon.FindNetwork(s) - if err != nil { - continue - } - - if sn.Name() == n.Name() { - // Avoid duplicate config - return nil - } - if !runconfig.NetworkMode(sn.Type()).IsPrivate() || - !runconfig.NetworkMode(n.Type()).IsPrivate() { - return runconfig.ErrConflictSharedNetwork - } - if runconfig.NetworkMode(sn.Name()).IsNone() || - runconfig.NetworkMode(n.Name()).IsNone() { - return runconfig.ErrConflictNoNetwork - } - } - container.NetworkSettings.Networks[n.Name()] = new(network.EndpointSettings) - - return nil -} - -func (daemon *Daemon) updateEndpointNetworkSettings(container *Container, n libnetwork.Network, ep libnetwork.Endpoint) error { - networkSettings, err := container.buildEndpointInfo(n, ep, container.NetworkSettings) - if err != nil { - return err - } - - if container.hostConfig.NetworkMode == runconfig.NetworkMode("bridge") { - networkSettings.Bridge = daemon.configStore.Bridge.Iface - } - - return nil -} - -func (container *Container) updateSandboxNetworkSettings(sb libnetwork.Sandbox) error { - container.NetworkSettings.SandboxID = sb.ID() - container.NetworkSettings.SandboxKey = sb.Key() - return nil -} - -// UpdateNetwork is used to update the container's network (e.g. when linked containers -// get removed/unlinked). -func (daemon *Daemon) updateNetwork(container *Container) error { - ctrl := daemon.netController - sid := container.NetworkSettings.SandboxID - - sb, err := ctrl.SandboxByID(sid) - if err != nil { - return derr.ErrorCodeNoSandbox.WithArgs(sid, err) - } - - // Find if container is connected to the default bridge network - var n libnetwork.Network - for name := range container.NetworkSettings.Networks { - sn, err := daemon.FindNetwork(name) - if err != nil { - continue - } - if sn.Name() == "bridge" { - n = sn - break - } - } - - if n == nil { - // Not connected to the default bridge network; Nothing to do - return nil - } - - options, err := daemon.buildSandboxOptions(container, n) - if err != nil { - return derr.ErrorCodeNetworkUpdate.WithArgs(err) - } - - if err := sb.Refresh(options...); err != nil { - return derr.ErrorCodeNetworkRefresh.WithArgs(sid, err) - } - - return nil -} - -func (container *Container) buildCreateEndpointOptions(n libnetwork.Network) ([]libnetwork.EndpointOption, error) { - var ( - portSpecs = make(nat.PortSet) - bindings = make(nat.PortMap) - pbList []types.PortBinding - exposeList []types.TransportPort - createOptions []libnetwork.EndpointOption - ) - - if container.Config.ExposedPorts != nil { - portSpecs = container.Config.ExposedPorts - } - - if container.hostConfig.PortBindings != nil { - for p, b := range container.hostConfig.PortBindings { - bindings[p] = []nat.PortBinding{} - for _, bb := range b { - bindings[p] = append(bindings[p], nat.PortBinding{ - HostIP: bb.HostIP, - HostPort: bb.HostPort, - }) - } - } - } - - ports := make([]nat.Port, len(portSpecs)) - var i int - for p := range portSpecs { - ports[i] = p - i++ - } - nat.SortPortMap(ports, bindings) - for _, port := range ports { - expose := types.TransportPort{} - expose.Proto = types.ParseProtocol(port.Proto()) - expose.Port = uint16(port.Int()) - exposeList = append(exposeList, expose) - - pb := types.PortBinding{Port: expose.Port, Proto: expose.Proto} - binding := bindings[port] - for i := 0; i < len(binding); i++ { - pbCopy := pb.GetCopy() - newP, err := nat.NewPort(nat.SplitProtoPort(binding[i].HostPort)) - var portStart, portEnd int - if err == nil { - portStart, portEnd, err = newP.Range() - } - if err != nil { - return nil, derr.ErrorCodeHostPort.WithArgs(binding[i].HostPort, err) - } - pbCopy.HostPort = uint16(portStart) - pbCopy.HostPortEnd = uint16(portEnd) - pbCopy.HostIP = net.ParseIP(binding[i].HostIP) - pbList = append(pbList, pbCopy) - } - - if container.hostConfig.PublishAllPorts && len(binding) == 0 { - pbList = append(pbList, pb) - } - } - - createOptions = append(createOptions, - libnetwork.CreateOptionPortMapping(pbList), - libnetwork.CreateOptionExposedPorts(exposeList)) - - if container.Config.MacAddress != "" { - mac, err := net.ParseMAC(container.Config.MacAddress) - if err != nil { - return nil, err - } - - genericOption := options.Generic{ - netlabel.MacAddress: mac, - } - - createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(genericOption)) - } - - if n.Name() == "bridge" || container.NetworkSettings.IsAnonymousEndpoint { - createOptions = append(createOptions, libnetwork.CreateOptionAnonymous()) - } - - return createOptions, nil -} - -func (daemon *Daemon) allocateNetwork(container *Container) error { - controller := daemon.netController - - // Cleanup any stale sandbox left over due to ungraceful daemon shutdown - if err := controller.SandboxDestroy(container.ID); err != nil { - logrus.Errorf("failed to cleanup up stale network sandbox for container %s", container.ID) - } - - updateSettings := false - if len(container.NetworkSettings.Networks) == 0 { - mode := container.hostConfig.NetworkMode - if container.Config.NetworkDisabled || mode.IsContainer() { - return nil - } - - networkName := mode.NetworkName() - if mode.IsDefault() { - networkName = controller.Config().Daemon.DefaultNetwork - } - if mode.IsUserDefined() { - n, err := daemon.FindNetwork(networkName) - if err != nil { - return err - } - networkName = n.Name() - } - container.NetworkSettings.Networks = make(map[string]*network.EndpointSettings) - container.NetworkSettings.Networks[networkName] = new(network.EndpointSettings) - updateSettings = true - } - - for n := range container.NetworkSettings.Networks { - if err := daemon.connectToNetwork(container, n, updateSettings); err != nil { - return err - } - } - - return container.writeHostConfig() -} - -func (daemon *Daemon) getNetworkSandbox(container *Container) libnetwork.Sandbox { - var sb libnetwork.Sandbox - daemon.netController.WalkSandboxes(func(s libnetwork.Sandbox) bool { - if s.ContainerID() == container.ID { - sb = s - return true - } - return false - }) - return sb -} - -// ConnectToNetwork connects a container to a netork -func (daemon *Daemon) ConnectToNetwork(container *Container, idOrName string) error { - if !container.Running { - return derr.ErrorCodeNotRunning.WithArgs(container.ID) - } - if err := daemon.connectToNetwork(container, idOrName, true); err != nil { - return err - } - if err := container.toDiskLocking(); err != nil { - return fmt.Errorf("Error saving container to disk: %v", err) - } - return nil -} - -func (daemon *Daemon) connectToNetwork(container *Container, idOrName string, updateSettings bool) (err error) { - if container.hostConfig.NetworkMode.IsContainer() { - return runconfig.ErrConflictSharedNetwork - } - - if runconfig.NetworkMode(idOrName).IsBridge() && - daemon.configStore.DisableBridge { - container.Config.NetworkDisabled = true - return nil - } - - controller := daemon.netController - - n, err := daemon.FindNetwork(idOrName) - if err != nil { - return err - } - - if updateSettings { - if err := daemon.updateNetworkSettings(container, n); err != nil { - return err - } - } - - ep, err := container.getEndpointInNetwork(n) - if err == nil { - return fmt.Errorf("container already connected to network %s", idOrName) - } - - if _, ok := err.(libnetwork.ErrNoSuchEndpoint); !ok { - return err - } - - createOptions, err := container.buildCreateEndpointOptions(n) - if err != nil { - return err - } - - endpointName := strings.TrimPrefix(container.Name, "/") - ep, err = n.CreateEndpoint(endpointName, createOptions...) - if err != nil { - return err - } - defer func() { - if err != nil { - if e := ep.Delete(); e != nil { - logrus.Warnf("Could not rollback container connection to network %s", idOrName) - } - } - }() - - if err := daemon.updateEndpointNetworkSettings(container, n, ep); err != nil { - return err - } - - sb := daemon.getNetworkSandbox(container) - if sb == nil { - options, err := daemon.buildSandboxOptions(container, n) - if err != nil { - return err - } - sb, err = controller.NewSandbox(container.ID, options...) - if err != nil { - return err - } - - container.updateSandboxNetworkSettings(sb) - } - - if err := ep.Join(sb); err != nil { - return err - } - - if err := container.updateJoinInfo(n, ep); err != nil { - return derr.ErrorCodeJoinInfo.WithArgs(err) - } - - return nil -} - -func (daemon *Daemon) initializeNetworking(container *Container) error { - var err error - - if container.hostConfig.NetworkMode.IsContainer() { - // we need to get the hosts files from the container to join - nc, err := daemon.getNetworkedContainer(container.ID, container.hostConfig.NetworkMode.ConnectedContainer()) - if err != nil { - return err - } - container.HostnamePath = nc.HostnamePath - container.HostsPath = nc.HostsPath - container.ResolvConfPath = nc.ResolvConfPath - container.Config.Hostname = nc.Config.Hostname - container.Config.Domainname = nc.Config.Domainname - return nil - } - - if container.hostConfig.NetworkMode.IsHost() { - container.Config.Hostname, err = os.Hostname() - if err != nil { - return err - } - - parts := strings.SplitN(container.Config.Hostname, ".", 2) - if len(parts) > 1 { - container.Config.Hostname = parts[0] - container.Config.Domainname = parts[1] - } - - } - - if err := daemon.allocateNetwork(container); err != nil { - return err - } - - return container.buildHostnameFile() -} - -// called from the libcontainer pre-start hook to set the network -// namespace configuration linkage to the libnetwork "sandbox" entity -func (daemon *Daemon) setNetworkNamespaceKey(containerID string, pid int) error { - path := fmt.Sprintf("/proc/%d/ns/net", pid) - var sandbox libnetwork.Sandbox - search := libnetwork.SandboxContainerWalker(&sandbox, containerID) - daemon.netController.WalkSandboxes(search) - if sandbox == nil { - return derr.ErrorCodeNoSandbox.WithArgs(containerID, "no sandbox found") - } - - return sandbox.SetKey(path) -} - -func (daemon *Daemon) getIpcContainer(container *Container) (*Container, error) { - containerID := container.hostConfig.IpcMode.Container() - c, err := daemon.Get(containerID) - if err != nil { - return nil, err - } - if !c.IsRunning() { - return nil, derr.ErrorCodeIPCRunning - } - return c, nil -} - -func (container *Container) setupWorkingDirectory() error { - if container.Config.WorkingDir == "" { - return nil - } - container.Config.WorkingDir = filepath.Clean(container.Config.WorkingDir) - - pth, err := container.GetResourcePath(container.Config.WorkingDir) - if err != nil { - return err - } - - pthInfo, err := os.Stat(pth) - if err != nil { - if !os.IsNotExist(err) { - return err - } - - if err := system.MkdirAll(pth, 0755); err != nil { - return err - } - } - if pthInfo != nil && !pthInfo.IsDir() { - return derr.ErrorCodeNotADir.WithArgs(container.Config.WorkingDir) - } - return nil -} - -func (daemon *Daemon) getNetworkedContainer(containerID, connectedContainerID string) (*Container, error) { - nc, err := daemon.Get(connectedContainerID) - if err != nil { - return nil, err - } - if containerID == nc.ID { - return nil, derr.ErrorCodeJoinSelf - } - if !nc.IsRunning() { - return nil, derr.ErrorCodeJoinRunning.WithArgs(connectedContainerID) - } - return nc, nil -} - -func (daemon *Daemon) releaseNetwork(container *Container) { - if container.hostConfig.NetworkMode.IsContainer() || container.Config.NetworkDisabled { - return - } - - sid := container.NetworkSettings.SandboxID - networks := container.NetworkSettings.Networks - for n := range networks { - networks[n] = &network.EndpointSettings{} - } - - container.NetworkSettings = &network.Settings{Networks: networks} - - if sid == "" || len(networks) == 0 { - return - } - - sb, err := daemon.netController.SandboxByID(sid) - if err != nil { - logrus.Errorf("error locating sandbox id %s: %v", sid, err) - return - } - - if err := sb.Delete(); err != nil { - logrus.Errorf("Error deleting sandbox id %s for container %s: %v", sid, container.ID, err) - } -} - -// DisconnectFromNetwork disconnects a container from a network -func (container *Container) DisconnectFromNetwork(n libnetwork.Network) error { - if !container.Running { - return derr.ErrorCodeNotRunning.WithArgs(container.ID) - } - - if err := container.disconnectFromNetwork(n); err != nil { - return err - } - - if err := container.toDiskLocking(); err != nil { - return fmt.Errorf("Error saving container to disk: %v", err) - } - return nil -} - -func (container *Container) disconnectFromNetwork(n libnetwork.Network) error { - var ( - ep libnetwork.Endpoint - sbox libnetwork.Sandbox - ) - - s := func(current libnetwork.Endpoint) bool { - epInfo := current.Info() - if epInfo == nil { - return false - } - if sb := epInfo.Sandbox(); sb != nil { - if sb.ContainerID() == container.ID { - ep = current - sbox = sb - return true - } - } - return false - } - n.WalkEndpoints(s) - - if ep == nil { - return fmt.Errorf("container %s is not connected to the network", container.ID) - } - - if err := ep.Leave(sbox); err != nil { - return fmt.Errorf("container %s failed to leave network %s: %v", container.ID, n.Name(), err) - } - - if err := ep.Delete(); err != nil { - return fmt.Errorf("endpoint delete failed for container %s on network %s: %v", container.ID, n.Name(), err) - } - - delete(container.NetworkSettings.Networks, n.Name()) - return nil -} - -// appendNetworkMounts appends any network mounts to the array of mount points passed in -func appendNetworkMounts(container *Container, volumeMounts []volume.MountPoint) ([]volume.MountPoint, error) { - for _, mnt := range container.networkMounts() { - dest, err := container.GetResourcePath(mnt.Destination) - if err != nil { - return nil, err - } - volumeMounts = append(volumeMounts, volume.MountPoint{Destination: dest}) - } - return volumeMounts, nil -} - -func (container *Container) networkMounts() []execdriver.Mount { - var mounts []execdriver.Mount - shared := container.hostConfig.NetworkMode.IsContainer() - if container.ResolvConfPath != "" { - if _, err := os.Stat(container.ResolvConfPath); err != nil { - logrus.Warnf("ResolvConfPath set to %q, but can't stat this filename (err = %v); skipping", container.ResolvConfPath, err) - } else { - label.Relabel(container.ResolvConfPath, container.MountLabel, shared) - writable := !container.hostConfig.ReadonlyRootfs - if m, exists := container.MountPoints["/etc/resolv.conf"]; exists { - writable = m.RW - } - mounts = append(mounts, execdriver.Mount{ - Source: container.ResolvConfPath, - Destination: "/etc/resolv.conf", - Writable: writable, - Private: true, - }) - } - } - if container.HostnamePath != "" { - if _, err := os.Stat(container.HostnamePath); err != nil { - logrus.Warnf("HostnamePath set to %q, but can't stat this filename (err = %v); skipping", container.HostnamePath, err) - } else { - label.Relabel(container.HostnamePath, container.MountLabel, shared) - writable := !container.hostConfig.ReadonlyRootfs - if m, exists := container.MountPoints["/etc/hostname"]; exists { - writable = m.RW - } - mounts = append(mounts, execdriver.Mount{ - Source: container.HostnamePath, - Destination: "/etc/hostname", - Writable: writable, - Private: true, - }) - } - } - if container.HostsPath != "" { - if _, err := os.Stat(container.HostsPath); err != nil { - logrus.Warnf("HostsPath set to %q, but can't stat this filename (err = %v); skipping", container.HostsPath, err) - } else { - label.Relabel(container.HostsPath, container.MountLabel, shared) - writable := !container.hostConfig.ReadonlyRootfs - if m, exists := container.MountPoints["/etc/hosts"]; exists { - writable = m.RW - } - mounts = append(mounts, execdriver.Mount{ - Source: container.HostsPath, - Destination: "/etc/hosts", - Writable: writable, - Private: true, - }) - } - } - return mounts -} - -func (container *Container) copyImagePathContent(v volume.Volume, destination string) error { - rootfs, err := symlink.FollowSymlinkInScope(filepath.Join(container.basefs, destination), container.basefs) - if err != nil { - return err - } - - if _, err = ioutil.ReadDir(rootfs); err != nil { - if os.IsNotExist(err) { - return nil - } - return err - } - - path, err := v.Mount() - if err != nil { - return err - } - - if err := copyExistingContents(rootfs, path); err != nil { - return err - } - - return v.Unmount() -} - -func (container *Container) shmPath() (string, error) { - return container.getRootResourcePath("shm") -} -func (container *Container) mqueuePath() (string, error) { - return container.getRootResourcePath("mqueue") -} - -func (container *Container) hasMountFor(path string) bool { - _, exists := container.MountPoints[path] - return exists -} - -func (daemon *Daemon) setupIpcDirs(container *Container) error { - rootUID, rootGID := daemon.GetRemappedUIDGID() - if !container.hasMountFor("/dev/shm") { - shmPath, err := container.shmPath() - if err != nil { - return err - } - - if err := idtools.MkdirAllAs(shmPath, 0700, rootUID, rootGID); err != nil { - return err - } - - if err := syscall.Mount("shm", shmPath, "tmpfs", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), label.FormatMountLabel("mode=1777,size=65536k", container.getMountLabel())); err != nil { - return fmt.Errorf("mounting shm tmpfs: %s", err) - } - if err := os.Chown(shmPath, rootUID, rootGID); err != nil { - return err - } - } - - if !container.hasMountFor("/dev/mqueue") { - mqueuePath, err := container.mqueuePath() - if err != nil { - return err - } - - if err := idtools.MkdirAllAs(mqueuePath, 0700, rootUID, rootGID); err != nil { - return err - } - - if err := syscall.Mount("mqueue", mqueuePath, "mqueue", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), ""); err != nil { - return fmt.Errorf("mounting mqueue mqueue : %s", err) - } - if err := os.Chown(mqueuePath, rootUID, rootGID); err != nil { - return err - } - } - - return nil -} - -func (container *Container) unmountIpcMounts(unmount func(pth string) error) { - if container.hostConfig.IpcMode.IsContainer() || container.hostConfig.IpcMode.IsHost() { - return - } - - var warnings []string - - if !container.hasMountFor("/dev/shm") { - shmPath, err := container.shmPath() - if err != nil { - logrus.Error(err) - warnings = append(warnings, err.Error()) - } else if shmPath != "" { - if err := unmount(shmPath); err != nil { - warnings = append(warnings, fmt.Sprintf("failed to umount %s: %v", shmPath, err)) - } - - } - } - - if !container.hasMountFor("/dev/mqueue") { - mqueuePath, err := container.mqueuePath() - if err != nil { - logrus.Error(err) - warnings = append(warnings, err.Error()) - } else if mqueuePath != "" { - if err := unmount(mqueuePath); err != nil { - warnings = append(warnings, fmt.Sprintf("failed to umount %s: %v", mqueuePath, err)) - } - } - } - - if len(warnings) > 0 { - logrus.Warnf("failed to cleanup ipc mounts:\n%v", strings.Join(warnings, "\n")) - } -} - -func (container *Container) ipcMounts() []execdriver.Mount { - var mounts []execdriver.Mount - - if !container.hasMountFor("/dev/shm") { - label.SetFileLabel(container.ShmPath, container.MountLabel) - mounts = append(mounts, execdriver.Mount{ - Source: container.ShmPath, - Destination: "/dev/shm", - Writable: true, - Private: true, - }) - } - - if !container.hasMountFor("/dev/mqueue") { - label.SetFileLabel(container.MqueuePath, container.MountLabel) - mounts = append(mounts, execdriver.Mount{ - Source: container.MqueuePath, - Destination: "/dev/mqueue", - Writable: true, - Private: true, - }) - } - return mounts -} - -func detachMounted(path string) error { - return syscall.Unmount(path, syscall.MNT_DETACH) -} diff --git a/vendor/github.com/docker/docker/daemon/container_windows.go b/vendor/github.com/docker/docker/daemon/container_windows.go deleted file mode 100644 index fd2dcb9b..00000000 --- a/vendor/github.com/docker/docker/daemon/container_windows.go +++ /dev/null @@ -1,192 +0,0 @@ -// +build windows - -package daemon - -import ( - "strings" - - "github.com/docker/docker/daemon/execdriver" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/volume" - "github.com/docker/libnetwork" -) - -// DefaultPathEnv is deliberately empty on Windows as the default path will be set by -// the container. Docker has no context of what the default path should be. -const DefaultPathEnv = "" - -// Container holds fields specific to the Windows implementation. See -// CommonContainer for standard fields common to all containers. -type Container struct { - CommonContainer - - // Fields below here are platform specific. -} - -func killProcessDirectly(container *Container) error { - return nil -} - -func (daemon *Daemon) setupLinkedContainers(container *Container) ([]string, error) { - return nil, nil -} - -func (container *Container) createDaemonEnvironment(linkedEnv []string) []string { - // On Windows, nothing to link. Just return the container environment. - return container.Config.Env -} - -func (daemon *Daemon) initializeNetworking(container *Container) error { - return nil -} - -// ConnectToNetwork connects a container to the network -func (daemon *Daemon) ConnectToNetwork(container *Container, idOrName string) error { - return nil -} - -// DisconnectFromNetwork disconnects a container from, the network -func (container *Container) DisconnectFromNetwork(n libnetwork.Network) error { - return nil -} - -func (container *Container) setupWorkingDirectory() error { - return nil -} - -func (daemon *Daemon) populateCommand(c *Container, env []string) error { - en := &execdriver.Network{ - Interface: nil, - } - - parts := strings.SplitN(string(c.hostConfig.NetworkMode), ":", 2) - switch parts[0] { - case "none": - case "default", "": // empty string to support existing containers - if !c.Config.NetworkDisabled { - en.Interface = &execdriver.NetworkInterface{ - MacAddress: c.Config.MacAddress, - Bridge: daemon.configStore.Bridge.VirtualSwitchName, - PortBindings: c.hostConfig.PortBindings, - - // TODO Windows. Include IPAddress. There already is a - // property IPAddress on execDrive.CommonNetworkInterface, - // but there is no CLI option in docker to pass through - // an IPAddress on docker run. - } - } - default: - return derr.ErrorCodeInvalidNetworkMode.WithArgs(c.hostConfig.NetworkMode) - } - - // TODO Windows. More resource controls to be implemented later. - resources := &execdriver.Resources{ - CommonResources: execdriver.CommonResources{ - CPUShares: c.hostConfig.CPUShares, - }, - } - - // TODO Windows. Further refactoring required (privileged/user) - processConfig := execdriver.ProcessConfig{ - Privileged: c.hostConfig.Privileged, - Entrypoint: c.Path, - Arguments: c.Args, - Tty: c.Config.Tty, - User: c.Config.User, - ConsoleSize: c.hostConfig.ConsoleSize, - } - - processConfig.Env = env - - var layerPaths []string - img, err := daemon.graph.Get(c.ImageID) - if err != nil { - return derr.ErrorCodeGetGraph.WithArgs(c.ImageID, err) - } - for i := img; i != nil && err == nil; i, err = daemon.graph.GetParent(i) { - lp, err := daemon.driver.Get(i.ID, "") - if err != nil { - return derr.ErrorCodeGetLayer.WithArgs(daemon.driver.String(), i.ID, err) - } - layerPaths = append(layerPaths, lp) - err = daemon.driver.Put(i.ID) - if err != nil { - return derr.ErrorCodePutLayer.WithArgs(daemon.driver.String(), i.ID, err) - } - } - m, err := daemon.driver.GetMetadata(c.ID) - if err != nil { - return derr.ErrorCodeGetLayerMetadata.WithArgs(err) - } - layerFolder := m["dir"] - - c.command = &execdriver.Command{ - CommonCommand: execdriver.CommonCommand{ - ID: c.ID, - Rootfs: c.rootfsPath(), - InitPath: "/.dockerinit", - WorkingDir: c.Config.WorkingDir, - Network: en, - MountLabel: c.getMountLabel(), - Resources: resources, - ProcessConfig: processConfig, - ProcessLabel: c.getProcessLabel(), - }, - FirstStart: !c.HasBeenStartedBefore, - LayerFolder: layerFolder, - LayerPaths: layerPaths, - Hostname: c.Config.Hostname, - Isolated: c.hostConfig.Isolation.IsHyperV(), - } - - return nil -} - -// getSize returns real size & virtual size -func (daemon *Daemon) getSize(container *Container) (int64, int64) { - // TODO Windows - return 0, 0 -} - -// setNetworkNamespaceKey is a no-op on Windows. -func (daemon *Daemon) setNetworkNamespaceKey(containerID string, pid int) error { - return nil -} - -// allocateNetwork is a no-op on Windows. -func (daemon *Daemon) allocateNetwork(container *Container) error { - return nil -} - -func (daemon *Daemon) updateNetwork(container *Container) error { - return nil -} - -func (daemon *Daemon) releaseNetwork(container *Container) { -} - -// appendNetworkMounts appends any network mounts to the array of mount points passed in. -// Windows does not support network mounts (not to be confused with SMB network mounts), so -// this is a no-op. -func appendNetworkMounts(container *Container, volumeMounts []volume.MountPoint) ([]volume.MountPoint, error) { - return volumeMounts, nil -} - -func (daemon *Daemon) setupIpcDirs(container *Container) error { - return nil -} - -func (container *Container) unmountIpcMounts(unmount func(pth string) error) { -} - -func detachMounted(path string) error { - return nil -} - -func (container *Container) ipcMounts() []execdriver.Mount { - return nil -} - -func getDefaultRouteMtu() (int, error) { - return -1, errSystemNotSupported -} diff --git a/vendor/github.com/docker/docker/daemon/create.go b/vendor/github.com/docker/docker/daemon/create.go deleted file mode 100644 index fb20d213..00000000 --- a/vendor/github.com/docker/docker/daemon/create.go +++ /dev/null @@ -1,148 +0,0 @@ -package daemon - -import ( - "github.com/Sirupsen/logrus" - "github.com/docker/docker/api/types" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/image" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/runconfig" - "github.com/docker/docker/volume" - "github.com/opencontainers/runc/libcontainer/label" -) - -// ContainerCreateConfig is the parameter set to ContainerCreate() -type ContainerCreateConfig struct { - Name string - Config *runconfig.Config - HostConfig *runconfig.HostConfig - AdjustCPUShares bool -} - -// ContainerCreate takes configs and creates a container. -func (daemon *Daemon) ContainerCreate(params *ContainerCreateConfig) (types.ContainerCreateResponse, error) { - if params.Config == nil { - return types.ContainerCreateResponse{}, derr.ErrorCodeEmptyConfig - } - - warnings, err := daemon.verifyContainerSettings(params.HostConfig, params.Config) - if err != nil { - return types.ContainerCreateResponse{ID: "", Warnings: warnings}, err - } - - daemon.adaptContainerSettings(params.HostConfig, params.AdjustCPUShares) - - container, err := daemon.create(params) - if err != nil { - return types.ContainerCreateResponse{ID: "", Warnings: warnings}, daemon.graphNotExistToErrcode(params.Config.Image, err) - } - - return types.ContainerCreateResponse{ID: container.ID, Warnings: warnings}, nil -} - -// Create creates a new container from the given configuration with a given name. -func (daemon *Daemon) create(params *ContainerCreateConfig) (retC *Container, retErr error) { - var ( - container *Container - img *image.Image - imgID string - err error - ) - - if params.Config.Image != "" { - img, err = daemon.repositories.LookupImage(params.Config.Image) - if err != nil { - return nil, err - } - if err = daemon.graph.CheckDepth(img); err != nil { - return nil, err - } - imgID = img.ID - } - - if err := daemon.mergeAndVerifyConfig(params.Config, img); err != nil { - return nil, err - } - - if params.HostConfig == nil { - params.HostConfig = &runconfig.HostConfig{} - } - if params.HostConfig.SecurityOpt == nil { - params.HostConfig.SecurityOpt, err = daemon.generateSecurityOpt(params.HostConfig.IpcMode, params.HostConfig.PidMode) - if err != nil { - return nil, err - } - } - if container, err = daemon.newContainer(params.Name, params.Config, imgID); err != nil { - return nil, err - } - defer func() { - if retErr != nil { - if err := daemon.rm(container, false); err != nil { - logrus.Errorf("Clean up Error! Cannot destroy container %s: %v", container.ID, err) - } - } - }() - - if err := daemon.Register(container); err != nil { - return nil, err - } - if err := daemon.createRootfs(container); err != nil { - return nil, err - } - if err := daemon.setHostConfig(container, params.HostConfig); err != nil { - return nil, err - } - defer func() { - if retErr != nil { - if err := daemon.removeMountPoints(container, true); err != nil { - logrus.Error(err) - } - } - }() - - if err := daemon.createContainerPlatformSpecificSettings(container, params.Config, params.HostConfig, img); err != nil { - return nil, err - } - - if err := container.toDiskLocking(); err != nil { - logrus.Errorf("Error saving new container to disk: %v", err) - return nil, err - } - daemon.LogContainerEvent(container, "create") - return container, nil -} - -func (daemon *Daemon) generateSecurityOpt(ipcMode runconfig.IpcMode, pidMode runconfig.PidMode) ([]string, error) { - if ipcMode.IsHost() || pidMode.IsHost() { - return label.DisableSecOpt(), nil - } - if ipcContainer := ipcMode.Container(); ipcContainer != "" { - c, err := daemon.Get(ipcContainer) - if err != nil { - return nil, err - } - - return label.DupSecOpt(c.ProcessLabel), nil - } - return nil, nil -} - -// VolumeCreate creates a volume with the specified name, driver, and opts -// This is called directly from the remote API -func (daemon *Daemon) VolumeCreate(name, driverName string, opts map[string]string) (*types.Volume, error) { - if name == "" { - name = stringid.GenerateNonCryptoID() - } - - v, err := daemon.volumes.Create(name, driverName, opts) - if err != nil { - return nil, err - } - - // keep "docker run -v existing_volume:/foo --volume-driver other_driver" work - if (driverName != "" && v.DriverName() != driverName) || (driverName == "" && v.DriverName() != volume.DefaultDriverName) { - return nil, derr.ErrorVolumeNameTaken.WithArgs(name, v.DriverName()) - } - return volumeToAPIType(v), nil -} diff --git a/vendor/github.com/docker/docker/daemon/create_unix.go b/vendor/github.com/docker/docker/daemon/create_unix.go deleted file mode 100644 index 4975c350..00000000 --- a/vendor/github.com/docker/docker/daemon/create_unix.go +++ /dev/null @@ -1,72 +0,0 @@ -// +build !windows - -package daemon - -import ( - "os" - "path/filepath" - - derr "github.com/docker/docker/errors" - "github.com/docker/docker/image" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/runconfig" - "github.com/docker/docker/volume" - "github.com/opencontainers/runc/libcontainer/label" -) - -// createContainerPlatformSpecificSettings performs platform specific container create functionality -func (daemon *Daemon) createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config, hostConfig *runconfig.HostConfig, img *image.Image) error { - if err := daemon.Mount(container); err != nil { - return err - } - defer daemon.Unmount(container) - - for spec := range config.Volumes { - name := stringid.GenerateNonCryptoID() - destination := filepath.Clean(spec) - - // Skip volumes for which we already have something mounted on that - // destination because of a --volume-from. - if container.isDestinationMounted(destination) { - continue - } - path, err := container.GetResourcePath(destination) - if err != nil { - return err - } - - stat, err := os.Stat(path) - if err == nil && !stat.IsDir() { - return derr.ErrorCodeMountOverFile.WithArgs(path) - } - - volumeDriver := hostConfig.VolumeDriver - if destination != "" && img != nil { - if _, ok := img.ContainerConfig.Volumes[destination]; ok { - // check for whether bind is not specified and then set to local - if _, ok := container.MountPoints[destination]; !ok { - volumeDriver = volume.DefaultDriverName - } - } - } - - v, err := daemon.createVolume(name, volumeDriver, nil) - if err != nil { - return err - } - - if err := label.Relabel(v.Path(), container.MountLabel, true); err != nil { - return err - } - - // never attempt to copy existing content in a container FS to a shared volume - if v.DriverName() == volume.DefaultDriverName { - if err := container.copyImagePathContent(v, destination); err != nil { - return err - } - } - - container.addMountPointWithVolume(destination, v, true) - } - return nil -} diff --git a/vendor/github.com/docker/docker/daemon/create_windows.go b/vendor/github.com/docker/docker/daemon/create_windows.go deleted file mode 100644 index a95e667b..00000000 --- a/vendor/github.com/docker/docker/daemon/create_windows.go +++ /dev/null @@ -1,83 +0,0 @@ -package daemon - -import ( - "fmt" - - "github.com/docker/docker/image" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/runconfig" - "github.com/docker/docker/volume" -) - -// createContainerPlatformSpecificSettings performs platform specific container create functionality -func (daemon *Daemon) createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config, hostConfig *runconfig.HostConfig, img *image.Image) error { - for spec := range config.Volumes { - - mp, err := volume.ParseMountSpec(spec, hostConfig.VolumeDriver) - if err != nil { - return fmt.Errorf("Unrecognised volume spec: %v", err) - } - - // If the mountpoint doesn't have a name, generate one. - if len(mp.Name) == 0 { - mp.Name = stringid.GenerateNonCryptoID() - } - - // Skip volumes for which we already have something mounted on that - // destination because of a --volume-from. - if container.isDestinationMounted(mp.Destination) { - continue - } - - volumeDriver := hostConfig.VolumeDriver - if mp.Destination != "" && img != nil { - if _, ok := img.ContainerConfig.Volumes[mp.Destination]; ok { - // check for whether bind is not specified and then set to local - if _, ok := container.MountPoints[mp.Destination]; !ok { - volumeDriver = volume.DefaultDriverName - } - } - } - - // Create the volume in the volume driver. If it doesn't exist, - // a new one will be created. - v, err := daemon.createVolume(mp.Name, volumeDriver, nil) - if err != nil { - return err - } - - // FIXME Windows: This code block is present in the Linux version and - // allows the contents to be copied to the container FS prior to it - // being started. However, the function utilises the FollowSymLinkInScope - // path which does not cope with Windows volume-style file paths. There - // is a seperate effort to resolve this (@swernli), so this processing - // is deferred for now. A case where this would be useful is when - // a dockerfile includes a VOLUME statement, but something is created - // in that directory during the dockerfile processing. What this means - // on Windows for TP4 is that in that scenario, the contents will not - // copied, but that's (somewhat) OK as HCS will bomb out soon after - // at it doesn't support mapped directories which have contents in the - // destination path anyway. - // - // Example for repro later: - // FROM windowsservercore - // RUN mkdir c:\myvol - // RUN copy c:\windows\system32\ntdll.dll c:\myvol - // VOLUME "c:\myvol" - // - // Then - // docker build -t vol . - // docker run -it --rm vol cmd <-- This is where HCS will error out. - // - // // never attempt to copy existing content in a container FS to a shared volume - // if v.DriverName() == volume.DefaultDriverName { - // if err := container.copyImagePathContent(v, mp.Destination); err != nil { - // return err - // } - // } - - // Add it to container.MountPoints - container.addMountPointWithVolume(mp.Destination, v, mp.RW) - } - return nil -} diff --git a/vendor/github.com/docker/docker/daemon/daemon.go b/vendor/github.com/docker/docker/daemon/daemon.go deleted file mode 100644 index 6336faf5..00000000 --- a/vendor/github.com/docker/docker/daemon/daemon.go +++ /dev/null @@ -1,1350 +0,0 @@ -// Package daemon exposes the functions that occur on the host server -// that the Docker daemon is running. -// -// In implementing the various functions of the daemon, there is often -// a method-specific struct for configuring the runtime behavior. -package daemon - -import ( - "errors" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "runtime" - "strings" - "sync" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/api" - "github.com/docker/docker/api/types" - "github.com/docker/docker/cliconfig" - "github.com/docker/docker/daemon/events" - "github.com/docker/docker/daemon/execdriver" - "github.com/docker/docker/daemon/execdriver/execdrivers" - "github.com/docker/docker/daemon/graphdriver" - _ "github.com/docker/docker/daemon/graphdriver/vfs" // register vfs - "github.com/docker/docker/daemon/logger" - "github.com/docker/docker/daemon/network" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/graph" - "github.com/docker/docker/image" - "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/broadcaster" - "github.com/docker/docker/pkg/discovery" - "github.com/docker/docker/pkg/fileutils" - "github.com/docker/docker/pkg/graphdb" - "github.com/docker/docker/pkg/idtools" - "github.com/docker/docker/pkg/ioutils" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/docker/docker/pkg/mount" - "github.com/docker/docker/pkg/namesgenerator" - "github.com/docker/docker/pkg/nat" - "github.com/docker/docker/pkg/parsers/filters" - "github.com/docker/docker/pkg/signal" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/pkg/stringutils" - "github.com/docker/docker/pkg/sysinfo" - "github.com/docker/docker/pkg/system" - "github.com/docker/docker/pkg/truncindex" - "github.com/docker/docker/registry" - "github.com/docker/docker/runconfig" - "github.com/docker/docker/utils" - volumedrivers "github.com/docker/docker/volume/drivers" - "github.com/docker/docker/volume/local" - "github.com/docker/docker/volume/store" - "github.com/docker/libnetwork" - lntypes "github.com/docker/libnetwork/types" - "github.com/opencontainers/runc/libcontainer" -) - -var ( - validContainerNameChars = utils.RestrictedNameChars - validContainerNamePattern = utils.RestrictedNamePattern - - errSystemNotSupported = errors.New("The Docker daemon is not supported on this platform.") -) - -type contStore struct { - s map[string]*Container - sync.Mutex -} - -func (c *contStore) Add(id string, cont *Container) { - c.Lock() - c.s[id] = cont - c.Unlock() -} - -func (c *contStore) Get(id string) *Container { - c.Lock() - res := c.s[id] - c.Unlock() - return res -} - -func (c *contStore) Delete(id string) { - c.Lock() - delete(c.s, id) - c.Unlock() -} - -func (c *contStore) List() []*Container { - containers := new(History) - c.Lock() - for _, cont := range c.s { - containers.Add(cont) - } - c.Unlock() - containers.sort() - return *containers -} - -// Daemon holds information about the Docker daemon. -type Daemon struct { - ID string - repository string - sysInitPath string - containers *contStore - execCommands *execStore - graph *graph.Graph - repositories *graph.TagStore - idIndex *truncindex.TruncIndex - configStore *Config - containerGraphDB *graphdb.Database - driver graphdriver.Driver - execDriver execdriver.Driver - statsCollector *statsCollector - defaultLogConfig runconfig.LogConfig - RegistryService *registry.Service - EventsService *events.Events - netController libnetwork.NetworkController - volumes *store.VolumeStore - discoveryWatcher discovery.Watcher - root string - shutdown bool - uidMaps []idtools.IDMap - gidMaps []idtools.IDMap -} - -// Get looks for a container using the provided information, which could be -// one of the following inputs from the caller: -// - A full container ID, which will exact match a container in daemon's list -// - A container name, which will only exact match via the GetByName() function -// - A partial container ID prefix (e.g. short ID) of any length that is -// unique enough to only return a single container object -// If none of these searches succeed, an error is returned -func (daemon *Daemon) Get(prefixOrName string) (*Container, error) { - if containerByID := daemon.containers.Get(prefixOrName); containerByID != nil { - // prefix is an exact match to a full container ID - return containerByID, nil - } - - // GetByName will match only an exact name provided; we ignore errors - if containerByName, _ := daemon.GetByName(prefixOrName); containerByName != nil { - // prefix is an exact match to a full container Name - return containerByName, nil - } - - containerID, indexError := daemon.idIndex.Get(prefixOrName) - if indexError != nil { - // When truncindex defines an error type, use that instead - if indexError == truncindex.ErrNotExist { - return nil, derr.ErrorCodeNoSuchContainer.WithArgs(prefixOrName) - } - return nil, indexError - } - return daemon.containers.Get(containerID), nil -} - -// Exists returns a true if a container of the specified ID or name exists, -// false otherwise. -func (daemon *Daemon) Exists(id string) bool { - c, _ := daemon.Get(id) - return c != nil -} - -// IsPaused returns a bool indicating if the specified container is paused. -func (daemon *Daemon) IsPaused(id string) bool { - c, _ := daemon.Get(id) - return c.State.isPaused() -} - -func (daemon *Daemon) containerRoot(id string) string { - return filepath.Join(daemon.repository, id) -} - -// Load reads the contents of a container from disk -// This is typically done at startup. -func (daemon *Daemon) load(id string) (*Container, error) { - container := daemon.newBaseContainer(id) - - if err := container.fromDisk(); err != nil { - return nil, err - } - - if container.ID != id { - return container, fmt.Errorf("Container %s is stored at %s", container.ID, id) - } - - return container, nil -} - -// Register makes a container object usable by the daemon as -func (daemon *Daemon) Register(container *Container) error { - if daemon.Exists(container.ID) { - return fmt.Errorf("Container is already loaded") - } - if err := validateID(container.ID); err != nil { - return err - } - if err := daemon.ensureName(container); err != nil { - return err - } - - // Attach to stdout and stderr - container.stderr = new(broadcaster.Unbuffered) - container.stdout = new(broadcaster.Unbuffered) - // Attach to stdin - if container.Config.OpenStdin { - container.stdin, container.stdinPipe = io.Pipe() - } else { - container.stdinPipe = ioutils.NopWriteCloser(ioutil.Discard) // Silently drop stdin - } - // done - daemon.containers.Add(container.ID, container) - - // don't update the Suffixarray if we're starting up - // we'll waste time if we update it for every container - daemon.idIndex.Add(container.ID) - - if container.IsRunning() { - logrus.Debugf("killing old running container %s", container.ID) - // Set exit code to 128 + SIGKILL (9) to properly represent unsuccessful exit - container.setStoppedLocking(&execdriver.ExitStatus{ExitCode: 137}) - // use the current driver and ensure that the container is dead x.x - cmd := &execdriver.Command{ - CommonCommand: execdriver.CommonCommand{ - ID: container.ID, - }, - } - daemon.execDriver.Terminate(cmd) - - container.unmountIpcMounts(mount.Unmount) - - if err := daemon.Unmount(container); err != nil { - logrus.Debugf("unmount error %s", err) - } - if err := container.toDiskLocking(); err != nil { - logrus.Errorf("Error saving stopped state to disk: %v", err) - } - } - - if err := daemon.verifyVolumesInfo(container); err != nil { - return err - } - - if err := daemon.prepareMountPoints(container); err != nil { - return err - } - - return nil -} - -func (daemon *Daemon) ensureName(container *Container) error { - if container.Name == "" { - name, err := daemon.generateNewName(container.ID) - if err != nil { - return err - } - container.Name = name - - if err := container.toDiskLocking(); err != nil { - logrus.Errorf("Error saving container name to disk: %v", err) - } - } - return nil -} - -func (daemon *Daemon) restore() error { - type cr struct { - container *Container - registered bool - } - - var ( - debug = os.Getenv("DEBUG") != "" - currentDriver = daemon.driver.String() - containers = make(map[string]*cr) - ) - - if !debug { - logrus.Info("Loading containers: start.") - } - dir, err := ioutil.ReadDir(daemon.repository) - if err != nil { - return err - } - - for _, v := range dir { - id := v.Name() - container, err := daemon.load(id) - if !debug && logrus.GetLevel() == logrus.InfoLevel { - fmt.Print(".") - } - if err != nil { - logrus.Errorf("Failed to load container %v: %v", id, err) - continue - } - - // Ignore the container if it does not support the current driver being used by the graph - if (container.Driver == "" && currentDriver == "aufs") || container.Driver == currentDriver { - logrus.Debugf("Loaded container %v", container.ID) - - containers[container.ID] = &cr{container: container} - } else { - logrus.Debugf("Cannot load container %s because it was created with another graph driver.", container.ID) - } - } - - if entities := daemon.containerGraphDB.List("/", -1); entities != nil { - for _, p := range entities.Paths() { - if !debug && logrus.GetLevel() == logrus.InfoLevel { - fmt.Print(".") - } - - e := entities[p] - - if c, ok := containers[e.ID()]; ok { - c.registered = true - } - } - } - - group := sync.WaitGroup{} - for _, c := range containers { - group.Add(1) - - go func(container *Container, registered bool) { - defer group.Done() - - if !registered { - // Try to set the default name for a container if it exists prior to links - container.Name, err = daemon.generateNewName(container.ID) - if err != nil { - logrus.Debugf("Setting default id - %s", err) - } - } - - if err := daemon.Register(container); err != nil { - logrus.Errorf("Failed to register container %s: %s", container.ID, err) - // The container register failed should not be started. - return - } - - // check the restart policy on the containers and restart any container with - // the restart policy of "always" - if daemon.configStore.AutoRestart && container.shouldRestart() { - logrus.Debugf("Starting container %s", container.ID) - - if err := daemon.containerStart(container); err != nil { - logrus.Errorf("Failed to start container %s: %s", container.ID, err) - } - } - }(c.container, c.registered) - } - group.Wait() - - if !debug { - if logrus.GetLevel() == logrus.InfoLevel { - fmt.Println() - } - logrus.Info("Loading containers: done.") - } - - return nil -} - -func (daemon *Daemon) mergeAndVerifyConfig(config *runconfig.Config, img *image.Image) error { - if img != nil && img.Config != nil { - if err := runconfig.Merge(config, img.Config); err != nil { - return err - } - } - if config.Entrypoint.Len() == 0 && config.Cmd.Len() == 0 { - return fmt.Errorf("No command specified") - } - return nil -} - -func (daemon *Daemon) generateIDAndName(name string) (string, string, error) { - var ( - err error - id = stringid.GenerateNonCryptoID() - ) - - if name == "" { - if name, err = daemon.generateNewName(id); err != nil { - return "", "", err - } - return id, name, nil - } - - if name, err = daemon.reserveName(id, name); err != nil { - return "", "", err - } - - return id, name, nil -} - -func (daemon *Daemon) reserveName(id, name string) (string, error) { - if !validContainerNamePattern.MatchString(name) { - return "", fmt.Errorf("Invalid container name (%s), only %s are allowed", name, validContainerNameChars) - } - - if name[0] != '/' { - name = "/" + name - } - - if _, err := daemon.containerGraphDB.Set(name, id); err != nil { - if !graphdb.IsNonUniqueNameError(err) { - return "", err - } - - conflictingContainer, err := daemon.GetByName(name) - if err != nil { - return "", err - } - return "", fmt.Errorf( - "Conflict. The name %q is already in use by container %s. You have to remove (or rename) that container to be able to reuse that name.", strings.TrimPrefix(name, "/"), - stringid.TruncateID(conflictingContainer.ID)) - - } - return name, nil -} - -func (daemon *Daemon) generateNewName(id string) (string, error) { - var name string - for i := 0; i < 6; i++ { - name = namesgenerator.GetRandomName(i) - if name[0] != '/' { - name = "/" + name - } - - if _, err := daemon.containerGraphDB.Set(name, id); err != nil { - if !graphdb.IsNonUniqueNameError(err) { - return "", err - } - continue - } - return name, nil - } - - name = "/" + stringid.TruncateID(id) - if _, err := daemon.containerGraphDB.Set(name, id); err != nil { - return "", err - } - return name, nil -} - -func (daemon *Daemon) generateHostname(id string, config *runconfig.Config) { - // Generate default hostname - if config.Hostname == "" { - config.Hostname = id[:12] - } -} - -func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint *stringutils.StrSlice, configCmd *stringutils.StrSlice) (string, []string) { - cmdSlice := configCmd.Slice() - if configEntrypoint.Len() != 0 { - eSlice := configEntrypoint.Slice() - return eSlice[0], append(eSlice[1:], cmdSlice...) - } - return cmdSlice[0], cmdSlice[1:] -} - -func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID string) (*Container, error) { - var ( - id string - err error - noExplicitName = name == "" - ) - id, name, err = daemon.generateIDAndName(name) - if err != nil { - return nil, err - } - - daemon.generateHostname(id, config) - entrypoint, args := daemon.getEntrypointAndArgs(config.Entrypoint, config.Cmd) - - base := daemon.newBaseContainer(id) - base.Created = time.Now().UTC() - base.Path = entrypoint - base.Args = args //FIXME: de-duplicate from config - base.Config = config - base.hostConfig = &runconfig.HostConfig{} - base.ImageID = imgID - base.NetworkSettings = &network.Settings{IsAnonymousEndpoint: noExplicitName} - base.Name = name - base.Driver = daemon.driver.String() - - return base, err -} - -// GetFullContainerName returns a constructed container name. I think -// it has to do with the fact that a container is a file on disk and -// this is sort of just creating a file name. -func GetFullContainerName(name string) (string, error) { - if name == "" { - return "", fmt.Errorf("Container name cannot be empty") - } - if name[0] != '/' { - name = "/" + name - } - return name, nil -} - -// GetByName returns a container given a name. -func (daemon *Daemon) GetByName(name string) (*Container, error) { - fullName, err := GetFullContainerName(name) - if err != nil { - return nil, err - } - entity := daemon.containerGraphDB.Get(fullName) - if entity == nil { - return nil, fmt.Errorf("Could not find entity for %s", name) - } - e := daemon.containers.Get(entity.ID()) - if e == nil { - return nil, fmt.Errorf("Could not find container for entity id %s", entity.ID()) - } - return e, nil -} - -// GetEventFilter returns a filters.Filter for a set of filters -func (daemon *Daemon) GetEventFilter(filter filters.Args) *events.Filter { - // incoming container filter can be name, id or partial id, convert to - // a full container id - for i, cn := range filter["container"] { - c, err := daemon.Get(cn) - if err != nil { - filter["container"][i] = "" - } else { - filter["container"][i] = c.ID - } - } - return events.NewFilter(filter, daemon.GetLabels) -} - -// SubscribeToEvents returns the currently record of events, a channel to stream new events from, and a function to cancel the stream of events. -func (daemon *Daemon) SubscribeToEvents() ([]*jsonmessage.JSONMessage, chan interface{}, func()) { - return daemon.EventsService.Subscribe() -} - -// GetLabels for a container or image id -func (daemon *Daemon) GetLabels(id string) map[string]string { - // TODO: TestCase - container := daemon.containers.Get(id) - if container != nil { - return container.Config.Labels - } - - img, err := daemon.repositories.LookupImage(id) - if err == nil { - return img.ContainerConfig.Labels - } - return nil -} - -// children returns all child containers of the container with the -// given name. The containers are returned as a map from the container -// name to a pointer to Container. -func (daemon *Daemon) children(name string) (map[string]*Container, error) { - name, err := GetFullContainerName(name) - if err != nil { - return nil, err - } - children := make(map[string]*Container) - - err = daemon.containerGraphDB.Walk(name, func(p string, e *graphdb.Entity) error { - c, err := daemon.Get(e.ID()) - if err != nil { - return err - } - children[p] = c - return nil - }, 0) - - if err != nil { - return nil, err - } - return children, nil -} - -// parents returns the names of the parent containers of the container -// with the given name. -func (daemon *Daemon) parents(name string) ([]string, error) { - name, err := GetFullContainerName(name) - if err != nil { - return nil, err - } - - return daemon.containerGraphDB.Parents(name) -} - -func (daemon *Daemon) registerLink(parent, child *Container, alias string) error { - fullName := filepath.Join(parent.Name, alias) - if !daemon.containerGraphDB.Exists(fullName) { - _, err := daemon.containerGraphDB.Set(fullName, child.ID) - return err - } - return nil -} - -// NewDaemon sets up everything for the daemon to be able to service -// requests from the webserver. -func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemon, err error) { - setDefaultMtu(config) - - // Ensure we have compatible configuration options - if err := checkConfigOptions(config); err != nil { - return nil, err - } - - // Do we have a disabled network? - config.DisableBridge = isBridgeNetworkDisabled(config) - - // Verify the platform is supported as a daemon - if !platformSupported { - return nil, errSystemNotSupported - } - - // Validate platform-specific requirements - if err := checkSystem(); err != nil { - return nil, err - } - - // set up SIGUSR1 handler on Unix-like systems, or a Win32 global event - // on Windows to dump Go routine stacks - setupDumpStackTrap() - - uidMaps, gidMaps, err := setupRemappedRoot(config) - if err != nil { - return nil, err - } - rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) - if err != nil { - return nil, err - } - - // get the canonical path to the Docker root directory - var realRoot string - if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) { - realRoot = config.Root - } else { - realRoot, err = fileutils.ReadSymlinkedDirectory(config.Root) - if err != nil { - return nil, fmt.Errorf("Unable to get the full path to root (%s): %s", config.Root, err) - } - } - - if err = setupDaemonRoot(config, realRoot, rootUID, rootGID); err != nil { - return nil, err - } - - // set up the tmpDir to use a canonical path - tmp, err := tempDir(config.Root, rootUID, rootGID) - if err != nil { - return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err) - } - realTmp, err := fileutils.ReadSymlinkedDirectory(tmp) - if err != nil { - return nil, fmt.Errorf("Unable to get the full path to the TempDir (%s): %s", tmp, err) - } - os.Setenv("TMPDIR", realTmp) - - // Set the default driver - graphdriver.DefaultDriver = config.GraphDriver - - // Load storage driver - driver, err := graphdriver.New(config.Root, config.GraphOptions, uidMaps, gidMaps) - if err != nil { - return nil, fmt.Errorf("error initializing graphdriver: %v", err) - } - logrus.Debugf("Using graph driver %s", driver) - - d := &Daemon{} - d.driver = driver - - // Ensure the graph driver is shutdown at a later point - defer func() { - if err != nil { - if err := d.Shutdown(); err != nil { - logrus.Error(err) - } - } - }() - - // Verify logging driver type - if config.LogConfig.Type != "none" { - if _, err := logger.GetLogDriver(config.LogConfig.Type); err != nil { - return nil, fmt.Errorf("error finding the logging driver: %v", err) - } - } - logrus.Debugf("Using default logging driver %s", config.LogConfig.Type) - - // Configure and validate the kernels security support - if err := configureKernelSecuritySupport(config, d.driver.String()); err != nil { - return nil, err - } - - daemonRepo := filepath.Join(config.Root, "containers") - - if err := idtools.MkdirAllAs(daemonRepo, 0700, rootUID, rootGID); err != nil && !os.IsExist(err) { - return nil, err - } - - // Migrate the container if it is aufs and aufs is enabled - if err := migrateIfDownlevel(d.driver, config.Root); err != nil { - return nil, err - } - - logrus.Debug("Creating images graph") - g, err := graph.NewGraph(filepath.Join(config.Root, "graph"), d.driver, uidMaps, gidMaps) - if err != nil { - return nil, err - } - - // Configure the volumes driver - volStore, err := configureVolumes(config, rootUID, rootGID) - if err != nil { - return nil, err - } - - trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath) - if err != nil { - return nil, err - } - - trustDir := filepath.Join(config.Root, "trust") - - if err := system.MkdirAll(trustDir, 0700); err != nil { - return nil, err - } - - eventsService := events.New() - logrus.Debug("Creating repository list") - tagCfg := &graph.TagStoreConfig{ - Graph: g, - Key: trustKey, - Registry: registryService, - Events: eventsService, - } - repositories, err := graph.NewTagStore(filepath.Join(config.Root, "repositories-"+d.driver.String()), tagCfg) - if err != nil { - return nil, fmt.Errorf("Couldn't create Tag store repositories-%s: %s", d.driver.String(), err) - } - - if restorer, ok := d.driver.(graphdriver.ImageRestorer); ok { - if _, err := restorer.RestoreCustomImages(repositories, g); err != nil { - return nil, fmt.Errorf("Couldn't restore custom images: %s", err) - } - } - - // Discovery is only enabled when the daemon is launched with an address to advertise. When - // initialized, the daemon is registered and we can store the discovery backend as its read-only - // DiscoveryWatcher version. - if config.ClusterStore != "" && config.ClusterAdvertise != "" { - advertise, err := discovery.ParseAdvertise(config.ClusterStore, config.ClusterAdvertise) - if err != nil { - return nil, fmt.Errorf("discovery advertise parsing failed (%v)", err) - } - config.ClusterAdvertise = advertise - d.discoveryWatcher, err = initDiscovery(config.ClusterStore, config.ClusterAdvertise, config.ClusterOpts) - if err != nil { - return nil, fmt.Errorf("discovery initialization failed (%v)", err) - } - } else if config.ClusterAdvertise != "" { - return nil, fmt.Errorf("invalid cluster configuration. --cluster-advertise must be accompanied by --cluster-store configuration") - } - - d.netController, err = d.initNetworkController(config) - if err != nil { - return nil, fmt.Errorf("Error initializing network controller: %v", err) - } - - graphdbPath := filepath.Join(config.Root, "linkgraph.db") - graph, err := graphdb.NewSqliteConn(graphdbPath) - if err != nil { - return nil, err - } - - d.containerGraphDB = graph - - var sysInitPath string - - sysInfo := sysinfo.New(false) - // Check if Devices cgroup is mounted, it is hard requirement for container security, - // on Linux/FreeBSD. - if runtime.GOOS != "windows" && !sysInfo.CgroupDevicesEnabled { - return nil, fmt.Errorf("Devices cgroup isn't mounted") - } - - ed, err := execdrivers.NewDriver(config.ExecOptions, config.ExecRoot, config.Root, sysInitPath, sysInfo) - if err != nil { - return nil, err - } - - d.ID = trustKey.PublicKey().KeyID() - d.repository = daemonRepo - d.containers = &contStore{s: make(map[string]*Container)} - d.execCommands = newExecStore() - d.graph = g - d.repositories = repositories - d.idIndex = truncindex.NewTruncIndex([]string{}) - d.configStore = config - d.sysInitPath = sysInitPath - d.execDriver = ed - d.statsCollector = d.newStatsCollector(1 * time.Second) - d.defaultLogConfig = config.LogConfig - d.RegistryService = registryService - d.EventsService = eventsService - d.volumes = volStore - d.root = config.Root - d.uidMaps = uidMaps - d.gidMaps = gidMaps - - if err := d.cleanupMounts(); err != nil { - return nil, err - } - - go d.execCommandGC() - - if err := d.restore(); err != nil { - return nil, err - } - - return d, nil -} - -func (daemon *Daemon) shutdownContainer(c *Container) error { - // TODO(windows): Handle docker restart with paused containers - if c.isPaused() { - // To terminate a process in freezer cgroup, we should send - // SIGTERM to this process then unfreeze it, and the process will - // force to terminate immediately. - logrus.Debugf("Found container %s is paused, sending SIGTERM before unpause it", c.ID) - sig, ok := signal.SignalMap["TERM"] - if !ok { - return fmt.Errorf("System doesn not support SIGTERM") - } - if err := daemon.kill(c, int(sig)); err != nil { - return fmt.Errorf("sending SIGTERM to container %s with error: %v", c.ID, err) - } - if err := daemon.containerUnpause(c); err != nil { - return fmt.Errorf("Failed to unpause container %s with error: %v", c.ID, err) - } - if _, err := c.WaitStop(10 * time.Second); err != nil { - logrus.Debugf("container %s failed to exit in 10 second of SIGTERM, sending SIGKILL to force", c.ID) - sig, ok := signal.SignalMap["KILL"] - if !ok { - return fmt.Errorf("System does not support SIGKILL") - } - if err := daemon.kill(c, int(sig)); err != nil { - logrus.Errorf("Failed to SIGKILL container %s", c.ID) - } - c.WaitStop(-1 * time.Second) - return err - } - } - // If container failed to exit in 10 seconds of SIGTERM, then using the force - if err := daemon.containerStop(c, 10); err != nil { - return fmt.Errorf("Stop container %s with error: %v", c.ID, err) - } - - c.WaitStop(-1 * time.Second) - return nil -} - -// Shutdown stops the daemon. -func (daemon *Daemon) Shutdown() error { - daemon.shutdown = true - if daemon.containers != nil { - group := sync.WaitGroup{} - logrus.Debug("starting clean shutdown of all containers...") - for _, container := range daemon.List() { - if !container.IsRunning() { - continue - } - logrus.Debugf("stopping %s", container.ID) - group.Add(1) - go func(c *Container) { - defer group.Done() - if err := daemon.shutdownContainer(c); err != nil { - logrus.Errorf("Stop container error: %v", err) - return - } - logrus.Debugf("container stopped %s", c.ID) - }(container) - } - group.Wait() - } - - // trigger libnetwork Stop only if it's initialized - if daemon.netController != nil { - daemon.netController.Stop() - } - - if daemon.containerGraphDB != nil { - if err := daemon.containerGraphDB.Close(); err != nil { - logrus.Errorf("Error during container graph.Close(): %v", err) - } - } - - if daemon.driver != nil { - if err := daemon.driver.Cleanup(); err != nil { - logrus.Errorf("Error during graph storage driver.Cleanup(): %v", err) - } - } - - if err := daemon.cleanupMounts(); err != nil { - return err - } - - return nil -} - -// Mount sets container.basefs -// (is it not set coming in? why is it unset?) -func (daemon *Daemon) Mount(container *Container) error { - dir, err := daemon.driver.Get(container.ID, container.getMountLabel()) - if err != nil { - return fmt.Errorf("Error getting container %s from driver %s: %s", container.ID, daemon.driver, err) - } - - if container.basefs != dir { - // The mount path reported by the graph driver should always be trusted on Windows, since the - // volume path for a given mounted layer may change over time. This should only be an error - // on non-Windows operating systems. - if container.basefs != "" && runtime.GOOS != "windows" { - daemon.driver.Put(container.ID) - return fmt.Errorf("Error: driver %s is returning inconsistent paths for container %s ('%s' then '%s')", - daemon.driver, container.ID, container.basefs, dir) - } - } - container.basefs = dir - return nil -} - -// Unmount unsets the container base filesystem -func (daemon *Daemon) Unmount(container *Container) error { - return daemon.driver.Put(container.ID) -} - -// Run uses the execution driver to run a given container -func (daemon *Daemon) Run(c *Container, pipes *execdriver.Pipes, startCallback execdriver.DriverCallback) (execdriver.ExitStatus, error) { - hooks := execdriver.Hooks{ - Start: startCallback, - } - hooks.PreStart = append(hooks.PreStart, func(processConfig *execdriver.ProcessConfig, pid int, chOOM <-chan struct{}) error { - return daemon.setNetworkNamespaceKey(c.ID, pid) - }) - return daemon.execDriver.Run(c.command, pipes, hooks) -} - -func (daemon *Daemon) kill(c *Container, sig int) error { - return daemon.execDriver.Kill(c.command, sig) -} - -func (daemon *Daemon) stats(c *Container) (*execdriver.ResourceStats, error) { - return daemon.execDriver.Stats(c.ID) -} - -func (daemon *Daemon) subscribeToContainerStats(c *Container) chan interface{} { - return daemon.statsCollector.collect(c) -} - -func (daemon *Daemon) unsubscribeToContainerStats(c *Container, ch chan interface{}) { - daemon.statsCollector.unsubscribe(c, ch) -} - -func (daemon *Daemon) changes(container *Container) ([]archive.Change, error) { - initID := fmt.Sprintf("%s-init", container.ID) - return daemon.driver.Changes(container.ID, initID) -} - -func (daemon *Daemon) diff(container *Container) (archive.Archive, error) { - initID := fmt.Sprintf("%s-init", container.ID) - return daemon.driver.Diff(container.ID, initID) -} - -func (daemon *Daemon) createRootfs(container *Container) error { - // Step 1: create the container directory. - // This doubles as a barrier to avoid race conditions. - rootUID, rootGID, err := idtools.GetRootUIDGID(daemon.uidMaps, daemon.gidMaps) - if err != nil { - return err - } - if err := idtools.MkdirAs(container.root, 0700, rootUID, rootGID); err != nil { - return err - } - initID := fmt.Sprintf("%s-init", container.ID) - if err := daemon.driver.Create(initID, container.ImageID); err != nil { - return err - } - initPath, err := daemon.driver.Get(initID, "") - if err != nil { - return err - } - - if err := setupInitLayer(initPath, rootUID, rootGID); err != nil { - if err := daemon.driver.Put(initID); err != nil { - logrus.Errorf("Failed to Put init layer: %v", err) - } - return err - } - - // We want to unmount init layer before we take snapshot of it - // for the actual container. - if err := daemon.driver.Put(initID); err != nil { - return err - } - - if err := daemon.driver.Create(container.ID, initID); err != nil { - return err - } - return nil -} - -// Graph returns *graph.Graph which can be using for layers graph operations. -func (daemon *Daemon) Graph() *graph.Graph { - return daemon.graph -} - -// TagImage creates a tag in the repository reponame, pointing to the image named -// imageName. If force is true, an existing tag with the same name may be -// overwritten. -func (daemon *Daemon) TagImage(repoName, tag, imageName string, force bool) error { - if err := daemon.repositories.Tag(repoName, tag, imageName, force); err != nil { - return err - } - daemon.EventsService.Log("tag", utils.ImageReference(repoName, tag), "") - return nil -} - -// PullImage initiates a pull operation. image is the repository name to pull, and -// tag may be either empty, or indicate a specific tag to pull. -func (daemon *Daemon) PullImage(image string, tag string, imagePullConfig *graph.ImagePullConfig) error { - return daemon.repositories.Pull(image, tag, imagePullConfig) -} - -// ImportImage imports an image, getting the archived layer data either from -// inConfig (if src is "-"), or from a URI specified in src. Progress output is -// written to outStream. Repository and tag names can optionally be given in -// the repo and tag arguments, respectively. -func (daemon *Daemon) ImportImage(src, repo, tag, msg string, inConfig io.ReadCloser, outStream io.Writer, containerConfig *runconfig.Config) error { - return daemon.repositories.Import(src, repo, tag, msg, inConfig, outStream, containerConfig) -} - -// ExportImage exports a list of images to the given output stream. The -// exported images are archived into a tar when written to the output -// stream. All images with the given tag and all versions containing -// the same tag are exported. names is the set of tags to export, and -// outStream is the writer which the images are written to. -func (daemon *Daemon) ExportImage(names []string, outStream io.Writer) error { - return daemon.repositories.ImageExport(names, outStream) -} - -// PushImage initiates a push operation on the repository named localName. -func (daemon *Daemon) PushImage(localName string, imagePushConfig *graph.ImagePushConfig) error { - return daemon.repositories.Push(localName, imagePushConfig) -} - -// LookupImage looks up an image by name and returns it as an ImageInspect -// structure. -func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) { - return daemon.repositories.Lookup(name) -} - -// LoadImage uploads a set of images into the repository. This is the -// complement of ImageExport. The input stream is an uncompressed tar -// ball containing images and metadata. -func (daemon *Daemon) LoadImage(inTar io.ReadCloser, outStream io.Writer) error { - return daemon.repositories.Load(inTar, outStream) -} - -// ListImages returns a filtered list of images. filterArgs is a JSON-encoded set -// of filter arguments which will be interpreted by pkg/parsers/filters. -// filter is a shell glob string applied to repository names. The argument -// named all controls whether all images in the graph are filtered, or just -// the heads. -func (daemon *Daemon) ListImages(filterArgs, filter string, all bool) ([]*types.Image, error) { - return daemon.repositories.Images(filterArgs, filter, all) -} - -// ImageHistory returns a slice of ImageHistory structures for the specified image -// name by walking the image lineage. -func (daemon *Daemon) ImageHistory(name string) ([]*types.ImageHistory, error) { - return daemon.repositories.History(name) -} - -// GetImage returns pointer to an Image struct corresponding to the given -// name. The name can include an optional tag; otherwise the default tag will -// be used. -func (daemon *Daemon) GetImage(name string) (*image.Image, error) { - return daemon.repositories.LookupImage(name) -} - -func (daemon *Daemon) config() *Config { - return daemon.configStore -} - -func (daemon *Daemon) systemInitPath() string { - return daemon.sysInitPath -} - -// GraphDriver returns the currently used driver for processing -// container layers. -func (daemon *Daemon) GraphDriver() graphdriver.Driver { - return daemon.driver -} - -// ExecutionDriver returns the currently used driver for creating and -// starting execs in a container. -func (daemon *Daemon) ExecutionDriver() execdriver.Driver { - return daemon.execDriver -} - -func (daemon *Daemon) containerGraph() *graphdb.Database { - return daemon.containerGraphDB -} - -// GetUIDGIDMaps returns the current daemon's user namespace settings -// for the full uid and gid maps which will be applied to containers -// started in this instance. -func (daemon *Daemon) GetUIDGIDMaps() ([]idtools.IDMap, []idtools.IDMap) { - return daemon.uidMaps, daemon.gidMaps -} - -// GetRemappedUIDGID returns the current daemon's uid and gid values -// if user namespaces are in use for this daemon instance. If not -// this function will return "real" root values of 0, 0. -func (daemon *Daemon) GetRemappedUIDGID() (int, int) { - uid, gid, _ := idtools.GetRootUIDGID(daemon.uidMaps, daemon.gidMaps) - return uid, gid -} - -// ImageGetCached returns the earliest created image that is a child -// of the image with imgID, that had the same config when it was -// created. nil is returned if a child cannot be found. An error is -// returned if the parent image cannot be found. -func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*image.Image, error) { - // for now just exit if imgID has no children. - // maybe parentRefs in graph could be used to store - // the Image obj children for faster lookup below but this can - // be quite memory hungry. - if !daemon.Graph().HasChildren(imgID) { - return nil, nil - } - - // Retrieve all images - images := daemon.Graph().Map() - - // Store the tree in a map of map (map[parentId][childId]) - imageMap := make(map[string]map[string]struct{}) - for _, img := range images { - if _, exists := imageMap[img.Parent]; !exists { - imageMap[img.Parent] = make(map[string]struct{}) - } - imageMap[img.Parent][img.ID] = struct{}{} - } - - // Loop on the children of the given image and check the config - var match *image.Image - for elem := range imageMap[imgID] { - img, ok := images[elem] - if !ok { - return nil, fmt.Errorf("unable to find image %q", elem) - } - if runconfig.Compare(&img.ContainerConfig, config) { - if match == nil || match.Created.Before(img.Created) { - match = img - } - } - } - return match, nil -} - -// tempDir returns the default directory to use for temporary files. -func tempDir(rootDir string, rootUID, rootGID int) (string, error) { - var tmpDir string - if tmpDir = os.Getenv("DOCKER_TMPDIR"); tmpDir == "" { - tmpDir = filepath.Join(rootDir, "tmp") - } - return tmpDir, idtools.MkdirAllAs(tmpDir, 0700, rootUID, rootGID) -} - -func (daemon *Daemon) setHostConfig(container *Container, hostConfig *runconfig.HostConfig) error { - container.Lock() - if err := parseSecurityOpt(container, hostConfig); err != nil { - container.Unlock() - return err - } - container.Unlock() - - // Do not lock while creating volumes since this could be calling out to external plugins - // Don't want to block other actions, like `docker ps` because we're waiting on an external plugin - if err := daemon.registerMountPoints(container, hostConfig); err != nil { - return err - } - - container.Lock() - defer container.Unlock() - // Register any links from the host config before starting the container - if err := daemon.registerLinks(container, hostConfig); err != nil { - return err - } - - container.hostConfig = hostConfig - container.toDisk() - return nil -} - -func setDefaultMtu(config *Config) { - // do nothing if the config does not have the default 0 value. - if config.Mtu != 0 { - return - } - config.Mtu = defaultNetworkMtu - if routeMtu, err := getDefaultRouteMtu(); err == nil { - config.Mtu = routeMtu - } -} - -var errNoDefaultRoute = errors.New("no default route was found") - -// verifyContainerSettings performs validation of the hostconfig and config -// structures. -func (daemon *Daemon) verifyContainerSettings(hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) { - - // First perform verification of settings common across all platforms. - if config != nil { - if config.WorkingDir != "" { - config.WorkingDir = filepath.FromSlash(config.WorkingDir) // Ensure in platform semantics - if !system.IsAbs(config.WorkingDir) { - return nil, fmt.Errorf("The working directory '%s' is invalid. It needs to be an absolute path.", config.WorkingDir) - } - } - - if len(config.StopSignal) > 0 { - _, err := signal.ParseSignal(config.StopSignal) - if err != nil { - return nil, err - } - } - } - - if hostConfig == nil { - return nil, nil - } - - for port := range hostConfig.PortBindings { - _, portStr := nat.SplitProtoPort(string(port)) - if _, err := nat.ParsePort(portStr); err != nil { - return nil, fmt.Errorf("Invalid port specification: %q", portStr) - } - for _, pb := range hostConfig.PortBindings[port] { - _, err := nat.NewPort(nat.SplitProtoPort(pb.HostPort)) - if err != nil { - return nil, fmt.Errorf("Invalid port specification: %q", pb.HostPort) - } - } - } - - // Now do platform-specific verification - return verifyPlatformContainerSettings(daemon, hostConfig, config) -} - -func configureVolumes(config *Config, rootUID, rootGID int) (*store.VolumeStore, error) { - volumesDriver, err := local.New(config.Root, rootUID, rootGID) - if err != nil { - return nil, err - } - - volumedrivers.Register(volumesDriver, volumesDriver.Name()) - s := store.New() - s.AddAll(volumesDriver.List()) - - return s, nil -} - -// AuthenticateToRegistry checks the validity of credentials in authConfig -func (daemon *Daemon) AuthenticateToRegistry(authConfig *cliconfig.AuthConfig) (string, error) { - return daemon.RegistryService.Auth(authConfig) -} - -// SearchRegistryForImages queries the registry for images matching -// term. authConfig is used to login. -func (daemon *Daemon) SearchRegistryForImages(term string, - authConfig *cliconfig.AuthConfig, - headers map[string][]string) (*registry.SearchResults, error) { - return daemon.RegistryService.Search(term, authConfig, headers) -} - -// IsShuttingDown tells whether the daemon is shutting down or not -func (daemon *Daemon) IsShuttingDown() bool { - return daemon.shutdown -} - -// GetContainerStats collects all the stats published by a container -func (daemon *Daemon) GetContainerStats(container *Container) (*execdriver.ResourceStats, error) { - stats, err := daemon.stats(container) - if err != nil { - return nil, err - } - - // Retrieve the nw statistics from libnetwork and inject them in the Stats - var nwStats []*libcontainer.NetworkInterface - if nwStats, err = daemon.getNetworkStats(container); err != nil { - return nil, err - } - stats.Interfaces = nwStats - - return stats, nil -} - -func (daemon *Daemon) getNetworkStats(c *Container) ([]*libcontainer.NetworkInterface, error) { - var list []*libcontainer.NetworkInterface - - sb, err := daemon.netController.SandboxByID(c.NetworkSettings.SandboxID) - if err != nil { - return list, err - } - - stats, err := sb.Statistics() - if err != nil { - return list, err - } - - // Convert libnetwork nw stats into libcontainer nw stats - for ifName, ifStats := range stats { - list = append(list, convertLnNetworkStats(ifName, ifStats)) - } - - return list, nil -} - -func convertLnNetworkStats(name string, stats *lntypes.InterfaceStatistics) *libcontainer.NetworkInterface { - n := &libcontainer.NetworkInterface{Name: name} - n.RxBytes = stats.RxBytes - n.RxPackets = stats.RxPackets - n.RxErrors = stats.RxErrors - n.RxDropped = stats.RxDropped - n.TxBytes = stats.TxBytes - n.TxPackets = stats.TxPackets - n.TxErrors = stats.TxErrors - n.TxDropped = stats.TxDropped - return n -} diff --git a/vendor/github.com/docker/docker/daemon/daemon_aufs.go b/vendor/github.com/docker/docker/daemon/daemon_aufs.go deleted file mode 100644 index 0848ea92..00000000 --- a/vendor/github.com/docker/docker/daemon/daemon_aufs.go +++ /dev/null @@ -1,21 +0,0 @@ -// +build !exclude_graphdriver_aufs,linux - -package daemon - -import ( - "github.com/Sirupsen/logrus" - "github.com/docker/docker/daemon/graphdriver" - "github.com/docker/docker/daemon/graphdriver/aufs" -) - -// Given the graphdriver ad, if it is aufs, then migrate it. -// If aufs driver is not built, this func is a noop. -func migrateIfAufs(driver graphdriver.Driver, root string) error { - if ad, ok := driver.(*aufs.Driver); ok { - logrus.Debugf("Migrating existing containers") - if err := ad.Migrate(root, setupInitLayer); err != nil { - return err - } - } - return nil -} diff --git a/vendor/github.com/docker/docker/daemon/daemon_btrfs.go b/vendor/github.com/docker/docker/daemon/daemon_btrfs.go deleted file mode 100644 index b15b37b9..00000000 --- a/vendor/github.com/docker/docker/daemon/daemon_btrfs.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !exclude_graphdriver_btrfs,linux - -package daemon - -import ( - // register the btrfs graphdriver - _ "github.com/docker/docker/daemon/graphdriver/btrfs" -) diff --git a/vendor/github.com/docker/docker/daemon/daemon_devicemapper.go b/vendor/github.com/docker/docker/daemon/daemon_devicemapper.go deleted file mode 100644 index b33b01a5..00000000 --- a/vendor/github.com/docker/docker/daemon/daemon_devicemapper.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !exclude_graphdriver_devicemapper,linux - -package daemon - -import ( - // register the devmapper graphdriver - _ "github.com/docker/docker/daemon/graphdriver/devmapper" -) diff --git a/vendor/github.com/docker/docker/daemon/daemon_experimental.go b/vendor/github.com/docker/docker/daemon/daemon_experimental.go deleted file mode 100644 index 58ef6e72..00000000 --- a/vendor/github.com/docker/docker/daemon/daemon_experimental.go +++ /dev/null @@ -1,107 +0,0 @@ -// +build experimental - -package daemon - -import ( - "fmt" - "os" - "path/filepath" - "runtime" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/pkg/directory" - "github.com/docker/docker/pkg/idtools" - "github.com/docker/docker/runconfig" -) - -func setupRemappedRoot(config *Config) ([]idtools.IDMap, []idtools.IDMap, error) { - if runtime.GOOS != "linux" && config.RemappedRoot != "" { - return nil, nil, fmt.Errorf("User namespaces are not supported on Linux") - } - - // if the daemon was started with remapped root option, parse - // the config option to the int uid,gid values - var ( - uidMaps, gidMaps []idtools.IDMap - ) - if config.RemappedRoot != "" { - username, groupname, err := parseRemappedRoot(config.RemappedRoot) - if err != nil { - return nil, nil, err - } - if username == "root" { - // Cannot setup user namespaces with a 1-to-1 mapping; "--root=0:0" is a no-op - // effectively - logrus.Warnf("User namespaces: root cannot be remapped with itself; user namespaces are OFF") - return uidMaps, gidMaps, nil - } - logrus.Infof("User namespaces: ID ranges will be mapped to subuid/subgid ranges of: %s:%s", username, groupname) - // update remapped root setting now that we have resolved them to actual names - config.RemappedRoot = fmt.Sprintf("%s:%s", username, groupname) - - uidMaps, gidMaps, err = idtools.CreateIDMappings(username, groupname) - if err != nil { - return nil, nil, fmt.Errorf("Can't create ID mappings: %v", err) - } - } - return uidMaps, gidMaps, nil -} - -func setupDaemonRoot(config *Config, rootDir string, rootUID, rootGID int) error { - // the main docker root needs to be accessible by all users, as user namespace support - // will create subdirectories owned by either a) the real system root (when no remapping - // is setup) or b) the remapped root host ID (when --root=uid:gid is used) - // for "first time" users of user namespaces, we need to migrate the current directory - // contents to the "0.0" (root == root "namespace" daemon root) - nsRoot := "0.0" - if _, err := os.Stat(rootDir); err == nil { - // root current exists; we need to check for a prior migration - if _, err := os.Stat(filepath.Join(rootDir, nsRoot)); err != nil && os.IsNotExist(err) { - // need to migrate current root to "0.0" subroot - // 1. create non-usernamespaced root as "0.0" - if err := os.Mkdir(filepath.Join(rootDir, nsRoot), 0700); err != nil { - return fmt.Errorf("Cannot create daemon root %q: %v", filepath.Join(rootDir, nsRoot), err) - } - // 2. move current root content to "0.0" new subroot - if err := directory.MoveToSubdir(rootDir, nsRoot); err != nil { - return fmt.Errorf("Cannot migrate current daemon root %q for user namespaces: %v", rootDir, err) - } - // 3. chmod outer root to 755 - if chmodErr := os.Chmod(rootDir, 0755); chmodErr != nil { - return chmodErr - } - } - } else if os.IsNotExist(err) { - // no root exists yet, create it 0755 with root:root ownership - if err := os.MkdirAll(rootDir, 0755); err != nil { - return err - } - // create the "0.0" subroot (so no future "migration" happens of the root) - if err := os.Mkdir(filepath.Join(rootDir, nsRoot), 0700); err != nil { - return err - } - } - - // for user namespaces we will create a subtree underneath the specified root - // with any/all specified remapped root uid/gid options on the daemon creating - // a new subdirectory with ownership set to the remapped uid/gid (so as to allow - // `chdir()` to work for containers namespaced to that uid/gid) - if config.RemappedRoot != "" { - nsRoot = fmt.Sprintf("%d.%d", rootUID, rootGID) - } - config.Root = filepath.Join(rootDir, nsRoot) - logrus.Debugf("Creating actual daemon root: %s", config.Root) - - // Create the root directory if it doesn't exists - if err := idtools.MkdirAllAs(config.Root, 0700, rootUID, rootGID); err != nil { - return fmt.Errorf("Cannot create daemon root: %s: %v", config.Root, err) - } - return nil -} - -func (daemon *Daemon) verifyExperimentalContainerSettings(hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) { - if hostConfig.Privileged && daemon.config().RemappedRoot != "" { - return nil, fmt.Errorf("Privileged mode is incompatible with user namespace mappings") - } - return nil, nil -} diff --git a/vendor/github.com/docker/docker/daemon/daemon_linux.go b/vendor/github.com/docker/docker/daemon/daemon_linux.go deleted file mode 100644 index cda0e82e..00000000 --- a/vendor/github.com/docker/docker/daemon/daemon_linux.go +++ /dev/null @@ -1,60 +0,0 @@ -package daemon - -import ( - "bufio" - "fmt" - "io" - "os" - "path/filepath" - "strings" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/pkg/mount" -) - -// cleanupMounts umounts shm/mqueue mounts for old containers -func (daemon *Daemon) cleanupMounts() error { - logrus.Debugf("Cleaning up old shm/mqueue mounts: start.") - f, err := os.Open("/proc/self/mountinfo") - if err != nil { - return err - } - defer f.Close() - - return daemon.cleanupMountsFromReader(f, mount.Unmount) -} - -func (daemon *Daemon) cleanupMountsFromReader(reader io.Reader, unmount func(target string) error) error { - if daemon.repository == "" { - return nil - } - sc := bufio.NewScanner(reader) - var errors []string - for sc.Scan() { - line := sc.Text() - fields := strings.Fields(line) - if strings.HasPrefix(fields[4], daemon.repository) { - logrus.Debugf("Mount base: %v, repository %s", fields[4], daemon.repository) - mnt := fields[4] - mountBase := filepath.Base(mnt) - if mountBase == "mqueue" || mountBase == "shm" { - logrus.Debugf("Unmounting %v", mnt) - if err := unmount(mnt); err != nil { - logrus.Error(err) - errors = append(errors, err.Error()) - } - } - } - } - - if err := sc.Err(); err != nil { - return err - } - - if len(errors) > 0 { - return fmt.Errorf("Error cleaningup mounts:\n%v", strings.Join(errors, "\n")) - } - - logrus.Debugf("Cleaning up old shm/mqueue mounts: done.") - return nil -} diff --git a/vendor/github.com/docker/docker/daemon/daemon_linux_test.go b/vendor/github.com/docker/docker/daemon/daemon_linux_test.go deleted file mode 100644 index 0439d0bc..00000000 --- a/vendor/github.com/docker/docker/daemon/daemon_linux_test.go +++ /dev/null @@ -1,74 +0,0 @@ -// +build linux - -package daemon - -import ( - "strings" - "testing" -) - -func TestCleanupMounts(t *testing.T) { - fixture := `230 138 0:60 / / rw,relatime - overlay overlay rw,lowerdir=/var/lib/docker/overlay/0ef9f93d5d365c1385b09d54bbee6afff3d92002c16f22eccb6e1549b2ff97d8/root,upperdir=/var/lib/docker/overlay/dfac036ce135a8914e292cb2f6fea114f7339983c186366aa26d0051e93162cb/upper,workdir=/var/lib/docker/overlay/dfac036ce135a8914e292cb2f6fea114f7339983c186366aa26d0051e93162cb/work -231 230 0:56 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw -232 230 0:57 / /dev rw,nosuid - tmpfs tmpfs rw,mode=755 -233 232 0:58 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=666 -234 232 0:59 / /dev/shm rw,nosuid,nodev,noexec,relatime - tmpfs shm rw,size=65536k -235 232 0:55 / /dev/mqueue rw,nosuid,nodev,noexec,relatime - mqueue mqueue rw -236 230 0:61 / /sys rw,nosuid,nodev,noexec,relatime - sysfs sysfs rw -237 236 0:62 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw -238 237 0:21 /system.slice/docker.service /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd -239 237 0:23 /docker/dfac036ce135a8914e292cb2f6fea114f7339983c186366aa26d0051e93162cb /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,perf_event -240 237 0:24 /docker/dfac036ce135a8914e292cb2f6fea114f7339983c186366aa26d0051e93162cb /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,cpuset,clone_children -241 237 0:25 /docker/dfac036ce135a8914e292cb2f6fea114f7339983c186366aa26d0051e93162cb /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,devices -242 237 0:26 /docker/dfac036ce135a8914e292cb2f6fea114f7339983c186366aa26d0051e93162cb /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,freezer -243 237 0:27 /docker/dfac036ce135a8914e292cb2f6fea114f7339983c186366aa26d0051e93162cb /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,cpu,cpuacct -244 237 0:28 /docker/dfac036ce135a8914e292cb2f6fea114f7339983c186366aa26d0051e93162cb /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,blkio -245 237 0:29 /docker/dfac036ce135a8914e292cb2f6fea114f7339983c186366aa26d0051e93162cb /sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,net_cls,net_prio -246 237 0:30 /docker/dfac036ce135a8914e292cb2f6fea114f7339983c186366aa26d0051e93162cb /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,hugetlb -247 237 0:31 /docker/dfac036ce135a8914e292cb2f6fea114f7339983c186366aa26d0051e93162cb /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,memory -248 230 253:1 /var/lib/docker/volumes/510cc41ac68c48bd4eac932e3e09711673876287abf1b185312cfbfe6261a111/_data /var/lib/docker rw,relatime - ext4 /dev/disk/by-uuid/ba70ea0c-1a8f-4ee4-9687-cb393730e2b5 rw,errors=remount-ro,data=ordered -250 230 253:1 /var/lib/docker/containers/dfac036ce135a8914e292cb2f6fea114f7339983c186366aa26d0051e93162cb/hostname /etc/hostname rw,relatime - ext4 /dev/disk/by-uuid/ba70ea0c-1a8f-4ee4-9687-cb393730e2b5 rw,errors=remount-ro,data=ordered -251 230 253:1 /var/lib/docker/containers/dfac036ce135a8914e292cb2f6fea114f7339983c186366aa26d0051e93162cb/hosts /etc/hosts rw,relatime - ext4 /dev/disk/by-uuid/ba70ea0c-1a8f-4ee4-9687-cb393730e2b5 rw,errors=remount-ro,data=ordered -252 232 0:13 /1 /dev/console rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=000 -139 236 0:11 / /sys/kernel/security rw,relatime - securityfs none rw -140 230 0:54 / /tmp rw,relatime - tmpfs none rw -145 230 0:3 / /run/docker/netns/default rw - nsfs nsfs rw -130 140 0:45 / /tmp/docker_recursive_mount_test312125472/tmpfs rw,relatime - tmpfs tmpfs rw -131 230 0:3 / /run/docker/netns/47903e2e6701 rw - nsfs nsfs rw -133 230 0:55 / /go/src/github.com/docker/docker/bundles/1.9.0-dev/test-integration-cli/d45526097/graph/containers/47903e2e67014246eba27607809d5f5c2437c3bf84c2986393448f84093cc40b/mqueue rw,nosuid,nodev,noexec,relatime - mqueue mqueue rw` - - d := &Daemon{ - repository: "/go/src/github.com/docker/docker/bundles/1.9.0-dev/test-integration-cli/d45526097/graph/containers/", - } - - expected := "/go/src/github.com/docker/docker/bundles/1.9.0-dev/test-integration-cli/d45526097/graph/containers/47903e2e67014246eba27607809d5f5c2437c3bf84c2986393448f84093cc40b/mqueue" - var unmounted bool - unmount := func(target string) error { - if target == expected { - unmounted = true - } - return nil - } - - d.cleanupMountsFromReader(strings.NewReader(fixture), unmount) - - if !unmounted { - t.Fatalf("Expected to unmount the mqueue") - } -} - -func TestNotCleanupMounts(t *testing.T) { - d := &Daemon{ - repository: "", - } - var unmounted bool - unmount := func(target string) error { - unmounted = true - return nil - } - mountInfo := `234 232 0:59 / /dev/shm rw,nosuid,nodev,noexec,relatime - tmpfs shm rw,size=65536k` - d.cleanupMountsFromReader(strings.NewReader(mountInfo), unmount) - if unmounted { - t.Fatalf("Expected not to clean up /dev/shm") - } -} diff --git a/vendor/github.com/docker/docker/daemon/daemon_no_aufs.go b/vendor/github.com/docker/docker/daemon/daemon_no_aufs.go deleted file mode 100644 index a74f7753..00000000 --- a/vendor/github.com/docker/docker/daemon/daemon_no_aufs.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build exclude_graphdriver_aufs,linux freebsd - -package daemon - -import ( - "github.com/docker/docker/daemon/graphdriver" -) - -func migrateIfAufs(driver graphdriver.Driver, root string) error { - return nil -} diff --git a/vendor/github.com/docker/docker/daemon/daemon_overlay.go b/vendor/github.com/docker/docker/daemon/daemon_overlay.go deleted file mode 100644 index 3c97db13..00000000 --- a/vendor/github.com/docker/docker/daemon/daemon_overlay.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !exclude_graphdriver_overlay,linux - -package daemon - -import ( - // register the overlay graphdriver - _ "github.com/docker/docker/daemon/graphdriver/overlay" -) diff --git a/vendor/github.com/docker/docker/daemon/daemon_stub.go b/vendor/github.com/docker/docker/daemon/daemon_stub.go deleted file mode 100644 index 8fbb0508..00000000 --- a/vendor/github.com/docker/docker/daemon/daemon_stub.go +++ /dev/null @@ -1,28 +0,0 @@ -// +build !experimental - -package daemon - -import ( - "os" - - "github.com/docker/docker/pkg/idtools" - "github.com/docker/docker/pkg/system" - "github.com/docker/docker/runconfig" -) - -func setupRemappedRoot(config *Config) ([]idtools.IDMap, []idtools.IDMap, error) { - return nil, nil, nil -} - -func setupDaemonRoot(config *Config, rootDir string, rootUID, rootGID int) error { - config.Root = rootDir - // Create the root directory if it doesn't exists - if err := system.MkdirAll(config.Root, 0700); err != nil && !os.IsExist(err) { - return err - } - return nil -} - -func (daemon *Daemon) verifyExperimentalContainerSettings(hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) { - return nil, nil -} diff --git a/vendor/github.com/docker/docker/daemon/daemon_test.go b/vendor/github.com/docker/docker/daemon/daemon_test.go deleted file mode 100644 index 6dcce346..00000000 --- a/vendor/github.com/docker/docker/daemon/daemon_test.go +++ /dev/null @@ -1,576 +0,0 @@ -package daemon - -import ( - "fmt" - "io/ioutil" - "os" - "path" - "path/filepath" - "testing" - - "github.com/docker/docker/pkg/graphdb" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/pkg/truncindex" - "github.com/docker/docker/runconfig" - "github.com/docker/docker/volume" - volumedrivers "github.com/docker/docker/volume/drivers" - "github.com/docker/docker/volume/local" - "github.com/docker/docker/volume/store" -) - -// -// https://github.com/docker/docker/issues/8069 -// - -func TestGet(t *testing.T) { - c1 := &Container{ - CommonContainer: CommonContainer{ - ID: "5a4ff6a163ad4533d22d69a2b8960bf7fafdcba06e72d2febdba229008b0bf57", - Name: "tender_bardeen", - }, - } - - c2 := &Container{ - CommonContainer: CommonContainer{ - ID: "3cdbd1aa394fd68559fd1441d6eff2ab7c1e6363582c82febfaa8045df3bd8de", - Name: "drunk_hawking", - }, - } - - c3 := &Container{ - CommonContainer: CommonContainer{ - ID: "3cdbd1aa394fd68559fd1441d6eff2abfafdcba06e72d2febdba229008b0bf57", - Name: "3cdbd1aa", - }, - } - - c4 := &Container{ - CommonContainer: CommonContainer{ - ID: "75fb0b800922abdbef2d27e60abcdfaf7fb0698b2a96d22d3354da361a6ff4a5", - Name: "5a4ff6a163ad4533d22d69a2b8960bf7fafdcba06e72d2febdba229008b0bf57", - }, - } - - c5 := &Container{ - CommonContainer: CommonContainer{ - ID: "d22d69a2b8960bf7fafdcba06e72d2febdba960bf7fafdcba06e72d2f9008b060b", - Name: "d22d69a2b896", - }, - } - - store := &contStore{ - s: map[string]*Container{ - c1.ID: c1, - c2.ID: c2, - c3.ID: c3, - c4.ID: c4, - c5.ID: c5, - }, - } - - index := truncindex.NewTruncIndex([]string{}) - index.Add(c1.ID) - index.Add(c2.ID) - index.Add(c3.ID) - index.Add(c4.ID) - index.Add(c5.ID) - - daemonTestDbPath := path.Join(os.TempDir(), "daemon_test.db") - graph, err := graphdb.NewSqliteConn(daemonTestDbPath) - if err != nil { - t.Fatalf("Failed to create daemon test sqlite database at %s", daemonTestDbPath) - } - graph.Set(c1.Name, c1.ID) - graph.Set(c2.Name, c2.ID) - graph.Set(c3.Name, c3.ID) - graph.Set(c4.Name, c4.ID) - graph.Set(c5.Name, c5.ID) - - daemon := &Daemon{ - containers: store, - idIndex: index, - containerGraphDB: graph, - } - - if container, _ := daemon.Get("3cdbd1aa394fd68559fd1441d6eff2ab7c1e6363582c82febfaa8045df3bd8de"); container != c2 { - t.Fatal("Should explicitly match full container IDs") - } - - if container, _ := daemon.Get("75fb0b8009"); container != c4 { - t.Fatal("Should match a partial ID") - } - - if container, _ := daemon.Get("drunk_hawking"); container != c2 { - t.Fatal("Should match a full name") - } - - // c3.Name is a partial match for both c3.ID and c2.ID - if c, _ := daemon.Get("3cdbd1aa"); c != c3 { - t.Fatal("Should match a full name even though it collides with another container's ID") - } - - if container, _ := daemon.Get("d22d69a2b896"); container != c5 { - t.Fatal("Should match a container where the provided prefix is an exact match to the it's name, and is also a prefix for it's ID") - } - - if _, err := daemon.Get("3cdbd1"); err == nil { - t.Fatal("Should return an error when provided a prefix that partially matches multiple container ID's") - } - - if _, err := daemon.Get("nothing"); err == nil { - t.Fatal("Should return an error when provided a prefix that is neither a name or a partial match to an ID") - } - - os.Remove(daemonTestDbPath) -} - -func TestLoadWithVolume(t *testing.T) { - tmp, err := ioutil.TempDir("", "docker-daemon-test-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - - containerID := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e" - containerPath := filepath.Join(tmp, containerID) - if err := os.MkdirAll(containerPath, 0755); err != nil { - t.Fatal(err) - } - - hostVolumeID := stringid.GenerateNonCryptoID() - vfsPath := filepath.Join(tmp, "vfs", "dir", hostVolumeID) - volumePath := filepath.Join(tmp, "volumes", hostVolumeID) - - if err := os.MkdirAll(vfsPath, 0755); err != nil { - t.Fatal(err) - } - if err := os.MkdirAll(volumePath, 0755); err != nil { - t.Fatal(err) - } - - content := filepath.Join(vfsPath, "helo") - if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil { - t.Fatal(err) - } - - config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0, -"Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"}, -"ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top", -"Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"", -"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true, -"StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null, -"NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95", -"NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1", -"LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","Ports":{}}, -"ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf", -"HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname", -"HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts", -"LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log", -"Name":"/ubuntu","Driver":"aufs","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0, -"UpdateDns":false,"Volumes":{"/vol1":"%s"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}` - - cfg := fmt.Sprintf(config, vfsPath) - if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(cfg), 0644); err != nil { - t.Fatal(err) - } - - hostConfig := `{"Binds":[],"ContainerIDFile":"","Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"", -"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsOptions":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null, -"Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0}, -"SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}` - if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil { - t.Fatal(err) - } - - daemon, err := initDaemonForVolumesTest(tmp) - if err != nil { - t.Fatal(err) - } - defer volumedrivers.Unregister(volume.DefaultDriverName) - - c, err := daemon.load(containerID) - if err != nil { - t.Fatal(err) - } - - err = daemon.verifyVolumesInfo(c) - if err != nil { - t.Fatal(err) - } - - if len(c.MountPoints) != 1 { - t.Fatalf("Expected 1 volume mounted, was 0\n") - } - - m := c.MountPoints["/vol1"] - if m.Name != hostVolumeID { - t.Fatalf("Expected mount name to be %s, was %s\n", hostVolumeID, m.Name) - } - - if m.Destination != "/vol1" { - t.Fatalf("Expected mount destination /vol1, was %s\n", m.Destination) - } - - if !m.RW { - t.Fatalf("Expected mount point to be RW but it was not\n") - } - - if m.Driver != volume.DefaultDriverName { - t.Fatalf("Expected mount driver local, was %s\n", m.Driver) - } - - newVolumeContent := filepath.Join(volumePath, local.VolumeDataPathName, "helo") - b, err := ioutil.ReadFile(newVolumeContent) - if err != nil { - t.Fatal(err) - } - if string(b) != "HELO" { - t.Fatalf("Expected HELO, was %s\n", string(b)) - } -} - -func TestLoadWithBindMount(t *testing.T) { - tmp, err := ioutil.TempDir("", "docker-daemon-test-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - - containerID := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e" - containerPath := filepath.Join(tmp, containerID) - if err = os.MkdirAll(containerPath, 0755); err != nil { - t.Fatal(err) - } - - config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0, -"Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"}, -"ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top", -"Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"", -"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true, -"StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null, -"NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95", -"NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1", -"LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","Ports":{}}, -"ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf", -"HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname", -"HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts", -"LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log", -"Name":"/ubuntu","Driver":"aufs","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0, -"UpdateDns":false,"Volumes":{"/vol1": "/vol1"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}` - - if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(config), 0644); err != nil { - t.Fatal(err) - } - - hostConfig := `{"Binds":["/vol1:/vol1"],"ContainerIDFile":"","Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"", -"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsOptions":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null, -"Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0}, -"SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}` - if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil { - t.Fatal(err) - } - - daemon, err := initDaemonForVolumesTest(tmp) - if err != nil { - t.Fatal(err) - } - defer volumedrivers.Unregister(volume.DefaultDriverName) - - c, err := daemon.load(containerID) - if err != nil { - t.Fatal(err) - } - - err = daemon.verifyVolumesInfo(c) - if err != nil { - t.Fatal(err) - } - - if len(c.MountPoints) != 1 { - t.Fatalf("Expected 1 volume mounted, was 0\n") - } - - m := c.MountPoints["/vol1"] - if m.Name != "" { - t.Fatalf("Expected empty mount name, was %s\n", m.Name) - } - - if m.Source != "/vol1" { - t.Fatalf("Expected mount source /vol1, was %s\n", m.Source) - } - - if m.Destination != "/vol1" { - t.Fatalf("Expected mount destination /vol1, was %s\n", m.Destination) - } - - if !m.RW { - t.Fatalf("Expected mount point to be RW but it was not\n") - } -} - -func TestLoadWithVolume17RC(t *testing.T) { - tmp, err := ioutil.TempDir("", "docker-daemon-test-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - - containerID := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e" - containerPath := filepath.Join(tmp, containerID) - if err := os.MkdirAll(containerPath, 0755); err != nil { - t.Fatal(err) - } - - hostVolumeID := "6a3c03fc4a4e588561a543cc3bdd50089e27bd11bbb0e551e19bf735e2514101" - volumePath := filepath.Join(tmp, "volumes", hostVolumeID) - - if err := os.MkdirAll(volumePath, 0755); err != nil { - t.Fatal(err) - } - - content := filepath.Join(volumePath, "helo") - if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil { - t.Fatal(err) - } - - config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0, -"Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"}, -"ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top", -"Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"", -"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true, -"StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null, -"NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95", -"NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1", -"LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","Ports":{}}, -"ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf", -"HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname", -"HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts", -"LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log", -"Name":"/ubuntu","Driver":"aufs","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0, -"UpdateDns":false,"MountPoints":{"/vol1":{"Name":"6a3c03fc4a4e588561a543cc3bdd50089e27bd11bbb0e551e19bf735e2514101","Destination":"/vol1","Driver":"local","RW":true,"Source":"","Relabel":""}},"AppliedVolumesFrom":null}` - - if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(config), 0644); err != nil { - t.Fatal(err) - } - - hostConfig := `{"Binds":[],"ContainerIDFile":"","Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"", -"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsOptions":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null, -"Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0}, -"SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}` - if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil { - t.Fatal(err) - } - - daemon, err := initDaemonForVolumesTest(tmp) - if err != nil { - t.Fatal(err) - } - defer volumedrivers.Unregister(volume.DefaultDriverName) - - c, err := daemon.load(containerID) - if err != nil { - t.Fatal(err) - } - - err = daemon.verifyVolumesInfo(c) - if err != nil { - t.Fatal(err) - } - - if len(c.MountPoints) != 1 { - t.Fatalf("Expected 1 volume mounted, was 0\n") - } - - m := c.MountPoints["/vol1"] - if m.Name != hostVolumeID { - t.Fatalf("Expected mount name to be %s, was %s\n", hostVolumeID, m.Name) - } - - if m.Destination != "/vol1" { - t.Fatalf("Expected mount destination /vol1, was %s\n", m.Destination) - } - - if !m.RW { - t.Fatalf("Expected mount point to be RW but it was not\n") - } - - if m.Driver != volume.DefaultDriverName { - t.Fatalf("Expected mount driver local, was %s\n", m.Driver) - } - - newVolumeContent := filepath.Join(volumePath, local.VolumeDataPathName, "helo") - b, err := ioutil.ReadFile(newVolumeContent) - if err != nil { - t.Fatal(err) - } - if string(b) != "HELO" { - t.Fatalf("Expected HELO, was %s\n", string(b)) - } -} - -func TestRemoveLocalVolumesFollowingSymlinks(t *testing.T) { - tmp, err := ioutil.TempDir("", "docker-daemon-test-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - - containerID := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e" - containerPath := filepath.Join(tmp, containerID) - if err := os.MkdirAll(containerPath, 0755); err != nil { - t.Fatal(err) - } - - hostVolumeID := stringid.GenerateNonCryptoID() - vfsPath := filepath.Join(tmp, "vfs", "dir", hostVolumeID) - volumePath := filepath.Join(tmp, "volumes", hostVolumeID) - - if err := os.MkdirAll(vfsPath, 0755); err != nil { - t.Fatal(err) - } - if err := os.MkdirAll(volumePath, 0755); err != nil { - t.Fatal(err) - } - - content := filepath.Join(vfsPath, "helo") - if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil { - t.Fatal(err) - } - - config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0, -"Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"}, -"ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top", -"Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"", -"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true, -"StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null, -"NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95", -"NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1", -"LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","Ports":{}}, -"ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf", -"HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname", -"HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts", -"LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log", -"Name":"/ubuntu","Driver":"aufs","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0, -"UpdateDns":false,"Volumes":{"/vol1":"%s"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}` - - cfg := fmt.Sprintf(config, vfsPath) - if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(cfg), 0644); err != nil { - t.Fatal(err) - } - - hostConfig := `{"Binds":[],"ContainerIDFile":"","Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"", -"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsOptions":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null, -"Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0}, -"SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}` - if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil { - t.Fatal(err) - } - - daemon, err := initDaemonForVolumesTest(tmp) - if err != nil { - t.Fatal(err) - } - defer volumedrivers.Unregister(volume.DefaultDriverName) - - c, err := daemon.load(containerID) - if err != nil { - t.Fatal(err) - } - - err = daemon.verifyVolumesInfo(c) - if err != nil { - t.Fatal(err) - } - - if len(c.MountPoints) != 1 { - t.Fatalf("Expected 1 volume mounted, was 0\n") - } - - m := c.MountPoints["/vol1"] - _, err = daemon.VolumeCreate(m.Name, m.Driver, nil) - if err != nil { - t.Fatal(err) - } - - if err := daemon.VolumeRm(m.Name); err != nil { - t.Fatal(err) - } - - fi, err := os.Stat(vfsPath) - if err == nil || !os.IsNotExist(err) { - t.Fatalf("Expected vfs path to not exist: %v - %v\n", fi, err) - } -} - -func initDaemonForVolumesTest(tmp string) (*Daemon, error) { - daemon := &Daemon{ - repository: tmp, - root: tmp, - volumes: store.New(), - } - - volumesDriver, err := local.New(tmp, 0, 0) - if err != nil { - return nil, err - } - volumedrivers.Register(volumesDriver, volumesDriver.Name()) - - return daemon, nil -} - -func TestParseSecurityOpt(t *testing.T) { - container := &Container{} - config := &runconfig.HostConfig{} - - // test apparmor - config.SecurityOpt = []string{"apparmor:test_profile"} - if err := parseSecurityOpt(container, config); err != nil { - t.Fatalf("Unexpected parseSecurityOpt error: %v", err) - } - if container.AppArmorProfile != "test_profile" { - t.Fatalf("Unexpected AppArmorProfile, expected: \"test_profile\", got %q", container.AppArmorProfile) - } - - // test valid label - config.SecurityOpt = []string{"label:user:USER"} - if err := parseSecurityOpt(container, config); err != nil { - t.Fatalf("Unexpected parseSecurityOpt error: %v", err) - } - - // test invalid label - config.SecurityOpt = []string{"label"} - if err := parseSecurityOpt(container, config); err == nil { - t.Fatal("Expected parseSecurityOpt error, got nil") - } - - // test invalid opt - config.SecurityOpt = []string{"test"} - if err := parseSecurityOpt(container, config); err == nil { - t.Fatal("Expected parseSecurityOpt error, got nil") - } -} - -func TestNetworkOptions(t *testing.T) { - daemon := &Daemon{} - dconfigCorrect := &Config{ - CommonConfig: CommonConfig{ - DefaultNetwork: "netPlugin:mynet:dev", - ClusterStore: "consul://localhost:8500", - ClusterAdvertise: "192.168.0.1:8000", - }, - } - - if _, err := daemon.networkOptions(dconfigCorrect); err != nil { - t.Fatalf("Expect networkOptions sucess, got error: %v", err) - } - - dconfigWrong := &Config{ - CommonConfig: CommonConfig{ - ClusterStore: "consul://localhost:8500://test://bbb", - }, - } - - if _, err := daemon.networkOptions(dconfigWrong); err == nil { - t.Fatalf("Expected networkOptions error, got nil") - } -} diff --git a/vendor/github.com/docker/docker/daemon/daemon_unix.go b/vendor/github.com/docker/docker/daemon/daemon_unix.go deleted file mode 100644 index cca5691a..00000000 --- a/vendor/github.com/docker/docker/daemon/daemon_unix.go +++ /dev/null @@ -1,640 +0,0 @@ -// +build linux freebsd - -package daemon - -import ( - "fmt" - "net" - "os" - "path/filepath" - "strconv" - "strings" - "syscall" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/daemon/graphdriver" - "github.com/docker/docker/dockerversion" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/pkg/fileutils" - "github.com/docker/docker/pkg/idtools" - "github.com/docker/docker/pkg/parsers" - "github.com/docker/docker/pkg/parsers/kernel" - "github.com/docker/docker/pkg/sysinfo" - "github.com/docker/docker/runconfig" - "github.com/docker/docker/utils" - "github.com/docker/docker/volume" - "github.com/docker/libnetwork" - nwconfig "github.com/docker/libnetwork/config" - "github.com/docker/libnetwork/drivers/bridge" - "github.com/docker/libnetwork/ipamutils" - "github.com/docker/libnetwork/netlabel" - "github.com/docker/libnetwork/options" - "github.com/docker/libnetwork/types" - "github.com/opencontainers/runc/libcontainer/label" - "github.com/vishvananda/netlink" -) - -const ( - // See https://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/tree/kernel/sched/sched.h?id=8cd9234c64c584432f6992fe944ca9e46ca8ea76#n269 - linuxMinCPUShares = 2 - linuxMaxCPUShares = 262144 - platformSupported = true -) - -func parseSecurityOpt(container *Container, config *runconfig.HostConfig) error { - var ( - labelOpts []string - err error - ) - - for _, opt := range config.SecurityOpt { - con := strings.SplitN(opt, ":", 2) - if len(con) == 1 { - return fmt.Errorf("Invalid --security-opt: %q", opt) - } - switch con[0] { - case "label": - labelOpts = append(labelOpts, con[1]) - case "apparmor": - container.AppArmorProfile = con[1] - default: - return fmt.Errorf("Invalid --security-opt: %q", opt) - } - } - - container.ProcessLabel, container.MountLabel, err = label.InitLabels(labelOpts) - return err -} - -func checkKernelVersion(k, major, minor int) bool { - if v, err := kernel.GetKernelVersion(); err != nil { - logrus.Warnf("%s", err) - } else { - if kernel.CompareKernelVersion(*v, kernel.VersionInfo{Kernel: k, Major: major, Minor: minor}) < 0 { - return false - } - } - return true -} - -func checkKernel() error { - // Check for unsupported kernel versions - // FIXME: it would be cleaner to not test for specific versions, but rather - // test for specific functionalities. - // Unfortunately we can't test for the feature "does not cause a kernel panic" - // without actually causing a kernel panic, so we need this workaround until - // the circumstances of pre-3.10 crashes are clearer. - // For details see https://github.com/docker/docker/issues/407 - if !checkKernelVersion(3, 10, 0) { - v, _ := kernel.GetKernelVersion() - if os.Getenv("DOCKER_NOWARN_KERNEL_VERSION") == "" { - logrus.Warnf("Your Linux kernel version %s can be unstable running docker. Please upgrade your kernel to 3.10.0.", v.String()) - } - } - return nil -} - -// adaptContainerSettings is called during container creation to modify any -// settings necessary in the HostConfig structure. -func (daemon *Daemon) adaptContainerSettings(hostConfig *runconfig.HostConfig, adjustCPUShares bool) { - if hostConfig == nil { - return - } - - if adjustCPUShares && hostConfig.CPUShares > 0 { - // Handle unsupported CPUShares - if hostConfig.CPUShares < linuxMinCPUShares { - logrus.Warnf("Changing requested CPUShares of %d to minimum allowed of %d", hostConfig.CPUShares, linuxMinCPUShares) - hostConfig.CPUShares = linuxMinCPUShares - } else if hostConfig.CPUShares > linuxMaxCPUShares { - logrus.Warnf("Changing requested CPUShares of %d to maximum allowed of %d", hostConfig.CPUShares, linuxMaxCPUShares) - hostConfig.CPUShares = linuxMaxCPUShares - } - } - if hostConfig.Memory > 0 && hostConfig.MemorySwap == 0 { - // By default, MemorySwap is set to twice the size of Memory. - hostConfig.MemorySwap = hostConfig.Memory * 2 - } -} - -// verifyPlatformContainerSettings performs platform-specific validation of the -// hostconfig and config structures. -func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) { - warnings := []string{} - sysInfo := sysinfo.New(true) - - warnings, err := daemon.verifyExperimentalContainerSettings(hostConfig, config) - if err != nil { - return warnings, err - } - - // memory subsystem checks and adjustments - if hostConfig.Memory != 0 && hostConfig.Memory < 4194304 { - return warnings, fmt.Errorf("Minimum memory limit allowed is 4MB") - } - if hostConfig.Memory > 0 && !sysInfo.MemoryLimit { - warnings = append(warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.") - logrus.Warnf("Your kernel does not support memory limit capabilities. Limitation discarded.") - hostConfig.Memory = 0 - hostConfig.MemorySwap = -1 - } - if hostConfig.Memory > 0 && hostConfig.MemorySwap != -1 && !sysInfo.SwapLimit { - warnings = append(warnings, "Your kernel does not support swap limit capabilities, memory limited without swap.") - logrus.Warnf("Your kernel does not support swap limit capabilities, memory limited without swap.") - hostConfig.MemorySwap = -1 - } - if hostConfig.Memory > 0 && hostConfig.MemorySwap > 0 && hostConfig.MemorySwap < hostConfig.Memory { - return warnings, fmt.Errorf("Minimum memoryswap limit should be larger than memory limit, see usage.") - } - if hostConfig.Memory == 0 && hostConfig.MemorySwap > 0 { - return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage.") - } - if hostConfig.MemorySwappiness != nil && *hostConfig.MemorySwappiness != -1 && !sysInfo.MemorySwappiness { - warnings = append(warnings, "Your kernel does not support memory swappiness capabilities, memory swappiness discarded.") - logrus.Warnf("Your kernel does not support memory swappiness capabilities, memory swappiness discarded.") - hostConfig.MemorySwappiness = nil - } - if hostConfig.MemorySwappiness != nil { - swappiness := *hostConfig.MemorySwappiness - if swappiness < -1 || swappiness > 100 { - return warnings, fmt.Errorf("Invalid value: %v, valid memory swappiness range is 0-100.", swappiness) - } - } - if hostConfig.MemoryReservation > 0 && !sysInfo.MemoryReservation { - warnings = append(warnings, "Your kernel does not support memory soft limit capabilities. Limitation discarded.") - logrus.Warnf("Your kernel does not support memory soft limit capabilities. Limitation discarded.") - hostConfig.MemoryReservation = 0 - } - if hostConfig.Memory > 0 && hostConfig.MemoryReservation > 0 && hostConfig.Memory < hostConfig.MemoryReservation { - return warnings, fmt.Errorf("Minimum memory limit should be larger than memory reservation limit, see usage.") - } - if hostConfig.KernelMemory > 0 && !sysInfo.KernelMemory { - warnings = append(warnings, "Your kernel does not support kernel memory limit capabilities. Limitation discarded.") - logrus.Warnf("Your kernel does not support kernel memory limit capabilities. Limitation discarded.") - hostConfig.KernelMemory = 0 - } - if hostConfig.KernelMemory > 0 && !checkKernelVersion(4, 0, 0) { - warnings = append(warnings, "You specified a kernel memory limit on a kernel older than 4.0. Kernel memory limits are experimental on older kernels, it won't work as expected and can cause your system to be unstable.") - logrus.Warnf("You specified a kernel memory limit on a kernel older than 4.0. Kernel memory limits are experimental on older kernels, it won't work as expected and can cause your system to be unstable.") - } - if hostConfig.CPUShares > 0 && !sysInfo.CPUShares { - warnings = append(warnings, "Your kernel does not support CPU shares. Shares discarded.") - logrus.Warnf("Your kernel does not support CPU shares. Shares discarded.") - hostConfig.CPUShares = 0 - } - if hostConfig.CPUPeriod > 0 && !sysInfo.CPUCfsPeriod { - warnings = append(warnings, "Your kernel does not support CPU cfs period. Period discarded.") - logrus.Warnf("Your kernel does not support CPU cfs period. Period discarded.") - hostConfig.CPUPeriod = 0 - } - if hostConfig.CPUQuota > 0 && !sysInfo.CPUCfsQuota { - warnings = append(warnings, "Your kernel does not support CPU cfs quota. Quota discarded.") - logrus.Warnf("Your kernel does not support CPU cfs quota. Quota discarded.") - hostConfig.CPUQuota = 0 - } - if (hostConfig.CpusetCpus != "" || hostConfig.CpusetMems != "") && !sysInfo.Cpuset { - warnings = append(warnings, "Your kernel does not support cpuset. Cpuset discarded.") - logrus.Warnf("Your kernel does not support cpuset. Cpuset discarded.") - hostConfig.CpusetCpus = "" - hostConfig.CpusetMems = "" - } - cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(hostConfig.CpusetCpus) - if err != nil { - return warnings, derr.ErrorCodeInvalidCpusetCpus.WithArgs(hostConfig.CpusetCpus) - } - if !cpusAvailable { - return warnings, derr.ErrorCodeNotAvailableCpusetCpus.WithArgs(hostConfig.CpusetCpus, sysInfo.Cpus) - } - memsAvailable, err := sysInfo.IsCpusetMemsAvailable(hostConfig.CpusetMems) - if err != nil { - return warnings, derr.ErrorCodeInvalidCpusetMems.WithArgs(hostConfig.CpusetMems) - } - if !memsAvailable { - return warnings, derr.ErrorCodeNotAvailableCpusetMems.WithArgs(hostConfig.CpusetMems, sysInfo.Mems) - } - if hostConfig.BlkioWeight > 0 && !sysInfo.BlkioWeight { - warnings = append(warnings, "Your kernel does not support Block I/O weight. Weight discarded.") - logrus.Warnf("Your kernel does not support Block I/O weight. Weight discarded.") - hostConfig.BlkioWeight = 0 - } - if hostConfig.BlkioWeight > 0 && (hostConfig.BlkioWeight < 10 || hostConfig.BlkioWeight > 1000) { - return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000.") - } - if hostConfig.OomKillDisable && !sysInfo.OomKillDisable { - hostConfig.OomKillDisable = false - return warnings, fmt.Errorf("Your kernel does not support oom kill disable.") - } - - if sysInfo.IPv4ForwardingDisabled { - warnings = append(warnings, "IPv4 forwarding is disabled. Networking will not work.") - logrus.Warnf("IPv4 forwarding is disabled. Networking will not work") - } - return warnings, nil -} - -// checkConfigOptions checks for mutually incompatible config options -func checkConfigOptions(config *Config) error { - // Check for mutually incompatible config options - if config.Bridge.Iface != "" && config.Bridge.IP != "" { - return fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one.") - } - if !config.Bridge.EnableIPTables && !config.Bridge.InterContainerCommunication { - return fmt.Errorf("You specified --iptables=false with --icc=false. ICC=false uses iptables to function. Please set --icc or --iptables to true.") - } - if !config.Bridge.EnableIPTables && config.Bridge.EnableIPMasq { - config.Bridge.EnableIPMasq = false - } - return nil -} - -// checkSystem validates platform-specific requirements -func checkSystem() error { - if os.Geteuid() != 0 { - return fmt.Errorf("The Docker daemon needs to be run as root") - } - return checkKernel() -} - -// configureKernelSecuritySupport configures and validate security support for the kernel -func configureKernelSecuritySupport(config *Config, driverName string) error { - if config.EnableSelinuxSupport { - if selinuxEnabled() { - // As Docker on either btrfs or overlayFS and SELinux are incompatible at present, error on both being enabled - if driverName == "btrfs" || driverName == "overlay" { - return fmt.Errorf("SELinux is not supported with the %s graph driver", driverName) - } - logrus.Debug("SELinux enabled successfully") - } else { - logrus.Warn("Docker could not enable SELinux on the host system") - } - } else { - selinuxSetDisabled() - } - return nil -} - -// MigrateIfDownlevel is a wrapper for AUFS migration for downlevel -func migrateIfDownlevel(driver graphdriver.Driver, root string) error { - return migrateIfAufs(driver, root) -} - -func configureSysInit(config *Config, rootUID, rootGID int) (string, error) { - localCopy := filepath.Join(config.Root, "init", fmt.Sprintf("dockerinit-%s", dockerversion.Version)) - sysInitPath := utils.DockerInitPath(localCopy) - if sysInitPath == "" { - return "", fmt.Errorf("Could not locate dockerinit: This usually means docker was built incorrectly. See https://docs.docker.com/project/set-up-dev-env/ for official build instructions.") - } - - if sysInitPath != localCopy { - // When we find a suitable dockerinit binary (even if it's our local binary), we copy it into config.Root at localCopy for future use (so that the original can go away without that being a problem, for example during a package upgrade). - if err := idtools.MkdirAs(filepath.Dir(localCopy), 0700, rootUID, rootGID); err != nil && !os.IsExist(err) { - return "", err - } - if _, err := fileutils.CopyFile(sysInitPath, localCopy); err != nil { - return "", err - } - if err := os.Chmod(localCopy, 0700); err != nil { - return "", err - } - sysInitPath = localCopy - } - return sysInitPath, nil -} - -func isBridgeNetworkDisabled(config *Config) bool { - return config.Bridge.Iface == disableNetworkBridge -} - -func (daemon *Daemon) networkOptions(dconfig *Config) ([]nwconfig.Option, error) { - options := []nwconfig.Option{} - if dconfig == nil { - return options, nil - } - - options = append(options, nwconfig.OptionDataDir(dconfig.Root)) - - if strings.TrimSpace(dconfig.DefaultNetwork) != "" { - dn := strings.Split(dconfig.DefaultNetwork, ":") - if len(dn) < 2 { - return nil, fmt.Errorf("default network daemon config must be of the form NETWORKDRIVER:NETWORKNAME") - } - options = append(options, nwconfig.OptionDefaultDriver(dn[0])) - options = append(options, nwconfig.OptionDefaultNetwork(strings.Join(dn[1:], ":"))) - } else { - dd := runconfig.DefaultDaemonNetworkMode() - dn := runconfig.DefaultDaemonNetworkMode().NetworkName() - options = append(options, nwconfig.OptionDefaultDriver(string(dd))) - options = append(options, nwconfig.OptionDefaultNetwork(dn)) - } - - if strings.TrimSpace(dconfig.ClusterStore) != "" { - kv := strings.Split(dconfig.ClusterStore, "://") - if len(kv) != 2 { - return nil, fmt.Errorf("kv store daemon config must be of the form KV-PROVIDER://KV-URL") - } - options = append(options, nwconfig.OptionKVProvider(kv[0])) - options = append(options, nwconfig.OptionKVProviderURL(kv[1])) - } - if len(dconfig.ClusterOpts) > 0 { - options = append(options, nwconfig.OptionKVOpts(dconfig.ClusterOpts)) - } - - if daemon.discoveryWatcher != nil { - options = append(options, nwconfig.OptionDiscoveryWatcher(daemon.discoveryWatcher)) - } - - if dconfig.ClusterAdvertise != "" { - options = append(options, nwconfig.OptionDiscoveryAddress(dconfig.ClusterAdvertise)) - } - - options = append(options, nwconfig.OptionLabels(dconfig.Labels)) - options = append(options, driverOptions(dconfig)...) - return options, nil -} - -func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkController, error) { - netOptions, err := daemon.networkOptions(config) - if err != nil { - return nil, err - } - - controller, err := libnetwork.New(netOptions...) - if err != nil { - return nil, fmt.Errorf("error obtaining controller instance: %v", err) - } - - // Initialize default network on "null" - if _, err := controller.NewNetwork("null", "none", libnetwork.NetworkOptionPersist(false)); err != nil { - return nil, fmt.Errorf("Error creating default \"null\" network: %v", err) - } - - // Initialize default network on "host" - if _, err := controller.NewNetwork("host", "host", libnetwork.NetworkOptionPersist(false)); err != nil { - return nil, fmt.Errorf("Error creating default \"host\" network: %v", err) - } - - if !config.DisableBridge { - // Initialize default driver "bridge" - if err := initBridgeDriver(controller, config); err != nil { - return nil, err - } - } - - return controller, nil -} - -func driverOptions(config *Config) []nwconfig.Option { - bridgeConfig := options.Generic{ - "EnableIPForwarding": config.Bridge.EnableIPForward, - "EnableIPTables": config.Bridge.EnableIPTables, - "EnableUserlandProxy": config.Bridge.EnableUserlandProxy} - bridgeOption := options.Generic{netlabel.GenericData: bridgeConfig} - - dOptions := []nwconfig.Option{} - dOptions = append(dOptions, nwconfig.OptionDriverConfig("bridge", bridgeOption)) - return dOptions -} - -func initBridgeDriver(controller libnetwork.NetworkController, config *Config) error { - if n, err := controller.NetworkByName("bridge"); err == nil { - if err = n.Delete(); err != nil { - return fmt.Errorf("could not delete the default bridge network: %v", err) - } - } - - bridgeName := bridge.DefaultBridgeName - if config.Bridge.Iface != "" { - bridgeName = config.Bridge.Iface - } - netOption := map[string]string{ - bridge.BridgeName: bridgeName, - bridge.DefaultBridge: strconv.FormatBool(true), - netlabel.DriverMTU: strconv.Itoa(config.Mtu), - bridge.EnableIPMasquerade: strconv.FormatBool(config.Bridge.EnableIPMasq), - bridge.EnableICC: strconv.FormatBool(config.Bridge.InterContainerCommunication), - } - - // --ip processing - if config.Bridge.DefaultIP != nil { - netOption[bridge.DefaultBindingIP] = config.Bridge.DefaultIP.String() - } - - ipamV4Conf := libnetwork.IpamConf{} - - ipamV4Conf.AuxAddresses = make(map[string]string) - - if nw, _, err := ipamutils.ElectInterfaceAddresses(bridgeName); err == nil { - ipamV4Conf.PreferredPool = nw.String() - hip, _ := types.GetHostPartIP(nw.IP, nw.Mask) - if hip.IsGlobalUnicast() { - ipamV4Conf.Gateway = nw.IP.String() - } - } - - if config.Bridge.IP != "" { - ipamV4Conf.PreferredPool = config.Bridge.IP - ip, _, err := net.ParseCIDR(config.Bridge.IP) - if err != nil { - return err - } - ipamV4Conf.Gateway = ip.String() - } else if bridgeName == bridge.DefaultBridgeName && ipamV4Conf.PreferredPool != "" { - logrus.Infof("Default bridge (%s) is assigned with an IP address %s. Daemon option --bip can be used to set a preferred IP address", bridgeName, ipamV4Conf.PreferredPool) - } - - if config.Bridge.FixedCIDR != "" { - _, fCIDR, err := net.ParseCIDR(config.Bridge.FixedCIDR) - if err != nil { - return err - } - - ipamV4Conf.SubPool = fCIDR.String() - } - - if config.Bridge.DefaultGatewayIPv4 != nil { - ipamV4Conf.AuxAddresses["DefaultGatewayIPv4"] = config.Bridge.DefaultGatewayIPv4.String() - } - - var ipamV6Conf *libnetwork.IpamConf - if config.Bridge.FixedCIDRv6 != "" { - _, fCIDRv6, err := net.ParseCIDR(config.Bridge.FixedCIDRv6) - if err != nil { - return err - } - if ipamV6Conf == nil { - ipamV6Conf = &libnetwork.IpamConf{} - } - ipamV6Conf.PreferredPool = fCIDRv6.String() - } - - if config.Bridge.DefaultGatewayIPv6 != nil { - if ipamV6Conf == nil { - ipamV6Conf = &libnetwork.IpamConf{} - } - ipamV6Conf.AuxAddresses["DefaultGatewayIPv6"] = config.Bridge.DefaultGatewayIPv6.String() - } - - v4Conf := []*libnetwork.IpamConf{&ipamV4Conf} - v6Conf := []*libnetwork.IpamConf{} - if ipamV6Conf != nil { - v6Conf = append(v6Conf, ipamV6Conf) - } - // Initialize default network on "bridge" with the same name - _, err := controller.NewNetwork("bridge", "bridge", - libnetwork.NetworkOptionGeneric(options.Generic{ - netlabel.GenericData: netOption, - netlabel.EnableIPv6: config.Bridge.EnableIPv6, - }), - libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf)) - if err != nil { - return fmt.Errorf("Error creating default \"bridge\" network: %v", err) - } - return nil -} - -// setupInitLayer populates a directory with mountpoints suitable -// for bind-mounting dockerinit into the container. The mountpoint is simply an -// empty file at /.dockerinit -// -// This extra layer is used by all containers as the top-most ro layer. It protects -// the container from unwanted side-effects on the rw layer. -func setupInitLayer(initLayer string, rootUID, rootGID int) error { - for pth, typ := range map[string]string{ - "/dev/pts": "dir", - "/dev/shm": "dir", - "/proc": "dir", - "/sys": "dir", - "/.dockerinit": "file", - "/.dockerenv": "file", - "/etc/resolv.conf": "file", - "/etc/hosts": "file", - "/etc/hostname": "file", - "/dev/console": "file", - "/etc/mtab": "/proc/mounts", - } { - parts := strings.Split(pth, "/") - prev := "/" - for _, p := range parts[1:] { - prev = filepath.Join(prev, p) - syscall.Unlink(filepath.Join(initLayer, prev)) - } - - if _, err := os.Stat(filepath.Join(initLayer, pth)); err != nil { - if os.IsNotExist(err) { - if err := idtools.MkdirAllAs(filepath.Join(initLayer, filepath.Dir(pth)), 0755, rootUID, rootGID); err != nil { - return err - } - switch typ { - case "dir": - if err := idtools.MkdirAllAs(filepath.Join(initLayer, pth), 0755, rootUID, rootGID); err != nil { - return err - } - case "file": - f, err := os.OpenFile(filepath.Join(initLayer, pth), os.O_CREATE, 0755) - if err != nil { - return err - } - f.Close() - f.Chown(rootUID, rootGID) - default: - if err := os.Symlink(typ, filepath.Join(initLayer, pth)); err != nil { - return err - } - } - } else { - return err - } - } - } - - // Layer is ready to use, if it wasn't before. - return nil -} - -// registerLinks writes the links to a file. -func (daemon *Daemon) registerLinks(container *Container, hostConfig *runconfig.HostConfig) error { - if hostConfig == nil || hostConfig.Links == nil { - return nil - } - - for _, l := range hostConfig.Links { - name, alias, err := parsers.ParseLink(l) - if err != nil { - return err - } - child, err := daemon.Get(name) - if err != nil { - //An error from daemon.Get() means this name could not be found - return fmt.Errorf("Could not get container for %s", name) - } - for child.hostConfig.NetworkMode.IsContainer() { - parts := strings.SplitN(string(child.hostConfig.NetworkMode), ":", 2) - child, err = daemon.Get(parts[1]) - if err != nil { - return fmt.Errorf("Could not get container for %s", parts[1]) - } - } - if child.hostConfig.NetworkMode.IsHost() { - return runconfig.ErrConflictHostNetworkAndLinks - } - if err := daemon.registerLink(container, child, alias); err != nil { - return err - } - } - - // After we load all the links into the daemon - // set them to nil on the hostconfig - hostConfig.Links = nil - if err := container.writeHostConfig(); err != nil { - return err - } - - return nil -} - -func (daemon *Daemon) newBaseContainer(id string) *Container { - return &Container{ - CommonContainer: CommonContainer{ - ID: id, - State: NewState(), - execCommands: newExecStore(), - root: daemon.containerRoot(id), - MountPoints: make(map[string]*volume.MountPoint), - }, - Volumes: make(map[string]string), - VolumesRW: make(map[string]bool), - } -} - -// conditionalMountOnStart is a platform specific helper function during the -// container start to call mount. -func (daemon *Daemon) conditionalMountOnStart(container *Container) error { - return daemon.Mount(container) -} - -// conditionalUnmountOnCleanup is a platform specific helper function called -// during the cleanup of a container to unmount. -func (daemon *Daemon) conditionalUnmountOnCleanup(container *Container) { - if err := daemon.Unmount(container); err != nil { - logrus.Errorf("%v: Failed to umount filesystem: %v", container.ID, err) - } -} - -// getDefaultRouteMtu returns the MTU for the default route's interface. -func getDefaultRouteMtu() (int, error) { - routes, err := netlink.RouteList(nil, 0) - if err != nil { - return 0, err - } - for _, r := range routes { - // a nil Dst means that this is the default route. - if r.Dst == nil { - i, err := net.InterfaceByIndex(r.LinkIndex) - if err != nil { - continue - } - return i.MTU, nil - } - } - return 0, errNoDefaultRoute -} diff --git a/vendor/github.com/docker/docker/daemon/daemon_unix_test.go b/vendor/github.com/docker/docker/daemon/daemon_unix_test.go deleted file mode 100644 index fc13e667..00000000 --- a/vendor/github.com/docker/docker/daemon/daemon_unix_test.go +++ /dev/null @@ -1,87 +0,0 @@ -// +build !windows - -package daemon - -import ( - "io/ioutil" - "os" - "testing" - - "github.com/docker/docker/runconfig" -) - -func TestAdjustCPUShares(t *testing.T) { - tmp, err := ioutil.TempDir("", "docker-daemon-unix-test-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - daemon := &Daemon{ - repository: tmp, - root: tmp, - } - - hostConfig := &runconfig.HostConfig{ - CPUShares: linuxMinCPUShares - 1, - } - daemon.adaptContainerSettings(hostConfig, true) - if hostConfig.CPUShares != linuxMinCPUShares { - t.Errorf("Expected CPUShares to be %d", linuxMinCPUShares) - } - - hostConfig.CPUShares = linuxMaxCPUShares + 1 - daemon.adaptContainerSettings(hostConfig, true) - if hostConfig.CPUShares != linuxMaxCPUShares { - t.Errorf("Expected CPUShares to be %d", linuxMaxCPUShares) - } - - hostConfig.CPUShares = 0 - daemon.adaptContainerSettings(hostConfig, true) - if hostConfig.CPUShares != 0 { - t.Error("Expected CPUShares to be unchanged") - } - - hostConfig.CPUShares = 1024 - daemon.adaptContainerSettings(hostConfig, true) - if hostConfig.CPUShares != 1024 { - t.Error("Expected CPUShares to be unchanged") - } -} - -func TestAdjustCPUSharesNoAdjustment(t *testing.T) { - tmp, err := ioutil.TempDir("", "docker-daemon-unix-test-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - daemon := &Daemon{ - repository: tmp, - root: tmp, - } - - hostConfig := &runconfig.HostConfig{ - CPUShares: linuxMinCPUShares - 1, - } - daemon.adaptContainerSettings(hostConfig, false) - if hostConfig.CPUShares != linuxMinCPUShares-1 { - t.Errorf("Expected CPUShares to be %d", linuxMinCPUShares-1) - } - - hostConfig.CPUShares = linuxMaxCPUShares + 1 - daemon.adaptContainerSettings(hostConfig, false) - if hostConfig.CPUShares != linuxMaxCPUShares+1 { - t.Errorf("Expected CPUShares to be %d", linuxMaxCPUShares+1) - } - - hostConfig.CPUShares = 0 - daemon.adaptContainerSettings(hostConfig, false) - if hostConfig.CPUShares != 0 { - t.Error("Expected CPUShares to be unchanged") - } - - hostConfig.CPUShares = 1024 - daemon.adaptContainerSettings(hostConfig, false) - if hostConfig.CPUShares != 1024 { - t.Error("Expected CPUShares to be unchanged") - } -} diff --git a/vendor/github.com/docker/docker/daemon/daemon_unsupported.go b/vendor/github.com/docker/docker/daemon/daemon_unsupported.go deleted file mode 100644 index 987528f4..00000000 --- a/vendor/github.com/docker/docker/daemon/daemon_unsupported.go +++ /dev/null @@ -1,5 +0,0 @@ -// +build !linux,!freebsd,!windows - -package daemon - -const platformSupported = false diff --git a/vendor/github.com/docker/docker/daemon/daemon_windows.go b/vendor/github.com/docker/docker/daemon/daemon_windows.go deleted file mode 100644 index 4050e288..00000000 --- a/vendor/github.com/docker/docker/daemon/daemon_windows.go +++ /dev/null @@ -1,173 +0,0 @@ -package daemon - -import ( - "fmt" - "os" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/daemon/graphdriver" - // register the windows graph driver - _ "github.com/docker/docker/daemon/graphdriver/windows" - "github.com/docker/docker/pkg/parsers" - "github.com/docker/docker/pkg/system" - "github.com/docker/docker/runconfig" - "github.com/docker/libnetwork" -) - -const ( - defaultVirtualSwitch = "Virtual Switch" - platformSupported = true - windowsMinCPUShares = 1 - windowsMaxCPUShares = 9 -) - -func parseSecurityOpt(container *Container, config *runconfig.HostConfig) error { - return nil -} - -func setupInitLayer(initLayer string, rootUID, rootGID int) error { - return nil -} - -func checkKernel() error { - return nil -} - -// adaptContainerSettings is called during container creation to modify any -// settings necessary in the HostConfig structure. -func (daemon *Daemon) adaptContainerSettings(hostConfig *runconfig.HostConfig, adjustCPUShares bool) { - if hostConfig == nil { - return - } - - if hostConfig.CPUShares < 0 { - logrus.Warnf("Changing requested CPUShares of %d to minimum allowed of %d", hostConfig.CPUShares, windowsMinCPUShares) - hostConfig.CPUShares = windowsMinCPUShares - } else if hostConfig.CPUShares > windowsMaxCPUShares { - logrus.Warnf("Changing requested CPUShares of %d to maximum allowed of %d", hostConfig.CPUShares, windowsMaxCPUShares) - hostConfig.CPUShares = windowsMaxCPUShares - } -} - -// verifyPlatformContainerSettings performs platform-specific validation of the -// hostconfig and config structures. -func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) { - return nil, nil -} - -// checkConfigOptions checks for mutually incompatible config options -func checkConfigOptions(config *Config) error { - return nil -} - -// checkSystem validates platform-specific requirements -func checkSystem() error { - // Validate the OS version. Note that docker.exe must be manifested for this - // call to return the correct version. - osv, err := system.GetOSVersion() - if err != nil { - return err - } - if osv.MajorVersion < 10 { - return fmt.Errorf("This version of Windows does not support the docker daemon") - } - return nil -} - -// configureKernelSecuritySupport configures and validate security support for the kernel -func configureKernelSecuritySupport(config *Config, driverName string) error { - return nil -} - -func migrateIfDownlevel(driver graphdriver.Driver, root string) error { - return nil -} - -func configureSysInit(config *Config, rootUID, rootGID int) (string, error) { - // TODO Windows. - return os.Getenv("TEMP"), nil -} - -func isBridgeNetworkDisabled(config *Config) bool { - return false -} - -func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkController, error) { - // Set the name of the virtual switch if not specified by -b on daemon start - if config.Bridge.VirtualSwitchName == "" { - config.Bridge.VirtualSwitchName = defaultVirtualSwitch - } - return nil, nil -} - -// registerLinks sets up links between containers and writes the -// configuration out for persistence. -func (daemon *Daemon) registerLinks(container *Container, hostConfig *runconfig.HostConfig) error { - // TODO Windows. Factored out for network modes. There may be more - // refactoring required here. - - if hostConfig == nil || hostConfig.Links == nil { - return nil - } - - for _, l := range hostConfig.Links { - name, alias, err := parsers.ParseLink(l) - if err != nil { - return err - } - child, err := daemon.Get(name) - if err != nil { - //An error from daemon.Get() means this name could not be found - return fmt.Errorf("Could not get container for %s", name) - } - if err := daemon.registerLink(container, child, alias); err != nil { - return err - } - } - - // After we load all the links into the daemon - // set them to nil on the hostconfig - hostConfig.Links = nil - if err := container.writeHostConfig(); err != nil { - return err - } - return nil -} - -func (daemon *Daemon) newBaseContainer(id string) *Container { - return &Container{ - CommonContainer: CommonContainer{ - ID: id, - State: NewState(), - execCommands: newExecStore(), - root: daemon.containerRoot(id), - }, - } -} - -func (daemon *Daemon) cleanupMounts() error { - return nil -} - -// conditionalMountOnStart is a platform specific helper function during the -// container start to call mount. -func (daemon *Daemon) conditionalMountOnStart(container *Container) error { - // We do not mount if a Hyper-V container - if !container.hostConfig.Isolation.IsHyperV() { - if err := daemon.Mount(container); err != nil { - return err - } - } - return nil -} - -// conditionalUnmountOnCleanup is a platform specific helper function called -// during the cleanup of a container to unmount. -func (daemon *Daemon) conditionalUnmountOnCleanup(container *Container) { - // We do not unmount if a Hyper-V container - if !container.hostConfig.Isolation.IsHyperV() { - if err := daemon.Unmount(container); err != nil { - logrus.Errorf("%v: Failed to umount filesystem: %v", container.ID, err) - } - } -} diff --git a/vendor/github.com/docker/docker/daemon/daemon_zfs.go b/vendor/github.com/docker/docker/daemon/daemon_zfs.go deleted file mode 100644 index e5b4dce9..00000000 --- a/vendor/github.com/docker/docker/daemon/daemon_zfs.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !exclude_graphdriver_zfs,linux !exclude_graphdriver_zfs,freebsd - -package daemon - -import ( - // register the zfs driver - _ "github.com/docker/docker/daemon/graphdriver/zfs" -) diff --git a/vendor/github.com/docker/docker/daemon/debugtrap_unix.go b/vendor/github.com/docker/docker/daemon/debugtrap_unix.go deleted file mode 100644 index c4a11b07..00000000 --- a/vendor/github.com/docker/docker/daemon/debugtrap_unix.go +++ /dev/null @@ -1,21 +0,0 @@ -// +build !windows - -package daemon - -import ( - "os" - "os/signal" - "syscall" - - psignal "github.com/docker/docker/pkg/signal" -) - -func setupDumpStackTrap() { - c := make(chan os.Signal, 1) - signal.Notify(c, syscall.SIGUSR1) - go func() { - for range c { - psignal.DumpStacks() - } - }() -} diff --git a/vendor/github.com/docker/docker/daemon/debugtrap_unsupported.go b/vendor/github.com/docker/docker/daemon/debugtrap_unsupported.go deleted file mode 100644 index fef1bd77..00000000 --- a/vendor/github.com/docker/docker/daemon/debugtrap_unsupported.go +++ /dev/null @@ -1,7 +0,0 @@ -// +build !linux,!darwin,!freebsd,!windows - -package daemon - -func setupDumpStackTrap() { - return -} diff --git a/vendor/github.com/docker/docker/daemon/debugtrap_windows.go b/vendor/github.com/docker/docker/daemon/debugtrap_windows.go deleted file mode 100644 index 4c47947b..00000000 --- a/vendor/github.com/docker/docker/daemon/debugtrap_windows.go +++ /dev/null @@ -1,30 +0,0 @@ -package daemon - -import ( - "fmt" - "os" - "syscall" - - "github.com/Sirupsen/logrus" - psignal "github.com/docker/docker/pkg/signal" - "github.com/docker/docker/pkg/system" -) - -func setupDumpStackTrap() { - // Windows does not support signals like *nix systems. So instead of - // trapping on SIGUSR1 to dump stacks, we wait on a Win32 event to be - // signalled. - go func() { - sa := syscall.SecurityAttributes{ - Length: 0, - } - ev := "Global\\docker-daemon-" + fmt.Sprint(os.Getpid()) - if h, _ := system.CreateEvent(&sa, false, false, ev); h != 0 { - logrus.Debugf("Stackdump - waiting signal at %s", ev) - for { - syscall.WaitForSingleObject(h, syscall.INFINITE) - psignal.DumpStacks() - } - } - }() -} diff --git a/vendor/github.com/docker/docker/daemon/delete.go b/vendor/github.com/docker/docker/daemon/delete.go deleted file mode 100644 index f62f71e9..00000000 --- a/vendor/github.com/docker/docker/daemon/delete.go +++ /dev/null @@ -1,162 +0,0 @@ -package daemon - -import ( - "fmt" - "os" - "path" - - "github.com/Sirupsen/logrus" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/volume/store" -) - -// ContainerRmConfig is a holder for passing in runtime config. -type ContainerRmConfig struct { - ForceRemove, RemoveVolume, RemoveLink bool -} - -// ContainerRm removes the container id from the filesystem. An error -// is returned if the container is not found, or if the remove -// fails. If the remove succeeds, the container name is released, and -// network links are removed. -func (daemon *Daemon) ContainerRm(name string, config *ContainerRmConfig) error { - container, err := daemon.Get(name) - if err != nil { - return err - } - - if config.RemoveLink { - name, err := GetFullContainerName(name) - if err != nil { - return err - } - parent, n := path.Split(name) - if parent == "/" { - return derr.ErrorCodeDefaultName - } - pe := daemon.containerGraph().Get(parent) - if pe == nil { - return derr.ErrorCodeNoParent.WithArgs(parent, name) - } - - if err := daemon.containerGraph().Delete(name); err != nil { - return err - } - - parentContainer, _ := daemon.Get(pe.ID()) - if parentContainer != nil { - if err := daemon.updateNetwork(parentContainer); err != nil { - logrus.Debugf("Could not update network to remove link %s: %v", n, err) - } - } - - return nil - } - - if err := daemon.rm(container, config.ForceRemove); err != nil { - // return derr.ErrorCodeCantDestroy.WithArgs(name, utils.GetErrorMessage(err)) - return err - } - - if err := daemon.removeMountPoints(container, config.RemoveVolume); err != nil { - logrus.Error(err) - } - - return nil -} - -// Destroy unregisters a container from the daemon and cleanly removes its contents from the filesystem. -func (daemon *Daemon) rm(container *Container, forceRemove bool) (err error) { - if container.IsRunning() { - if !forceRemove { - return derr.ErrorCodeRmRunning - } - if err := daemon.Kill(container); err != nil { - return derr.ErrorCodeRmFailed.WithArgs(err) - } - } - - // Container state RemovalInProgress should be used to avoid races. - if err = container.setRemovalInProgress(); err != nil { - if err == derr.ErrorCodeAlreadyRemoving { - // do not fail when the removal is in progress started by other request. - return nil - } - return derr.ErrorCodeRmState.WithArgs(err) - } - defer container.resetRemovalInProgress() - - // stop collection of stats for the container regardless - // if stats are currently getting collected. - daemon.statsCollector.stopCollection(container) - - if err = daemon.containerStop(container, 3); err != nil { - return err - } - - // Mark container dead. We don't want anybody to be restarting it. - container.setDead() - - // Save container state to disk. So that if error happens before - // container meta file got removed from disk, then a restart of - // docker should not make a dead container alive. - if err := container.toDiskLocking(); err != nil { - logrus.Errorf("Error saving dying container to disk: %v", err) - } - - // If force removal is required, delete container from various - // indexes even if removal failed. - defer func() { - if err != nil && forceRemove { - daemon.idIndex.Delete(container.ID) - daemon.containers.Delete(container.ID) - os.RemoveAll(container.root) - daemon.LogContainerEvent(container, "destroy") - } - }() - - if _, err := daemon.containerGraphDB.Purge(container.ID); err != nil { - logrus.Debugf("Unable to remove container from link graph: %s", err) - } - - if err = daemon.driver.Remove(container.ID); err != nil { - return derr.ErrorCodeRmDriverFS.WithArgs(daemon.driver, container.ID, err) - } - - initID := fmt.Sprintf("%s-init", container.ID) - if err := daemon.driver.Remove(initID); err != nil { - return derr.ErrorCodeRmInit.WithArgs(daemon.driver, initID, err) - } - - if err = os.RemoveAll(container.root); err != nil { - return derr.ErrorCodeRmFS.WithArgs(container.ID, err) - } - - if err = daemon.execDriver.Clean(container.ID); err != nil { - return derr.ErrorCodeRmExecDriver.WithArgs(container.ID, err) - } - - selinuxFreeLxcContexts(container.ProcessLabel) - daemon.idIndex.Delete(container.ID) - daemon.containers.Delete(container.ID) - - daemon.LogContainerEvent(container, "destroy") - return nil -} - -// VolumeRm removes the volume with the given name. -// If the volume is referenced by a container it is not removed -// This is called directly from the remote API -func (daemon *Daemon) VolumeRm(name string) error { - v, err := daemon.volumes.Get(name) - if err != nil { - return err - } - if err := daemon.volumes.Remove(v); err != nil { - if err == store.ErrVolumeInUse { - return derr.ErrorCodeRmVolumeInUse.WithArgs(err) - } - return derr.ErrorCodeRmVolume.WithArgs(name, err) - } - return nil -} diff --git a/vendor/github.com/docker/docker/daemon/delete_test.go b/vendor/github.com/docker/docker/daemon/delete_test.go deleted file mode 100644 index 9a82fce2..00000000 --- a/vendor/github.com/docker/docker/daemon/delete_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package daemon - -import ( - "io/ioutil" - "os" - "testing" - - "github.com/docker/docker/runconfig" -) - -func TestContainerDoubleDelete(t *testing.T) { - tmp, err := ioutil.TempDir("", "docker-daemon-unix-test-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - daemon := &Daemon{ - repository: tmp, - root: tmp, - } - - container := &Container{ - CommonContainer: CommonContainer{ - State: NewState(), - Config: &runconfig.Config{}, - }, - } - - // Mark the container as having a delete in progress - if err := container.setRemovalInProgress(); err != nil { - t.Fatal(err) - } - - // Try to remove the container when it's start is removalInProgress. - // It should ignore the container and not return an error. - if err := daemon.rm(container, true); err != nil { - t.Fatal(err) - } -} diff --git a/vendor/github.com/docker/docker/daemon/discovery.go b/vendor/github.com/docker/docker/daemon/discovery.go deleted file mode 100644 index 006eddec..00000000 --- a/vendor/github.com/docker/docker/daemon/discovery.go +++ /dev/null @@ -1,48 +0,0 @@ -package daemon - -import ( - "time" - - log "github.com/Sirupsen/logrus" - "github.com/docker/docker/pkg/discovery" - - // Register the libkv backends for discovery. - _ "github.com/docker/docker/pkg/discovery/kv" -) - -const ( - // defaultDiscoveryHeartbeat is the default value for discovery heartbeat interval. - defaultDiscoveryHeartbeat = 20 * time.Second - - // defaultDiscoveryTTL is the default TTL interface for discovery. - defaultDiscoveryTTL = 60 * time.Second -) - -// initDiscovery initialized the nodes discovery subsystem by connecting to the specified backend -// and start a registration loop to advertise the current node under the specified address. -func initDiscovery(backend, address string, clusterOpts map[string]string) (discovery.Backend, error) { - var ( - discoveryBackend discovery.Backend - err error - ) - if discoveryBackend, err = discovery.New(backend, defaultDiscoveryHeartbeat, defaultDiscoveryTTL, clusterOpts); err != nil { - return nil, err - } - - // We call Register() on the discovery backend in a loop for the whole lifetime of the daemon, - // but we never actually Watch() for nodes appearing and disappearing for the moment. - go registrationLoop(discoveryBackend, address) - return discoveryBackend, nil -} - -// registrationLoop registers the current node against the discovery backend using the specified -// address. The function never returns, as registration against the backend comes with a TTL and -// requires regular heartbeats. -func registrationLoop(discoveryBackend discovery.Backend, address string) { - for { - if err := discoveryBackend.Register(address); err != nil { - log.Errorf("Registering as %q in discovery failed: %v", address, err) - } - time.Sleep(defaultDiscoveryHeartbeat) - } -} diff --git a/vendor/github.com/docker/docker/daemon/errors.go b/vendor/github.com/docker/docker/daemon/errors.go deleted file mode 100644 index 45a48820..00000000 --- a/vendor/github.com/docker/docker/daemon/errors.go +++ /dev/null @@ -1,23 +0,0 @@ -package daemon - -import ( - "strings" - - derr "github.com/docker/docker/errors" - "github.com/docker/docker/graph/tags" - "github.com/docker/docker/pkg/parsers" -) - -func (d *Daemon) graphNotExistToErrcode(imageName string, err error) error { - if d.Graph().IsNotExist(err, imageName) { - if strings.Contains(imageName, "@") { - return derr.ErrorCodeNoSuchImageHash.WithArgs(imageName) - } - img, tag := parsers.ParseRepositoryTag(imageName) - if tag == "" { - tag = tags.DefaultTag - } - return derr.ErrorCodeNoSuchImageTag.WithArgs(img, tag) - } - return err -} diff --git a/vendor/github.com/docker/docker/daemon/events.go b/vendor/github.com/docker/docker/daemon/events.go deleted file mode 100644 index 85ac25c0..00000000 --- a/vendor/github.com/docker/docker/daemon/events.go +++ /dev/null @@ -1,10 +0,0 @@ -package daemon - -// LogContainerEvent generates an event related to a container. -func (daemon *Daemon) LogContainerEvent(container *Container, action string) { - daemon.EventsService.Log( - action, - container.ID, - container.Config.Image, - ) -} diff --git a/vendor/github.com/docker/docker/daemon/exec.go b/vendor/github.com/docker/docker/daemon/exec.go deleted file mode 100644 index 299aaf60..00000000 --- a/vendor/github.com/docker/docker/daemon/exec.go +++ /dev/null @@ -1,391 +0,0 @@ -package daemon - -import ( - "io" - "io/ioutil" - "strings" - "sync" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/daemon/execdriver" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/pkg/broadcaster" - "github.com/docker/docker/pkg/ioutils" - "github.com/docker/docker/pkg/pools" - "github.com/docker/docker/pkg/promise" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/pkg/stringutils" - "github.com/docker/docker/runconfig" -) - -// ExecConfig holds the configurations for execs. The Daemon keeps -// track of both running and finished execs so that they can be -// examined both during and after completion. -type ExecConfig struct { - sync.Mutex - ID string - Running bool - ExitCode int - ProcessConfig *execdriver.ProcessConfig - streamConfig - OpenStdin bool - OpenStderr bool - OpenStdout bool - Container *Container - canRemove bool - - // waitStart will be closed immediately after the exec is really started. - waitStart chan struct{} -} - -type execStore struct { - s map[string]*ExecConfig - sync.RWMutex -} - -func newExecStore() *execStore { - return &execStore{s: make(map[string]*ExecConfig, 0)} -} - -func (e *execStore) Add(id string, ExecConfig *ExecConfig) { - e.Lock() - e.s[id] = ExecConfig - e.Unlock() -} - -func (e *execStore) Get(id string) *ExecConfig { - e.RLock() - res := e.s[id] - e.RUnlock() - return res -} - -func (e *execStore) Delete(id string) { - e.Lock() - delete(e.s, id) - e.Unlock() -} - -func (e *execStore) List() []string { - var IDs []string - e.RLock() - for id := range e.s { - IDs = append(IDs, id) - } - e.RUnlock() - return IDs -} - -func (ExecConfig *ExecConfig) resize(h, w int) error { - select { - case <-ExecConfig.waitStart: - case <-time.After(time.Second): - return derr.ErrorCodeExecResize.WithArgs(ExecConfig.ID) - } - return ExecConfig.ProcessConfig.Terminal.Resize(h, w) -} - -func (d *Daemon) registerExecCommand(ExecConfig *ExecConfig) { - // Storing execs in container in order to kill them gracefully whenever the container is stopped or removed. - ExecConfig.Container.execCommands.Add(ExecConfig.ID, ExecConfig) - // Storing execs in daemon for easy access via remote API. - d.execCommands.Add(ExecConfig.ID, ExecConfig) -} - -// ExecExists looks up the exec instance and returns a bool if it exists or not. -// It will also return the error produced by `getExecConfig` -func (d *Daemon) ExecExists(name string) (bool, error) { - if _, err := d.getExecConfig(name); err != nil { - return false, err - } - return true, nil -} - -// getExecConfig looks up the exec instance by name. If the container associated -// with the exec instance is stopped or paused, it will return an error. -func (d *Daemon) getExecConfig(name string) (*ExecConfig, error) { - ec := d.execCommands.Get(name) - - // If the exec is found but its container is not in the daemon's list of - // containers then it must have been delete, in which case instead of - // saying the container isn't running, we should return a 404 so that - // the user sees the same error now that they will after the - // 5 minute clean-up loop is run which erases old/dead execs. - - if ec != nil && d.containers.Get(ec.Container.ID) != nil { - if !ec.Container.IsRunning() { - return nil, derr.ErrorCodeContainerNotRunning.WithArgs(ec.Container.ID, ec.Container.State.String()) - } - if ec.Container.isPaused() { - return nil, derr.ErrorCodeExecPaused.WithArgs(ec.Container.ID) - } - return ec, nil - } - - return nil, derr.ErrorCodeNoExecID.WithArgs(name) -} - -func (d *Daemon) unregisterExecCommand(ExecConfig *ExecConfig) { - ExecConfig.Container.execCommands.Delete(ExecConfig.ID) - d.execCommands.Delete(ExecConfig.ID) -} - -func (d *Daemon) getActiveContainer(name string) (*Container, error) { - container, err := d.Get(name) - if err != nil { - return nil, err - } - - if !container.IsRunning() { - return nil, derr.ErrorCodeNotRunning.WithArgs(name) - } - if container.isPaused() { - return nil, derr.ErrorCodeExecPaused.WithArgs(name) - } - return container, nil -} - -// ContainerExecCreate sets up an exec in a running container. -func (d *Daemon) ContainerExecCreate(config *runconfig.ExecConfig) (string, error) { - container, err := d.getActiveContainer(config.Container) - if err != nil { - return "", err - } - - cmd := stringutils.NewStrSlice(config.Cmd...) - entrypoint, args := d.getEntrypointAndArgs(stringutils.NewStrSlice(), cmd) - - user := config.User - if len(user) == 0 { - user = container.Config.User - } - - processConfig := &execdriver.ProcessConfig{ - Tty: config.Tty, - Entrypoint: entrypoint, - Arguments: args, - User: user, - Privileged: config.Privileged, - } - - ExecConfig := &ExecConfig{ - ID: stringid.GenerateNonCryptoID(), - OpenStdin: config.AttachStdin, - OpenStdout: config.AttachStdout, - OpenStderr: config.AttachStderr, - streamConfig: streamConfig{}, - ProcessConfig: processConfig, - Container: container, - Running: false, - waitStart: make(chan struct{}), - } - - d.registerExecCommand(ExecConfig) - - d.LogContainerEvent(container, "exec_create: "+ExecConfig.ProcessConfig.Entrypoint+" "+strings.Join(ExecConfig.ProcessConfig.Arguments, " ")) - - return ExecConfig.ID, nil -} - -// ContainerExecStart starts a previously set up exec instance. The -// std streams are set up. -func (d *Daemon) ContainerExecStart(name string, stdin io.ReadCloser, stdout io.Writer, stderr io.Writer) error { - var ( - cStdin io.ReadCloser - cStdout, cStderr io.Writer - ) - - ec, err := d.getExecConfig(name) - if err != nil { - return derr.ErrorCodeNoExecID.WithArgs(name) - } - - ec.Lock() - if ec.Running { - ec.Unlock() - return derr.ErrorCodeExecRunning.WithArgs(ec.ID) - } - ec.Running = true - ec.Unlock() - - logrus.Debugf("starting exec command %s in container %s", ec.ID, ec.Container.ID) - container := ec.Container - d.LogContainerEvent(container, "exec_start: "+ec.ProcessConfig.Entrypoint+" "+strings.Join(ec.ProcessConfig.Arguments, " ")) - - if ec.OpenStdin { - r, w := io.Pipe() - go func() { - defer w.Close() - defer logrus.Debugf("Closing buffered stdin pipe") - pools.Copy(w, stdin) - }() - cStdin = r - } - if ec.OpenStdout { - cStdout = stdout - } - if ec.OpenStderr { - cStderr = stderr - } - - ec.streamConfig.stderr = new(broadcaster.Unbuffered) - ec.streamConfig.stdout = new(broadcaster.Unbuffered) - // Attach to stdin - if ec.OpenStdin { - ec.streamConfig.stdin, ec.streamConfig.stdinPipe = io.Pipe() - } else { - ec.streamConfig.stdinPipe = ioutils.NopWriteCloser(ioutil.Discard) // Silently drop stdin - } - - attachErr := attach(&ec.streamConfig, ec.OpenStdin, true, ec.ProcessConfig.Tty, cStdin, cStdout, cStderr) - - execErr := make(chan error) - - // Note, the ExecConfig data will be removed when the container - // itself is deleted. This allows us to query it (for things like - // the exitStatus) even after the cmd is done running. - - go func() { - execErr <- d.containerExec(container, ec) - }() - - select { - case err := <-attachErr: - if err != nil { - return derr.ErrorCodeExecAttach.WithArgs(err) - } - return nil - case err := <-execErr: - if aErr := <-attachErr; aErr != nil && err == nil { - return derr.ErrorCodeExecAttach.WithArgs(aErr) - } - if err == nil { - return nil - } - - // Maybe the container stopped while we were trying to exec - if !container.IsRunning() { - return derr.ErrorCodeExecContainerStopped - } - return derr.ErrorCodeExecCantRun.WithArgs(ec.ID, container.ID, err) - } -} - -// Exec calls the underlying exec driver to run -func (d *Daemon) Exec(c *Container, ExecConfig *ExecConfig, pipes *execdriver.Pipes, startCallback execdriver.DriverCallback) (int, error) { - hooks := execdriver.Hooks{ - Start: startCallback, - } - exitStatus, err := d.execDriver.Exec(c.command, ExecConfig.ProcessConfig, pipes, hooks) - - // On err, make sure we don't leave ExitCode at zero - if err != nil && exitStatus == 0 { - exitStatus = 128 - } - - ExecConfig.ExitCode = exitStatus - ExecConfig.Running = false - - return exitStatus, err -} - -// execCommandGC runs a ticker to clean up the daemon references -// of exec configs that are no longer part of the container. -func (d *Daemon) execCommandGC() { - for range time.Tick(5 * time.Minute) { - var ( - cleaned int - liveExecCommands = d.containerExecIds() - ) - for id, config := range d.execCommands.s { - if config.canRemove { - cleaned++ - d.execCommands.Delete(id) - } else { - if _, exists := liveExecCommands[id]; !exists { - config.canRemove = true - } - } - } - if cleaned > 0 { - logrus.Debugf("clean %d unused exec commands", cleaned) - } - } -} - -// containerExecIds returns a list of all the current exec ids that are in use -// and running inside a container. -func (d *Daemon) containerExecIds() map[string]struct{} { - ids := map[string]struct{}{} - for _, c := range d.containers.List() { - for _, id := range c.execCommands.List() { - ids[id] = struct{}{} - } - } - return ids -} - -func (d *Daemon) containerExec(container *Container, ec *ExecConfig) error { - container.Lock() - defer container.Unlock() - - callback := func(processConfig *execdriver.ProcessConfig, pid int, chOOM <-chan struct{}) error { - if processConfig.Tty { - // The callback is called after the process Start() - // so we are in the parent process. In TTY mode, stdin/out/err is the PtySlave - // which we close here. - if c, ok := processConfig.Stdout.(io.Closer); ok { - c.Close() - } - } - close(ec.waitStart) - return nil - } - - // We use a callback here instead of a goroutine and an chan for - // synchronization purposes - cErr := promise.Go(func() error { return d.monitorExec(container, ec, callback) }) - - // Exec should not return until the process is actually running - select { - case <-ec.waitStart: - case err := <-cErr: - return err - } - - return nil -} - -func (d *Daemon) monitorExec(container *Container, ExecConfig *ExecConfig, callback execdriver.DriverCallback) error { - var ( - err error - exitCode int - ) - pipes := execdriver.NewPipes(ExecConfig.streamConfig.stdin, ExecConfig.streamConfig.stdout, ExecConfig.streamConfig.stderr, ExecConfig.OpenStdin) - exitCode, err = d.Exec(container, ExecConfig, pipes, callback) - if err != nil { - logrus.Errorf("Error running command in existing container %s: %s", container.ID, err) - } - logrus.Debugf("Exec task in container %s exited with code %d", container.ID, exitCode) - if ExecConfig.OpenStdin { - if err := ExecConfig.streamConfig.stdin.Close(); err != nil { - logrus.Errorf("Error closing stdin while running in %s: %s", container.ID, err) - } - } - if err := ExecConfig.streamConfig.stdout.Clean(); err != nil { - logrus.Errorf("Error closing stdout while running in %s: %s", container.ID, err) - } - if err := ExecConfig.streamConfig.stderr.Clean(); err != nil { - logrus.Errorf("Error closing stderr while running in %s: %s", container.ID, err) - } - if ExecConfig.ProcessConfig.Terminal != nil { - if err := ExecConfig.ProcessConfig.Terminal.Close(); err != nil { - logrus.Errorf("Error closing terminal while running in container %s: %s", container.ID, err) - } - } - // remove the exec command from the container's store only and not the - // daemon's store so that the exec command can be inspected. - container.execCommands.Delete(ExecConfig.ID) - return err -} diff --git a/vendor/github.com/docker/docker/daemon/export.go b/vendor/github.com/docker/docker/daemon/export.go deleted file mode 100644 index 0a246ed5..00000000 --- a/vendor/github.com/docker/docker/daemon/export.go +++ /dev/null @@ -1,54 +0,0 @@ -package daemon - -import ( - "io" - - derr "github.com/docker/docker/errors" - "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/ioutils" -) - -// ContainerExport writes the contents of the container to the given -// writer. An error is returned if the container cannot be found. -func (daemon *Daemon) ContainerExport(name string, out io.Writer) error { - container, err := daemon.Get(name) - if err != nil { - return err - } - - data, err := daemon.containerExport(container) - if err != nil { - return derr.ErrorCodeExportFailed.WithArgs(name, err) - } - defer data.Close() - - // Stream the entire contents of the container (basically a volatile snapshot) - if _, err := io.Copy(out, data); err != nil { - return derr.ErrorCodeExportFailed.WithArgs(name, err) - } - return nil -} - -func (daemon *Daemon) containerExport(container *Container) (archive.Archive, error) { - if err := daemon.Mount(container); err != nil { - return nil, err - } - - uidMaps, gidMaps := daemon.GetUIDGIDMaps() - archive, err := archive.TarWithOptions(container.basefs, &archive.TarOptions{ - Compression: archive.Uncompressed, - UIDMaps: uidMaps, - GIDMaps: gidMaps, - }) - if err != nil { - daemon.Unmount(container) - return nil, err - } - arch := ioutils.NewReadCloserWrapper(archive, func() error { - err := archive.Close() - daemon.Unmount(container) - return err - }) - daemon.LogContainerEvent(container, "export") - return arch, err -} diff --git a/vendor/github.com/docker/docker/daemon/history.go b/vendor/github.com/docker/docker/daemon/history.go deleted file mode 100644 index 3fc10da0..00000000 --- a/vendor/github.com/docker/docker/daemon/history.go +++ /dev/null @@ -1,32 +0,0 @@ -package daemon - -import ( - "sort" -) - -// History is a convenience type for storing a list of containers, -// ordered by creation date. -type History []*Container - -func (history *History) Len() int { - return len(*history) -} - -func (history *History) Less(i, j int) bool { - containers := *history - return containers[j].Created.Before(containers[i].Created) -} - -func (history *History) Swap(i, j int) { - containers := *history - containers[i], containers[j] = containers[j], containers[i] -} - -// Add the given container to history. -func (history *History) Add(container *Container) { - *history = append(*history, container) -} - -func (history *History) sort() { - sort.Sort(history) -} diff --git a/vendor/github.com/docker/docker/daemon/image_delete.go b/vendor/github.com/docker/docker/daemon/image_delete.go deleted file mode 100644 index ca8b82a1..00000000 --- a/vendor/github.com/docker/docker/daemon/image_delete.go +++ /dev/null @@ -1,346 +0,0 @@ -package daemon - -import ( - "fmt" - "strings" - - "github.com/docker/docker/api/types" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/graph/tags" - "github.com/docker/docker/image" - "github.com/docker/docker/pkg/parsers" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/utils" -) - -// ImageDelete deletes the image referenced by the given imageRef from this -// daemon. The given imageRef can be an image ID, ID prefix, or a repository -// reference (with an optional tag or digest, defaulting to the tag name -// "latest"). There is differing behavior depending on whether the given -// imageRef is a repository reference or not. -// -// If the given imageRef is a repository reference then that repository -// reference will be removed. However, if there exists any containers which -// were created using the same image reference then the repository reference -// cannot be removed unless either there are other repository references to the -// same image or force is true. Following removal of the repository reference, -// the referenced image itself will attempt to be deleted as described below -// but quietly, meaning any image delete conflicts will cause the image to not -// be deleted and the conflict will not be reported. -// -// There may be conflicts preventing deletion of an image and these conflicts -// are divided into two categories grouped by their severity: -// -// Hard Conflict: -// - a pull or build using the image. -// - any descendent image. -// - any running container using the image. -// -// Soft Conflict: -// - any stopped container using the image. -// - any repository tag or digest references to the image. -// -// The image cannot be removed if there are any hard conflicts and can be -// removed if there are soft conflicts only if force is true. -// -// If prune is true, ancestor images will each attempt to be deleted quietly, -// meaning any delete conflicts will cause the image to not be deleted and the -// conflict will not be reported. -// -// FIXME: remove ImageDelete's dependency on Daemon, then move to the graph -// package. This would require that we no longer need the daemon to determine -// whether images are being used by a stopped or running container. -func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.ImageDelete, error) { - records := []types.ImageDelete{} - - img, err := daemon.repositories.LookupImage(imageRef) - if err != nil { - return nil, daemon.graphNotExistToErrcode(imageRef, err) - } - - var removedRepositoryRef bool - if !isImageIDPrefix(img.ID, imageRef) { - // A repository reference was given and should be removed - // first. We can only remove this reference if either force is - // true, there are multiple repository references to this - // image, or there are no containers using the given reference. - if !(force || daemon.imageHasMultipleRepositoryReferences(img.ID)) { - if container := daemon.getContainerUsingImage(img.ID); container != nil { - // If we removed the repository reference then - // this image would remain "dangling" and since - // we really want to avoid that the client must - // explicitly force its removal. - return nil, derr.ErrorCodeImgDelUsed.WithArgs(imageRef, stringid.TruncateID(container.ID), stringid.TruncateID(img.ID)) - } - } - - parsedRef, err := daemon.removeImageRef(imageRef) - if err != nil { - return nil, err - } - - untaggedRecord := types.ImageDelete{Untagged: parsedRef} - - daemon.EventsService.Log("untag", img.ID, "") - records = append(records, untaggedRecord) - - // If has remaining references then untag finishes the remove - if daemon.repositories.HasReferences(img) { - return records, nil - } - - removedRepositoryRef = true - } else { - // If an ID reference was given AND there is exactly one - // repository reference to the image then we will want to - // remove that reference. - // FIXME: Is this the behavior we want? - repoRefs := daemon.repositories.ByID()[img.ID] - if len(repoRefs) == 1 { - parsedRef, err := daemon.removeImageRef(repoRefs[0]) - if err != nil { - return nil, err - } - - untaggedRecord := types.ImageDelete{Untagged: parsedRef} - - daemon.EventsService.Log("untag", img.ID, "") - records = append(records, untaggedRecord) - } - } - - return records, daemon.imageDeleteHelper(img, &records, force, prune, removedRepositoryRef) -} - -// isImageIDPrefix returns whether the given possiblePrefix is a prefix of the -// given imageID. -func isImageIDPrefix(imageID, possiblePrefix string) bool { - return strings.HasPrefix(imageID, possiblePrefix) -} - -// imageHasMultipleRepositoryReferences returns whether there are multiple -// repository references to the given imageID. -func (daemon *Daemon) imageHasMultipleRepositoryReferences(imageID string) bool { - return len(daemon.repositories.ByID()[imageID]) > 1 -} - -// getContainerUsingImage returns a container that was created using the given -// imageID. Returns nil if there is no such container. -func (daemon *Daemon) getContainerUsingImage(imageID string) *Container { - for _, container := range daemon.List() { - if container.ImageID == imageID { - return container - } - } - - return nil -} - -// removeImageRef attempts to parse and remove the given image reference from -// this daemon's store of repository tag/digest references. The given -// repositoryRef must not be an image ID but a repository name followed by an -// optional tag or digest reference. If tag or digest is omitted, the default -// tag is used. Returns the resolved image reference and an error. -func (daemon *Daemon) removeImageRef(repositoryRef string) (string, error) { - repository, ref := parsers.ParseRepositoryTag(repositoryRef) - if ref == "" { - ref = tags.DefaultTag - } - - // Ignore the boolean value returned, as far as we're concerned, this - // is an idempotent operation and it's okay if the reference didn't - // exist in the first place. - _, err := daemon.repositories.Delete(repository, ref) - - return utils.ImageReference(repository, ref), err -} - -// removeAllReferencesToImageID attempts to remove every reference to the given -// imgID from this daemon's store of repository tag/digest references. Returns -// on the first encountered error. Removed references are logged to this -// daemon's event service. An "Untagged" types.ImageDelete is added to the -// given list of records. -func (daemon *Daemon) removeAllReferencesToImageID(imgID string, records *[]types.ImageDelete) error { - imageRefs := daemon.repositories.ByID()[imgID] - - for _, imageRef := range imageRefs { - parsedRef, err := daemon.removeImageRef(imageRef) - if err != nil { - return err - } - - untaggedRecord := types.ImageDelete{Untagged: parsedRef} - - daemon.EventsService.Log("untag", imgID, "") - *records = append(*records, untaggedRecord) - } - - return nil -} - -// ImageDeleteConflict holds a soft or hard conflict and an associated error. -// Implements the error interface. -type imageDeleteConflict struct { - hard bool - imgID string - message string -} - -func (idc *imageDeleteConflict) Error() string { - var forceMsg string - if idc.hard { - forceMsg = "cannot be forced" - } else { - forceMsg = "must be forced" - } - - return fmt.Sprintf("conflict: unable to delete %s (%s) - %s", stringid.TruncateID(idc.imgID), forceMsg, idc.message) -} - -// imageDeleteHelper attempts to delete the given image from this daemon. If -// the image has any hard delete conflicts (child images or running containers -// using the image) then it cannot be deleted. If the image has any soft delete -// conflicts (any tags/digests referencing the image or any stopped container -// using the image) then it can only be deleted if force is true. If the delete -// succeeds and prune is true, the parent images are also deleted if they do -// not have any soft or hard delete conflicts themselves. Any deleted images -// and untagged references are appended to the given records. If any error or -// conflict is encountered, it will be returned immediately without deleting -// the image. If quiet is true, any encountered conflicts will be ignored and -// the function will return nil immediately without deleting the image. -func (daemon *Daemon) imageDeleteHelper(img *image.Image, records *[]types.ImageDelete, force, prune, quiet bool) error { - // First, determine if this image has any conflicts. Ignore soft conflicts - // if force is true. - if conflict := daemon.checkImageDeleteConflict(img, force); conflict != nil { - if quiet && !daemon.imageIsDangling(img) { - // Ignore conflicts UNLESS the image is "dangling" in - // which case we want the user to know. - return nil - } - - // There was a conflict and it's either a hard conflict OR we are not - // forcing deletion on soft conflicts. - return conflict - } - - // Delete all repository tag/digest references to this image. - if err := daemon.removeAllReferencesToImageID(img.ID, records); err != nil { - return err - } - - if err := daemon.Graph().Delete(img.ID); err != nil { - return err - } - - daemon.EventsService.Log("delete", img.ID, "") - *records = append(*records, types.ImageDelete{Deleted: img.ID}) - - if !prune || img.Parent == "" { - return nil - } - - // We need to prune the parent image. This means delete it if there are - // no tags/digests referencing it and there are no containers using it ( - // either running or stopped). - parentImg, err := daemon.Graph().Get(img.Parent) - if err != nil { - return derr.ErrorCodeImgNoParent.WithArgs(err) - } - - // Do not force prunings, but do so quietly (stopping on any encountered - // conflicts). - return daemon.imageDeleteHelper(parentImg, records, false, true, true) -} - -// checkImageDeleteConflict determines whether there are any conflicts -// preventing deletion of the given image from this daemon. A hard conflict is -// any image which has the given image as a parent or any running container -// using the image. A soft conflict is any tags/digest referencing the given -// image or any stopped container using the image. If ignoreSoftConflicts is -// true, this function will not check for soft conflict conditions. -func (daemon *Daemon) checkImageDeleteConflict(img *image.Image, ignoreSoftConflicts bool) *imageDeleteConflict { - // Check for hard conflicts first. - if conflict := daemon.checkImageDeleteHardConflict(img); conflict != nil { - return conflict - } - - // Then check for soft conflicts. - if ignoreSoftConflicts { - // Don't bother checking for soft conflicts. - return nil - } - - return daemon.checkImageDeleteSoftConflict(img) -} - -func (daemon *Daemon) checkImageDeleteHardConflict(img *image.Image) *imageDeleteConflict { - // Check if the image ID is being used by a pull or build. - if daemon.Graph().IsHeld(img.ID) { - return &imageDeleteConflict{ - hard: true, - imgID: img.ID, - message: "image is held by an ongoing pull or build", - } - } - - // Check if the image has any descendent images. - if daemon.Graph().HasChildren(img.ID) { - return &imageDeleteConflict{ - hard: true, - imgID: img.ID, - message: "image has dependent child images", - } - } - - // Check if any running container is using the image. - for _, container := range daemon.List() { - if !container.IsRunning() { - // Skip this until we check for soft conflicts later. - continue - } - - if container.ImageID == img.ID { - return &imageDeleteConflict{ - imgID: img.ID, - hard: true, - message: fmt.Sprintf("image is being used by running container %s", stringid.TruncateID(container.ID)), - } - } - } - - return nil -} - -func (daemon *Daemon) checkImageDeleteSoftConflict(img *image.Image) *imageDeleteConflict { - // Check if any repository tags/digest reference this image. - if daemon.repositories.HasReferences(img) { - return &imageDeleteConflict{ - imgID: img.ID, - message: "image is referenced in one or more repositories", - } - } - - // Check if any stopped containers reference this image. - for _, container := range daemon.List() { - if container.IsRunning() { - // Skip this as it was checked above in hard conflict conditions. - continue - } - - if container.ImageID == img.ID { - return &imageDeleteConflict{ - imgID: img.ID, - message: fmt.Sprintf("image is being used by stopped container %s", stringid.TruncateID(container.ID)), - } - } - } - - return nil -} - -// imageIsDangling returns whether the given image is "dangling" which means -// that there are no repository references to the given image and it has no -// child images. -func (daemon *Daemon) imageIsDangling(img *image.Image) bool { - return !(daemon.repositories.HasReferences(img) || daemon.Graph().HasChildren(img.ID)) -} diff --git a/vendor/github.com/docker/docker/daemon/info.go b/vendor/github.com/docker/docker/daemon/info.go deleted file mode 100644 index 2ef7b668..00000000 --- a/vendor/github.com/docker/docker/daemon/info.go +++ /dev/null @@ -1,124 +0,0 @@ -package daemon - -import ( - "os" - "runtime" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/api/types" - "github.com/docker/docker/dockerversion" - "github.com/docker/docker/pkg/fileutils" - "github.com/docker/docker/pkg/parsers/kernel" - "github.com/docker/docker/pkg/parsers/operatingsystem" - "github.com/docker/docker/pkg/sysinfo" - "github.com/docker/docker/pkg/system" - "github.com/docker/docker/registry" - "github.com/docker/docker/utils" -) - -// SystemInfo returns information about the host server the daemon is running on. -func (daemon *Daemon) SystemInfo() (*types.Info, error) { - images := daemon.Graph().Map() - var imgcount int - if images == nil { - imgcount = 0 - } else { - imgcount = len(images) - } - kernelVersion := "" - if kv, err := kernel.GetKernelVersion(); err == nil { - kernelVersion = kv.String() - } - - operatingSystem := "" - if s, err := operatingsystem.GetOperatingSystem(); err == nil { - operatingSystem = s - } - - // Don't do containerized check on Windows - if runtime.GOOS != "windows" { - if inContainer, err := operatingsystem.IsContainerized(); err != nil { - logrus.Errorf("Could not determine if daemon is containerized: %v", err) - operatingSystem += " (error determining if containerized)" - } else if inContainer { - operatingSystem += " (containerized)" - } - } - - meminfo, err := system.ReadMemInfo() - if err != nil { - logrus.Errorf("Could not read system memory info: %v", err) - } - - // if we still have the original dockerinit binary from before - // we copied it locally, let's return the path to that, since - // that's more intuitive (the copied path is trivial to derive - // by hand given VERSION) - initPath := utils.DockerInitPath("") - if initPath == "" { - // if that fails, we'll just return the path from the daemon - initPath = daemon.systemInitPath() - } - - sysInfo := sysinfo.New(true) - - v := &types.Info{ - ID: daemon.ID, - Containers: len(daemon.List()), - Images: imgcount, - Driver: daemon.GraphDriver().String(), - DriverStatus: daemon.GraphDriver().Status(), - IPv4Forwarding: !sysInfo.IPv4ForwardingDisabled, - BridgeNfIptables: !sysInfo.BridgeNfCallIptablesDisabled, - BridgeNfIP6tables: !sysInfo.BridgeNfCallIP6tablesDisabled, - Debug: os.Getenv("DEBUG") != "", - NFd: fileutils.GetTotalUsedFds(), - NGoroutines: runtime.NumGoroutine(), - SystemTime: time.Now().Format(time.RFC3339Nano), - ExecutionDriver: daemon.ExecutionDriver().Name(), - LoggingDriver: daemon.defaultLogConfig.Type, - NEventsListener: daemon.EventsService.SubscribersCount(), - KernelVersion: kernelVersion, - OperatingSystem: operatingSystem, - IndexServerAddress: registry.IndexServer, - RegistryConfig: daemon.RegistryService.Config, - InitSha1: dockerversion.InitSHA1, - InitPath: initPath, - NCPU: runtime.NumCPU(), - MemTotal: meminfo.MemTotal, - DockerRootDir: daemon.config().Root, - Labels: daemon.config().Labels, - ExperimentalBuild: utils.ExperimentalBuild(), - ServerVersion: dockerversion.Version, - ClusterStore: daemon.config().ClusterStore, - ClusterAdvertise: daemon.config().ClusterAdvertise, - } - - // TODO Windows. Refactor this more once sysinfo is refactored into - // platform specific code. On Windows, sysinfo.cgroupMemInfo and - // sysinfo.cgroupCpuInfo will be nil otherwise and cause a SIGSEGV if - // an attempt is made to access through them. - if runtime.GOOS != "windows" { - v.MemoryLimit = sysInfo.MemoryLimit - v.SwapLimit = sysInfo.SwapLimit - v.OomKillDisable = sysInfo.OomKillDisable - v.CPUCfsPeriod = sysInfo.CPUCfsPeriod - v.CPUCfsQuota = sysInfo.CPUCfsQuota - } - - if httpProxy := os.Getenv("http_proxy"); httpProxy != "" { - v.HTTPProxy = httpProxy - } - if httpsProxy := os.Getenv("https_proxy"); httpsProxy != "" { - v.HTTPSProxy = httpsProxy - } - if noProxy := os.Getenv("no_proxy"); noProxy != "" { - v.NoProxy = noProxy - } - if hostname, err := os.Hostname(); err == nil { - v.Name = hostname - } - - return v, nil -} diff --git a/vendor/github.com/docker/docker/daemon/inspect.go b/vendor/github.com/docker/docker/daemon/inspect.go deleted file mode 100644 index 3107b3bd..00000000 --- a/vendor/github.com/docker/docker/daemon/inspect.go +++ /dev/null @@ -1,215 +0,0 @@ -package daemon - -import ( - "fmt" - "time" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/versions/v1p20" - "github.com/docker/docker/daemon/network" -) - -// ContainerInspect returns low-level information about a -// container. Returns an error if the container cannot be found, or if -// there is an error getting the data. -func (daemon *Daemon) ContainerInspect(name string, size bool) (*types.ContainerJSON, error) { - container, err := daemon.Get(name) - if err != nil { - return nil, err - } - - container.Lock() - defer container.Unlock() - - base, err := daemon.getInspectData(container, size) - if err != nil { - return nil, err - } - - mountPoints := addMountPoints(container) - networkSettings := &types.NetworkSettings{ - NetworkSettingsBase: types.NetworkSettingsBase{ - Bridge: container.NetworkSettings.Bridge, - SandboxID: container.NetworkSettings.SandboxID, - HairpinMode: container.NetworkSettings.HairpinMode, - LinkLocalIPv6Address: container.NetworkSettings.LinkLocalIPv6Address, - LinkLocalIPv6PrefixLen: container.NetworkSettings.LinkLocalIPv6PrefixLen, - Ports: container.NetworkSettings.Ports, - SandboxKey: container.NetworkSettings.SandboxKey, - SecondaryIPAddresses: container.NetworkSettings.SecondaryIPAddresses, - SecondaryIPv6Addresses: container.NetworkSettings.SecondaryIPv6Addresses, - }, - DefaultNetworkSettings: daemon.getDefaultNetworkSettings(container.NetworkSettings.Networks), - Networks: container.NetworkSettings.Networks, - } - - return &types.ContainerJSON{ - ContainerJSONBase: base, - Mounts: mountPoints, - Config: container.Config, - NetworkSettings: networkSettings, - }, nil -} - -// ContainerInspect120 serializes the master version of a container into a json type. -func (daemon *Daemon) ContainerInspect120(name string) (*v1p20.ContainerJSON, error) { - container, err := daemon.Get(name) - if err != nil { - return nil, err - } - - container.Lock() - defer container.Unlock() - - base, err := daemon.getInspectData(container, false) - if err != nil { - return nil, err - } - - mountPoints := addMountPoints(container) - config := &v1p20.ContainerConfig{ - Config: container.Config, - MacAddress: container.Config.MacAddress, - NetworkDisabled: container.Config.NetworkDisabled, - ExposedPorts: container.Config.ExposedPorts, - VolumeDriver: container.hostConfig.VolumeDriver, - } - networkSettings := daemon.getBackwardsCompatibleNetworkSettings(container.NetworkSettings) - - return &v1p20.ContainerJSON{ - ContainerJSONBase: base, - Mounts: mountPoints, - Config: config, - NetworkSettings: networkSettings, - }, nil -} - -func (daemon *Daemon) getInspectData(container *Container, size bool) (*types.ContainerJSONBase, error) { - // make a copy to play with - hostConfig := *container.hostConfig - - if children, err := daemon.children(container.Name); err == nil { - for linkAlias, child := range children { - hostConfig.Links = append(hostConfig.Links, fmt.Sprintf("%s:%s", child.Name, linkAlias)) - } - } - // we need this trick to preserve empty log driver, so - // container will use daemon defaults even if daemon change them - if hostConfig.LogConfig.Type == "" { - hostConfig.LogConfig.Type = daemon.defaultLogConfig.Type - } - - if len(hostConfig.LogConfig.Config) == 0 { - hostConfig.LogConfig.Config = daemon.defaultLogConfig.Config - } - - containerState := &types.ContainerState{ - Status: container.State.StateString(), - Running: container.State.Running, - Paused: container.State.Paused, - Restarting: container.State.Restarting, - OOMKilled: container.State.OOMKilled, - Dead: container.State.Dead, - Pid: container.State.Pid, - ExitCode: container.State.ExitCode, - Error: container.State.Error, - StartedAt: container.State.StartedAt.Format(time.RFC3339Nano), - FinishedAt: container.State.FinishedAt.Format(time.RFC3339Nano), - } - - contJSONBase := &types.ContainerJSONBase{ - ID: container.ID, - Created: container.Created.Format(time.RFC3339Nano), - Path: container.Path, - Args: container.Args, - State: containerState, - Image: container.ImageID, - LogPath: container.LogPath, - Name: container.Name, - RestartCount: container.RestartCount, - Driver: container.Driver, - MountLabel: container.MountLabel, - ProcessLabel: container.ProcessLabel, - ExecIDs: container.getExecIDs(), - HostConfig: &hostConfig, - } - - var ( - sizeRw int64 - sizeRootFs int64 - ) - if size { - sizeRw, sizeRootFs = daemon.getSize(container) - contJSONBase.SizeRw = &sizeRw - contJSONBase.SizeRootFs = &sizeRootFs - } - - // Now set any platform-specific fields - contJSONBase = setPlatformSpecificContainerFields(container, contJSONBase) - - contJSONBase.GraphDriver.Name = container.Driver - graphDriverData, err := daemon.driver.GetMetadata(container.ID) - if err != nil { - return nil, err - } - contJSONBase.GraphDriver.Data = graphDriverData - - return contJSONBase, nil -} - -// ContainerExecInspect returns low-level information about the exec -// command. An error is returned if the exec cannot be found. -func (daemon *Daemon) ContainerExecInspect(id string) (*ExecConfig, error) { - eConfig, err := daemon.getExecConfig(id) - if err != nil { - return nil, err - } - return eConfig, nil -} - -// VolumeInspect looks up a volume by name. An error is returned if -// the volume cannot be found. -func (daemon *Daemon) VolumeInspect(name string) (*types.Volume, error) { - v, err := daemon.volumes.Get(name) - if err != nil { - return nil, err - } - return volumeToAPIType(v), nil -} - -func (daemon *Daemon) getBackwardsCompatibleNetworkSettings(settings *network.Settings) *v1p20.NetworkSettings { - result := &v1p20.NetworkSettings{ - NetworkSettingsBase: types.NetworkSettingsBase{ - Bridge: settings.Bridge, - SandboxID: settings.SandboxID, - HairpinMode: settings.HairpinMode, - LinkLocalIPv6Address: settings.LinkLocalIPv6Address, - LinkLocalIPv6PrefixLen: settings.LinkLocalIPv6PrefixLen, - Ports: settings.Ports, - SandboxKey: settings.SandboxKey, - SecondaryIPAddresses: settings.SecondaryIPAddresses, - SecondaryIPv6Addresses: settings.SecondaryIPv6Addresses, - }, - DefaultNetworkSettings: daemon.getDefaultNetworkSettings(settings.Networks), - } - - return result -} - -// getDefaultNetworkSettings creates the deprecated structure that holds the information -// about the bridge network for a container. -func (daemon *Daemon) getDefaultNetworkSettings(networks map[string]*network.EndpointSettings) types.DefaultNetworkSettings { - var settings types.DefaultNetworkSettings - - if defaultNetwork, ok := networks["bridge"]; ok { - settings.EndpointID = defaultNetwork.EndpointID - settings.Gateway = defaultNetwork.Gateway - settings.GlobalIPv6Address = defaultNetwork.GlobalIPv6Address - settings.GlobalIPv6PrefixLen = defaultNetwork.GlobalIPv6PrefixLen - settings.IPAddress = defaultNetwork.IPAddress - settings.IPPrefixLen = defaultNetwork.IPPrefixLen - settings.IPv6Gateway = defaultNetwork.IPv6Gateway - settings.MacAddress = defaultNetwork.MacAddress - } - return settings -} diff --git a/vendor/github.com/docker/docker/daemon/inspect_unix.go b/vendor/github.com/docker/docker/daemon/inspect_unix.go deleted file mode 100644 index d445660f..00000000 --- a/vendor/github.com/docker/docker/daemon/inspect_unix.go +++ /dev/null @@ -1,77 +0,0 @@ -// +build !windows - -package daemon - -import ( - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/versions/v1p19" -) - -// This sets platform-specific fields -func setPlatformSpecificContainerFields(container *Container, contJSONBase *types.ContainerJSONBase) *types.ContainerJSONBase { - contJSONBase.AppArmorProfile = container.AppArmorProfile - contJSONBase.ResolvConfPath = container.ResolvConfPath - contJSONBase.HostnamePath = container.HostnamePath - contJSONBase.HostsPath = container.HostsPath - - return contJSONBase -} - -// ContainerInspectPre120 gets containers for pre 1.20 APIs. -func (daemon *Daemon) ContainerInspectPre120(name string) (*v1p19.ContainerJSON, error) { - container, err := daemon.Get(name) - if err != nil { - return nil, err - } - - container.Lock() - defer container.Unlock() - - base, err := daemon.getInspectData(container, false) - if err != nil { - return nil, err - } - - volumes := make(map[string]string) - volumesRW := make(map[string]bool) - for _, m := range container.MountPoints { - volumes[m.Destination] = m.Path() - volumesRW[m.Destination] = m.RW - } - - config := &v1p19.ContainerConfig{ - Config: container.Config, - MacAddress: container.Config.MacAddress, - NetworkDisabled: container.Config.NetworkDisabled, - ExposedPorts: container.Config.ExposedPorts, - VolumeDriver: container.hostConfig.VolumeDriver, - Memory: container.hostConfig.Memory, - MemorySwap: container.hostConfig.MemorySwap, - CPUShares: container.hostConfig.CPUShares, - CPUSet: container.hostConfig.CpusetCpus, - } - networkSettings := daemon.getBackwardsCompatibleNetworkSettings(container.NetworkSettings) - - return &v1p19.ContainerJSON{ - ContainerJSONBase: base, - Volumes: volumes, - VolumesRW: volumesRW, - Config: config, - NetworkSettings: networkSettings, - }, nil -} - -func addMountPoints(container *Container) []types.MountPoint { - mountPoints := make([]types.MountPoint, 0, len(container.MountPoints)) - for _, m := range container.MountPoints { - mountPoints = append(mountPoints, types.MountPoint{ - Name: m.Name, - Source: m.Path(), - Destination: m.Destination, - Driver: m.Driver, - Mode: m.Mode, - RW: m.RW, - }) - } - return mountPoints -} diff --git a/vendor/github.com/docker/docker/daemon/inspect_windows.go b/vendor/github.com/docker/docker/daemon/inspect_windows.go deleted file mode 100644 index 26b38616..00000000 --- a/vendor/github.com/docker/docker/daemon/inspect_windows.go +++ /dev/null @@ -1,27 +0,0 @@ -package daemon - -import "github.com/docker/docker/api/types" - -// This sets platform-specific fields -func setPlatformSpecificContainerFields(container *Container, contJSONBase *types.ContainerJSONBase) *types.ContainerJSONBase { - return contJSONBase -} - -func addMountPoints(container *Container) []types.MountPoint { - mountPoints := make([]types.MountPoint, 0, len(container.MountPoints)) - for _, m := range container.MountPoints { - mountPoints = append(mountPoints, types.MountPoint{ - Name: m.Name, - Source: m.Path(), - Destination: m.Destination, - Driver: m.Driver, - RW: m.RW, - }) - } - return mountPoints -} - -// ContainerInspectPre120 get containers for pre 1.20 APIs. -func (daemon *Daemon) ContainerInspectPre120(name string) (*types.ContainerJSON, error) { - return daemon.ContainerInspect(name, false) -} diff --git a/vendor/github.com/docker/docker/daemon/kill.go b/vendor/github.com/docker/docker/daemon/kill.go deleted file mode 100644 index 8b94fa3a..00000000 --- a/vendor/github.com/docker/docker/daemon/kill.go +++ /dev/null @@ -1,122 +0,0 @@ -package daemon - -import ( - "fmt" - "runtime" - "syscall" - "time" - - "github.com/Sirupsen/logrus" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/pkg/signal" -) - -// ContainerKill send signal to the container -// If no signal is given (sig 0), then Kill with SIGKILL and wait -// for the container to exit. -// If a signal is given, then just send it to the container and return. -func (daemon *Daemon) ContainerKill(name string, sig uint64) error { - container, err := daemon.Get(name) - if err != nil { - return err - } - - if sig != 0 && !signal.ValidSignalForPlatform(syscall.Signal(sig)) { - return fmt.Errorf("The %s daemon does not support signal %d", runtime.GOOS, sig) - } - - // If no signal is passed, or SIGKILL, perform regular Kill (SIGKILL + wait()) - if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL { - if err := daemon.Kill(container); err != nil { - return err - } - } else { - // Otherwise, just send the requested signal - if err := daemon.killWithSignal(container, int(sig)); err != nil { - return err - } - } - return nil -} - -// killWithSignal sends the container the given signal. This wrapper for the -// host specific kill command prepares the container before attempting -// to send the signal. An error is returned if the container is paused -// or not running, or if there is a problem returned from the -// underlying kill command. -func (daemon *Daemon) killWithSignal(container *Container, sig int) error { - logrus.Debugf("Sending %d to %s", sig, container.ID) - container.Lock() - defer container.Unlock() - - // We could unpause the container for them rather than returning this error - if container.Paused { - return derr.ErrorCodeUnpauseContainer.WithArgs(container.ID) - } - - if !container.Running { - return derr.ErrorCodeNotRunning.WithArgs(container.ID) - } - - container.ExitOnNext() - - // if the container is currently restarting we do not need to send the signal - // to the process. Telling the monitor that it should exit on it's next event - // loop is enough - if container.Restarting { - return nil - } - - if err := daemon.kill(container, sig); err != nil { - return err - } - - daemon.LogContainerEvent(container, "kill") - return nil -} - -// Kill forcefully terminates a container. -func (daemon *Daemon) Kill(container *Container) error { - if !container.IsRunning() { - return derr.ErrorCodeNotRunning.WithArgs(container.ID) - } - - // 1. Send SIGKILL - if err := daemon.killPossiblyDeadProcess(container, int(syscall.SIGKILL)); err != nil { - // While normally we might "return err" here we're not going to - // because if we can't stop the container by this point then - // its probably because its already stopped. Meaning, between - // the time of the IsRunning() call above and now it stopped. - // Also, since the err return will be exec driver specific we can't - // look for any particular (common) error that would indicate - // that the process is already dead vs something else going wrong. - // So, instead we'll give it up to 2 more seconds to complete and if - // by that time the container is still running, then the error - // we got is probably valid and so we return it to the caller. - - if container.IsRunning() { - container.WaitStop(2 * time.Second) - if container.IsRunning() { - return err - } - } - } - - // 2. Wait for the process to die, in last resort, try to kill the process directly - if err := killProcessDirectly(container); err != nil { - return err - } - - container.WaitStop(-1 * time.Second) - return nil -} - -// killPossibleDeadProcess is a wrapper aroung killSig() suppressing "no such process" error. -func (daemon *Daemon) killPossiblyDeadProcess(container *Container, sig int) error { - err := daemon.killWithSignal(container, sig) - if err == syscall.ESRCH { - logrus.Debugf("Cannot kill process (pid=%d) with signal %d: no such process.", container.GetPID(), sig) - return nil - } - return err -} diff --git a/vendor/github.com/docker/docker/daemon/list.go b/vendor/github.com/docker/docker/daemon/list.go deleted file mode 100644 index b91e69a7..00000000 --- a/vendor/github.com/docker/docker/daemon/list.go +++ /dev/null @@ -1,426 +0,0 @@ -package daemon - -import ( - "errors" - "fmt" - "strconv" - "strings" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/api/types" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/graph" - "github.com/docker/docker/image" - "github.com/docker/docker/pkg/graphdb" - "github.com/docker/docker/pkg/nat" - "github.com/docker/docker/pkg/parsers/filters" -) - -// iterationAction represents possible outcomes happening during the container iteration. -type iterationAction int - -// containerReducer represents a reducer for a container. -// Returns the object to serialize by the api. -type containerReducer func(*Container, *listContext) (*types.Container, error) - -const ( - // includeContainer is the action to include a container in the reducer. - includeContainer iterationAction = iota - // excludeContainer is the action to exclude a container in the reducer. - excludeContainer - // stopIteration is the action to stop iterating over the list of containers. - stopIteration -) - -// errStopIteration makes the iterator to stop without returning an error. -var errStopIteration = errors.New("container list iteration stopped") - -// List returns an array of all containers registered in the daemon. -func (daemon *Daemon) List() []*Container { - return daemon.containers.List() -} - -// ContainersConfig is the filtering specified by the user to iterate over containers. -type ContainersConfig struct { - // if true show all containers, otherwise only running containers. - All bool - // show all containers created after this container id - Since string - // show all containers created before this container id - Before string - // number of containers to return at most - Limit int - // if true include the sizes of the containers - Size bool - // return only containers that match filters - Filters string -} - -// listContext is the daemon generated filtering to iterate over containers. -// This is created based on the user specification. -type listContext struct { - // idx is the container iteration index for this context - idx int - // ancestorFilter tells whether it should check ancestors or not - ancestorFilter bool - // names is a list of container names to filter with - names map[string][]string - // images is a list of images to filter with - images map[string]bool - // filters is a collection of arguments to filter with, specified by the user - filters filters.Args - // exitAllowed is a list of exit codes allowed to filter with - exitAllowed []int - // beforeContainer is a filter to ignore containers that appear before the one given - beforeContainer *Container - // sinceContainer is a filter to stop the filtering when the iterator arrive to the given container - sinceContainer *Container - // ContainersConfig is the filters set by the user - *ContainersConfig -} - -// Containers returns the list of containers to show given the user's filtering. -func (daemon *Daemon) Containers(config *ContainersConfig) ([]*types.Container, error) { - return daemon.reduceContainers(config, daemon.transformContainer) -} - -// reduceContainer parses the user filtering and generates the list of containers to return based on a reducer. -func (daemon *Daemon) reduceContainers(config *ContainersConfig, reducer containerReducer) ([]*types.Container, error) { - containers := []*types.Container{} - - ctx, err := daemon.foldFilter(config) - if err != nil { - return nil, err - } - - for _, container := range daemon.List() { - t, err := daemon.reducePsContainer(container, ctx, reducer) - if err != nil { - if err != errStopIteration { - return nil, err - } - break - } - if t != nil { - containers = append(containers, t) - ctx.idx++ - } - } - return containers, nil -} - -// reducePsContainer is the basic representation for a container as expected by the ps command. -func (daemon *Daemon) reducePsContainer(container *Container, ctx *listContext, reducer containerReducer) (*types.Container, error) { - container.Lock() - defer container.Unlock() - - // filter containers to return - action := includeContainerInList(container, ctx) - switch action { - case excludeContainer: - return nil, nil - case stopIteration: - return nil, errStopIteration - } - - // transform internal container struct into api structs - return reducer(container, ctx) -} - -// foldFilter generates the container filter based in the user's filtering options. -func (daemon *Daemon) foldFilter(config *ContainersConfig) (*listContext, error) { - psFilters, err := filters.FromParam(config.Filters) - if err != nil { - return nil, err - } - - var filtExited []int - if i, ok := psFilters["exited"]; ok { - for _, value := range i { - code, err := strconv.Atoi(value) - if err != nil { - return nil, err - } - filtExited = append(filtExited, code) - } - } - - if i, ok := psFilters["status"]; ok { - for _, value := range i { - if !isValidStateString(value) { - return nil, errors.New("Unrecognised filter value for status") - } - if value == "exited" || value == "created" { - config.All = true - } - } - } - - imagesFilter := map[string]bool{} - var ancestorFilter bool - if ancestors, ok := psFilters["ancestor"]; ok { - ancestorFilter = true - byParents := daemon.Graph().ByParent() - // The idea is to walk the graph down the most "efficient" way. - for _, ancestor := range ancestors { - // First, get the imageId of the ancestor filter (yay) - image, err := daemon.repositories.LookupImage(ancestor) - if err != nil { - logrus.Warnf("Error while looking up for image %v", ancestor) - continue - } - if imagesFilter[ancestor] { - // Already seen this ancestor, skip it - continue - } - // Then walk down the graph and put the imageIds in imagesFilter - populateImageFilterByParents(imagesFilter, image.ID, byParents) - } - } - - names := make(map[string][]string) - daemon.containerGraph().Walk("/", func(p string, e *graphdb.Entity) error { - names[e.ID()] = append(names[e.ID()], p) - return nil - }, 1) - - var beforeCont, sinceCont *Container - if config.Before != "" { - beforeCont, err = daemon.Get(config.Before) - if err != nil { - return nil, err - } - } - - if config.Since != "" { - sinceCont, err = daemon.Get(config.Since) - if err != nil { - return nil, err - } - } - - return &listContext{ - filters: psFilters, - ancestorFilter: ancestorFilter, - names: names, - images: imagesFilter, - exitAllowed: filtExited, - beforeContainer: beforeCont, - sinceContainer: sinceCont, - ContainersConfig: config, - }, nil -} - -// includeContainerInList decides whether a containers should be include in the output or not based in the filter. -// It also decides if the iteration should be stopped or not. -func includeContainerInList(container *Container, ctx *listContext) iterationAction { - // Do not include container if it's stopped and we're not filters - if !container.Running && !ctx.All && ctx.Limit <= 0 && ctx.beforeContainer == nil && ctx.sinceContainer == nil { - return excludeContainer - } - - // Do not include container if the name doesn't match - if !ctx.filters.Match("name", container.Name) { - return excludeContainer - } - - // Do not include container if the id doesn't match - if !ctx.filters.Match("id", container.ID) { - return excludeContainer - } - - // Do not include container if any of the labels don't match - if !ctx.filters.MatchKVList("label", container.Config.Labels) { - return excludeContainer - } - - // Do not include container if the isolation mode doesn't match - if excludeContainer == excludeByIsolation(container, ctx) { - return excludeContainer - } - - // Do not include container if it's in the list before the filter container. - // Set the filter container to nil to include the rest of containers after this one. - if ctx.beforeContainer != nil { - if container.ID == ctx.beforeContainer.ID { - ctx.beforeContainer = nil - } - return excludeContainer - } - - // Stop iteration when the index is over the limit - if ctx.Limit > 0 && ctx.idx == ctx.Limit { - return stopIteration - } - - // Stop interation when the container arrives to the filter container - if ctx.sinceContainer != nil { - if container.ID == ctx.sinceContainer.ID { - return stopIteration - } - } - - // Do not include container if its exit code is not in the filter - if len(ctx.exitAllowed) > 0 { - shouldSkip := true - for _, code := range ctx.exitAllowed { - if code == container.ExitCode && !container.Running { - shouldSkip = false - break - } - } - if shouldSkip { - return excludeContainer - } - } - - // Do not include container if its status doesn't match the filter - if !ctx.filters.Match("status", container.State.StateString()) { - return excludeContainer - } - - if ctx.ancestorFilter { - if len(ctx.images) == 0 { - return excludeContainer - } - if !ctx.images[container.ImageID] { - return excludeContainer - } - } - - return includeContainer -} - -func getImage(s *graph.TagStore, img, imgID string) (string, error) { - // both Image and ImageID is actually ids, nothing to guess - if strings.HasPrefix(imgID, img) { - return img, nil - } - id, err := s.GetID(img) - if err != nil { - if err == graph.ErrNameIsNotExist { - return imgID, nil - } - return "", err - } - if id != imgID { - return imgID, nil - } - return img, nil -} - -// transformContainer generates the container type expected by the docker ps command. -func (daemon *Daemon) transformContainer(container *Container, ctx *listContext) (*types.Container, error) { - newC := &types.Container{ - ID: container.ID, - Names: ctx.names[container.ID], - ImageID: container.ImageID, - } - if newC.Names == nil { - // Dead containers will often have no name, so make sure the response isn't null - newC.Names = []string{} - } - - showImg, err := getImage(daemon.repositories, container.Config.Image, container.ImageID) - if err != nil { - return nil, err - } - newC.Image = showImg - - if len(container.Args) > 0 { - args := []string{} - for _, arg := range container.Args { - if strings.Contains(arg, " ") { - args = append(args, fmt.Sprintf("'%s'", arg)) - } else { - args = append(args, arg) - } - } - argsAsString := strings.Join(args, " ") - - newC.Command = fmt.Sprintf("%s %s", container.Path, argsAsString) - } else { - newC.Command = container.Path - } - newC.Created = container.Created.Unix() - newC.Status = container.State.String() - newC.HostConfig.NetworkMode = string(container.hostConfig.NetworkMode) - - newC.Ports = []types.Port{} - for port, bindings := range container.NetworkSettings.Ports { - p, err := nat.ParsePort(port.Port()) - if err != nil { - return nil, err - } - if len(bindings) == 0 { - newC.Ports = append(newC.Ports, types.Port{ - PrivatePort: p, - Type: port.Proto(), - }) - continue - } - for _, binding := range bindings { - h, err := nat.ParsePort(binding.HostPort) - if err != nil { - return nil, err - } - newC.Ports = append(newC.Ports, types.Port{ - PrivatePort: p, - PublicPort: h, - Type: port.Proto(), - IP: binding.HostIP, - }) - } - } - - if ctx.Size { - sizeRw, sizeRootFs := daemon.getSize(container) - newC.SizeRw = sizeRw - newC.SizeRootFs = sizeRootFs - } - newC.Labels = container.Config.Labels - - return newC, nil -} - -// Volumes lists known volumes, using the filter to restrict the range -// of volumes returned. -func (daemon *Daemon) Volumes(filter string) ([]*types.Volume, error) { - var volumesOut []*types.Volume - volFilters, err := filters.FromParam(filter) - if err != nil { - return nil, err - } - - filterUsed := false - if i, ok := volFilters["dangling"]; ok { - if len(i) > 1 { - return nil, derr.ErrorCodeDanglingOne - } - - filterValue := i[0] - if strings.ToLower(filterValue) == "true" || filterValue == "1" { - filterUsed = true - } - } - - volumes := daemon.volumes.List() - for _, v := range volumes { - if filterUsed && daemon.volumes.Count(v) > 0 { - continue - } - volumesOut = append(volumesOut, volumeToAPIType(v)) - } - return volumesOut, nil -} - -func populateImageFilterByParents(ancestorMap map[string]bool, imageID string, byParents map[string][]*image.Image) { - if !ancestorMap[imageID] { - if images, ok := byParents[imageID]; ok { - for _, image := range images { - populateImageFilterByParents(ancestorMap, image.ID, byParents) - } - } - ancestorMap[imageID] = true - } -} diff --git a/vendor/github.com/docker/docker/daemon/list_unix.go b/vendor/github.com/docker/docker/daemon/list_unix.go deleted file mode 100644 index 156e12d9..00000000 --- a/vendor/github.com/docker/docker/daemon/list_unix.go +++ /dev/null @@ -1,9 +0,0 @@ -// +build linux freebsd - -package daemon - -// excludeByIsolation is a platform specific helper function to support PS -// filtering by Isolation. This is a Windows-only concept, so is a no-op on Unix. -func excludeByIsolation(container *Container, ctx *listContext) iterationAction { - return includeContainer -} diff --git a/vendor/github.com/docker/docker/daemon/list_windows.go b/vendor/github.com/docker/docker/daemon/list_windows.go deleted file mode 100644 index d14bf8ca..00000000 --- a/vendor/github.com/docker/docker/daemon/list_windows.go +++ /dev/null @@ -1,16 +0,0 @@ -package daemon - -import "strings" - -// excludeByIsolation is a platform specific helper function to support PS -// filtering by Isolation. This is a Windows-only concept, so is a no-op on Unix. -func excludeByIsolation(container *Container, ctx *listContext) iterationAction { - i := strings.ToLower(string(container.hostConfig.Isolation)) - if i == "" { - i = "default" - } - if !ctx.filters.Match("isolation", i) { - return excludeContainer - } - return includeContainer -} diff --git a/vendor/github.com/docker/docker/daemon/logdrivers_linux.go b/vendor/github.com/docker/docker/daemon/logdrivers_linux.go deleted file mode 100644 index 0abc6269..00000000 --- a/vendor/github.com/docker/docker/daemon/logdrivers_linux.go +++ /dev/null @@ -1,13 +0,0 @@ -package daemon - -import ( - // Importing packages here only to make sure their init gets called and - // therefore they register themselves to the logdriver factory. - _ "github.com/docker/docker/daemon/logger/awslogs" - _ "github.com/docker/docker/daemon/logger/fluentd" - _ "github.com/docker/docker/daemon/logger/gelf" - _ "github.com/docker/docker/daemon/logger/journald" - _ "github.com/docker/docker/daemon/logger/jsonfilelog" - _ "github.com/docker/docker/daemon/logger/splunk" - _ "github.com/docker/docker/daemon/logger/syslog" -) diff --git a/vendor/github.com/docker/docker/daemon/logdrivers_windows.go b/vendor/github.com/docker/docker/daemon/logdrivers_windows.go deleted file mode 100644 index 3b4a1f3a..00000000 --- a/vendor/github.com/docker/docker/daemon/logdrivers_windows.go +++ /dev/null @@ -1,8 +0,0 @@ -package daemon - -import ( - // Importing packages here only to make sure their init gets called and - // therefore they register themselves to the logdriver factory. - _ "github.com/docker/docker/daemon/logger/awslogs" - _ "github.com/docker/docker/daemon/logger/jsonfilelog" -) diff --git a/vendor/github.com/docker/docker/daemon/logs.go b/vendor/github.com/docker/docker/daemon/logs.go deleted file mode 100644 index f3fa866a..00000000 --- a/vendor/github.com/docker/docker/daemon/logs.go +++ /dev/null @@ -1,139 +0,0 @@ -package daemon - -import ( - "io" - "strconv" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/daemon/logger" - "github.com/docker/docker/daemon/logger/jsonfilelog" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/pkg/stdcopy" -) - -// ContainerLogsConfig holds configs for logging operations. Exists -// for users of the daemon to to pass it a logging configuration. -type ContainerLogsConfig struct { - // if true stream log output - Follow bool - // if true include timestamps for each line of log output - Timestamps bool - // return that many lines of log output from the end - Tail string - // filter logs by returning on those entries after this time - Since time.Time - // whether or not to show stdout and stderr as well as log entries. - UseStdout, UseStderr bool - OutStream io.Writer - Stop <-chan bool -} - -// ContainerLogs hooks up a container's stdout and stderr streams -// configured with the given struct. -func (daemon *Daemon) ContainerLogs(containerName string, config *ContainerLogsConfig) error { - container, err := daemon.Get(containerName) - if err != nil { - return derr.ErrorCodeNoSuchContainer.WithArgs(containerName) - } - - if !(config.UseStdout || config.UseStderr) { - return derr.ErrorCodeNeedStream - } - - outStream := config.OutStream - errStream := outStream - if !container.Config.Tty { - errStream = stdcopy.NewStdWriter(outStream, stdcopy.Stderr) - outStream = stdcopy.NewStdWriter(outStream, stdcopy.Stdout) - } - config.OutStream = outStream - - cLog, err := daemon.getLogger(container) - if err != nil { - return err - } - logReader, ok := cLog.(logger.LogReader) - if !ok { - return logger.ErrReadLogsNotSupported - } - - follow := config.Follow && container.IsRunning() - tailLines, err := strconv.Atoi(config.Tail) - if err != nil { - tailLines = -1 - } - - logrus.Debug("logs: begin stream") - readConfig := logger.ReadConfig{ - Since: config.Since, - Tail: tailLines, - Follow: follow, - } - logs := logReader.ReadLogs(readConfig) - - for { - select { - case err := <-logs.Err: - logrus.Errorf("Error streaming logs: %v", err) - return nil - case <-config.Stop: - logs.Close() - return nil - case msg, ok := <-logs.Msg: - if !ok { - logrus.Debugf("logs: end stream") - return nil - } - logLine := msg.Line - if config.Timestamps { - logLine = append([]byte(msg.Timestamp.Format(logger.TimeFormat)+" "), logLine...) - } - if msg.Source == "stdout" && config.UseStdout { - outStream.Write(logLine) - } - if msg.Source == "stderr" && config.UseStderr { - errStream.Write(logLine) - } - } - } -} - -func (daemon *Daemon) getLogger(container *Container) (logger.Logger, error) { - if container.logDriver != nil && container.IsRunning() { - return container.logDriver, nil - } - cfg := container.getLogConfig(daemon.defaultLogConfig) - if err := logger.ValidateLogOpts(cfg.Type, cfg.Config); err != nil { - return nil, err - } - return container.StartLogger(cfg) -} - -// StartLogging initializes and starts the container logging stream. -func (daemon *Daemon) StartLogging(container *Container) error { - cfg := container.getLogConfig(daemon.defaultLogConfig) - if cfg.Type == "none" { - return nil // do not start logging routines - } - - if err := logger.ValidateLogOpts(cfg.Type, cfg.Config); err != nil { - return err - } - l, err := container.StartLogger(cfg) - if err != nil { - return derr.ErrorCodeInitLogger.WithArgs(err) - } - - copier := logger.NewCopier(container.ID, map[string]io.Reader{"stdout": container.StdoutPipe(), "stderr": container.StderrPipe()}, l) - container.logCopier = copier - copier.Run() - container.logDriver = l - - // set LogPath field only for json-file logdriver - if jl, ok := l.(*jsonfilelog.JSONFileLogger); ok { - container.LogPath = jl.LogPath() - } - - return nil -} diff --git a/vendor/github.com/docker/docker/daemon/monitor.go b/vendor/github.com/docker/docker/daemon/monitor.go deleted file mode 100644 index 02f594e4..00000000 --- a/vendor/github.com/docker/docker/daemon/monitor.go +++ /dev/null @@ -1,392 +0,0 @@ -package daemon - -import ( - "io" - "os/exec" - "strings" - "sync" - "syscall" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/daemon/execdriver" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/runconfig" - "github.com/docker/docker/utils" -) - -const ( - defaultTimeIncrement = 100 - loggerCloseTimeout = 10 * time.Second -) - -// containerSupervisor defines the interface that a supervisor must implement -type containerSupervisor interface { - // LogContainerEvent generates events related to a given container - LogContainerEvent(*Container, string) - // Cleanup ensures that the container is properly unmounted - Cleanup(*Container) - // StartLogging starts the logging driver for the container - StartLogging(*Container) error - // Run starts a container - Run(c *Container, pipes *execdriver.Pipes, startCallback execdriver.DriverCallback) (execdriver.ExitStatus, error) - // IsShuttingDown tells whether the supervisor is shutting down or not - IsShuttingDown() bool -} - -// containerMonitor monitors the execution of a container's main process. -// If a restart policy is specified for the container the monitor will ensure that the -// process is restarted based on the rules of the policy. When the container is finally stopped -// the monitor will reset and cleanup any of the container resources such as networking allocations -// and the rootfs -type containerMonitor struct { - mux sync.Mutex - - // supervisor keeps track of the container and the events it generates - supervisor containerSupervisor - - // container is the container being monitored - container *Container - - // restartPolicy is the current policy being applied to the container monitor - restartPolicy runconfig.RestartPolicy - - // failureCount is the number of times the container has failed to - // start in a row - failureCount int - - // shouldStop signals the monitor that the next time the container exits it is - // either because docker or the user asked for the container to be stopped - shouldStop bool - - // startSignal is a channel that is closes after the container initially starts - startSignal chan struct{} - - // stopChan is used to signal to the monitor whenever there is a wait for the - // next restart so that the timeIncrement is not honored and the user is not - // left waiting for nothing to happen during this time - stopChan chan struct{} - - // timeIncrement is the amount of time to wait between restarts - // this is in milliseconds - timeIncrement int - - // lastStartTime is the time which the monitor last exec'd the container's process - lastStartTime time.Time -} - -// newContainerMonitor returns an initialized containerMonitor for the provided container -// honoring the provided restart policy -func (daemon *Daemon) newContainerMonitor(container *Container, policy runconfig.RestartPolicy) *containerMonitor { - return &containerMonitor{ - supervisor: daemon, - container: container, - restartPolicy: policy, - timeIncrement: defaultTimeIncrement, - stopChan: make(chan struct{}), - startSignal: make(chan struct{}), - } -} - -// Stop signals to the container monitor that it should stop monitoring the container -// for exits the next time the process dies -func (m *containerMonitor) ExitOnNext() { - m.mux.Lock() - - // we need to protect having a double close of the channel when stop is called - // twice or else we will get a panic - if !m.shouldStop { - m.shouldStop = true - close(m.stopChan) - } - - m.mux.Unlock() -} - -// Close closes the container's resources such as networking allocations and -// unmounts the contatiner's root filesystem -func (m *containerMonitor) Close() error { - // Cleanup networking and mounts - m.supervisor.Cleanup(m.container) - - // FIXME: here is race condition between two RUN instructions in Dockerfile - // because they share same runconfig and change image. Must be fixed - // in builder/builder.go - if err := m.container.toDisk(); err != nil { - logrus.Errorf("Error dumping container %s state to disk: %s", m.container.ID, err) - - return err - } - - return nil -} - -// Start starts the containers process and monitors it according to the restart policy -func (m *containerMonitor) Start() error { - var ( - err error - exitStatus execdriver.ExitStatus - // this variable indicates where we in execution flow: - // before Run or after - afterRun bool - ) - - // ensure that when the monitor finally exits we release the networking and unmount the rootfs - defer func() { - if afterRun { - m.container.Lock() - m.container.setStopped(&exitStatus) - defer m.container.Unlock() - } - m.Close() - }() - // reset stopped flag - if m.container.HasBeenManuallyStopped { - m.container.HasBeenManuallyStopped = false - } - - // reset the restart count - m.container.RestartCount = -1 - - for { - m.container.RestartCount++ - - if err := m.supervisor.StartLogging(m.container); err != nil { - m.resetContainer(false) - - return err - } - - pipes := execdriver.NewPipes(m.container.stdin, m.container.stdout, m.container.stderr, m.container.Config.OpenStdin) - - m.logEvent("start") - - m.lastStartTime = time.Now() - - if exitStatus, err = m.supervisor.Run(m.container, pipes, m.callback); err != nil { - // if we receive an internal error from the initial start of a container then lets - // return it instead of entering the restart loop - // set to 127 for container cmd not found/does not exist) - if strings.Contains(err.Error(), "executable file not found") || - strings.Contains(err.Error(), "no such file or directory") || - strings.Contains(err.Error(), "system cannot find the file specified") { - if m.container.RestartCount == 0 { - m.container.ExitCode = 127 - m.resetContainer(false) - return derr.ErrorCodeCmdNotFound - } - } - // set to 126 for container cmd can't be invoked errors - if strings.Contains(err.Error(), syscall.EACCES.Error()) { - if m.container.RestartCount == 0 { - m.container.ExitCode = 126 - m.resetContainer(false) - return derr.ErrorCodeCmdCouldNotBeInvoked - } - } - - if m.container.RestartCount == 0 { - m.container.ExitCode = -1 - m.resetContainer(false) - - return derr.ErrorCodeCantStart.WithArgs(m.container.ID, utils.GetErrorMessage(err)) - } - - logrus.Errorf("Error running container: %s", err) - } - - // here container.Lock is already lost - afterRun = true - - m.resetMonitor(err == nil && exitStatus.ExitCode == 0) - - if m.shouldRestart(exitStatus.ExitCode) { - m.container.setRestarting(&exitStatus) - m.logEvent("die") - m.resetContainer(true) - - // sleep with a small time increment between each restart to help avoid issues cased by quickly - // restarting the container because of some types of errors ( networking cut out, etc... ) - m.waitForNextRestart() - - // we need to check this before reentering the loop because the waitForNextRestart could have - // been terminated by a request from a user - if m.shouldStop { - return err - } - continue - } - - m.logEvent("die") - m.resetContainer(true) - return err - } -} - -// resetMonitor resets the stateful fields on the containerMonitor based on the -// previous runs success or failure. Regardless of success, if the container had -// an execution time of more than 10s then reset the timer back to the default -func (m *containerMonitor) resetMonitor(successful bool) { - executionTime := time.Now().Sub(m.lastStartTime).Seconds() - - if executionTime > 10 { - m.timeIncrement = defaultTimeIncrement - } else { - // otherwise we need to increment the amount of time we wait before restarting - // the process. We will build up by multiplying the increment by 2 - m.timeIncrement *= 2 - } - - // the container exited successfully so we need to reset the failure counter - if successful { - m.failureCount = 0 - } else { - m.failureCount++ - } -} - -// waitForNextRestart waits with the default time increment to restart the container unless -// a user or docker asks for the container to be stopped -func (m *containerMonitor) waitForNextRestart() { - select { - case <-time.After(time.Duration(m.timeIncrement) * time.Millisecond): - case <-m.stopChan: - } -} - -// shouldRestart checks the restart policy and applies the rules to determine if -// the container's process should be restarted -func (m *containerMonitor) shouldRestart(exitCode int) bool { - m.mux.Lock() - defer m.mux.Unlock() - - // do not restart if the user or docker has requested that this container be stopped - if m.shouldStop { - m.container.HasBeenManuallyStopped = !m.supervisor.IsShuttingDown() - return false - } - - switch { - case m.restartPolicy.IsAlways(), m.restartPolicy.IsUnlessStopped(): - return true - case m.restartPolicy.IsOnFailure(): - // the default value of 0 for MaximumRetryCount means that we will not enforce a maximum count - if max := m.restartPolicy.MaximumRetryCount; max != 0 && m.failureCount > max { - logrus.Debugf("stopping restart of container %s because maximum failure could of %d has been reached", - stringid.TruncateID(m.container.ID), max) - return false - } - - return exitCode != 0 - } - - return false -} - -// callback ensures that the container's state is properly updated after we -// received ack from the execution drivers -func (m *containerMonitor) callback(processConfig *execdriver.ProcessConfig, pid int, chOOM <-chan struct{}) error { - go func() { - _, ok := <-chOOM - if ok { - m.logEvent("oom") - } - }() - - if processConfig.Tty { - // The callback is called after the process Start() - // so we are in the parent process. In TTY mode, stdin/out/err is the PtySlave - // which we close here. - if c, ok := processConfig.Stdout.(io.Closer); ok { - c.Close() - } - } - - m.container.setRunning(pid) - - // signal that the process has started - // close channel only if not closed - select { - case <-m.startSignal: - default: - close(m.startSignal) - } - - if err := m.container.toDiskLocking(); err != nil { - logrus.Errorf("Error saving container to disk: %v", err) - } - return nil -} - -// resetContainer resets the container's IO and ensures that the command is able to be executed again -// by copying the data into a new struct -// if lock is true, then container locked during reset -func (m *containerMonitor) resetContainer(lock bool) { - container := m.container - if lock { - container.Lock() - defer container.Unlock() - } - - if container.Config.OpenStdin { - if err := container.stdin.Close(); err != nil { - logrus.Errorf("%s: Error close stdin: %s", container.ID, err) - } - } - - if err := container.stdout.Clean(); err != nil { - logrus.Errorf("%s: Error close stdout: %s", container.ID, err) - } - - if err := container.stderr.Clean(); err != nil { - logrus.Errorf("%s: Error close stderr: %s", container.ID, err) - } - - if container.command != nil && container.command.ProcessConfig.Terminal != nil { - if err := container.command.ProcessConfig.Terminal.Close(); err != nil { - logrus.Errorf("%s: Error closing terminal: %s", container.ID, err) - } - } - - // Re-create a brand new stdin pipe once the container exited - if container.Config.OpenStdin { - container.stdin, container.stdinPipe = io.Pipe() - } - - if container.logDriver != nil { - if container.logCopier != nil { - exit := make(chan struct{}) - go func() { - container.logCopier.Wait() - close(exit) - }() - select { - case <-time.After(loggerCloseTimeout): - logrus.Warnf("Logger didn't exit in time: logs may be truncated") - case <-exit: - } - } - container.logDriver.Close() - container.logCopier = nil - container.logDriver = nil - } - - c := container.command.ProcessConfig.Cmd - - container.command.ProcessConfig.Cmd = exec.Cmd{ - Stdin: c.Stdin, - Stdout: c.Stdout, - Stderr: c.Stderr, - Path: c.Path, - Env: c.Env, - ExtraFiles: c.ExtraFiles, - Args: c.Args, - Dir: c.Dir, - SysProcAttr: c.SysProcAttr, - } -} - -func (m *containerMonitor) logEvent(action string) { - m.supervisor.LogContainerEvent(m.container, action) -} diff --git a/vendor/github.com/docker/docker/daemon/mounts.go b/vendor/github.com/docker/docker/daemon/mounts.go deleted file mode 100644 index 9d195fa8..00000000 --- a/vendor/github.com/docker/docker/daemon/mounts.go +++ /dev/null @@ -1,46 +0,0 @@ -package daemon - -import ( - "strings" - - derr "github.com/docker/docker/errors" - "github.com/docker/docker/volume/store" -) - -func (daemon *Daemon) prepareMountPoints(container *Container) error { - for _, config := range container.MountPoints { - if len(config.Driver) > 0 { - v, err := daemon.createVolume(config.Name, config.Driver, nil) - if err != nil { - return err - } - config.Volume = v - } - } - return nil -} - -func (daemon *Daemon) removeMountPoints(container *Container, rm bool) error { - var rmErrors []string - for _, m := range container.MountPoints { - if m.Volume == nil { - continue - } - daemon.volumes.Decrement(m.Volume) - if rm { - err := daemon.volumes.Remove(m.Volume) - // ErrVolumeInUse is ignored because having this - // volume being referenced by other container is - // not an error, but an implementation detail. - // This prevents docker from logging "ERROR: Volume in use" - // where there is another container using the volume. - if err != nil && err != store.ErrVolumeInUse { - rmErrors = append(rmErrors, err.Error()) - } - } - } - if len(rmErrors) > 0 { - return derr.ErrorCodeRemovingVolume.WithArgs(strings.Join(rmErrors, "\n")) - } - return nil -} diff --git a/vendor/github.com/docker/docker/daemon/network.go b/vendor/github.com/docker/docker/daemon/network.go deleted file mode 100644 index c1412cec..00000000 --- a/vendor/github.com/docker/docker/daemon/network.go +++ /dev/null @@ -1,148 +0,0 @@ -package daemon - -import ( - "errors" - "fmt" - "net" - "strings" - - "github.com/docker/docker/daemon/network" - "github.com/docker/libnetwork" -) - -const ( - // NetworkByID represents a constant to find a network by its ID - NetworkByID = iota + 1 - // NetworkByName represents a constant to find a network by its Name - NetworkByName -) - -// NetworkControllerEnabled checks if the networking stack is enabled. -// This feature depends on OS primitives and it's dissabled in systems like Windows. -func (daemon *Daemon) NetworkControllerEnabled() bool { - return daemon.netController != nil -} - -// FindNetwork function finds a network for a given string that can represent network name or id -func (daemon *Daemon) FindNetwork(idName string) (libnetwork.Network, error) { - // Find by Name - n, err := daemon.GetNetwork(idName, NetworkByName) - if _, ok := err.(libnetwork.ErrNoSuchNetwork); err != nil && !ok { - return nil, err - } - - if n != nil { - return n, nil - } - - // Find by id - n, err = daemon.GetNetwork(idName, NetworkByID) - if err != nil { - return nil, err - } - - return n, nil -} - -// GetNetwork function returns a network for a given string that represents the network and -// a hint to indicate if the string is an Id or Name of the network -func (daemon *Daemon) GetNetwork(idName string, by int) (libnetwork.Network, error) { - c := daemon.netController - switch by { - case NetworkByID: - list := daemon.GetNetworksByID(idName) - - if len(list) == 0 { - return nil, libnetwork.ErrNoSuchNetwork(idName) - } - - if len(list) > 1 { - return nil, libnetwork.ErrInvalidID(idName) - } - - return list[0], nil - case NetworkByName: - if idName == "" { - idName = c.Config().Daemon.DefaultNetwork - } - return c.NetworkByName(idName) - } - return nil, errors.New("unexpected selector for GetNetwork") -} - -// GetNetworksByID returns a list of networks whose ID partially matches zero or more networks -func (daemon *Daemon) GetNetworksByID(partialID string) []libnetwork.Network { - c := daemon.netController - list := []libnetwork.Network{} - l := func(nw libnetwork.Network) bool { - if strings.HasPrefix(nw.ID(), partialID) { - list = append(list, nw) - } - return false - } - c.WalkNetworks(l) - - return list -} - -// CreateNetwork creates a network with the given name, driver and other optional parameters -func (daemon *Daemon) CreateNetwork(name, driver string, ipam network.IPAM, options map[string]string) (libnetwork.Network, error) { - c := daemon.netController - if driver == "" { - driver = c.Config().Daemon.DefaultDriver - } - - nwOptions := []libnetwork.NetworkOption{} - - v4Conf, v6Conf, err := getIpamConfig(ipam.Config) - if err != nil { - return nil, err - } - - nwOptions = append(nwOptions, libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf)) - nwOptions = append(nwOptions, libnetwork.NetworkOptionDriverOpts(options)) - return c.NewNetwork(driver, name, nwOptions...) -} - -func getIpamConfig(data []network.IPAMConfig) ([]*libnetwork.IpamConf, []*libnetwork.IpamConf, error) { - ipamV4Cfg := []*libnetwork.IpamConf{} - ipamV6Cfg := []*libnetwork.IpamConf{} - for _, d := range data { - iCfg := libnetwork.IpamConf{} - iCfg.PreferredPool = d.Subnet - iCfg.SubPool = d.IPRange - iCfg.Gateway = d.Gateway - iCfg.AuxAddresses = d.AuxAddress - ip, _, err := net.ParseCIDR(d.Subnet) - if err != nil { - return nil, nil, fmt.Errorf("Invalid subnet %s : %v", d.Subnet, err) - } - if ip.To4() != nil { - ipamV4Cfg = append(ipamV4Cfg, &iCfg) - } else { - ipamV6Cfg = append(ipamV6Cfg, &iCfg) - } - } - return ipamV4Cfg, ipamV6Cfg, nil -} - -// ConnectContainerToNetwork connects the given container to the given -// network. If either cannot be found, an err is returned. If the -// network cannot be set up, an err is returned. -func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName string) error { - container, err := daemon.Get(containerName) - if err != nil { - return err - } - return daemon.ConnectToNetwork(container, networkName) -} - -// DisconnectContainerFromNetwork disconnects the given container from -// the given network. If either cannot be found, an err is returned. -func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, network libnetwork.Network) error { - container, err := daemon.Get(containerName) - if err != nil { - return err - } - return container.DisconnectFromNetwork(network) -} diff --git a/vendor/github.com/docker/docker/daemon/network/settings.go b/vendor/github.com/docker/docker/daemon/network/settings.go deleted file mode 100644 index ddc87a7c..00000000 --- a/vendor/github.com/docker/docker/daemon/network/settings.go +++ /dev/null @@ -1,51 +0,0 @@ -package network - -import "github.com/docker/docker/pkg/nat" - -// Address represents an IP address -type Address struct { - Addr string - PrefixLen int -} - -// IPAM represents IP Address Management -type IPAM struct { - Driver string - Config []IPAMConfig -} - -// IPAMConfig represents IPAM configurations -type IPAMConfig struct { - Subnet string `json:",omitempty"` - IPRange string `json:",omitempty"` - Gateway string `json:",omitempty"` - AuxAddress map[string]string `json:"AuxiliaryAddresses,omitempty"` -} - -// Settings stores configuration details about the daemon network config -// TODO Windows. Many of these fields can be factored out., -type Settings struct { - Bridge string - SandboxID string - HairpinMode bool - LinkLocalIPv6Address string - LinkLocalIPv6PrefixLen int - Networks map[string]*EndpointSettings - Ports nat.PortMap - SandboxKey string - SecondaryIPAddresses []Address - SecondaryIPv6Addresses []Address - IsAnonymousEndpoint bool -} - -// EndpointSettings stores the network endpoint details -type EndpointSettings struct { - EndpointID string - Gateway string - IPAddress string - IPPrefixLen int - IPv6Gateway string - GlobalIPv6Address string - GlobalIPv6PrefixLen int - MacAddress string -} diff --git a/vendor/github.com/docker/docker/daemon/pause.go b/vendor/github.com/docker/docker/daemon/pause.go deleted file mode 100644 index be7f6339..00000000 --- a/vendor/github.com/docker/docker/daemon/pause.go +++ /dev/null @@ -1,43 +0,0 @@ -package daemon - -import ( - derr "github.com/docker/docker/errors" -) - -// ContainerPause pauses a container -func (daemon *Daemon) ContainerPause(name string) error { - container, err := daemon.Get(name) - if err != nil { - return err - } - - if err := daemon.containerPause(container); err != nil { - return derr.ErrorCodePauseError.WithArgs(name, err) - } - - return nil -} - -// containerPause pauses the container execution without stopping the process. -// The execution can be resumed by calling containerUnpause. -func (daemon *Daemon) containerPause(container *Container) error { - container.Lock() - defer container.Unlock() - - // We cannot Pause the container which is not running - if !container.Running { - return derr.ErrorCodeNotRunning.WithArgs(container.ID) - } - - // We cannot Pause the container which is already paused - if container.Paused { - return derr.ErrorCodeAlreadyPaused.WithArgs(container.ID) - } - - if err := daemon.execDriver.Pause(container.command); err != nil { - return err - } - container.Paused = true - daemon.LogContainerEvent(container, "pause") - return nil -} diff --git a/vendor/github.com/docker/docker/daemon/rename.go b/vendor/github.com/docker/docker/daemon/rename.go deleted file mode 100644 index 36421dcd..00000000 --- a/vendor/github.com/docker/docker/daemon/rename.go +++ /dev/null @@ -1,84 +0,0 @@ -package daemon - -import ( - "strings" - - "github.com/Sirupsen/logrus" - derr "github.com/docker/docker/errors" - "github.com/docker/libnetwork" -) - -// ContainerRename changes the name of a container, using the oldName -// to find the container. An error is returned if newName is already -// reserved. -func (daemon *Daemon) ContainerRename(oldName, newName string) error { - var ( - err error - sid string - sb libnetwork.Sandbox - container *Container - ) - - if oldName == "" || newName == "" { - return derr.ErrorCodeEmptyRename - } - - container, err = daemon.Get(oldName) - if err != nil { - return err - } - - oldName = container.Name - - container.Lock() - defer container.Unlock() - if newName, err = daemon.reserveName(container.ID, newName); err != nil { - return derr.ErrorCodeRenameTaken.WithArgs(err) - } - - container.Name = newName - - defer func() { - if err != nil { - container.Name = oldName - daemon.reserveName(container.ID, oldName) - daemon.containerGraphDB.Delete(newName) - } - }() - - if err = daemon.containerGraphDB.Delete(oldName); err != nil { - return derr.ErrorCodeRenameDelete.WithArgs(oldName, err) - } - - if err = container.toDisk(); err != nil { - return err - } - - if !container.Running { - daemon.LogContainerEvent(container, "rename") - return nil - } - - defer func() { - if err != nil { - container.Name = oldName - if e := container.toDisk(); e != nil { - logrus.Errorf("%s: Failed in writing to Disk on rename failure: %v", container.ID, e) - } - } - }() - - sid = container.NetworkSettings.SandboxID - sb, err = daemon.netController.SandboxByID(sid) - if err != nil { - return err - } - - err = sb.Rename(strings.TrimPrefix(container.Name, "/")) - if err != nil { - return err - } - - daemon.LogContainerEvent(container, "rename") - return nil -} diff --git a/vendor/github.com/docker/docker/daemon/resize.go b/vendor/github.com/docker/docker/daemon/resize.go deleted file mode 100644 index ea9928c4..00000000 --- a/vendor/github.com/docker/docker/daemon/resize.go +++ /dev/null @@ -1,33 +0,0 @@ -package daemon - -import derr "github.com/docker/docker/errors" - -// ContainerResize changes the size of the TTY of the process running -// in the container with the given name to the given height and width. -func (daemon *Daemon) ContainerResize(name string, height, width int) error { - container, err := daemon.Get(name) - if err != nil { - return err - } - - if !container.IsRunning() { - return derr.ErrorCodeNotRunning.WithArgs(container.ID) - } - - if err = container.Resize(height, width); err == nil { - daemon.LogContainerEvent(container, "resize") - } - return err -} - -// ContainerExecResize changes the size of the TTY of the process -// running in the exec with the given name to the given height and -// width. -func (daemon *Daemon) ContainerExecResize(name string, height, width int) error { - ExecConfig, err := daemon.getExecConfig(name) - if err != nil { - return err - } - - return ExecConfig.resize(height, width) -} diff --git a/vendor/github.com/docker/docker/daemon/restart.go b/vendor/github.com/docker/docker/daemon/restart.go deleted file mode 100644 index fcfe6128..00000000 --- a/vendor/github.com/docker/docker/daemon/restart.go +++ /dev/null @@ -1,46 +0,0 @@ -package daemon - -import ( - derr "github.com/docker/docker/errors" -) - -// ContainerRestart stops and starts a container. It attempts to -// gracefully stop the container within the given timeout, forcefully -// stopping it if the timeout is exceeded. If given a negative -// timeout, ContainerRestart will wait forever until a graceful -// stop. Returns an error if the container cannot be found, or if -// there is an underlying error at any stage of the restart. -func (daemon *Daemon) ContainerRestart(name string, seconds int) error { - container, err := daemon.Get(name) - if err != nil { - return err - } - if err := daemon.containerRestart(container, seconds); err != nil { - return derr.ErrorCodeCantRestart.WithArgs(name, err) - } - return nil -} - -// containerRestart attempts to gracefully stop and then start the -// container. When stopping, wait for the given duration in seconds to -// gracefully stop, before forcefully terminating the container. If -// given a negative duration, wait forever for a graceful stop. -func (daemon *Daemon) containerRestart(container *Container, seconds int) error { - // Avoid unnecessarily unmounting and then directly mounting - // the container when the container stops and then starts - // again - if err := daemon.Mount(container); err == nil { - defer daemon.Unmount(container) - } - - if err := daemon.containerStop(container, seconds); err != nil { - return err - } - - if err := daemon.containerStart(container); err != nil { - return err - } - - daemon.LogContainerEvent(container, "restart") - return nil -} diff --git a/vendor/github.com/docker/docker/daemon/start.go b/vendor/github.com/docker/docker/daemon/start.go deleted file mode 100644 index de4516c7..00000000 --- a/vendor/github.com/docker/docker/daemon/start.go +++ /dev/null @@ -1,160 +0,0 @@ -package daemon - -import ( - "runtime" - - "github.com/Sirupsen/logrus" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/pkg/promise" - "github.com/docker/docker/runconfig" -) - -// ContainerStart starts a container. -func (daemon *Daemon) ContainerStart(name string, hostConfig *runconfig.HostConfig) error { - container, err := daemon.Get(name) - if err != nil { - return err - } - - if container.isPaused() { - return derr.ErrorCodeStartPaused - } - - if container.IsRunning() { - return derr.ErrorCodeAlreadyStarted - } - - // Windows does not have the backwards compatibility issue here. - if runtime.GOOS != "windows" { - // This is kept for backward compatibility - hostconfig should be passed when - // creating a container, not during start. - if hostConfig != nil { - if err := daemon.setHostConfig(container, hostConfig); err != nil { - return err - } - } - } else { - if hostConfig != nil { - return derr.ErrorCodeHostConfigStart - } - } - - // check if hostConfig is in line with the current system settings. - // It may happen cgroups are umounted or the like. - if _, err = daemon.verifyContainerSettings(container.hostConfig, nil); err != nil { - return err - } - - if err := daemon.containerStart(container); err != nil { - return err - } - - return nil -} - -// Start starts a container -func (daemon *Daemon) Start(container *Container) error { - return daemon.containerStart(container) -} - -// containerStart prepares the container to run by setting up everything the -// container needs, such as storage and networking, as well as links -// between containers. The container is left waiting for a signal to -// begin running. -func (daemon *Daemon) containerStart(container *Container) (err error) { - container.Lock() - defer container.Unlock() - - if container.Running { - return nil - } - - if container.removalInProgress || container.Dead { - return derr.ErrorCodeContainerBeingRemoved - } - - // if we encounter an error during start we need to ensure that any other - // setup has been cleaned up properly - defer func() { - if err != nil { - container.setError(err) - // if no one else has set it, make sure we don't leave it at zero - if container.ExitCode == 0 { - container.ExitCode = 128 - } - container.toDisk() - daemon.Cleanup(container) - daemon.LogContainerEvent(container, "die") - } - }() - - if err := daemon.conditionalMountOnStart(container); err != nil { - return err - } - - // Make sure NetworkMode has an acceptable value. We do this to ensure - // backwards API compatibility. - container.hostConfig = runconfig.SetDefaultNetModeIfBlank(container.hostConfig) - - if err := daemon.initializeNetworking(container); err != nil { - return err - } - linkedEnv, err := daemon.setupLinkedContainers(container) - if err != nil { - return err - } - if err := container.setupWorkingDirectory(); err != nil { - return err - } - env := container.createDaemonEnvironment(linkedEnv) - if err := daemon.populateCommand(container, env); err != nil { - return err - } - - if !container.hostConfig.IpcMode.IsContainer() && !container.hostConfig.IpcMode.IsHost() { - if err := daemon.setupIpcDirs(container); err != nil { - return err - } - } - - mounts, err := daemon.setupMounts(container) - if err != nil { - return err - } - mounts = append(mounts, container.ipcMounts()...) - - container.command.Mounts = mounts - return daemon.waitForStart(container) -} - -func (daemon *Daemon) waitForStart(container *Container) error { - container.monitor = daemon.newContainerMonitor(container, container.hostConfig.RestartPolicy) - - // block until we either receive an error from the initial start of the container's - // process or until the process is running in the container - select { - case <-container.monitor.startSignal: - case err := <-promise.Go(container.monitor.Start): - return err - } - - return nil -} - -// Cleanup releases any network resources allocated to the container along with any rules -// around how containers are linked together. It also unmounts the container's root filesystem. -func (daemon *Daemon) Cleanup(container *Container) { - daemon.releaseNetwork(container) - - container.unmountIpcMounts(detachMounted) - - daemon.conditionalUnmountOnCleanup(container) - - for _, eConfig := range container.execCommands.s { - daemon.unregisterExecCommand(eConfig) - } - - if err := container.unmountVolumes(false); err != nil { - logrus.Warnf("%s cleanup: Failed to umount volumes: %v", container.ID, err) - } -} diff --git a/vendor/github.com/docker/docker/daemon/state.go b/vendor/github.com/docker/docker/daemon/state.go deleted file mode 100644 index 8ff5effc..00000000 --- a/vendor/github.com/docker/docker/daemon/state.go +++ /dev/null @@ -1,263 +0,0 @@ -package daemon - -import ( - "fmt" - "sync" - "time" - - "github.com/docker/docker/daemon/execdriver" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/pkg/units" -) - -// State holds the current container state, and has methods to get and -// set the state. Container has an embed, which allows all of the -// functions defined against State to run against Container. -type State struct { - sync.Mutex - // FIXME: Why do we have both paused and running if a - // container cannot be paused and running at the same time? - Running bool - Paused bool - Restarting bool - OOMKilled bool - removalInProgress bool // Not need for this to be persistent on disk. - Dead bool - Pid int - ExitCode int - Error string // contains last known error when starting the container - StartedAt time.Time - FinishedAt time.Time - waitChan chan struct{} -} - -// NewState creates a default state object with a fresh channel for state changes. -func NewState() *State { - return &State{ - waitChan: make(chan struct{}), - } -} - -// String returns a human-readable description of the state -func (s *State) String() string { - if s.Running { - if s.Paused { - return fmt.Sprintf("Up %s (Paused)", units.HumanDuration(time.Now().UTC().Sub(s.StartedAt))) - } - if s.Restarting { - return fmt.Sprintf("Restarting (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt))) - } - - return fmt.Sprintf("Up %s", units.HumanDuration(time.Now().UTC().Sub(s.StartedAt))) - } - - if s.removalInProgress { - return "Removal In Progress" - } - - if s.Dead { - return "Dead" - } - - if s.StartedAt.IsZero() { - return "Created" - } - - if s.FinishedAt.IsZero() { - return "" - } - - return fmt.Sprintf("Exited (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt))) -} - -// StateString returns a single string to describe state -func (s *State) StateString() string { - if s.Running { - if s.Paused { - return "paused" - } - if s.Restarting { - return "restarting" - } - return "running" - } - - if s.Dead { - return "dead" - } - - if s.StartedAt.IsZero() { - return "created" - } - - return "exited" -} - -func isValidStateString(s string) bool { - if s != "paused" && - s != "restarting" && - s != "running" && - s != "dead" && - s != "created" && - s != "exited" { - return false - } - return true -} - -func wait(waitChan <-chan struct{}, timeout time.Duration) error { - if timeout < 0 { - <-waitChan - return nil - } - select { - case <-time.After(timeout): - return derr.ErrorCodeTimedOut.WithArgs(timeout) - case <-waitChan: - return nil - } -} - -// waitRunning waits until state is running. If state is already -// running it returns immediately. If you want wait forever you must -// supply negative timeout. Returns pid, that was passed to -// setRunning. -func (s *State) waitRunning(timeout time.Duration) (int, error) { - s.Lock() - if s.Running { - pid := s.Pid - s.Unlock() - return pid, nil - } - waitChan := s.waitChan - s.Unlock() - if err := wait(waitChan, timeout); err != nil { - return -1, err - } - return s.GetPID(), nil -} - -// WaitStop waits until state is stopped. If state already stopped it returns -// immediately. If you want wait forever you must supply negative timeout. -// Returns exit code, that was passed to setStoppedLocking -func (s *State) WaitStop(timeout time.Duration) (int, error) { - s.Lock() - if !s.Running { - exitCode := s.ExitCode - s.Unlock() - return exitCode, nil - } - waitChan := s.waitChan - s.Unlock() - if err := wait(waitChan, timeout); err != nil { - return -1, err - } - return s.getExitCode(), nil -} - -// IsRunning returns whether the running flag is set. Used by Container to check whether a container is running. -func (s *State) IsRunning() bool { - s.Lock() - res := s.Running - s.Unlock() - return res -} - -// GetPID holds the process id of a container. -func (s *State) GetPID() int { - s.Lock() - res := s.Pid - s.Unlock() - return res -} - -func (s *State) getExitCode() int { - s.Lock() - res := s.ExitCode - s.Unlock() - return res -} - -func (s *State) setRunning(pid int) { - s.Error = "" - s.Running = true - s.Paused = false - s.Restarting = false - s.ExitCode = 0 - s.Pid = pid - s.StartedAt = time.Now().UTC() - close(s.waitChan) // fire waiters for start - s.waitChan = make(chan struct{}) -} - -func (s *State) setStoppedLocking(exitStatus *execdriver.ExitStatus) { - s.Lock() - s.setStopped(exitStatus) - s.Unlock() -} - -func (s *State) setStopped(exitStatus *execdriver.ExitStatus) { - s.Running = false - s.Restarting = false - s.Pid = 0 - s.FinishedAt = time.Now().UTC() - s.setFromExitStatus(exitStatus) - close(s.waitChan) // fire waiters for stop - s.waitChan = make(chan struct{}) -} - -// setRestarting is when docker handles the auto restart of containers when they are -// in the middle of a stop and being restarted again -func (s *State) setRestartingLocking(exitStatus *execdriver.ExitStatus) { - s.Lock() - s.setRestarting(exitStatus) - s.Unlock() -} - -func (s *State) setRestarting(exitStatus *execdriver.ExitStatus) { - // we should consider the container running when it is restarting because of - // all the checks in docker around rm/stop/etc - s.Running = true - s.Restarting = true - s.Pid = 0 - s.FinishedAt = time.Now().UTC() - s.setFromExitStatus(exitStatus) - close(s.waitChan) // fire waiters for stop - s.waitChan = make(chan struct{}) -} - -// setError sets the container's error state. This is useful when we want to -// know the error that occurred when container transits to another state -// when inspecting it -func (s *State) setError(err error) { - s.Error = err.Error() -} - -func (s *State) isPaused() bool { - s.Lock() - res := s.Paused - s.Unlock() - return res -} - -func (s *State) setRemovalInProgress() error { - s.Lock() - defer s.Unlock() - if s.removalInProgress { - return derr.ErrorCodeAlreadyRemoving - } - s.removalInProgress = true - return nil -} - -func (s *State) resetRemovalInProgress() { - s.Lock() - s.removalInProgress = false - s.Unlock() -} - -func (s *State) setDead() { - s.Lock() - s.Dead = true - s.Unlock() -} diff --git a/vendor/github.com/docker/docker/daemon/state_test.go b/vendor/github.com/docker/docker/daemon/state_test.go deleted file mode 100644 index c70dc4e1..00000000 --- a/vendor/github.com/docker/docker/daemon/state_test.go +++ /dev/null @@ -1,111 +0,0 @@ -package daemon - -import ( - "sync/atomic" - "testing" - "time" - - "github.com/docker/docker/daemon/execdriver" -) - -func TestStateRunStop(t *testing.T) { - s := NewState() - for i := 1; i < 3; i++ { // full lifecycle two times - started := make(chan struct{}) - var pid int64 - go func() { - runPid, _ := s.waitRunning(-1 * time.Second) - atomic.StoreInt64(&pid, int64(runPid)) - close(started) - }() - s.Lock() - s.setRunning(i + 100) - s.Unlock() - - if !s.IsRunning() { - t.Fatal("State not running") - } - if s.Pid != i+100 { - t.Fatalf("Pid %v, expected %v", s.Pid, i+100) - } - if s.ExitCode != 0 { - t.Fatalf("ExitCode %v, expected 0", s.ExitCode) - } - select { - case <-time.After(100 * time.Millisecond): - t.Fatal("Start callback doesn't fire in 100 milliseconds") - case <-started: - t.Log("Start callback fired") - } - runPid := int(atomic.LoadInt64(&pid)) - if runPid != i+100 { - t.Fatalf("Pid %v, expected %v", runPid, i+100) - } - if pid, err := s.waitRunning(-1 * time.Second); err != nil || pid != i+100 { - t.Fatalf("waitRunning returned pid: %v, err: %v, expected pid: %v, err: %v", pid, err, i+100, nil) - } - - stopped := make(chan struct{}) - var exit int64 - go func() { - exitCode, _ := s.WaitStop(-1 * time.Second) - atomic.StoreInt64(&exit, int64(exitCode)) - close(stopped) - }() - s.setStoppedLocking(&execdriver.ExitStatus{ExitCode: i}) - if s.IsRunning() { - t.Fatal("State is running") - } - if s.ExitCode != i { - t.Fatalf("ExitCode %v, expected %v", s.ExitCode, i) - } - if s.Pid != 0 { - t.Fatalf("Pid %v, expected 0", s.Pid) - } - select { - case <-time.After(100 * time.Millisecond): - t.Fatal("Stop callback doesn't fire in 100 milliseconds") - case <-stopped: - t.Log("Stop callback fired") - } - exitCode := int(atomic.LoadInt64(&exit)) - if exitCode != i { - t.Fatalf("ExitCode %v, expected %v", exitCode, i) - } - if exitCode, err := s.WaitStop(-1 * time.Second); err != nil || exitCode != i { - t.Fatalf("WaitStop returned exitCode: %v, err: %v, expected exitCode: %v, err: %v", exitCode, err, i, nil) - } - } -} - -func TestStateTimeoutWait(t *testing.T) { - s := NewState() - started := make(chan struct{}) - go func() { - s.waitRunning(100 * time.Millisecond) - close(started) - }() - select { - case <-time.After(200 * time.Millisecond): - t.Fatal("Start callback doesn't fire in 100 milliseconds") - case <-started: - t.Log("Start callback fired") - } - - s.Lock() - s.setRunning(49) - s.Unlock() - - stopped := make(chan struct{}) - go func() { - s.waitRunning(100 * time.Millisecond) - close(stopped) - }() - select { - case <-time.After(200 * time.Millisecond): - t.Fatal("Start callback doesn't fire in 100 milliseconds") - case <-stopped: - t.Log("Start callback fired") - } - -} diff --git a/vendor/github.com/docker/docker/daemon/state_unix.go b/vendor/github.com/docker/docker/daemon/state_unix.go deleted file mode 100644 index e5f4db33..00000000 --- a/vendor/github.com/docker/docker/daemon/state_unix.go +++ /dev/null @@ -1,12 +0,0 @@ -// +build linux freebsd - -package daemon - -import "github.com/docker/docker/daemon/execdriver" - -// setFromExitStatus is a platform specific helper function to set the state -// based on the ExitStatus structure. -func (s *State) setFromExitStatus(exitStatus *execdriver.ExitStatus) { - s.ExitCode = exitStatus.ExitCode - s.OOMKilled = exitStatus.OOMKilled -} diff --git a/vendor/github.com/docker/docker/daemon/state_windows.go b/vendor/github.com/docker/docker/daemon/state_windows.go deleted file mode 100644 index 223d4bc5..00000000 --- a/vendor/github.com/docker/docker/daemon/state_windows.go +++ /dev/null @@ -1,9 +0,0 @@ -package daemon - -import "github.com/docker/docker/daemon/execdriver" - -// setFromExitStatus is a platform specific helper function to set the state -// based on the ExitStatus structure. -func (s *State) setFromExitStatus(exitStatus *execdriver.ExitStatus) { - s.ExitCode = exitStatus.ExitCode -} diff --git a/vendor/github.com/docker/docker/daemon/stats.go b/vendor/github.com/docker/docker/daemon/stats.go deleted file mode 100644 index ed829c85..00000000 --- a/vendor/github.com/docker/docker/daemon/stats.go +++ /dev/null @@ -1,124 +0,0 @@ -package daemon - -import ( - "encoding/json" - "io" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/versions/v1p20" - "github.com/docker/docker/daemon/execdriver" - "github.com/docker/docker/pkg/version" -) - -// ContainerStatsConfig holds information for configuring the runtime -// behavior of a daemon.ContainerStats() call. -type ContainerStatsConfig struct { - Stream bool - OutStream io.Writer - Stop <-chan bool - Version version.Version -} - -// ContainerStats writes information about the container to the stream -// given in the config object. -func (daemon *Daemon) ContainerStats(prefixOrName string, config *ContainerStatsConfig) error { - container, err := daemon.Get(prefixOrName) - if err != nil { - return err - } - - // If the container is not running and requires no stream, return an empty stats. - if !container.IsRunning() && !config.Stream { - return json.NewEncoder(config.OutStream).Encode(&types.Stats{}) - } - - if config.Stream { - // Write an empty chunk of data. - // This is to ensure that the HTTP status code is sent immediately, - // even if the container has not yet produced any data. - config.OutStream.Write(nil) - } - - var preCPUStats types.CPUStats - getStatJSON := func(v interface{}) *types.StatsJSON { - update := v.(*execdriver.ResourceStats) - ss := convertStatsToAPITypes(update.Stats) - ss.PreCPUStats = preCPUStats - ss.MemoryStats.Limit = uint64(update.MemoryLimit) - ss.Read = update.Read - ss.CPUStats.SystemUsage = update.SystemUsage - preCPUStats = ss.CPUStats - return ss - } - - enc := json.NewEncoder(config.OutStream) - - updates := daemon.subscribeToContainerStats(container) - defer daemon.unsubscribeToContainerStats(container, updates) - - noStreamFirstFrame := true - for { - select { - case v, ok := <-updates: - if !ok { - return nil - } - - var statsJSON interface{} - statsJSONPost120 := getStatJSON(v) - if config.Version.LessThan("1.21") { - var ( - rxBytes uint64 - rxPackets uint64 - rxErrors uint64 - rxDropped uint64 - txBytes uint64 - txPackets uint64 - txErrors uint64 - txDropped uint64 - ) - for _, v := range statsJSONPost120.Networks { - rxBytes += v.RxBytes - rxPackets += v.RxPackets - rxErrors += v.RxErrors - rxDropped += v.RxDropped - txBytes += v.TxBytes - txPackets += v.TxPackets - txErrors += v.TxErrors - txDropped += v.TxDropped - } - statsJSON = &v1p20.StatsJSON{ - Stats: statsJSONPost120.Stats, - Network: types.NetworkStats{ - RxBytes: rxBytes, - RxPackets: rxPackets, - RxErrors: rxErrors, - RxDropped: rxDropped, - TxBytes: txBytes, - TxPackets: txPackets, - TxErrors: txErrors, - TxDropped: txDropped, - }, - } - } else { - statsJSON = statsJSONPost120 - } - - if !config.Stream && noStreamFirstFrame { - // prime the cpu stats so they aren't 0 in the final output - noStreamFirstFrame = false - continue - } - - if err := enc.Encode(statsJSON); err != nil { - return err - } - - if !config.Stream { - return nil - } - case <-config.Stop: - return nil - } - } -} diff --git a/vendor/github.com/docker/docker/daemon/stats_collector_unix.go b/vendor/github.com/docker/docker/daemon/stats_collector_unix.go deleted file mode 100644 index 6fb32b9a..00000000 --- a/vendor/github.com/docker/docker/daemon/stats_collector_unix.go +++ /dev/null @@ -1,180 +0,0 @@ -// +build !windows - -package daemon - -import ( - "bufio" - "os" - "strconv" - "strings" - "sync" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/daemon/execdriver" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/pkg/pubsub" - "github.com/opencontainers/runc/libcontainer/system" -) - -type statsSupervisor interface { - // GetContainerStats collects all the stats related to a container - GetContainerStats(container *Container) (*execdriver.ResourceStats, error) -} - -// newStatsCollector returns a new statsCollector that collections -// network and cgroup stats for a registered container at the specified -// interval. The collector allows non-running containers to be added -// and will start processing stats when they are started. -func (daemon *Daemon) newStatsCollector(interval time.Duration) *statsCollector { - s := &statsCollector{ - interval: interval, - supervisor: daemon, - publishers: make(map[*Container]*pubsub.Publisher), - clockTicksPerSecond: uint64(system.GetClockTicks()), - bufReader: bufio.NewReaderSize(nil, 128), - } - go s.run() - return s -} - -// statsCollector manages and provides container resource stats -type statsCollector struct { - m sync.Mutex - supervisor statsSupervisor - interval time.Duration - clockTicksPerSecond uint64 - publishers map[*Container]*pubsub.Publisher - bufReader *bufio.Reader -} - -// collect registers the container with the collector and adds it to -// the event loop for collection on the specified interval returning -// a channel for the subscriber to receive on. -func (s *statsCollector) collect(c *Container) chan interface{} { - s.m.Lock() - defer s.m.Unlock() - publisher, exists := s.publishers[c] - if !exists { - publisher = pubsub.NewPublisher(100*time.Millisecond, 1024) - s.publishers[c] = publisher - } - return publisher.Subscribe() -} - -// stopCollection closes the channels for all subscribers and removes -// the container from metrics collection. -func (s *statsCollector) stopCollection(c *Container) { - s.m.Lock() - if publisher, exists := s.publishers[c]; exists { - publisher.Close() - delete(s.publishers, c) - } - s.m.Unlock() -} - -// unsubscribe removes a specific subscriber from receiving updates for a container's stats. -func (s *statsCollector) unsubscribe(c *Container, ch chan interface{}) { - s.m.Lock() - publisher := s.publishers[c] - if publisher != nil { - publisher.Evict(ch) - if publisher.Len() == 0 { - delete(s.publishers, c) - } - } - s.m.Unlock() -} - -func (s *statsCollector) run() { - type publishersPair struct { - container *Container - publisher *pubsub.Publisher - } - // we cannot determine the capacity here. - // it will grow enough in first iteration - var pairs []publishersPair - - for range time.Tick(s.interval) { - // it does not make sense in the first iteration, - // but saves allocations in further iterations - pairs = pairs[:0] - - s.m.Lock() - for container, publisher := range s.publishers { - // copy pointers here to release the lock ASAP - pairs = append(pairs, publishersPair{container, publisher}) - } - s.m.Unlock() - if len(pairs) == 0 { - continue - } - - systemUsage, err := s.getSystemCPUUsage() - if err != nil { - logrus.Errorf("collecting system cpu usage: %v", err) - continue - } - - for _, pair := range pairs { - stats, err := s.supervisor.GetContainerStats(pair.container) - if err != nil { - if err != execdriver.ErrNotRunning { - logrus.Errorf("collecting stats for %s: %v", pair.container.ID, err) - } - continue - } - stats.SystemUsage = systemUsage - - pair.publisher.Publish(stats) - } - } -} - -const nanoSecondsPerSecond = 1e9 - -// getSystemCPUUsage returns the host system's cpu usage in -// nanoseconds. An error is returned if the format of the underlying -// file does not match. -// -// Uses /proc/stat defined by POSIX. Looks for the cpu -// statistics line and then sums up the first seven fields -// provided. See `man 5 proc` for details on specific field -// information. -func (s *statsCollector) getSystemCPUUsage() (uint64, error) { - var line string - f, err := os.Open("/proc/stat") - if err != nil { - return 0, err - } - defer func() { - s.bufReader.Reset(nil) - f.Close() - }() - s.bufReader.Reset(f) - err = nil - for err == nil { - line, err = s.bufReader.ReadString('\n') - if err != nil { - break - } - parts := strings.Fields(line) - switch parts[0] { - case "cpu": - if len(parts) < 8 { - return 0, derr.ErrorCodeBadCPUFields - } - var totalClockTicks uint64 - for _, i := range parts[1:8] { - v, err := strconv.ParseUint(i, 10, 64) - if err != nil { - return 0, derr.ErrorCodeBadCPUInt.WithArgs(i, err) - } - totalClockTicks += v - } - return (totalClockTicks * nanoSecondsPerSecond) / - s.clockTicksPerSecond, nil - } - } - return 0, derr.ErrorCodeBadStatFormat -} diff --git a/vendor/github.com/docker/docker/daemon/stats_collector_windows.go b/vendor/github.com/docker/docker/daemon/stats_collector_windows.go deleted file mode 100644 index e63f37b0..00000000 --- a/vendor/github.com/docker/docker/daemon/stats_collector_windows.go +++ /dev/null @@ -1,31 +0,0 @@ -package daemon - -import "time" - -// newStatsCollector returns a new statsCollector for collection stats -// for a registered container at the specified interval. The collector allows -// non-running containers to be added and will start processing stats when -// they are started. -func (daemon *Daemon) newStatsCollector(interval time.Duration) *statsCollector { - return &statsCollector{} -} - -// statsCollector manages and provides container resource stats -type statsCollector struct { -} - -// collect registers the container with the collector and adds it to -// the event loop for collection on the specified interval returning -// a channel for the subscriber to receive on. -func (s *statsCollector) collect(c *Container) chan interface{} { - return nil -} - -// stopCollection closes the channels for all subscribers and removes -// the container from metrics collection. -func (s *statsCollector) stopCollection(c *Container) { -} - -// unsubscribe removes a specific subscriber from receiving updates for a container's stats. -func (s *statsCollector) unsubscribe(c *Container, ch chan interface{}) { -} diff --git a/vendor/github.com/docker/docker/daemon/stats_freebsd.go b/vendor/github.com/docker/docker/daemon/stats_freebsd.go deleted file mode 100644 index 1898ca9d..00000000 --- a/vendor/github.com/docker/docker/daemon/stats_freebsd.go +++ /dev/null @@ -1,14 +0,0 @@ -package daemon - -import ( - "github.com/docker/docker/api/types" - "github.com/opencontainers/runc/libcontainer" -) - -// convertStatsToAPITypes converts the libcontainer.Stats to the api specific -// structs. This is done to preserve API compatibility and versioning. -func convertStatsToAPITypes(ls *libcontainer.Stats) *types.StatsJSON { - // TODO FreeBSD. Refactor accordingly to fill in stats. - s := &types.StatsJSON{} - return s -} diff --git a/vendor/github.com/docker/docker/daemon/stats_linux.go b/vendor/github.com/docker/docker/daemon/stats_linux.go deleted file mode 100644 index 466f2df5..00000000 --- a/vendor/github.com/docker/docker/daemon/stats_linux.go +++ /dev/null @@ -1,80 +0,0 @@ -package daemon - -import ( - "github.com/docker/docker/api/types" - "github.com/opencontainers/runc/libcontainer" - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -// convertStatsToAPITypes converts the libcontainer.Stats to the api specific -// structs. This is done to preserve API compatibility and versioning. -func convertStatsToAPITypes(ls *libcontainer.Stats) *types.StatsJSON { - s := &types.StatsJSON{} - if ls.Interfaces != nil { - s.Networks = make(map[string]types.NetworkStats) - for _, iface := range ls.Interfaces { - // For API Version >= 1.21, the original data of network will - // be returned. - s.Networks[iface.Name] = types.NetworkStats{ - RxBytes: iface.RxBytes, - RxPackets: iface.RxPackets, - RxErrors: iface.RxErrors, - RxDropped: iface.RxDropped, - TxBytes: iface.TxBytes, - TxPackets: iface.TxPackets, - TxErrors: iface.TxErrors, - TxDropped: iface.TxDropped, - } - } - } - - cs := ls.CgroupStats - if cs != nil { - s.BlkioStats = types.BlkioStats{ - IoServiceBytesRecursive: copyBlkioEntry(cs.BlkioStats.IoServiceBytesRecursive), - IoServicedRecursive: copyBlkioEntry(cs.BlkioStats.IoServicedRecursive), - IoQueuedRecursive: copyBlkioEntry(cs.BlkioStats.IoQueuedRecursive), - IoServiceTimeRecursive: copyBlkioEntry(cs.BlkioStats.IoServiceTimeRecursive), - IoWaitTimeRecursive: copyBlkioEntry(cs.BlkioStats.IoWaitTimeRecursive), - IoMergedRecursive: copyBlkioEntry(cs.BlkioStats.IoMergedRecursive), - IoTimeRecursive: copyBlkioEntry(cs.BlkioStats.IoTimeRecursive), - SectorsRecursive: copyBlkioEntry(cs.BlkioStats.SectorsRecursive), - } - cpu := cs.CpuStats - s.CPUStats = types.CPUStats{ - CPUUsage: types.CPUUsage{ - TotalUsage: cpu.CpuUsage.TotalUsage, - PercpuUsage: cpu.CpuUsage.PercpuUsage, - UsageInKernelmode: cpu.CpuUsage.UsageInKernelmode, - UsageInUsermode: cpu.CpuUsage.UsageInUsermode, - }, - ThrottlingData: types.ThrottlingData{ - Periods: cpu.ThrottlingData.Periods, - ThrottledPeriods: cpu.ThrottlingData.ThrottledPeriods, - ThrottledTime: cpu.ThrottlingData.ThrottledTime, - }, - } - mem := cs.MemoryStats - s.MemoryStats = types.MemoryStats{ - Usage: mem.Usage.Usage, - MaxUsage: mem.Usage.MaxUsage, - Stats: mem.Stats, - Failcnt: mem.Usage.Failcnt, - } - } - - return s -} - -func copyBlkioEntry(entries []cgroups.BlkioStatEntry) []types.BlkioStatEntry { - out := make([]types.BlkioStatEntry, len(entries)) - for i, re := range entries { - out[i] = types.BlkioStatEntry{ - Major: re.Major, - Minor: re.Minor, - Op: re.Op, - Value: re.Value, - } - } - return out -} diff --git a/vendor/github.com/docker/docker/daemon/stats_windows.go b/vendor/github.com/docker/docker/daemon/stats_windows.go deleted file mode 100644 index fc8991ba..00000000 --- a/vendor/github.com/docker/docker/daemon/stats_windows.go +++ /dev/null @@ -1,14 +0,0 @@ -package daemon - -import ( - "github.com/docker/docker/api/types" - "github.com/opencontainers/runc/libcontainer" -) - -// convertStatsToAPITypes converts the libcontainer.Stats to the api specific -// structs. This is done to preserve API compatibility and versioning. -func convertStatsToAPITypes(ls *libcontainer.Stats) *types.StatsJSON { - // TODO Windows. Refactor accordingly to fill in stats. - s := &types.StatsJSON{} - return s -} diff --git a/vendor/github.com/docker/docker/daemon/stop.go b/vendor/github.com/docker/docker/daemon/stop.go deleted file mode 100644 index c97781b8..00000000 --- a/vendor/github.com/docker/docker/daemon/stop.go +++ /dev/null @@ -1,60 +0,0 @@ -package daemon - -import ( - "time" - - "github.com/Sirupsen/logrus" - derr "github.com/docker/docker/errors" -) - -// ContainerStop looks for the given container and terminates it, -// waiting the given number of seconds before forcefully killing the -// container. If a negative number of seconds is given, ContainerStop -// will wait for a graceful termination. An error is returned if the -// container is not found, is already stopped, or if there is a -// problem stopping the container. -func (daemon *Daemon) ContainerStop(name string, seconds int) error { - container, err := daemon.Get(name) - if err != nil { - return err - } - if !container.IsRunning() { - return derr.ErrorCodeStopped - } - if err := daemon.containerStop(container, seconds); err != nil { - return derr.ErrorCodeCantStop.WithArgs(name, err) - } - return nil -} - -// containerStop halts a container by sending a stop signal, waiting for the given -// duration in seconds, and then calling SIGKILL and waiting for the -// process to exit. If a negative duration is given, Stop will wait -// for the initial signal forever. If the container is not running Stop returns -// immediately. -func (daemon *Daemon) containerStop(container *Container, seconds int) error { - if !container.IsRunning() { - return nil - } - - // 1. Send a SIGTERM - if err := daemon.killPossiblyDeadProcess(container, container.stopSignal()); err != nil { - logrus.Infof("Failed to send SIGTERM to the process, force killing") - if err := daemon.killPossiblyDeadProcess(container, 9); err != nil { - return err - } - } - - // 2. Wait for the process to exit on its own - if _, err := container.WaitStop(time.Duration(seconds) * time.Second); err != nil { - logrus.Infof("Container %v failed to exit within %d seconds of SIGTERM - using the force", container.ID, seconds) - // 3. If it doesn't, then send SIGKILL - if err := daemon.Kill(container); err != nil { - container.WaitStop(-1 * time.Second) - logrus.Warn(err) // Don't return error because we only care that container is stopped, not what function stopped it - } - } - - daemon.LogContainerEvent(container, "stop") - return nil -} diff --git a/vendor/github.com/docker/docker/daemon/top_unix.go b/vendor/github.com/docker/docker/daemon/top_unix.go deleted file mode 100644 index 36ace121..00000000 --- a/vendor/github.com/docker/docker/daemon/top_unix.go +++ /dev/null @@ -1,81 +0,0 @@ -//+build !windows - -package daemon - -import ( - "os/exec" - "strconv" - "strings" - - "github.com/docker/docker/api/types" - derr "github.com/docker/docker/errors" -) - -// ContainerTop lists the processes running inside of the given -// container by calling ps with the given args, or with the flags -// "-ef" if no args are given. An error is returned if the container -// is not found, or is not running, or if there are any problems -// running ps, or parsing the output. -func (daemon *Daemon) ContainerTop(name string, psArgs string) (*types.ContainerProcessList, error) { - if psArgs == "" { - psArgs = "-ef" - } - - container, err := daemon.Get(name) - if err != nil { - return nil, err - } - - if !container.IsRunning() { - return nil, derr.ErrorCodeNotRunning.WithArgs(name) - } - - pids, err := daemon.ExecutionDriver().GetPidsForContainer(container.ID) - if err != nil { - return nil, err - } - - output, err := exec.Command("ps", strings.Split(psArgs, " ")...).Output() - if err != nil { - return nil, derr.ErrorCodePSError.WithArgs(err) - } - - procList := &types.ContainerProcessList{} - - lines := strings.Split(string(output), "\n") - procList.Titles = strings.Fields(lines[0]) - - pidIndex := -1 - for i, name := range procList.Titles { - if name == "PID" { - pidIndex = i - } - } - if pidIndex == -1 { - return nil, derr.ErrorCodeNoPID - } - - // loop through the output and extract the PID from each line - for _, line := range lines[1:] { - if len(line) == 0 { - continue - } - fields := strings.Fields(line) - p, err := strconv.Atoi(fields[pidIndex]) - if err != nil { - return nil, derr.ErrorCodeBadPID.WithArgs(fields[pidIndex], err) - } - - for _, pid := range pids { - if pid == p { - // Make sure number of fields equals number of header titles - // merging "overhanging" fields - process := fields[:len(procList.Titles)-1] - process = append(process, strings.Join(fields[len(procList.Titles)-1:], " ")) - procList.Processes = append(procList.Processes, process) - } - } - } - daemon.LogContainerEvent(container, "top") - return procList, nil -} diff --git a/vendor/github.com/docker/docker/daemon/top_windows.go b/vendor/github.com/docker/docker/daemon/top_windows.go deleted file mode 100644 index f224b2e2..00000000 --- a/vendor/github.com/docker/docker/daemon/top_windows.go +++ /dev/null @@ -1,11 +0,0 @@ -package daemon - -import ( - "github.com/docker/docker/api/types" - derr "github.com/docker/docker/errors" -) - -// ContainerTop is not supported on Windows and returns an error. -func (daemon *Daemon) ContainerTop(name string, psArgs string) (*types.ContainerProcessList, error) { - return nil, derr.ErrorCodeNoTop -} diff --git a/vendor/github.com/docker/docker/daemon/unpause.go b/vendor/github.com/docker/docker/daemon/unpause.go deleted file mode 100644 index 3397f44b..00000000 --- a/vendor/github.com/docker/docker/daemon/unpause.go +++ /dev/null @@ -1,43 +0,0 @@ -package daemon - -import ( - derr "github.com/docker/docker/errors" -) - -// ContainerUnpause unpauses a container -func (daemon *Daemon) ContainerUnpause(name string) error { - container, err := daemon.Get(name) - if err != nil { - return err - } - - if err := daemon.containerUnpause(container); err != nil { - return derr.ErrorCodeCantUnpause.WithArgs(name, err) - } - - return nil -} - -// containerUnpause resumes the container execution after the container is paused. -func (daemon *Daemon) containerUnpause(container *Container) error { - container.Lock() - defer container.Unlock() - - // We cannot unpause the container which is not running - if !container.Running { - return derr.ErrorCodeNotRunning.WithArgs(container.ID) - } - - // We cannot unpause the container which is not paused - if !container.Paused { - return derr.ErrorCodeNotPaused.WithArgs(container.ID) - } - - if err := daemon.execDriver.Unpause(container.command); err != nil { - return err - } - - container.Paused = false - daemon.LogContainerEvent(container, "unpause") - return nil -} diff --git a/vendor/github.com/docker/docker/daemon/utils_linux.go b/vendor/github.com/docker/docker/daemon/utils_linux.go deleted file mode 100644 index 83a34471..00000000 --- a/vendor/github.com/docker/docker/daemon/utils_linux.go +++ /dev/null @@ -1,17 +0,0 @@ -// +build linux - -package daemon - -import "github.com/opencontainers/runc/libcontainer/selinux" - -func selinuxSetDisabled() { - selinux.SetDisabled() -} - -func selinuxFreeLxcContexts(label string) { - selinux.FreeLxcContexts(label) -} - -func selinuxEnabled() bool { - return selinux.SelinuxEnabled() -} diff --git a/vendor/github.com/docker/docker/daemon/utils_nounix.go b/vendor/github.com/docker/docker/daemon/utils_nounix.go deleted file mode 100644 index 25a56ad1..00000000 --- a/vendor/github.com/docker/docker/daemon/utils_nounix.go +++ /dev/null @@ -1,13 +0,0 @@ -// +build !linux - -package daemon - -func selinuxSetDisabled() { -} - -func selinuxFreeLxcContexts(label string) { -} - -func selinuxEnabled() bool { - return false -} diff --git a/vendor/github.com/docker/docker/daemon/volumes.go b/vendor/github.com/docker/docker/daemon/volumes.go deleted file mode 100644 index cca88983..00000000 --- a/vendor/github.com/docker/docker/daemon/volumes.go +++ /dev/null @@ -1,155 +0,0 @@ -package daemon - -import ( - "errors" - "os" - "path/filepath" - "strings" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/daemon/execdriver" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/runconfig" - "github.com/docker/docker/volume" - "github.com/opencontainers/runc/libcontainer/label" -) - -var ( - // ErrVolumeReadonly is used to signal an error when trying to copy data into - // a volume mount that is not writable. - ErrVolumeReadonly = errors.New("mounted volume is marked read-only") -) - -type mounts []execdriver.Mount - -// volumeToAPIType converts a volume.Volume to the type used by the remote API -func volumeToAPIType(v volume.Volume) *types.Volume { - return &types.Volume{ - Name: v.Name(), - Driver: v.DriverName(), - Mountpoint: v.Path(), - } -} - -// createVolume creates a volume. -func (daemon *Daemon) createVolume(name, driverName string, opts map[string]string) (volume.Volume, error) { - v, err := daemon.volumes.Create(name, driverName, opts) - if err != nil { - return nil, err - } - daemon.volumes.Increment(v) - return v, nil -} - -// Len returns the number of mounts. Used in sorting. -func (m mounts) Len() int { - return len(m) -} - -// Less returns true if the number of parts (a/b/c would be 3 parts) in the -// mount indexed by parameter 1 is less than that of the mount indexed by -// parameter 2. Used in sorting. -func (m mounts) Less(i, j int) bool { - return m.parts(i) < m.parts(j) -} - -// Swap swaps two items in an array of mounts. Used in sorting -func (m mounts) Swap(i, j int) { - m[i], m[j] = m[j], m[i] -} - -// parts returns the number of parts in the destination of a mount. Used in sorting. -func (m mounts) parts(i int) int { - return strings.Count(filepath.Clean(m[i].Destination), string(os.PathSeparator)) -} - -// registerMountPoints initializes the container mount points with the configured volumes and bind mounts. -// It follows the next sequence to decide what to mount in each final destination: -// -// 1. Select the previously configured mount points for the containers, if any. -// 2. Select the volumes mounted from another containers. Overrides previously configured mount point destination. -// 3. Select the bind mounts set by the client. Overrides previously configured mount point destinations. -func (daemon *Daemon) registerMountPoints(container *Container, hostConfig *runconfig.HostConfig) error { - binds := map[string]bool{} - mountPoints := map[string]*volume.MountPoint{} - - // 1. Read already configured mount points. - for name, point := range container.MountPoints { - mountPoints[name] = point - } - - // 2. Read volumes from other containers. - for _, v := range hostConfig.VolumesFrom { - containerID, mode, err := volume.ParseVolumesFrom(v) - if err != nil { - return err - } - - c, err := daemon.Get(containerID) - if err != nil { - return err - } - - for _, m := range c.MountPoints { - cp := &volume.MountPoint{ - Name: m.Name, - Source: m.Source, - RW: m.RW && volume.ReadWrite(mode), - Driver: m.Driver, - Destination: m.Destination, - } - - if len(cp.Source) == 0 { - v, err := daemon.createVolume(cp.Name, cp.Driver, nil) - if err != nil { - return err - } - cp.Volume = v - } - - mountPoints[cp.Destination] = cp - } - } - - // 3. Read bind mounts - for _, b := range hostConfig.Binds { - // #10618 - bind, err := volume.ParseMountSpec(b, hostConfig.VolumeDriver) - if err != nil { - return err - } - - if binds[bind.Destination] { - return derr.ErrorCodeVolumeDup.WithArgs(bind.Destination) - } - - if len(bind.Name) > 0 && len(bind.Driver) > 0 { - // create the volume - v, err := daemon.createVolume(bind.Name, bind.Driver, nil) - if err != nil { - return err - } - bind.Volume = v - bind.Source = v.Path() - // bind.Name is an already existing volume, we need to use that here - bind.Driver = v.DriverName() - bind = setBindModeIfNull(bind) - } - shared := label.IsShared(bind.Mode) - if err := label.Relabel(bind.Source, container.MountLabel, shared); err != nil { - return err - } - binds[bind.Destination] = true - mountPoints[bind.Destination] = bind - } - - bcVolumes, bcVolumesRW := configureBackCompatStructures(daemon, container, mountPoints) - - container.Lock() - container.MountPoints = mountPoints - setBackCompatStructures(container, bcVolumes, bcVolumesRW) - - container.Unlock() - - return nil -} diff --git a/vendor/github.com/docker/docker/daemon/volumes_unit_test.go b/vendor/github.com/docker/docker/daemon/volumes_unit_test.go deleted file mode 100644 index dadf24e1..00000000 --- a/vendor/github.com/docker/docker/daemon/volumes_unit_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package daemon - -import ( - "github.com/docker/docker/volume" - "testing" -) - -func TestParseVolumesFrom(t *testing.T) { - cases := []struct { - spec string - expID string - expMode string - fail bool - }{ - {"", "", "", true}, - {"foobar", "foobar", "rw", false}, - {"foobar:rw", "foobar", "rw", false}, - {"foobar:ro", "foobar", "ro", false}, - {"foobar:baz", "", "", true}, - } - - for _, c := range cases { - id, mode, err := volume.ParseVolumesFrom(c.spec) - if c.fail { - if err == nil { - t.Fatalf("Expected error, was nil, for spec %s\n", c.spec) - } - continue - } - - if id != c.expID { - t.Fatalf("Expected id %s, was %s, for spec %s\n", c.expID, id, c.spec) - } - if mode != c.expMode { - t.Fatalf("Expected mode %s, was %s for spec %s\n", c.expMode, mode, c.spec) - } - } -} diff --git a/vendor/github.com/docker/docker/daemon/volumes_unix.go b/vendor/github.com/docker/docker/daemon/volumes_unix.go deleted file mode 100644 index a7ac9911..00000000 --- a/vendor/github.com/docker/docker/daemon/volumes_unix.go +++ /dev/null @@ -1,252 +0,0 @@ -// +build !windows - -package daemon - -import ( - "io/ioutil" - "os" - "path/filepath" - "sort" - "strings" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/daemon/execdriver" - "github.com/docker/docker/pkg/chrootarchive" - "github.com/docker/docker/pkg/system" - "github.com/docker/docker/volume" - volumedrivers "github.com/docker/docker/volume/drivers" - "github.com/docker/docker/volume/local" -) - -// copyExistingContents copies from the source to the destination and -// ensures the ownership is appropriately set. -func copyExistingContents(source, destination string) error { - volList, err := ioutil.ReadDir(source) - if err != nil { - return err - } - if len(volList) > 0 { - srcList, err := ioutil.ReadDir(destination) - if err != nil { - return err - } - if len(srcList) == 0 { - // If the source volume is empty copy files from the root into the volume - if err := chrootarchive.CopyWithTar(source, destination); err != nil { - return err - } - } - } - return copyOwnership(source, destination) -} - -// copyOwnership copies the permissions and uid:gid of the source file -// to the destination file -func copyOwnership(source, destination string) error { - stat, err := system.Stat(source) - if err != nil { - return err - } - - if err := os.Chown(destination, int(stat.UID()), int(stat.GID())); err != nil { - return err - } - - return os.Chmod(destination, os.FileMode(stat.Mode())) -} - -// setupMounts iterates through each of the mount points for a container and -// calls Setup() on each. It also looks to see if is a network mount such as -// /etc/resolv.conf, and if it is not, appends it to the array of mounts. -func (daemon *Daemon) setupMounts(container *Container) ([]execdriver.Mount, error) { - var mounts []execdriver.Mount - for _, m := range container.MountPoints { - path, err := m.Setup() - if err != nil { - return nil, err - } - if !container.trySetNetworkMount(m.Destination, path) { - mounts = append(mounts, execdriver.Mount{ - Source: path, - Destination: m.Destination, - Writable: m.RW, - }) - } - } - - mounts = sortMounts(mounts) - netMounts := container.networkMounts() - // if we are going to mount any of the network files from container - // metadata, the ownership must be set properly for potential container - // remapped root (user namespaces) - rootUID, rootGID := daemon.GetRemappedUIDGID() - for _, mount := range netMounts { - if err := os.Chown(mount.Source, rootUID, rootGID); err != nil { - return nil, err - } - } - return append(mounts, netMounts...), nil -} - -// sortMounts sorts an array of mounts in lexicographic order. This ensure that -// when mounting, the mounts don't shadow other mounts. For example, if mounting -// /etc and /etc/resolv.conf, /etc/resolv.conf must not be mounted first. -func sortMounts(m []execdriver.Mount) []execdriver.Mount { - sort.Sort(mounts(m)) - return m -} - -// migrateVolume links the contents of a volume created pre Docker 1.7 -// into the location expected by the local driver. -// It creates a symlink from DOCKER_ROOT/vfs/dir/VOLUME_ID to DOCKER_ROOT/volumes/VOLUME_ID/_container_data. -// It preserves the volume json configuration generated pre Docker 1.7 to be able to -// downgrade from Docker 1.7 to Docker 1.6 without losing volume compatibility. -func migrateVolume(id, vfs string) error { - l, err := volumedrivers.Lookup(volume.DefaultDriverName) - if err != nil { - return err - } - - newDataPath := l.(*local.Root).DataPath(id) - fi, err := os.Stat(newDataPath) - if err != nil && !os.IsNotExist(err) { - return err - } - - if fi != nil && fi.IsDir() { - return nil - } - - return os.Symlink(vfs, newDataPath) -} - -// validVolumeLayout checks whether the volume directory layout -// is valid to work with Docker post 1.7 or not. -func validVolumeLayout(files []os.FileInfo) bool { - if len(files) == 1 && files[0].Name() == local.VolumeDataPathName && files[0].IsDir() { - return true - } - - if len(files) != 2 { - return false - } - - for _, f := range files { - if f.Name() == "config.json" || - (f.Name() == local.VolumeDataPathName && f.Mode()&os.ModeSymlink == os.ModeSymlink) { - // Old volume configuration, we ignore it - continue - } - return false - } - - return true -} - -// verifyVolumesInfo ports volumes configured for the containers pre docker 1.7. -// It reads the container configuration and creates valid mount points for the old volumes. -func (daemon *Daemon) verifyVolumesInfo(container *Container) error { - // Inspect old structures only when we're upgrading from old versions - // to versions >= 1.7 and the MountPoints has not been populated with volumes data. - if len(container.MountPoints) == 0 && len(container.Volumes) > 0 { - for destination, hostPath := range container.Volumes { - vfsPath := filepath.Join(daemon.root, "vfs", "dir") - rw := container.VolumesRW != nil && container.VolumesRW[destination] - - if strings.HasPrefix(hostPath, vfsPath) { - id := filepath.Base(hostPath) - if err := migrateVolume(id, hostPath); err != nil { - return err - } - container.addLocalMountPoint(id, destination, rw) - } else { // Bind mount - id, source := volume.ParseVolumeSource(hostPath) - container.addBindMountPoint(id, source, destination, rw) - } - } - } else if len(container.MountPoints) > 0 { - // Volumes created with a Docker version >= 1.7. We verify integrity in case of data created - // with Docker 1.7 RC versions that put the information in - // DOCKER_ROOT/volumes/VOLUME_ID rather than DOCKER_ROOT/volumes/VOLUME_ID/_container_data. - l, err := volumedrivers.Lookup(volume.DefaultDriverName) - if err != nil { - return err - } - - for _, m := range container.MountPoints { - if m.Driver != volume.DefaultDriverName { - continue - } - dataPath := l.(*local.Root).DataPath(m.Name) - volumePath := filepath.Dir(dataPath) - - d, err := ioutil.ReadDir(volumePath) - if err != nil { - // If the volume directory doesn't exist yet it will be recreated, - // so we only return the error when there is a different issue. - if !os.IsNotExist(err) { - return err - } - // Do not check when the volume directory does not exist. - continue - } - if validVolumeLayout(d) { - continue - } - - if err := os.Mkdir(dataPath, 0755); err != nil { - return err - } - - // Move data inside the data directory - for _, f := range d { - oldp := filepath.Join(volumePath, f.Name()) - newp := filepath.Join(dataPath, f.Name()) - if err := os.Rename(oldp, newp); err != nil { - logrus.Errorf("Unable to move %s to %s\n", oldp, newp) - } - } - } - - return container.toDiskLocking() - } - - return nil -} - -// setBindModeIfNull is platform specific processing to ensure the -// shared mode is set to 'z' if it is null. This is called in the case -// of processing a named volume and not a typical bind. -func setBindModeIfNull(bind *volume.MountPoint) *volume.MountPoint { - if bind.Mode == "" { - bind.Mode = "z" - } - return bind -} - -// configureBackCompatStructures is platform specific processing for -// registering mount points to populate old structures. -func configureBackCompatStructures(daemon *Daemon, container *Container, mountPoints map[string]*volume.MountPoint) (map[string]string, map[string]bool) { - // Keep backwards compatible structures - bcVolumes := map[string]string{} - bcVolumesRW := map[string]bool{} - for _, m := range mountPoints { - if m.BackwardsCompatible() { - bcVolumes[m.Destination] = m.Path() - bcVolumesRW[m.Destination] = m.RW - - // This mountpoint is replacing an existing one, so the count needs to be decremented - if mp, exists := container.MountPoints[m.Destination]; exists && mp.Volume != nil { - daemon.volumes.Decrement(mp.Volume) - } - } - } - return bcVolumes, bcVolumesRW -} - -// setBackCompatStructures is a platform specific helper function to set -// backwards compatible structures in the container when registering volumes. -func setBackCompatStructures(container *Container, bcVolumes map[string]string, bcVolumesRW map[string]bool) { - container.Volumes = bcVolumes - container.VolumesRW = bcVolumesRW -} diff --git a/vendor/github.com/docker/docker/daemon/volumes_windows.go b/vendor/github.com/docker/docker/daemon/volumes_windows.go deleted file mode 100644 index 73ec1719..00000000 --- a/vendor/github.com/docker/docker/daemon/volumes_windows.go +++ /dev/null @@ -1,61 +0,0 @@ -// +build windows - -package daemon - -import ( - "sort" - - "github.com/docker/docker/daemon/execdriver" - derr "github.com/docker/docker/errors" - "github.com/docker/docker/volume" -) - -// setupMounts configures the mount points for a container by appending each -// of the configured mounts on the container to the execdriver mount structure -// which will ultimately be passed into the exec driver during container creation. -// It also ensures each of the mounts are lexographically sorted. -func (daemon *Daemon) setupMounts(container *Container) ([]execdriver.Mount, error) { - var mnts []execdriver.Mount - for _, mount := range container.MountPoints { // type is volume.MountPoint - // If there is no source, take it from the volume path - s := mount.Source - if s == "" && mount.Volume != nil { - s = mount.Volume.Path() - } - if s == "" { - return nil, derr.ErrorCodeVolumeNoSourceForMount.WithArgs(mount.Name, mount.Driver, mount.Destination) - } - mnts = append(mnts, execdriver.Mount{ - Source: s, - Destination: mount.Destination, - Writable: mount.RW, - }) - } - - sort.Sort(mounts(mnts)) - return mnts, nil -} - -// verifyVolumesInfo ports volumes configured for the containers pre docker 1.7. -// As the Windows daemon was not supported before 1.7, this is a no-op -func (daemon *Daemon) verifyVolumesInfo(container *Container) error { - return nil -} - -// setBindModeIfNull is platform specific processing which is a no-op on -// Windows. -func setBindModeIfNull(bind *volume.MountPoint) *volume.MountPoint { - return bind -} - -// configureBackCompatStructures is platform specific processing for -// registering mount points to populate old structures. This is a no-op on Windows. -func configureBackCompatStructures(*Daemon, *Container, map[string]*volume.MountPoint) (map[string]string, map[string]bool) { - return nil, nil -} - -// setBackCompatStructures is a platform specific helper function to set -// backwards compatible structures in the container when registering volumes. -// This is a no-op on Windows. -func setBackCompatStructures(*Container, map[string]string, map[string]bool) { -} diff --git a/vendor/github.com/docker/docker/daemon/wait.go b/vendor/github.com/docker/docker/daemon/wait.go deleted file mode 100644 index e429c460..00000000 --- a/vendor/github.com/docker/docker/daemon/wait.go +++ /dev/null @@ -1,17 +0,0 @@ -package daemon - -import "time" - -// ContainerWait stops processing until the given container is -// stopped. If the container is not found, an error is returned. On a -// successful stop, the exit code of the container is returned. On a -// timeout, an error is returned. If you want to wait forever, supply -// a negative duration for the timeout. -func (daemon *Daemon) ContainerWait(name string, timeout time.Duration) (int, error) { - container, err := daemon.Get(name) - if err != nil { - return -1, err - } - - return container.WaitStop(timeout) -} diff --git a/vendor/github.com/docker/docker/graph/export.go b/vendor/github.com/docker/docker/graph/export.go deleted file mode 100644 index 3a47f318..00000000 --- a/vendor/github.com/docker/docker/graph/export.go +++ /dev/null @@ -1,180 +0,0 @@ -package graph - -import ( - "encoding/json" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/distribution/digest" - "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/parsers" - "github.com/docker/docker/registry" -) - -// ImageExport exports list of images to a output stream specified in the -// config. The exported images are archived into a tar when written to the -// output stream. All images with the given tag and all versions containing the -// same tag are exported. names is the set of tags to export, and outStream -// is the writer which the images are written to. -func (s *TagStore) ImageExport(names []string, outStream io.Writer) error { - // get image json - tempdir, err := ioutil.TempDir("", "docker-export-") - if err != nil { - return err - } - defer os.RemoveAll(tempdir) - - rootRepoMap := map[string]repository{} - addKey := func(name string, tag string, id string) { - logrus.Debugf("add key [%s:%s]", name, tag) - if repo, ok := rootRepoMap[name]; !ok { - rootRepoMap[name] = repository{tag: id} - } else { - repo[tag] = id - } - } - for _, name := range names { - name = registry.NormalizeLocalName(name) - logrus.Debugf("Serializing %s", name) - rootRepo := s.Repositories[name] - if rootRepo != nil { - // this is a base repo name, like 'busybox' - for tag, id := range rootRepo { - addKey(name, tag, id) - if err := s.exportImage(id, tempdir); err != nil { - return err - } - } - } else { - img, err := s.LookupImage(name) - if err != nil { - return err - } - - if img != nil { - // This is a named image like 'busybox:latest' - repoName, repoTag := parsers.ParseRepositoryTag(name) - - // Skip digests on save - if _, err := digest.ParseDigest(repoTag); err == nil { - repoTag = "" - } - - // check this length, because a lookup of a truncated has will not have a tag - // and will not need to be added to this map - if len(repoTag) > 0 { - addKey(repoName, repoTag, img.ID) - } - if err := s.exportImage(img.ID, tempdir); err != nil { - return err - } - - } else { - // this must be an ID that didn't get looked up just right? - if err := s.exportImage(name, tempdir); err != nil { - return err - } - } - } - logrus.Debugf("End Serializing %s", name) - } - // write repositories, if there is something to write - if len(rootRepoMap) > 0 { - f, err := os.OpenFile(filepath.Join(tempdir, "repositories"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) - if err != nil { - f.Close() - return err - } - if err := json.NewEncoder(f).Encode(rootRepoMap); err != nil { - return err - } - if err := f.Close(); err != nil { - return err - } - if err := os.Chtimes(filepath.Join(tempdir, "repositories"), time.Unix(0, 0), time.Unix(0, 0)); err != nil { - return err - } - } else { - logrus.Debugf("There were no repositories to write") - } - - fs, err := archive.Tar(tempdir, archive.Uncompressed) - if err != nil { - return err - } - defer fs.Close() - - if _, err := io.Copy(outStream, fs); err != nil { - return err - } - logrus.Debugf("End export image") - return nil -} - -func (s *TagStore) exportImage(name, tempdir string) error { - for n := name; n != ""; { - img, err := s.LookupImage(n) - if err != nil || img == nil { - return fmt.Errorf("No such image %s", n) - } - - // temporary directory - tmpImageDir := filepath.Join(tempdir, n) - if err := os.Mkdir(tmpImageDir, os.FileMode(0755)); err != nil { - if os.IsExist(err) { - return nil - } - return err - } - - var version = "1.0" - var versionBuf = []byte(version) - - if err := ioutil.WriteFile(filepath.Join(tmpImageDir, "VERSION"), versionBuf, os.FileMode(0644)); err != nil { - return err - } - - imageInspectRaw, err := json.Marshal(img) - if err != nil { - return err - } - - // serialize json - json, err := os.Create(filepath.Join(tmpImageDir, "json")) - if err != nil { - return err - } - - written, err := json.Write(imageInspectRaw) - if err != nil { - return err - } - if written != len(imageInspectRaw) { - logrus.Warnf("%d byes should have been written instead %d have been written", written, len(imageInspectRaw)) - } - - // serialize filesystem - fsTar, err := os.Create(filepath.Join(tmpImageDir, "layer.tar")) - if err != nil { - return err - } - if err := s.imageTarLayer(n, fsTar); err != nil { - return err - } - - for _, fname := range []string{"", "VERSION", "json", "layer.tar"} { - if err := os.Chtimes(filepath.Join(tmpImageDir, fname), img.Created, img.Created); err != nil { - return err - } - } - - // try again with parent - n = img.Parent - } - return nil -} diff --git a/vendor/github.com/docker/docker/graph/graph.go b/vendor/github.com/docker/docker/graph/graph.go deleted file mode 100644 index fed2ee02..00000000 --- a/vendor/github.com/docker/docker/graph/graph.go +++ /dev/null @@ -1,815 +0,0 @@ -package graph - -import ( - "compress/gzip" - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "runtime" - "strconv" - "strings" - "sync" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/distribution/digest" - "github.com/docker/docker/daemon/graphdriver" - "github.com/docker/docker/dockerversion" - "github.com/docker/docker/image" - "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/idtools" - "github.com/docker/docker/pkg/locker" - "github.com/docker/docker/pkg/progressreader" - "github.com/docker/docker/pkg/streamformatter" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/pkg/truncindex" - "github.com/docker/docker/runconfig" - "github.com/vbatts/tar-split/tar/asm" - "github.com/vbatts/tar-split/tar/storage" -) - -// v1Descriptor is a non-content-addressable image descriptor -type v1Descriptor struct { - img *image.Image -} - -// ID returns the image ID specified in the image structure. -func (img v1Descriptor) ID() string { - return img.img.ID -} - -// Parent returns the parent ID specified in the image structure. -func (img v1Descriptor) Parent() string { - return img.img.Parent -} - -// MarshalConfig renders the image structure into JSON. -func (img v1Descriptor) MarshalConfig() ([]byte, error) { - return json.Marshal(img.img) -} - -// The type is used to protect pulling or building related image -// layers from deleteing when filtered by dangling=true -// The key of layers is the images ID which is pulling or building -// The value of layers is a slice which hold layer IDs referenced to -// pulling or building images -type retainedLayers struct { - layerHolders map[string]map[string]struct{} // map[layerID]map[sessionID] - sync.Mutex -} - -func (r *retainedLayers) Add(sessionID string, layerIDs []string) { - r.Lock() - defer r.Unlock() - for _, layerID := range layerIDs { - if r.layerHolders[layerID] == nil { - r.layerHolders[layerID] = map[string]struct{}{} - } - r.layerHolders[layerID][sessionID] = struct{}{} - } -} - -func (r *retainedLayers) Delete(sessionID string, layerIDs []string) { - r.Lock() - defer r.Unlock() - for _, layerID := range layerIDs { - holders, ok := r.layerHolders[layerID] - if !ok { - continue - } - delete(holders, sessionID) - if len(holders) == 0 { - delete(r.layerHolders, layerID) // Delete any empty reference set. - } - } -} - -func (r *retainedLayers) Exists(layerID string) bool { - r.Lock() - _, exists := r.layerHolders[layerID] - r.Unlock() - return exists -} - -// A Graph is a store for versioned filesystem images and the relationship between them. -type Graph struct { - root string - idIndex *truncindex.TruncIndex - driver graphdriver.Driver - imagesMutex sync.Mutex - imageMutex locker.Locker // protect images in driver. - retained *retainedLayers - tarSplitDisabled bool - uidMaps []idtools.IDMap - gidMaps []idtools.IDMap - - // access to parentRefs must be protected with imageMutex locking the image id - // on the key of the map (e.g. imageMutex.Lock(img.ID), parentRefs[img.ID]...) - parentRefs map[string]int -} - -// file names for ./graph// -const ( - jsonFileName = "json" - layersizeFileName = "layersize" - digestFileName = "checksum" - tarDataFileName = "tar-data.json.gz" - v1CompatibilityFileName = "v1Compatibility" - parentFileName = "parent" -) - -var ( - // errDigestNotSet is used when request the digest for a layer - // but the layer has no digest value or content to compute the - // the digest. - errDigestNotSet = errors.New("digest is not set for layer") -) - -// NewGraph instantiates a new graph at the given root path in the filesystem. -// `root` will be created if it doesn't exist. -func NewGraph(root string, driver graphdriver.Driver, uidMaps, gidMaps []idtools.IDMap) (*Graph, error) { - abspath, err := filepath.Abs(root) - if err != nil { - return nil, err - } - - rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) - if err != nil { - return nil, err - } - // Create the root directory if it doesn't exists - if err := idtools.MkdirAllAs(root, 0700, rootUID, rootGID); err != nil && !os.IsExist(err) { - return nil, err - } - - graph := &Graph{ - root: abspath, - idIndex: truncindex.NewTruncIndex([]string{}), - driver: driver, - retained: &retainedLayers{layerHolders: make(map[string]map[string]struct{})}, - uidMaps: uidMaps, - gidMaps: gidMaps, - parentRefs: make(map[string]int), - } - - // Windows does not currently support tarsplit functionality. - if runtime.GOOS == "windows" { - graph.tarSplitDisabled = true - } - - if err := graph.restore(); err != nil { - return nil, err - } - return graph, nil -} - -// IsHeld returns whether the given layerID is being used by an ongoing pull or build. -func (graph *Graph) IsHeld(layerID string) bool { - return graph.retained.Exists(layerID) -} - -func (graph *Graph) restore() error { - dir, err := ioutil.ReadDir(graph.root) - if err != nil { - return err - } - var ids = []string{} - for _, v := range dir { - id := v.Name() - if graph.driver.Exists(id) { - img, err := graph.loadImage(id) - if err != nil { - logrus.Warnf("ignoring image %s, it could not be restored: %v", id, err) - continue - } - graph.imageMutex.Lock(img.Parent) - graph.parentRefs[img.Parent]++ - graph.imageMutex.Unlock(img.Parent) - ids = append(ids, id) - } - } - - graph.idIndex = truncindex.NewTruncIndex(ids) - logrus.Debugf("Restored %d elements", len(ids)) - return nil -} - -// IsNotExist detects whether an image exists by parsing the incoming error -// message. -func (graph *Graph) IsNotExist(err error, id string) bool { - // FIXME: Implement error subclass instead of looking at the error text - // Note: This is the way golang implements os.IsNotExists on Plan9 - return err != nil && (strings.Contains(strings.ToLower(err.Error()), "does not exist") || strings.Contains(strings.ToLower(err.Error()), "no such")) && strings.Contains(err.Error(), id) -} - -// Exists returns true if an image is registered at the given id. -// If the image doesn't exist or if an error is encountered, false is returned. -func (graph *Graph) Exists(id string) bool { - if _, err := graph.Get(id); err != nil { - return false - } - return true -} - -// Get returns the image with the given id, or an error if the image doesn't exist. -func (graph *Graph) Get(name string) (*image.Image, error) { - id, err := graph.idIndex.Get(name) - if err != nil { - if err == truncindex.ErrNotExist { - return nil, fmt.Errorf("image %s does not exist", name) - } - return nil, err - } - img, err := graph.loadImage(id) - if err != nil { - return nil, err - } - if img.ID != id { - return nil, fmt.Errorf("Image stored at '%s' has wrong id '%s'", id, img.ID) - } - - if img.Size < 0 { - size, err := graph.driver.DiffSize(img.ID, img.Parent) - if err != nil { - return nil, fmt.Errorf("unable to calculate size of image id %q: %s", img.ID, err) - } - - img.Size = size - if err := graph.saveSize(graph.imageRoot(id), img.Size); err != nil { - return nil, err - } - } - return img, nil -} - -// Create creates a new image and registers it in the graph. -func (graph *Graph) Create(layerData io.Reader, containerID, containerImage, comment, author string, containerConfig, config *runconfig.Config) (*image.Image, error) { - img := &image.Image{ - ID: stringid.GenerateRandomID(), - Comment: comment, - Created: time.Now().UTC(), - DockerVersion: dockerversion.Version, - Author: author, - Config: config, - Architecture: runtime.GOARCH, - OS: runtime.GOOS, - } - - if containerID != "" { - img.Parent = containerImage - img.Container = containerID - img.ContainerConfig = *containerConfig - } - - if err := graph.Register(v1Descriptor{img}, layerData); err != nil { - return nil, err - } - return img, nil -} - -// Register imports a pre-existing image into the graph. -// Returns nil if the image is already registered. -func (graph *Graph) Register(im image.Descriptor, layerData io.Reader) (err error) { - imgID := im.ID() - - if err := image.ValidateID(imgID); err != nil { - return err - } - - // this is needed cause pull_v2 attemptIDReuse could deadlock - graph.imagesMutex.Lock() - defer graph.imagesMutex.Unlock() - - // We need this entire operation to be atomic within the engine. Note that - // this doesn't mean Register is fully safe yet. - graph.imageMutex.Lock(imgID) - defer graph.imageMutex.Unlock(imgID) - - return graph.register(im, layerData) -} - -func (graph *Graph) register(im image.Descriptor, layerData io.Reader) (err error) { - imgID := im.ID() - - // Skip register if image is already registered - if graph.Exists(imgID) { - return nil - } - - // The returned `error` must be named in this function's signature so that - // `err` is not shadowed in this deferred cleanup. - defer func() { - // If any error occurs, remove the new dir from the driver. - // Don't check for errors since the dir might not have been created. - if err != nil { - graph.driver.Remove(imgID) - } - }() - - // Ensure that the image root does not exist on the filesystem - // when it is not registered in the graph. - // This is common when you switch from one graph driver to another - if err := os.RemoveAll(graph.imageRoot(imgID)); err != nil && !os.IsNotExist(err) { - return err - } - - // If the driver has this ID but the graph doesn't, remove it from the driver to start fresh. - // (the graph is the source of truth). - // Ignore errors, since we don't know if the driver correctly returns ErrNotExist. - // (FIXME: make that mandatory for drivers). - graph.driver.Remove(imgID) - - tmp, err := graph.mktemp() - if err != nil { - return err - } - defer os.RemoveAll(tmp) - - parent := im.Parent() - - // Create root filesystem in the driver - if err := createRootFilesystemInDriver(graph, imgID, parent); err != nil { - return err - } - - // Apply the diff/layer - config, err := im.MarshalConfig() - if err != nil { - return err - } - if err := graph.storeImage(imgID, parent, config, layerData, tmp); err != nil { - return err - } - // Commit - if err := os.Rename(tmp, graph.imageRoot(imgID)); err != nil { - return err - } - - graph.idIndex.Add(imgID) - - graph.imageMutex.Lock(parent) - graph.parentRefs[parent]++ - graph.imageMutex.Unlock(parent) - - return nil -} - -func createRootFilesystemInDriver(graph *Graph, id, parent string) error { - if err := graph.driver.Create(id, parent); err != nil { - return fmt.Errorf("Driver %s failed to create image rootfs %s: %s", graph.driver, id, err) - } - return nil -} - -// TempLayerArchive creates a temporary archive of the given image's filesystem layer. -// The archive is stored on disk and will be automatically deleted as soon as has been read. -// If output is not nil, a human-readable progress bar will be written to it. -func (graph *Graph) tempLayerArchive(id string, sf *streamformatter.StreamFormatter, output io.Writer) (*archive.TempArchive, error) { - image, err := graph.Get(id) - if err != nil { - return nil, err - } - tmp, err := graph.mktemp() - if err != nil { - return nil, err - } - defer os.RemoveAll(tmp) - a, err := graph.tarLayer(image) - if err != nil { - return nil, err - } - progressReader := progressreader.New(progressreader.Config{ - In: a, - Out: output, - Formatter: sf, - Size: 0, - NewLines: false, - ID: stringid.TruncateID(id), - Action: "Buffering to disk", - }) - defer progressReader.Close() - return archive.NewTempArchive(progressReader, tmp) -} - -// mktemp creates a temporary sub-directory inside the graph's filesystem. -func (graph *Graph) mktemp() (string, error) { - dir := filepath.Join(graph.root, "_tmp", stringid.GenerateNonCryptoID()) - rootUID, rootGID, err := idtools.GetRootUIDGID(graph.uidMaps, graph.gidMaps) - if err != nil { - return "", err - } - if err := idtools.MkdirAllAs(dir, 0700, rootUID, rootGID); err != nil { - return "", err - } - return dir, nil -} - -// Delete atomically removes an image from the graph. -func (graph *Graph) Delete(name string) error { - id, err := graph.idIndex.Get(name) - if err != nil { - return err - } - img, err := graph.Get(id) - if err != nil { - return err - } - graph.idIndex.Delete(id) - tmp, err := graph.mktemp() - if err != nil { - tmp = graph.imageRoot(id) - } else { - if err := os.Rename(graph.imageRoot(id), tmp); err != nil { - // On err make tmp point to old dir and cleanup unused tmp dir - os.RemoveAll(tmp) - tmp = graph.imageRoot(id) - } - } - // Remove rootfs data from the driver - graph.driver.Remove(id) - - graph.imageMutex.Lock(img.Parent) - graph.parentRefs[img.Parent]-- - if graph.parentRefs[img.Parent] == 0 { - delete(graph.parentRefs, img.Parent) - } - graph.imageMutex.Unlock(img.Parent) - - // Remove the trashed image directory - return os.RemoveAll(tmp) -} - -// Map returns a list of all images in the graph, addressable by ID. -func (graph *Graph) Map() map[string]*image.Image { - images := make(map[string]*image.Image) - graph.walkAll(func(image *image.Image) { - images[image.ID] = image - }) - return images -} - -// walkAll iterates over each image in the graph, and passes it to a handler. -// The walking order is undetermined. -func (graph *Graph) walkAll(handler func(*image.Image)) { - graph.idIndex.Iterate(func(id string) { - img, err := graph.Get(id) - if err != nil { - return - } - if handler != nil { - handler(img) - } - }) -} - -// ByParent returns a lookup table of images by their parent. -// If an image of key ID has 3 children images, then the value for key ID -// will be a list of 3 images. -// If an image has no children, it will not have an entry in the table. -func (graph *Graph) ByParent() map[string][]*image.Image { - byParent := make(map[string][]*image.Image) - graph.walkAll(func(img *image.Image) { - parent, err := graph.Get(img.Parent) - if err != nil { - return - } - if children, exists := byParent[parent.ID]; exists { - byParent[parent.ID] = append(children, img) - } else { - byParent[parent.ID] = []*image.Image{img} - } - }) - return byParent -} - -// HasChildren returns whether the given image has any child images. -func (graph *Graph) HasChildren(imgID string) bool { - graph.imageMutex.Lock(imgID) - count := graph.parentRefs[imgID] - graph.imageMutex.Unlock(imgID) - return count > 0 -} - -// Retain keeps the images and layers that are in the pulling chain so that -// they are not deleted. If not retained, they may be deleted by rmi. -func (graph *Graph) Retain(sessionID string, layerIDs ...string) { - graph.retained.Add(sessionID, layerIDs) -} - -// Release removes the referenced image ID from the provided set of layers. -func (graph *Graph) Release(sessionID string, layerIDs ...string) { - graph.retained.Delete(sessionID, layerIDs) -} - -// heads returns all heads in the graph, keyed by id. -// A head is an image which is not the parent of another image in the graph. -func (graph *Graph) heads() map[string]*image.Image { - heads := make(map[string]*image.Image) - graph.walkAll(func(image *image.Image) { - // if it has no children, then it's not a parent, so it's an head - if !graph.HasChildren(image.ID) { - heads[image.ID] = image - } - }) - return heads -} - -// tarLayer returns a tar archive of the image's filesystem layer. -func (graph *Graph) tarLayer(img *image.Image) (arch io.ReadCloser, err error) { - rdr, err := graph.assembleTarLayer(img) - if err != nil { - logrus.Debugf("[graph] tarLayer with traditional differ: %s", img.ID) - return graph.driver.Diff(img.ID, img.Parent) - } - return rdr, nil -} - -func (graph *Graph) imageRoot(id string) string { - return filepath.Join(graph.root, id) -} - -// loadImage fetches the image with the given id from the graph. -func (graph *Graph) loadImage(id string) (*image.Image, error) { - root := graph.imageRoot(id) - - // Open the JSON file to decode by streaming - jsonSource, err := os.Open(jsonPath(root)) - if err != nil { - return nil, err - } - defer jsonSource.Close() - - img := &image.Image{} - dec := json.NewDecoder(jsonSource) - - // Decode the JSON data - if err := dec.Decode(img); err != nil { - return nil, err - } - - if img.ID == "" { - img.ID = id - } - - if img.Parent == "" && img.ParentID != "" && img.ParentID.Validate() == nil { - img.Parent = img.ParentID.Hex() - } - - // compatibilityID for parent - parent, err := ioutil.ReadFile(filepath.Join(root, parentFileName)) - if err == nil && len(parent) > 0 { - img.Parent = string(parent) - } - - if err := image.ValidateID(img.ID); err != nil { - return nil, err - } - - if buf, err := ioutil.ReadFile(filepath.Join(root, layersizeFileName)); err != nil { - if !os.IsNotExist(err) { - return nil, err - } - // If the layersize file does not exist then set the size to a negative number - // because a layer size of 0 (zero) is valid - img.Size = -1 - } else { - // Using Atoi here instead would temporarily convert the size to a machine - // dependent integer type, which causes images larger than 2^31 bytes to - // display negative sizes on 32-bit machines: - size, err := strconv.ParseInt(string(buf), 10, 64) - if err != nil { - return nil, err - } - img.Size = int64(size) - } - - return img, nil -} - -// saveSize stores the `size` in the provided graph `img` directory `root`. -func (graph *Graph) saveSize(root string, size int64) error { - if err := ioutil.WriteFile(filepath.Join(root, layersizeFileName), []byte(strconv.FormatInt(size, 10)), 0600); err != nil { - return fmt.Errorf("Error storing image size in %s/%s: %s", root, layersizeFileName, err) - } - return nil -} - -// setLayerDigestWithLock sets the digest for the image layer to the provided value. -func (graph *Graph) setLayerDigestWithLock(id string, dgst digest.Digest) error { - graph.imageMutex.Lock(id) - defer graph.imageMutex.Unlock(id) - - return graph.setLayerDigest(id, dgst) -} -func (graph *Graph) setLayerDigest(id string, dgst digest.Digest) error { - root := graph.imageRoot(id) - if err := ioutil.WriteFile(filepath.Join(root, digestFileName), []byte(dgst.String()), 0600); err != nil { - return fmt.Errorf("Error storing digest in %s/%s: %s", root, digestFileName, err) - } - return nil -} - -// getLayerDigestWithLock gets the digest for the provide image layer id. -func (graph *Graph) getLayerDigestWithLock(id string) (digest.Digest, error) { - graph.imageMutex.Lock(id) - defer graph.imageMutex.Unlock(id) - - return graph.getLayerDigest(id) -} - -func (graph *Graph) getLayerDigest(id string) (digest.Digest, error) { - root := graph.imageRoot(id) - cs, err := ioutil.ReadFile(filepath.Join(root, digestFileName)) - if err != nil { - if os.IsNotExist(err) { - return "", errDigestNotSet - } - return "", err - } - return digest.ParseDigest(string(cs)) -} - -// setV1CompatibilityConfig stores the v1Compatibility JSON data associated -// with the image in the manifest to the disk -func (graph *Graph) setV1CompatibilityConfig(id string, data []byte) error { - root := graph.imageRoot(id) - return ioutil.WriteFile(filepath.Join(root, v1CompatibilityFileName), data, 0600) -} - -// getV1CompatibilityConfig reads the v1Compatibility JSON data for the image -// from the disk -func (graph *Graph) getV1CompatibilityConfig(id string) ([]byte, error) { - root := graph.imageRoot(id) - return ioutil.ReadFile(filepath.Join(root, v1CompatibilityFileName)) -} - -// generateV1CompatibilityChain makes sure v1Compatibility JSON data exists -// for the image. If it doesn't it generates and stores it for the image and -// all of it's parents based on the image config JSON. -func (graph *Graph) generateV1CompatibilityChain(id string) ([]byte, error) { - graph.imageMutex.Lock(id) - defer graph.imageMutex.Unlock(id) - - if v1config, err := graph.getV1CompatibilityConfig(id); err == nil { - return v1config, nil - } - - // generate new, store it to disk - img, err := graph.Get(id) - if err != nil { - return nil, err - } - - digestPrefix := string(digest.Canonical) + ":" - img.ID = strings.TrimPrefix(img.ID, digestPrefix) - - if img.Parent != "" { - parentConfig, err := graph.generateV1CompatibilityChain(img.Parent) - if err != nil { - return nil, err - } - var parent struct{ ID string } - err = json.Unmarshal(parentConfig, &parent) - if err != nil { - return nil, err - } - img.Parent = parent.ID - } - - json, err := json.Marshal(img) - if err != nil { - return nil, err - } - if err := graph.setV1CompatibilityConfig(id, json); err != nil { - return nil, err - } - return json, nil -} - -func jsonPath(root string) string { - return filepath.Join(root, jsonFileName) -} - -// storeImage stores file system layer data for the given image to the -// graph's storage driver. Image metadata is stored in a file -// at the specified root directory. -func (graph *Graph) storeImage(id, parent string, config []byte, layerData io.Reader, root string) (err error) { - var size int64 - // Store the layer. If layerData is not nil, unpack it into the new layer - if layerData != nil { - if size, err = graph.disassembleAndApplyTarLayer(id, parent, layerData, root); err != nil { - return err - } - } - - if err := graph.saveSize(root, size); err != nil { - return err - } - - if err := ioutil.WriteFile(jsonPath(root), config, 0600); err != nil { - return err - } - - // If image is pointing to a parent via CompatibilityID write the reference to disk - img, err := image.NewImgJSON(config) - if err != nil { - return err - } - - if img.ParentID.Validate() == nil && parent != img.ParentID.Hex() { - if err := ioutil.WriteFile(filepath.Join(root, parentFileName), []byte(parent), 0600); err != nil { - return err - } - } - return nil -} - -func (graph *Graph) disassembleAndApplyTarLayer(id, parent string, layerData io.Reader, root string) (size int64, err error) { - var ar io.Reader - - if graph.tarSplitDisabled { - ar = layerData - } else { - // this is saving the tar-split metadata - mf, err := os.OpenFile(filepath.Join(root, tarDataFileName), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600)) - if err != nil { - return 0, err - } - - mfz := gzip.NewWriter(mf) - metaPacker := storage.NewJSONPacker(mfz) - defer mf.Close() - defer mfz.Close() - - inflatedLayerData, err := archive.DecompressStream(layerData) - if err != nil { - return 0, err - } - - // we're passing nil here for the file putter, because the ApplyDiff will - // handle the extraction of the archive - rdr, err := asm.NewInputTarStream(inflatedLayerData, metaPacker, nil) - if err != nil { - return 0, err - } - - ar = archive.Reader(rdr) - } - - if size, err = graph.driver.ApplyDiff(id, parent, ar); err != nil { - return 0, err - } - - return -} - -func (graph *Graph) assembleTarLayer(img *image.Image) (io.ReadCloser, error) { - root := graph.imageRoot(img.ID) - mFileName := filepath.Join(root, tarDataFileName) - mf, err := os.Open(mFileName) - if err != nil { - if !os.IsNotExist(err) { - logrus.Errorf("failed to open %q: %s", mFileName, err) - } - return nil, err - } - pR, pW := io.Pipe() - // this will need to be in a goroutine, as we are returning the stream of a - // tar archive, but can not close the metadata reader early (when this - // function returns)... - go func() { - defer mf.Close() - // let's reassemble! - logrus.Debugf("[graph] TarLayer with reassembly: %s", img.ID) - mfz, err := gzip.NewReader(mf) - if err != nil { - pW.CloseWithError(fmt.Errorf("[graph] error with %s: %s", mFileName, err)) - return - } - defer mfz.Close() - - // get our relative path to the container - fsLayer, err := graph.driver.Get(img.ID, "") - if err != nil { - pW.CloseWithError(err) - return - } - defer graph.driver.Put(img.ID) - - metaUnpacker := storage.NewJSONUnpacker(mfz) - fileGetter := storage.NewPathFileGetter(fsLayer) - logrus.Debugf("[graph] %s is at %q", img.ID, fsLayer) - ots := asm.NewOutputTarStream(fileGetter, metaUnpacker) - defer ots.Close() - if _, err := io.Copy(pW, ots); err != nil { - pW.CloseWithError(err) - return - } - pW.Close() - }() - return pR, nil -} diff --git a/vendor/github.com/docker/docker/graph/graph_test.go b/vendor/github.com/docker/docker/graph/graph_test.go deleted file mode 100644 index 3e0ba3c6..00000000 --- a/vendor/github.com/docker/docker/graph/graph_test.go +++ /dev/null @@ -1,308 +0,0 @@ -package graph - -import ( - "errors" - "io" - "io/ioutil" - "os" - "path" - "testing" - "time" - - "github.com/docker/docker/daemon/graphdriver" - "github.com/docker/docker/dockerversion" - "github.com/docker/docker/image" - "github.com/docker/docker/pkg/stringid" -) - -func TestMount(t *testing.T) { - graph, driver := tempGraph(t) - defer os.RemoveAll(graph.root) - defer driver.Cleanup() - - archive, err := fakeTar() - if err != nil { - t.Fatal(err) - } - image, err := graph.Create(archive, "", "", "Testing", "", nil, nil) - if err != nil { - t.Fatal(err) - } - tmp, err := ioutil.TempDir("", "docker-test-graph-mount-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - rootfs := path.Join(tmp, "rootfs") - if err := os.MkdirAll(rootfs, 0700); err != nil { - t.Fatal(err) - } - rw := path.Join(tmp, "rw") - if err := os.MkdirAll(rw, 0700); err != nil { - t.Fatal(err) - } - - if _, err := driver.Get(image.ID, ""); err != nil { - t.Fatal(err) - } - -} - -func TestInit(t *testing.T) { - graph, _ := tempGraph(t) - defer nukeGraph(graph) - // Root should exist - if _, err := os.Stat(graph.root); err != nil { - t.Fatal(err) - } - // Map() should be empty - l := graph.Map() - if len(l) != 0 { - t.Fatalf("len(Map()) should return %d, not %d", 0, len(l)) - } -} - -// Test that Register can be interrupted cleanly without side effects -func TestInterruptedRegister(t *testing.T) { - graph, _ := tempGraph(t) - defer nukeGraph(graph) - badArchive, w := io.Pipe() // Use a pipe reader as a fake archive which never yields data - image := &image.Image{ - ID: stringid.GenerateNonCryptoID(), - Comment: "testing", - Created: time.Now(), - } - w.CloseWithError(errors.New("But I'm not a tarball!")) // (Nobody's perfect, darling) - graph.Register(v1Descriptor{image}, badArchive) - if _, err := graph.Get(image.ID); err == nil { - t.Fatal("Image should not exist after Register is interrupted") - } - // Registering the same image again should succeed if the first register was interrupted - goodArchive, err := fakeTar() - if err != nil { - t.Fatal(err) - } - if err := graph.Register(v1Descriptor{image}, goodArchive); err != nil { - t.Fatal(err) - } -} - -// FIXME: Do more extensive tests (ex: create multiple, delete, recreate; -// create multiple, check the amount of images and paths, etc..) -func TestGraphCreate(t *testing.T) { - graph, _ := tempGraph(t) - defer nukeGraph(graph) - archive, err := fakeTar() - if err != nil { - t.Fatal(err) - } - img, err := graph.Create(archive, "", "", "Testing", "", nil, nil) - if err != nil { - t.Fatal(err) - } - if err := image.ValidateID(img.ID); err != nil { - t.Fatal(err) - } - if img.Comment != "Testing" { - t.Fatalf("Wrong comment: should be '%s', not '%s'", "Testing", img.Comment) - } - if img.DockerVersion != dockerversion.Version { - t.Fatalf("Wrong docker_version: should be '%s', not '%s'", dockerversion.Version, img.DockerVersion) - } - images := graph.Map() - if l := len(images); l != 1 { - t.Fatalf("Wrong number of images. Should be %d, not %d", 1, l) - } - if images[img.ID] == nil { - t.Fatalf("Could not find image with id %s", img.ID) - } -} - -func TestRegister(t *testing.T) { - graph, _ := tempGraph(t) - defer nukeGraph(graph) - archive, err := fakeTar() - if err != nil { - t.Fatal(err) - } - image := &image.Image{ - ID: stringid.GenerateNonCryptoID(), - Comment: "testing", - Created: time.Now(), - } - err = graph.Register(v1Descriptor{image}, archive) - if err != nil { - t.Fatal(err) - } - images := graph.Map() - if l := len(images); l != 1 { - t.Fatalf("Wrong number of images. Should be %d, not %d", 1, l) - } - if resultImg, err := graph.Get(image.ID); err != nil { - t.Fatal(err) - } else { - if resultImg.ID != image.ID { - t.Fatalf("Wrong image ID. Should be '%s', not '%s'", image.ID, resultImg.ID) - } - if resultImg.Comment != image.Comment { - t.Fatalf("Wrong image comment. Should be '%s', not '%s'", image.Comment, resultImg.Comment) - } - } -} - -// Test that an image can be deleted by its shorthand prefix -func TestDeletePrefix(t *testing.T) { - graph, _ := tempGraph(t) - defer nukeGraph(graph) - img := createTestImage(graph, t) - if err := graph.Delete(stringid.TruncateID(img.ID)); err != nil { - t.Fatal(err) - } - assertNImages(graph, t, 0) -} - -func TestDelete(t *testing.T) { - graph, _ := tempGraph(t) - defer nukeGraph(graph) - archive, err := fakeTar() - if err != nil { - t.Fatal(err) - } - assertNImages(graph, t, 0) - img, err := graph.Create(archive, "", "", "Bla bla", "", nil, nil) - if err != nil { - t.Fatal(err) - } - assertNImages(graph, t, 1) - if err := graph.Delete(img.ID); err != nil { - t.Fatal(err) - } - assertNImages(graph, t, 0) - - archive, err = fakeTar() - if err != nil { - t.Fatal(err) - } - // Test 2 create (same name) / 1 delete - img1, err := graph.Create(archive, "", "", "Testing", "", nil, nil) - if err != nil { - t.Fatal(err) - } - archive, err = fakeTar() - if err != nil { - t.Fatal(err) - } - if _, err = graph.Create(archive, "", "", "Testing", "", nil, nil); err != nil { - t.Fatal(err) - } - assertNImages(graph, t, 2) - if err := graph.Delete(img1.ID); err != nil { - t.Fatal(err) - } - assertNImages(graph, t, 1) - - // Test delete wrong name - if err := graph.Delete("Not_foo"); err == nil { - t.Fatalf("Deleting wrong ID should return an error") - } - assertNImages(graph, t, 1) - - archive, err = fakeTar() - if err != nil { - t.Fatal(err) - } - // Test delete twice (pull -> rm -> pull -> rm) - if err := graph.Register(v1Descriptor{img1}, archive); err != nil { - t.Fatal(err) - } - if err := graph.Delete(img1.ID); err != nil { - t.Fatal(err) - } - assertNImages(graph, t, 1) -} - -func TestByParent(t *testing.T) { - archive1, _ := fakeTar() - archive2, _ := fakeTar() - archive3, _ := fakeTar() - - graph, _ := tempGraph(t) - defer nukeGraph(graph) - parentImage := &image.Image{ - ID: stringid.GenerateNonCryptoID(), - Comment: "parent", - Created: time.Now(), - Parent: "", - } - childImage1 := &image.Image{ - ID: stringid.GenerateNonCryptoID(), - Comment: "child1", - Created: time.Now(), - Parent: parentImage.ID, - } - childImage2 := &image.Image{ - ID: stringid.GenerateNonCryptoID(), - Comment: "child2", - Created: time.Now(), - Parent: parentImage.ID, - } - - err := graph.Register(v1Descriptor{parentImage}, archive1) - if err != nil { - t.Fatal(err) - } - err = graph.Register(v1Descriptor{childImage1}, archive2) - if err != nil { - t.Fatal(err) - } - err = graph.Register(v1Descriptor{childImage2}, archive3) - if err != nil { - t.Fatal(err) - } - - byParent := graph.ByParent() - numChildren := len(byParent[parentImage.ID]) - if numChildren != 2 { - t.Fatalf("Expected 2 children, found %d", numChildren) - } -} - -func createTestImage(graph *Graph, t *testing.T) *image.Image { - archive, err := fakeTar() - if err != nil { - t.Fatal(err) - } - img, err := graph.Create(archive, "", "", "Test image", "", nil, nil) - if err != nil { - t.Fatal(err) - } - return img -} - -func assertNImages(graph *Graph, t *testing.T, n int) { - images := graph.Map() - if actualN := len(images); actualN != n { - t.Fatalf("Expected %d images, found %d", n, actualN) - } -} - -func tempGraph(t *testing.T) (*Graph, graphdriver.Driver) { - tmp, err := ioutil.TempDir("", "docker-graph-") - if err != nil { - t.Fatal(err) - } - driver, err := graphdriver.New(tmp, nil, nil, nil) - if err != nil { - t.Fatal(err) - } - graph, err := NewGraph(tmp, driver, nil, nil) - if err != nil { - t.Fatal(err) - } - return graph, driver -} - -func nukeGraph(graph *Graph) { - graph.driver.Cleanup() - os.RemoveAll(graph.root) -} diff --git a/vendor/github.com/docker/docker/graph/history.go b/vendor/github.com/docker/docker/graph/history.go deleted file mode 100644 index de702987..00000000 --- a/vendor/github.com/docker/docker/graph/history.go +++ /dev/null @@ -1,119 +0,0 @@ -package graph - -import ( - "fmt" - "strings" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/image" - "github.com/docker/docker/utils" -) - -// walkHistory calls the handler function for each image in the -// provided images lineage starting from immediate parent. -func (graph *Graph) walkHistory(img *image.Image, handler func(image.Image) error) (err error) { - currentImg := img - for currentImg != nil { - if handler != nil { - if err := handler(*currentImg); err != nil { - return err - } - } - currentImg, err = graph.GetParent(currentImg) - if err != nil { - return fmt.Errorf("Error while getting parent image: %v", err) - } - } - return nil -} - -// depth returns the number of parents for the current image -func (graph *Graph) depth(img *image.Image) (int, error) { - var ( - count = 0 - parent = img - err error - ) - - for parent != nil { - count++ - if parent, err = graph.GetParent(parent); err != nil { - return -1, err - } - } - return count, nil -} - -// Set the max depth to the aufs default that most kernels are compiled with. -// For more information see: http://sourceforge.net/p/aufs/aufs3-standalone/ci/aufs3.12/tree/config.mk -const maxImageDepth = 127 - -// CheckDepth returns an error if the depth of an image, as returned -// by ImageDepth, is too large to support creating a container from it -// on this daemon. -func (graph *Graph) CheckDepth(img *image.Image) error { - // We add 2 layers to the depth because the container's rw and - // init layer add to the restriction - depth, err := graph.depth(img) - if err != nil { - return err - } - if depth+2 >= maxImageDepth { - return fmt.Errorf("Cannot create container with more than %d parents", maxImageDepth) - } - return nil -} - -// History returns a slice of ImageHistory structures for the specified image -// name by walking the image lineage. -func (s *TagStore) History(name string) ([]*types.ImageHistory, error) { - foundImage, err := s.LookupImage(name) - if err != nil { - return nil, err - } - - lookupMap := make(map[string][]string) - for name, repository := range s.Repositories { - for tag, id := range repository { - // If the ID already has a reverse lookup, do not update it unless for "latest" - if _, exists := lookupMap[id]; !exists { - lookupMap[id] = []string{} - } - lookupMap[id] = append(lookupMap[id], utils.ImageReference(name, tag)) - } - } - - history := []*types.ImageHistory{} - - err = s.graph.walkHistory(foundImage, func(img image.Image) error { - history = append(history, &types.ImageHistory{ - ID: img.ID, - Created: img.Created.Unix(), - CreatedBy: strings.Join(img.ContainerConfig.Cmd.Slice(), " "), - Tags: lookupMap[img.ID], - Size: img.Size, - Comment: img.Comment, - }) - return nil - }) - - return history, err -} - -// GetParent returns the parent image for the specified image. -func (graph *Graph) GetParent(img *image.Image) (*image.Image, error) { - if img.Parent == "" { - return nil, nil - } - return graph.Get(img.Parent) -} - -// getParentsSize returns the combined size of all parent images. If there is -// no parent image or it's unavailable, it returns 0. -func (graph *Graph) getParentsSize(img *image.Image) int64 { - parentImage, err := graph.GetParent(img) - if err != nil || parentImage == nil { - return 0 - } - return parentImage.Size + graph.getParentsSize(parentImage) -} diff --git a/vendor/github.com/docker/docker/graph/import.go b/vendor/github.com/docker/docker/graph/import.go deleted file mode 100644 index 1a09dec4..00000000 --- a/vendor/github.com/docker/docker/graph/import.go +++ /dev/null @@ -1,79 +0,0 @@ -package graph - -import ( - "io" - "net/http" - "net/url" - - "github.com/docker/docker/pkg/httputils" - "github.com/docker/docker/pkg/progressreader" - "github.com/docker/docker/pkg/streamformatter" - "github.com/docker/docker/runconfig" - "github.com/docker/docker/utils" -) - -// Import imports an image, getting the archived layer data either from -// inConfig (if src is "-"), or from a URI specified in src. Progress output is -// written to outStream. Repository and tag names can optionally be given in -// the repo and tag arguments, respectively. -func (s *TagStore) Import(src string, repo string, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, containerConfig *runconfig.Config) error { - var ( - sf = streamformatter.NewJSONStreamFormatter() - archive io.ReadCloser - resp *http.Response - ) - - if src == "-" { - archive = inConfig - } else { - inConfig.Close() - u, err := url.Parse(src) - if err != nil { - return err - } - if u.Scheme == "" { - u.Scheme = "http" - u.Host = src - u.Path = "" - } - outStream.Write(sf.FormatStatus("", "Downloading from %s", u)) - resp, err = httputils.Download(u.String()) - if err != nil { - return err - } - progressReader := progressreader.New(progressreader.Config{ - In: resp.Body, - Out: outStream, - Formatter: sf, - Size: resp.ContentLength, - NewLines: true, - ID: "", - Action: "Importing", - }) - archive = progressReader - } - - defer archive.Close() - if len(msg) == 0 { - msg = "Imported from " + src - } - - img, err := s.graph.Create(archive, "", "", msg, "", nil, containerConfig) - if err != nil { - return err - } - // Optionally register the image at REPO/TAG - if repo != "" { - if err := s.Tag(repo, tag, img.ID, true); err != nil { - return err - } - } - outStream.Write(sf.FormatStatus("", img.ID)) - logID := img.ID - if tag != "" { - logID = utils.ImageReference(logID, tag) - } - - s.eventsService.Log("import", logID, "") - return nil -} diff --git a/vendor/github.com/docker/docker/graph/list.go b/vendor/github.com/docker/docker/graph/list.go deleted file mode 100644 index 675110ff..00000000 --- a/vendor/github.com/docker/docker/graph/list.go +++ /dev/null @@ -1,185 +0,0 @@ -package graph - -import ( - "fmt" - "path" - "sort" - "strings" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/api/types" - "github.com/docker/docker/image" - "github.com/docker/docker/pkg/parsers/filters" - "github.com/docker/docker/utils" -) - -var acceptedImageFilterTags = map[string]struct{}{ - "dangling": {}, - "label": {}, -} - -// byCreated is a temporary type used to sort a list of images by creation -// time. -type byCreated []*types.Image - -func (r byCreated) Len() int { return len(r) } -func (r byCreated) Swap(i, j int) { r[i], r[j] = r[j], r[i] } -func (r byCreated) Less(i, j int) bool { return r[i].Created < r[j].Created } - -// Images returns a filtered list of images. filterArgs is a JSON-encoded set -// of filter arguments which will be interpreted by pkg/parsers/filters. -// filter is a shell glob string applied to repository names. The argument -// named all controls whether all images in the graph are filtered, or just -// the heads. -func (s *TagStore) Images(filterArgs, filter string, all bool) ([]*types.Image, error) { - var ( - allImages map[string]*image.Image - err error - filtTagged = true - filtLabel = false - ) - - imageFilters, err := filters.FromParam(filterArgs) - if err != nil { - return nil, err - } - for name := range imageFilters { - if _, ok := acceptedImageFilterTags[name]; !ok { - return nil, fmt.Errorf("Invalid filter '%s'", name) - } - } - - if i, ok := imageFilters["dangling"]; ok { - for _, value := range i { - if v := strings.ToLower(value); v == "true" { - filtTagged = false - } else if v != "false" { - return nil, fmt.Errorf("Invalid filter 'dangling=%s'", v) - } - } - } - - _, filtLabel = imageFilters["label"] - - if all && filtTagged { - allImages = s.graph.Map() - } else { - allImages = s.graph.heads() - } - - lookup := make(map[string]*types.Image) - s.Lock() - for repoName, repository := range s.Repositories { - filterTagName := "" - if filter != "" { - filterName := filter - // Test if the tag was in there, if yes, get the name - if strings.Contains(filterName, ":") { - filterWithTag := strings.Split(filter, ":") - filterName = filterWithTag[0] - filterTagName = filterWithTag[1] - } - if match, _ := path.Match(filterName, repoName); !match { - continue - } - if filterTagName != "" { - if _, ok := repository[filterTagName]; !ok { - continue - } - } - } - for ref, id := range repository { - imgRef := utils.ImageReference(repoName, ref) - if !strings.Contains(imgRef, filterTagName) { - continue - } - image, err := s.graph.Get(id) - if err != nil { - logrus.Warnf("couldn't load %s from %s: %s", id, imgRef, err) - continue - } - - if lImage, exists := lookup[id]; exists { - if filtTagged { - if utils.DigestReference(ref) { - lImage.RepoDigests = append(lImage.RepoDigests, imgRef) - } else { // Tag Ref. - lImage.RepoTags = append(lImage.RepoTags, imgRef) - } - } - } else { - // get the boolean list for if only the untagged images are requested - delete(allImages, id) - - if len(imageFilters["label"]) > 0 { - if image.Config == nil { - // Very old image that do not have image.Config (or even labels) - continue - } - // We are now sure image.Config is not nil - if !imageFilters.MatchKVList("label", image.Config.Labels) { - continue - } - } - if filtTagged { - newImage := newImage(image, s.graph.getParentsSize(image)) - - if utils.DigestReference(ref) { - newImage.RepoTags = []string{} - newImage.RepoDigests = []string{imgRef} - } else { - newImage.RepoTags = []string{imgRef} - newImage.RepoDigests = []string{} - } - - lookup[id] = newImage - } - } - - } - } - s.Unlock() - - images := []*types.Image{} - for _, value := range lookup { - images = append(images, value) - } - - // Display images which aren't part of a repository/tag - if filter == "" || filtLabel { - for _, image := range allImages { - if len(imageFilters["label"]) > 0 { - if image.Config == nil { - // Very old image that do not have image.Config (or even labels) - continue - } - // We are now sure image.Config is not nil - if !imageFilters.MatchKVList("label", image.Config.Labels) { - continue - } - } - newImage := newImage(image, s.graph.getParentsSize(image)) - newImage.RepoTags = []string{":"} - newImage.RepoDigests = []string{"@"} - - images = append(images, newImage) - } - } - - sort.Sort(sort.Reverse(byCreated(images))) - - return images, nil -} - -func newImage(image *image.Image, parentSize int64) *types.Image { - newImage := new(types.Image) - newImage.ParentID = image.Parent - newImage.ID = image.ID - newImage.Created = image.Created.Unix() - newImage.Size = image.Size - newImage.VirtualSize = parentSize + image.Size - if image.Config != nil { - newImage.Labels = image.Config.Labels - } - return newImage -} diff --git a/vendor/github.com/docker/docker/graph/load.go b/vendor/github.com/docker/docker/graph/load.go deleted file mode 100644 index 3be3a8e8..00000000 --- a/vendor/github.com/docker/docker/graph/load.go +++ /dev/null @@ -1,134 +0,0 @@ -// +build linux windows - -package graph - -import ( - "encoding/json" - "io" - "io/ioutil" - "os" - "path/filepath" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/image" - "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/chrootarchive" -) - -// Load uploads a set of images into the repository. This is the complementary of ImageExport. -// The input stream is an uncompressed tar ball containing images and metadata. -func (s *TagStore) Load(inTar io.ReadCloser, outStream io.Writer) error { - tmpImageDir, err := ioutil.TempDir("", "docker-import-") - if err != nil { - return err - } - defer os.RemoveAll(tmpImageDir) - - var ( - repoDir = filepath.Join(tmpImageDir, "repo") - ) - - if err := os.Mkdir(repoDir, os.ModeDir); err != nil { - return err - } - images := s.graph.Map() - excludes := make([]string, len(images)) - i := 0 - for k := range images { - excludes[i] = k - i++ - } - if err := chrootarchive.Untar(inTar, repoDir, &archive.TarOptions{ExcludePatterns: excludes}); err != nil { - return err - } - - dirs, err := ioutil.ReadDir(repoDir) - if err != nil { - return err - } - - for _, d := range dirs { - if d.IsDir() { - if err := s.recursiveLoad(d.Name(), tmpImageDir); err != nil { - return err - } - } - } - - reposJSONFile, err := os.Open(filepath.Join(tmpImageDir, "repo", "repositories")) - if err != nil { - if !os.IsNotExist(err) { - return err - } - return nil - } - defer reposJSONFile.Close() - - repositories := map[string]repository{} - if err := json.NewDecoder(reposJSONFile).Decode(&repositories); err != nil { - return err - } - - for imageName, tagMap := range repositories { - for tag, address := range tagMap { - if err := s.setLoad(imageName, tag, address, true, outStream); err != nil { - return err - } - } - } - - return nil -} - -func (s *TagStore) recursiveLoad(address, tmpImageDir string) error { - if _, err := s.LookupImage(address); err != nil { - logrus.Debugf("Loading %s", address) - - imageJSON, err := ioutil.ReadFile(filepath.Join(tmpImageDir, "repo", address, "json")) - if err != nil { - logrus.Debugf("Error reading json: %v", err) - return err - } - - layer, err := os.Open(filepath.Join(tmpImageDir, "repo", address, "layer.tar")) - if err != nil { - logrus.Debugf("Error reading embedded tar: %v", err) - return err - } - img, err := image.NewImgJSON(imageJSON) - if err != nil { - logrus.Debugf("Error unmarshalling json: %v", err) - return err - } - if err := image.ValidateID(img.ID); err != nil { - logrus.Debugf("Error validating ID: %v", err) - return err - } - - // ensure no two downloads of the same layer happen at the same time - poolKey := "layer:" + img.ID - broadcaster, found := s.poolAdd("pull", poolKey) - if found { - logrus.Debugf("Image (id: %s) load is already running, waiting", img.ID) - return broadcaster.Wait() - } - - defer s.poolRemove("pull", poolKey) - - if img.Parent != "" { - if !s.graph.Exists(img.Parent) { - if err := s.recursiveLoad(img.Parent, tmpImageDir); err != nil { - return err - } - } - } - if err := s.graph.Register(v1Descriptor{img}, layer); err != nil { - return err - } - logrus.Debugf("Completed processing %s", address) - return nil - } - logrus.Debugf("already loaded %s", address) - - return nil -} diff --git a/vendor/github.com/docker/docker/graph/load_unsupported.go b/vendor/github.com/docker/docker/graph/load_unsupported.go deleted file mode 100644 index 7154931f..00000000 --- a/vendor/github.com/docker/docker/graph/load_unsupported.go +++ /dev/null @@ -1,14 +0,0 @@ -// +build !linux,!windows - -package graph - -import ( - "fmt" - "io" -) - -// Load method is implemented here for non-linux and non-windows platforms and -// may return an error indicating that image load is not supported on other platforms. -func (s *TagStore) Load(inTar io.ReadCloser, outStream io.Writer) error { - return fmt.Errorf("Load is not supported on this platform") -} diff --git a/vendor/github.com/docker/docker/graph/pools_test.go b/vendor/github.com/docker/docker/graph/pools_test.go deleted file mode 100644 index 6382c155..00000000 --- a/vendor/github.com/docker/docker/graph/pools_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package graph - -import ( - "testing" - - "github.com/docker/docker/pkg/broadcaster" - "github.com/docker/docker/pkg/reexec" -) - -func init() { - reexec.Init() -} - -func TestPools(t *testing.T) { - s := &TagStore{ - pullingPool: make(map[string]*broadcaster.Buffered), - pushingPool: make(map[string]*broadcaster.Buffered), - } - - if _, found := s.poolAdd("pull", "test1"); found { - t.Fatal("Expected pull test1 not to be in progress") - } - if _, found := s.poolAdd("pull", "test2"); found { - t.Fatal("Expected pull test2 not to be in progress") - } - if _, found := s.poolAdd("push", "test1"); !found { - t.Fatalf("Expected pull test1 to be in progress`") - } - if _, found := s.poolAdd("pull", "test1"); !found { - t.Fatalf("Expected pull test1 to be in progress`") - } - if err := s.poolRemove("pull", "test2"); err != nil { - t.Fatal(err) - } - if err := s.poolRemove("pull", "test2"); err != nil { - t.Fatal(err) - } - if err := s.poolRemove("pull", "test1"); err != nil { - t.Fatal(err) - } - if err := s.poolRemove("push", "test1"); err != nil { - t.Fatal(err) - } -} diff --git a/vendor/github.com/docker/docker/graph/pull.go b/vendor/github.com/docker/docker/graph/pull.go deleted file mode 100644 index ce600479..00000000 --- a/vendor/github.com/docker/docker/graph/pull.go +++ /dev/null @@ -1,148 +0,0 @@ -package graph - -import ( - "fmt" - "io" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/cliconfig" - "github.com/docker/docker/pkg/streamformatter" - "github.com/docker/docker/registry" - "github.com/docker/docker/utils" -) - -// ImagePullConfig stores pull configuration. -type ImagePullConfig struct { - // MetaHeaders stores HTTP headers with metadata about the image - // (DockerHeaders with prefix X-Meta- in the request). - MetaHeaders map[string][]string - // AuthConfig holds authentication credentials for authenticating with - // the registry. - AuthConfig *cliconfig.AuthConfig - // OutStream is the output writer for showing the status of the pull - // operation. - OutStream io.Writer -} - -// puller is an interface that abstracts pulling for different API versions. -type puller interface { - // Pull tries to pull the image referenced by `tag` - // Pull returns an error if any, as well as a boolean that determines whether to retry Pull on the next configured endpoint. - // - // TODO(tiborvass): have Pull() take a reference to repository + tag, so that the puller itself is repository-agnostic. - Pull(tag string) (fallback bool, err error) -} - -// newPuller returns a Puller interface that will pull from either a v1 or v2 -// registry. The endpoint argument contains a Version field that determines -// whether a v1 or v2 puller will be created. The other parameters are passed -// through to the underlying puller implementation for use during the actual -// pull operation. -func newPuller(s *TagStore, endpoint registry.APIEndpoint, repoInfo *registry.RepositoryInfo, imagePullConfig *ImagePullConfig, sf *streamformatter.StreamFormatter) (puller, error) { - switch endpoint.Version { - case registry.APIVersion2: - return &v2Puller{ - TagStore: s, - endpoint: endpoint, - config: imagePullConfig, - sf: sf, - repoInfo: repoInfo, - }, nil - case registry.APIVersion1: - return &v1Puller{ - TagStore: s, - endpoint: endpoint, - config: imagePullConfig, - sf: sf, - repoInfo: repoInfo, - }, nil - } - return nil, fmt.Errorf("unknown version %d for registry %s", endpoint.Version, endpoint.URL) -} - -// Pull initiates a pull operation. image is the repository name to pull, and -// tag may be either empty, or indicate a specific tag to pull. -func (s *TagStore) Pull(image string, tag string, imagePullConfig *ImagePullConfig) error { - var sf = streamformatter.NewJSONStreamFormatter() - - // Resolve the Repository name from fqn to RepositoryInfo - repoInfo, err := s.registryService.ResolveRepository(image) - if err != nil { - return err - } - - // makes sure name is not empty or `scratch` - if err := validateRepoName(repoInfo.LocalName); err != nil { - return err - } - - endpoints, err := s.registryService.LookupPullEndpoints(repoInfo.CanonicalName) - if err != nil { - return err - } - - logName := repoInfo.LocalName - if tag != "" { - logName = utils.ImageReference(logName, tag) - } - - var ( - lastErr error - - // discardNoSupportErrors is used to track whether an endpoint encountered an error of type registry.ErrNoSupport - // By default it is false, which means that if a ErrNoSupport error is encountered, it will be saved in lastErr. - // As soon as another kind of error is encountered, discardNoSupportErrors is set to true, avoiding the saving of - // any subsequent ErrNoSupport errors in lastErr. - // It's needed for pull-by-digest on v1 endpoints: if there are only v1 endpoints configured, the error should be - // returned and displayed, but if there was a v2 endpoint which supports pull-by-digest, then the last relevant - // error is the ones from v2 endpoints not v1. - discardNoSupportErrors bool - ) - for _, endpoint := range endpoints { - logrus.Debugf("Trying to pull %s from %s %s", repoInfo.LocalName, endpoint.URL, endpoint.Version) - - puller, err := newPuller(s, endpoint, repoInfo, imagePullConfig, sf) - if err != nil { - lastErr = err - continue - } - if fallback, err := puller.Pull(tag); err != nil { - if fallback { - if _, ok := err.(registry.ErrNoSupport); !ok { - // Because we found an error that's not ErrNoSupport, discard all subsequent ErrNoSupport errors. - discardNoSupportErrors = true - // save the current error - lastErr = err - } else if !discardNoSupportErrors { - // Save the ErrNoSupport error, because it's either the first error or all encountered errors - // were also ErrNoSupport errors. - lastErr = err - } - continue - } - logrus.Debugf("Not continuing with error: %v", err) - return err - - } - - s.eventsService.Log("pull", logName, "") - return nil - } - - if lastErr == nil { - lastErr = fmt.Errorf("no endpoints found for %s", image) - } - return lastErr -} - -// writeStatus writes a status message to out. If layersDownloaded is true, the -// status message indicates that a newer image was downloaded. Otherwise, it -// indicates that the image is up to date. requestedTag is the tag the message -// will refer to. -func writeStatus(requestedTag string, out io.Writer, sf *streamformatter.StreamFormatter, layersDownloaded bool) { - if layersDownloaded { - out.Write(sf.FormatStatus("", "Status: Downloaded newer image for %s", requestedTag)) - } else { - out.Write(sf.FormatStatus("", "Status: Image is up to date for %s", requestedTag)) - } -} diff --git a/vendor/github.com/docker/docker/graph/pull_v1.go b/vendor/github.com/docker/docker/graph/pull_v1.go deleted file mode 100644 index 51150dbe..00000000 --- a/vendor/github.com/docker/docker/graph/pull_v1.go +++ /dev/null @@ -1,350 +0,0 @@ -package graph - -import ( - "errors" - "fmt" - "io" - "net" - "net/url" - "strings" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/distribution/registry/client/transport" - "github.com/docker/docker/image" - "github.com/docker/docker/pkg/progressreader" - "github.com/docker/docker/pkg/streamformatter" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/registry" - "github.com/docker/docker/utils" -) - -type v1Puller struct { - *TagStore - endpoint registry.APIEndpoint - config *ImagePullConfig - sf *streamformatter.StreamFormatter - repoInfo *registry.RepositoryInfo - session *registry.Session -} - -func (p *v1Puller) Pull(tag string) (fallback bool, err error) { - if utils.DigestReference(tag) { - // Allowing fallback, because HTTPS v1 is before HTTP v2 - return true, registry.ErrNoSupport{Err: errors.New("Cannot pull by digest with v1 registry")} - } - - tlsConfig, err := p.registryService.TLSConfig(p.repoInfo.Index.Name) - if err != nil { - return false, err - } - // Adds Docker-specific headers as well as user-specified headers (metaHeaders) - tr := transport.NewTransport( - // TODO(tiborvass): was ReceiveTimeout - registry.NewTransport(tlsConfig), - registry.DockerHeaders(p.config.MetaHeaders)..., - ) - client := registry.HTTPClient(tr) - v1Endpoint, err := p.endpoint.ToV1Endpoint(p.config.MetaHeaders) - if err != nil { - logrus.Debugf("Could not get v1 endpoint: %v", err) - return true, err - } - p.session, err = registry.NewSession(client, p.config.AuthConfig, v1Endpoint) - if err != nil { - // TODO(dmcgowan): Check if should fallback - logrus.Debugf("Fallback from error: %s", err) - return true, err - } - if err := p.pullRepository(tag); err != nil { - // TODO(dmcgowan): Check if should fallback - return false, err - } - out := p.config.OutStream - out.Write(p.sf.FormatStatus("", "%s: this image was pulled from a legacy registry. Important: This registry version will not be supported in future versions of docker.", p.repoInfo.CanonicalName)) - - return false, nil -} - -func (p *v1Puller) pullRepository(askedTag string) error { - out := p.config.OutStream - out.Write(p.sf.FormatStatus("", "Pulling repository %s", p.repoInfo.CanonicalName)) - - repoData, err := p.session.GetRepositoryData(p.repoInfo.RemoteName) - if err != nil { - if strings.Contains(err.Error(), "HTTP code: 404") { - return fmt.Errorf("Error: image %s not found", utils.ImageReference(p.repoInfo.RemoteName, askedTag)) - } - // Unexpected HTTP error - return err - } - - logrus.Debugf("Retrieving the tag list") - tagsList := make(map[string]string) - if askedTag == "" { - tagsList, err = p.session.GetRemoteTags(repoData.Endpoints, p.repoInfo.RemoteName) - } else { - var tagID string - tagID, err = p.session.GetRemoteTag(repoData.Endpoints, p.repoInfo.RemoteName, askedTag) - tagsList[askedTag] = tagID - } - if err != nil { - if err == registry.ErrRepoNotFound && askedTag != "" { - return fmt.Errorf("Tag %s not found in repository %s", askedTag, p.repoInfo.CanonicalName) - } - logrus.Errorf("unable to get remote tags: %s", err) - return err - } - - for tag, id := range tagsList { - repoData.ImgList[id] = ®istry.ImgData{ - ID: id, - Tag: tag, - Checksum: "", - } - } - - logrus.Debugf("Registering tags") - // If no tag has been specified, pull them all - if askedTag == "" { - for tag, id := range tagsList { - repoData.ImgList[id].Tag = tag - } - } else { - // Otherwise, check that the tag exists and use only that one - id, exists := tagsList[askedTag] - if !exists { - return fmt.Errorf("Tag %s not found in repository %s", askedTag, p.repoInfo.CanonicalName) - } - repoData.ImgList[id].Tag = askedTag - } - - errors := make(chan error) - - layersDownloaded := false - imgIDs := []string{} - sessionID := p.session.ID() - defer func() { - p.graph.Release(sessionID, imgIDs...) - }() - for _, imgData := range repoData.ImgList { - downloadImage := func(img *registry.ImgData) { - if askedTag != "" && img.Tag != askedTag { - errors <- nil - return - } - - if img.Tag == "" { - logrus.Debugf("Image (id: %s) present in this repository but untagged, skipping", img.ID) - errors <- nil - return - } - - if err := image.ValidateID(img.ID); err != nil { - errors <- err - return - } - - // ensure no two downloads of the same image happen at the same time - poolKey := "img:" + img.ID - broadcaster, found := p.poolAdd("pull", poolKey) - broadcaster.Add(out) - if found { - errors <- broadcaster.Wait() - return - } - defer p.poolRemove("pull", poolKey) - - // we need to retain it until tagging - p.graph.Retain(sessionID, img.ID) - imgIDs = append(imgIDs, img.ID) - - broadcaster.Write(p.sf.FormatProgress(stringid.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s", img.Tag, p.repoInfo.CanonicalName), nil)) - success := false - var lastErr, err error - var isDownloaded bool - for _, ep := range p.repoInfo.Index.Mirrors { - ep += "v1/" - broadcaster.Write(p.sf.FormatProgress(stringid.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s, mirror: %s", img.Tag, p.repoInfo.CanonicalName, ep), nil)) - if isDownloaded, err = p.pullImage(broadcaster, img.ID, ep); err != nil { - // Don't report errors when pulling from mirrors. - logrus.Debugf("Error pulling image (%s) from %s, mirror: %s, %s", img.Tag, p.repoInfo.CanonicalName, ep, err) - continue - } - layersDownloaded = layersDownloaded || isDownloaded - success = true - break - } - if !success { - for _, ep := range repoData.Endpoints { - broadcaster.Write(p.sf.FormatProgress(stringid.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s, endpoint: %s", img.Tag, p.repoInfo.CanonicalName, ep), nil)) - if isDownloaded, err = p.pullImage(broadcaster, img.ID, ep); err != nil { - // It's not ideal that only the last error is returned, it would be better to concatenate the errors. - // As the error is also given to the output stream the user will see the error. - lastErr = err - broadcaster.Write(p.sf.FormatProgress(stringid.TruncateID(img.ID), fmt.Sprintf("Error pulling image (%s) from %s, endpoint: %s, %s", img.Tag, p.repoInfo.CanonicalName, ep, err), nil)) - continue - } - layersDownloaded = layersDownloaded || isDownloaded - success = true - break - } - } - if !success { - err := fmt.Errorf("Error pulling image (%s) from %s, %v", img.Tag, p.repoInfo.CanonicalName, lastErr) - broadcaster.Write(p.sf.FormatProgress(stringid.TruncateID(img.ID), err.Error(), nil)) - errors <- err - broadcaster.CloseWithError(err) - return - } - broadcaster.Write(p.sf.FormatProgress(stringid.TruncateID(img.ID), "Download complete", nil)) - - errors <- nil - } - - go downloadImage(imgData) - } - - var lastError error - for i := 0; i < len(repoData.ImgList); i++ { - if err := <-errors; err != nil { - lastError = err - } - } - if lastError != nil { - return lastError - } - - for tag, id := range tagsList { - if askedTag != "" && tag != askedTag { - continue - } - if err := p.Tag(p.repoInfo.LocalName, tag, id, true); err != nil { - return err - } - } - - requestedTag := p.repoInfo.LocalName - if len(askedTag) > 0 { - requestedTag = utils.ImageReference(p.repoInfo.LocalName, askedTag) - } - writeStatus(requestedTag, out, p.sf, layersDownloaded) - return nil -} - -func (p *v1Puller) pullImage(out io.Writer, imgID, endpoint string) (layersDownloaded bool, err error) { - var history []string - history, err = p.session.GetRemoteHistory(imgID, endpoint) - if err != nil { - return false, err - } - out.Write(p.sf.FormatProgress(stringid.TruncateID(imgID), "Pulling dependent layers", nil)) - // FIXME: Try to stream the images? - // FIXME: Launch the getRemoteImage() in goroutines - - sessionID := p.session.ID() - // As imgID has been retained in pullRepository, no need to retain again - p.graph.Retain(sessionID, history[1:]...) - defer p.graph.Release(sessionID, history[1:]...) - - layersDownloaded = false - for i := len(history) - 1; i >= 0; i-- { - id := history[i] - - // ensure no two downloads of the same layer happen at the same time - poolKey := "layer:" + id - broadcaster, found := p.poolAdd("pull", poolKey) - broadcaster.Add(out) - if found { - logrus.Debugf("Image (id: %s) pull is already running, skipping", id) - err = broadcaster.Wait() - if err != nil { - return layersDownloaded, err - } - continue - } - - // This must use a closure so it captures the value of err when - // the function returns, not when the 'defer' is evaluated. - defer func() { - p.poolRemoveWithError("pull", poolKey, err) - }() - - if !p.graph.Exists(id) { - broadcaster.Write(p.sf.FormatProgress(stringid.TruncateID(id), "Pulling metadata", nil)) - var ( - imgJSON []byte - imgSize int64 - err error - img *image.Image - ) - retries := 5 - for j := 1; j <= retries; j++ { - imgJSON, imgSize, err = p.session.GetRemoteImageJSON(id, endpoint) - if err != nil && j == retries { - broadcaster.Write(p.sf.FormatProgress(stringid.TruncateID(id), "Error pulling dependent layers", nil)) - return layersDownloaded, err - } else if err != nil { - time.Sleep(time.Duration(j) * 500 * time.Millisecond) - continue - } - img, err = image.NewImgJSON(imgJSON) - layersDownloaded = true - if err != nil && j == retries { - broadcaster.Write(p.sf.FormatProgress(stringid.TruncateID(id), "Error pulling dependent layers", nil)) - return layersDownloaded, fmt.Errorf("Failed to parse json: %s", err) - } else if err != nil { - time.Sleep(time.Duration(j) * 500 * time.Millisecond) - continue - } else { - break - } - } - - for j := 1; j <= retries; j++ { - // Get the layer - status := "Pulling fs layer" - if j > 1 { - status = fmt.Sprintf("Pulling fs layer [retries: %d]", j) - } - broadcaster.Write(p.sf.FormatProgress(stringid.TruncateID(id), status, nil)) - layer, err := p.session.GetRemoteImageLayer(img.ID, endpoint, imgSize) - if uerr, ok := err.(*url.Error); ok { - err = uerr.Err - } - if terr, ok := err.(net.Error); ok && terr.Timeout() && j < retries { - time.Sleep(time.Duration(j) * 500 * time.Millisecond) - continue - } else if err != nil { - broadcaster.Write(p.sf.FormatProgress(stringid.TruncateID(id), "Error pulling dependent layers", nil)) - return layersDownloaded, err - } - layersDownloaded = true - defer layer.Close() - - err = p.graph.Register(v1Descriptor{img}, - progressreader.New(progressreader.Config{ - In: layer, - Out: broadcaster, - Formatter: p.sf, - Size: imgSize, - NewLines: false, - ID: stringid.TruncateID(id), - Action: "Downloading", - })) - if terr, ok := err.(net.Error); ok && terr.Timeout() && j < retries { - time.Sleep(time.Duration(j) * 500 * time.Millisecond) - continue - } else if err != nil { - broadcaster.Write(p.sf.FormatProgress(stringid.TruncateID(id), "Error downloading dependent layers", nil)) - return layersDownloaded, err - } else { - break - } - } - } - broadcaster.Write(p.sf.FormatProgress(stringid.TruncateID(id), "Download complete", nil)) - broadcaster.Close() - } - return layersDownloaded, nil -} diff --git a/vendor/github.com/docker/docker/graph/pull_v2.go b/vendor/github.com/docker/docker/graph/pull_v2.go deleted file mode 100644 index 9eb0b5dd..00000000 --- a/vendor/github.com/docker/docker/graph/pull_v2.go +++ /dev/null @@ -1,698 +0,0 @@ -package graph - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "os" - - "github.com/Sirupsen/logrus" - "github.com/docker/distribution" - "github.com/docker/distribution/digest" - "github.com/docker/distribution/manifest/schema1" - "github.com/docker/docker/image" - "github.com/docker/docker/pkg/broadcaster" - "github.com/docker/docker/pkg/progressreader" - "github.com/docker/docker/pkg/streamformatter" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/registry" - "github.com/docker/docker/utils" - "golang.org/x/net/context" -) - -type v2Puller struct { - *TagStore - endpoint registry.APIEndpoint - config *ImagePullConfig - sf *streamformatter.StreamFormatter - repoInfo *registry.RepositoryInfo - repo distribution.Repository - sessionID string -} - -func (p *v2Puller) Pull(tag string) (fallback bool, err error) { - // TODO(tiborvass): was ReceiveTimeout - p.repo, err = newV2Repository(p.repoInfo, p.endpoint, p.config.MetaHeaders, p.config.AuthConfig, "pull") - if err != nil { - logrus.Warnf("Error getting v2 registry: %v", err) - return true, err - } - - p.sessionID = stringid.GenerateRandomID() - - if err := p.pullV2Repository(tag); err != nil { - if registry.ContinueOnError(err) { - logrus.Debugf("Error trying v2 registry: %v", err) - return true, err - } - return false, err - } - return false, nil -} - -func (p *v2Puller) pullV2Repository(tag string) (err error) { - var tags []string - taggedName := p.repoInfo.LocalName - if len(tag) > 0 { - tags = []string{tag} - taggedName = utils.ImageReference(p.repoInfo.LocalName, tag) - } else { - var err error - - manSvc, err := p.repo.Manifests(context.Background()) - if err != nil { - return err - } - - tags, err = manSvc.Tags() - if err != nil { - return err - } - - } - - poolKey := "v2:" + taggedName - broadcaster, found := p.poolAdd("pull", poolKey) - broadcaster.Add(p.config.OutStream) - if found { - // Another pull of the same repository is already taking place; just wait for it to finish - return broadcaster.Wait() - } - - // This must use a closure so it captures the value of err when the - // function returns, not when the 'defer' is evaluated. - defer func() { - p.poolRemoveWithError("pull", poolKey, err) - }() - - var layersDownloaded bool - for _, tag := range tags { - // pulledNew is true if either new layers were downloaded OR if existing images were newly tagged - // TODO(tiborvass): should we change the name of `layersDownload`? What about message in WriteStatus? - pulledNew, err := p.pullV2Tag(broadcaster, tag, taggedName) - if err != nil { - return err - } - layersDownloaded = layersDownloaded || pulledNew - } - - writeStatus(taggedName, broadcaster, p.sf, layersDownloaded) - - return nil -} - -// downloadInfo is used to pass information from download to extractor -type downloadInfo struct { - img contentAddressableDescriptor - imgIndex int - tmpFile *os.File - digest digest.Digest - layer distribution.ReadSeekCloser - size int64 - err chan error - poolKey string - broadcaster *broadcaster.Buffered -} - -// contentAddressableDescriptor is used to pass image data from a manifest to the -// graph. -type contentAddressableDescriptor struct { - id string - parent string - strongID digest.Digest - compatibilityID string - config []byte - v1Compatibility []byte -} - -func newContentAddressableImage(v1Compatibility []byte, blobSum digest.Digest, parent digest.Digest) (contentAddressableDescriptor, error) { - img := contentAddressableDescriptor{ - v1Compatibility: v1Compatibility, - } - - var err error - img.config, err = image.MakeImageConfig(v1Compatibility, blobSum, parent) - if err != nil { - return img, err - } - img.strongID, err = image.StrongID(img.config) - if err != nil { - return img, err - } - - unmarshalledConfig, err := image.NewImgJSON(v1Compatibility) - if err != nil { - return img, err - } - - img.compatibilityID = unmarshalledConfig.ID - img.id = img.strongID.Hex() - - return img, nil -} - -// ID returns the actual ID to be used for the downloaded image. This may be -// a computed ID. -func (img contentAddressableDescriptor) ID() string { - return img.id -} - -// Parent returns the parent ID to be used for the image. This may be a -// computed ID. -func (img contentAddressableDescriptor) Parent() string { - return img.parent -} - -// MarshalConfig renders the image structure into JSON. -func (img contentAddressableDescriptor) MarshalConfig() ([]byte, error) { - return img.config, nil -} - -type errVerification struct{} - -func (errVerification) Error() string { return "verification failed" } - -func (p *v2Puller) download(di *downloadInfo) { - logrus.Debugf("pulling blob %q to %s", di.digest, di.img.id) - - blobs := p.repo.Blobs(context.Background()) - - desc, err := blobs.Stat(context.Background(), di.digest) - if err != nil { - logrus.Debugf("Error statting layer: %v", err) - di.err <- err - return - } - di.size = desc.Size - - layerDownload, err := blobs.Open(context.Background(), di.digest) - if err != nil { - logrus.Debugf("Error fetching layer: %v", err) - di.err <- err - return - } - defer layerDownload.Close() - - verifier, err := digest.NewDigestVerifier(di.digest) - if err != nil { - di.err <- err - return - } - - reader := progressreader.New(progressreader.Config{ - In: ioutil.NopCloser(io.TeeReader(layerDownload, verifier)), - Out: di.broadcaster, - Formatter: p.sf, - Size: di.size, - NewLines: false, - ID: stringid.TruncateID(di.img.id), - Action: "Downloading", - }) - io.Copy(di.tmpFile, reader) - - di.broadcaster.Write(p.sf.FormatProgress(stringid.TruncateID(di.img.id), "Verifying Checksum", nil)) - - if !verifier.Verified() { - err = fmt.Errorf("filesystem layer verification failed for digest %s", di.digest) - logrus.Error(err) - di.err <- err - return - } - - di.broadcaster.Write(p.sf.FormatProgress(stringid.TruncateID(di.img.id), "Download complete", nil)) - - logrus.Debugf("Downloaded %s to tempfile %s", di.img.id, di.tmpFile.Name()) - di.layer = layerDownload - - di.err <- nil -} - -func (p *v2Puller) pullV2Tag(out io.Writer, tag, taggedName string) (tagUpdated bool, err error) { - logrus.Debugf("Pulling tag from V2 registry: %q", tag) - - manSvc, err := p.repo.Manifests(context.Background()) - if err != nil { - return false, err - } - - unverifiedManifest, err := manSvc.GetByTag(tag) - if err != nil { - return false, err - } - if unverifiedManifest == nil { - return false, fmt.Errorf("image manifest does not exist for tag %q", tag) - } - var verifiedManifest *schema1.Manifest - verifiedManifest, err = verifyManifest(unverifiedManifest, tag) - if err != nil { - return false, err - } - - // remove duplicate layers and check parent chain validity - err = fixManifestLayers(verifiedManifest) - if err != nil { - return false, err - } - - imgs, err := p.getImageInfos(verifiedManifest) - if err != nil { - return false, err - } - - out.Write(p.sf.FormatStatus(tag, "Pulling from %s", p.repo.Name())) - - var downloads []*downloadInfo - - var layerIDs []string - defer func() { - p.graph.Release(p.sessionID, layerIDs...) - - for _, d := range downloads { - p.poolRemoveWithError("pull", d.poolKey, err) - if d.tmpFile != nil { - d.tmpFile.Close() - if err := os.RemoveAll(d.tmpFile.Name()); err != nil { - logrus.Errorf("Failed to remove temp file: %s", d.tmpFile.Name()) - } - } - } - }() - - for i := len(verifiedManifest.FSLayers) - 1; i >= 0; i-- { - img := imgs[i] - - p.graph.Retain(p.sessionID, img.id) - layerIDs = append(layerIDs, img.id) - - p.graph.imageMutex.Lock(img.id) - - // Check if exists - if p.graph.Exists(img.id) { - if err := p.validateImageInGraph(img.id, imgs, i); err != nil { - p.graph.imageMutex.Unlock(img.id) - return false, fmt.Errorf("image validation failed: %v", err) - } - logrus.Debugf("Image already exists: %s", img.id) - p.graph.imageMutex.Unlock(img.id) - continue - } - p.graph.imageMutex.Unlock(img.id) - - out.Write(p.sf.FormatProgress(stringid.TruncateID(img.id), "Pulling fs layer", nil)) - - d := &downloadInfo{ - img: img, - imgIndex: i, - poolKey: "v2layer:" + img.id, - digest: verifiedManifest.FSLayers[i].BlobSum, - // TODO: seems like this chan buffer solved hanging problem in go1.5, - // this can indicate some deeper problem that somehow we never take - // error from channel in loop below - err: make(chan error, 1), - } - - tmpFile, err := ioutil.TempFile("", "GetImageBlob") - if err != nil { - return false, err - } - d.tmpFile = tmpFile - - downloads = append(downloads, d) - - broadcaster, found := p.poolAdd("pull", d.poolKey) - broadcaster.Add(out) - d.broadcaster = broadcaster - if found { - d.err <- nil - } else { - go p.download(d) - } - } - - for _, d := range downloads { - if err := <-d.err; err != nil { - return false, err - } - - if d.layer == nil { - // Wait for a different pull to download and extract - // this layer. - err = d.broadcaster.Wait() - if err != nil { - return false, err - } - continue - } - - d.tmpFile.Seek(0, 0) - err := func() error { - reader := progressreader.New(progressreader.Config{ - In: d.tmpFile, - Out: d.broadcaster, - Formatter: p.sf, - Size: d.size, - NewLines: false, - ID: stringid.TruncateID(d.img.id), - Action: "Extracting", - }) - - p.graph.imagesMutex.Lock() - defer p.graph.imagesMutex.Unlock() - - p.graph.imageMutex.Lock(d.img.id) - defer p.graph.imageMutex.Unlock(d.img.id) - - // Must recheck the data on disk if any exists. - // This protects against races where something - // else is written to the graph under this ID - // after attemptIDReuse. - if p.graph.Exists(d.img.id) { - if err := p.validateImageInGraph(d.img.id, imgs, d.imgIndex); err != nil { - return fmt.Errorf("image validation failed: %v", err) - } - } - - if err := p.graph.register(d.img, reader); err != nil { - return err - } - - if err := p.graph.setLayerDigest(d.img.id, d.digest); err != nil { - return err - } - - if err := p.graph.setV1CompatibilityConfig(d.img.id, d.img.v1Compatibility); err != nil { - return err - } - - return nil - }() - if err != nil { - return false, err - } - - d.broadcaster.Write(p.sf.FormatProgress(stringid.TruncateID(d.img.id), "Pull complete", nil)) - d.broadcaster.Close() - tagUpdated = true - } - - manifestDigest, _, err := digestFromManifest(unverifiedManifest, p.repoInfo.LocalName) - if err != nil { - return false, err - } - - // Check for new tag if no layers downloaded - if !tagUpdated { - repo, err := p.get(p.repoInfo.LocalName) - if err != nil { - return false, err - } - if repo != nil { - if _, exists := repo[tag]; !exists { - tagUpdated = true - } - } else { - tagUpdated = true - } - } - - firstID := layerIDs[len(layerIDs)-1] - if utils.DigestReference(tag) { - // TODO(stevvooe): Ideally, we should always set the digest so we can - // use the digest whether we pull by it or not. Unfortunately, the tag - // store treats the digest as a separate tag, meaning there may be an - // untagged digest image that would seem to be dangling by a user. - if err = p.setDigest(p.repoInfo.LocalName, tag, firstID); err != nil { - return false, err - } - } else { - // only set the repository/tag -> image ID mapping when pulling by tag (i.e. not by digest) - if err = p.Tag(p.repoInfo.LocalName, tag, firstID, true); err != nil { - return false, err - } - } - - if manifestDigest != "" { - out.Write(p.sf.FormatStatus("", "Digest: %s", manifestDigest)) - } - - return tagUpdated, nil -} - -func verifyManifest(signedManifest *schema1.SignedManifest, tag string) (m *schema1.Manifest, err error) { - // If pull by digest, then verify the manifest digest. NOTE: It is - // important to do this first, before any other content validation. If the - // digest cannot be verified, don't even bother with those other things. - if manifestDigest, err := digest.ParseDigest(tag); err == nil { - verifier, err := digest.NewDigestVerifier(manifestDigest) - if err != nil { - return nil, err - } - payload, err := signedManifest.Payload() - if err != nil { - // If this failed, the signatures section was corrupted - // or missing. Treat the entire manifest as the payload. - payload = signedManifest.Raw - } - if _, err := verifier.Write(payload); err != nil { - return nil, err - } - if !verifier.Verified() { - err := fmt.Errorf("image verification failed for digest %s", manifestDigest) - logrus.Error(err) - return nil, err - } - - var verifiedManifest schema1.Manifest - if err = json.Unmarshal(payload, &verifiedManifest); err != nil { - return nil, err - } - m = &verifiedManifest - } else { - m = &signedManifest.Manifest - } - - if m.SchemaVersion != 1 { - return nil, fmt.Errorf("unsupported schema version %d for tag %q", m.SchemaVersion, tag) - } - if len(m.FSLayers) != len(m.History) { - return nil, fmt.Errorf("length of history not equal to number of layers for tag %q", tag) - } - if len(m.FSLayers) == 0 { - return nil, fmt.Errorf("no FSLayers in manifest for tag %q", tag) - } - return m, nil -} - -// fixManifestLayers removes repeated layers from the manifest and checks the -// correctness of the parent chain. -func fixManifestLayers(m *schema1.Manifest) error { - images := make([]*image.Image, len(m.FSLayers)) - for i := range m.FSLayers { - img, err := image.NewImgJSON([]byte(m.History[i].V1Compatibility)) - if err != nil { - return err - } - images[i] = img - if err := image.ValidateID(img.ID); err != nil { - return err - } - } - - if images[len(images)-1].Parent != "" { - return errors.New("Invalid parent ID in the base layer of the image.") - } - - // check general duplicates to error instead of a deadlock - idmap := make(map[string]struct{}) - - var lastID string - for _, img := range images { - // skip IDs that appear after each other, we handle those later - if _, exists := idmap[img.ID]; img.ID != lastID && exists { - return fmt.Errorf("ID %+v appears multiple times in manifest", img.ID) - } - lastID = img.ID - idmap[lastID] = struct{}{} - } - - // backwards loop so that we keep the remaining indexes after removing items - for i := len(images) - 2; i >= 0; i-- { - if images[i].ID == images[i+1].ID { // repeated ID. remove and continue - m.FSLayers = append(m.FSLayers[:i], m.FSLayers[i+1:]...) - m.History = append(m.History[:i], m.History[i+1:]...) - } else if images[i].Parent != images[i+1].ID { - return fmt.Errorf("Invalid parent ID. Expected %v, got %v.", images[i+1].ID, images[i].Parent) - } - } - - return nil -} - -// getImageInfos returns an imageinfo struct for every image in the manifest. -// These objects contain both calculated strongIDs and compatibilityIDs found -// in v1Compatibility object. -func (p *v2Puller) getImageInfos(m *schema1.Manifest) ([]contentAddressableDescriptor, error) { - imgs := make([]contentAddressableDescriptor, len(m.FSLayers)) - - var parent digest.Digest - for i := len(imgs) - 1; i >= 0; i-- { - var err error - imgs[i], err = newContentAddressableImage([]byte(m.History[i].V1Compatibility), m.FSLayers[i].BlobSum, parent) - if err != nil { - return nil, err - } - parent = imgs[i].strongID - } - - p.attemptIDReuse(imgs) - - return imgs, nil -} - -// attemptIDReuse does a best attempt to match verified compatibilityIDs -// already in the graph with the computed strongIDs so we can keep using them. -// This process will never fail but may just return the strongIDs if none of -// the compatibilityIDs exists or can be verified. If the strongIDs themselves -// fail verification, we deterministically generate alternate IDs to use until -// we find one that's available or already exists with the correct data. -func (p *v2Puller) attemptIDReuse(imgs []contentAddressableDescriptor) { - // This function needs to be protected with a global lock, because it - // locks multiple IDs at once, and there's no good way to make sure - // the locking happens a deterministic order. - p.graph.imagesMutex.Lock() - defer p.graph.imagesMutex.Unlock() - - idMap := make(map[string]struct{}) - for _, img := range imgs { - idMap[img.id] = struct{}{} - idMap[img.compatibilityID] = struct{}{} - - if p.graph.Exists(img.compatibilityID) { - if _, err := p.graph.generateV1CompatibilityChain(img.compatibilityID); err != nil { - logrus.Debugf("Migration v1Compatibility generation error: %v", err) - return - } - } - } - for id := range idMap { - p.graph.imageMutex.Lock(id) - defer p.graph.imageMutex.Unlock(id) - } - - // continueReuse controls whether the function will try to find - // existing layers on disk under the old v1 IDs, to avoid repulling - // them. The hashes are checked to ensure these layers are okay to - // use. continueReuse starts out as true, but is set to false if - // the code encounters something that doesn't match the expected hash. - continueReuse := true - - for i := len(imgs) - 1; i >= 0; i-- { - if p.graph.Exists(imgs[i].id) { - // Found an image in the graph under the strongID. Validate the - // image before using it. - if err := p.validateImageInGraph(imgs[i].id, imgs, i); err != nil { - continueReuse = false - logrus.Debugf("not using existing strongID: %v", err) - - // The strong ID existed in the graph but didn't - // validate successfully. We can't use the strong ID - // because it didn't validate successfully. Treat the - // graph like a hash table with probing... compute - // SHA256(id) until we find an ID that either doesn't - // already exist in the graph, or has existing content - // that validates successfully. - for { - if err := p.tryNextID(imgs, i, idMap); err != nil { - logrus.Debug(err.Error()) - } else { - break - } - } - } - continue - } - - if continueReuse { - compatibilityID := imgs[i].compatibilityID - if err := p.validateImageInGraph(compatibilityID, imgs, i); err != nil { - logrus.Debugf("stopping ID reuse: %v", err) - continueReuse = false - } else { - // The compatibility ID exists in the graph and was - // validated. Use it. - imgs[i].id = compatibilityID - } - } - } - - // fix up the parents of the images - for i := 0; i < len(imgs); i++ { - if i == len(imgs)-1 { // Base layer - imgs[i].parent = "" - } else { - imgs[i].parent = imgs[i+1].id - } - } -} - -// validateImageInGraph checks that an image in the graph has the expected -// strongID. id is the entry in the graph to check, imgs is the slice of -// images being processed (for access to the parent), and i is the index -// into this slice which the graph entry should be checked against. -func (p *v2Puller) validateImageInGraph(id string, imgs []contentAddressableDescriptor, i int) error { - img, err := p.graph.Get(id) - if err != nil { - return fmt.Errorf("missing: %v", err) - } - layerID, err := p.graph.getLayerDigest(id) - if err != nil { - return fmt.Errorf("digest: %v", err) - } - var parentID digest.Digest - if i != len(imgs)-1 { - if img.Parent != imgs[i+1].id { // comparing that graph points to validated ID - return fmt.Errorf("parent: %v %v", img.Parent, imgs[i+1].id) - } - parentID = imgs[i+1].strongID - } else if img.Parent != "" { - return fmt.Errorf("unexpected parent: %v", img.Parent) - } - - v1Config, err := p.graph.getV1CompatibilityConfig(img.ID) - if err != nil { - return fmt.Errorf("v1Compatibility: %v %v", img.ID, err) - } - - json, err := image.MakeImageConfig(v1Config, layerID, parentID) - if err != nil { - return fmt.Errorf("make config: %v", err) - } - - if dgst, err := image.StrongID(json); err == nil && dgst == imgs[i].strongID { - logrus.Debugf("Validated %v as %v", dgst, id) - } else { - return fmt.Errorf("digest mismatch: %v %v, error: %v", dgst, imgs[i].strongID, err) - } - - // All clear - return nil -} - -func (p *v2Puller) tryNextID(imgs []contentAddressableDescriptor, i int, idMap map[string]struct{}) error { - nextID, _ := digest.FromBytes([]byte(imgs[i].id)) - imgs[i].id = nextID.Hex() - - if _, exists := idMap[imgs[i].id]; !exists { - p.graph.imageMutex.Lock(imgs[i].id) - defer p.graph.imageMutex.Unlock(imgs[i].id) - } - - if p.graph.Exists(imgs[i].id) { - if err := p.validateImageInGraph(imgs[i].id, imgs, i); err != nil { - return fmt.Errorf("not using existing strongID permutation %s: %v", imgs[i].id, err) - } - } - return nil -} diff --git a/vendor/github.com/docker/docker/graph/pull_v2_test.go b/vendor/github.com/docker/docker/graph/pull_v2_test.go deleted file mode 100644 index f7ec1e28..00000000 --- a/vendor/github.com/docker/docker/graph/pull_v2_test.go +++ /dev/null @@ -1,195 +0,0 @@ -package graph - -import ( - "encoding/json" - "io/ioutil" - "reflect" - "strings" - "testing" - - "github.com/docker/distribution/digest" - "github.com/docker/distribution/manifest/schema1" -) - -// TestFixManifestLayers checks that fixManifestLayers removes a duplicate -// layer, and that it makes no changes to the manifest when called a second -// time, after the duplicate is removed. -func TestFixManifestLayers(t *testing.T) { - duplicateLayerManifest := schema1.Manifest{ - FSLayers: []schema1.FSLayer{ - {BlobSum: digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4")}, - {BlobSum: digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4")}, - {BlobSum: digest.Digest("sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa")}, - }, - History: []schema1.History{ - {V1Compatibility: "{\"id\":\"3b38edc92eb7c074812e217b41a6ade66888531009d6286a6f5f36a06f9841b9\",\"parent\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:11.368300679Z\",\"container\":\"d91be3479d5b1e84b0c00d18eea9dc777ca0ad166d51174b24283e2e6f104253\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ENTRYPOINT [\\\"/go/bin/dnsdock\\\"]\"],\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":null,\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n"}, - {V1Compatibility: "{\"id\":\"3b38edc92eb7c074812e217b41a6ade66888531009d6286a6f5f36a06f9841b9\",\"parent\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:11.368300679Z\",\"container\":\"d91be3479d5b1e84b0c00d18eea9dc777ca0ad166d51174b24283e2e6f104253\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ENTRYPOINT [\\\"/go/bin/dnsdock\\\"]\"],\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":null,\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n"}, - {V1Compatibility: "{\"id\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:07.568027497Z\",\"container\":\"fe9e5a5264a843c9292d17b736c92dd19bdb49986a8782d7389964ddaff887cc\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"cd /go/src/github.com/tonistiigi/dnsdock \\u0026\\u0026 go get -v github.com/tools/godep \\u0026\\u0026 godep restore \\u0026\\u0026 go install -ldflags \\\"-X main.version `git describe --tags HEAD``if [[ -n $(command git status --porcelain --untracked-files=no 2\\u003e/dev/null) ]]; then echo \\\"-dirty\\\"; fi`\\\" ./...\"],\"Image\":\"e3b0ff09e647595dafee15c54cd632c900df9e82b1d4d313b1e20639a1461779\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/bash\"],\"Image\":\"e3b0ff09e647595dafee15c54cd632c900df9e82b1d4d313b1e20639a1461779\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":118430532}\n"}, - }, - } - - duplicateLayerManifestExpectedOutput := schema1.Manifest{ - FSLayers: []schema1.FSLayer{ - {BlobSum: digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4")}, - {BlobSum: digest.Digest("sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa")}, - }, - History: []schema1.History{ - {V1Compatibility: "{\"id\":\"3b38edc92eb7c074812e217b41a6ade66888531009d6286a6f5f36a06f9841b9\",\"parent\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:11.368300679Z\",\"container\":\"d91be3479d5b1e84b0c00d18eea9dc777ca0ad166d51174b24283e2e6f104253\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ENTRYPOINT [\\\"/go/bin/dnsdock\\\"]\"],\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":null,\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n"}, - {V1Compatibility: "{\"id\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:07.568027497Z\",\"container\":\"fe9e5a5264a843c9292d17b736c92dd19bdb49986a8782d7389964ddaff887cc\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"cd /go/src/github.com/tonistiigi/dnsdock \\u0026\\u0026 go get -v github.com/tools/godep \\u0026\\u0026 godep restore \\u0026\\u0026 go install -ldflags \\\"-X main.version `git describe --tags HEAD``if [[ -n $(command git status --porcelain --untracked-files=no 2\\u003e/dev/null) ]]; then echo \\\"-dirty\\\"; fi`\\\" ./...\"],\"Image\":\"e3b0ff09e647595dafee15c54cd632c900df9e82b1d4d313b1e20639a1461779\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/bash\"],\"Image\":\"e3b0ff09e647595dafee15c54cd632c900df9e82b1d4d313b1e20639a1461779\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":118430532}\n"}, - }, - } - - if err := fixManifestLayers(&duplicateLayerManifest); err != nil { - t.Fatalf("unexpected error from fixManifestLayers: %v", err) - } - - if !reflect.DeepEqual(duplicateLayerManifest, duplicateLayerManifestExpectedOutput) { - t.Fatal("incorrect output from fixManifestLayers on duplicate layer manifest") - } - - // Run fixManifestLayers again and confirm that it doesn't change the - // manifest (which no longer has duplicate layers). - if err := fixManifestLayers(&duplicateLayerManifest); err != nil { - t.Fatalf("unexpected error from fixManifestLayers: %v", err) - } - - if !reflect.DeepEqual(duplicateLayerManifest, duplicateLayerManifestExpectedOutput) { - t.Fatal("incorrect output from fixManifestLayers on duplicate layer manifest (second pass)") - } -} - -// TestFixManifestLayersBaseLayerParent makes sure that fixManifestLayers fails -// if the base layer configuration specifies a parent. -func TestFixManifestLayersBaseLayerParent(t *testing.T) { - duplicateLayerManifest := schema1.Manifest{ - FSLayers: []schema1.FSLayer{ - {BlobSum: digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4")}, - {BlobSum: digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4")}, - {BlobSum: digest.Digest("sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa")}, - }, - History: []schema1.History{ - {V1Compatibility: "{\"id\":\"3b38edc92eb7c074812e217b41a6ade66888531009d6286a6f5f36a06f9841b9\",\"parent\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:11.368300679Z\",\"container\":\"d91be3479d5b1e84b0c00d18eea9dc777ca0ad166d51174b24283e2e6f104253\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ENTRYPOINT [\\\"/go/bin/dnsdock\\\"]\"],\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":null,\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n"}, - {V1Compatibility: "{\"id\":\"3b38edc92eb7c074812e217b41a6ade66888531009d6286a6f5f36a06f9841b9\",\"parent\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:11.368300679Z\",\"container\":\"d91be3479d5b1e84b0c00d18eea9dc777ca0ad166d51174b24283e2e6f104253\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ENTRYPOINT [\\\"/go/bin/dnsdock\\\"]\"],\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":null,\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n"}, - {V1Compatibility: "{\"id\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"parent\":\"e3b0ff09e647595dafee15c54cd632c900df9e82b1d4d313b1e20639a1461779\",\"created\":\"2015-08-19T16:49:07.568027497Z\",\"container\":\"fe9e5a5264a843c9292d17b736c92dd19bdb49986a8782d7389964ddaff887cc\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"cd /go/src/github.com/tonistiigi/dnsdock \\u0026\\u0026 go get -v github.com/tools/godep \\u0026\\u0026 godep restore \\u0026\\u0026 go install -ldflags \\\"-X main.version `git describe --tags HEAD``if [[ -n $(command git status --porcelain --untracked-files=no 2\\u003e/dev/null) ]]; then echo \\\"-dirty\\\"; fi`\\\" ./...\"],\"Image\":\"e3b0ff09e647595dafee15c54cd632c900df9e82b1d4d313b1e20639a1461779\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/bash\"],\"Image\":\"e3b0ff09e647595dafee15c54cd632c900df9e82b1d4d313b1e20639a1461779\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":118430532}\n"}, - }, - } - - if err := fixManifestLayers(&duplicateLayerManifest); err == nil || !strings.Contains(err.Error(), "Invalid parent ID in the base layer of the image.") { - t.Fatalf("expected an invalid parent ID error from fixManifestLayers") - } -} - -// TestFixManifestLayersBadParent makes sure that fixManifestLayers fails -// if an image configuration specifies a parent that doesn't directly follow -// that (deduplicated) image in the image history. -func TestFixManifestLayersBadParent(t *testing.T) { - duplicateLayerManifest := schema1.Manifest{ - FSLayers: []schema1.FSLayer{ - {BlobSum: digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4")}, - {BlobSum: digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4")}, - {BlobSum: digest.Digest("sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa")}, - }, - History: []schema1.History{ - {V1Compatibility: "{\"id\":\"3b38edc92eb7c074812e217b41a6ade66888531009d6286a6f5f36a06f9841b9\",\"parent\":\"ac3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:11.368300679Z\",\"container\":\"d91be3479d5b1e84b0c00d18eea9dc777ca0ad166d51174b24283e2e6f104253\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ENTRYPOINT [\\\"/go/bin/dnsdock\\\"]\"],\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":null,\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n"}, - {V1Compatibility: "{\"id\":\"3b38edc92eb7c074812e217b41a6ade66888531009d6286a6f5f36a06f9841b9\",\"parent\":\"ac3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:11.368300679Z\",\"container\":\"d91be3479d5b1e84b0c00d18eea9dc777ca0ad166d51174b24283e2e6f104253\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ENTRYPOINT [\\\"/go/bin/dnsdock\\\"]\"],\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":null,\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n"}, - {V1Compatibility: "{\"id\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:07.568027497Z\",\"container\":\"fe9e5a5264a843c9292d17b736c92dd19bdb49986a8782d7389964ddaff887cc\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"cd /go/src/github.com/tonistiigi/dnsdock \\u0026\\u0026 go get -v github.com/tools/godep \\u0026\\u0026 godep restore \\u0026\\u0026 go install -ldflags \\\"-X main.version `git describe --tags HEAD``if [[ -n $(command git status --porcelain --untracked-files=no 2\\u003e/dev/null) ]]; then echo \\\"-dirty\\\"; fi`\\\" ./...\"],\"Image\":\"e3b0ff09e647595dafee15c54cd632c900df9e82b1d4d313b1e20639a1461779\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/bash\"],\"Image\":\"e3b0ff09e647595dafee15c54cd632c900df9e82b1d4d313b1e20639a1461779\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":118430532}\n"}, - }, - } - - if err := fixManifestLayers(&duplicateLayerManifest); err == nil || !strings.Contains(err.Error(), "Invalid parent ID.") { - t.Fatalf("expected an invalid parent ID error from fixManifestLayers") - } -} - -// TestValidateManifest verifies the validateManifest function -func TestValidateManifest(t *testing.T) { - expectedDigest := "sha256:02fee8c3220ba806531f606525eceb83f4feb654f62b207191b1c9209188dedd" - expectedFSLayer0 := digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4") - - // Good manifest - - goodManifestBytes, err := ioutil.ReadFile("fixtures/validate_manifest/good_manifest") - if err != nil { - t.Fatal("error reading fixture:", err) - } - - var goodSignedManifest schema1.SignedManifest - err = json.Unmarshal(goodManifestBytes, &goodSignedManifest) - if err != nil { - t.Fatal("error unmarshaling manifest:", err) - } - - verifiedManifest, err := verifyManifest(&goodSignedManifest, expectedDigest) - if err != nil { - t.Fatal("validateManifest failed:", err) - } - - if verifiedManifest.FSLayers[0].BlobSum != expectedFSLayer0 { - t.Fatal("unexpected FSLayer in good manifest") - } - - // "Extra data" manifest - - extraDataManifestBytes, err := ioutil.ReadFile("fixtures/validate_manifest/extra_data_manifest") - if err != nil { - t.Fatal("error reading fixture:", err) - } - - var extraDataSignedManifest schema1.SignedManifest - err = json.Unmarshal(extraDataManifestBytes, &extraDataSignedManifest) - if err != nil { - t.Fatal("error unmarshaling manifest:", err) - } - - verifiedManifest, err = verifyManifest(&extraDataSignedManifest, expectedDigest) - if err != nil { - t.Fatal("validateManifest failed:", err) - } - - if verifiedManifest.FSLayers[0].BlobSum != expectedFSLayer0 { - t.Fatal("unexpected FSLayer in extra data manifest") - } - - // Bad manifest - - badManifestBytes, err := ioutil.ReadFile("fixtures/validate_manifest/bad_manifest") - if err != nil { - t.Fatal("error reading fixture:", err) - } - - var badSignedManifest schema1.SignedManifest - err = json.Unmarshal(badManifestBytes, &badSignedManifest) - if err != nil { - t.Fatal("error unmarshaling manifest:", err) - } - - verifiedManifest, err = verifyManifest(&badSignedManifest, expectedDigest) - if err == nil || !strings.HasPrefix(err.Error(), "image verification failed for digest") { - t.Fatal("expected validateManifest to fail with digest error") - } - - // Manifest with no signature - - expectedWholeFileDigest := "7ec3615a120efcdfc270e9c7ea4183330775a3e52a09e2efb194b9a7c18e5ff7" - - noSignatureManifestBytes, err := ioutil.ReadFile("fixtures/validate_manifest/no_signature_manifest") - if err != nil { - t.Fatal("error reading fixture:", err) - } - - var noSignatureSignedManifest schema1.SignedManifest - noSignatureSignedManifest.Raw = noSignatureManifestBytes - err = json.Unmarshal(noSignatureManifestBytes, &noSignatureSignedManifest.Manifest) - if err != nil { - t.Fatal("error unmarshaling manifest:", err) - } - - verifiedManifest, err = verifyManifest(&noSignatureSignedManifest, expectedWholeFileDigest) - if err != nil { - t.Fatal("validateManifest failed:", err) - } - - if verifiedManifest.FSLayers[0].BlobSum != expectedFSLayer0 { - t.Fatal("unexpected FSLayer in no-signature manifest") - } -} diff --git a/vendor/github.com/docker/docker/graph/push.go b/vendor/github.com/docker/docker/graph/push.go deleted file mode 100644 index 750eec50..00000000 --- a/vendor/github.com/docker/docker/graph/push.go +++ /dev/null @@ -1,126 +0,0 @@ -package graph - -import ( - "fmt" - "io" - - "github.com/Sirupsen/logrus" - "github.com/docker/distribution/digest" - "github.com/docker/docker/cliconfig" - "github.com/docker/docker/pkg/streamformatter" - "github.com/docker/docker/registry" -) - -// ImagePushConfig stores push configuration. -type ImagePushConfig struct { - // MetaHeaders store HTTP headers with metadata about the image - // (DockerHeaders with prefix X-Meta- in the request). - MetaHeaders map[string][]string - // AuthConfig holds authentication credentials for authenticating with - // the registry. - AuthConfig *cliconfig.AuthConfig - // Tag is the specific variant of the image to be pushed. - // If no tag is provided, all tags will be pushed. - Tag string - // OutStream is the output writer for showing the status of the push - // operation. - OutStream io.Writer -} - -// pusher is an interface that abstracts pushing for different API versions. -type pusher interface { - // Push tries to push the image configured at the creation of Pusher. - // Push returns an error if any, as well as a boolean that determines whether to retry Push on the next configured endpoint. - // - // TODO(tiborvass): have Push() take a reference to repository + tag, so that the pusher itself is repository-agnostic. - Push() (fallback bool, err error) -} - -// newPusher creates a new Pusher interface that will push to either a v1 or v2 -// registry. The endpoint argument contains a Version field that determines -// whether a v1 or v2 pusher will be created. The other parameters are passed -// through to the underlying pusher implementation for use during the actual -// push operation. -func (s *TagStore) newPusher(endpoint registry.APIEndpoint, localRepo repository, repoInfo *registry.RepositoryInfo, imagePushConfig *ImagePushConfig, sf *streamformatter.StreamFormatter) (pusher, error) { - switch endpoint.Version { - case registry.APIVersion2: - return &v2Pusher{ - TagStore: s, - endpoint: endpoint, - localRepo: localRepo, - repoInfo: repoInfo, - config: imagePushConfig, - sf: sf, - layersPushed: make(map[digest.Digest]bool), - }, nil - case registry.APIVersion1: - return &v1Pusher{ - TagStore: s, - endpoint: endpoint, - localRepo: localRepo, - repoInfo: repoInfo, - config: imagePushConfig, - sf: sf, - }, nil - } - return nil, fmt.Errorf("unknown version %d for registry %s", endpoint.Version, endpoint.URL) -} - -// Push initiates a push operation on the repository named localName. -func (s *TagStore) Push(localName string, imagePushConfig *ImagePushConfig) error { - // FIXME: Allow to interrupt current push when new push of same image is done. - - var sf = streamformatter.NewJSONStreamFormatter() - - // Resolve the Repository name from fqn to RepositoryInfo - repoInfo, err := s.registryService.ResolveRepository(localName) - if err != nil { - return err - } - - endpoints, err := s.registryService.LookupPushEndpoints(repoInfo.CanonicalName) - if err != nil { - return err - } - - reposLen := 1 - if imagePushConfig.Tag == "" { - reposLen = len(s.Repositories[repoInfo.LocalName]) - } - - imagePushConfig.OutStream.Write(sf.FormatStatus("", "The push refers to a repository [%s] (len: %d)", repoInfo.CanonicalName, reposLen)) - - // If it fails, try to get the repository - localRepo, exists := s.Repositories[repoInfo.LocalName] - if !exists { - return fmt.Errorf("Repository does not exist: %s", repoInfo.LocalName) - } - - var lastErr error - for _, endpoint := range endpoints { - logrus.Debugf("Trying to push %s to %s %s", repoInfo.CanonicalName, endpoint.URL, endpoint.Version) - - pusher, err := s.newPusher(endpoint, localRepo, repoInfo, imagePushConfig, sf) - if err != nil { - lastErr = err - continue - } - if fallback, err := pusher.Push(); err != nil { - if fallback { - lastErr = err - continue - } - logrus.Debugf("Not continuing with error: %v", err) - return err - - } - - s.eventsService.Log("push", repoInfo.LocalName, "") - return nil - } - - if lastErr == nil { - lastErr = fmt.Errorf("no endpoints found for %s", repoInfo.CanonicalName) - } - return lastErr -} diff --git a/vendor/github.com/docker/docker/graph/push_v1.go b/vendor/github.com/docker/docker/graph/push_v1.go deleted file mode 100644 index 01ad73ed..00000000 --- a/vendor/github.com/docker/docker/graph/push_v1.go +++ /dev/null @@ -1,354 +0,0 @@ -package graph - -import ( - "fmt" - "io" - "os" - "sync" - - "github.com/Sirupsen/logrus" - "github.com/docker/distribution/registry/client/transport" - "github.com/docker/docker/image" - "github.com/docker/docker/pkg/ioutils" - "github.com/docker/docker/pkg/progressreader" - "github.com/docker/docker/pkg/streamformatter" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/registry" - "github.com/docker/docker/utils" -) - -type v1Pusher struct { - *TagStore - endpoint registry.APIEndpoint - localRepo repository - repoInfo *registry.RepositoryInfo - config *ImagePushConfig - sf *streamformatter.StreamFormatter - session *registry.Session - - out io.Writer -} - -func (p *v1Pusher) Push() (fallback bool, err error) { - tlsConfig, err := p.registryService.TLSConfig(p.repoInfo.Index.Name) - if err != nil { - return false, err - } - // Adds Docker-specific headers as well as user-specified headers (metaHeaders) - tr := transport.NewTransport( - // TODO(tiborvass): was NoTimeout - registry.NewTransport(tlsConfig), - registry.DockerHeaders(p.config.MetaHeaders)..., - ) - client := registry.HTTPClient(tr) - v1Endpoint, err := p.endpoint.ToV1Endpoint(p.config.MetaHeaders) - if err != nil { - logrus.Debugf("Could not get v1 endpoint: %v", err) - return true, err - } - p.session, err = registry.NewSession(client, p.config.AuthConfig, v1Endpoint) - if err != nil { - // TODO(dmcgowan): Check if should fallback - return true, err - } - if err := p.pushRepository(p.config.Tag); err != nil { - // TODO(dmcgowan): Check if should fallback - return false, err - } - return false, nil -} - -// Retrieve the all the images to be uploaded in the correct order -func (p *v1Pusher) getImageList(requestedTag string) ([]string, map[string][]string, error) { - var ( - imageList []string - imagesSeen = make(map[string]bool) - tagsByImage = make(map[string][]string) - ) - - for tag, id := range p.localRepo { - if requestedTag != "" && requestedTag != tag { - // Include only the requested tag. - continue - } - - if utils.DigestReference(tag) { - // Ignore digest references. - continue - } - - var imageListForThisTag []string - - tagsByImage[id] = append(tagsByImage[id], tag) - - for img, err := p.graph.Get(id); img != nil; img, err = p.graph.GetParent(img) { - if err != nil { - return nil, nil, err - } - - if imagesSeen[img.ID] { - // This image is already on the list, we can ignore it and all its parents - break - } - - imagesSeen[img.ID] = true - imageListForThisTag = append(imageListForThisTag, img.ID) - } - - // reverse the image list for this tag (so the "most"-parent image is first) - for i, j := 0, len(imageListForThisTag)-1; i < j; i, j = i+1, j-1 { - imageListForThisTag[i], imageListForThisTag[j] = imageListForThisTag[j], imageListForThisTag[i] - } - - // append to main image list - imageList = append(imageList, imageListForThisTag...) - } - if len(imageList) == 0 { - return nil, nil, fmt.Errorf("No images found for the requested repository / tag") - } - logrus.Debugf("Image list: %v", imageList) - logrus.Debugf("Tags by image: %v", tagsByImage) - - return imageList, tagsByImage, nil -} - -// createImageIndex returns an index of an image's layer IDs and tags. -func (s *TagStore) createImageIndex(images []string, tags map[string][]string) []*registry.ImgData { - var imageIndex []*registry.ImgData - for _, id := range images { - if tags, hasTags := tags[id]; hasTags { - // If an image has tags you must add an entry in the image index - // for each tag - for _, tag := range tags { - imageIndex = append(imageIndex, ®istry.ImgData{ - ID: id, - Tag: tag, - }) - } - continue - } - // If the image does not have a tag it still needs to be sent to the - // registry with an empty tag so that it is associated with the repository - imageIndex = append(imageIndex, ®istry.ImgData{ - ID: id, - Tag: "", - }) - } - return imageIndex -} - -type imagePushData struct { - id string - compatibilityID string - endpoint string -} - -// lookupImageOnEndpoint checks the specified endpoint to see if an image exists -// and if it is absent then it sends the image id to the channel to be pushed. -func (p *v1Pusher) lookupImageOnEndpoint(wg *sync.WaitGroup, images chan imagePushData, imagesToPush chan string) { - defer wg.Done() - for image := range images { - if err := p.session.LookupRemoteImage(image.compatibilityID, image.endpoint); err != nil { - logrus.Errorf("Error in LookupRemoteImage: %s", err) - imagesToPush <- image.id - continue - } - p.out.Write(p.sf.FormatStatus("", "Image %s already pushed, skipping", stringid.TruncateID(image.id))) - } -} - -func (p *v1Pusher) pushImageToEndpoint(endpoint string, imageIDs []string, tags map[string][]string, repo *registry.RepositoryData) error { - workerCount := len(imageIDs) - // start a maximum of 5 workers to check if images exist on the specified endpoint. - if workerCount > 5 { - workerCount = 5 - } - var ( - wg = &sync.WaitGroup{} - imageData = make(chan imagePushData, workerCount*2) - imagesToPush = make(chan string, workerCount*2) - pushes = make(chan map[string]struct{}, 1) - ) - for i := 0; i < workerCount; i++ { - wg.Add(1) - go p.lookupImageOnEndpoint(wg, imageData, imagesToPush) - } - // start a go routine that consumes the images to push - go func() { - shouldPush := make(map[string]struct{}) - for id := range imagesToPush { - shouldPush[id] = struct{}{} - } - pushes <- shouldPush - }() - for _, id := range imageIDs { - compatibilityID, err := p.getV1ID(id) - if err != nil { - return err - } - imageData <- imagePushData{ - id: id, - compatibilityID: compatibilityID, - endpoint: endpoint, - } - } - // close the channel to notify the workers that there will be no more images to check. - close(imageData) - wg.Wait() - close(imagesToPush) - // wait for all the images that require pushes to be collected into a consumable map. - shouldPush := <-pushes - // finish by pushing any images and tags to the endpoint. The order that the images are pushed - // is very important that is why we are still iterating over the ordered list of imageIDs. - for _, id := range imageIDs { - if _, push := shouldPush[id]; push { - if _, err := p.pushImage(id, endpoint); err != nil { - // FIXME: Continue on error? - return err - } - } - for _, tag := range tags[id] { - p.out.Write(p.sf.FormatStatus("", "Pushing tag for rev [%s] on {%s}", stringid.TruncateID(id), endpoint+"repositories/"+p.repoInfo.RemoteName+"/tags/"+tag)) - compatibilityID, err := p.getV1ID(id) - if err != nil { - return err - } - if err := p.session.PushRegistryTag(p.repoInfo.RemoteName, compatibilityID, tag, endpoint); err != nil { - return err - } - } - } - return nil -} - -// pushRepository pushes layers that do not already exist on the registry. -func (p *v1Pusher) pushRepository(tag string) error { - logrus.Debugf("Local repo: %s", p.localRepo) - p.out = ioutils.NewWriteFlusher(p.config.OutStream) - imgList, tags, err := p.getImageList(tag) - if err != nil { - return err - } - p.out.Write(p.sf.FormatStatus("", "Sending image list")) - - imageIndex := p.createImageIndex(imgList, tags) - logrus.Debugf("Preparing to push %s with the following images and tags", p.localRepo) - for _, data := range imageIndex { - logrus.Debugf("Pushing ID: %s with Tag: %s", data.ID, data.Tag) - - // convert IDs to compatibilityIDs, imageIndex only used in registry calls - data.ID, err = p.getV1ID(data.ID) - if err != nil { - return err - } - } - - if _, found := p.poolAdd("push", p.repoInfo.LocalName); found { - return fmt.Errorf("push or pull %s is already in progress", p.repoInfo.LocalName) - } - defer p.poolRemove("push", p.repoInfo.LocalName) - - // Register all the images in a repository with the registry - // If an image is not in this list it will not be associated with the repository - repoData, err := p.session.PushImageJSONIndex(p.repoInfo.RemoteName, imageIndex, false, nil) - if err != nil { - return err - } - nTag := 1 - if tag == "" { - nTag = len(p.localRepo) - } - p.out.Write(p.sf.FormatStatus("", "Pushing repository %s (%d tags)", p.repoInfo.CanonicalName, nTag)) - // push the repository to each of the endpoints only if it does not exist. - for _, endpoint := range repoData.Endpoints { - if err := p.pushImageToEndpoint(endpoint, imgList, tags, repoData); err != nil { - return err - } - } - _, err = p.session.PushImageJSONIndex(p.repoInfo.RemoteName, imageIndex, true, repoData.Endpoints) - return err -} - -func (p *v1Pusher) pushImage(imgID, ep string) (checksum string, err error) { - jsonRaw, err := p.getV1Config(imgID) - if err != nil { - return "", fmt.Errorf("Cannot retrieve the path for {%s}: %s", imgID, err) - } - p.out.Write(p.sf.FormatProgress(stringid.TruncateID(imgID), "Pushing", nil)) - - compatibilityID, err := p.getV1ID(imgID) - if err != nil { - return "", err - } - - // General rule is to use ID for graph accesses and compatibilityID for - // calls to session.registry() - imgData := ®istry.ImgData{ - ID: compatibilityID, - } - - // Send the json - if err := p.session.PushImageJSONRegistry(imgData, jsonRaw, ep); err != nil { - if err == registry.ErrAlreadyExists { - p.out.Write(p.sf.FormatProgress(stringid.TruncateID(imgID), "Image already pushed, skipping", nil)) - return "", nil - } - return "", err - } - - layerData, err := p.graph.tempLayerArchive(imgID, p.sf, p.out) - if err != nil { - return "", fmt.Errorf("Failed to generate layer archive: %s", err) - } - defer os.RemoveAll(layerData.Name()) - - // Send the layer - logrus.Debugf("rendered layer for %s of [%d] size", imgID, layerData.Size) - - checksum, checksumPayload, err := p.session.PushImageLayerRegistry(imgData.ID, - progressreader.New(progressreader.Config{ - In: layerData, - Out: p.out, - Formatter: p.sf, - Size: layerData.Size, - NewLines: false, - ID: stringid.TruncateID(imgID), - Action: "Pushing", - }), ep, jsonRaw) - if err != nil { - return "", err - } - imgData.Checksum = checksum - imgData.ChecksumPayload = checksumPayload - // Send the checksum - if err := p.session.PushImageChecksumRegistry(imgData, ep); err != nil { - return "", err - } - - p.out.Write(p.sf.FormatProgress(stringid.TruncateID(imgID), "Image successfully pushed", nil)) - return imgData.Checksum, nil -} - -// getV1ID returns the compatibilityID for the ID in the graph. compatibilityID -// is read from from the v1Compatibility config file in the disk. -func (p *v1Pusher) getV1ID(id string) (string, error) { - jsonData, err := p.getV1Config(id) - if err != nil { - return "", err - } - img, err := image.NewImgJSON(jsonData) - if err != nil { - return "", err - } - return img.ID, nil -} - -// getV1Config returns v1Compatibility config for the image in the graph. If -// there is no v1Compatibility file on disk for the image -func (p *v1Pusher) getV1Config(id string) ([]byte, error) { - jsonData, err := p.graph.generateV1CompatibilityChain(id) - if err != nil { - return nil, err - } - return jsonData, nil -} diff --git a/vendor/github.com/docker/docker/graph/push_v2.go b/vendor/github.com/docker/docker/graph/push_v2.go deleted file mode 100644 index 8586fa91..00000000 --- a/vendor/github.com/docker/docker/graph/push_v2.go +++ /dev/null @@ -1,301 +0,0 @@ -package graph - -import ( - "bufio" - "compress/gzip" - "fmt" - "io" - "io/ioutil" - - "github.com/Sirupsen/logrus" - "github.com/docker/distribution" - "github.com/docker/distribution/digest" - "github.com/docker/distribution/manifest" - "github.com/docker/distribution/manifest/schema1" - "github.com/docker/docker/image" - "github.com/docker/docker/pkg/progressreader" - "github.com/docker/docker/pkg/streamformatter" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/registry" - "github.com/docker/docker/runconfig" - "github.com/docker/docker/utils" - "golang.org/x/net/context" -) - -const compressionBufSize = 32768 - -type v2Pusher struct { - *TagStore - endpoint registry.APIEndpoint - localRepo repository - repoInfo *registry.RepositoryInfo - config *ImagePushConfig - sf *streamformatter.StreamFormatter - repo distribution.Repository - - // layersPushed is the set of layers known to exist on the remote side. - // This avoids redundant queries when pushing multiple tags that - // involve the same layers. - layersPushed map[digest.Digest]bool -} - -func (p *v2Pusher) Push() (fallback bool, err error) { - p.repo, err = newV2Repository(p.repoInfo, p.endpoint, p.config.MetaHeaders, p.config.AuthConfig, "push", "pull") - if err != nil { - logrus.Debugf("Error getting v2 registry: %v", err) - return true, err - } - return false, p.pushV2Repository(p.config.Tag) -} - -func (p *v2Pusher) getImageTags(askedTag string) ([]string, error) { - logrus.Debugf("Checking %q against %#v", askedTag, p.localRepo) - if len(askedTag) > 0 { - if _, ok := p.localRepo[askedTag]; !ok || utils.DigestReference(askedTag) { - return nil, fmt.Errorf("Tag does not exist for %s", askedTag) - } - return []string{askedTag}, nil - } - var tags []string - for tag := range p.localRepo { - if !utils.DigestReference(tag) { - tags = append(tags, tag) - } - } - return tags, nil -} - -func (p *v2Pusher) pushV2Repository(tag string) error { - localName := p.repoInfo.LocalName - if _, found := p.poolAdd("push", localName); found { - return fmt.Errorf("push or pull %s is already in progress", localName) - } - defer p.poolRemove("push", localName) - - tags, err := p.getImageTags(tag) - if err != nil { - return fmt.Errorf("error getting tags for %s: %s", localName, err) - } - if len(tags) == 0 { - return fmt.Errorf("no tags to push for %s", localName) - } - - for _, tag := range tags { - if err := p.pushV2Tag(tag); err != nil { - return err - } - } - - return nil -} - -func (p *v2Pusher) pushV2Tag(tag string) error { - logrus.Debugf("Pushing repository: %s:%s", p.repo.Name(), tag) - - layerID, exists := p.localRepo[tag] - if !exists { - return fmt.Errorf("tag does not exist: %s", tag) - } - - layersSeen := make(map[string]bool) - - layer, err := p.graph.Get(layerID) - if err != nil { - return err - } - - m := &schema1.Manifest{ - Versioned: manifest.Versioned{ - SchemaVersion: 1, - }, - Name: p.repo.Name(), - Tag: tag, - Architecture: layer.Architecture, - FSLayers: []schema1.FSLayer{}, - History: []schema1.History{}, - } - - var metadata runconfig.Config - if layer != nil && layer.Config != nil { - metadata = *layer.Config - } - - out := p.config.OutStream - - for ; layer != nil; layer, err = p.graph.GetParent(layer) { - if err != nil { - return err - } - - // break early if layer has already been seen in this image, - // this prevents infinite loops on layers which loopback, this - // cannot be prevented since layer IDs are not merkle hashes - // TODO(dmcgowan): throw error if no valid use case is found - if layersSeen[layer.ID] { - break - } - - logrus.Debugf("Pushing layer: %s", layer.ID) - - if layer.Config != nil && metadata.Image != layer.ID { - if err := runconfig.Merge(&metadata, layer.Config); err != nil { - return err - } - } - - var exists bool - dgst, err := p.graph.getLayerDigestWithLock(layer.ID) - switch err { - case nil: - if p.layersPushed[dgst] { - exists = true - // break out of switch, it is already known that - // the push is not needed and therefore doing a - // stat is unnecessary - break - } - _, err := p.repo.Blobs(context.Background()).Stat(context.Background(), dgst) - switch err { - case nil: - exists = true - out.Write(p.sf.FormatProgress(stringid.TruncateID(layer.ID), "Image already exists", nil)) - case distribution.ErrBlobUnknown: - // nop - default: - out.Write(p.sf.FormatProgress(stringid.TruncateID(layer.ID), "Image push failed", nil)) - return err - } - case errDigestNotSet: - // nop - case digest.ErrDigestInvalidFormat, digest.ErrDigestUnsupported: - return fmt.Errorf("error getting image checksum: %v", err) - } - - // if digest was empty or not saved, or if blob does not exist on the remote repository, - // then fetch it. - if !exists { - var pushDigest digest.Digest - if pushDigest, err = p.pushV2Image(p.repo.Blobs(context.Background()), layer); err != nil { - return err - } - if dgst == "" { - // Cache new checksum - if err := p.graph.setLayerDigestWithLock(layer.ID, pushDigest); err != nil { - return err - } - } - dgst = pushDigest - } - - // read v1Compatibility config, generate new if needed - jsonData, err := p.graph.generateV1CompatibilityChain(layer.ID) - if err != nil { - return err - } - - m.FSLayers = append(m.FSLayers, schema1.FSLayer{BlobSum: dgst}) - m.History = append(m.History, schema1.History{V1Compatibility: string(jsonData)}) - - layersSeen[layer.ID] = true - p.layersPushed[dgst] = true - } - - logrus.Infof("Signed manifest for %s:%s using daemon's key: %s", p.repo.Name(), tag, p.trustKey.KeyID()) - signed, err := schema1.Sign(m, p.trustKey) - if err != nil { - return err - } - - manifestDigest, manifestSize, err := digestFromManifest(signed, p.repo.Name()) - if err != nil { - return err - } - if manifestDigest != "" { - out.Write(p.sf.FormatStatus("", "%s: digest: %s size: %d", tag, manifestDigest, manifestSize)) - } - - manSvc, err := p.repo.Manifests(context.Background()) - if err != nil { - return err - } - return manSvc.Put(signed) -} - -func (p *v2Pusher) pushV2Image(bs distribution.BlobService, img *image.Image) (digest.Digest, error) { - out := p.config.OutStream - - out.Write(p.sf.FormatProgress(stringid.TruncateID(img.ID), "Preparing", nil)) - - image, err := p.graph.Get(img.ID) - if err != nil { - return "", err - } - arch, err := p.graph.tarLayer(image) - if err != nil { - return "", err - } - defer arch.Close() - - // Send the layer - layerUpload, err := bs.Create(context.Background()) - if err != nil { - return "", err - } - defer layerUpload.Close() - - reader := progressreader.New(progressreader.Config{ - In: ioutil.NopCloser(arch), // we'll take care of close here. - Out: out, - Formatter: p.sf, - - // TODO(stevvooe): This may cause a size reporting error. Try to get - // this from tar-split or elsewhere. The main issue here is that we - // don't want to buffer to disk *just* to calculate the size. - Size: img.Size, - - NewLines: false, - ID: stringid.TruncateID(img.ID), - Action: "Pushing", - }) - - digester := digest.Canonical.New() - // HACK: The MultiWriter doesn't write directly to layerUpload because - // we must make sure the ReadFrom is used, not Write. Using Write would - // send a PATCH request for every Write call. - pipeReader, pipeWriter := io.Pipe() - // Use a bufio.Writer to avoid excessive chunking in HTTP request. - bufWriter := bufio.NewWriterSize(io.MultiWriter(pipeWriter, digester.Hash()), compressionBufSize) - compressor := gzip.NewWriter(bufWriter) - - go func() { - _, err := io.Copy(compressor, reader) - if err == nil { - err = compressor.Close() - } - if err == nil { - err = bufWriter.Flush() - } - if err != nil { - pipeWriter.CloseWithError(err) - } else { - pipeWriter.Close() - } - }() - - out.Write(p.sf.FormatProgress(stringid.TruncateID(img.ID), "Pushing", nil)) - nn, err := layerUpload.ReadFrom(pipeReader) - pipeReader.Close() - if err != nil { - return "", err - } - - dgst := digester.Digest() - if _, err := layerUpload.Commit(context.Background(), distribution.Descriptor{Digest: dgst}); err != nil { - return "", err - } - - logrus.Debugf("uploaded layer %s (%s), %d bytes", img.ID, dgst, nn) - out.Write(p.sf.FormatProgress(stringid.TruncateID(img.ID), "Pushed", nil)) - - return dgst, nil -} diff --git a/vendor/github.com/docker/docker/graph/registry.go b/vendor/github.com/docker/docker/graph/registry.go deleted file mode 100644 index a9a4ad18..00000000 --- a/vendor/github.com/docker/docker/graph/registry.go +++ /dev/null @@ -1,116 +0,0 @@ -package graph - -import ( - "errors" - "net" - "net/http" - "net/url" - "time" - - "strings" - - "github.com/Sirupsen/logrus" - "github.com/docker/distribution" - "github.com/docker/distribution/digest" - "github.com/docker/distribution/manifest/schema1" - "github.com/docker/distribution/registry/client" - "github.com/docker/distribution/registry/client/auth" - "github.com/docker/distribution/registry/client/transport" - "github.com/docker/docker/cliconfig" - "github.com/docker/docker/registry" - "golang.org/x/net/context" -) - -type dumbCredentialStore struct { - auth *cliconfig.AuthConfig -} - -func (dcs dumbCredentialStore) Basic(*url.URL) (string, string) { - return dcs.auth.Username, dcs.auth.Password -} - -// newV2Repository returns a repository (v2 only). It creates a HTTP transport -// providing timeout settings and authentication support, and also verifies the -// remote API version. -func newV2Repository(repoInfo *registry.RepositoryInfo, endpoint registry.APIEndpoint, metaHeaders http.Header, authConfig *cliconfig.AuthConfig, actions ...string) (distribution.Repository, error) { - ctx := context.Background() - - repoName := repoInfo.CanonicalName - // If endpoint does not support CanonicalName, use the RemoteName instead - if endpoint.TrimHostname { - repoName = repoInfo.RemoteName - } - - // TODO(dmcgowan): Call close idle connections when complete, use keep alive - base := &http.Transport{ - Proxy: http.ProxyFromEnvironment, - Dial: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - DualStack: true, - }).Dial, - TLSHandshakeTimeout: 10 * time.Second, - TLSClientConfig: endpoint.TLSConfig, - // TODO(dmcgowan): Call close idle connections when complete and use keep alive - DisableKeepAlives: true, - } - - modifiers := registry.DockerHeaders(metaHeaders) - authTransport := transport.NewTransport(base, modifiers...) - pingClient := &http.Client{ - Transport: authTransport, - Timeout: 15 * time.Second, - } - endpointStr := strings.TrimRight(endpoint.URL, "/") + "/v2/" - req, err := http.NewRequest("GET", endpointStr, nil) - if err != nil { - return nil, err - } - resp, err := pingClient.Do(req) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - versions := auth.APIVersions(resp, endpoint.VersionHeader) - if endpoint.VersionHeader != "" && len(endpoint.Versions) > 0 { - var foundVersion bool - for _, version := range endpoint.Versions { - for _, pingVersion := range versions { - if version == pingVersion { - foundVersion = true - } - } - } - if !foundVersion { - return nil, errors.New("endpoint does not support v2 API") - } - } - - challengeManager := auth.NewSimpleChallengeManager() - if err := challengeManager.AddResponse(resp); err != nil { - return nil, err - } - - creds := dumbCredentialStore{auth: authConfig} - tokenHandler := auth.NewTokenHandler(authTransport, creds, repoName, actions...) - basicHandler := auth.NewBasicHandler(creds) - modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, tokenHandler, basicHandler)) - tr := transport.NewTransport(base, modifiers...) - - return client.NewRepository(ctx, repoName, endpoint.URL, tr) -} - -func digestFromManifest(m *schema1.SignedManifest, localName string) (digest.Digest, int, error) { - payload, err := m.Payload() - if err != nil { - // If this failed, the signatures section was corrupted - // or missing. Treat the entire manifest as the payload. - payload = m.Raw - } - manifestDigest, err := digest.FromBytes(payload) - if err != nil { - logrus.Infof("Could not compute manifest digest for %s:%s : %v", localName, m.Tag, err) - } - return manifestDigest, len(payload), nil -} diff --git a/vendor/github.com/docker/docker/graph/service.go b/vendor/github.com/docker/docker/graph/service.go deleted file mode 100644 index 11fe9266..00000000 --- a/vendor/github.com/docker/docker/graph/service.go +++ /dev/null @@ -1,89 +0,0 @@ -package graph - -import ( - "fmt" - "io" - "runtime" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/api/types" - "github.com/docker/docker/utils" -) - -// Lookup looks up an image by name in a TagStore and returns it as an -// ImageInspect structure. -func (s *TagStore) Lookup(name string) (*types.ImageInspect, error) { - image, err := s.LookupImage(name) - if err != nil || image == nil { - return nil, fmt.Errorf("No such image: %s", name) - } - - var repoTags = make([]string, 0) - var repoDigests = make([]string, 0) - - s.Lock() - for repoName, repository := range s.Repositories { - for ref, id := range repository { - if id == image.ID { - imgRef := utils.ImageReference(repoName, ref) - if utils.DigestReference(ref) { - repoDigests = append(repoDigests, imgRef) - } else { - repoTags = append(repoTags, imgRef) - } - } - } - } - s.Unlock() - - imageInspect := &types.ImageInspect{ - ID: image.ID, - RepoTags: repoTags, - RepoDigests: repoDigests, - Parent: image.Parent, - Comment: image.Comment, - Created: image.Created.Format(time.RFC3339Nano), - Container: image.Container, - ContainerConfig: &image.ContainerConfig, - DockerVersion: image.DockerVersion, - Author: image.Author, - Config: image.Config, - Architecture: image.Architecture, - Os: image.OS, - Size: image.Size, - VirtualSize: s.graph.getParentsSize(image) + image.Size, - } - - imageInspect.GraphDriver.Name = s.graph.driver.String() - - graphDriverData, err := s.graph.driver.GetMetadata(image.ID) - if err != nil { - return nil, err - } - imageInspect.GraphDriver.Data = graphDriverData - return imageInspect, nil -} - -// imageTarLayer return the tarLayer of the image -func (s *TagStore) imageTarLayer(name string, dest io.Writer) error { - if image, err := s.LookupImage(name); err == nil && image != nil { - // On Windows, the base layer cannot be exported - if runtime.GOOS != "windows" || image.Parent != "" { - - fs, err := s.graph.tarLayer(image) - if err != nil { - return err - } - defer fs.Close() - - written, err := io.Copy(dest, fs) - if err != nil { - return err - } - logrus.Debugf("rendered layer for %s of [%d] size", image.ID, written) - } - return nil - } - return fmt.Errorf("No such image: %s", name) -} diff --git a/vendor/github.com/docker/docker/graph/tags.go b/vendor/github.com/docker/docker/graph/tags.go deleted file mode 100644 index d9423373..00000000 --- a/vendor/github.com/docker/docker/graph/tags.go +++ /dev/null @@ -1,432 +0,0 @@ -package graph - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "sort" - "strings" - "sync" - - "github.com/docker/distribution/digest" - "github.com/docker/docker/daemon/events" - "github.com/docker/docker/graph/tags" - "github.com/docker/docker/image" - "github.com/docker/docker/pkg/broadcaster" - "github.com/docker/docker/pkg/parsers" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/registry" - "github.com/docker/docker/utils" - "github.com/docker/libtrust" -) - -// ErrNameIsNotExist returned when there is no image with requested name. -var ErrNameIsNotExist = errors.New("image with specified name does not exist") - -// TagStore manages repositories. It encompasses the Graph used for versioned -// storage, as well as various services involved in pushing and pulling -// repositories. -type TagStore struct { - path string - graph *Graph - // Repositories is a map of repositories, indexed by name. - Repositories map[string]repository - trustKey libtrust.PrivateKey - sync.Mutex - // FIXME: move push/pull-related fields - // to a helper type - pullingPool map[string]*broadcaster.Buffered - pushingPool map[string]*broadcaster.Buffered - registryService *registry.Service - eventsService *events.Events -} - -// repository maps tags to image IDs. -type repository map[string]string - -// TagStoreConfig provides parameters for a new TagStore. -type TagStoreConfig struct { - // Graph is the versioned image store - Graph *Graph - // Key is the private key to use for signing manifests. - Key libtrust.PrivateKey - // Registry is the registry service to use for TLS configuration and - // endpoint lookup. - Registry *registry.Service - // Events is the events service to use for logging. - Events *events.Events -} - -// NewTagStore creates a new TagStore at specified path, using the parameters -// and services provided in cfg. -func NewTagStore(path string, cfg *TagStoreConfig) (*TagStore, error) { - abspath, err := filepath.Abs(path) - if err != nil { - return nil, err - } - - store := &TagStore{ - path: abspath, - graph: cfg.Graph, - trustKey: cfg.Key, - Repositories: make(map[string]repository), - pullingPool: make(map[string]*broadcaster.Buffered), - pushingPool: make(map[string]*broadcaster.Buffered), - registryService: cfg.Registry, - eventsService: cfg.Events, - } - // Load the json file if it exists, otherwise create it. - if err := store.reload(); os.IsNotExist(err) { - if err := store.save(); err != nil { - return nil, err - } - } else if err != nil { - return nil, err - } - return store, nil -} - -func (store *TagStore) save() error { - // Store the json ball - jsonData, err := json.Marshal(store) - if err != nil { - return err - } - if err := ioutil.WriteFile(store.path, jsonData, 0600); err != nil { - return err - } - return nil -} - -func (store *TagStore) reload() error { - f, err := os.Open(store.path) - if err != nil { - return err - } - defer f.Close() - if err := json.NewDecoder(f).Decode(&store); err != nil { - return err - } - return nil -} - -// LookupImage returns pointer to an Image struct corresponding to the given -// name. The name can include an optional tag; otherwise the default tag will -// be used. -func (store *TagStore) LookupImage(name string) (*image.Image, error) { - repoName, ref := parsers.ParseRepositoryTag(name) - if ref == "" { - ref = tags.DefaultTag - } - var ( - err error - img *image.Image - ) - - img, err = store.getImage(repoName, ref) - if err != nil { - return nil, err - } - - if img != nil { - return img, nil - } - - // name must be an image ID. - store.Lock() - defer store.Unlock() - if img, err = store.graph.Get(name); err != nil { - return nil, err - } - - return img, nil -} - -// GetID returns ID for image name. -func (store *TagStore) GetID(name string) (string, error) { - repoName, ref := parsers.ParseRepositoryTag(name) - if ref == "" { - ref = tags.DefaultTag - } - store.Lock() - defer store.Unlock() - repoName = registry.NormalizeLocalName(repoName) - repo, ok := store.Repositories[repoName] - if !ok { - return "", ErrNameIsNotExist - } - id, ok := repo[ref] - if !ok { - return "", ErrNameIsNotExist - } - return id, nil -} - -// ByID returns a reverse-lookup table of all the names which refer to each -// image - e.g. {"43b5f19b10584": {"base:latest", "base:v1"}} -func (store *TagStore) ByID() map[string][]string { - store.Lock() - defer store.Unlock() - byID := make(map[string][]string) - for repoName, repository := range store.Repositories { - for tag, id := range repository { - name := utils.ImageReference(repoName, tag) - if _, exists := byID[id]; !exists { - byID[id] = []string{name} - } else { - byID[id] = append(byID[id], name) - sort.Strings(byID[id]) - } - } - } - return byID -} - -// HasReferences returns whether or not the given image is referenced in one or -// more repositories. -func (store *TagStore) HasReferences(img *image.Image) bool { - return len(store.ByID()[img.ID]) > 0 -} - -// Delete deletes a repository or a specific tag. If ref is empty, the entire -// repository named repoName will be deleted; otherwise only the tag named by -// ref will be deleted. -func (store *TagStore) Delete(repoName, ref string) (bool, error) { - store.Lock() - defer store.Unlock() - deleted := false - if err := store.reload(); err != nil { - return false, err - } - - repoName = registry.NormalizeLocalName(repoName) - - if ref == "" { - // Delete the whole repository. - delete(store.Repositories, repoName) - return true, store.save() - } - - repoRefs, exists := store.Repositories[repoName] - if !exists { - return false, fmt.Errorf("No such repository: %s", repoName) - } - - if _, exists := repoRefs[ref]; exists { - delete(repoRefs, ref) - if len(repoRefs) == 0 { - delete(store.Repositories, repoName) - } - deleted = true - } - - return deleted, store.save() -} - -// Tag creates a tag in the repository reponame, pointing to the image named -// imageName. If force is true, an existing tag with the same name may be -// overwritten. -func (store *TagStore) Tag(repoName, tag, imageName string, force bool) error { - return store.setLoad(repoName, tag, imageName, force, nil) -} - -// setLoad stores the image to the store. -// If the imageName is already in the repo then a '-f' flag should be used to replace existing image. -func (store *TagStore) setLoad(repoName, tag, imageName string, force bool, out io.Writer) error { - img, err := store.LookupImage(imageName) - store.Lock() - defer store.Unlock() - if err != nil { - return err - } - if tag == "" { - tag = tags.DefaultTag - } - if err := validateRepoName(repoName); err != nil { - return err - } - if err := tags.ValidateTagName(tag); err != nil { - return err - } - if err := store.reload(); err != nil { - return err - } - var repo repository - repoName = registry.NormalizeLocalName(repoName) - if r, exists := store.Repositories[repoName]; exists { - repo = r - if old, exists := store.Repositories[repoName][tag]; exists { - - if !force { - return fmt.Errorf("Conflict: Tag %s:%s is already set to image %s, if you want to replace it, please use -f option", repoName, tag, old[:12]) - } - - if old != img.ID && out != nil { - - fmt.Fprintf(out, "The image %s:%s already exists, renaming the old one with ID %s to empty string\n", repoName, tag, old[:12]) - - } - } - } else { - repo = make(map[string]string) - store.Repositories[repoName] = repo - } - repo[tag] = img.ID - return store.save() -} - -// setDigest creates a digest reference to an image ID. -func (store *TagStore) setDigest(repoName, digest, imageName string) error { - img, err := store.LookupImage(imageName) - if err != nil { - return err - } - - if err := validateRepoName(repoName); err != nil { - return err - } - - if err := validateDigest(digest); err != nil { - return err - } - - store.Lock() - defer store.Unlock() - if err := store.reload(); err != nil { - return err - } - - repoName = registry.NormalizeLocalName(repoName) - repoRefs, exists := store.Repositories[repoName] - if !exists { - repoRefs = repository{} - store.Repositories[repoName] = repoRefs - } else if oldID, exists := repoRefs[digest]; exists && oldID != img.ID { - return fmt.Errorf("Conflict: Digest %s is already set to image %s", digest, oldID) - } - - repoRefs[digest] = img.ID - return store.save() -} - -// get returns the repository tag/image map for a given repository. -func (store *TagStore) get(repoName string) (repository, error) { - store.Lock() - defer store.Unlock() - if err := store.reload(); err != nil { - return nil, err - } - repoName = registry.NormalizeLocalName(repoName) - if r, exists := store.Repositories[repoName]; exists { - return r, nil - } - return nil, nil -} - -// getImage returns a pointer to an Image structure describing the image -// referred to by refOrID inside repository repoName. -func (store *TagStore) getImage(repoName, refOrID string) (*image.Image, error) { - repo, err := store.get(repoName) - - if err != nil { - return nil, err - } - if repo == nil { - return nil, nil - } - - store.Lock() - defer store.Unlock() - if imgID, exists := repo[refOrID]; exists { - return store.graph.Get(imgID) - } - - // If no matching tag is found, search through images for a matching image id - // iff it looks like a short ID or would look like a short ID - if stringid.IsShortID(stringid.TruncateID(refOrID)) { - for _, revision := range repo { - if strings.HasPrefix(revision, refOrID) { - return store.graph.Get(revision) - } - } - } - - return nil, nil -} - -// validateRepoName validates the name of a repository. -func validateRepoName(name string) error { - if name == "" { - return fmt.Errorf("Repository name can't be empty") - } - if name == "scratch" { - return fmt.Errorf("'scratch' is a reserved name") - } - return nil -} - -func validateDigest(dgst string) error { - if dgst == "" { - return errors.New("digest can't be empty") - } - if _, err := digest.ParseDigest(dgst); err != nil { - return err - } - return nil -} - -// poolAdd checks if a push or pull is already running, and returns -// (broadcaster, true) if a running operation is found. Otherwise, it creates a -// new one and returns (broadcaster, false). -func (store *TagStore) poolAdd(kind, key string) (*broadcaster.Buffered, bool) { - store.Lock() - defer store.Unlock() - - if p, exists := store.pullingPool[key]; exists { - return p, true - } - if p, exists := store.pushingPool[key]; exists { - return p, true - } - - broadcaster := broadcaster.NewBuffered() - - switch kind { - case "pull": - store.pullingPool[key] = broadcaster - case "push": - store.pushingPool[key] = broadcaster - default: - panic("Unknown pool type") - } - - return broadcaster, false -} - -func (store *TagStore) poolRemoveWithError(kind, key string, broadcasterResult error) error { - store.Lock() - defer store.Unlock() - switch kind { - case "pull": - if broadcaster, exists := store.pullingPool[key]; exists { - broadcaster.CloseWithError(broadcasterResult) - delete(store.pullingPool, key) - } - case "push": - if broadcaster, exists := store.pushingPool[key]; exists { - broadcaster.CloseWithError(broadcasterResult) - delete(store.pushingPool, key) - } - default: - return fmt.Errorf("Unknown pool type") - } - return nil -} - -func (store *TagStore) poolRemove(kind, key string) error { - return store.poolRemoveWithError(kind, key, nil) -} diff --git a/vendor/github.com/docker/docker/graph/tags/tags.go b/vendor/github.com/docker/docker/graph/tags/tags.go deleted file mode 100644 index 4c9399b4..00000000 --- a/vendor/github.com/docker/docker/graph/tags/tags.go +++ /dev/null @@ -1,36 +0,0 @@ -package tags - -import ( - "fmt" - "regexp" - - "github.com/docker/distribution/reference" -) - -// DefaultTag defines the default tag used when performing images related actions and no tag string is specified -const DefaultTag = "latest" - -var anchoredTagRegexp = regexp.MustCompile(`^` + reference.TagRegexp.String() + `$`) - -// ErrTagInvalidFormat is returned if tag is invalid. -type ErrTagInvalidFormat struct { - name string -} - -func (e ErrTagInvalidFormat) Error() string { - return fmt.Sprintf("Illegal tag name (%s): only [A-Za-z0-9_.-] are allowed ('.' and '-' are NOT allowed in the initial), minimum 1, maximum 128 in length", e.name) -} - -// ValidateTagName validates the name of a tag. -// It returns an error if the given name is an emtpy string. -// If name is not valid, it returns ErrTagInvalidFormat -func ValidateTagName(name string) error { - if name == "" { - return fmt.Errorf("tag name can't be empty") - } - - if !anchoredTagRegexp.MatchString(name) { - return ErrTagInvalidFormat{name} - } - return nil -} diff --git a/vendor/github.com/docker/docker/graph/tags/tags_unit_test.go b/vendor/github.com/docker/docker/graph/tags/tags_unit_test.go deleted file mode 100644 index 374e0f05..00000000 --- a/vendor/github.com/docker/docker/graph/tags/tags_unit_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package tags - -import ( - "testing" -) - -func TestValidTagName(t *testing.T) { - validTags := []string{"9", "foo", "foo-test", "bar.baz.boo"} - for _, tag := range validTags { - if err := ValidateTagName(tag); err != nil { - t.Errorf("'%s' should've been a valid tag", tag) - } - } -} - -func TestInvalidTagName(t *testing.T) { - inValidTags := []string{"-9", ".foo", "-test", ".", "-"} - for _, tag := range inValidTags { - if err := ValidateTagName(tag); err == nil { - t.Errorf("'%s' should've been an invalid tag", tag) - } - } -} diff --git a/vendor/github.com/docker/docker/graph/tags_unit_test.go b/vendor/github.com/docker/docker/graph/tags_unit_test.go deleted file mode 100644 index 0406f154..00000000 --- a/vendor/github.com/docker/docker/graph/tags_unit_test.go +++ /dev/null @@ -1,205 +0,0 @@ -package graph - -import ( - "archive/tar" - "bytes" - "io" - "os" - "path" - "testing" - - "github.com/docker/docker/daemon/events" - "github.com/docker/docker/daemon/graphdriver" - _ "github.com/docker/docker/daemon/graphdriver/vfs" // import the vfs driver so it is used in the tests - "github.com/docker/docker/graph/tags" - "github.com/docker/docker/image" - "github.com/docker/docker/utils" -) - -const ( - testOfficialImageName = "myapp" - testOfficialImageID = "1a2d3c4d4e5fa2d2a21acea242a5e2345d3aefc3e7dfa2a2a2a21a2a2ad2d234" - testOfficialImageIDShort = "1a2d3c4d4e5f" - testPrivateImageName = "127.0.0.1:8000/privateapp" - testPrivateImageID = "5bc255f8699e4ee89ac4469266c3d11515da88fdcbde45d7b069b636ff4efd81" - testPrivateImageIDShort = "5bc255f8699e" - testPrivateImageDigest = "sha256:bc8813ea7b3603864987522f02a76101c17ad122e1c46d790efc0fca78ca7bfb" - testPrivateImageTag = "sometag" -) - -func fakeTar() (io.Reader, error) { - uid := os.Getuid() - gid := os.Getgid() - - content := []byte("Hello world!\n") - buf := new(bytes.Buffer) - tw := tar.NewWriter(buf) - for _, name := range []string{"/etc/postgres/postgres.conf", "/etc/passwd", "/var/log/postgres/postgres.conf"} { - hdr := new(tar.Header) - - // Leaving these fields blank requires root privileges - hdr.Uid = uid - hdr.Gid = gid - - hdr.Size = int64(len(content)) - hdr.Name = name - if err := tw.WriteHeader(hdr); err != nil { - return nil, err - } - tw.Write([]byte(content)) - } - tw.Close() - return buf, nil -} - -func mkTestTagStore(root string, t *testing.T) *TagStore { - driver, err := graphdriver.New(root, nil, nil, nil) - if err != nil { - t.Fatal(err) - } - graph, err := NewGraph(root, driver, nil, nil) - if err != nil { - t.Fatal(err) - } - - tagCfg := &TagStoreConfig{ - Graph: graph, - Events: events.New(), - } - store, err := NewTagStore(path.Join(root, "tags"), tagCfg) - if err != nil { - t.Fatal(err) - } - officialArchive, err := fakeTar() - if err != nil { - t.Fatal(err) - } - img := &image.Image{ID: testOfficialImageID} - if err := graph.Register(v1Descriptor{img}, officialArchive); err != nil { - t.Fatal(err) - } - if err := store.Tag(testOfficialImageName, "", testOfficialImageID, false); err != nil { - t.Fatal(err) - } - privateArchive, err := fakeTar() - if err != nil { - t.Fatal(err) - } - img = &image.Image{ID: testPrivateImageID} - if err := graph.Register(v1Descriptor{img}, privateArchive); err != nil { - t.Fatal(err) - } - if err := store.Tag(testPrivateImageName, "", testPrivateImageID, false); err != nil { - t.Fatal(err) - } - if err := store.setDigest(testPrivateImageName, testPrivateImageDigest, testPrivateImageID); err != nil { - t.Fatal(err) - } - return store -} - -func TestLookupImage(t *testing.T) { - tmp, err := utils.TestDirectory("") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - store := mkTestTagStore(tmp, t) - defer store.graph.driver.Cleanup() - - officialLookups := []string{ - testOfficialImageID, - testOfficialImageIDShort, - testOfficialImageName + ":" + testOfficialImageID, - testOfficialImageName + ":" + testOfficialImageIDShort, - testOfficialImageName, - testOfficialImageName + ":" + tags.DefaultTag, - "docker.io/" + testOfficialImageName, - "docker.io/" + testOfficialImageName + ":" + tags.DefaultTag, - "index.docker.io/" + testOfficialImageName, - "index.docker.io/" + testOfficialImageName + ":" + tags.DefaultTag, - "library/" + testOfficialImageName, - "library/" + testOfficialImageName + ":" + tags.DefaultTag, - "docker.io/library/" + testOfficialImageName, - "docker.io/library/" + testOfficialImageName + ":" + tags.DefaultTag, - "index.docker.io/library/" + testOfficialImageName, - "index.docker.io/library/" + testOfficialImageName + ":" + tags.DefaultTag, - } - - privateLookups := []string{ - testPrivateImageID, - testPrivateImageIDShort, - testPrivateImageName + ":" + testPrivateImageID, - testPrivateImageName + ":" + testPrivateImageIDShort, - testPrivateImageName, - testPrivateImageName + ":" + tags.DefaultTag, - } - - invalidLookups := []string{ - testOfficialImageName + ":" + "fail", - "fail:fail", - } - - digestLookups := []string{ - testPrivateImageName + "@" + testPrivateImageDigest, - } - - for _, name := range officialLookups { - if img, err := store.LookupImage(name); err != nil { - t.Errorf("Error looking up %s: %s", name, err) - } else if img == nil { - t.Errorf("Expected 1 image, none found: %s", name) - } else if img.ID != testOfficialImageID { - t.Errorf("Expected ID '%s' found '%s'", testOfficialImageID, img.ID) - } - } - - for _, name := range privateLookups { - if img, err := store.LookupImage(name); err != nil { - t.Errorf("Error looking up %s: %s", name, err) - } else if img == nil { - t.Errorf("Expected 1 image, none found: %s", name) - } else if img.ID != testPrivateImageID { - t.Errorf("Expected ID '%s' found '%s'", testPrivateImageID, img.ID) - } - } - - for _, name := range invalidLookups { - if img, err := store.LookupImage(name); err == nil { - t.Errorf("Expected error, none found: %s", name) - } else if img != nil { - t.Errorf("Expected 0 image, 1 found: %s", name) - } - } - - for _, name := range digestLookups { - if img, err := store.LookupImage(name); err != nil { - t.Errorf("Error looking up %s: %s", name, err) - } else if img == nil { - t.Errorf("Expected 1 image, none found: %s", name) - } else if img.ID != testPrivateImageID { - t.Errorf("Expected ID '%s' found '%s'", testPrivateImageID, img.ID) - } - } -} - -func TestValidateDigest(t *testing.T) { - tests := []struct { - input string - expectError bool - }{ - {"", true}, - {"latest", true}, - {"sha256:b", false}, - {"tarsum+v1+sha256:bY852-_.+=", false}, - {"#$%#$^:$%^#$%", true}, - } - - for i, test := range tests { - err := validateDigest(test.input) - gotError := err != nil - if e, a := test.expectError, gotError; e != a { - t.Errorf("%d: with input %s, expected error=%t, got %t: %s", i, test.input, test.expectError, gotError, err) - } - } -} diff --git a/vendor/github.com/docker/docker/image/fixtures/post1.9/expected_computed_id b/vendor/github.com/docker/docker/image/fixtures/post1.9/expected_computed_id deleted file mode 100644 index cba6d81f..00000000 --- a/vendor/github.com/docker/docker/image/fixtures/post1.9/expected_computed_id +++ /dev/null @@ -1 +0,0 @@ -sha256:f2722a8ec6926e02fa9f2674072cbc2a25cf0f449f27350f613cd843b02c9105 diff --git a/vendor/github.com/docker/docker/image/fixtures/post1.9/expected_config b/vendor/github.com/docker/docker/image/fixtures/post1.9/expected_config deleted file mode 100644 index ae27bdd4..00000000 --- a/vendor/github.com/docker/docker/image/fixtures/post1.9/expected_config +++ /dev/null @@ -1 +0,0 @@ -{"architecture":"amd64","config":{"Hostname":"fb1f7270da95","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["foo=bar"],"Cmd":null,"Image":"361a94d06b2b781b2f1ee6c72e1cbbfbbd032a103e26a3db75b431743829ae4f","Volumes":null,"VolumeDriver":"","WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"container":"fb1f7270da9519308361b99dc8e0d30f12c24dfd28537c2337ece995ac853a16","container_config":{"Hostname":"fb1f7270da95","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["foo=bar"],"Cmd":["/bin/sh","-c","#(nop) ADD file:11998b2a4d664a75cd0c3f4e4cb1837434e0f997ba157a0ac1d3c68a07aa2f4f in /"],"Image":"361a94d06b2b781b2f1ee6c72e1cbbfbbd032a103e26a3db75b431743829ae4f","Volumes":null,"VolumeDriver":"","WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"created":"2015-09-08T21:30:30.807853054Z","docker_version":"1.9.0-dev","layer_id":"sha256:31176893850e05d308cdbfef88877e460d50c8063883fb13eb5753097da6422a","os":"linux","parent_id":"sha256:ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02"} diff --git a/vendor/github.com/docker/docker/image/fixtures/post1.9/layer_id b/vendor/github.com/docker/docker/image/fixtures/post1.9/layer_id deleted file mode 100644 index ded2db28..00000000 --- a/vendor/github.com/docker/docker/image/fixtures/post1.9/layer_id +++ /dev/null @@ -1 +0,0 @@ -sha256:31176893850e05d308cdbfef88877e460d50c8063883fb13eb5753097da6422a diff --git a/vendor/github.com/docker/docker/image/fixtures/post1.9/parent_id b/vendor/github.com/docker/docker/image/fixtures/post1.9/parent_id deleted file mode 100644 index 7d524f80..00000000 --- a/vendor/github.com/docker/docker/image/fixtures/post1.9/parent_id +++ /dev/null @@ -1 +0,0 @@ -sha256:ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02 diff --git a/vendor/github.com/docker/docker/image/fixtures/post1.9/v1compatibility b/vendor/github.com/docker/docker/image/fixtures/post1.9/v1compatibility deleted file mode 100644 index d6697c2b..00000000 --- a/vendor/github.com/docker/docker/image/fixtures/post1.9/v1compatibility +++ /dev/null @@ -1 +0,0 @@ -{"id":"8dfb96b5d09e6cf6f376d81f1e2770ee5ede309f9bd9e079688c9782649ab326","parent":"361a94d06b2b781b2f1ee6c72e1cbbfbbd032a103e26a3db75b431743829ae4f","created":"2015-09-08T21:30:30.807853054Z","container":"fb1f7270da9519308361b99dc8e0d30f12c24dfd28537c2337ece995ac853a16","container_config":{"Hostname":"fb1f7270da95","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["foo=bar"],"Cmd":["/bin/sh","-c","#(nop) ADD file:11998b2a4d664a75cd0c3f4e4cb1837434e0f997ba157a0ac1d3c68a07aa2f4f in /"],"Image":"361a94d06b2b781b2f1ee6c72e1cbbfbbd032a103e26a3db75b431743829ae4f","Volumes":null,"VolumeDriver":"","WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"docker_version":"1.9.0-dev","config":{"Hostname":"fb1f7270da95","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["foo=bar"],"Cmd":null,"Image":"361a94d06b2b781b2f1ee6c72e1cbbfbbd032a103e26a3db75b431743829ae4f","Volumes":null,"VolumeDriver":"","WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"architecture":"amd64","os":"linux"} diff --git a/vendor/github.com/docker/docker/image/fixtures/pre1.9/expected_computed_id b/vendor/github.com/docker/docker/image/fixtures/pre1.9/expected_computed_id deleted file mode 100644 index 98a34f8c..00000000 --- a/vendor/github.com/docker/docker/image/fixtures/pre1.9/expected_computed_id +++ /dev/null @@ -1 +0,0 @@ -sha256:731d62ca192955d38edd4333c89aad021002b1e570daa6bb9f8f06b500c76a4d diff --git a/vendor/github.com/docker/docker/image/fixtures/pre1.9/expected_config b/vendor/github.com/docker/docker/image/fixtures/pre1.9/expected_config deleted file mode 100644 index e29c9d34..00000000 --- a/vendor/github.com/docker/docker/image/fixtures/pre1.9/expected_config +++ /dev/null @@ -1 +0,0 @@ -{"architecture":"amd64","config":{"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Cmd":null,"Entrypoint":["/go/bin/dnsdock"],"Env":["PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","GOLANG_VERSION=1.4.1","GOPATH=/go"],"Hostname":"03797203757d","Image":"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02","Labels":{},"OnBuild":[],"OpenStdin":false,"StdinOnce":false,"Tty":false,"Volumes":null,"WorkingDir":"/go","Domainname":"","User":""},"container":"d91be3479d5b1e84b0c00d18eea9dc777ca0ad166d51174b24283e2e6f104253","container_config":{"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Cmd":["/bin/sh","-c","#(nop) ENTRYPOINT [\"/go/bin/dnsdock\"]"],"Entrypoint":["/go/bin/dnsdock"],"Env":["PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","GOLANG_VERSION=1.4.1","GOPATH=/go"],"Hostname":"03797203757d","Image":"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02","Labels":{},"OnBuild":[],"OpenStdin":false,"StdinOnce":false,"Tty":false,"Volumes":null,"WorkingDir":"/go","Domainname":"","User":""},"created":"2015-08-19T16:49:11.368300679Z","docker_version":"1.6.2","layer_id":"sha256:31176893850e05d308cdbfef88877e460d50c8063883fb13eb5753097da6422a","os":"linux","parent_id":"sha256:ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02"} diff --git a/vendor/github.com/docker/docker/image/fixtures/pre1.9/layer_id b/vendor/github.com/docker/docker/image/fixtures/pre1.9/layer_id deleted file mode 100644 index ded2db28..00000000 --- a/vendor/github.com/docker/docker/image/fixtures/pre1.9/layer_id +++ /dev/null @@ -1 +0,0 @@ -sha256:31176893850e05d308cdbfef88877e460d50c8063883fb13eb5753097da6422a diff --git a/vendor/github.com/docker/docker/image/fixtures/pre1.9/parent_id b/vendor/github.com/docker/docker/image/fixtures/pre1.9/parent_id deleted file mode 100644 index 7d524f80..00000000 --- a/vendor/github.com/docker/docker/image/fixtures/pre1.9/parent_id +++ /dev/null @@ -1 +0,0 @@ -sha256:ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02 diff --git a/vendor/github.com/docker/docker/image/fixtures/pre1.9/v1compatibility b/vendor/github.com/docker/docker/image/fixtures/pre1.9/v1compatibility deleted file mode 100644 index af96e825..00000000 --- a/vendor/github.com/docker/docker/image/fixtures/pre1.9/v1compatibility +++ /dev/null @@ -1 +0,0 @@ -{"id":"3b38edc92eb7c074812e217b41a6ade66888531009d6286a6f5f36a06f9841b9","parent":"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02","created":"2015-08-19T16:49:11.368300679Z","container":"d91be3479d5b1e84b0c00d18eea9dc777ca0ad166d51174b24283e2e6f104253","container_config":{"Hostname":"03797203757d","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","GOLANG_VERSION=1.4.1","GOPATH=/go"],"Cmd":["/bin/sh","-c","#(nop) ENTRYPOINT [\"/go/bin/dnsdock\"]"],"Image":"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02","Volumes":null,"WorkingDir":"/go","Entrypoint":["/go/bin/dnsdock"],"NetworkDisabled":false,"MacAddress":"","OnBuild":[],"Labels":{}},"docker_version":"1.6.2","config":{"Hostname":"03797203757d","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","GOLANG_VERSION=1.4.1","GOPATH=/go"],"Cmd":null,"Image":"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02","Volumes":null,"WorkingDir":"/go","Entrypoint":["/go/bin/dnsdock"],"NetworkDisabled":false,"MacAddress":"","OnBuild":[],"Labels":{}},"architecture":"amd64","os":"linux","Size":0} diff --git a/vendor/github.com/docker/docker/image/spec/v1.md b/vendor/github.com/docker/docker/image/spec/v1.md deleted file mode 100644 index f2c29155..00000000 --- a/vendor/github.com/docker/docker/image/spec/v1.md +++ /dev/null @@ -1,573 +0,0 @@ -# Docker Image Specification v1.0.0 - -An *Image* is an ordered collection of root filesystem changes and the -corresponding execution parameters for use within a container runtime. This -specification outlines the format of these filesystem changes and corresponding -parameters and describes how to create and use them for use with a container -runtime and execution tool. - -## Terminology - -This specification uses the following terms: - -
-
- Layer -
-
- Images are composed of layers. Image layer is a general - term which may be used to refer to one or both of the following: - -
    -
  1. The metadata for the layer, described in the JSON format.
  2. -
  3. The filesystem changes described by a layer.
  4. -
- - To refer to the former you may use the term Layer JSON or - Layer Metadata. To refer to the latter you may use the term - Image Filesystem Changeset or Image Diff. -
-
- Image JSON -
-
- Each layer has an associated JSON structure which describes some - basic information about the image such as date created, author, and the - ID of its parent image as well as execution/runtime configuration like - its entry point, default arguments, CPU/memory shares, networking, and - volumes. -
-
- Image Filesystem Changeset -
-
- Each layer has an archive of the files which have been added, changed, - or deleted relative to its parent layer. Using a layer-based or union - filesystem such as AUFS, or by computing the diff from filesystem - snapshots, the filesystem changeset can be used to present a series of - image layers as if they were one cohesive filesystem. -
-
- Image ID -
-
- Each layer is given an ID upon its creation. It is - represented as a hexadecimal encoding of 256 bits, e.g., - a9561eb1b190625c9adb5a9513e72c4dedafc1cb2d4c5236c9a6957ec7dfd5a9. - Image IDs should be sufficiently random so as to be globally unique. - 32 bytes read from /dev/urandom is sufficient for all - practical purposes. Alternatively, an image ID may be derived as a - cryptographic hash of image contents as the result is considered - indistinguishable from random. The choice is left up to implementors. -
-
- Image Parent -
-
- Most layer metadata structs contain a parent field which - refers to the Image from which another directly descends. An image - contains a separate JSON metadata file and set of changes relative to - the filesystem of its parent image. Image Ancestor and - Image Descendant are also common terms. -
-
- Image Checksum -
-
- Layer metadata structs contain a cryptographic hash of the contents of - the layer's filesystem changeset. Though the set of changes exists as a - simple Tar archive, two archives with identical filenames and content - will have different SHA digests if the last-access or last-modified - times of any entries differ. For this reason, image checksums are - generated using the TarSum algorithm which produces a cryptographic - hash of file contents and selected headers only. Details of this - algorithm are described in the separate TarSum specification. -
-
- Tag -
-
- A tag serves to map a descriptive, user-given name to any single image - ID. An image name suffix (the name component after :) is - often referred to as a tag as well, though it strictly refers to the - full name of an image. Acceptable values for a tag suffix are - implementation specific, but they SHOULD be limited to the set of - alphanumeric characters [a-zA-z0-9], punctuation - characters [._-], and MUST NOT contain a : - character. -
-
- Repository -
-
- A collection of tags grouped under a common prefix (the name component - before :). For example, in an image tagged with the name - my-app:3.1.4, my-app is the Repository - component of the name. Acceptable values for repository name are - implementation specific, but they SHOULD be limited to the set of - alphanumeric characters [a-zA-z0-9], and punctuation - characters [._-], however it MAY contain additional - / and : characters for organizational - purposes, with the last : character being interpreted - dividing the repository component of the name from the tag suffix - component. -
-
- -## Image JSON Description - -Here is an example image JSON file: - -``` -{ - "id": "a9561eb1b190625c9adb5a9513e72c4dedafc1cb2d4c5236c9a6957ec7dfd5a9", - "parent": "c6e3cedcda2e3982a1a6760e178355e8e65f7b80e4e5248743fa3549d284e024", - "checksum": "tarsum.v1+sha256:e58fcf7418d2390dec8e8fb69d88c06ec07039d651fedc3aa72af9972e7d046b", - "created": "2014-10-13T21:19:18.674353812Z", - "author": "Alyssa P. Hacker <alyspdev@example.com>", - "architecture": "amd64", - "os": "linux", - "Size": 271828, - "config": { - "User": "alice", - "Memory": 2048, - "MemorySwap": 4096, - "CpuShares": 8, - "ExposedPorts": { - "8080/tcp": {} - }, - "Env": [ - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - "FOO=docker_is_a_really", - "BAR=great_tool_you_know" - ], - "Entrypoint": [ - "/bin/my-app-binary" - ], - "Cmd": [ - "--foreground", - "--config", - "/etc/my-app.d/default.cfg" - ], - "Volumes": { - "/var/job-result-data": {}, - "/var/log/my-app-logs": {}, - }, - "WorkingDir": "/home/alice", - } -} -``` - -### Image JSON Field Descriptions - -
-
- id string -
-
- Randomly generated, 256-bit, hexadecimal encoded. Uniquely identifies - the image. -
-
- parent string -
-
- ID of the parent image. If there is no parent image then this field - should be omitted. A collection of images may share many of the same - ancestor layers. This organizational structure is strictly a tree with - any one layer having either no parent or a single parent and zero or - more descendent layers. Cycles are not allowed and implementations - should be careful to avoid creating them or iterating through a cycle - indefinitely. -
-
- created string -
-
- ISO-8601 formatted combined date and time at which the image was - created. -
-
- author string -
-
- Gives the name and/or email address of the person or entity which - created and is responsible for maintaining the image. -
-
- architecture string -
-
- The CPU architecture which the binaries in this image are built to run - on. Possible values include: -
    -
  • 386
  • -
  • amd64
  • -
  • arm
  • -
- More values may be supported in the future and any of these may or may - not be supported by a given container runtime implementation. -
-
- os string -
-
- The name of the operating system which the image is built to run on. - Possible values include: -
    -
  • darwin
  • -
  • freebsd
  • -
  • linux
  • -
- More values may be supported in the future and any of these may or may - not be supported by a given container runtime implementation. -
-
- checksum string -
-
- Image Checksum of the filesystem changeset associated with the image - layer. -
-
- Size integer -
-
- The size in bytes of the filesystem changeset associated with the image - layer. -
-
- config struct -
-
- The execution parameters which should be used as a base when running a - container using the image. This field can be null, in - which case any execution parameters should be specified at creation of - the container. - -

Container RunConfig Field Descriptions

- -
-
- User string -
-
-

The username or UID which the process in the container should - run as. This acts as a default value to use when the value is - not specified when creating a container.

- -

All of the following are valid:

- -
    -
  • user
  • -
  • uid
  • -
  • user:group
  • -
  • uid:gid
  • -
  • uid:group
  • -
  • user:gid
  • -
- -

If group/gid is not specified, the - default group and supplementary groups of the given - user/uid in /etc/passwd - from the container are applied.

-
-
- Memory integer -
-
- Memory limit (in bytes). This acts as a default value to use - when the value is not specified when creating a container. -
-
- MemorySwap integer -
-
- Total memory usage (memory + swap); set to -1 to - disable swap. This acts as a default value to use when the - value is not specified when creating a container. -
-
- CpuShares integer -
-
- CPU shares (relative weight vs. other containers). This acts as - a default value to use when the value is not specified when - creating a container. -
-
- ExposedPorts struct -
-
- A set of ports to expose from a container running this image. - This JSON structure value is unusual because it is a direct - JSON serialization of the Go type - map[string]struct{} and is represented in JSON as - an object mapping its keys to an empty object. Here is an - example: - -
{
-    "8080": {},
-    "53/udp": {},
-    "2356/tcp": {}
-}
- - Its keys can be in the format of: -
    -
  • - "port/tcp" -
  • -
  • - "port/udp" -
  • -
  • - "port" -
  • -
- with the default protocol being "tcp" if not - specified. - - These values act as defaults and are merged with any specified - when creating a container. -
-
- Env array of strings -
-
- Entries are in the format of VARNAME="var value". - These values act as defaults and are merged with any specified - when creating a container. -
-
- Entrypoint array of strings -
-
- A list of arguments to use as the command to execute when the - container starts. This value acts as a default and is replaced - by an entrypoint specified when creating a container. -
-
- Cmd array of strings -
-
- Default arguments to the entry point of the container. These - values act as defaults and are replaced with any specified when - creating a container. If an Entrypoint value is - not specified, then the first entry of the Cmd - array should be interpreted as the executable to run. -
-
- Volumes struct -
-
- A set of directories which should be created as data volumes in - a container running this image. This JSON structure value is - unusual because it is a direct JSON serialization of the Go - type map[string]struct{} and is represented in - JSON as an object mapping its keys to an empty object. Here is - an example: -
{
-    "/var/my-app-data/": {},
-    "/etc/some-config.d/": {},
-}
-
-
- WorkingDir string -
-
- Sets the current working directory of the entry point process - in the container. This value acts as a default and is replaced - by a working directory specified when creating a container. -
-
-
-
- -Any extra fields in the Image JSON struct are considered implementation -specific and should be ignored by any implementations which are unable to -interpret them. - -## Creating an Image Filesystem Changeset - -An example of creating an Image Filesystem Changeset follows. - -An image root filesystem is first created as an empty directory named with the -ID of the image being created. Here is the initial empty directory structure -for the changeset for an image with ID `c3167915dc9d` ([real IDs are much -longer](#id_desc), but this example use a truncated one here for brevity. -Implementations need not name the rootfs directory in this way but it may be -convenient for keeping record of a large number of image layers.): - -``` -c3167915dc9d/ -``` - -Files and directories are then created: - -``` -c3167915dc9d/ - etc/ - my-app-config - bin/ - my-app-binary - my-app-tools -``` - -The `c3167915dc9d` directory is then committed as a plain Tar archive with -entries for the following files: - -``` -etc/my-app-config -bin/my-app-binary -bin/my-app-tools -``` - -The TarSum checksum for the archive file is then computed and placed in the -JSON metadata along with the execution parameters. - -To make changes to the filesystem of this container image, create a new -directory named with a new ID, such as `f60c56784b83`, and initialize it with -a snapshot of the parent image's root filesystem, so that the directory is -identical to that of `c3167915dc9d`. NOTE: a copy-on-write or union filesystem -can make this very efficient: - -``` -f60c56784b83/ - etc/ - my-app-config - bin/ - my-app-binary - my-app-tools -``` - -This example change is going add a configuration directory at `/etc/my-app.d` -which contains a default config file. There's also a change to the -`my-app-tools` binary to handle the config layout change. The `f60c56784b83` -directory then looks like this: - -``` -f60c56784b83/ - etc/ - my-app.d/ - default.cfg - bin/ - my-app-binary - my-app-tools -``` - -This reflects the removal of `/etc/my-app-config` and creation of a file and -directory at `/etc/my-app.d/default.cfg`. `/bin/my-app-tools` has also been -replaced with an updated version. Before committing this directory to a -changeset, because it has a parent image, it is first compared with the -directory tree of the parent snapshot, `f60c56784b83`, looking for files and -directories that have been added, modified, or removed. The following changeset -is found: - -``` -Added: /etc/my-app.d/default.cfg -Modified: /bin/my-app-tools -Deleted: /etc/my-app-config -``` - -A Tar Archive is then created which contains *only* this changeset: The added -and modified files and directories in their entirety, and for each deleted item -an entry for an empty file at the same location but with the basename of the -deleted file or directory prefixed with `.wh.`. The filenames prefixed with -`.wh.` are known as "whiteout" files. NOTE: For this reason, it is not possible -to create an image root filesystem which contains a file or directory with a -name beginning with `.wh.`. The resulting Tar archive for `f60c56784b83` has -the following entries: - -``` -/etc/my-app.d/default.cfg -/bin/my-app-tools -/etc/.wh.my-app-config -``` - -Any given image is likely to be composed of several of these Image Filesystem -Changeset tar archives. - -## Combined Image JSON + Filesystem Changeset Format - -There is also a format for a single archive which contains complete information -about an image, including: - - - repository names/tags - - all image layer JSON files - - all tar archives of each layer filesystem changesets - -For example, here's what the full archive of `library/busybox` is (displayed in -`tree` format): - -``` -. -├── 5785b62b697b99a5af6cd5d0aabc804d5748abbb6d3d07da5d1d3795f2dcc83e -│   ├── VERSION -│   ├── json -│   └── layer.tar -├── a7b8b41220991bfc754d7ad445ad27b7f272ab8b4a2c175b9512b97471d02a8a -│   ├── VERSION -│   ├── json -│   └── layer.tar -├── a936027c5ca8bf8f517923169a233e391cbb38469a75de8383b5228dc2d26ceb -│   ├── VERSION -│   ├── json -│   └── layer.tar -├── f60c56784b832dd990022afc120b8136ab3da9528094752ae13fe63a2d28dc8c -│   ├── VERSION -│   ├── json -│   └── layer.tar -└── repositories -``` - -There are one or more directories named with the ID for each layer in a full -image. Each of these directories contains 3 files: - - * `VERSION` - The schema version of the `json` file - * `json` - The JSON metadata for an image layer - * `layer.tar` - The Tar archive of the filesystem changeset for an image - layer. - -The content of the `VERSION` files is simply the semantic version of the JSON -metadata schema: - -``` -1.0 -``` - -And the `repositories` file is another JSON file which describes names/tags: - -``` -{ - "busybox":{ - "latest":"5785b62b697b99a5af6cd5d0aabc804d5748abbb6d3d07da5d1d3795f2dcc83e" - } -} -``` - -Every key in this object is the name of a repository, and maps to a collection -of tag suffixes. Each tag maps to the ID of the image represented by that tag. - -## Loading an Image Filesystem Changeset - -Unpacking a bundle of image layer JSON files and their corresponding filesystem -changesets can be done using a series of steps: - -1. Follow the parent IDs of image layers to find the root ancestor (an image -with no parent ID specified). -2. For every image layer, in order from root ancestor and descending down, -extract the contents of that layer's filesystem changeset archive into a -directory which will be used as the root of a container filesystem. - - - Extract all contents of each archive. - - Walk the directory tree once more, removing any files with the prefix - `.wh.` and the corresponding file or directory named without this prefix. - - -## Implementations - -This specification is an admittedly imperfect description of an -imperfectly-understood problem. The Docker project is, in turn, an attempt to -implement this specification. Our goal and our execution toward it will evolve -over time, but our primary concern in this specification and in our -implementation is compatibility and interoperability. diff --git a/vendor/github.com/docker/docker/pkg/archive/testdata/broken.tar b/vendor/github.com/docker/docker/pkg/archive/testdata/broken.tar deleted file mode 100644 index 8f10ea6b..00000000 Binary files a/vendor/github.com/docker/docker/pkg/archive/testdata/broken.tar and /dev/null differ diff --git a/vendor/github.com/docker/docker/pkg/mflag/example/example.go b/vendor/github.com/docker/docker/pkg/mflag/example/example.go deleted file mode 100644 index 2e766dd1..00000000 --- a/vendor/github.com/docker/docker/pkg/mflag/example/example.go +++ /dev/null @@ -1,36 +0,0 @@ -package main - -import ( - "fmt" - - flag "github.com/docker/docker/pkg/mflag" -) - -var ( - i int - str string - b, b2, h bool -) - -func init() { - flag.Bool([]string{"#hp", "#-halp"}, false, "display the halp") - flag.BoolVar(&b, []string{"b", "#bal", "#bol", "-bal"}, false, "a simple bool") - flag.BoolVar(&b, []string{"g", "#gil"}, false, "a simple bool") - flag.BoolVar(&b2, []string{"#-bool"}, false, "a simple bool") - flag.IntVar(&i, []string{"-integer", "-number"}, -1, "a simple integer") - flag.StringVar(&str, []string{"s", "#hidden", "-string"}, "", "a simple string") //-s -hidden and --string will work, but -hidden won't be in the usage - flag.BoolVar(&h, []string{"h", "#help", "-help"}, false, "display the help") - flag.StringVar(&str, []string{"mode"}, "mode1", "set the mode\nmode1: use the mode1\nmode2: use the mode2\nmode3: use the mode3") - flag.Parse() -} -func main() { - if h { - flag.PrintDefaults() - } else { - fmt.Printf("s/#hidden/-string: %s\n", str) - fmt.Printf("b: %t\n", b) - fmt.Printf("-bool: %t\n", b2) - fmt.Printf("s/#hidden/-string(via lookup): %s\n", flag.Lookup("s").Value.String()) - fmt.Printf("ARGS: %v\n", flag.Args()) - } -} diff --git a/vendor/github.com/docker/docker/pkg/parsers/filters/parse.go b/vendor/github.com/docker/docker/pkg/parsers/filters/parse.go deleted file mode 100644 index 6c394f16..00000000 --- a/vendor/github.com/docker/docker/pkg/parsers/filters/parse.go +++ /dev/null @@ -1,134 +0,0 @@ -// Package filters provides helper function to parse and handle command line -// filter, used for example in docker ps or docker images commands. -package filters - -import ( - "encoding/json" - "errors" - "regexp" - "strings" -) - -// Args stores filter arguments as map key:{array of values}. -// It contains a aggregation of the list of arguments (which are in the form -// of -f 'key=value') based on the key, and store values for the same key -// in an slice. -// e.g given -f 'label=label1=1' -f 'label=label2=2' -f 'image.name=ubuntu' -// the args will be {'label': {'label1=1','label2=2'}, 'image.name', {'ubuntu'}} -type Args map[string][]string - -// ParseFlag parses the argument to the filter flag. Like -// -// `docker ps -f 'created=today' -f 'image.name=ubuntu*'` -// -// If prev map is provided, then it is appended to, and returned. By default a new -// map is created. -func ParseFlag(arg string, prev Args) (Args, error) { - filters := prev - if prev == nil { - filters = Args{} - } - if len(arg) == 0 { - return filters, nil - } - - if !strings.Contains(arg, "=") { - return filters, ErrBadFormat - } - - f := strings.SplitN(arg, "=", 2) - name := strings.ToLower(strings.TrimSpace(f[0])) - value := strings.TrimSpace(f[1]) - filters[name] = append(filters[name], value) - - return filters, nil -} - -// ErrBadFormat is an error returned in case of bad format for a filter. -var ErrBadFormat = errors.New("bad format of filter (expected name=value)") - -// ToParam packs the Args into an string for easy transport from client to server. -func ToParam(a Args) (string, error) { - // this way we don't URL encode {}, just empty space - if len(a) == 0 { - return "", nil - } - - buf, err := json.Marshal(a) - if err != nil { - return "", err - } - return string(buf), nil -} - -// FromParam unpacks the filter Args. -func FromParam(p string) (Args, error) { - args := Args{} - if len(p) == 0 { - return args, nil - } - if err := json.NewDecoder(strings.NewReader(p)).Decode(&args); err != nil { - return nil, err - } - return args, nil -} - -// MatchKVList returns true if the values for the specified field maches the ones -// from the sources. -// e.g. given Args are {'label': {'label1=1','label2=1'}, 'image.name', {'ubuntu'}}, -// field is 'label' and sources are {'label':{'label1=1','label2=2','label3=3'}} -// it returns true. -func (filters Args) MatchKVList(field string, sources map[string]string) bool { - fieldValues := filters[field] - - //do not filter if there is no filter set or cannot determine filter - if len(fieldValues) == 0 { - return true - } - - if sources == nil || len(sources) == 0 { - return false - } - -outer: - for _, name2match := range fieldValues { - testKV := strings.SplitN(name2match, "=", 2) - - for k, v := range sources { - if len(testKV) == 1 { - if k == testKV[0] { - continue outer - } - } else if k == testKV[0] && v == testKV[1] { - continue outer - } - } - - return false - } - - return true -} - -// Match returns true if the values for the specified field matches the source string -// e.g. given Args are {'label': {'label1=1','label2=1'}, 'image.name', {'ubuntu'}}, -// field is 'image.name' and source is 'ubuntu' -// it returns true. -func (filters Args) Match(field, source string) bool { - fieldValues := filters[field] - - //do not filter if there is no filter set or cannot determine filter - if len(fieldValues) == 0 { - return true - } - for _, name2match := range fieldValues { - match, err := regexp.MatchString(name2match, source) - if err != nil { - continue - } - if match { - return true - } - } - return false -} diff --git a/vendor/github.com/docker/docker/pkg/parsers/filters/parse_test.go b/vendor/github.com/docker/docker/pkg/parsers/filters/parse_test.go deleted file mode 100644 index eb9fcef9..00000000 --- a/vendor/github.com/docker/docker/pkg/parsers/filters/parse_test.go +++ /dev/null @@ -1,218 +0,0 @@ -package filters - -import ( - "sort" - "testing" -) - -func TestParseArgs(t *testing.T) { - // equivalent of `docker ps -f 'created=today' -f 'image.name=ubuntu*' -f 'image.name=*untu'` - flagArgs := []string{ - "created=today", - "image.name=ubuntu*", - "image.name=*untu", - } - var ( - args = Args{} - err error - ) - for i := range flagArgs { - args, err = ParseFlag(flagArgs[i], args) - if err != nil { - t.Errorf("failed to parse %s: %s", flagArgs[i], err) - } - } - if len(args["created"]) != 1 { - t.Errorf("failed to set this arg") - } - if len(args["image.name"]) != 2 { - t.Errorf("the args should have collapsed") - } -} - -func TestParseArgsEdgeCase(t *testing.T) { - var filters Args - args, err := ParseFlag("", filters) - if err != nil { - t.Fatal(err) - } - if args == nil || len(args) != 0 { - t.Fatalf("Expected an empty Args (map), got %v", args) - } - if args, err = ParseFlag("anything", args); err == nil || err != ErrBadFormat { - t.Fatalf("Expected ErrBadFormat, got %v", err) - } -} - -func TestToParam(t *testing.T) { - a := Args{ - "created": []string{"today"}, - "image.name": []string{"ubuntu*", "*untu"}, - } - - _, err := ToParam(a) - if err != nil { - t.Errorf("failed to marshal the filters: %s", err) - } -} - -func TestFromParam(t *testing.T) { - invalids := []string{ - "anything", - "['a','list']", - "{'key': 'value'}", - `{"key": "value"}`, - } - valids := map[string]Args{ - `{"key": ["value"]}`: { - "key": {"value"}, - }, - `{"key": ["value1", "value2"]}`: { - "key": {"value1", "value2"}, - }, - `{"key1": ["value1"], "key2": ["value2"]}`: { - "key1": {"value1"}, - "key2": {"value2"}, - }, - } - for _, invalid := range invalids { - if _, err := FromParam(invalid); err == nil { - t.Fatalf("Expected an error with %v, got nothing", invalid) - } - } - for json, expectedArgs := range valids { - args, err := FromParam(json) - if err != nil { - t.Fatal(err) - } - if len(args) != len(expectedArgs) { - t.Fatalf("Expected %v, go %v", expectedArgs, args) - } - for key, expectedValues := range expectedArgs { - values := args[key] - sort.Strings(values) - sort.Strings(expectedValues) - if len(values) != len(expectedValues) { - t.Fatalf("Expected %v, go %v", expectedArgs, args) - } - for index, expectedValue := range expectedValues { - if values[index] != expectedValue { - t.Fatalf("Expected %v, go %v", expectedArgs, args) - } - } - } - } -} - -func TestEmpty(t *testing.T) { - a := Args{} - v, err := ToParam(a) - if err != nil { - t.Errorf("failed to marshal the filters: %s", err) - } - v1, err := FromParam(v) - if err != nil { - t.Errorf("%s", err) - } - if len(a) != len(v1) { - t.Errorf("these should both be empty sets") - } -} - -func TestArgsMatchKVList(t *testing.T) { - // empty sources - args := Args{ - "created": []string{"today"}, - } - if args.MatchKVList("created", map[string]string{}) { - t.Fatalf("Expected false for (%v,created), got true", args) - } - // Not empty sources - sources := map[string]string{ - "key1": "value1", - "key2": "value2", - "key3": "value3", - } - matches := map[*Args]string{ - &Args{}: "field", - &Args{ - "created": []string{"today"}, - "labels": []string{"key1"}, - }: "labels", - &Args{ - "created": []string{"today"}, - "labels": []string{"key1=value1"}, - }: "labels", - } - differs := map[*Args]string{ - &Args{ - "created": []string{"today"}, - }: "created", - &Args{ - "created": []string{"today"}, - "labels": []string{"key4"}, - }: "labels", - &Args{ - "created": []string{"today"}, - "labels": []string{"key1=value3"}, - }: "labels", - } - for args, field := range matches { - if args.MatchKVList(field, sources) != true { - t.Fatalf("Expected true for %v on %v, got false", sources, args) - } - } - for args, field := range differs { - if args.MatchKVList(field, sources) != false { - t.Fatalf("Expected false for %v on %v, got true", sources, args) - } - } -} - -func TestArgsMatch(t *testing.T) { - source := "today" - matches := map[*Args]string{ - &Args{}: "field", - &Args{ - "created": []string{"today"}, - "labels": []string{"key1"}, - }: "today", - &Args{ - "created": []string{"to*"}, - }: "created", - &Args{ - "created": []string{"to(.*)"}, - }: "created", - &Args{ - "created": []string{"tod"}, - }: "created", - &Args{ - "created": []string{"anything", "to*"}, - }: "created", - } - differs := map[*Args]string{ - &Args{ - "created": []string{"tomorrow"}, - }: "created", - &Args{ - "created": []string{"to(day"}, - }: "created", - &Args{ - "created": []string{"tom(.*)"}, - }: "created", - &Args{ - "created": []string{"today1"}, - "labels": []string{"today"}, - }: "created", - } - for args, field := range matches { - if args.Match(field, source) != true { - t.Fatalf("Expected true for %v on %v, got false", source, args) - } - } - for args, field := range differs { - if args.Match(field, source) != false { - t.Fatalf("Expected false for %v on %v, got true", source, args) - } - } -} diff --git a/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_freebsd.go b/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_freebsd.go deleted file mode 100644 index 0589cf2a..00000000 --- a/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_freebsd.go +++ /dev/null @@ -1,18 +0,0 @@ -package operatingsystem - -import ( - "errors" -) - -// GetOperatingSystem gets the name of the current operating system. -func GetOperatingSystem() (string, error) { - // TODO: Implement OS detection - return "", errors.New("Cannot detect OS version") -} - -// IsContainerized returns true if we are running inside a container. -// No-op on FreeBSD, always returns false. -func IsContainerized() (bool, error) { - // TODO: Implement jail detection - return false, errors.New("Cannot detect if we are in container") -} diff --git a/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_linux.go b/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_linux.go deleted file mode 100644 index f6f0a728..00000000 --- a/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_linux.go +++ /dev/null @@ -1,68 +0,0 @@ -// Package operatingsystem provides helper function to get the operating system -// name for different platforms. -package operatingsystem - -import ( - "bufio" - "bytes" - "fmt" - "io/ioutil" - "os" - "strings" - - "github.com/mattn/go-shellwords" -) - -var ( - // file to use to detect if the daemon is running in a container - proc1Cgroup = "/proc/1/cgroup" - - // file to check to determine Operating System - etcOsRelease = "/etc/os-release" -) - -// GetOperatingSystem gets the name of the current operating system. -func GetOperatingSystem() (string, error) { - osReleaseFile, err := os.Open(etcOsRelease) - if err != nil { - return "", err - } - defer osReleaseFile.Close() - - var prettyName string - scanner := bufio.NewScanner(osReleaseFile) - for scanner.Scan() { - line := scanner.Text() - if strings.HasPrefix(line, "PRETTY_NAME=") { - data := strings.SplitN(line, "=", 2) - prettyNames, err := shellwords.Parse(data[1]) - if err != nil { - return "", fmt.Errorf("PRETTY_NAME is invalid: %s", err.Error()) - } - if len(prettyNames) != 1 { - return "", fmt.Errorf("PRETTY_NAME needs to be enclosed by quotes if they have spaces: %s", data[1]) - } - prettyName = prettyNames[0] - } - } - if prettyName != "" { - return prettyName, nil - } - // If not set, defaults to PRETTY_NAME="Linux" - // c.f. http://www.freedesktop.org/software/systemd/man/os-release.html - return "Linux", nil -} - -// IsContainerized returns true if we are running inside a container. -func IsContainerized() (bool, error) { - b, err := ioutil.ReadFile(proc1Cgroup) - if err != nil { - return false, err - } - for _, line := range bytes.Split(b, []byte{'\n'}) { - if len(line) > 0 && !bytes.HasSuffix(line, []byte{'/'}) { - return true, nil - } - } - return false, nil -} diff --git a/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_unix_test.go b/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_unix_test.go deleted file mode 100644 index 1bad093c..00000000 --- a/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_unix_test.go +++ /dev/null @@ -1,197 +0,0 @@ -// +build linux freebsd - -package operatingsystem - -import ( - "io/ioutil" - "os" - "path/filepath" - "testing" -) - -func TestGetOperatingSystem(t *testing.T) { - var backup = etcOsRelease - - invalids := []struct { - content string - errorExpected string - }{ - { - `PRETTY_NAME=Source Mage GNU/Linux -PRETTY_NAME=Ubuntu 14.04.LTS`, - "PRETTY_NAME needs to be enclosed by quotes if they have spaces: Source Mage GNU/Linux", - }, - { - `PRETTY_NAME="Ubuntu Linux -PRETTY_NAME=Ubuntu 14.04.LTS`, - "PRETTY_NAME is invalid: invalid command line string", - }, - { - `PRETTY_NAME=Ubuntu' -PRETTY_NAME=Ubuntu 14.04.LTS`, - "PRETTY_NAME is invalid: invalid command line string", - }, - { - `PRETTY_NAME' -PRETTY_NAME=Ubuntu 14.04.LTS`, - "PRETTY_NAME needs to be enclosed by quotes if they have spaces: Ubuntu 14.04.LTS", - }, - } - - valids := []struct { - content string - expected string - }{ - { - `NAME="Ubuntu" -PRETTY_NAME_AGAIN="Ubuntu 14.04.LTS" -VERSION="14.04, Trusty Tahr" -ID=ubuntu -ID_LIKE=debian -VERSION_ID="14.04" -HOME_URL="http://www.ubuntu.com/" -SUPPORT_URL="http://help.ubuntu.com/" -BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`, - "Linux", - }, - { - `NAME="Ubuntu" -VERSION="14.04, Trusty Tahr" -ID=ubuntu -ID_LIKE=debian -VERSION_ID="14.04" -HOME_URL="http://www.ubuntu.com/" -SUPPORT_URL="http://help.ubuntu.com/" -BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`, - "Linux", - }, - { - `NAME=Gentoo -ID=gentoo -PRETTY_NAME="Gentoo/Linux" -ANSI_COLOR="1;32" -HOME_URL="http://www.gentoo.org/" -SUPPORT_URL="http://www.gentoo.org/main/en/support.xml" -BUG_REPORT_URL="https://bugs.gentoo.org/" -`, - "Gentoo/Linux", - }, - { - `NAME="Ubuntu" -VERSION="14.04, Trusty Tahr" -ID=ubuntu -ID_LIKE=debian -PRETTY_NAME="Ubuntu 14.04 LTS" -VERSION_ID="14.04" -HOME_URL="http://www.ubuntu.com/" -SUPPORT_URL="http://help.ubuntu.com/" -BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`, - "Ubuntu 14.04 LTS", - }, - { - `NAME="Ubuntu" -VERSION="14.04, Trusty Tahr" -ID=ubuntu -ID_LIKE=debian -PRETTY_NAME='Ubuntu 14.04 LTS'`, - "Ubuntu 14.04 LTS", - }, - { - `PRETTY_NAME=Source -NAME="Source Mage"`, - "Source", - }, - { - `PRETTY_NAME=Source -PRETTY_NAME="Source Mage"`, - "Source Mage", - }, - } - - dir := os.TempDir() - etcOsRelease = filepath.Join(dir, "etcOsRelease") - - defer func() { - os.Remove(etcOsRelease) - etcOsRelease = backup - }() - - for _, elt := range invalids { - if err := ioutil.WriteFile(etcOsRelease, []byte(elt.content), 0600); err != nil { - t.Fatalf("failed to write to %s: %v", etcOsRelease, err) - } - s, err := GetOperatingSystem() - if err == nil || err.Error() != elt.errorExpected { - t.Fatalf("Expected an error %q, got %q (err: %v)", elt.errorExpected, s, err) - } - } - - for _, elt := range valids { - if err := ioutil.WriteFile(etcOsRelease, []byte(elt.content), 0600); err != nil { - t.Fatalf("failed to write to %s: %v", etcOsRelease, err) - } - s, err := GetOperatingSystem() - if err != nil || s != elt.expected { - t.Fatalf("Expected %q, got %q (err: %v)", elt.expected, s, err) - } - } -} - -func TestIsContainerized(t *testing.T) { - var ( - backup = proc1Cgroup - nonContainerizedProc1Cgroup = []byte(`14:name=systemd:/ -13:hugetlb:/ -12:net_prio:/ -11:perf_event:/ -10:bfqio:/ -9:blkio:/ -8:net_cls:/ -7:freezer:/ -6:devices:/ -5:memory:/ -4:cpuacct:/ -3:cpu:/ -2:cpuset:/ -`) - containerizedProc1Cgroup = []byte(`9:perf_event:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d -8:blkio:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d -7:net_cls:/ -6:freezer:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d -5:devices:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d -4:memory:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d -3:cpuacct:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d -2:cpu:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d -1:cpuset:/`) - ) - - dir := os.TempDir() - proc1Cgroup = filepath.Join(dir, "proc1Cgroup") - - defer func() { - os.Remove(proc1Cgroup) - proc1Cgroup = backup - }() - - if err := ioutil.WriteFile(proc1Cgroup, nonContainerizedProc1Cgroup, 0600); err != nil { - t.Fatalf("failed to write to %s: %v", proc1Cgroup, err) - } - inContainer, err := IsContainerized() - if err != nil { - t.Fatal(err) - } - if inContainer { - t.Fatal("Wrongly assuming containerized") - } - - if err := ioutil.WriteFile(proc1Cgroup, containerizedProc1Cgroup, 0600); err != nil { - t.Fatalf("failed to write to %s: %v", proc1Cgroup, err) - } - inContainer, err = IsContainerized() - if err != nil { - t.Fatal(err) - } - if !inContainer { - t.Fatal("Wrongly assuming non-containerized") - } -} diff --git a/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_windows.go b/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_windows.go deleted file mode 100644 index 3c86b6af..00000000 --- a/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_windows.go +++ /dev/null @@ -1,49 +0,0 @@ -package operatingsystem - -import ( - "syscall" - "unsafe" -) - -// See https://code.google.com/p/go/source/browse/src/pkg/mime/type_windows.go?r=d14520ac25bf6940785aabb71f5be453a286f58c -// for a similar sample - -// GetOperatingSystem gets the name of the current operating system. -func GetOperatingSystem() (string, error) { - - var h syscall.Handle - - // Default return value - ret := "Unknown Operating System" - - if err := syscall.RegOpenKeyEx(syscall.HKEY_LOCAL_MACHINE, - syscall.StringToUTF16Ptr(`SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\`), - 0, - syscall.KEY_READ, - &h); err != nil { - return ret, err - } - defer syscall.RegCloseKey(h) - - var buf [1 << 10]uint16 - var typ uint32 - n := uint32(len(buf) * 2) // api expects array of bytes, not uint16 - - if err := syscall.RegQueryValueEx(h, - syscall.StringToUTF16Ptr("ProductName"), - nil, - &typ, - (*byte)(unsafe.Pointer(&buf[0])), - &n); err != nil { - return ret, err - } - ret = syscall.UTF16ToString(buf[:]) - - return ret, nil -} - -// IsContainerized returns true if we are running inside a container. -// No-op on Windows, always returns false. -func IsContainerized() (bool, error) { - return false, nil -} diff --git a/vendor/github.com/docker/docker/pkg/stdcopy/stdcopy.go b/vendor/github.com/docker/docker/pkg/stdcopy/stdcopy.go deleted file mode 100644 index 9be01841..00000000 --- a/vendor/github.com/docker/docker/pkg/stdcopy/stdcopy.go +++ /dev/null @@ -1,175 +0,0 @@ -package stdcopy - -import ( - "encoding/binary" - "errors" - "io" - - "github.com/Sirupsen/logrus" -) - -const ( - stdWriterPrefixLen = 8 - stdWriterFdIndex = 0 - stdWriterSizeIndex = 4 - - startingBufLen = 32*1024 + stdWriterPrefixLen + 1 -) - -// StdType prefixes type and length to standard stream. -type StdType [stdWriterPrefixLen]byte - -var ( - // Stdin represents standard input stream type. - Stdin = StdType{0: 0} - // Stdout represents standard output stream type. - Stdout = StdType{0: 1} - // Stderr represents standard error steam type. - Stderr = StdType{0: 2} -) - -// StdWriter is wrapper of io.Writer with extra customized info. -type StdWriter struct { - io.Writer - prefix StdType - sizeBuf []byte -} - -func (w *StdWriter) Write(buf []byte) (n int, err error) { - var n1, n2 int - if w == nil || w.Writer == nil { - return 0, errors.New("Writer not instantiated") - } - binary.BigEndian.PutUint32(w.prefix[4:], uint32(len(buf))) - n1, err = w.Writer.Write(w.prefix[:]) - if err != nil { - n = n1 - stdWriterPrefixLen - } else { - n2, err = w.Writer.Write(buf) - n = n1 + n2 - stdWriterPrefixLen - } - if n < 0 { - n = 0 - } - return -} - -// NewStdWriter instantiates a new Writer. -// Everything written to it will be encapsulated using a custom format, -// and written to the underlying `w` stream. -// This allows multiple write streams (e.g. stdout and stderr) to be muxed into a single connection. -// `t` indicates the id of the stream to encapsulate. -// It can be stdcopy.Stdin, stdcopy.Stdout, stdcopy.Stderr. -func NewStdWriter(w io.Writer, t StdType) *StdWriter { - return &StdWriter{ - Writer: w, - prefix: t, - sizeBuf: make([]byte, 4), - } -} - -var errInvalidStdHeader = errors.New("Unrecognized input header") - -// StdCopy is a modified version of io.Copy. -// -// StdCopy will demultiplex `src`, assuming that it contains two streams, -// previously multiplexed together using a StdWriter instance. -// As it reads from `src`, StdCopy will write to `dstout` and `dsterr`. -// -// StdCopy will read until it hits EOF on `src`. It will then return a nil error. -// In other words: if `err` is non nil, it indicates a real underlying error. -// -// `written` will hold the total number of bytes written to `dstout` and `dsterr`. -func StdCopy(dstout, dsterr io.Writer, src io.Reader) (written int64, err error) { - var ( - buf = make([]byte, startingBufLen) - bufLen = len(buf) - nr, nw int - er, ew error - out io.Writer - frameSize int - ) - - for { - // Make sure we have at least a full header - for nr < stdWriterPrefixLen { - var nr2 int - nr2, er = src.Read(buf[nr:]) - nr += nr2 - if er == io.EOF { - if nr < stdWriterPrefixLen { - logrus.Debugf("Corrupted prefix: %v", buf[:nr]) - return written, nil - } - break - } - if er != nil { - logrus.Debugf("Error reading header: %s", er) - return 0, er - } - } - - // Check the first byte to know where to write - switch buf[stdWriterFdIndex] { - case 0: - fallthrough - case 1: - // Write on stdout - out = dstout - case 2: - // Write on stderr - out = dsterr - default: - logrus.Debugf("Error selecting output fd: (%d)", buf[stdWriterFdIndex]) - return 0, errInvalidStdHeader - } - - // Retrieve the size of the frame - frameSize = int(binary.BigEndian.Uint32(buf[stdWriterSizeIndex : stdWriterSizeIndex+4])) - logrus.Debugf("framesize: %d", frameSize) - - // Check if the buffer is big enough to read the frame. - // Extend it if necessary. - if frameSize+stdWriterPrefixLen > bufLen { - logrus.Debugf("Extending buffer cap by %d (was %d)", frameSize+stdWriterPrefixLen-bufLen+1, len(buf)) - buf = append(buf, make([]byte, frameSize+stdWriterPrefixLen-bufLen+1)...) - bufLen = len(buf) - } - - // While the amount of bytes read is less than the size of the frame + header, we keep reading - for nr < frameSize+stdWriterPrefixLen { - var nr2 int - nr2, er = src.Read(buf[nr:]) - nr += nr2 - if er == io.EOF { - if nr < frameSize+stdWriterPrefixLen { - logrus.Debugf("Corrupted frame: %v", buf[stdWriterPrefixLen:nr]) - return written, nil - } - break - } - if er != nil { - logrus.Debugf("Error reading frame: %s", er) - return 0, er - } - } - - // Write the retrieved frame (without header) - nw, ew = out.Write(buf[stdWriterPrefixLen : frameSize+stdWriterPrefixLen]) - if ew != nil { - logrus.Debugf("Error writing frame: %s", ew) - return 0, ew - } - // If the frame has not been fully written: error - if nw != frameSize { - logrus.Debugf("Error Short Write: (%d on %d)", nw, frameSize) - return 0, io.ErrShortWrite - } - written += int64(nw) - - // Move the rest of the buffer to the beginning - copy(buf, buf[frameSize+stdWriterPrefixLen:]) - // Move the index - nr -= frameSize + stdWriterPrefixLen - } -} diff --git a/vendor/github.com/docker/docker/pkg/stdcopy/stdcopy_test.go b/vendor/github.com/docker/docker/pkg/stdcopy/stdcopy_test.go deleted file mode 100644 index 88d88d41..00000000 --- a/vendor/github.com/docker/docker/pkg/stdcopy/stdcopy_test.go +++ /dev/null @@ -1,261 +0,0 @@ -package stdcopy - -import ( - "bytes" - "errors" - "io" - "io/ioutil" - "strings" - "testing" -) - -func TestNewStdWriter(t *testing.T) { - writer := NewStdWriter(ioutil.Discard, Stdout) - if writer == nil { - t.Fatalf("NewStdWriter with an invalid StdType should not return nil.") - } -} - -func TestWriteWithUnitializedStdWriter(t *testing.T) { - writer := StdWriter{ - Writer: nil, - prefix: Stdout, - sizeBuf: make([]byte, 4), - } - n, err := writer.Write([]byte("Something here")) - if n != 0 || err == nil { - t.Fatalf("Should fail when given an uncomplete or uninitialized StdWriter") - } -} - -func TestWriteWithNilBytes(t *testing.T) { - writer := NewStdWriter(ioutil.Discard, Stdout) - n, err := writer.Write(nil) - if err != nil { - t.Fatalf("Shouldn't have fail when given no data") - } - if n > 0 { - t.Fatalf("Write should have written 0 byte, but has written %d", n) - } -} - -func TestWrite(t *testing.T) { - writer := NewStdWriter(ioutil.Discard, Stdout) - data := []byte("Test StdWrite.Write") - n, err := writer.Write(data) - if err != nil { - t.Fatalf("Error while writing with StdWrite") - } - if n != len(data) { - t.Fatalf("Write should have written %d byte but wrote %d.", len(data), n) - } -} - -type errWriter struct { - n int - err error -} - -func (f *errWriter) Write(buf []byte) (int, error) { - return f.n, f.err -} - -func TestWriteWithWriterError(t *testing.T) { - expectedError := errors.New("expected") - expectedReturnedBytes := 10 - writer := NewStdWriter(&errWriter{ - n: stdWriterPrefixLen + expectedReturnedBytes, - err: expectedError}, Stdout) - data := []byte("This won't get written, sigh") - n, err := writer.Write(data) - if err != expectedError { - t.Fatalf("Didn't get expected error.") - } - if n != expectedReturnedBytes { - t.Fatalf("Didn't get expected writen bytes %d, got %d.", - expectedReturnedBytes, n) - } -} - -func TestWriteDoesNotReturnNegativeWrittenBytes(t *testing.T) { - writer := NewStdWriter(&errWriter{n: -1}, Stdout) - data := []byte("This won't get written, sigh") - actual, _ := writer.Write(data) - if actual != 0 { - t.Fatalf("Expected returned written bytes equal to 0, got %d", actual) - } -} - -func getSrcBuffer(stdOutBytes, stdErrBytes []byte) (buffer *bytes.Buffer, err error) { - buffer = new(bytes.Buffer) - dstOut := NewStdWriter(buffer, Stdout) - _, err = dstOut.Write(stdOutBytes) - if err != nil { - return - } - dstErr := NewStdWriter(buffer, Stderr) - _, err = dstErr.Write(stdErrBytes) - return -} - -func TestStdCopyWriteAndRead(t *testing.T) { - stdOutBytes := []byte(strings.Repeat("o", startingBufLen)) - stdErrBytes := []byte(strings.Repeat("e", startingBufLen)) - buffer, err := getSrcBuffer(stdOutBytes, stdErrBytes) - if err != nil { - t.Fatal(err) - } - written, err := StdCopy(ioutil.Discard, ioutil.Discard, buffer) - if err != nil { - t.Fatal(err) - } - expectedTotalWritten := len(stdOutBytes) + len(stdErrBytes) - if written != int64(expectedTotalWritten) { - t.Fatalf("Expected to have total of %d bytes written, got %d", expectedTotalWritten, written) - } -} - -type customReader struct { - n int - err error - totalCalls int - correctCalls int - src *bytes.Buffer -} - -func (f *customReader) Read(buf []byte) (int, error) { - f.totalCalls++ - if f.totalCalls <= f.correctCalls { - return f.src.Read(buf) - } - return f.n, f.err -} - -func TestStdCopyReturnsErrorReadingHeader(t *testing.T) { - expectedError := errors.New("error") - reader := &customReader{ - err: expectedError} - written, err := StdCopy(ioutil.Discard, ioutil.Discard, reader) - if written != 0 { - t.Fatalf("Expected 0 bytes read, got %d", written) - } - if err != expectedError { - t.Fatalf("Didn't get expected error") - } -} - -func TestStdCopyReturnsErrorReadingFrame(t *testing.T) { - expectedError := errors.New("error") - stdOutBytes := []byte(strings.Repeat("o", startingBufLen)) - stdErrBytes := []byte(strings.Repeat("e", startingBufLen)) - buffer, err := getSrcBuffer(stdOutBytes, stdErrBytes) - if err != nil { - t.Fatal(err) - } - reader := &customReader{ - correctCalls: 1, - n: stdWriterPrefixLen + 1, - err: expectedError, - src: buffer} - written, err := StdCopy(ioutil.Discard, ioutil.Discard, reader) - if written != 0 { - t.Fatalf("Expected 0 bytes read, got %d", written) - } - if err != expectedError { - t.Fatalf("Didn't get expected error") - } -} - -func TestStdCopyDetectsCorruptedFrame(t *testing.T) { - stdOutBytes := []byte(strings.Repeat("o", startingBufLen)) - stdErrBytes := []byte(strings.Repeat("e", startingBufLen)) - buffer, err := getSrcBuffer(stdOutBytes, stdErrBytes) - if err != nil { - t.Fatal(err) - } - reader := &customReader{ - correctCalls: 1, - n: stdWriterPrefixLen + 1, - err: io.EOF, - src: buffer} - written, err := StdCopy(ioutil.Discard, ioutil.Discard, reader) - if written != startingBufLen { - t.Fatalf("Expected 0 bytes read, got %d", written) - } - if err != nil { - t.Fatal("Didn't get nil error") - } -} - -func TestStdCopyWithInvalidInputHeader(t *testing.T) { - dstOut := NewStdWriter(ioutil.Discard, Stdout) - dstErr := NewStdWriter(ioutil.Discard, Stderr) - src := strings.NewReader("Invalid input") - _, err := StdCopy(dstOut, dstErr, src) - if err == nil { - t.Fatal("StdCopy with invalid input header should fail.") - } -} - -func TestStdCopyWithCorruptedPrefix(t *testing.T) { - data := []byte{0x01, 0x02, 0x03} - src := bytes.NewReader(data) - written, err := StdCopy(nil, nil, src) - if err != nil { - t.Fatalf("StdCopy should not return an error with corrupted prefix.") - } - if written != 0 { - t.Fatalf("StdCopy should have written 0, but has written %d", written) - } -} - -func TestStdCopyReturnsWriteErrors(t *testing.T) { - stdOutBytes := []byte(strings.Repeat("o", startingBufLen)) - stdErrBytes := []byte(strings.Repeat("e", startingBufLen)) - buffer, err := getSrcBuffer(stdOutBytes, stdErrBytes) - if err != nil { - t.Fatal(err) - } - expectedError := errors.New("expected") - - dstOut := &errWriter{err: expectedError} - - written, err := StdCopy(dstOut, ioutil.Discard, buffer) - if written != 0 { - t.Fatalf("StdCopy should have written 0, but has written %d", written) - } - if err != expectedError { - t.Fatalf("Didn't get expected error, got %v", err) - } -} - -func TestStdCopyDetectsNotFullyWrittenFrames(t *testing.T) { - stdOutBytes := []byte(strings.Repeat("o", startingBufLen)) - stdErrBytes := []byte(strings.Repeat("e", startingBufLen)) - buffer, err := getSrcBuffer(stdOutBytes, stdErrBytes) - if err != nil { - t.Fatal(err) - } - dstOut := &errWriter{n: startingBufLen - 10} - - written, err := StdCopy(dstOut, ioutil.Discard, buffer) - if written != 0 { - t.Fatalf("StdCopy should have return 0 written bytes, but returned %d", written) - } - if err != io.ErrShortWrite { - t.Fatalf("Didn't get expected io.ErrShortWrite error") - } -} - -func BenchmarkWrite(b *testing.B) { - w := NewStdWriter(ioutil.Discard, Stdout) - data := []byte("Test line for testing stdwriter performance\n") - data = bytes.Repeat(data, 100) - b.SetBytes(int64(len(data))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - if _, err := w.Write(data); err != nil { - b.Fatal(err) - } - } -} diff --git a/vendor/github.com/docker/docker/pkg/tarsum/testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/json b/vendor/github.com/docker/docker/pkg/tarsum/testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/json deleted file mode 100644 index 48e2af34..00000000 --- a/vendor/github.com/docker/docker/pkg/tarsum/testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/json +++ /dev/null @@ -1 +0,0 @@ -{"id":"46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457","parent":"def3f9165934325dfd027c86530b2ea49bb57a0963eb1336b3a0415ff6fd56de","created":"2014-04-07T02:45:52.610504484Z","container":"e0f07f8d72cae171a3dcc35859960e7e956e0628bce6fedc4122bf55b2c287c7","container_config":{"Hostname":"88807319f25e","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"ExposedPorts":null,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["HOME=/","PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh","-c","sed -ri 's/^(%wheel.*)(ALL)$/\\1NOPASSWD: \\2/' /etc/sudoers"],"Image":"def3f9165934325dfd027c86530b2ea49bb57a0963eb1336b3a0415ff6fd56de","Volumes":null,"WorkingDir":"","Entrypoint":null,"NetworkDisabled":false,"OnBuild":[]},"docker_version":"0.9.1-dev","config":{"Hostname":"88807319f25e","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"ExposedPorts":null,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["HOME=/","PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":null,"Image":"def3f9165934325dfd027c86530b2ea49bb57a0963eb1336b3a0415ff6fd56de","Volumes":null,"WorkingDir":"","Entrypoint":null,"NetworkDisabled":false,"OnBuild":[]},"architecture":"amd64","os":"linux","Size":3425} \ No newline at end of file diff --git a/vendor/github.com/docker/docker/pkg/tarsum/testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar b/vendor/github.com/docker/docker/pkg/tarsum/testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar deleted file mode 100644 index dfd5c204..00000000 Binary files a/vendor/github.com/docker/docker/pkg/tarsum/testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar and /dev/null differ diff --git a/vendor/github.com/docker/docker/pkg/tarsum/testdata/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/json b/vendor/github.com/docker/docker/pkg/tarsum/testdata/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/json deleted file mode 100644 index af57be01..00000000 --- a/vendor/github.com/docker/docker/pkg/tarsum/testdata/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/json +++ /dev/null @@ -1 +0,0 @@ -{"id":"511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158","comment":"Imported from -","created":"2013-06-13T14:03:50.821769-07:00","container_config":{"Hostname":"","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"ExposedPorts":null,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":null,"Cmd":null,"Image":"","Volumes":null,"WorkingDir":"","Entrypoint":null,"NetworkDisabled":false,"OnBuild":null},"docker_version":"0.4.0","architecture":"x86_64","Size":0} \ No newline at end of file diff --git a/vendor/github.com/docker/docker/pkg/tarsum/testdata/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/layer.tar b/vendor/github.com/docker/docker/pkg/tarsum/testdata/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/layer.tar deleted file mode 100644 index 880b3f2c..00000000 Binary files a/vendor/github.com/docker/docker/pkg/tarsum/testdata/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/layer.tar and /dev/null differ diff --git a/vendor/github.com/docker/docker/pkg/tarsum/testdata/collision/collision-0.tar b/vendor/github.com/docker/docker/pkg/tarsum/testdata/collision/collision-0.tar deleted file mode 100644 index 1c636b3b..00000000 Binary files a/vendor/github.com/docker/docker/pkg/tarsum/testdata/collision/collision-0.tar and /dev/null differ diff --git a/vendor/github.com/docker/docker/pkg/tarsum/testdata/collision/collision-1.tar b/vendor/github.com/docker/docker/pkg/tarsum/testdata/collision/collision-1.tar deleted file mode 100644 index b411be97..00000000 Binary files a/vendor/github.com/docker/docker/pkg/tarsum/testdata/collision/collision-1.tar and /dev/null differ diff --git a/vendor/github.com/docker/docker/pkg/tarsum/testdata/collision/collision-2.tar b/vendor/github.com/docker/docker/pkg/tarsum/testdata/collision/collision-2.tar deleted file mode 100644 index 7b5c04a9..00000000 Binary files a/vendor/github.com/docker/docker/pkg/tarsum/testdata/collision/collision-2.tar and /dev/null differ diff --git a/vendor/github.com/docker/docker/pkg/tarsum/testdata/collision/collision-3.tar b/vendor/github.com/docker/docker/pkg/tarsum/testdata/collision/collision-3.tar deleted file mode 100644 index f8c64586..00000000 Binary files a/vendor/github.com/docker/docker/pkg/tarsum/testdata/collision/collision-3.tar and /dev/null differ diff --git a/vendor/github.com/docker/docker/pkg/tarsum/testdata/xattr/json b/vendor/github.com/docker/docker/pkg/tarsum/testdata/xattr/json deleted file mode 100644 index 288441a9..00000000 --- a/vendor/github.com/docker/docker/pkg/tarsum/testdata/xattr/json +++ /dev/null @@ -1 +0,0 @@ -{"id":"4439c3c7f847954100b42b267e7e5529cac1d6934db082f65795c5ca2e594d93","parent":"73b164f4437db87e96e90083c73a6592f549646ae2ec00ed33c6b9b49a5c4470","created":"2014-05-16T17:19:44.091534414Z","container":"5f92fb06cc58f357f0cde41394e2bbbb664e663974b2ac1693ab07b7a306749b","container_config":{"Hostname":"9565c6517a0e","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"ExposedPorts":null,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["HOME=/","PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh","-c","setcap 'cap_setgid,cap_setuid+ep' ./file \u0026\u0026 getcap ./file"],"Image":"73b164f4437db87e96e90083c73a6592f549646ae2ec00ed33c6b9b49a5c4470","Volumes":null,"WorkingDir":"","Entrypoint":null,"NetworkDisabled":false,"OnBuild":[]},"docker_version":"0.11.1-dev","config":{"Hostname":"9565c6517a0e","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"ExposedPorts":null,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["HOME=/","PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":null,"Image":"73b164f4437db87e96e90083c73a6592f549646ae2ec00ed33c6b9b49a5c4470","Volumes":null,"WorkingDir":"","Entrypoint":null,"NetworkDisabled":false,"OnBuild":[]},"architecture":"amd64","os":"linux","Size":0} \ No newline at end of file diff --git a/vendor/github.com/docker/docker/pkg/tarsum/testdata/xattr/layer.tar b/vendor/github.com/docker/docker/pkg/tarsum/testdata/xattr/layer.tar deleted file mode 100644 index 819351d4..00000000 Binary files a/vendor/github.com/docker/docker/pkg/tarsum/testdata/xattr/layer.tar and /dev/null differ diff --git a/vendor/github.com/docker/docker/pkg/term/windows/ansi_reader.go b/vendor/github.com/docker/docker/pkg/term/windows/ansi_reader.go deleted file mode 100644 index bb47e120..00000000 --- a/vendor/github.com/docker/docker/pkg/term/windows/ansi_reader.go +++ /dev/null @@ -1,256 +0,0 @@ -// +build windows - -package windows - -import ( - "bytes" - "errors" - "fmt" - "os" - "strings" - "unsafe" - - ansiterm "github.com/Azure/go-ansiterm" - "github.com/Azure/go-ansiterm/winterm" -) - -// ansiReader wraps a standard input file (e.g., os.Stdin) providing ANSI sequence translation. -type ansiReader struct { - file *os.File - fd uintptr - buffer []byte - cbBuffer int - command []byte - // TODO(azlinux): Remove this and hard-code the string -- it is not going to change - escapeSequence []byte -} - -func newAnsiReader(nFile int) *ansiReader { - file, fd := winterm.GetStdFile(nFile) - return &ansiReader{ - file: file, - fd: fd, - command: make([]byte, 0, ansiterm.ANSI_MAX_CMD_LENGTH), - escapeSequence: []byte(ansiterm.KEY_ESC_CSI), - buffer: make([]byte, 0), - } -} - -// Close closes the wrapped file. -func (ar *ansiReader) Close() (err error) { - return ar.file.Close() -} - -// Fd returns the file descriptor of the wrapped file. -func (ar *ansiReader) Fd() uintptr { - return ar.fd -} - -// Read reads up to len(p) bytes of translated input events into p. -func (ar *ansiReader) Read(p []byte) (int, error) { - if len(p) == 0 { - return 0, nil - } - - // Previously read bytes exist, read as much as we can and return - if len(ar.buffer) > 0 { - logger.Debugf("Reading previously cached bytes") - - originalLength := len(ar.buffer) - copiedLength := copy(p, ar.buffer) - - if copiedLength == originalLength { - ar.buffer = make([]byte, 0, len(p)) - } else { - ar.buffer = ar.buffer[copiedLength:] - } - - logger.Debugf("Read from cache p[%d]: % x", copiedLength, p) - return copiedLength, nil - } - - // Read and translate key events - events, err := readInputEvents(ar.fd, len(p)) - if err != nil { - return 0, err - } else if len(events) == 0 { - logger.Debug("No input events detected") - return 0, nil - } - - keyBytes := translateKeyEvents(events, ar.escapeSequence) - - // Save excess bytes and right-size keyBytes - if len(keyBytes) > len(p) { - logger.Debugf("Received %d keyBytes, only room for %d bytes", len(keyBytes), len(p)) - ar.buffer = keyBytes[len(p):] - keyBytes = keyBytes[:len(p)] - } else if len(keyBytes) == 0 { - logger.Debug("No key bytes returned from the translator") - return 0, nil - } - - copiedLength := copy(p, keyBytes) - if copiedLength != len(keyBytes) { - return 0, errors.New("Unexpected copy length encountered.") - } - - logger.Debugf("Read p[%d]: % x", copiedLength, p) - logger.Debugf("Read keyBytes[%d]: % x", copiedLength, keyBytes) - return copiedLength, nil -} - -// readInputEvents polls until at least one event is available. -func readInputEvents(fd uintptr, maxBytes int) ([]winterm.INPUT_RECORD, error) { - // Determine the maximum number of records to retrieve - // -- Cast around the type system to obtain the size of a single INPUT_RECORD. - // unsafe.Sizeof requires an expression vs. a type-reference; the casting - // tricks the type system into believing it has such an expression. - recordSize := int(unsafe.Sizeof(*((*winterm.INPUT_RECORD)(unsafe.Pointer(&maxBytes))))) - countRecords := maxBytes / recordSize - if countRecords > ansiterm.MAX_INPUT_EVENTS { - countRecords = ansiterm.MAX_INPUT_EVENTS - } - logger.Debugf("[windows] readInputEvents: Reading %v records (buffer size %v, record size %v)", countRecords, maxBytes, recordSize) - - // Wait for and read input events - events := make([]winterm.INPUT_RECORD, countRecords) - nEvents := uint32(0) - eventsExist, err := winterm.WaitForSingleObject(fd, winterm.WAIT_INFINITE) - if err != nil { - return nil, err - } - - if eventsExist { - err = winterm.ReadConsoleInput(fd, events, &nEvents) - if err != nil { - return nil, err - } - } - - // Return a slice restricted to the number of returned records - logger.Debugf("[windows] readInputEvents: Read %v events", nEvents) - return events[:nEvents], nil -} - -// KeyEvent Translation Helpers - -var arrowKeyMapPrefix = map[winterm.WORD]string{ - winterm.VK_UP: "%s%sA", - winterm.VK_DOWN: "%s%sB", - winterm.VK_RIGHT: "%s%sC", - winterm.VK_LEFT: "%s%sD", -} - -var keyMapPrefix = map[winterm.WORD]string{ - winterm.VK_UP: "\x1B[%sA", - winterm.VK_DOWN: "\x1B[%sB", - winterm.VK_RIGHT: "\x1B[%sC", - winterm.VK_LEFT: "\x1B[%sD", - winterm.VK_HOME: "\x1B[1%s~", // showkey shows ^[[1 - winterm.VK_END: "\x1B[4%s~", // showkey shows ^[[4 - winterm.VK_INSERT: "\x1B[2%s~", - winterm.VK_DELETE: "\x1B[3%s~", - winterm.VK_PRIOR: "\x1B[5%s~", - winterm.VK_NEXT: "\x1B[6%s~", - winterm.VK_F1: "", - winterm.VK_F2: "", - winterm.VK_F3: "\x1B[13%s~", - winterm.VK_F4: "\x1B[14%s~", - winterm.VK_F5: "\x1B[15%s~", - winterm.VK_F6: "\x1B[17%s~", - winterm.VK_F7: "\x1B[18%s~", - winterm.VK_F8: "\x1B[19%s~", - winterm.VK_F9: "\x1B[20%s~", - winterm.VK_F10: "\x1B[21%s~", - winterm.VK_F11: "\x1B[23%s~", - winterm.VK_F12: "\x1B[24%s~", -} - -// translateKeyEvents converts the input events into the appropriate ANSI string. -func translateKeyEvents(events []winterm.INPUT_RECORD, escapeSequence []byte) []byte { - var buffer bytes.Buffer - for _, event := range events { - if event.EventType == winterm.KEY_EVENT && event.KeyEvent.KeyDown != 0 { - buffer.WriteString(keyToString(&event.KeyEvent, escapeSequence)) - } - } - - return buffer.Bytes() -} - -// keyToString maps the given input event record to the corresponding string. -func keyToString(keyEvent *winterm.KEY_EVENT_RECORD, escapeSequence []byte) string { - if keyEvent.UnicodeChar == 0 { - return formatVirtualKey(keyEvent.VirtualKeyCode, keyEvent.ControlKeyState, escapeSequence) - } - - _, alt, control := getControlKeys(keyEvent.ControlKeyState) - if control { - // TODO(azlinux): Implement following control sequences - // -D Signals the end of input from the keyboard; also exits current shell. - // -H Deletes the first character to the left of the cursor. Also called the ERASE key. - // -Q Restarts printing after it has been stopped with -s. - // -S Suspends printing on the screen (does not stop the program). - // -U Deletes all characters on the current line. Also called the KILL key. - // -E Quits current command and creates a core - - } - - // +Key generates ESC N Key - if !control && alt { - return ansiterm.KEY_ESC_N + strings.ToLower(string(keyEvent.UnicodeChar)) - } - - return string(keyEvent.UnicodeChar) -} - -// formatVirtualKey converts a virtual key (e.g., up arrow) into the appropriate ANSI string. -func formatVirtualKey(key winterm.WORD, controlState winterm.DWORD, escapeSequence []byte) string { - shift, alt, control := getControlKeys(controlState) - modifier := getControlKeysModifier(shift, alt, control) - - if format, ok := arrowKeyMapPrefix[key]; ok { - return fmt.Sprintf(format, escapeSequence, modifier) - } - - if format, ok := keyMapPrefix[key]; ok { - return fmt.Sprintf(format, modifier) - } - - return "" -} - -// getControlKeys extracts the shift, alt, and ctrl key states. -func getControlKeys(controlState winterm.DWORD) (shift, alt, control bool) { - shift = 0 != (controlState & winterm.SHIFT_PRESSED) - alt = 0 != (controlState & (winterm.LEFT_ALT_PRESSED | winterm.RIGHT_ALT_PRESSED)) - control = 0 != (controlState & (winterm.LEFT_CTRL_PRESSED | winterm.RIGHT_CTRL_PRESSED)) - return shift, alt, control -} - -// getControlKeysModifier returns the ANSI modifier for the given combination of control keys. -func getControlKeysModifier(shift, alt, control bool) string { - if shift && alt && control { - return ansiterm.KEY_CONTROL_PARAM_8 - } - if alt && control { - return ansiterm.KEY_CONTROL_PARAM_7 - } - if shift && control { - return ansiterm.KEY_CONTROL_PARAM_6 - } - if control { - return ansiterm.KEY_CONTROL_PARAM_5 - } - if shift && alt { - return ansiterm.KEY_CONTROL_PARAM_4 - } - if alt { - return ansiterm.KEY_CONTROL_PARAM_3 - } - if shift { - return ansiterm.KEY_CONTROL_PARAM_2 - } - return "" -} diff --git a/vendor/github.com/docker/docker/pkg/term/windows/ansi_writer.go b/vendor/github.com/docker/docker/pkg/term/windows/ansi_writer.go deleted file mode 100644 index 9f3232c0..00000000 --- a/vendor/github.com/docker/docker/pkg/term/windows/ansi_writer.go +++ /dev/null @@ -1,76 +0,0 @@ -// +build windows - -package windows - -import ( - "io/ioutil" - "os" - - ansiterm "github.com/Azure/go-ansiterm" - "github.com/Azure/go-ansiterm/winterm" - "github.com/Sirupsen/logrus" -) - -var logger *logrus.Logger - -// ansiWriter wraps a standard output file (e.g., os.Stdout) providing ANSI sequence translation. -type ansiWriter struct { - file *os.File - fd uintptr - infoReset *winterm.CONSOLE_SCREEN_BUFFER_INFO - command []byte - escapeSequence []byte - inAnsiSequence bool - parser *ansiterm.AnsiParser -} - -func newAnsiWriter(nFile int) *ansiWriter { - logFile := ioutil.Discard - - if isDebugEnv := os.Getenv(ansiterm.LogEnv); isDebugEnv == "1" { - logFile, _ = os.Create("ansiReaderWriter.log") - } - - logger = &logrus.Logger{ - Out: logFile, - Formatter: new(logrus.TextFormatter), - Level: logrus.DebugLevel, - } - - file, fd := winterm.GetStdFile(nFile) - info, err := winterm.GetConsoleScreenBufferInfo(fd) - if err != nil { - return nil - } - - parser := ansiterm.CreateParser("Ground", winterm.CreateWinEventHandler(fd, file)) - logger.Infof("newAnsiWriter: parser %p", parser) - - aw := &ansiWriter{ - file: file, - fd: fd, - infoReset: info, - command: make([]byte, 0, ansiterm.ANSI_MAX_CMD_LENGTH), - escapeSequence: []byte(ansiterm.KEY_ESC_CSI), - parser: parser, - } - - logger.Infof("newAnsiWriter: aw.parser %p", aw.parser) - logger.Infof("newAnsiWriter: %v", aw) - return aw -} - -func (aw *ansiWriter) Fd() uintptr { - return aw.fd -} - -// Write writes len(p) bytes from p to the underlying data stream. -func (aw *ansiWriter) Write(p []byte) (total int, err error) { - if len(p) == 0 { - return 0, nil - } - - logger.Infof("Write: % x", p) - logger.Infof("Write: %s", string(p)) - return aw.parser.Parse(p) -} diff --git a/vendor/github.com/docker/docker/pkg/term/windows/console.go b/vendor/github.com/docker/docker/pkg/term/windows/console.go deleted file mode 100644 index 3711d988..00000000 --- a/vendor/github.com/docker/docker/pkg/term/windows/console.go +++ /dev/null @@ -1,61 +0,0 @@ -// +build windows - -package windows - -import ( - "io" - "os" - "syscall" - - "github.com/Azure/go-ansiterm/winterm" -) - -// ConsoleStreams returns a wrapped version for each standard stream referencing a console, -// that handles ANSI character sequences. -func ConsoleStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { - if IsConsole(os.Stdin.Fd()) { - stdIn = newAnsiReader(syscall.STD_INPUT_HANDLE) - } else { - stdIn = os.Stdin - } - - if IsConsole(os.Stdout.Fd()) { - stdOut = newAnsiWriter(syscall.STD_OUTPUT_HANDLE) - } else { - stdOut = os.Stdout - } - - if IsConsole(os.Stderr.Fd()) { - stdErr = newAnsiWriter(syscall.STD_ERROR_HANDLE) - } else { - stdErr = os.Stderr - } - - return stdIn, stdOut, stdErr -} - -// GetHandleInfo returns file descriptor and bool indicating whether the file is a console. -func GetHandleInfo(in interface{}) (uintptr, bool) { - switch t := in.(type) { - case *ansiReader: - return t.Fd(), true - case *ansiWriter: - return t.Fd(), true - } - - var inFd uintptr - var isTerminal bool - - if file, ok := in.(*os.File); ok { - inFd = file.Fd() - isTerminal = IsConsole(inFd) - } - return inFd, isTerminal -} - -// IsConsole returns true if the given file descriptor is a Windows Console. -// The code assumes that GetConsoleMode will return an error for file descriptors that are not a console. -func IsConsole(fd uintptr) bool { - _, e := winterm.GetConsoleMode(fd) - return e == nil -} diff --git a/vendor/github.com/docker/docker/pkg/term/windows/windows.go b/vendor/github.com/docker/docker/pkg/term/windows/windows.go deleted file mode 100644 index bf4c7b50..00000000 --- a/vendor/github.com/docker/docker/pkg/term/windows/windows.go +++ /dev/null @@ -1,5 +0,0 @@ -// These files implement ANSI-aware input and output streams for use by the Docker Windows client. -// When asked for the set of standard streams (e.g., stdin, stdout, stderr), the code will create -// and return pseudo-streams that convert ANSI sequences to / from Windows Console API calls. - -package windows diff --git a/vendor/github.com/docker/docker/pkg/term/windows/windows_test.go b/vendor/github.com/docker/docker/pkg/term/windows/windows_test.go deleted file mode 100644 index 52aeab54..00000000 --- a/vendor/github.com/docker/docker/pkg/term/windows/windows_test.go +++ /dev/null @@ -1,3 +0,0 @@ -// This file is necessary to pass the Docker tests. - -package windows diff --git a/vendor/github.com/docker/docker/runconfig/fixtures/unix/container_config_1_14.json b/vendor/github.com/docker/docker/runconfig/fixtures/unix/container_config_1_14.json deleted file mode 100644 index b08334c0..00000000 --- a/vendor/github.com/docker/docker/runconfig/fixtures/unix/container_config_1_14.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "Hostname":"", - "Domainname": "", - "User":"", - "Memory": 1000, - "MemorySwap":0, - "CpuShares": 512, - "Cpuset": "0,1", - "AttachStdin":false, - "AttachStdout":true, - "AttachStderr":true, - "PortSpecs":null, - "Tty":false, - "OpenStdin":false, - "StdinOnce":false, - "Env":null, - "Cmd":[ - "bash" - ], - "Image":"ubuntu", - "Volumes":{ - "/tmp": {} - }, - "WorkingDir":"", - "NetworkDisabled": false, - "ExposedPorts":{ - "22/tcp": {} - }, - "RestartPolicy": { "Name": "always" } -} diff --git a/vendor/github.com/docker/docker/runconfig/fixtures/unix/container_config_1_17.json b/vendor/github.com/docker/docker/runconfig/fixtures/unix/container_config_1_17.json deleted file mode 100644 index 0d780877..00000000 --- a/vendor/github.com/docker/docker/runconfig/fixtures/unix/container_config_1_17.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "Hostname": "", - "Domainname": "", - "User": "", - "Memory": 1000, - "MemorySwap": 0, - "CpuShares": 512, - "Cpuset": "0,1", - "AttachStdin": false, - "AttachStdout": true, - "AttachStderr": true, - "Tty": false, - "OpenStdin": false, - "StdinOnce": false, - "Env": null, - "Cmd": [ - "date" - ], - "Entrypoint": "bash", - "Image": "ubuntu", - "Volumes": { - "/tmp": {} - }, - "WorkingDir": "", - "NetworkDisabled": false, - "MacAddress": "12:34:56:78:9a:bc", - "ExposedPorts": { - "22/tcp": {} - }, - "SecurityOpt": [""], - "HostConfig": { - "Binds": ["/tmp:/tmp"], - "Links": ["redis3:redis"], - "LxcConf": {"lxc.utsname":"docker"}, - "PortBindings": { "22/tcp": [{ "HostPort": "11022" }] }, - "PublishAllPorts": false, - "Privileged": false, - "ReadonlyRootfs": false, - "Dns": ["8.8.8.8"], - "DnsSearch": [""], - "DnsOptions": [""], - "ExtraHosts": null, - "VolumesFrom": ["parent", "other:ro"], - "CapAdd": ["NET_ADMIN"], - "CapDrop": ["MKNOD"], - "RestartPolicy": { "Name": "", "MaximumRetryCount": 0 }, - "NetworkMode": "bridge", - "Devices": [] - } -} diff --git a/vendor/github.com/docker/docker/runconfig/fixtures/unix/container_config_1_19.json b/vendor/github.com/docker/docker/runconfig/fixtures/unix/container_config_1_19.json deleted file mode 100644 index de49cf32..00000000 --- a/vendor/github.com/docker/docker/runconfig/fixtures/unix/container_config_1_19.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "Hostname": "", - "Domainname": "", - "User": "", - "AttachStdin": false, - "AttachStdout": true, - "AttachStderr": true, - "Tty": false, - "OpenStdin": false, - "StdinOnce": false, - "Env": null, - "Cmd": [ - "date" - ], - "Entrypoint": "bash", - "Image": "ubuntu", - "Labels": { - "com.example.vendor": "Acme", - "com.example.license": "GPL", - "com.example.version": "1.0" - }, - "Volumes": { - "/tmp": {} - }, - "WorkingDir": "", - "NetworkDisabled": false, - "MacAddress": "12:34:56:78:9a:bc", - "ExposedPorts": { - "22/tcp": {} - }, - "HostConfig": { - "Binds": ["/tmp:/tmp"], - "Links": ["redis3:redis"], - "LxcConf": {"lxc.utsname":"docker"}, - "Memory": 1000, - "MemorySwap": 0, - "CpuShares": 512, - "CpusetCpus": "0,1", - "PortBindings": { "22/tcp": [{ "HostPort": "11022" }] }, - "PublishAllPorts": false, - "Privileged": false, - "ReadonlyRootfs": false, - "Dns": ["8.8.8.8"], - "DnsSearch": [""], - "DnsOptions": [""], - "ExtraHosts": null, - "VolumesFrom": ["parent", "other:ro"], - "CapAdd": ["NET_ADMIN"], - "CapDrop": ["MKNOD"], - "RestartPolicy": { "Name": "", "MaximumRetryCount": 0 }, - "NetworkMode": "bridge", - "Devices": [], - "Ulimits": [{}], - "LogConfig": { "Type": "json-file", "Config": {} }, - "SecurityOpt": [""], - "CgroupParent": "" - } -} diff --git a/vendor/github.com/docker/docker/runconfig/fixtures/unix/container_hostconfig_1_14.json b/vendor/github.com/docker/docker/runconfig/fixtures/unix/container_hostconfig_1_14.json deleted file mode 100644 index c72ac91c..00000000 --- a/vendor/github.com/docker/docker/runconfig/fixtures/unix/container_hostconfig_1_14.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "Binds": ["/tmp:/tmp"], - "ContainerIDFile": "", - "LxcConf": [], - "Privileged": false, - "PortBindings": { - "80/tcp": [ - { - "HostIp": "0.0.0.0", - "HostPort": "49153" - } - ] - }, - "Links": ["/name:alias"], - "PublishAllPorts": false, - "CapAdd": ["NET_ADMIN"], - "CapDrop": ["MKNOD"] -} diff --git a/vendor/github.com/docker/docker/runconfig/fixtures/unix/container_hostconfig_1_19.json b/vendor/github.com/docker/docker/runconfig/fixtures/unix/container_hostconfig_1_19.json deleted file mode 100644 index 5ca8aa7e..00000000 --- a/vendor/github.com/docker/docker/runconfig/fixtures/unix/container_hostconfig_1_19.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "Binds": ["/tmp:/tmp"], - "Links": ["redis3:redis"], - "LxcConf": {"lxc.utsname":"docker"}, - "Memory": 0, - "MemorySwap": 0, - "CpuShares": 512, - "CpuPeriod": 100000, - "CpusetCpus": "0,1", - "CpusetMems": "0,1", - "BlkioWeight": 300, - "OomKillDisable": false, - "PortBindings": { "22/tcp": [{ "HostPort": "11022" }] }, - "PublishAllPorts": false, - "Privileged": false, - "ReadonlyRootfs": false, - "Dns": ["8.8.8.8"], - "DnsSearch": [""], - "ExtraHosts": null, - "VolumesFrom": ["parent", "other:ro"], - "CapAdd": ["NET_ADMIN"], - "CapDrop": ["MKNOD"], - "RestartPolicy": { "Name": "", "MaximumRetryCount": 0 }, - "NetworkMode": "bridge", - "Devices": [], - "Ulimits": [{}], - "LogConfig": { "Type": "json-file", "Config": {} }, - "SecurityOpt": [""], - "CgroupParent": "" -} diff --git a/vendor/github.com/docker/docker/runconfig/fixtures/valid.env b/vendor/github.com/docker/docker/runconfig/fixtures/valid.env deleted file mode 100644 index 3afbdc81..00000000 --- a/vendor/github.com/docker/docker/runconfig/fixtures/valid.env +++ /dev/null @@ -1 +0,0 @@ -ENV1=value1 diff --git a/vendor/github.com/docker/docker/runconfig/fixtures/valid.label b/vendor/github.com/docker/docker/runconfig/fixtures/valid.label deleted file mode 100644 index b4208bdf..00000000 --- a/vendor/github.com/docker/docker/runconfig/fixtures/valid.label +++ /dev/null @@ -1 +0,0 @@ -LABEL1=value1 diff --git a/vendor/github.com/docker/docker/runconfig/fixtures/windows/container_config_1_19.json b/vendor/github.com/docker/docker/runconfig/fixtures/windows/container_config_1_19.json deleted file mode 100644 index 724320c7..00000000 --- a/vendor/github.com/docker/docker/runconfig/fixtures/windows/container_config_1_19.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "Hostname": "", - "Domainname": "", - "User": "", - "AttachStdin": false, - "AttachStdout": true, - "AttachStderr": true, - "Tty": false, - "OpenStdin": false, - "StdinOnce": false, - "Env": null, - "Cmd": [ - "date" - ], - "Entrypoint": "cmd", - "Image": "windows", - "Labels": { - "com.example.vendor": "Acme", - "com.example.license": "GPL", - "com.example.version": "1.0" - }, - "Volumes": { - "c:/windows": {} - }, - "WorkingDir": "", - "NetworkDisabled": false, - "MacAddress": "12:34:56:78:9a:bc", - "ExposedPorts": { - "22/tcp": {} - }, - "HostConfig": { - "Binds": ["c:/windows:d:/tmp"], - "Links": ["redis3:redis"], - "LxcConf": {"lxc.utsname":"docker"}, - "Memory": 1000, - "MemorySwap": 0, - "CpuShares": 512, - "CpusetCpus": "0,1", - "PortBindings": { "22/tcp": [{ "HostPort": "11022" }] }, - "PublishAllPorts": false, - "Privileged": false, - "ReadonlyRootfs": false, - "Dns": ["8.8.8.8"], - "DnsSearch": [""], - "DnsOptions": [""], - "ExtraHosts": null, - "VolumesFrom": ["parent", "other:ro"], - "CapAdd": ["NET_ADMIN"], - "CapDrop": ["MKNOD"], - "RestartPolicy": { "Name": "", "MaximumRetryCount": 0 }, - "NetworkMode": "default", - "Devices": [], - "Ulimits": [{}], - "LogConfig": { "Type": "json-file", "Config": {} }, - "SecurityOpt": [""], - "CgroupParent": "" - } -} diff --git a/vendor/github.com/docker/docker/volume/drivers/adapter.go b/vendor/github.com/docker/docker/volume/drivers/adapter.go deleted file mode 100644 index a5db6991..00000000 --- a/vendor/github.com/docker/docker/volume/drivers/adapter.go +++ /dev/null @@ -1,65 +0,0 @@ -package volumedrivers - -import "github.com/docker/docker/volume" - -type volumeDriverAdapter struct { - name string - proxy *volumeDriverProxy -} - -func (a *volumeDriverAdapter) Name() string { - return a.name -} - -func (a *volumeDriverAdapter) Create(name string, opts map[string]string) (volume.Volume, error) { - err := a.proxy.Create(name, opts) - if err != nil { - return nil, err - } - return &volumeAdapter{ - proxy: a.proxy, - name: name, - driverName: a.name}, nil -} - -func (a *volumeDriverAdapter) Remove(v volume.Volume) error { - return a.proxy.Remove(v.Name()) -} - -type volumeAdapter struct { - proxy *volumeDriverProxy - name string - driverName string - eMount string // ephemeral host volume path -} - -type proxyVolume struct { - Name string - Mountpoint string -} - -func (a *volumeAdapter) Name() string { - return a.name -} - -func (a *volumeAdapter) DriverName() string { - return a.driverName -} - -func (a *volumeAdapter) Path() string { - if len(a.eMount) > 0 { - return a.eMount - } - m, _ := a.proxy.Path(a.name) - return m -} - -func (a *volumeAdapter) Mount() (string, error) { - var err error - a.eMount, err = a.proxy.Mount(a.name) - return a.eMount, err -} - -func (a *volumeAdapter) Unmount() error { - return a.proxy.Unmount(a.name) -} diff --git a/vendor/github.com/docker/docker/volume/drivers/extpoint.go b/vendor/github.com/docker/docker/volume/drivers/extpoint.go deleted file mode 100644 index 3927b29c..00000000 --- a/vendor/github.com/docker/docker/volume/drivers/extpoint.go +++ /dev/null @@ -1,108 +0,0 @@ -//go:generate pluginrpc-gen -i $GOFILE -o proxy.go -type volumeDriver -name VolumeDriver - -package volumedrivers - -import ( - "fmt" - "sync" - - "github.com/docker/docker/pkg/plugins" - "github.com/docker/docker/volume" -) - -// currently created by hand. generation tool would generate this like: -// $ extpoint-gen Driver > volume/extpoint.go - -var drivers = &driverExtpoint{extensions: make(map[string]volume.Driver)} - -// NewVolumeDriver returns a driver has the given name mapped on the given client. -func NewVolumeDriver(name string, c client) volume.Driver { - proxy := &volumeDriverProxy{c} - return &volumeDriverAdapter{name, proxy} -} - -type opts map[string]string - -// volumeDriver defines the available functions that volume plugins must implement. -// This interface is only defined to generate the proxy objects. -// It's not intended to be public or reused. -type volumeDriver interface { - // Create a volume with the given name - Create(name string, opts opts) (err error) - // Remove the volume with the given name - Remove(name string) (err error) - // Get the mountpoint of the given volume - Path(name string) (mountpoint string, err error) - // Mount the given volume and return the mountpoint - Mount(name string) (mountpoint string, err error) - // Unmount the given volume - Unmount(name string) (err error) -} - -type driverExtpoint struct { - extensions map[string]volume.Driver - sync.Mutex -} - -// Register associates the given driver to the given name, checking if -// the name is already associated -func Register(extension volume.Driver, name string) bool { - drivers.Lock() - defer drivers.Unlock() - if name == "" { - return false - } - _, exists := drivers.extensions[name] - if exists { - return false - } - drivers.extensions[name] = extension - return true -} - -// Unregister dissociates the name from it's driver, if the association exists. -func Unregister(name string) bool { - drivers.Lock() - defer drivers.Unlock() - _, exists := drivers.extensions[name] - if !exists { - return false - } - delete(drivers.extensions, name) - return true -} - -// Lookup returns the driver associated with the given name. If a -// driver with the given name has not been registered it checks if -// there is a VolumeDriver plugin available with the given name. -func Lookup(name string) (volume.Driver, error) { - drivers.Lock() - ext, ok := drivers.extensions[name] - drivers.Unlock() - if ok { - return ext, nil - } - pl, err := plugins.Get(name, "VolumeDriver") - if err != nil { - return nil, fmt.Errorf("Error looking up volume plugin %s: %v", name, err) - } - - drivers.Lock() - defer drivers.Unlock() - if ext, ok := drivers.extensions[name]; ok { - return ext, nil - } - - d := NewVolumeDriver(name, pl.Client) - drivers.extensions[name] = d - return d, nil -} - -// GetDriver returns a volume driver by it's name. -// If the driver is empty, it looks for the local driver. -func GetDriver(name string) (volume.Driver, error) { - if name == "" { - name = volume.DefaultDriverName - } - return Lookup(name) -} diff --git a/vendor/github.com/docker/docker/volume/drivers/extpoint_test.go b/vendor/github.com/docker/docker/volume/drivers/extpoint_test.go deleted file mode 100644 index 8ab60c95..00000000 --- a/vendor/github.com/docker/docker/volume/drivers/extpoint_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package volumedrivers - -import ( - "testing" - - "github.com/docker/docker/volume/testutils" -) - -func TestGetDriver(t *testing.T) { - _, err := GetDriver("missing") - if err == nil { - t.Fatal("Expected error, was nil") - } - Register(volumetestutils.FakeDriver{}, "fake") - d, err := GetDriver("fake") - if err != nil { - t.Fatal(err) - } - if d.Name() != "fake" { - t.Fatalf("Expected fake driver, got %s\n", d.Name()) - } -} diff --git a/vendor/github.com/docker/docker/volume/drivers/proxy.go b/vendor/github.com/docker/docker/volume/drivers/proxy.go deleted file mode 100644 index f2e2f044..00000000 --- a/vendor/github.com/docker/docker/volume/drivers/proxy.go +++ /dev/null @@ -1,151 +0,0 @@ -// generated code - DO NOT EDIT - -package volumedrivers - -import "errors" - -type client interface { - Call(string, interface{}, interface{}) error -} - -type volumeDriverProxy struct { - client -} - -type volumeDriverProxyCreateRequest struct { - Name string - Opts opts -} - -type volumeDriverProxyCreateResponse struct { - Err string -} - -func (pp *volumeDriverProxy) Create(name string, opts opts) (err error) { - var ( - req volumeDriverProxyCreateRequest - ret volumeDriverProxyCreateResponse - ) - - req.Name = name - req.Opts = opts - if err = pp.Call("VolumeDriver.Create", req, &ret); err != nil { - return - } - - if ret.Err != "" { - err = errors.New(ret.Err) - } - - return -} - -type volumeDriverProxyRemoveRequest struct { - Name string -} - -type volumeDriverProxyRemoveResponse struct { - Err string -} - -func (pp *volumeDriverProxy) Remove(name string) (err error) { - var ( - req volumeDriverProxyRemoveRequest - ret volumeDriverProxyRemoveResponse - ) - - req.Name = name - if err = pp.Call("VolumeDriver.Remove", req, &ret); err != nil { - return - } - - if ret.Err != "" { - err = errors.New(ret.Err) - } - - return -} - -type volumeDriverProxyPathRequest struct { - Name string -} - -type volumeDriverProxyPathResponse struct { - Mountpoint string - Err string -} - -func (pp *volumeDriverProxy) Path(name string) (mountpoint string, err error) { - var ( - req volumeDriverProxyPathRequest - ret volumeDriverProxyPathResponse - ) - - req.Name = name - if err = pp.Call("VolumeDriver.Path", req, &ret); err != nil { - return - } - - mountpoint = ret.Mountpoint - - if ret.Err != "" { - err = errors.New(ret.Err) - } - - return -} - -type volumeDriverProxyMountRequest struct { - Name string -} - -type volumeDriverProxyMountResponse struct { - Mountpoint string - Err string -} - -func (pp *volumeDriverProxy) Mount(name string) (mountpoint string, err error) { - var ( - req volumeDriverProxyMountRequest - ret volumeDriverProxyMountResponse - ) - - req.Name = name - if err = pp.Call("VolumeDriver.Mount", req, &ret); err != nil { - return - } - - mountpoint = ret.Mountpoint - - if ret.Err != "" { - err = errors.New(ret.Err) - } - - return -} - -type volumeDriverProxyUnmountRequest struct { - Name string -} - -type volumeDriverProxyUnmountResponse struct { - Err string -} - -func (pp *volumeDriverProxy) Unmount(name string) (err error) { - var ( - req volumeDriverProxyUnmountRequest - ret volumeDriverProxyUnmountResponse - ) - - req.Name = name - if err = pp.Call("VolumeDriver.Unmount", req, &ret); err != nil { - return - } - - if ret.Err != "" { - err = errors.New(ret.Err) - } - - return -} diff --git a/vendor/github.com/docker/docker/volume/drivers/proxy_test.go b/vendor/github.com/docker/docker/volume/drivers/proxy_test.go deleted file mode 100644 index aa1d67e3..00000000 --- a/vendor/github.com/docker/docker/volume/drivers/proxy_test.go +++ /dev/null @@ -1,96 +0,0 @@ -package volumedrivers - -import ( - "fmt" - "net/http" - "net/http/httptest" - "net/url" - "strings" - "testing" - - "github.com/docker/docker/pkg/plugins" - "github.com/docker/docker/pkg/tlsconfig" -) - -func TestVolumeRequestError(t *testing.T) { - mux := http.NewServeMux() - server := httptest.NewServer(mux) - defer server.Close() - - mux.HandleFunc("/VolumeDriver.Create", func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") - fmt.Fprintln(w, `{"Err": "Cannot create volume"}`) - }) - - mux.HandleFunc("/VolumeDriver.Remove", func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") - fmt.Fprintln(w, `{"Err": "Cannot remove volume"}`) - }) - - mux.HandleFunc("/VolumeDriver.Mount", func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") - fmt.Fprintln(w, `{"Err": "Cannot mount volume"}`) - }) - - mux.HandleFunc("/VolumeDriver.Unmount", func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") - fmt.Fprintln(w, `{"Err": "Cannot unmount volume"}`) - }) - - mux.HandleFunc("/VolumeDriver.Path", func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") - fmt.Fprintln(w, `{"Err": "Unknown volume"}`) - }) - - u, _ := url.Parse(server.URL) - client, err := plugins.NewClient("tcp://"+u.Host, tlsconfig.Options{InsecureSkipVerify: true}) - if err != nil { - t.Fatal(err) - } - - driver := volumeDriverProxy{client} - - if err = driver.Create("volume", nil); err == nil { - t.Fatal("Expected error, was nil") - } - - if !strings.Contains(err.Error(), "Cannot create volume") { - t.Fatalf("Unexpected error: %v\n", err) - } - - _, err = driver.Mount("volume") - if err == nil { - t.Fatal("Expected error, was nil") - } - - if !strings.Contains(err.Error(), "Cannot mount volume") { - t.Fatalf("Unexpected error: %v\n", err) - } - - err = driver.Unmount("volume") - if err == nil { - t.Fatal("Expected error, was nil") - } - - if !strings.Contains(err.Error(), "Cannot unmount volume") { - t.Fatalf("Unexpected error: %v\n", err) - } - - err = driver.Remove("volume") - if err == nil { - t.Fatal("Expected error, was nil") - } - - if !strings.Contains(err.Error(), "Cannot remove volume") { - t.Fatalf("Unexpected error: %v\n", err) - } - - _, err = driver.Path("volume") - if err == nil { - t.Fatal("Expected error, was nil") - } - - if !strings.Contains(err.Error(), "Unknown volume") { - t.Fatalf("Unexpected error: %v\n", err) - } -} diff --git a/vendor/github.com/docker/docker/volume/local/local.go b/vendor/github.com/docker/docker/volume/local/local.go deleted file mode 100644 index e0c3a644..00000000 --- a/vendor/github.com/docker/docker/volume/local/local.go +++ /dev/null @@ -1,232 +0,0 @@ -// Package local provides the default implementation for volumes. It -// is used to mount data volume containers and directories local to -// the host server. -package local - -import ( - "errors" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "sync" - - derr "github.com/docker/docker/errors" - "github.com/docker/docker/pkg/idtools" - "github.com/docker/docker/utils" - "github.com/docker/docker/volume" -) - -// VolumeDataPathName is the name of the directory where the volume data is stored. -// It uses a very distintive name to avoid collisions migrating data between -// Docker versions. -const ( - VolumeDataPathName = "_data" - volumesPathName = "volumes" -) - -var ( - // ErrNotFound is the typed error returned when the requested volume name can't be found - ErrNotFound = errors.New("volume not found") - // volumeNameRegex ensures the name asigned for the volume is valid. - // This name is used to create the bind directory, so we need to avoid characters that - // would make the path to escape the root directory. - volumeNameRegex = utils.RestrictedNamePattern -) - -// New instantiates a new Root instance with the provided scope. Scope -// is the base path that the Root instance uses to store its -// volumes. The base path is created here if it does not exist. -func New(scope string, rootUID, rootGID int) (*Root, error) { - rootDirectory := filepath.Join(scope, volumesPathName) - - if err := idtools.MkdirAllAs(rootDirectory, 0700, rootUID, rootGID); err != nil { - return nil, err - } - - r := &Root{ - scope: scope, - path: rootDirectory, - volumes: make(map[string]*localVolume), - rootUID: rootUID, - rootGID: rootGID, - } - - dirs, err := ioutil.ReadDir(rootDirectory) - if err != nil { - return nil, err - } - - for _, d := range dirs { - name := filepath.Base(d.Name()) - r.volumes[name] = &localVolume{ - driverName: r.Name(), - name: name, - path: r.DataPath(name), - } - } - - return r, nil -} - -// Root implements the Driver interface for the volume package and -// manages the creation/removal of volumes. It uses only standard vfs -// commands to create/remove dirs within its provided scope. -type Root struct { - m sync.Mutex - scope string - path string - volumes map[string]*localVolume - rootUID int - rootGID int -} - -// List lists all the volumes -func (r *Root) List() []volume.Volume { - var ls []volume.Volume - for _, v := range r.volumes { - ls = append(ls, v) - } - return ls -} - -// DataPath returns the constructed path of this volume. -func (r *Root) DataPath(volumeName string) string { - return filepath.Join(r.path, volumeName, VolumeDataPathName) -} - -// Name returns the name of Root, defined in the volume package in the DefaultDriverName constant. -func (r *Root) Name() string { - return volume.DefaultDriverName -} - -// Create creates a new volume.Volume with the provided name, creating -// the underlying directory tree required for this volume in the -// process. -func (r *Root) Create(name string, _ map[string]string) (volume.Volume, error) { - if err := r.validateName(name); err != nil { - return nil, err - } - - r.m.Lock() - defer r.m.Unlock() - - v, exists := r.volumes[name] - if exists { - return v, nil - } - - path := r.DataPath(name) - if err := idtools.MkdirAllAs(path, 0755, r.rootUID, r.rootGID); err != nil { - if os.IsExist(err) { - return nil, fmt.Errorf("volume already exists under %s", filepath.Dir(path)) - } - return nil, err - } - v = &localVolume{ - driverName: r.Name(), - name: name, - path: path, - } - r.volumes[name] = v - return v, nil -} - -// Remove removes the specified volume and all underlying data. If the -// given volume does not belong to this driver and an error is -// returned. The volume is reference counted, if all references are -// not released then the volume is not removed. -func (r *Root) Remove(v volume.Volume) error { - r.m.Lock() - defer r.m.Unlock() - - lv, ok := v.(*localVolume) - if !ok { - return errors.New("unknown volume type") - } - - realPath, err := filepath.EvalSymlinks(lv.path) - if err != nil { - if !os.IsNotExist(err) { - return err - } - realPath = filepath.Dir(lv.path) - } - - if !r.scopedPath(realPath) { - return fmt.Errorf("Unable to remove a directory of out the Docker root %s: %s", r.scope, realPath) - } - - if err := removePath(realPath); err != nil { - return err - } - - delete(r.volumes, lv.name) - return removePath(filepath.Dir(lv.path)) -} - -func removePath(path string) error { - if err := os.RemoveAll(path); err != nil { - if os.IsNotExist(err) { - return nil - } - return err - } - return nil -} - -// Get looks up the volume for the given name and returns it if found -func (r *Root) Get(name string) (volume.Volume, error) { - r.m.Lock() - v, exists := r.volumes[name] - r.m.Unlock() - if !exists { - return nil, ErrNotFound - } - return v, nil -} - -func (r *Root) validateName(name string) error { - if !volumeNameRegex.MatchString(name) { - return derr.ErrorCodeVolumeName.WithArgs(name, utils.RestrictedNameChars) - } - return nil -} - -// localVolume implements the Volume interface from the volume package and -// represents the volumes created by Root. -type localVolume struct { - m sync.Mutex - usedCount int - // unique name of the volume - name string - // path is the path on the host where the data lives - path string - // driverName is the name of the driver that created the volume. - driverName string -} - -// Name returns the name of the given Volume. -func (v *localVolume) Name() string { - return v.name -} - -// DriverName returns the driver that created the given Volume. -func (v *localVolume) DriverName() string { - return v.driverName -} - -// Path returns the data location. -func (v *localVolume) Path() string { - return v.path -} - -// Mount implements the localVolume interface, returning the data location. -func (v *localVolume) Mount() (string, error) { - return v.path, nil -} - -// Umount is for satisfying the localVolume interface and does not do anything in this driver. -func (v *localVolume) Unmount() error { - return nil -} diff --git a/vendor/github.com/docker/docker/volume/local/local_test.go b/vendor/github.com/docker/docker/volume/local/local_test.go deleted file mode 100644 index 2c5b800a..00000000 --- a/vendor/github.com/docker/docker/volume/local/local_test.go +++ /dev/null @@ -1,126 +0,0 @@ -package local - -import ( - "io/ioutil" - "os" - "testing" -) - -func TestRemove(t *testing.T) { - rootDir, err := ioutil.TempDir("", "local-volume-test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(rootDir) - - r, err := New(rootDir, 0, 0) - if err != nil { - t.Fatal(err) - } - - vol, err := r.Create("testing", nil) - if err != nil { - t.Fatal(err) - } - - if err := r.Remove(vol); err != nil { - t.Fatal(err) - } - - vol, err = r.Create("testing2", nil) - if err != nil { - t.Fatal(err) - } - if err := os.RemoveAll(vol.Path()); err != nil { - t.Fatal(err) - } - - if err := r.Remove(vol); err != nil { - t.Fatal(err) - } - - if _, err := os.Stat(vol.Path()); err != nil && !os.IsNotExist(err) { - t.Fatal("volume dir not removed") - } - - if len(r.List()) != 0 { - t.Fatal("expected there to be no volumes") - } -} - -func TestInitializeWithVolumes(t *testing.T) { - rootDir, err := ioutil.TempDir("", "local-volume-test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(rootDir) - - r, err := New(rootDir, 0, 0) - if err != nil { - t.Fatal(err) - } - - vol, err := r.Create("testing", nil) - if err != nil { - t.Fatal(err) - } - - r, err = New(rootDir, 0, 0) - if err != nil { - t.Fatal(err) - } - - v, err := r.Get(vol.Name()) - if err != nil { - t.Fatal(err) - } - - if v.Path() != vol.Path() { - t.Fatal("expected to re-initialize root with existing volumes") - } -} - -func TestCreate(t *testing.T) { - rootDir, err := ioutil.TempDir("", "local-volume-test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(rootDir) - - r, err := New(rootDir, 0, 0) - if err != nil { - t.Fatal(err) - } - - cases := map[string]bool{ - "name": true, - "name-with-dash": true, - "name_with_underscore": true, - "name/with/slash": false, - "name/with/../../slash": false, - "./name": false, - "../name": false, - "./": false, - "../": false, - "~": false, - ".": false, - "..": false, - "...": false, - } - - for name, success := range cases { - v, err := r.Create(name, nil) - if success { - if err != nil { - t.Fatal(err) - } - if v.Name() != name { - t.Fatalf("Expected volume with name %s, got %s", name, v.Name()) - } - } else { - if err == nil { - t.Fatalf("Expected error creating volume with name %s, got nil", name) - } - } - } -} diff --git a/vendor/github.com/docker/docker/volume/local/local_unix.go b/vendor/github.com/docker/docker/volume/local/local_unix.go deleted file mode 100644 index 60f0e765..00000000 --- a/vendor/github.com/docker/docker/volume/local/local_unix.go +++ /dev/null @@ -1,29 +0,0 @@ -// +build linux freebsd - -// Package local provides the default implementation for volumes. It -// is used to mount data volume containers and directories local to -// the host server. -package local - -import ( - "path/filepath" - "strings" -) - -var oldVfsDir = filepath.Join("vfs", "dir") - -// scopedPath verifies that the path where the volume is located -// is under Docker's root and the valid local paths. -func (r *Root) scopedPath(realPath string) bool { - // Volumes path for Docker version >= 1.7 - if strings.HasPrefix(realPath, filepath.Join(r.scope, volumesPathName)) && realPath != filepath.Join(r.scope, volumesPathName) { - return true - } - - // Volumes path for Docker version < 1.7 - if strings.HasPrefix(realPath, filepath.Join(r.scope, oldVfsDir)) { - return true - } - - return false -} diff --git a/vendor/github.com/docker/docker/volume/local/local_windows.go b/vendor/github.com/docker/docker/volume/local/local_windows.go deleted file mode 100644 index 38812aa2..00000000 --- a/vendor/github.com/docker/docker/volume/local/local_windows.go +++ /dev/null @@ -1,18 +0,0 @@ -// Package local provides the default implementation for volumes. It -// is used to mount data volume containers and directories local to -// the host server. -package local - -import ( - "path/filepath" - "strings" -) - -// scopedPath verifies that the path where the volume is located -// is under Docker's root and the valid local paths. -func (r *Root) scopedPath(realPath string) bool { - if strings.HasPrefix(realPath, filepath.Join(r.scope, volumesPathName)) && realPath != filepath.Join(r.scope, volumesPathName) { - return true - } - return false -} diff --git a/vendor/github.com/docker/docker/volume/store/store.go b/vendor/github.com/docker/docker/volume/store/store.go deleted file mode 100644 index 73ae79fb..00000000 --- a/vendor/github.com/docker/docker/volume/store/store.go +++ /dev/null @@ -1,228 +0,0 @@ -package store - -import ( - "errors" - "sync" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/pkg/locker" - "github.com/docker/docker/volume" - "github.com/docker/docker/volume/drivers" -) - -var ( - // ErrVolumeInUse is a typed error returned when trying to remove a volume that is currently in use by a container - ErrVolumeInUse = errors.New("volume is in use") - // ErrNoSuchVolume is a typed error returned if the requested volume doesn't exist in the volume store - ErrNoSuchVolume = errors.New("no such volume") - // ErrInvalidName is a typed error returned when creating a volume with a name that is not valid on the platform - ErrInvalidName = errors.New("volume name is not valid on this platform") -) - -// New initializes a VolumeStore to keep -// reference counting of volumes in the system. -func New() *VolumeStore { - return &VolumeStore{ - vols: make(map[string]*volumeCounter), - locks: &locker.Locker{}, - } -} - -func (s *VolumeStore) get(name string) (*volumeCounter, bool) { - s.globalLock.Lock() - vc, exists := s.vols[name] - s.globalLock.Unlock() - return vc, exists -} - -func (s *VolumeStore) set(name string, vc *volumeCounter) { - s.globalLock.Lock() - s.vols[name] = vc - s.globalLock.Unlock() -} - -func (s *VolumeStore) remove(name string) { - s.globalLock.Lock() - delete(s.vols, name) - s.globalLock.Unlock() -} - -// VolumeStore is a struct that stores the list of volumes available and keeps track of their usage counts -type VolumeStore struct { - vols map[string]*volumeCounter - locks *locker.Locker - globalLock sync.Mutex -} - -// volumeCounter keeps track of references to a volume -type volumeCounter struct { - volume.Volume - count uint -} - -// AddAll adds a list of volumes to the store -func (s *VolumeStore) AddAll(vols []volume.Volume) { - for _, v := range vols { - s.vols[normaliseVolumeName(v.Name())] = &volumeCounter{v, 0} - } -} - -// Create tries to find an existing volume with the given name or create a new one from the passed in driver -func (s *VolumeStore) Create(name, driverName string, opts map[string]string) (volume.Volume, error) { - name = normaliseVolumeName(name) - s.locks.Lock(name) - defer s.locks.Unlock(name) - - if vc, exists := s.get(name); exists { - v := vc.Volume - return v, nil - } - logrus.Debugf("Registering new volume reference: driver %s, name %s", driverName, name) - - vd, err := volumedrivers.GetDriver(driverName) - if err != nil { - return nil, err - } - - // Validate the name in a platform-specific manner - valid, err := volume.IsVolumeNameValid(name) - if err != nil { - return nil, err - } - if !valid { - return nil, ErrInvalidName - } - - v, err := vd.Create(name, opts) - if err != nil { - return nil, err - } - - s.set(name, &volumeCounter{v, 0}) - return v, nil -} - -// Get looks if a volume with the given name exists and returns it if so -func (s *VolumeStore) Get(name string) (volume.Volume, error) { - name = normaliseVolumeName(name) - s.locks.Lock(name) - defer s.locks.Unlock(name) - - vc, exists := s.get(name) - if !exists { - return nil, ErrNoSuchVolume - } - return vc.Volume, nil -} - -// Remove removes the requested volume. A volume is not removed if the usage count is > 0 -func (s *VolumeStore) Remove(v volume.Volume) error { - name := normaliseVolumeName(v.Name()) - s.locks.Lock(name) - defer s.locks.Unlock(name) - - logrus.Debugf("Removing volume reference: driver %s, name %s", v.DriverName(), name) - vc, exists := s.get(name) - if !exists { - return ErrNoSuchVolume - } - - if vc.count > 0 { - return ErrVolumeInUse - } - - vd, err := volumedrivers.GetDriver(vc.DriverName()) - if err != nil { - return err - } - if err := vd.Remove(vc.Volume); err != nil { - return err - } - - s.remove(name) - return nil -} - -// Increment increments the usage count of the passed in volume by 1 -func (s *VolumeStore) Increment(v volume.Volume) { - name := normaliseVolumeName(v.Name()) - s.locks.Lock(name) - defer s.locks.Unlock(name) - - logrus.Debugf("Incrementing volume reference: driver %s, name %s", v.DriverName(), v.Name()) - vc, exists := s.get(name) - if !exists { - s.set(name, &volumeCounter{v, 1}) - return - } - vc.count++ -} - -// Decrement decrements the usage count of the passed in volume by 1 -func (s *VolumeStore) Decrement(v volume.Volume) { - name := normaliseVolumeName(v.Name()) - s.locks.Lock(name) - defer s.locks.Unlock(name) - logrus.Debugf("Decrementing volume reference: driver %s, name %s", v.DriverName(), v.Name()) - - vc, exists := s.get(name) - if !exists { - return - } - if vc.count == 0 { - return - } - vc.count-- -} - -// Count returns the usage count of the passed in volume -func (s *VolumeStore) Count(v volume.Volume) uint { - name := normaliseVolumeName(v.Name()) - s.locks.Lock(name) - defer s.locks.Unlock(name) - - vc, exists := s.get(name) - if !exists { - return 0 - } - return vc.count -} - -// List returns all the available volumes -func (s *VolumeStore) List() []volume.Volume { - s.globalLock.Lock() - defer s.globalLock.Unlock() - var ls []volume.Volume - for _, vc := range s.vols { - ls = append(ls, vc.Volume) - } - return ls -} - -// FilterByDriver returns the available volumes filtered by driver name -func (s *VolumeStore) FilterByDriver(name string) []volume.Volume { - return s.filter(byDriver(name)) -} - -// filterFunc defines a function to allow filter volumes in the store -type filterFunc func(vol volume.Volume) bool - -// byDriver generates a filterFunc to filter volumes by their driver name -func byDriver(name string) filterFunc { - return func(vol volume.Volume) bool { - return vol.DriverName() == name - } -} - -// filter returns the available volumes filtered by a filterFunc function -func (s *VolumeStore) filter(f filterFunc) []volume.Volume { - s.globalLock.Lock() - defer s.globalLock.Unlock() - var ls []volume.Volume - for _, vc := range s.vols { - if f(vc.Volume) { - ls = append(ls, vc.Volume) - } - } - return ls -} diff --git a/vendor/github.com/docker/docker/volume/store/store_test.go b/vendor/github.com/docker/docker/volume/store/store_test.go deleted file mode 100644 index 0b38ce62..00000000 --- a/vendor/github.com/docker/docker/volume/store/store_test.go +++ /dev/null @@ -1,152 +0,0 @@ -package store - -import ( - "testing" - - "github.com/docker/docker/volume" - "github.com/docker/docker/volume/drivers" - vt "github.com/docker/docker/volume/testutils" -) - -func TestList(t *testing.T) { - volumedrivers.Register(vt.FakeDriver{}, "fake") - s := New() - s.AddAll([]volume.Volume{vt.NewFakeVolume("fake1"), vt.NewFakeVolume("fake2")}) - l := s.List() - if len(l) != 2 { - t.Fatalf("Expected 2 volumes in the store, got %v: %v", len(l), l) - } -} - -func TestGet(t *testing.T) { - volumedrivers.Register(vt.FakeDriver{}, "fake") - s := New() - s.AddAll([]volume.Volume{vt.NewFakeVolume("fake1"), vt.NewFakeVolume("fake2")}) - v, err := s.Get("fake1") - if err != nil { - t.Fatal(err) - } - if v.Name() != "fake1" { - t.Fatalf("Expected fake1 volume, got %v", v) - } - - if _, err := s.Get("fake4"); err != ErrNoSuchVolume { - t.Fatalf("Expected ErrNoSuchVolume error, got %v", err) - } -} - -func TestCreate(t *testing.T) { - volumedrivers.Register(vt.FakeDriver{}, "fake") - s := New() - v, err := s.Create("fake1", "fake", nil) - if err != nil { - t.Fatal(err) - } - if v.Name() != "fake1" { - t.Fatalf("Expected fake1 volume, got %v", v) - } - if l := s.List(); len(l) != 1 { - t.Fatalf("Expected 1 volume in the store, got %v: %v", len(l), l) - } - - if _, err := s.Create("none", "none", nil); err == nil { - t.Fatalf("Expected unknown driver error, got nil") - } - - _, err = s.Create("fakeError", "fake", map[string]string{"error": "create error"}) - if err == nil || err.Error() != "create error" { - t.Fatalf("Expected create error, got %v", err) - } -} - -func TestRemove(t *testing.T) { - volumedrivers.Register(vt.FakeDriver{}, "fake") - s := New() - if err := s.Remove(vt.NoopVolume{}); err != ErrNoSuchVolume { - t.Fatalf("Expected ErrNoSuchVolume error, got %v", err) - } - v, err := s.Create("fake1", "fake", nil) - if err != nil { - t.Fatal(err) - } - s.Increment(v) - if err := s.Remove(v); err != ErrVolumeInUse { - t.Fatalf("Expected ErrVolumeInUse error, got %v", err) - } - s.Decrement(v) - if err := s.Remove(v); err != nil { - t.Fatal(err) - } - if l := s.List(); len(l) != 0 { - t.Fatalf("Expected 0 volumes in the store, got %v, %v", len(l), l) - } -} - -func TestIncrement(t *testing.T) { - s := New() - v := vt.NewFakeVolume("fake1") - s.Increment(v) - if l := s.List(); len(l) != 1 { - t.Fatalf("Expected 1 volume, got %v, %v", len(l), l) - } - if c := s.Count(v); c != 1 { - t.Fatalf("Expected 1 counter, got %v", c) - } - - s.Increment(v) - if l := s.List(); len(l) != 1 { - t.Fatalf("Expected 1 volume, got %v, %v", len(l), l) - } - if c := s.Count(v); c != 2 { - t.Fatalf("Expected 2 counter, got %v", c) - } - - v2 := vt.NewFakeVolume("fake2") - s.Increment(v2) - if l := s.List(); len(l) != 2 { - t.Fatalf("Expected 2 volume, got %v, %v", len(l), l) - } -} - -func TestDecrement(t *testing.T) { - s := New() - v := vt.NoopVolume{} - s.Decrement(v) - if c := s.Count(v); c != 0 { - t.Fatalf("Expected 0 volumes, got %v", c) - } - - s.Increment(v) - s.Increment(v) - s.Decrement(v) - if c := s.Count(v); c != 1 { - t.Fatalf("Expected 1 volume, got %v", c) - } - - s.Decrement(v) - if c := s.Count(v); c != 0 { - t.Fatalf("Expected 0 volumes, got %v", c) - } - - // Test counter cannot be negative. - s.Decrement(v) - if c := s.Count(v); c != 0 { - t.Fatalf("Expected 0 volumes, got %v", c) - } -} - -func TestFilterByDriver(t *testing.T) { - s := New() - - s.Increment(vt.NewFakeVolume("fake1")) - s.Increment(vt.NewFakeVolume("fake2")) - s.Increment(vt.NoopVolume{}) - - if l := s.FilterByDriver("fake"); len(l) != 2 { - t.Fatalf("Expected 2 volumes, got %v, %v", len(l), l) - } - - if l := s.FilterByDriver("noop"); len(l) != 1 { - t.Fatalf("Expected 1 volume, got %v, %v", len(l), l) - } -} diff --git a/vendor/github.com/docker/docker/volume/store/store_unix.go b/vendor/github.com/docker/docker/volume/store/store_unix.go deleted file mode 100644 index 319c541d..00000000 --- a/vendor/github.com/docker/docker/volume/store/store_unix.go +++ /dev/null @@ -1,9 +0,0 @@ -// +build linux freebsd - -package store - -// normaliseVolumeName is a platform specific function to normalise the name -// of a volume. This is a no-op on Unix-like platforms -func normaliseVolumeName(name string) string { - return name -} diff --git a/vendor/github.com/docker/docker/volume/store/store_windows.go b/vendor/github.com/docker/docker/volume/store/store_windows.go deleted file mode 100644 index a42c1f84..00000000 --- a/vendor/github.com/docker/docker/volume/store/store_windows.go +++ /dev/null @@ -1,12 +0,0 @@ -package store - -import "strings" - -// normaliseVolumeName is a platform specific function to normalise the name -// of a volume. On Windows, as NTFS is case insensitive, under -// c:\ProgramData\Docker\Volumes\, the folders John and john would be synonymous. -// Hence we can't allow the volume "John" and "john" to be created as seperate -// volumes. -func normaliseVolumeName(name string) string { - return strings.ToLower(name) -} diff --git a/vendor/github.com/docker/docker/volume/testutils/testutils.go b/vendor/github.com/docker/docker/volume/testutils/testutils.go deleted file mode 100644 index e1c75e91..00000000 --- a/vendor/github.com/docker/docker/volume/testutils/testutils.go +++ /dev/null @@ -1,68 +0,0 @@ -package volumetestutils - -import ( - "fmt" - - "github.com/docker/docker/volume" -) - -// NoopVolume is a volume that doesn't perform any operation -type NoopVolume struct{} - -// Name is the name of the volume -func (NoopVolume) Name() string { return "noop" } - -// DriverName is the name of the driver -func (NoopVolume) DriverName() string { return "noop" } - -// Path is the filesystem path to the volume -func (NoopVolume) Path() string { return "noop" } - -// Mount mounts the volume in the container -func (NoopVolume) Mount() (string, error) { return "noop", nil } - -// Unmount unmounts the volume from the container -func (NoopVolume) Unmount() error { return nil } - -// FakeVolume is a fake volume with a random name -type FakeVolume struct { - name string -} - -// NewFakeVolume creates a new fake volume for testing -func NewFakeVolume(name string) volume.Volume { - return FakeVolume{name: name} -} - -// Name is the name of the volume -func (f FakeVolume) Name() string { return f.name } - -// DriverName is the name of the driver -func (FakeVolume) DriverName() string { return "fake" } - -// Path is the filesystem path to the volume -func (FakeVolume) Path() string { return "fake" } - -// Mount mounts the volume in the container -func (FakeVolume) Mount() (string, error) { return "fake", nil } - -// Unmount unmounts the volume from the container -func (FakeVolume) Unmount() error { return nil } - -// FakeDriver is a driver that generates fake volumes -type FakeDriver struct{} - -// Name is the name of the driver -func (FakeDriver) Name() string { return "fake" } - -// Create initializes a fake volume. -// It returns an error if the options include an "error" key with a message -func (FakeDriver) Create(name string, opts map[string]string) (volume.Volume, error) { - if opts != nil && opts["error"] != "" { - return nil, fmt.Errorf(opts["error"]) - } - return NewFakeVolume(name), nil -} - -// Remove deletes a volume. -func (FakeDriver) Remove(v volume.Volume) error { return nil } diff --git a/vendor/github.com/docker/libcompose/cli/main/main.go b/vendor/github.com/docker/libcompose/cli/main/main.go deleted file mode 100644 index f9731371..00000000 --- a/vendor/github.com/docker/libcompose/cli/main/main.go +++ /dev/null @@ -1,41 +0,0 @@ -package main - -import ( - "os" - - "github.com/codegangsta/cli" - cliApp "github.com/docker/libcompose/cli/app" - "github.com/docker/libcompose/cli/command" - dockerApp "github.com/docker/libcompose/cli/docker/app" - "github.com/docker/libcompose/version" -) - -func main() { - factory := &dockerApp.ProjectFactory{} - - app := cli.NewApp() - app.Name = "libcompose-cli" - app.Usage = "Command line interface for libcompose." - app.Version = version.VERSION + " (" + version.GITCOMMIT + ")" - app.Author = "Docker Compose Contributors" - app.Email = "https://github.com/docker/libcompose" - app.Before = cliApp.BeforeApp - app.Flags = append(command.CommonFlags(), dockerApp.DockerClientFlags()...) - app.Commands = []cli.Command{ - command.BuildCommand(factory), - command.CreateCommand(factory), - command.UpCommand(factory), - command.StartCommand(factory), - command.LogsCommand(factory), - command.RestartCommand(factory), - command.StopCommand(factory), - command.ScaleCommand(factory), - command.RmCommand(factory), - command.PullCommand(factory), - command.KillCommand(factory), - command.PortCommand(factory), - command.PsCommand(factory), - } - - app.Run(os.Args) -} diff --git a/vendor/github.com/docker/libtrust/testutil/certificates.go b/vendor/github.com/docker/libtrust/testutil/certificates.go deleted file mode 100644 index 89debf6b..00000000 --- a/vendor/github.com/docker/libtrust/testutil/certificates.go +++ /dev/null @@ -1,94 +0,0 @@ -package testutil - -import ( - "crypto" - "crypto/rand" - "crypto/x509" - "crypto/x509/pkix" - "math/big" - "time" -) - -// GenerateTrustCA generates a new certificate authority for testing. -func GenerateTrustCA(pub crypto.PublicKey, priv crypto.PrivateKey) (*x509.Certificate, error) { - cert := &x509.Certificate{ - SerialNumber: big.NewInt(0), - Subject: pkix.Name{ - CommonName: "CA Root", - }, - NotBefore: time.Now().Add(-time.Second), - NotAfter: time.Now().Add(time.Hour), - IsCA: true, - KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, - BasicConstraintsValid: true, - } - - certDER, err := x509.CreateCertificate(rand.Reader, cert, cert, pub, priv) - if err != nil { - return nil, err - } - - cert, err = x509.ParseCertificate(certDER) - if err != nil { - return nil, err - } - - return cert, nil -} - -// GenerateIntermediate generates an intermediate certificate for testing using -// the parent certificate (likely a CA) and the provided keys. -func GenerateIntermediate(key crypto.PublicKey, parentKey crypto.PrivateKey, parent *x509.Certificate) (*x509.Certificate, error) { - cert := &x509.Certificate{ - SerialNumber: big.NewInt(0), - Subject: pkix.Name{ - CommonName: "Intermediate", - }, - NotBefore: time.Now().Add(-time.Second), - NotAfter: time.Now().Add(time.Hour), - IsCA: true, - KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, - BasicConstraintsValid: true, - } - - certDER, err := x509.CreateCertificate(rand.Reader, cert, parent, key, parentKey) - if err != nil { - return nil, err - } - - cert, err = x509.ParseCertificate(certDER) - if err != nil { - return nil, err - } - - return cert, nil -} - -// GenerateTrustCert generates a new trust certificate for testing. Unlike the -// intermediate certificates, this certificate should be used for signature -// only, not creating certificates. -func GenerateTrustCert(key crypto.PublicKey, parentKey crypto.PrivateKey, parent *x509.Certificate) (*x509.Certificate, error) { - cert := &x509.Certificate{ - SerialNumber: big.NewInt(0), - Subject: pkix.Name{ - CommonName: "Trust Cert", - }, - NotBefore: time.Now().Add(-time.Second), - NotAfter: time.Now().Add(time.Hour), - IsCA: true, - KeyUsage: x509.KeyUsageDigitalSignature, - BasicConstraintsValid: true, - } - - certDER, err := x509.CreateCertificate(rand.Reader, cert, parent, key, parentKey) - if err != nil { - return nil, err - } - - cert, err = x509.ParseCertificate(certDER) - if err != nil { - return nil, err - } - - return cert, nil -} diff --git a/vendor/github.com/docker/libtrust/tlsdemo/README.md b/vendor/github.com/docker/libtrust/tlsdemo/README.md deleted file mode 100644 index 24124db2..00000000 --- a/vendor/github.com/docker/libtrust/tlsdemo/README.md +++ /dev/null @@ -1,50 +0,0 @@ -## Libtrust TLS Config Demo - -This program generates key pairs and trust files for a TLS client and server. - -To generate the keys, run: - -``` -$ go run genkeys.go -``` - -The generated files are: - -``` -$ ls -l client_data/ server_data/ -client_data/: -total 24 --rw------- 1 jlhawn staff 281 Aug 8 16:21 private_key.json --rw-r--r-- 1 jlhawn staff 225 Aug 8 16:21 public_key.json --rw-r--r-- 1 jlhawn staff 275 Aug 8 16:21 trusted_hosts.json - -server_data/: -total 24 --rw-r--r-- 1 jlhawn staff 348 Aug 8 16:21 trusted_clients.json --rw------- 1 jlhawn staff 281 Aug 8 16:21 private_key.json --rw-r--r-- 1 jlhawn staff 225 Aug 8 16:21 public_key.json -``` - -The private key and public key for the client and server are stored in `private_key.json` and `public_key.json`, respectively, and in their respective directories. They are represented as JSON Web Keys: JSON objects which represent either an ECDSA or RSA private key. The host keys trusted by the client are stored in `trusted_hosts.json` and contain a mapping of an internet address, `:`, to a JSON Web Key which is a JSON object representing either an ECDSA or RSA public key of the trusted server. The client keys trusted by the server are stored in `trusted_clients.json` and contain an array of JSON objects which contain a comment field which can be used describe the key and a JSON Web Key which is a JSON object representing either an ECDSA or RSA public key of the trusted client. - -To start the server, run: - -``` -$ go run server.go -``` - -This starts an HTTPS server which listens on `localhost:8888`. The server configures itself with a certificate which is valid for both `localhost` and `127.0.0.1` and uses the key from `server_data/private_key.json`. It accepts connections from clients which present a certificate for a key that it is configured to trust from the `trusted_clients.json` file and returns a simple 'hello' message. - -To make a request using the client, run: - -``` -$ go run client.go -``` - -This command creates an HTTPS client which makes a GET request to `https://localhost:8888`. The client configures itself with a certificate using the key from `client_data/private_key.json`. It only connects to a server which presents a certificate signed by the key specified for the `localhost:8888` address from `client_data/trusted_hosts.json` and made to be used for the `localhost` hostname. If the connection succeeds, it prints the response from the server. - -The file `gencert.go` can be used to generate PEM encoded version of the client key and certificate. If you save them to `key.pem` and `cert.pem` respectively, you can use them with `curl` to test out the server (if it is still running). - -``` -curl --cert cert.pem --key key.pem -k https://localhost:8888 -``` diff --git a/vendor/github.com/docker/libtrust/tlsdemo/client.go b/vendor/github.com/docker/libtrust/tlsdemo/client.go deleted file mode 100644 index 0a699a0e..00000000 --- a/vendor/github.com/docker/libtrust/tlsdemo/client.go +++ /dev/null @@ -1,89 +0,0 @@ -package main - -import ( - "crypto/tls" - "fmt" - "io/ioutil" - "log" - "net" - "net/http" - - "github.com/docker/libtrust" -) - -var ( - serverAddress = "localhost:8888" - privateKeyFilename = "client_data/private_key.pem" - trustedHostsFilename = "client_data/trusted_hosts.pem" -) - -func main() { - // Load Client Key. - clientKey, err := libtrust.LoadKeyFile(privateKeyFilename) - if err != nil { - log.Fatal(err) - } - - // Generate Client Certificate. - selfSignedClientCert, err := libtrust.GenerateSelfSignedClientCert(clientKey) - if err != nil { - log.Fatal(err) - } - - // Load trusted host keys. - hostKeys, err := libtrust.LoadKeySetFile(trustedHostsFilename) - if err != nil { - log.Fatal(err) - } - - // Ensure the host we want to connect to is trusted! - host, _, err := net.SplitHostPort(serverAddress) - if err != nil { - log.Fatal(err) - } - serverKeys, err := libtrust.FilterByHosts(hostKeys, host, false) - if err != nil { - log.Fatalf("%q is not a known and trusted host", host) - } - - // Generate a CA pool with the trusted host's key. - caPool, err := libtrust.GenerateCACertPool(clientKey, serverKeys) - if err != nil { - log.Fatal(err) - } - - // Create HTTP Client. - client := &http.Client{ - Transport: &http.Transport{ - TLSClientConfig: &tls.Config{ - Certificates: []tls.Certificate{ - tls.Certificate{ - Certificate: [][]byte{selfSignedClientCert.Raw}, - PrivateKey: clientKey.CryptoPrivateKey(), - Leaf: selfSignedClientCert, - }, - }, - RootCAs: caPool, - }, - }, - } - - var makeRequest = func(url string) { - resp, err := client.Get(url) - if err != nil { - log.Fatal(err) - } - defer resp.Body.Close() - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - log.Fatal(err) - } - - log.Println(resp.Status) - log.Println(string(body)) - } - - // Make the request to the trusted server! - makeRequest(fmt.Sprintf("https://%s", serverAddress)) -} diff --git a/vendor/github.com/docker/libtrust/tlsdemo/gencert.go b/vendor/github.com/docker/libtrust/tlsdemo/gencert.go deleted file mode 100644 index c65f3b6b..00000000 --- a/vendor/github.com/docker/libtrust/tlsdemo/gencert.go +++ /dev/null @@ -1,62 +0,0 @@ -package main - -import ( - "encoding/pem" - "fmt" - "log" - "net" - - "github.com/docker/libtrust" -) - -var ( - serverAddress = "localhost:8888" - clientPrivateKeyFilename = "client_data/private_key.pem" - trustedHostsFilename = "client_data/trusted_hosts.pem" -) - -func main() { - key, err := libtrust.LoadKeyFile(clientPrivateKeyFilename) - if err != nil { - log.Fatal(err) - } - - keyPEMBlock, err := key.PEMBlock() - if err != nil { - log.Fatal(err) - } - - encodedPrivKey := pem.EncodeToMemory(keyPEMBlock) - fmt.Printf("Client Key:\n\n%s\n", string(encodedPrivKey)) - - cert, err := libtrust.GenerateSelfSignedClientCert(key) - if err != nil { - log.Fatal(err) - } - - encodedCert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}) - fmt.Printf("Client Cert:\n\n%s\n", string(encodedCert)) - - trustedServerKeys, err := libtrust.LoadKeySetFile(trustedHostsFilename) - if err != nil { - log.Fatal(err) - } - - hostname, _, err := net.SplitHostPort(serverAddress) - if err != nil { - log.Fatal(err) - } - - trustedServerKeys, err = libtrust.FilterByHosts(trustedServerKeys, hostname, false) - if err != nil { - log.Fatal(err) - } - - caCert, err := libtrust.GenerateCACert(key, trustedServerKeys[0]) - if err != nil { - log.Fatal(err) - } - - encodedCert = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: caCert.Raw}) - fmt.Printf("CA Cert:\n\n%s\n", string(encodedCert)) -} diff --git a/vendor/github.com/docker/libtrust/tlsdemo/genkeys.go b/vendor/github.com/docker/libtrust/tlsdemo/genkeys.go deleted file mode 100644 index 9dc8842a..00000000 --- a/vendor/github.com/docker/libtrust/tlsdemo/genkeys.go +++ /dev/null @@ -1,61 +0,0 @@ -package main - -import ( - "log" - - "github.com/docker/libtrust" -) - -func main() { - // Generate client key. - clientKey, err := libtrust.GenerateECP256PrivateKey() - if err != nil { - log.Fatal(err) - } - - // Add a comment for the client key. - clientKey.AddExtendedField("comment", "TLS Demo Client") - - // Save the client key, public and private versions. - err = libtrust.SaveKey("client_data/private_key.pem", clientKey) - if err != nil { - log.Fatal(err) - } - - err = libtrust.SavePublicKey("client_data/public_key.pem", clientKey.PublicKey()) - if err != nil { - log.Fatal(err) - } - - // Generate server key. - serverKey, err := libtrust.GenerateECP256PrivateKey() - if err != nil { - log.Fatal(err) - } - - // Set the list of addresses to use for the server. - serverKey.AddExtendedField("hosts", []string{"localhost", "docker.example.com"}) - - // Save the server key, public and private versions. - err = libtrust.SaveKey("server_data/private_key.pem", serverKey) - if err != nil { - log.Fatal(err) - } - - err = libtrust.SavePublicKey("server_data/public_key.pem", serverKey.PublicKey()) - if err != nil { - log.Fatal(err) - } - - // Generate Authorized Keys file for server. - err = libtrust.AddKeySetFile("server_data/trusted_clients.pem", clientKey.PublicKey()) - if err != nil { - log.Fatal(err) - } - - // Generate Known Host Keys file for client. - err = libtrust.AddKeySetFile("client_data/trusted_hosts.pem", serverKey.PublicKey()) - if err != nil { - log.Fatal(err) - } -} diff --git a/vendor/github.com/docker/libtrust/tlsdemo/server.go b/vendor/github.com/docker/libtrust/tlsdemo/server.go deleted file mode 100644 index d3cb2ea9..00000000 --- a/vendor/github.com/docker/libtrust/tlsdemo/server.go +++ /dev/null @@ -1,80 +0,0 @@ -package main - -import ( - "crypto/tls" - "fmt" - "html" - "log" - "net" - "net/http" - - "github.com/docker/libtrust" -) - -var ( - serverAddress = "localhost:8888" - privateKeyFilename = "server_data/private_key.pem" - authorizedClientsFilename = "server_data/trusted_clients.pem" -) - -func requestHandler(w http.ResponseWriter, r *http.Request) { - clientCert := r.TLS.PeerCertificates[0] - keyID := clientCert.Subject.CommonName - log.Printf("Request from keyID: %s\n", keyID) - fmt.Fprintf(w, "Hello, client! I'm a server! And you are %T: %s.\n", clientCert.PublicKey, html.EscapeString(keyID)) -} - -func main() { - // Load server key. - serverKey, err := libtrust.LoadKeyFile(privateKeyFilename) - if err != nil { - log.Fatal(err) - } - - // Generate server certificate. - selfSignedServerCert, err := libtrust.GenerateSelfSignedServerCert( - serverKey, []string{"localhost"}, []net.IP{net.ParseIP("127.0.0.1")}, - ) - if err != nil { - log.Fatal(err) - } - - // Load authorized client keys. - authorizedClients, err := libtrust.LoadKeySetFile(authorizedClientsFilename) - if err != nil { - log.Fatal(err) - } - - // Create CA pool using trusted client keys. - caPool, err := libtrust.GenerateCACertPool(serverKey, authorizedClients) - if err != nil { - log.Fatal(err) - } - - // Create TLS config, requiring client certificates. - tlsConfig := &tls.Config{ - Certificates: []tls.Certificate{ - tls.Certificate{ - Certificate: [][]byte{selfSignedServerCert.Raw}, - PrivateKey: serverKey.CryptoPrivateKey(), - Leaf: selfSignedServerCert, - }, - }, - ClientAuth: tls.RequireAndVerifyClientCert, - ClientCAs: caPool, - } - - // Create HTTP server with simple request handler. - server := &http.Server{ - Addr: serverAddress, - Handler: http.HandlerFunc(requestHandler), - } - - // Listen and server HTTPS using the libtrust TLS config. - listener, err := net.Listen("tcp", server.Addr) - if err != nil { - log.Fatal(err) - } - tlsListener := tls.NewListener(listener, tlsConfig) - server.Serve(tlsListener) -} diff --git a/vendor/github.com/docker/libtrust/trustgraph/graph.go b/vendor/github.com/docker/libtrust/trustgraph/graph.go deleted file mode 100644 index 72b0fc36..00000000 --- a/vendor/github.com/docker/libtrust/trustgraph/graph.go +++ /dev/null @@ -1,50 +0,0 @@ -package trustgraph - -import "github.com/docker/libtrust" - -// TrustGraph represents a graph of authorization mapping -// public keys to nodes and grants between nodes. -type TrustGraph interface { - // Verifies that the given public key is allowed to perform - // the given action on the given node according to the trust - // graph. - Verify(libtrust.PublicKey, string, uint16) (bool, error) - - // GetGrants returns an array of all grant chains which are used to - // allow the requested permission. - GetGrants(libtrust.PublicKey, string, uint16) ([][]*Grant, error) -} - -// Grant represents a transfer of permission from one part of the -// trust graph to another. This is the only way to delegate -// permission between two different sub trees in the graph. -type Grant struct { - // Subject is the namespace being granted - Subject string - - // Permissions is a bit map of permissions - Permission uint16 - - // Grantee represents the node being granted - // a permission scope. The grantee can be - // either a namespace item or a key id where namespace - // items will always start with a '/'. - Grantee string - - // statement represents the statement used to create - // this object. - statement *Statement -} - -// Permissions -// Read node 0x01 (can read node, no sub nodes) -// Write node 0x02 (can write to node object, cannot create subnodes) -// Read subtree 0x04 (delegates read to each sub node) -// Write subtree 0x08 (delegates write to each sub node, included create on the subject) -// -// Permission shortcuts -// ReadItem = 0x01 -// WriteItem = 0x03 -// ReadAccess = 0x07 -// WriteAccess = 0x0F -// Delegate = 0x0F diff --git a/vendor/github.com/docker/libtrust/trustgraph/memory_graph.go b/vendor/github.com/docker/libtrust/trustgraph/memory_graph.go deleted file mode 100644 index 247bfa7a..00000000 --- a/vendor/github.com/docker/libtrust/trustgraph/memory_graph.go +++ /dev/null @@ -1,133 +0,0 @@ -package trustgraph - -import ( - "strings" - - "github.com/docker/libtrust" -) - -type grantNode struct { - grants []*Grant - children map[string]*grantNode -} - -type memoryGraph struct { - roots map[string]*grantNode -} - -func newGrantNode() *grantNode { - return &grantNode{ - grants: []*Grant{}, - children: map[string]*grantNode{}, - } -} - -// NewMemoryGraph returns a new in memory trust graph created from -// a static list of grants. This graph is immutable after creation -// and any alterations should create a new instance. -func NewMemoryGraph(grants []*Grant) TrustGraph { - roots := map[string]*grantNode{} - for _, grant := range grants { - parts := strings.Split(grant.Grantee, "/") - nodes := roots - var node *grantNode - var nodeOk bool - for _, part := range parts { - node, nodeOk = nodes[part] - if !nodeOk { - node = newGrantNode() - nodes[part] = node - } - if part != "" { - node.grants = append(node.grants, grant) - } - nodes = node.children - } - } - return &memoryGraph{roots} -} - -func (g *memoryGraph) getGrants(name string) []*Grant { - nameParts := strings.Split(name, "/") - nodes := g.roots - var node *grantNode - var nodeOk bool - for _, part := range nameParts { - node, nodeOk = nodes[part] - if !nodeOk { - return nil - } - nodes = node.children - } - return node.grants -} - -func isSubName(name, sub string) bool { - if strings.HasPrefix(name, sub) { - if len(name) == len(sub) || name[len(sub)] == '/' { - return true - } - } - return false -} - -type walkFunc func(*Grant, []*Grant) bool - -func foundWalkFunc(*Grant, []*Grant) bool { - return true -} - -func (g *memoryGraph) walkGrants(start, target string, permission uint16, f walkFunc, chain []*Grant, visited map[*Grant]bool, collect bool) bool { - if visited == nil { - visited = map[*Grant]bool{} - } - grants := g.getGrants(start) - subGrants := make([]*Grant, 0, len(grants)) - for _, grant := range grants { - if visited[grant] { - continue - } - visited[grant] = true - if grant.Permission&permission == permission { - if isSubName(target, grant.Subject) { - if f(grant, chain) { - return true - } - } else { - subGrants = append(subGrants, grant) - } - } - } - for _, grant := range subGrants { - var chainCopy []*Grant - if collect { - chainCopy = make([]*Grant, len(chain)+1) - copy(chainCopy, chain) - chainCopy[len(chainCopy)-1] = grant - } else { - chainCopy = nil - } - - if g.walkGrants(grant.Subject, target, permission, f, chainCopy, visited, collect) { - return true - } - } - return false -} - -func (g *memoryGraph) Verify(key libtrust.PublicKey, node string, permission uint16) (bool, error) { - return g.walkGrants(key.KeyID(), node, permission, foundWalkFunc, nil, nil, false), nil -} - -func (g *memoryGraph) GetGrants(key libtrust.PublicKey, node string, permission uint16) ([][]*Grant, error) { - grants := [][]*Grant{} - collect := func(grant *Grant, chain []*Grant) bool { - grantChain := make([]*Grant, len(chain)+1) - copy(grantChain, chain) - grantChain[len(grantChain)-1] = grant - grants = append(grants, grantChain) - return false - } - g.walkGrants(key.KeyID(), node, permission, collect, nil, nil, true) - return grants, nil -} diff --git a/vendor/github.com/docker/libtrust/trustgraph/memory_graph_test.go b/vendor/github.com/docker/libtrust/trustgraph/memory_graph_test.go deleted file mode 100644 index 49fd0f3b..00000000 --- a/vendor/github.com/docker/libtrust/trustgraph/memory_graph_test.go +++ /dev/null @@ -1,174 +0,0 @@ -package trustgraph - -import ( - "fmt" - "testing" - - "github.com/docker/libtrust" -) - -func createTestKeysAndGrants(count int) ([]*Grant, []libtrust.PrivateKey) { - grants := make([]*Grant, count) - keys := make([]libtrust.PrivateKey, count) - for i := 0; i < count; i++ { - pk, err := libtrust.GenerateECP256PrivateKey() - if err != nil { - panic(err) - } - grant := &Grant{ - Subject: fmt.Sprintf("/user-%d", i+1), - Permission: 0x0f, - Grantee: pk.KeyID(), - } - keys[i] = pk - grants[i] = grant - } - return grants, keys -} - -func testVerified(t *testing.T, g TrustGraph, k libtrust.PublicKey, keyName, target string, permission uint16) { - if ok, err := g.Verify(k, target, permission); err != nil { - t.Fatalf("Unexpected error during verification: %s", err) - } else if !ok { - t.Errorf("key failed verification\n\tKey: %s(%s)\n\tNamespace: %s", keyName, k.KeyID(), target) - } -} - -func testNotVerified(t *testing.T, g TrustGraph, k libtrust.PublicKey, keyName, target string, permission uint16) { - if ok, err := g.Verify(k, target, permission); err != nil { - t.Fatalf("Unexpected error during verification: %s", err) - } else if ok { - t.Errorf("key should have failed verification\n\tKey: %s(%s)\n\tNamespace: %s", keyName, k.KeyID(), target) - } -} - -func TestVerify(t *testing.T) { - grants, keys := createTestKeysAndGrants(4) - extraGrants := make([]*Grant, 3) - extraGrants[0] = &Grant{ - Subject: "/user-3", - Permission: 0x0f, - Grantee: "/user-2", - } - extraGrants[1] = &Grant{ - Subject: "/user-3/sub-project", - Permission: 0x0f, - Grantee: "/user-4", - } - extraGrants[2] = &Grant{ - Subject: "/user-4", - Permission: 0x07, - Grantee: "/user-1", - } - grants = append(grants, extraGrants...) - - g := NewMemoryGraph(grants) - - testVerified(t, g, keys[0].PublicKey(), "user-key-1", "/user-1", 0x0f) - testVerified(t, g, keys[0].PublicKey(), "user-key-1", "/user-1/some-project/sub-value", 0x0f) - testVerified(t, g, keys[0].PublicKey(), "user-key-1", "/user-4", 0x07) - testVerified(t, g, keys[1].PublicKey(), "user-key-2", "/user-2/", 0x0f) - testVerified(t, g, keys[2].PublicKey(), "user-key-3", "/user-3/sub-value", 0x0f) - testVerified(t, g, keys[1].PublicKey(), "user-key-2", "/user-3/sub-value", 0x0f) - testVerified(t, g, keys[1].PublicKey(), "user-key-2", "/user-3", 0x0f) - testVerified(t, g, keys[1].PublicKey(), "user-key-2", "/user-3/", 0x0f) - testVerified(t, g, keys[3].PublicKey(), "user-key-4", "/user-3/sub-project", 0x0f) - testVerified(t, g, keys[3].PublicKey(), "user-key-4", "/user-3/sub-project/app", 0x0f) - testVerified(t, g, keys[3].PublicKey(), "user-key-4", "/user-4", 0x0f) - - testNotVerified(t, g, keys[0].PublicKey(), "user-key-1", "/user-2", 0x0f) - testNotVerified(t, g, keys[0].PublicKey(), "user-key-1", "/user-3/sub-value", 0x0f) - testNotVerified(t, g, keys[0].PublicKey(), "user-key-1", "/user-4", 0x0f) - testNotVerified(t, g, keys[1].PublicKey(), "user-key-2", "/user-1/", 0x0f) - testNotVerified(t, g, keys[2].PublicKey(), "user-key-3", "/user-2", 0x0f) - testNotVerified(t, g, keys[1].PublicKey(), "user-key-2", "/user-4", 0x0f) - testNotVerified(t, g, keys[3].PublicKey(), "user-key-4", "/user-3", 0x0f) -} - -func TestCircularWalk(t *testing.T) { - grants, keys := createTestKeysAndGrants(3) - user1Grant := &Grant{ - Subject: "/user-2", - Permission: 0x0f, - Grantee: "/user-1", - } - user2Grant := &Grant{ - Subject: "/user-1", - Permission: 0x0f, - Grantee: "/user-2", - } - grants = append(grants, user1Grant, user2Grant) - - g := NewMemoryGraph(grants) - - testVerified(t, g, keys[0].PublicKey(), "user-key-1", "/user-1", 0x0f) - testVerified(t, g, keys[0].PublicKey(), "user-key-1", "/user-2", 0x0f) - testVerified(t, g, keys[1].PublicKey(), "user-key-2", "/user-2", 0x0f) - testVerified(t, g, keys[1].PublicKey(), "user-key-2", "/user-1", 0x0f) - testVerified(t, g, keys[2].PublicKey(), "user-key-3", "/user-3", 0x0f) - - testNotVerified(t, g, keys[0].PublicKey(), "user-key-1", "/user-3", 0x0f) - testNotVerified(t, g, keys[1].PublicKey(), "user-key-2", "/user-3", 0x0f) -} - -func assertGrantSame(t *testing.T, actual, expected *Grant) { - if actual != expected { - t.Fatalf("Unexpected grant retrieved\n\tExpected: %v\n\tActual: %v", expected, actual) - } -} - -func TestGetGrants(t *testing.T) { - grants, keys := createTestKeysAndGrants(5) - extraGrants := make([]*Grant, 4) - extraGrants[0] = &Grant{ - Subject: "/user-3/friend-project", - Permission: 0x0f, - Grantee: "/user-2/friends", - } - extraGrants[1] = &Grant{ - Subject: "/user-3/sub-project", - Permission: 0x0f, - Grantee: "/user-4", - } - extraGrants[2] = &Grant{ - Subject: "/user-2/friends", - Permission: 0x0f, - Grantee: "/user-5/fun-project", - } - extraGrants[3] = &Grant{ - Subject: "/user-5/fun-project", - Permission: 0x0f, - Grantee: "/user-1", - } - grants = append(grants, extraGrants...) - - g := NewMemoryGraph(grants) - - grantChains, err := g.GetGrants(keys[3], "/user-3/sub-project/specific-app", 0x0f) - if err != nil { - t.Fatalf("Error getting grants: %s", err) - } - if len(grantChains) != 1 { - t.Fatalf("Expected number of grant chains returned, expected %d, received %d", 1, len(grantChains)) - } - if len(grantChains[0]) != 2 { - t.Fatalf("Unexpected number of grants retrieved\n\tExpected: %d\n\tActual: %d", 2, len(grantChains[0])) - } - assertGrantSame(t, grantChains[0][0], grants[3]) - assertGrantSame(t, grantChains[0][1], extraGrants[1]) - - grantChains, err = g.GetGrants(keys[0], "/user-3/friend-project/fun-app", 0x0f) - if err != nil { - t.Fatalf("Error getting grants: %s", err) - } - if len(grantChains) != 1 { - t.Fatalf("Expected number of grant chains returned, expected %d, received %d", 1, len(grantChains)) - } - if len(grantChains[0]) != 4 { - t.Fatalf("Unexpected number of grants retrieved\n\tExpected: %d\n\tActual: %d", 2, len(grantChains[0])) - } - assertGrantSame(t, grantChains[0][0], grants[0]) - assertGrantSame(t, grantChains[0][1], extraGrants[3]) - assertGrantSame(t, grantChains[0][2], extraGrants[2]) - assertGrantSame(t, grantChains[0][3], extraGrants[0]) -} diff --git a/vendor/github.com/docker/libtrust/trustgraph/statement.go b/vendor/github.com/docker/libtrust/trustgraph/statement.go deleted file mode 100644 index 7a74b553..00000000 --- a/vendor/github.com/docker/libtrust/trustgraph/statement.go +++ /dev/null @@ -1,227 +0,0 @@ -package trustgraph - -import ( - "crypto/x509" - "encoding/json" - "io" - "io/ioutil" - "sort" - "strings" - "time" - - "github.com/docker/libtrust" -) - -type jsonGrant struct { - Subject string `json:"subject"` - Permission uint16 `json:"permission"` - Grantee string `json:"grantee"` -} - -type jsonRevocation struct { - Subject string `json:"subject"` - Revocation uint16 `json:"revocation"` - Grantee string `json:"grantee"` -} - -type jsonStatement struct { - Revocations []*jsonRevocation `json:"revocations"` - Grants []*jsonGrant `json:"grants"` - Expiration time.Time `json:"expiration"` - IssuedAt time.Time `json:"issuedAt"` -} - -func (g *jsonGrant) Grant(statement *Statement) *Grant { - return &Grant{ - Subject: g.Subject, - Permission: g.Permission, - Grantee: g.Grantee, - statement: statement, - } -} - -// Statement represents a set of grants made from a verifiable -// authority. A statement has an expiration associated with it -// set by the authority. -type Statement struct { - jsonStatement - - signature *libtrust.JSONSignature -} - -// IsExpired returns whether the statement has expired -func (s *Statement) IsExpired() bool { - return s.Expiration.Before(time.Now().Add(-10 * time.Second)) -} - -// Bytes returns an indented json representation of the statement -// in a byte array. This value can be written to a file or stream -// without alteration. -func (s *Statement) Bytes() ([]byte, error) { - return s.signature.PrettySignature("signatures") -} - -// LoadStatement loads and verifies a statement from an input stream. -func LoadStatement(r io.Reader, authority *x509.CertPool) (*Statement, error) { - b, err := ioutil.ReadAll(r) - if err != nil { - return nil, err - } - js, err := libtrust.ParsePrettySignature(b, "signatures") - if err != nil { - return nil, err - } - payload, err := js.Payload() - if err != nil { - return nil, err - } - var statement Statement - err = json.Unmarshal(payload, &statement.jsonStatement) - if err != nil { - return nil, err - } - - if authority == nil { - _, err = js.Verify() - if err != nil { - return nil, err - } - } else { - _, err = js.VerifyChains(authority) - if err != nil { - return nil, err - } - } - statement.signature = js - - return &statement, nil -} - -// CreateStatements creates and signs a statement from a stream of grants -// and revocations in a JSON array. -func CreateStatement(grants, revocations io.Reader, expiration time.Duration, key libtrust.PrivateKey, chain []*x509.Certificate) (*Statement, error) { - var statement Statement - err := json.NewDecoder(grants).Decode(&statement.jsonStatement.Grants) - if err != nil { - return nil, err - } - err = json.NewDecoder(revocations).Decode(&statement.jsonStatement.Revocations) - if err != nil { - return nil, err - } - statement.jsonStatement.Expiration = time.Now().UTC().Add(expiration) - statement.jsonStatement.IssuedAt = time.Now().UTC() - - b, err := json.MarshalIndent(&statement.jsonStatement, "", " ") - if err != nil { - return nil, err - } - - statement.signature, err = libtrust.NewJSONSignature(b) - if err != nil { - return nil, err - } - err = statement.signature.SignWithChain(key, chain) - if err != nil { - return nil, err - } - - return &statement, nil -} - -type statementList []*Statement - -func (s statementList) Len() int { - return len(s) -} - -func (s statementList) Less(i, j int) bool { - return s[i].IssuedAt.Before(s[j].IssuedAt) -} - -func (s statementList) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -// CollapseStatements returns a single list of the valid statements as well as the -// time when the next grant will expire. -func CollapseStatements(statements []*Statement, useExpired bool) ([]*Grant, time.Time, error) { - sorted := make(statementList, 0, len(statements)) - for _, statement := range statements { - if useExpired || !statement.IsExpired() { - sorted = append(sorted, statement) - } - } - sort.Sort(sorted) - - var minExpired time.Time - var grantCount int - roots := map[string]*grantNode{} - for i, statement := range sorted { - if statement.Expiration.Before(minExpired) || i == 0 { - minExpired = statement.Expiration - } - for _, grant := range statement.Grants { - parts := strings.Split(grant.Grantee, "/") - nodes := roots - g := grant.Grant(statement) - grantCount = grantCount + 1 - - for _, part := range parts { - node, nodeOk := nodes[part] - if !nodeOk { - node = newGrantNode() - nodes[part] = node - } - node.grants = append(node.grants, g) - nodes = node.children - } - } - - for _, revocation := range statement.Revocations { - parts := strings.Split(revocation.Grantee, "/") - nodes := roots - - var node *grantNode - var nodeOk bool - for _, part := range parts { - node, nodeOk = nodes[part] - if !nodeOk { - break - } - nodes = node.children - } - if node != nil { - for _, grant := range node.grants { - if isSubName(grant.Subject, revocation.Subject) { - grant.Permission = grant.Permission &^ revocation.Revocation - } - } - } - } - } - - retGrants := make([]*Grant, 0, grantCount) - for _, rootNodes := range roots { - retGrants = append(retGrants, rootNodes.grants...) - } - - return retGrants, minExpired, nil -} - -// FilterStatements filters the statements to statements including the given grants. -func FilterStatements(grants []*Grant) ([]*Statement, error) { - statements := map[*Statement]bool{} - for _, grant := range grants { - if grant.statement != nil { - statements[grant.statement] = true - } - } - retStatements := make([]*Statement, len(statements)) - var i int - for statement := range statements { - retStatements[i] = statement - i++ - } - return retStatements, nil -} diff --git a/vendor/github.com/docker/libtrust/trustgraph/statement_test.go b/vendor/github.com/docker/libtrust/trustgraph/statement_test.go deleted file mode 100644 index e5094686..00000000 --- a/vendor/github.com/docker/libtrust/trustgraph/statement_test.go +++ /dev/null @@ -1,417 +0,0 @@ -package trustgraph - -import ( - "bytes" - "crypto/x509" - "encoding/json" - "testing" - "time" - - "github.com/docker/libtrust" - "github.com/docker/libtrust/testutil" -) - -const testStatementExpiration = time.Hour * 5 - -func generateStatement(grants []*Grant, key libtrust.PrivateKey, chain []*x509.Certificate) (*Statement, error) { - var statement Statement - - statement.Grants = make([]*jsonGrant, len(grants)) - for i, grant := range grants { - statement.Grants[i] = &jsonGrant{ - Subject: grant.Subject, - Permission: grant.Permission, - Grantee: grant.Grantee, - } - } - statement.IssuedAt = time.Now() - statement.Expiration = time.Now().Add(testStatementExpiration) - statement.Revocations = make([]*jsonRevocation, 0) - - marshalled, err := json.MarshalIndent(statement.jsonStatement, "", " ") - if err != nil { - return nil, err - } - - sig, err := libtrust.NewJSONSignature(marshalled) - if err != nil { - return nil, err - } - err = sig.SignWithChain(key, chain) - if err != nil { - return nil, err - } - statement.signature = sig - - return &statement, nil -} - -func generateTrustChain(t *testing.T, chainLen int) (libtrust.PrivateKey, *x509.CertPool, []*x509.Certificate) { - caKey, err := libtrust.GenerateECP256PrivateKey() - if err != nil { - t.Fatalf("Error generating key: %s", err) - } - ca, err := testutil.GenerateTrustCA(caKey.CryptoPublicKey(), caKey.CryptoPrivateKey()) - if err != nil { - t.Fatalf("Error generating ca: %s", err) - } - - parent := ca - parentKey := caKey - chain := make([]*x509.Certificate, chainLen) - for i := chainLen - 1; i > 0; i-- { - intermediatekey, err := libtrust.GenerateECP256PrivateKey() - if err != nil { - t.Fatalf("Error generate key: %s", err) - } - chain[i], err = testutil.GenerateIntermediate(intermediatekey.CryptoPublicKey(), parentKey.CryptoPrivateKey(), parent) - if err != nil { - t.Fatalf("Error generating intermdiate certificate: %s", err) - } - parent = chain[i] - parentKey = intermediatekey - } - trustKey, err := libtrust.GenerateECP256PrivateKey() - if err != nil { - t.Fatalf("Error generate key: %s", err) - } - chain[0], err = testutil.GenerateTrustCert(trustKey.CryptoPublicKey(), parentKey.CryptoPrivateKey(), parent) - if err != nil { - t.Fatalf("Error generate trust cert: %s", err) - } - - caPool := x509.NewCertPool() - caPool.AddCert(ca) - - return trustKey, caPool, chain -} - -func TestLoadStatement(t *testing.T) { - grantCount := 4 - grants, _ := createTestKeysAndGrants(grantCount) - - trustKey, caPool, chain := generateTrustChain(t, 6) - - statement, err := generateStatement(grants, trustKey, chain) - if err != nil { - t.Fatalf("Error generating statement: %s", err) - } - - statementBytes, err := statement.Bytes() - if err != nil { - t.Fatalf("Error getting statement bytes: %s", err) - } - - s2, err := LoadStatement(bytes.NewReader(statementBytes), caPool) - if err != nil { - t.Fatalf("Error loading statement: %s", err) - } - if len(s2.Grants) != grantCount { - t.Fatalf("Unexpected grant length\n\tExpected: %d\n\tActual: %d", grantCount, len(s2.Grants)) - } - - pool := x509.NewCertPool() - _, err = LoadStatement(bytes.NewReader(statementBytes), pool) - if err == nil { - t.Fatalf("No error thrown verifying without an authority") - } else if _, ok := err.(x509.UnknownAuthorityError); !ok { - t.Fatalf("Unexpected error verifying without authority: %s", err) - } - - s2, err = LoadStatement(bytes.NewReader(statementBytes), nil) - if err != nil { - t.Fatalf("Error loading statement: %s", err) - } - if len(s2.Grants) != grantCount { - t.Fatalf("Unexpected grant length\n\tExpected: %d\n\tActual: %d", grantCount, len(s2.Grants)) - } - - badData := make([]byte, len(statementBytes)) - copy(badData, statementBytes) - badData[0] = '[' - _, err = LoadStatement(bytes.NewReader(badData), nil) - if err == nil { - t.Fatalf("No error thrown parsing bad json") - } - - alteredData := make([]byte, len(statementBytes)) - copy(alteredData, statementBytes) - alteredData[30] = '0' - _, err = LoadStatement(bytes.NewReader(alteredData), nil) - if err == nil { - t.Fatalf("No error thrown from bad data") - } -} - -func TestCollapseGrants(t *testing.T) { - grantCount := 8 - grants, keys := createTestKeysAndGrants(grantCount) - linkGrants := make([]*Grant, 4) - linkGrants[0] = &Grant{ - Subject: "/user-3", - Permission: 0x0f, - Grantee: "/user-2", - } - linkGrants[1] = &Grant{ - Subject: "/user-3/sub-project", - Permission: 0x0f, - Grantee: "/user-4", - } - linkGrants[2] = &Grant{ - Subject: "/user-6", - Permission: 0x0f, - Grantee: "/user-7", - } - linkGrants[3] = &Grant{ - Subject: "/user-6/sub-project/specific-app", - Permission: 0x0f, - Grantee: "/user-5", - } - trustKey, pool, chain := generateTrustChain(t, 3) - - statements := make([]*Statement, 3) - var err error - statements[0], err = generateStatement(grants[0:4], trustKey, chain) - if err != nil { - t.Fatalf("Error generating statement: %s", err) - } - statements[1], err = generateStatement(grants[4:], trustKey, chain) - if err != nil { - t.Fatalf("Error generating statement: %s", err) - } - statements[2], err = generateStatement(linkGrants, trustKey, chain) - if err != nil { - t.Fatalf("Error generating statement: %s", err) - } - - statementsCopy := make([]*Statement, len(statements)) - for i, statement := range statements { - b, err := statement.Bytes() - if err != nil { - t.Fatalf("Error getting statement bytes: %s", err) - } - verifiedStatement, err := LoadStatement(bytes.NewReader(b), pool) - if err != nil { - t.Fatalf("Error loading statement: %s", err) - } - // Force sort by reversing order - statementsCopy[len(statementsCopy)-i-1] = verifiedStatement - } - statements = statementsCopy - - collapsedGrants, expiration, err := CollapseStatements(statements, false) - if len(collapsedGrants) != 12 { - t.Fatalf("Unexpected number of grants\n\tExpected: %d\n\tActual: %d", 12, len(collapsedGrants)) - } - if expiration.After(time.Now().Add(time.Hour*5)) || expiration.Before(time.Now()) { - t.Fatalf("Unexpected expiration time: %s", expiration.String()) - } - g := NewMemoryGraph(collapsedGrants) - - testVerified(t, g, keys[0].PublicKey(), "user-key-1", "/user-1", 0x0f) - testVerified(t, g, keys[1].PublicKey(), "user-key-2", "/user-2", 0x0f) - testVerified(t, g, keys[2].PublicKey(), "user-key-3", "/user-3", 0x0f) - testVerified(t, g, keys[3].PublicKey(), "user-key-4", "/user-4", 0x0f) - testVerified(t, g, keys[4].PublicKey(), "user-key-5", "/user-5", 0x0f) - testVerified(t, g, keys[5].PublicKey(), "user-key-6", "/user-6", 0x0f) - testVerified(t, g, keys[6].PublicKey(), "user-key-7", "/user-7", 0x0f) - testVerified(t, g, keys[7].PublicKey(), "user-key-8", "/user-8", 0x0f) - testVerified(t, g, keys[1].PublicKey(), "user-key-2", "/user-3", 0x0f) - testVerified(t, g, keys[1].PublicKey(), "user-key-2", "/user-3/sub-project/specific-app", 0x0f) - testVerified(t, g, keys[3].PublicKey(), "user-key-4", "/user-3/sub-project", 0x0f) - testVerified(t, g, keys[6].PublicKey(), "user-key-7", "/user-6", 0x0f) - testVerified(t, g, keys[6].PublicKey(), "user-key-7", "/user-6/sub-project/specific-app", 0x0f) - testVerified(t, g, keys[4].PublicKey(), "user-key-5", "/user-6/sub-project/specific-app", 0x0f) - - testNotVerified(t, g, keys[3].PublicKey(), "user-key-4", "/user-3", 0x0f) - testNotVerified(t, g, keys[3].PublicKey(), "user-key-4", "/user-6/sub-project", 0x0f) - testNotVerified(t, g, keys[4].PublicKey(), "user-key-5", "/user-6/sub-project", 0x0f) - - // Add revocation grant - statements = append(statements, &Statement{ - jsonStatement{ - IssuedAt: time.Now(), - Expiration: time.Now().Add(testStatementExpiration), - Grants: []*jsonGrant{}, - Revocations: []*jsonRevocation{ - &jsonRevocation{ - Subject: "/user-1", - Revocation: 0x0f, - Grantee: keys[0].KeyID(), - }, - &jsonRevocation{ - Subject: "/user-2", - Revocation: 0x08, - Grantee: keys[1].KeyID(), - }, - &jsonRevocation{ - Subject: "/user-6", - Revocation: 0x0f, - Grantee: "/user-7", - }, - &jsonRevocation{ - Subject: "/user-9", - Revocation: 0x0f, - Grantee: "/user-10", - }, - }, - }, - nil, - }) - - collapsedGrants, expiration, err = CollapseStatements(statements, false) - if len(collapsedGrants) != 12 { - t.Fatalf("Unexpected number of grants\n\tExpected: %d\n\tActual: %d", 12, len(collapsedGrants)) - } - if expiration.After(time.Now().Add(time.Hour*5)) || expiration.Before(time.Now()) { - t.Fatalf("Unexpected expiration time: %s", expiration.String()) - } - g = NewMemoryGraph(collapsedGrants) - - testNotVerified(t, g, keys[0].PublicKey(), "user-key-1", "/user-1", 0x0f) - testNotVerified(t, g, keys[1].PublicKey(), "user-key-2", "/user-2", 0x0f) - testNotVerified(t, g, keys[6].PublicKey(), "user-key-7", "/user-6/sub-project/specific-app", 0x0f) - - testVerified(t, g, keys[1].PublicKey(), "user-key-2", "/user-2", 0x07) -} - -func TestFilterStatements(t *testing.T) { - grantCount := 8 - grants, keys := createTestKeysAndGrants(grantCount) - linkGrants := make([]*Grant, 3) - linkGrants[0] = &Grant{ - Subject: "/user-3", - Permission: 0x0f, - Grantee: "/user-2", - } - linkGrants[1] = &Grant{ - Subject: "/user-5", - Permission: 0x0f, - Grantee: "/user-4", - } - linkGrants[2] = &Grant{ - Subject: "/user-7", - Permission: 0x0f, - Grantee: "/user-6", - } - - trustKey, _, chain := generateTrustChain(t, 3) - - statements := make([]*Statement, 5) - var err error - statements[0], err = generateStatement(grants[0:2], trustKey, chain) - if err != nil { - t.Fatalf("Error generating statement: %s", err) - } - statements[1], err = generateStatement(grants[2:4], trustKey, chain) - if err != nil { - t.Fatalf("Error generating statement: %s", err) - } - statements[2], err = generateStatement(grants[4:6], trustKey, chain) - if err != nil { - t.Fatalf("Error generating statement: %s", err) - } - statements[3], err = generateStatement(grants[6:], trustKey, chain) - if err != nil { - t.Fatalf("Error generating statement: %s", err) - } - statements[4], err = generateStatement(linkGrants, trustKey, chain) - if err != nil { - t.Fatalf("Error generating statement: %s", err) - } - collapsed, _, err := CollapseStatements(statements, false) - if err != nil { - t.Fatalf("Error collapsing grants: %s", err) - } - - // Filter 1, all 5 statements - filter1, err := FilterStatements(collapsed) - if err != nil { - t.Fatalf("Error filtering statements: %s", err) - } - if len(filter1) != 5 { - t.Fatalf("Wrong number of statements, expected %d, received %d", 5, len(filter1)) - } - - // Filter 2, one statement - filter2, err := FilterStatements([]*Grant{collapsed[0]}) - if err != nil { - t.Fatalf("Error filtering statements: %s", err) - } - if len(filter2) != 1 { - t.Fatalf("Wrong number of statements, expected %d, received %d", 1, len(filter2)) - } - - // Filter 3, 2 statements, from graph lookup - g := NewMemoryGraph(collapsed) - lookupGrants, err := g.GetGrants(keys[1], "/user-3", 0x0f) - if err != nil { - t.Fatalf("Error looking up grants: %s", err) - } - if len(lookupGrants) != 1 { - t.Fatalf("Wrong numberof grant chains returned from lookup, expected %d, received %d", 1, len(lookupGrants)) - } - if len(lookupGrants[0]) != 2 { - t.Fatalf("Wrong number of grants looked up, expected %d, received %d", 2, len(lookupGrants)) - } - filter3, err := FilterStatements(lookupGrants[0]) - if err != nil { - t.Fatalf("Error filtering statements: %s", err) - } - if len(filter3) != 2 { - t.Fatalf("Wrong number of statements, expected %d, received %d", 2, len(filter3)) - } - -} - -func TestCreateStatement(t *testing.T) { - grantJSON := bytes.NewReader([]byte(`[ - { - "subject": "/user-2", - "permission": 15, - "grantee": "/user-1" - }, - { - "subject": "/user-7", - "permission": 1, - "grantee": "/user-9" - }, - { - "subject": "/user-3", - "permission": 15, - "grantee": "/user-2" - } -]`)) - revocationJSON := bytes.NewReader([]byte(`[ - { - "subject": "user-8", - "revocation": 12, - "grantee": "user-9" - } -]`)) - - trustKey, pool, chain := generateTrustChain(t, 3) - - statement, err := CreateStatement(grantJSON, revocationJSON, testStatementExpiration, trustKey, chain) - if err != nil { - t.Fatalf("Error creating statement: %s", err) - } - - b, err := statement.Bytes() - if err != nil { - t.Fatalf("Error retrieving bytes: %s", err) - } - - verified, err := LoadStatement(bytes.NewReader(b), pool) - if err != nil { - t.Fatalf("Error loading statement: %s", err) - } - - if len(verified.Grants) != 3 { - t.Errorf("Unexpected number of grants, expected %d, received %d", 3, len(verified.Grants)) - } - - if len(verified.Revocations) != 1 { - t.Errorf("Unexpected number of revocations, expected %d, received %d", 1, len(verified.Revocations)) - } -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/distribution/registry/api/errcode/errors.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/distribution/registry/api/errcode/errors.go deleted file mode 100644 index fdaddbcf..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/distribution/registry/api/errcode/errors.go +++ /dev/null @@ -1,259 +0,0 @@ -package errcode - -import ( - "encoding/json" - "fmt" - "strings" -) - -// ErrorCoder is the base interface for ErrorCode and Error allowing -// users of each to just call ErrorCode to get the real ID of each -type ErrorCoder interface { - ErrorCode() ErrorCode -} - -// ErrorCode represents the error type. The errors are serialized via strings -// and the integer format may change and should *never* be exported. -type ErrorCode int - -var _ error = ErrorCode(0) - -// ErrorCode just returns itself -func (ec ErrorCode) ErrorCode() ErrorCode { - return ec -} - -// Error returns the ID/Value -func (ec ErrorCode) Error() string { - return ec.Descriptor().Value -} - -// Descriptor returns the descriptor for the error code. -func (ec ErrorCode) Descriptor() ErrorDescriptor { - d, ok := errorCodeToDescriptors[ec] - - if !ok { - return ErrorCodeUnknown.Descriptor() - } - - return d -} - -// String returns the canonical identifier for this error code. -func (ec ErrorCode) String() string { - return ec.Descriptor().Value -} - -// Message returned the human-readable error message for this error code. -func (ec ErrorCode) Message() string { - return ec.Descriptor().Message -} - -// MarshalText encodes the receiver into UTF-8-encoded text and returns the -// result. -func (ec ErrorCode) MarshalText() (text []byte, err error) { - return []byte(ec.String()), nil -} - -// UnmarshalText decodes the form generated by MarshalText. -func (ec *ErrorCode) UnmarshalText(text []byte) error { - desc, ok := idToDescriptors[string(text)] - - if !ok { - desc = ErrorCodeUnknown.Descriptor() - } - - *ec = desc.Code - - return nil -} - -// WithDetail creates a new Error struct based on the passed-in info and -// set the Detail property appropriately -func (ec ErrorCode) WithDetail(detail interface{}) Error { - return Error{ - Code: ec, - Message: ec.Message(), - }.WithDetail(detail) -} - -// WithArgs creates a new Error struct and sets the Args slice -func (ec ErrorCode) WithArgs(args ...interface{}) Error { - return Error{ - Code: ec, - Message: ec.Message(), - }.WithArgs(args...) -} - -// Error provides a wrapper around ErrorCode with extra Details provided. -type Error struct { - Code ErrorCode `json:"code"` - Message string `json:"message"` - Detail interface{} `json:"detail,omitempty"` - - // TODO(duglin): See if we need an "args" property so we can do the - // variable substitution right before showing the message to the user -} - -var _ error = Error{} - -// ErrorCode returns the ID/Value of this Error -func (e Error) ErrorCode() ErrorCode { - return e.Code -} - -// Error returns a human readable representation of the error. -func (e Error) Error() string { - return fmt.Sprintf("%s: %s", - strings.ToLower(strings.Replace(e.Code.String(), "_", " ", -1)), - e.Message) -} - -// WithDetail will return a new Error, based on the current one, but with -// some Detail info added -func (e Error) WithDetail(detail interface{}) Error { - return Error{ - Code: e.Code, - Message: e.Message, - Detail: detail, - } -} - -// WithArgs uses the passed-in list of interface{} as the substitution -// variables in the Error's Message string, but returns a new Error -func (e Error) WithArgs(args ...interface{}) Error { - return Error{ - Code: e.Code, - Message: fmt.Sprintf(e.Code.Message(), args...), - Detail: e.Detail, - } -} - -// ErrorDescriptor provides relevant information about a given error code. -type ErrorDescriptor struct { - // Code is the error code that this descriptor describes. - Code ErrorCode - - // Value provides a unique, string key, often captilized with - // underscores, to identify the error code. This value is used as the - // keyed value when serializing api errors. - Value string - - // Message is a short, human readable decription of the error condition - // included in API responses. - Message string - - // Description provides a complete account of the errors purpose, suitable - // for use in documentation. - Description string - - // HTTPStatusCode provides the http status code that is associated with - // this error condition. - HTTPStatusCode int -} - -// ParseErrorCode returns the value by the string error code. -// `ErrorCodeUnknown` will be returned if the error is not known. -func ParseErrorCode(value string) ErrorCode { - ed, ok := idToDescriptors[value] - if ok { - return ed.Code - } - - return ErrorCodeUnknown -} - -// Errors provides the envelope for multiple errors and a few sugar methods -// for use within the application. -type Errors []error - -var _ error = Errors{} - -func (errs Errors) Error() string { - switch len(errs) { - case 0: - return "" - case 1: - return errs[0].Error() - default: - msg := "errors:\n" - for _, err := range errs { - msg += err.Error() + "\n" - } - return msg - } -} - -// Len returns the current number of errors. -func (errs Errors) Len() int { - return len(errs) -} - -// MarshalJSON converts slice of error, ErrorCode or Error into a -// slice of Error - then serializes -func (errs Errors) MarshalJSON() ([]byte, error) { - var tmpErrs struct { - Errors []Error `json:"errors,omitempty"` - } - - for _, daErr := range errs { - var err Error - - switch daErr.(type) { - case ErrorCode: - err = daErr.(ErrorCode).WithDetail(nil) - case Error: - err = daErr.(Error) - default: - err = ErrorCodeUnknown.WithDetail(daErr) - - } - - // If the Error struct was setup and they forgot to set the - // Message field (meaning its "") then grab it from the ErrCode - msg := err.Message - if msg == "" { - msg = err.Code.Message() - } - - tmpErrs.Errors = append(tmpErrs.Errors, Error{ - Code: err.Code, - Message: msg, - Detail: err.Detail, - }) - } - - return json.Marshal(tmpErrs) -} - -// UnmarshalJSON deserializes []Error and then converts it into slice of -// Error or ErrorCode -func (errs *Errors) UnmarshalJSON(data []byte) error { - var tmpErrs struct { - Errors []Error - } - - if err := json.Unmarshal(data, &tmpErrs); err != nil { - return err - } - - var newErrs Errors - for _, daErr := range tmpErrs.Errors { - // If Message is empty or exactly matches the Code's message string - // then just use the Code, no need for a full Error struct - if daErr.Detail == nil && (daErr.Message == "" || daErr.Message == daErr.Code.Message()) { - // Error's w/o details get converted to ErrorCode - newErrs = append(newErrs, daErr.Code) - } else { - // Error's w/ details are untouched - newErrs = append(newErrs, Error{ - Code: daErr.Code, - Message: daErr.Message, - Detail: daErr.Detail, - }) - } - } - - *errs = newErrs - return nil -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/distribution/registry/api/errcode/errors_test.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/distribution/registry/api/errcode/errors_test.go deleted file mode 100644 index 27fb1cec..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/distribution/registry/api/errcode/errors_test.go +++ /dev/null @@ -1,179 +0,0 @@ -package errcode - -import ( - "encoding/json" - "net/http" - "reflect" - "testing" -) - -// TestErrorCodes ensures that error code format, mappings and -// marshaling/unmarshaling. round trips are stable. -func TestErrorCodes(t *testing.T) { - if len(errorCodeToDescriptors) == 0 { - t.Fatal("errors aren't loaded!") - } - - for ec, desc := range errorCodeToDescriptors { - if ec != desc.Code { - t.Fatalf("error code in descriptor isn't correct, %q != %q", ec, desc.Code) - } - - if idToDescriptors[desc.Value].Code != ec { - t.Fatalf("error code in idToDesc isn't correct, %q != %q", idToDescriptors[desc.Value].Code, ec) - } - - if ec.Message() != desc.Message { - t.Fatalf("ec.Message doesn't mtach desc.Message: %q != %q", ec.Message(), desc.Message) - } - - // Test (de)serializing the ErrorCode - p, err := json.Marshal(ec) - if err != nil { - t.Fatalf("couldn't marshal ec %v: %v", ec, err) - } - - if len(p) <= 0 { - t.Fatalf("expected content in marshaled before for error code %v", ec) - } - - // First, unmarshal to interface and ensure we have a string. - var ecUnspecified interface{} - if err := json.Unmarshal(p, &ecUnspecified); err != nil { - t.Fatalf("error unmarshaling error code %v: %v", ec, err) - } - - if _, ok := ecUnspecified.(string); !ok { - t.Fatalf("expected a string for error code %v on unmarshal got a %T", ec, ecUnspecified) - } - - // Now, unmarshal with the error code type and ensure they are equal - var ecUnmarshaled ErrorCode - if err := json.Unmarshal(p, &ecUnmarshaled); err != nil { - t.Fatalf("error unmarshaling error code %v: %v", ec, err) - } - - if ecUnmarshaled != ec { - t.Fatalf("unexpected error code during error code marshal/unmarshal: %v != %v", ecUnmarshaled, ec) - } - } - -} - -// TestErrorsManagement does a quick check of the Errors type to ensure that -// members are properly pushed and marshaled. -var ErrorCodeTest1 = Register("v2.errors", ErrorDescriptor{ - Value: "TEST1", - Message: "test error 1", - Description: `Just a test message #1.`, - HTTPStatusCode: http.StatusInternalServerError, -}) - -var ErrorCodeTest2 = Register("v2.errors", ErrorDescriptor{ - Value: "TEST2", - Message: "test error 2", - Description: `Just a test message #2.`, - HTTPStatusCode: http.StatusNotFound, -}) - -var ErrorCodeTest3 = Register("v2.errors", ErrorDescriptor{ - Value: "TEST3", - Message: "Sorry %q isn't valid", - Description: `Just a test message #3.`, - HTTPStatusCode: http.StatusNotFound, -}) - -func TestErrorsManagement(t *testing.T) { - var errs Errors - - errs = append(errs, ErrorCodeTest1) - errs = append(errs, ErrorCodeTest2.WithDetail( - map[string]interface{}{"digest": "sometestblobsumdoesntmatter"})) - errs = append(errs, ErrorCodeTest3.WithArgs("BOOGIE")) - errs = append(errs, ErrorCodeTest3.WithArgs("BOOGIE").WithDetail("data")) - - p, err := json.Marshal(errs) - - if err != nil { - t.Fatalf("error marashaling errors: %v", err) - } - - expectedJSON := `{"errors":[` + - `{"code":"TEST1","message":"test error 1"},` + - `{"code":"TEST2","message":"test error 2","detail":{"digest":"sometestblobsumdoesntmatter"}},` + - `{"code":"TEST3","message":"Sorry \"BOOGIE\" isn't valid"},` + - `{"code":"TEST3","message":"Sorry \"BOOGIE\" isn't valid","detail":"data"}` + - `]}` - - if string(p) != expectedJSON { - t.Fatalf("unexpected json:\ngot:\n%q\n\nexpected:\n%q", string(p), expectedJSON) - } - - // Now test the reverse - var unmarshaled Errors - if err := json.Unmarshal(p, &unmarshaled); err != nil { - t.Fatalf("unexpected error unmarshaling error envelope: %v", err) - } - - if !reflect.DeepEqual(unmarshaled, errs) { - t.Fatalf("errors not equal after round trip:\nunmarshaled:\n%#v\n\nerrs:\n%#v", unmarshaled, errs) - } - - // Test the arg substitution stuff - e1 := unmarshaled[3].(Error) - exp1 := `Sorry "BOOGIE" isn't valid` - if e1.Message != exp1 { - t.Fatalf("Wrong msg, got:\n%q\n\nexpected:\n%q", e1.Message, exp1) - } - - exp1 = "test3: " + exp1 - if e1.Error() != exp1 { - t.Fatalf("Error() didn't return the right string, got:%s\nexpected:%s", e1.Error(), exp1) - } - - // Test again with a single value this time - errs = Errors{ErrorCodeUnknown} - expectedJSON = "{\"errors\":[{\"code\":\"UNKNOWN\",\"message\":\"unknown error\"}]}" - p, err = json.Marshal(errs) - - if err != nil { - t.Fatalf("error marashaling errors: %v", err) - } - - if string(p) != expectedJSON { - t.Fatalf("unexpected json: %q != %q", string(p), expectedJSON) - } - - // Now test the reverse - unmarshaled = nil - if err := json.Unmarshal(p, &unmarshaled); err != nil { - t.Fatalf("unexpected error unmarshaling error envelope: %v", err) - } - - if !reflect.DeepEqual(unmarshaled, errs) { - t.Fatalf("errors not equal after round trip:\nunmarshaled:\n%#v\n\nerrs:\n%#v", unmarshaled, errs) - } - - // Verify that calling WithArgs() more than once does the right thing. - // Meaning creates a new Error and uses the ErrorCode Message - e1 = ErrorCodeTest3.WithArgs("test1") - e2 := e1.WithArgs("test2") - if &e1 == &e2 { - t.Fatalf("args: e2 and e1 should not be the same, but they are") - } - if e2.Message != `Sorry "test2" isn't valid` { - t.Fatalf("e2 had wrong message: %q", e2.Message) - } - - // Verify that calling WithDetail() more than once does the right thing. - // Meaning creates a new Error and overwrites the old detail field - e1 = ErrorCodeTest3.WithDetail("stuff1") - e2 = e1.WithDetail("stuff2") - if &e1 == &e2 { - t.Fatalf("detail: e2 and e1 should not be the same, but they are") - } - if e2.Detail != `stuff2` { - t.Fatalf("e2 had wrong detail: %q", e2.Detail) - } - -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/distribution/registry/api/errcode/handler.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/distribution/registry/api/errcode/handler.go deleted file mode 100644 index 49a64a86..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/distribution/registry/api/errcode/handler.go +++ /dev/null @@ -1,44 +0,0 @@ -package errcode - -import ( - "encoding/json" - "net/http" -) - -// ServeJSON attempts to serve the errcode in a JSON envelope. It marshals err -// and sets the content-type header to 'application/json'. It will handle -// ErrorCoder and Errors, and if necessary will create an envelope. -func ServeJSON(w http.ResponseWriter, err error) error { - w.Header().Set("Content-Type", "application/json; charset=utf-8") - var sc int - - switch errs := err.(type) { - case Errors: - if len(errs) < 1 { - break - } - - if err, ok := errs[0].(ErrorCoder); ok { - sc = err.ErrorCode().Descriptor().HTTPStatusCode - } - case ErrorCoder: - sc = errs.ErrorCode().Descriptor().HTTPStatusCode - err = Errors{err} // create an envelope. - default: - // We just have an unhandled error type, so just place in an envelope - // and move along. - err = Errors{err} - } - - if sc == 0 { - sc = http.StatusInternalServerError - } - - w.WriteHeader(sc) - - if err := json.NewEncoder(w).Encode(err); err != nil { - return err - } - - return nil -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/distribution/registry/api/errcode/register.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/distribution/registry/api/errcode/register.go deleted file mode 100644 index 01c34384..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/distribution/registry/api/errcode/register.go +++ /dev/null @@ -1,128 +0,0 @@ -package errcode - -import ( - "fmt" - "net/http" - "sort" - "sync" -) - -var ( - errorCodeToDescriptors = map[ErrorCode]ErrorDescriptor{} - idToDescriptors = map[string]ErrorDescriptor{} - groupToDescriptors = map[string][]ErrorDescriptor{} -) - -var ( - // ErrorCodeUnknown is a generic error that can be used as a last - // resort if there is no situation-specific error message that can be used - ErrorCodeUnknown = Register("errcode", ErrorDescriptor{ - Value: "UNKNOWN", - Message: "unknown error", - Description: `Generic error returned when the error does not have an - API classification.`, - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeUnsupported is returned when an operation is not supported. - ErrorCodeUnsupported = Register("errcode", ErrorDescriptor{ - Value: "UNSUPPORTED", - Message: "The operation is unsupported.", - Description: `The operation was unsupported due to a missing - implementation or invalid set of parameters.`, - HTTPStatusCode: http.StatusMethodNotAllowed, - }) - - // ErrorCodeUnauthorized is returned if a request requires - // authentication. - ErrorCodeUnauthorized = Register("errcode", ErrorDescriptor{ - Value: "UNAUTHORIZED", - Message: "authentication required", - Description: `The access controller was unable to authenticate - the client. Often this will be accompanied by a - Www-Authenticate HTTP response header indicating how to - authenticate.`, - HTTPStatusCode: http.StatusUnauthorized, - }) - - // ErrorCodeDenied is returned if a client does not have sufficient - // permission to perform an action. - ErrorCodeDenied = Register("errcode", ErrorDescriptor{ - Value: "DENIED", - Message: "requested access to the resource is denied", - Description: `The access controller denied access for the - operation on a resource.`, - HTTPStatusCode: http.StatusForbidden, - }) - - // ErrorCodeUnavailable provides a common error to report unavialability - // of a service or endpoint. - ErrorCodeUnavailable = Register("errcode", ErrorDescriptor{ - Value: "UNAVAILABLE", - Message: "service unavailable", - Description: "Returned when a service is not available", - HTTPStatusCode: http.StatusServiceUnavailable, - }) -) - -var nextCode = 1000 -var registerLock sync.Mutex - -// Register will make the passed-in error known to the environment and -// return a new ErrorCode -func Register(group string, descriptor ErrorDescriptor) ErrorCode { - registerLock.Lock() - defer registerLock.Unlock() - - descriptor.Code = ErrorCode(nextCode) - - if _, ok := idToDescriptors[descriptor.Value]; ok { - panic(fmt.Sprintf("ErrorValue %q is already registered", descriptor.Value)) - } - if _, ok := errorCodeToDescriptors[descriptor.Code]; ok { - panic(fmt.Sprintf("ErrorCode %v is already registered", descriptor.Code)) - } - - groupToDescriptors[group] = append(groupToDescriptors[group], descriptor) - errorCodeToDescriptors[descriptor.Code] = descriptor - idToDescriptors[descriptor.Value] = descriptor - - nextCode++ - return descriptor.Code -} - -type byValue []ErrorDescriptor - -func (a byValue) Len() int { return len(a) } -func (a byValue) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a byValue) Less(i, j int) bool { return a[i].Value < a[j].Value } - -// GetGroupNames returns the list of Error group names that are registered -func GetGroupNames() []string { - keys := []string{} - - for k := range groupToDescriptors { - keys = append(keys, k) - } - sort.Strings(keys) - return keys -} - -// GetErrorCodeGroup returns the named group of error descriptors -func GetErrorCodeGroup(name string) []ErrorDescriptor { - desc := groupToDescriptors[name] - sort.Sort(byValue(desc)) - return desc -} - -// GetErrorAllDescriptors returns a slice of all ErrorDescriptors that are -// registered, irrespective of what group they're in -func GetErrorAllDescriptors() []ErrorDescriptor { - result := []ErrorDescriptor{} - - for _, group := range GetGroupNames() { - result = append(result, GetErrorCodeGroup(group)...) - } - sort.Sort(byValue(result)) - return result -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors/README.md b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors/README.md deleted file mode 100644 index 81fa04cc..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors/README.md +++ /dev/null @@ -1,58 +0,0 @@ -Docker 'errors' package -======================= - -This package contains all of the error messages generated by the Docker -engine that might be exposed via the Docker engine's REST API. - -Each top-level engine package will have its own file in this directory -so that there's a clear grouping of errors, instead of just one big -file. The errors for each package are defined here instead of within -their respective package structure so that Docker CLI code that may need -to import these error definition files will not need to know or understand -the engine's package/directory structure. In other words, all they should -need to do is import `.../docker/errors` and they will automatically -pick up all Docker engine defined errors. This also gives the engine -developers the freedom to change the engine packaging structure (e.g. to -CRUD packages) without worrying about breaking existing clients. - -These errors are defined using the 'errcode' package. The `errcode` package -allows for each error to be typed and include all information necessary to -have further processing done on them if necessary. In particular, each error -includes: - -* Value - a unique string (in all caps) associated with this error. -Typically, this string is the same name as the variable name of the error -(w/o the `ErrorCode` text) but in all caps. - -* Message - the human readable sentence that will be displayed for this -error. It can contain '%s' substitutions that allows for the code generating -the error to specify values that will be inserted in the string prior to -being displayed to the end-user. The `WithArgs()` function can be used to -specify the insertion strings. Note, the evaluation of the strings will be -done at the time `WithArgs()` is called. - -* Description - additional human readable text to further explain the -circumstances of the error situation. - -* HTTPStatusCode - when the error is returned back to a CLI, this value -will be used to populate the HTTP status code. If not present the default -value will be `StatusInternalServerError`, 500. - -Not all errors generated within the engine's executable will be propagated -back to the engine's API layer. For example, it is expected that errors -generated by vendored code (under `docker/vendor`) and packaged code -(under `docker/pkg`) will be converted into errors defined by this package. - -When processing an errcode error, if you are looking for a particular -error then you can do something like: - -``` -import derr "github.com/docker/docker/errors" - -... - -err := someFunc() -if err.ErrorCode() == derr.ErrorCodeNoSuchContainer { - ... -} -``` diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors/builder.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors/builder.go deleted file mode 100644 index 07a33bbf..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors/builder.go +++ /dev/null @@ -1,93 +0,0 @@ -package errors - -// This file contains all of the errors that can be generated from the -// docker/builder component. - -import ( - "net/http" - - "github.com/fsouza/go-dockerclient/external/github.com/docker/distribution/registry/api/errcode" -) - -var ( - // ErrorCodeAtLeastOneArg is generated when the parser comes across a - // Dockerfile command that doesn't have any args. - ErrorCodeAtLeastOneArg = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "ATLEASTONEARG", - Message: "%s requires at least one argument", - Description: "The specified command requires at least one argument", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeExactlyOneArg is generated when the parser comes across a - // Dockerfile command that requires exactly one arg but got less/more. - ErrorCodeExactlyOneArg = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "EXACTLYONEARG", - Message: "%s requires exactly one argument", - Description: "The specified command requires exactly one argument", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeAtLeastTwoArgs is generated when the parser comes across a - // Dockerfile command that requires at least two args but got less. - ErrorCodeAtLeastTwoArgs = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "ATLEASTTWOARGS", - Message: "%s requires at least two arguments", - Description: "The specified command requires at least two arguments", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeTooManyArgs is generated when the parser comes across a - // Dockerfile command that has more args than it should - ErrorCodeTooManyArgs = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "TOOMANYARGS", - Message: "Bad input to %s, too many args", - Description: "The specified command was passed too many arguments", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeChainOnBuild is generated when the parser comes across a - // Dockerfile command that is trying to chain ONBUILD commands. - ErrorCodeChainOnBuild = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "CHAINONBUILD", - Message: "Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed", - Description: "ONBUILD Dockerfile commands aren't allow on ONBUILD commands", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeBadOnBuildCmd is generated when the parser comes across a - // an ONBUILD Dockerfile command with an invalid trigger/command. - ErrorCodeBadOnBuildCmd = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "BADONBUILDCMD", - Message: "%s isn't allowed as an ONBUILD trigger", - Description: "The specified ONBUILD command isn't allowed", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeMissingFrom is generated when the Dockerfile is missing - // a FROM command. - ErrorCodeMissingFrom = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "MISSINGFROM", - Message: "Please provide a source image with `from` prior to run", - Description: "The Dockerfile is missing a FROM command", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeNotOnWindows is generated when the specified Dockerfile - // command is not supported on Windows. - ErrorCodeNotOnWindows = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NOTONWINDOWS", - Message: "%s is not supported on Windows", - Description: "The specified Dockerfile command is not supported on Windows", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeVolumeEmpty is generated when the specified Volume string - // is empty. - ErrorCodeVolumeEmpty = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "VOLUMEEMPTY", - Message: "Volume specified can not be an empty string", - Description: "The specified volume can not be an empty string", - HTTPStatusCode: http.StatusInternalServerError, - }) -) diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors/daemon.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors/daemon.go deleted file mode 100644 index 29d077a9..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors/daemon.go +++ /dev/null @@ -1,925 +0,0 @@ -package errors - -// This file contains all of the errors that can be generated from the -// docker/daemon component. - -import ( - "net/http" - - "github.com/fsouza/go-dockerclient/external/github.com/docker/distribution/registry/api/errcode" -) - -var ( - // ErrorCodeNoSuchContainer is generated when we look for a container by - // name or ID and we can't find it. - ErrorCodeNoSuchContainer = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NOSUCHCONTAINER", - Message: "no such id: %s", - Description: "The specified container can not be found", - HTTPStatusCode: http.StatusNotFound, - }) - - // ErrorCodeUnregisteredContainer is generated when we try to load - // a storage driver for an unregistered container - ErrorCodeUnregisteredContainer = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "UNREGISTEREDCONTAINER", - Message: "Can't load storage driver for unregistered container %s", - Description: "An attempt was made to load the storage driver for a container that is not registered with the daemon", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeContainerBeingRemoved is generated when an attempt to start - // a container is made but its in the process of being removed, or is dead. - ErrorCodeContainerBeingRemoved = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "CONTAINERBEINGREMOVED", - Message: "Container is marked for removal and cannot be started.", - Description: "An attempt was made to start a container that is in the process of being deleted", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeUnpauseContainer is generated when we attempt to stop a - // container but its paused. - ErrorCodeUnpauseContainer = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "UNPAUSECONTAINER", - Message: "Container %s is paused. Unpause the container before stopping", - Description: "The specified container is paused, before it can be stopped it must be unpaused", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeAlreadyPaused is generated when we attempt to pause a - // container when its already paused. - ErrorCodeAlreadyPaused = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "ALREADYPAUSED", - Message: "Container %s is already paused", - Description: "The specified container is already in the paused state", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeNotPaused is generated when we attempt to unpause a - // container when its not paused. - ErrorCodeNotPaused = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NOTPAUSED", - Message: "Container %s is not paused", - Description: "The specified container can not be unpaused because it is not in a paused state", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeImageUnregContainer is generated when we attempt to get the - // image of an unknown/unregistered container. - ErrorCodeImageUnregContainer = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "IMAGEUNREGCONTAINER", - Message: "Can't get image of unregistered container", - Description: "An attempt to retrieve the image of a container was made but the container is not registered", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeEmptyID is generated when an ID is the emptry string. - ErrorCodeEmptyID = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "EMPTYID", - Message: "Invalid empty id", - Description: "An attempt was made to register a container but the container's ID can not be an empty string", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeLoggingFactory is generated when we could not load the - // log driver. - ErrorCodeLoggingFactory = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "LOGGINGFACTORY", - Message: "Failed to get logging factory: %v", - Description: "An attempt was made to register a container but the container's ID can not be an empty string", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeInitLogger is generated when we could not initialize - // the logging driver. - ErrorCodeInitLogger = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "INITLOGGER", - Message: "Failed to initialize logging driver: %v", - Description: "An error occurred while trying to initialize the logging driver", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeNotRunning is generated when we need to verify that - // a container is running, but its not. - ErrorCodeNotRunning = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NOTRUNNING", - Message: "Container %s is not running", - Description: "The specified action can not be taken due to the container not being in a running state", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeLinkNotRunning is generated when we try to link to a - // container that is not running. - ErrorCodeLinkNotRunning = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "LINKNOTRUNNING", - Message: "Cannot link to a non running container: %s AS %s", - Description: "An attempt was made to link to a container but the container is not in a running state", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeDeviceInfo is generated when there is an error while trying - // to get info about a custom device. - // container that is not running. - ErrorCodeDeviceInfo = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "DEVICEINFO", - Message: "error gathering device information while adding custom device %q: %s", - Description: "There was an error while trying to retrieve the information about a custom device", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeEmptyEndpoint is generated when the endpoint for a port - // map is nil. - ErrorCodeEmptyEndpoint = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "EMPTYENDPOINT", - Message: "invalid endpoint while building port map info", - Description: "The specified endpoint for the port mapping is empty", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeEmptyNetwork is generated when the networkSettings for a port - // map is nil. - ErrorCodeEmptyNetwork = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "EMPTYNETWORK", - Message: "invalid networksettings while building port map info", - Description: "The specified endpoint for the port mapping is empty", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeParsingPort is generated when there is an error parsing - // a "port" string. - ErrorCodeParsingPort = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "PARSINGPORT", - Message: "Error parsing Port value(%v):%v", - Description: "There was an error while trying to parse the specified 'port' value", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeNoSandbox is generated when we can't find the specified - // sandbox(network) by ID. - ErrorCodeNoSandbox = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NOSANDBOX", - Message: "error locating sandbox id %s: %v", - Description: "There was an error trying to located the specified networking sandbox", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeNetworkUpdate is generated when there is an error while - // trying update a network/sandbox config. - ErrorCodeNetworkUpdate = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NETWORKUPDATE", - Message: "Update network failed: %v", - Description: "There was an error trying to update the configuration information of the specified network sandbox", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeNetworkRefresh is generated when there is an error while - // trying refresh a network/sandbox config. - ErrorCodeNetworkRefresh = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NETWORKREFRESH", - Message: "Update network failed: Failure in refresh sandbox %s: %v", - Description: "There was an error trying to refresh the configuration information of the specified network sandbox", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeHostPort is generated when there was an error while trying - // to parse a "host/port" string. - ErrorCodeHostPort = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "HOSTPORT", - Message: "Error parsing HostPort value(%s):%v", - Description: "There was an error trying to parse the specified 'HostPort' value", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeNetworkConflict is generated when we try to publish a service - // in network mode. - ErrorCodeNetworkConflict = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NETWORKCONFLICT", - Message: "conflicting options: publishing a service and network mode", - Description: "It is not possible to publish a service when it is in network mode", - HTTPStatusCode: http.StatusConflict, - }) - - // ErrorCodeJoinInfo is generated when we failed to update a container's - // join info. - ErrorCodeJoinInfo = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "JOININFO", - Message: "Updating join info failed: %v", - Description: "There was an error during an attempt update a container's join information", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeIPCRunning is generated when we try to join a container's - // IPC but its not running. - ErrorCodeIPCRunning = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "IPCRUNNING", - Message: "cannot join IPC of a non running container: %s", - Description: "An attempt was made to join the IPC of a container, but the container is not running", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeNotADir is generated when we try to create a directory - // but the path isn't a dir. - ErrorCodeNotADir = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NOTADIR", - Message: "Cannot mkdir: %s is not a directory", - Description: "An attempt was made create a directory, but the location in which it is being created is not a directory", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeParseContainer is generated when the reference to a - // container doesn't include a ":" (another container). - ErrorCodeParseContainer = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "PARSECONTAINER", - Message: "no container specified to join network", - Description: "The specified reference to a container is missing a ':' as a separator between 'container' and 'name'/'id'", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeJoinSelf is generated when we try to network to ourselves. - ErrorCodeJoinSelf = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "JOINSELF", - Message: "cannot join own network", - Description: "An attempt was made to have a container join its own network", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeJoinRunning is generated when we try to network to ourselves. - ErrorCodeJoinRunning = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "JOINRUNNING", - Message: "cannot join network of a non running container: %s", - Description: "An attempt to join the network of a container, but that container isn't running", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeModeNotContainer is generated when we try to network to - // another container but the mode isn't 'container'. - ErrorCodeModeNotContainer = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "MODENOTCONTAINER", - Message: "network mode not set to container", - Description: "An attempt was made to connect to a container's network but the mode wasn't set to 'container'", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeRemovingVolume is generated when we try remove a mount - // point (volume) but fail. - ErrorCodeRemovingVolume = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "REMOVINGVOLUME", - Message: "Error removing volumes:\n%v", - Description: "There was an error while trying to remove the mount point (volume) of a container", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeInvalidNetworkMode is generated when an invalid network - // mode value is specified. - ErrorCodeInvalidNetworkMode = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "INVALIDNETWORKMODE", - Message: "invalid network mode: %s", - Description: "The specified networking mode is not valid", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeGetGraph is generated when there was an error while - // trying to find a graph/image. - ErrorCodeGetGraph = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "GETGRAPH", - Message: "Failed to graph.Get on ImageID %s - %s", - Description: "There was an error trying to retrieve the image for the specified image ID", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeGetLayer is generated when there was an error while - // trying to retrieve a particular layer of an image. - ErrorCodeGetLayer = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "GETLAYER", - Message: "Failed to get layer path from graphdriver %s for ImageID %s - %s", - Description: "There was an error trying to retrieve the layer of the specified image", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodePutLayer is generated when there was an error while - // trying to 'put' a particular layer of an image. - ErrorCodePutLayer = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "PUTLAYER", - Message: "Failed to put layer path from graphdriver %s for ImageID %s - %s", - Description: "There was an error trying to store a layer for the specified image", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeGetLayerMetadata is generated when there was an error while - // trying to retrieve the metadata of a layer of an image. - ErrorCodeGetLayerMetadata = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "GETLAYERMETADATA", - Message: "Failed to get layer metadata - %s", - Description: "There was an error trying to retrieve the metadata of a layer for the specified image", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeEmptyConfig is generated when the input config data - // is empty. - ErrorCodeEmptyConfig = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "EMPTYCONFIG", - Message: "Config cannot be empty in order to create a container", - Description: "While trying to create a container, the specified configuration information was empty", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeNoSuchImageHash is generated when we can't find the - // specified image by its hash - ErrorCodeNoSuchImageHash = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NOSUCHIMAGEHASH", - Message: "No such image: %s", - Description: "An attempt was made to find an image by its hash, but the lookup failed", - HTTPStatusCode: http.StatusNotFound, - }) - - // ErrorCodeNoSuchImageTag is generated when we can't find the - // specified image byt its name/tag. - ErrorCodeNoSuchImageTag = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NOSUCHIMAGETAG", - Message: "No such image: %s:%s", - Description: "An attempt was made to find an image by its name/tag, but the lookup failed", - HTTPStatusCode: http.StatusNotFound, - }) - - // ErrorCodeMountOverFile is generated when we try to mount a volume - // over an existing file (but not a dir). - ErrorCodeMountOverFile = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "MOUNTOVERFILE", - Message: "cannot mount volume over existing file, file exists %s", - Description: "An attempt was made to mount a volume at the same location as a pre-existing file", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeMountSetup is generated when we can't define a mount point - // due to the source and destination being undefined. - ErrorCodeMountSetup = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "MOUNTSETUP", - Message: "Unable to setup mount point, neither source nor volume defined", - Description: "An attempt was made to setup a mount point, but the source and destination are undefined", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeVolumeInvalidMode is generated when we the mode of a volume/bind - // mount is invalid. - ErrorCodeVolumeInvalidMode = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "VOLUMEINVALIDMODE", - Message: "invalid mode: %s", - Description: "An invalid 'mode' was specified", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeVolumeInvalid is generated when the format fo the - // volume specification isn't valid. - ErrorCodeVolumeInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "VOLUMEINVALID", - Message: "Invalid volume specification: %s", - Description: "An invalid 'volume' was specified in the mount request", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeVolumeAbs is generated when path to a volume isn't absolute. - ErrorCodeVolumeAbs = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "VOLUMEABS", - Message: "Invalid volume destination path: %s mount path must be absolute.", - Description: "An invalid 'destination' path was specified in the mount request, it must be an absolute path", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeVolumeName is generated when the name of named volume isn't valid. - ErrorCodeVolumeName = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "VOLUME_NAME_INVALID", - Message: "%s includes invalid characters for a local volume name, only %s are allowed", - Description: "The name of volume is invalid", - HTTPStatusCode: http.StatusBadRequest, - }) - - // ErrorCodeVolumeSlash is generated when destination path to a volume is / - ErrorCodeVolumeSlash = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "VOLUMESLASH", - Message: "Invalid specification: destination can't be '/' in '%s'", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeVolumeDestIsC is generated the destination is c: (Windows specific) - ErrorCodeVolumeDestIsC = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "VOLUMEDESTISC", - Message: "Destination drive letter in '%s' cannot be c:", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeVolumeDestIsCRoot is generated the destination path is c:\ (Windows specific) - ErrorCodeVolumeDestIsCRoot = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "VOLUMEDESTISCROOT", - Message: `Destination path in '%s' cannot be c:\`, - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeVolumeSourceNotFound is generated the source directory could not be found (Windows specific) - ErrorCodeVolumeSourceNotFound = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "VOLUMESOURCENOTFOUND", - Message: "Source directory '%s' could not be found: %v", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeVolumeSourceNotDirectory is generated the source is not a directory (Windows specific) - ErrorCodeVolumeSourceNotDirectory = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "VOLUMESOURCENOTDIRECTORY", - Message: "Source '%s' is not a directory", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeVolumeFromBlank is generated when path to a volume is blank. - ErrorCodeVolumeFromBlank = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "VOLUMEFROMBLANK", - Message: "malformed volumes-from specification: %s", - Description: "An invalid 'destination' path was specified in the mount request, it must not be blank", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeVolumeDup is generated when we try to mount two volumes - // to the same path. - ErrorCodeVolumeDup = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "VOLUMEDUP", - Message: "Duplicate bind mount %s", - Description: "An attempt was made to mount a volume but the specified destination location is already used in a previous mount", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeVolumeNoSourceForMount is generated when no source directory - // for a volume mount was found. (Windows specific) - ErrorCodeVolumeNoSourceForMount = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "VOLUMENOSOURCEFORMOUNT", - Message: "No source for mount name %q driver %q destination %s", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeVolumeNameReservedWord is generated when the name in a volume - // uses a reserved word for filenames. (Windows specific) - ErrorCodeVolumeNameReservedWord = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "VOLUMENAMERESERVEDWORD", - Message: "Volume name %q cannot be a reserved word for Windows filenames", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeCantUnpause is generated when there's an error while trying - // to unpause a container. - ErrorCodeCantUnpause = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "CANTUNPAUSE", - Message: "Cannot unpause container %s: %s", - Description: "An error occurred while trying to unpause the specified container", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodePSError is generated when trying to run 'ps'. - ErrorCodePSError = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "PSError", - Message: "Error running ps: %s", - Description: "There was an error trying to run the 'ps' command in the specified container", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeNoPID is generated when looking for the PID field in the - // ps output. - ErrorCodeNoPID = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NOPID", - Message: "Couldn't find PID field in ps output", - Description: "There was no 'PID' field in the output of the 'ps' command that was executed", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeBadPID is generated when we can't convert a PID to an int. - ErrorCodeBadPID = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "BADPID", - Message: "Unexpected pid '%s': %s", - Description: "While trying to parse the output of the 'ps' command, the 'PID' field was not an integer", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeNoTop is generated when we try to run 'top' but can't - // because we're on windows. - ErrorCodeNoTop = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NOTOP", - Message: "Top is not supported on Windows", - Description: "The 'top' command is not supported on Windows", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeStopped is generated when we try to stop a container - // that is already stopped. - ErrorCodeStopped = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "STOPPED", - Message: "Container already stopped", - Description: "An attempt was made to stop a container, but the container is already stopped", - HTTPStatusCode: http.StatusNotModified, - }) - - // ErrorCodeCantStop is generated when we try to stop a container - // but failed for some reason. - ErrorCodeCantStop = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "CANTSTOP", - Message: "Cannot stop container %s: %s\n", - Description: "An error occurred while tring to stop the specified container", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeBadCPUFields is generated when the number of CPU fields is - // less than 8. - ErrorCodeBadCPUFields = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "BADCPUFIELDS", - Message: "invalid number of cpu fields", - Description: "While reading the '/proc/stat' file, the number of 'cpu' fields is less than 8", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeBadCPUInt is generated the CPU field can't be parsed as an int. - ErrorCodeBadCPUInt = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "BADCPUINT", - Message: "Unable to convert value %s to int: %s", - Description: "While reading the '/proc/stat' file, the 'CPU' field could not be parsed as an integer", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeBadStatFormat is generated the output of the stat info - // isn't parseable. - ErrorCodeBadStatFormat = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "BADSTATFORMAT", - Message: "invalid stat format", - Description: "There was an error trying to parse the '/proc/stat' file", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeTimedOut is generated when a timer expires. - ErrorCodeTimedOut = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "TIMEDOUT", - Message: "Timed out: %v", - Description: "A timer expired", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeAlreadyRemoving is generated when we try to remove a - // container that is already being removed. - ErrorCodeAlreadyRemoving = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "ALREADYREMOVING", - Message: "Status is already RemovalInProgress", - Description: "An attempt to remove a container was made, but the container is already in the process of being removed", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeStartPaused is generated when we start a paused container. - ErrorCodeStartPaused = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "STARTPAUSED", - Message: "Cannot start a paused container, try unpause instead.", - Description: "An attempt to start a container was made, but the container is paused. Unpause it first", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeAlreadyStarted is generated when we try to start a container - // that is already running. - ErrorCodeAlreadyStarted = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "ALREADYSTARTED", - Message: "Container already started", - Description: "An attempt to start a container was made, but the container is already started", - HTTPStatusCode: http.StatusNotModified, - }) - - // ErrorCodeHostConfigStart is generated when a HostConfig is passed - // into the start command. - ErrorCodeHostConfigStart = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "HOSTCONFIGSTART", - Message: "Supplying a hostconfig on start is not supported. It should be supplied on create", - Description: "The 'start' command does not accept 'HostConfig' data, try using the 'create' command instead", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeCantStart is generated when an error occurred while - // trying to start a container. - ErrorCodeCantStart = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "CANTSTART", - Message: "Cannot start container %s: %s", - Description: "There was an error while trying to start a container", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeCantRestart is generated when an error occurred while - // trying to restart a container. - ErrorCodeCantRestart = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "CANTRESTART", - Message: "Cannot restart container %s: %s", - Description: "There was an error while trying to restart a container", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeEmptyRename is generated when one of the names on a - // rename is empty. - ErrorCodeEmptyRename = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "EMPTYRENAME", - Message: "Neither old nor new names may be empty", - Description: "An attempt was made to rename a container but either the old or new names were blank", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeRenameTaken is generated when we try to rename but the - // new name isn't available. - ErrorCodeRenameTaken = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "RENAMETAKEN", - Message: "Error when allocating new name: %s", - Description: "The new name specified on the 'rename' command is already being used", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeRenameDelete is generated when we try to rename but - // failed trying to delete the old container. - ErrorCodeRenameDelete = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "RENAMEDELETE", - Message: "Failed to delete container %q: %v", - Description: "There was an error trying to delete the specified container", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodePauseError is generated when we try to pause a container - // but failed. - ErrorCodePauseError = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "PAUSEERROR", - Message: "Cannot pause container %s: %s", - Description: "There was an error trying to pause the specified container", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeNeedStream is generated when we try to stream a container's - // logs but no output stream was specified. - ErrorCodeNeedStream = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NEEDSTREAM", - Message: "You must choose at least one stream", - Description: "While trying to stream a container's logs, no output stream was specified", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeDanglingOne is generated when we try to specify more than one - // 'dangling' specifier. - ErrorCodeDanglingOne = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "DANLGINGONE", - Message: "Conflict: cannot use more than 1 value for `dangling` filter", - Description: "The specified 'dangling' filter may not have more than one value", - HTTPStatusCode: http.StatusConflict, - }) - - // ErrorCodeImgDelUsed is generated when we try to delete an image - // but it is being used. - ErrorCodeImgDelUsed = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "IMGDELUSED", - Message: "conflict: unable to remove repository reference %q (must force) - container %s is using its referenced image %s", - Description: "An attempt was made to delete an image but it is currently being used", - HTTPStatusCode: http.StatusConflict, - }) - - // ErrorCodeImgNoParent is generated when we try to find an image's - // parent but its not in the graph. - ErrorCodeImgNoParent = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "IMGNOPARENT", - Message: "unable to get parent image: %v", - Description: "There was an error trying to find an image's parent, it was not in the graph", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeExportFailed is generated when an export fails. - ErrorCodeExportFailed = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "EXPORTFAILED", - Message: "%s: %s", - Description: "There was an error during an export operation", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeExecResize is generated when we try to resize an exec - // but its not running. - ErrorCodeExecResize = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "EXECRESIZE", - Message: "Exec %s is not running, so it can not be resized.", - Description: "An attempt was made to resize an 'exec', but the 'exec' is not running", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeContainerNotRunning is generated when we try to get the info - // on an exec but the container is not running. - ErrorCodeContainerNotRunning = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "CONTAINERNOTRUNNING", - Message: "Container %s is not running: %s", - Description: "An attempt was made to retrieve the information about an 'exec' but the container is not running", - HTTPStatusCode: http.StatusConflict, - }) - - // ErrorCodeNoExecID is generated when we try to get the info - // on an exec but it can't be found. - ErrorCodeNoExecID = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NOEXECID", - Message: "No such exec instance '%s' found in daemon", - Description: "The specified 'exec' instance could not be found", - HTTPStatusCode: http.StatusNotFound, - }) - - // ErrorCodeExecPaused is generated when we try to start an exec - // but the container is paused. - ErrorCodeExecPaused = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "EXECPAUSED", - Message: "Container %s is paused, unpause the container before exec", - Description: "An attempt to start an 'exec' was made, but the owning container is paused", - HTTPStatusCode: http.StatusConflict, - }) - - // ErrorCodeExecRunning is generated when we try to start an exec - // but its already running. - ErrorCodeExecRunning = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "EXECRUNNING", - Message: "Error: Exec command %s is already running", - Description: "An attempt to start an 'exec' was made, but 'exec' is already running", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeExecCantRun is generated when we try to start an exec - // but it failed for some reason. - ErrorCodeExecCantRun = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "EXECCANTRUN", - Message: "Cannot run exec command %s in container %s: %s", - Description: "An attempt to start an 'exec' was made, but an error occurred", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeExecAttach is generated when we try to attach to an exec - // but failed. - ErrorCodeExecAttach = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "EXECATTACH", - Message: "attach failed with error: %s", - Description: "There was an error while trying to attach to an 'exec'", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeExecContainerStopped is generated when we try to start - // an exec but then the container stopped. - ErrorCodeExecContainerStopped = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "EXECCONTAINERSTOPPED", - Message: "container stopped while running exec", - Description: "An attempt was made to start an 'exec' but the owning container is in the 'stopped' state", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeDefaultName is generated when we try to delete the - // default name of a container. - ErrorCodeDefaultName = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "DEFAULTNAME", - Message: "Conflict, cannot remove the default name of the container", - Description: "An attempt to delete the default name of a container was made, but that is not allowed", - HTTPStatusCode: http.StatusConflict, - }) - - // ErrorCodeNoParent is generated when we try to delete a container - // but we can't find its parent image. - ErrorCodeNoParent = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NOPARENT", - Message: "Cannot get parent %s for name %s", - Description: "An attempt was made to delete a container but its parent image could not be found", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeCantDestroy is generated when we try to delete a container - // but failed for some reason. - ErrorCodeCantDestroy = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "CANTDESTROY", - Message: "Cannot destroy container %s: %v", - Description: "An attempt was made to delete a container but it failed", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeRmRunning is generated when we try to delete a container - // but its still running. - ErrorCodeRmRunning = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "RMRUNNING", - Message: "Conflict, You cannot remove a running container. Stop the container before attempting removal or use -f", - Description: "An attempt was made to delete a container but the container is still running, try to either stop it first or use '-f'", - HTTPStatusCode: http.StatusConflict, - }) - - // ErrorCodeRmFailed is generated when we try to delete a container - // but it failed for some reason. - ErrorCodeRmFailed = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "RMFAILED", - Message: "Could not kill running container, cannot remove - %v", - Description: "An error occurred while trying to delete a running container", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeRmNotFound is generated when we try to delete a container - // but couldn't find it. - ErrorCodeRmNotFound = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "RMNOTFOUND", - Message: "Could not kill running container, cannot remove - %v", - Description: "An attempt to delete a container was made but the container could not be found", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeRmState is generated when we try to delete a container - // but couldn't set its state to RemovalInProgress. - ErrorCodeRmState = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "RMSTATE", - Message: "Failed to set container state to RemovalInProgress: %s", - Description: "An attempt to delete a container was made, but there as an error trying to set its state to 'RemovalInProgress'", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeRmDriverFS is generated when we try to delete a container - // but the driver failed to delete its filesystem. - ErrorCodeRmDriverFS = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "RMDRIVERFS", - Message: "Driver %s failed to remove root filesystem %s: %s", - Description: "While trying to delete a container, the driver failed to remove the root filesystem", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeRmInit is generated when we try to delete a container - // but failed deleting its init filesystem. - ErrorCodeRmInit = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "RMINIT", - Message: "Driver %s failed to remove init filesystem %s: %s", - Description: "While trying to delete a container, the driver failed to remove the init filesystem", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeRmFS is generated when we try to delete a container - // but failed deleting its filesystem. - ErrorCodeRmFS = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "RMFS", - Message: "Unable to remove filesystem for %v: %v", - Description: "While trying to delete a container, the driver failed to remove the filesystem", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeRmExecDriver is generated when we try to delete a container - // but failed deleting its exec driver data. - ErrorCodeRmExecDriver = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "RMEXECDRIVER", - Message: "Unable to remove execdriver data for %s: %s", - Description: "While trying to delete a container, there was an error trying to remove th exec driver data", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeRmVolumeInUse is generated when we try to delete a container - // but failed deleting a volume because its being used. - ErrorCodeRmVolumeInUse = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "RMVOLUMEINUSE", - Message: "Conflict: %v", - Description: "While trying to delete a container, one of its volumes is still being used", - HTTPStatusCode: http.StatusConflict, - }) - - // ErrorCodeRmVolume is generated when we try to delete a container - // but failed deleting a volume. - ErrorCodeRmVolume = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "RMVOLUME", - Message: "Error while removing volume %s: %v", - Description: "While trying to delete a container, there was an error trying to delete one of its volumes", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeInvalidCpusetCpus is generated when user provided cpuset CPUs - // are invalid. - ErrorCodeInvalidCpusetCpus = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "INVALIDCPUSETCPUS", - Message: "Invalid value %s for cpuset cpus.", - Description: "While verifying the container's 'HostConfig', CpusetCpus value was in an incorrect format", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeInvalidCpusetMems is generated when user provided cpuset mems - // are invalid. - ErrorCodeInvalidCpusetMems = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "INVALIDCPUSETMEMS", - Message: "Invalid value %s for cpuset mems.", - Description: "While verifying the container's 'HostConfig', CpusetMems value was in an incorrect format", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeNotAvailableCpusetCpus is generated when user provided cpuset - // CPUs aren't available in the container's cgroup. - ErrorCodeNotAvailableCpusetCpus = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NOTAVAILABLECPUSETCPUS", - Message: "Requested CPUs are not available - requested %s, available: %s.", - Description: "While verifying the container's 'HostConfig', cpuset CPUs provided aren't available in the container's cgroup available set", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeNotAvailableCpusetMems is generated when user provided cpuset - // memory nodes aren't available in the container's cgroup. - ErrorCodeNotAvailableCpusetMems = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NOTAVAILABLECPUSETMEMS", - Message: "Requested memory nodes are not available - requested %s, available: %s.", - Description: "While verifying the container's 'HostConfig', cpuset memory nodes provided aren't available in the container's cgroup available set", - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorVolumeNameTaken is generated when an error occurred while - // trying to create a volume that has existed using different driver. - ErrorVolumeNameTaken = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "VOLUME_NAME_TAKEN", - Message: "A volume name %s already exists with the %s driver. Choose a different volume name.", - Description: "An attempt to create a volume using a driver but the volume already exists with a different driver", - HTTPStatusCode: http.StatusInternalServerError, - }) -) diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors/error.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors/error.go deleted file mode 100644 index 37222d44..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors/error.go +++ /dev/null @@ -1,6 +0,0 @@ -package errors - -// This file contains all of the errors that can be generated from the -// docker engine but are not tied to any specific top-level component. - -const errGroup = "engine" diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors/image.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors/image.go deleted file mode 100644 index c104b1bb..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors/image.go +++ /dev/null @@ -1,20 +0,0 @@ -package errors - -// This file contains all of the errors that can be generated from the -// docker/image component. - -import ( - "net/http" - - "github.com/fsouza/go-dockerclient/external/github.com/docker/distribution/registry/api/errcode" -) - -var ( - // ErrorCodeInvalidImageID is generated when image id specified is incorrectly formatted. - ErrorCodeInvalidImageID = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "INVALIDIMAGEID", - Message: "image ID '%s' is invalid ", - Description: "The specified image id is incorrectly formatted", - HTTPStatusCode: http.StatusInternalServerError, - }) -) diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors/server.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors/server.go deleted file mode 100644 index 580b47f7..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors/server.go +++ /dev/null @@ -1,36 +0,0 @@ -package errors - -import ( - "net/http" - - "github.com/fsouza/go-dockerclient/external/github.com/docker/distribution/registry/api/errcode" -) - -var ( - // ErrorCodeNewerClientVersion is generated when a request from a client - // specifies a higher version than the server supports. - ErrorCodeNewerClientVersion = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NEWERCLIENTVERSION", - Message: "client is newer than server (client API version: %s, server API version: %s)", - Description: "The client version is higher than the server version", - HTTPStatusCode: http.StatusBadRequest, - }) - - // ErrorCodeOldClientVersion is generated when a request from a client - // specifies a version lower than the minimum version supported by the server. - ErrorCodeOldClientVersion = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "OLDCLIENTVERSION", - Message: "client version %s is too old. Minimum supported API version is %s, please upgrade your client to a newer version", - Description: "The client version is too old for the server", - HTTPStatusCode: http.StatusBadRequest, - }) - - // ErrorNetworkControllerNotEnabled is generated when the networking stack in not enabled - // for certain platforms, like windows. - ErrorNetworkControllerNotEnabled = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NETWORK_CONTROLLER_NOT_ENABLED", - Message: "the network controller is not enabled for this platform", - Description: "Docker's networking stack is disabled for this platform", - HTTPStatusCode: http.StatusNotFound, - }) -) diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/archive/testdata/broken.tar b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/archive/testdata/broken.tar deleted file mode 100644 index 8f10ea6b..00000000 Binary files a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/archive/testdata/broken.tar and /dev/null differ diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/longpath/longpath.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/longpath/longpath.go deleted file mode 100644 index 9b15bfff..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/longpath/longpath.go +++ /dev/null @@ -1,26 +0,0 @@ -// longpath introduces some constants and helper functions for handling long paths -// in Windows, which are expected to be prepended with `\\?\` and followed by either -// a drive letter, a UNC server\share, or a volume identifier. - -package longpath - -import ( - "strings" -) - -// Prefix is the longpath prefix for Windows file paths. -const Prefix = `\\?\` - -// AddPrefix will add the Windows long path prefix to the path provided if -// it does not already have it. -func AddPrefix(path string) string { - if !strings.HasPrefix(path, Prefix) { - if strings.HasPrefix(path, `\\`) { - // This is a UNC path, so we need to add 'UNC' to the path as well. - path = Prefix + `UNC` + path[1:] - } else { - path = Prefix + path - } - } - return path -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/longpath/longpath_test.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/longpath/longpath_test.go deleted file mode 100644 index 01865eff..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/longpath/longpath_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package longpath - -import ( - "strings" - "testing" -) - -func TestStandardLongPath(t *testing.T) { - c := `C:\simple\path` - longC := AddPrefix(c) - if !strings.EqualFold(longC, `\\?\C:\simple\path`) { - t.Errorf("Wrong long path returned. Original = %s ; Long = %s", c, longC) - } -} - -func TestUNCLongPath(t *testing.T) { - c := `\\server\share\path` - longC := AddPrefix(c) - if !strings.EqualFold(longC, `\\?\UNC\server\share\path`) { - t.Errorf("Wrong UNC long path returned. Original = %s ; Long = %s", c, longC) - } -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/mflag/LICENSE b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/mflag/LICENSE deleted file mode 100644 index ac74d8f0..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/mflag/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2014-2015 The Docker & Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/mflag/README.md b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/mflag/README.md deleted file mode 100644 index da00efa3..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/mflag/README.md +++ /dev/null @@ -1,40 +0,0 @@ -Package mflag (aka multiple-flag) implements command-line flag parsing. -It's an **hacky** fork of the [official golang package](http://golang.org/pkg/flag/) - -It adds: - -* both short and long flag version -`./example -s red` `./example --string blue` - -* multiple names for the same option -``` -$>./example -h -Usage of example: - -s, --string="": a simple string -``` - -___ -It is very flexible on purpose, so you can do things like: -``` -$>./example -h -Usage of example: - -s, -string, --string="": a simple string -``` - -Or: -``` -$>./example -h -Usage of example: - -oldflag, --newflag="": a simple string -``` - -You can also hide some flags from the usage, so if we want only `--newflag`: -``` -$>./example -h -Usage of example: - --newflag="": a simple string -$>./example -oldflag str -str -``` - -See [example.go](example/example.go) for more details. diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/mflag/flag.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/mflag/flag.go deleted file mode 100644 index ebfa3501..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/mflag/flag.go +++ /dev/null @@ -1,1201 +0,0 @@ -// Copyright 2014-2015 The Docker & 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 mflag implements command-line flag parsing. -// -// Usage: -// -// Define flags using flag.String(), Bool(), Int(), etc. -// -// This declares an integer flag, -f or --flagname, stored in the pointer ip, with type *int. -// import "flag /github.com/docker/docker/pkg/mflag" -// var ip = flag.Int([]string{"f", "-flagname"}, 1234, "help message for flagname") -// If you like, you can bind the flag to a variable using the Var() functions. -// var flagvar int -// func init() { -// // -flaghidden will work, but will be hidden from the usage -// flag.IntVar(&flagvar, []string{"f", "#flaghidden", "-flagname"}, 1234, "help message for flagname") -// } -// Or you can create custom flags that satisfy the Value interface (with -// pointer receivers) and couple them to flag parsing by -// flag.Var(&flagVal, []string{"name"}, "help message for flagname") -// For such flags, the default value is just the initial value of the variable. -// -// You can also add "deprecated" flags, they are still usable, but are not shown -// in the usage and will display a warning when you try to use them. `#` before -// an option means this option is deprecated, if there is an following option -// without `#` ahead, then that's the replacement, if not, it will just be removed: -// var ip = flag.Int([]string{"#f", "#flagname", "-flagname"}, 1234, "help message for flagname") -// this will display: `Warning: '-f' is deprecated, it will be replaced by '--flagname' soon. See usage.` or -// this will display: `Warning: '-flagname' is deprecated, it will be replaced by '--flagname' soon. See usage.` -// var ip = flag.Int([]string{"f", "#flagname"}, 1234, "help message for flagname") -// will display: `Warning: '-flagname' is deprecated, it will be removed soon. See usage.` -// so you can only use `-f`. -// -// You can also group one letter flags, bif you declare -// var v = flag.Bool([]string{"v", "-verbose"}, false, "help message for verbose") -// var s = flag.Bool([]string{"s", "-slow"}, false, "help message for slow") -// you will be able to use the -vs or -sv -// -// After all flags are defined, call -// flag.Parse() -// to parse the command line into the defined flags. -// -// Flags may then be used directly. If you're using the flags themselves, -// they are all pointers; if you bind to variables, they're values. -// fmt.Println("ip has value ", *ip) -// fmt.Println("flagvar has value ", flagvar) -// -// After parsing, the arguments after the flag are available as the -// slice flag.Args() or individually as flag.Arg(i). -// The arguments are indexed from 0 through flag.NArg()-1. -// -// Command line flag syntax: -// -flag -// -flag=x -// -flag="x" -// -flag='x' -// -flag x // non-boolean flags only -// One or two minus signs may be used; they are equivalent. -// The last form is not permitted for boolean flags because the -// meaning of the command -// cmd -x * -// will change if there is a file called 0, false, etc. You must -// use the -flag=false form to turn off a boolean flag. -// -// Flag parsing stops just before the first non-flag argument -// ("-" is a non-flag argument) or after the terminator "--". -// -// Integer flags accept 1234, 0664, 0x1234 and may be negative. -// Boolean flags may be 1, 0, t, f, true, false, TRUE, FALSE, True, False. -// Duration flags accept any input valid for time.ParseDuration. -// -// The default set of command-line flags is controlled by -// top-level functions. The FlagSet type allows one to define -// independent sets of flags, such as to implement subcommands -// in a command-line interface. The methods of FlagSet are -// analogous to the top-level functions for the command-line -// flag set. - -package mflag - -import ( - "errors" - "fmt" - "io" - "os" - "runtime" - "sort" - "strconv" - "strings" - "text/tabwriter" - "time" - - "github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/homedir" -) - -// ErrHelp is the error returned if the flag -help is invoked but no such flag is defined. -var ErrHelp = errors.New("flag: help requested") - -// ErrRetry is the error returned if you need to try letter by letter -var ErrRetry = errors.New("flag: retry") - -// -- bool Value -type boolValue bool - -func newBoolValue(val bool, p *bool) *boolValue { - *p = val - return (*boolValue)(p) -} - -func (b *boolValue) Set(s string) error { - v, err := strconv.ParseBool(s) - *b = boolValue(v) - return err -} - -func (b *boolValue) Get() interface{} { return bool(*b) } - -func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) } - -func (b *boolValue) IsBoolFlag() bool { return true } - -// optional interface to indicate boolean flags that can be -// supplied without "=value" text -type boolFlag interface { - Value - IsBoolFlag() bool -} - -// -- int Value -type intValue int - -func newIntValue(val int, p *int) *intValue { - *p = val - return (*intValue)(p) -} - -func (i *intValue) Set(s string) error { - v, err := strconv.ParseInt(s, 0, 64) - *i = intValue(v) - return err -} - -func (i *intValue) Get() interface{} { return int(*i) } - -func (i *intValue) String() string { return fmt.Sprintf("%v", *i) } - -// -- int64 Value -type int64Value int64 - -func newInt64Value(val int64, p *int64) *int64Value { - *p = val - return (*int64Value)(p) -} - -func (i *int64Value) Set(s string) error { - v, err := strconv.ParseInt(s, 0, 64) - *i = int64Value(v) - return err -} - -func (i *int64Value) Get() interface{} { return int64(*i) } - -func (i *int64Value) String() string { return fmt.Sprintf("%v", *i) } - -// -- uint Value -type uintValue uint - -func newUintValue(val uint, p *uint) *uintValue { - *p = val - return (*uintValue)(p) -} - -func (i *uintValue) Set(s string) error { - v, err := strconv.ParseUint(s, 0, 64) - *i = uintValue(v) - return err -} - -func (i *uintValue) Get() interface{} { return uint(*i) } - -func (i *uintValue) String() string { return fmt.Sprintf("%v", *i) } - -// -- uint64 Value -type uint64Value uint64 - -func newUint64Value(val uint64, p *uint64) *uint64Value { - *p = val - return (*uint64Value)(p) -} - -func (i *uint64Value) Set(s string) error { - v, err := strconv.ParseUint(s, 0, 64) - *i = uint64Value(v) - return err -} - -func (i *uint64Value) Get() interface{} { return uint64(*i) } - -func (i *uint64Value) String() string { return fmt.Sprintf("%v", *i) } - -// -- string Value -type stringValue string - -func newStringValue(val string, p *string) *stringValue { - *p = val - return (*stringValue)(p) -} - -func (s *stringValue) Set(val string) error { - *s = stringValue(val) - return nil -} - -func (s *stringValue) Get() interface{} { return string(*s) } - -func (s *stringValue) String() string { return fmt.Sprintf("%s", *s) } - -// -- float64 Value -type float64Value float64 - -func newFloat64Value(val float64, p *float64) *float64Value { - *p = val - return (*float64Value)(p) -} - -func (f *float64Value) Set(s string) error { - v, err := strconv.ParseFloat(s, 64) - *f = float64Value(v) - return err -} - -func (f *float64Value) Get() interface{} { return float64(*f) } - -func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) } - -// -- time.Duration Value -type durationValue time.Duration - -func newDurationValue(val time.Duration, p *time.Duration) *durationValue { - *p = val - return (*durationValue)(p) -} - -func (d *durationValue) Set(s string) error { - v, err := time.ParseDuration(s) - *d = durationValue(v) - return err -} - -func (d *durationValue) Get() interface{} { return time.Duration(*d) } - -func (d *durationValue) String() string { return (*time.Duration)(d).String() } - -// Value is the interface to the dynamic value stored in a flag. -// (The default value is represented as a string.) -// -// If a Value has an IsBoolFlag() bool method returning true, -// the command-line parser makes -name equivalent to -name=true -// rather than using the next command-line argument. -type Value interface { - String() string - Set(string) error -} - -// Getter is an interface that allows the contents of a Value to be retrieved. -// It wraps the Value interface, rather than being part of it, because it -// appeared after Go 1 and its compatibility rules. All Value types provided -// by this package satisfy the Getter interface. -type Getter interface { - Value - Get() interface{} -} - -// ErrorHandling defines how to handle flag parsing errors. -type ErrorHandling int - -// ErrorHandling strategies available when a flag parsing error occurs -const ( - ContinueOnError ErrorHandling = iota - ExitOnError - PanicOnError -) - -// A FlagSet represents a set of defined flags. The zero value of a FlagSet -// has no name and has ContinueOnError error handling. -type FlagSet struct { - // Usage is the function called when an error occurs while parsing flags. - // The field is a function (not a method) that may be changed to point to - // a custom error handler. - Usage func() - ShortUsage func() - - name string - parsed bool - actual map[string]*Flag - formal map[string]*Flag - args []string // arguments after flags - errorHandling ErrorHandling - output io.Writer // nil means stderr; use Out() accessor - nArgRequirements []nArgRequirement -} - -// A Flag represents the state of a flag. -type Flag struct { - Names []string // name as it appears on command line - Usage string // help message - Value Value // value as set - DefValue string // default value (as text); for usage message -} - -type flagSlice []string - -func (p flagSlice) Len() int { return len(p) } -func (p flagSlice) Less(i, j int) bool { - pi, pj := strings.TrimPrefix(p[i], "-"), strings.TrimPrefix(p[j], "-") - lpi, lpj := strings.ToLower(pi), strings.ToLower(pj) - if lpi != lpj { - return lpi < lpj - } - return pi < pj -} -func (p flagSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } - -// sortFlags returns the flags as a slice in lexicographical sorted order. -func sortFlags(flags map[string]*Flag) []*Flag { - var list flagSlice - - // The sorted list is based on the first name, when flag map might use the other names. - nameMap := make(map[string]string) - - for n, f := range flags { - fName := strings.TrimPrefix(f.Names[0], "#") - nameMap[fName] = n - if len(f.Names) == 1 { - list = append(list, fName) - continue - } - - found := false - for _, name := range list { - if name == fName { - found = true - break - } - } - if !found { - list = append(list, fName) - } - } - sort.Sort(list) - result := make([]*Flag, len(list)) - for i, name := range list { - result[i] = flags[nameMap[name]] - } - return result -} - -// Name returns the name of the FlagSet. -func (fs *FlagSet) Name() string { - return fs.name -} - -// Out returns the destination for usage and error messages. -func (fs *FlagSet) Out() io.Writer { - if fs.output == nil { - return os.Stderr - } - return fs.output -} - -// SetOutput sets the destination for usage and error messages. -// If output is nil, os.Stderr is used. -func (fs *FlagSet) SetOutput(output io.Writer) { - fs.output = output -} - -// VisitAll visits the flags in lexicographical order, calling fn for each. -// It visits all flags, even those not set. -func (fs *FlagSet) VisitAll(fn func(*Flag)) { - for _, flag := range sortFlags(fs.formal) { - fn(flag) - } -} - -// VisitAll visits the command-line flags in lexicographical order, calling -// fn for each. It visits all flags, even those not set. -func VisitAll(fn func(*Flag)) { - CommandLine.VisitAll(fn) -} - -// Visit visits the flags in lexicographical order, calling fn for each. -// It visits only those flags that have been set. -func (fs *FlagSet) Visit(fn func(*Flag)) { - for _, flag := range sortFlags(fs.actual) { - fn(flag) - } -} - -// Visit visits the command-line flags in lexicographical order, calling fn -// for each. It visits only those flags that have been set. -func Visit(fn func(*Flag)) { - CommandLine.Visit(fn) -} - -// Lookup returns the Flag structure of the named flag, returning nil if none exists. -func (fs *FlagSet) Lookup(name string) *Flag { - return fs.formal[name] -} - -// IsSet indicates whether the specified flag is set in the given FlagSet -func (fs *FlagSet) IsSet(name string) bool { - return fs.actual[name] != nil -} - -// Lookup returns the Flag structure of the named command-line flag, -// returning nil if none exists. -func Lookup(name string) *Flag { - return CommandLine.formal[name] -} - -// IsSet indicates whether the specified flag was specified at all on the cmd line. -func IsSet(name string) bool { - return CommandLine.IsSet(name) -} - -type nArgRequirementType int - -// Indicator used to pass to BadArgs function -const ( - Exact nArgRequirementType = iota - Max - Min -) - -type nArgRequirement struct { - Type nArgRequirementType - N int -} - -// Require adds a requirement about the number of arguments for the FlagSet. -// The first parameter can be Exact, Max, or Min to respectively specify the exact, -// the maximum, or the minimal number of arguments required. -// The actual check is done in FlagSet.CheckArgs(). -func (fs *FlagSet) Require(nArgRequirementType nArgRequirementType, nArg int) { - fs.nArgRequirements = append(fs.nArgRequirements, nArgRequirement{nArgRequirementType, nArg}) -} - -// CheckArgs uses the requirements set by FlagSet.Require() to validate -// the number of arguments. If the requirements are not met, -// an error message string is returned. -func (fs *FlagSet) CheckArgs() (message string) { - for _, req := range fs.nArgRequirements { - var arguments string - if req.N == 1 { - arguments = "1 argument" - } else { - arguments = fmt.Sprintf("%d arguments", req.N) - } - - str := func(kind string) string { - return fmt.Sprintf("%q requires %s%s", fs.name, kind, arguments) - } - - switch req.Type { - case Exact: - if fs.NArg() != req.N { - return str("") - } - case Max: - if fs.NArg() > req.N { - return str("a maximum of ") - } - case Min: - if fs.NArg() < req.N { - return str("a minimum of ") - } - } - } - return "" -} - -// Set sets the value of the named flag. -func (fs *FlagSet) Set(name, value string) error { - flag, ok := fs.formal[name] - if !ok { - return fmt.Errorf("no such flag -%v", name) - } - if err := flag.Value.Set(value); err != nil { - return err - } - if fs.actual == nil { - fs.actual = make(map[string]*Flag) - } - fs.actual[name] = flag - return nil -} - -// Set sets the value of the named command-line flag. -func Set(name, value string) error { - return CommandLine.Set(name, value) -} - -// PrintDefaults prints, to standard error unless configured -// otherwise, the default values of all defined flags in the set. -func (fs *FlagSet) PrintDefaults() { - writer := tabwriter.NewWriter(fs.Out(), 20, 1, 3, ' ', 0) - home := homedir.Get() - - // Don't substitute when HOME is / - if runtime.GOOS != "windows" && home == "/" { - home = "" - } - - // Add a blank line between cmd description and list of options - if fs.FlagCount() > 0 { - fmt.Fprintln(writer, "") - } - - fs.VisitAll(func(flag *Flag) { - format := " -%s=%s" - names := []string{} - for _, name := range flag.Names { - if name[0] != '#' { - names = append(names, name) - } - } - if len(names) > 0 && len(flag.Usage) > 0 { - val := flag.DefValue - - if home != "" && strings.HasPrefix(val, home) { - val = homedir.GetShortcutString() + val[len(home):] - } - - fmt.Fprintf(writer, format, strings.Join(names, ", -"), val) - for i, line := range strings.Split(flag.Usage, "\n") { - if i != 0 { - line = " " + line - } - fmt.Fprintln(writer, "\t", line) - } - } - }) - writer.Flush() -} - -// PrintDefaults prints to standard error the default values of all defined command-line flags. -func PrintDefaults() { - CommandLine.PrintDefaults() -} - -// defaultUsage is the default function to print a usage message. -func defaultUsage(fs *FlagSet) { - if fs.name == "" { - fmt.Fprintf(fs.Out(), "Usage:\n") - } else { - fmt.Fprintf(fs.Out(), "Usage of %s:\n", fs.name) - } - fs.PrintDefaults() -} - -// NOTE: Usage is not just defaultUsage(CommandLine) -// because it serves (via godoc flag Usage) as the example -// for how to write your own usage function. - -// Usage prints to standard error a usage message documenting all defined command-line flags. -// The function is a variable that may be changed to point to a custom function. -var Usage = func() { - fmt.Fprintf(CommandLine.Out(), "Usage of %s:\n", os.Args[0]) - PrintDefaults() -} - -// Usage prints to standard error a usage message documenting the standard command layout -// The function is a variable that may be changed to point to a custom function. -var ShortUsage = func() { - fmt.Fprintf(CommandLine.output, "Usage of %s:\n", os.Args[0]) -} - -// FlagCount returns the number of flags that have been defined. -func (fs *FlagSet) FlagCount() int { return len(sortFlags(fs.formal)) } - -// FlagCountUndeprecated returns the number of undeprecated flags that have been defined. -func (fs *FlagSet) FlagCountUndeprecated() int { - count := 0 - for _, flag := range sortFlags(fs.formal) { - for _, name := range flag.Names { - if name[0] != '#' { - count++ - break - } - } - } - return count -} - -// NFlag returns the number of flags that have been set. -func (fs *FlagSet) NFlag() int { return len(fs.actual) } - -// NFlag returns the number of command-line flags that have been set. -func NFlag() int { return len(CommandLine.actual) } - -// Arg returns the i'th argument. Arg(0) is the first remaining argument -// after flags have been processed. -func (fs *FlagSet) Arg(i int) string { - if i < 0 || i >= len(fs.args) { - return "" - } - return fs.args[i] -} - -// Arg returns the i'th command-line argument. Arg(0) is the first remaining argument -// after flags have been processed. -func Arg(i int) string { - return CommandLine.Arg(i) -} - -// NArg is the number of arguments remaining after flags have been processed. -func (fs *FlagSet) NArg() int { return len(fs.args) } - -// NArg is the number of arguments remaining after flags have been processed. -func NArg() int { return len(CommandLine.args) } - -// Args returns the non-flag arguments. -func (fs *FlagSet) Args() []string { return fs.args } - -// Args returns the non-flag command-line arguments. -func Args() []string { return CommandLine.args } - -// BoolVar defines a bool flag with specified name, default value, and usage string. -// The argument p points to a bool variable in which to store the value of the flag. -func (fs *FlagSet) BoolVar(p *bool, names []string, value bool, usage string) { - fs.Var(newBoolValue(value, p), names, usage) -} - -// BoolVar defines a bool flag with specified name, default value, and usage string. -// The argument p points to a bool variable in which to store the value of the flag. -func BoolVar(p *bool, names []string, value bool, usage string) { - CommandLine.Var(newBoolValue(value, p), names, usage) -} - -// Bool defines a bool flag with specified name, default value, and usage string. -// The return value is the address of a bool variable that stores the value of the flag. -func (fs *FlagSet) Bool(names []string, value bool, usage string) *bool { - p := new(bool) - fs.BoolVar(p, names, value, usage) - return p -} - -// Bool defines a bool flag with specified name, default value, and usage string. -// The return value is the address of a bool variable that stores the value of the flag. -func Bool(names []string, value bool, usage string) *bool { - return CommandLine.Bool(names, value, usage) -} - -// IntVar defines an int flag with specified name, default value, and usage string. -// The argument p points to an int variable in which to store the value of the flag. -func (fs *FlagSet) IntVar(p *int, names []string, value int, usage string) { - fs.Var(newIntValue(value, p), names, usage) -} - -// IntVar defines an int flag with specified name, default value, and usage string. -// The argument p points to an int variable in which to store the value of the flag. -func IntVar(p *int, names []string, value int, usage string) { - CommandLine.Var(newIntValue(value, p), names, usage) -} - -// Int defines an int flag with specified name, default value, and usage string. -// The return value is the address of an int variable that stores the value of the flag. -func (fs *FlagSet) Int(names []string, value int, usage string) *int { - p := new(int) - fs.IntVar(p, names, value, usage) - return p -} - -// Int defines an int flag with specified name, default value, and usage string. -// The return value is the address of an int variable that stores the value of the flag. -func Int(names []string, value int, usage string) *int { - return CommandLine.Int(names, value, usage) -} - -// Int64Var defines an int64 flag with specified name, default value, and usage string. -// The argument p points to an int64 variable in which to store the value of the flag. -func (fs *FlagSet) Int64Var(p *int64, names []string, value int64, usage string) { - fs.Var(newInt64Value(value, p), names, usage) -} - -// Int64Var defines an int64 flag with specified name, default value, and usage string. -// The argument p points to an int64 variable in which to store the value of the flag. -func Int64Var(p *int64, names []string, value int64, usage string) { - CommandLine.Var(newInt64Value(value, p), names, usage) -} - -// Int64 defines an int64 flag with specified name, default value, and usage string. -// The return value is the address of an int64 variable that stores the value of the flag. -func (fs *FlagSet) Int64(names []string, value int64, usage string) *int64 { - p := new(int64) - fs.Int64Var(p, names, value, usage) - return p -} - -// Int64 defines an int64 flag with specified name, default value, and usage string. -// The return value is the address of an int64 variable that stores the value of the flag. -func Int64(names []string, value int64, usage string) *int64 { - return CommandLine.Int64(names, value, usage) -} - -// UintVar defines a uint flag with specified name, default value, and usage string. -// The argument p points to a uint variable in which to store the value of the flag. -func (fs *FlagSet) UintVar(p *uint, names []string, value uint, usage string) { - fs.Var(newUintValue(value, p), names, usage) -} - -// UintVar defines a uint flag with specified name, default value, and usage string. -// The argument p points to a uint variable in which to store the value of the flag. -func UintVar(p *uint, names []string, value uint, usage string) { - CommandLine.Var(newUintValue(value, p), names, usage) -} - -// Uint defines a uint flag with specified name, default value, and usage string. -// The return value is the address of a uint variable that stores the value of the flag. -func (fs *FlagSet) Uint(names []string, value uint, usage string) *uint { - p := new(uint) - fs.UintVar(p, names, value, usage) - return p -} - -// Uint defines a uint flag with specified name, default value, and usage string. -// The return value is the address of a uint variable that stores the value of the flag. -func Uint(names []string, value uint, usage string) *uint { - return CommandLine.Uint(names, value, usage) -} - -// Uint64Var defines a uint64 flag with specified name, default value, and usage string. -// The argument p points to a uint64 variable in which to store the value of the flag. -func (fs *FlagSet) Uint64Var(p *uint64, names []string, value uint64, usage string) { - fs.Var(newUint64Value(value, p), names, usage) -} - -// Uint64Var defines a uint64 flag with specified name, default value, and usage string. -// The argument p points to a uint64 variable in which to store the value of the flag. -func Uint64Var(p *uint64, names []string, value uint64, usage string) { - CommandLine.Var(newUint64Value(value, p), names, usage) -} - -// Uint64 defines a uint64 flag with specified name, default value, and usage string. -// The return value is the address of a uint64 variable that stores the value of the flag. -func (fs *FlagSet) Uint64(names []string, value uint64, usage string) *uint64 { - p := new(uint64) - fs.Uint64Var(p, names, value, usage) - return p -} - -// Uint64 defines a uint64 flag with specified name, default value, and usage string. -// The return value is the address of a uint64 variable that stores the value of the flag. -func Uint64(names []string, value uint64, usage string) *uint64 { - return CommandLine.Uint64(names, value, usage) -} - -// StringVar defines a string flag with specified name, default value, and usage string. -// The argument p points to a string variable in which to store the value of the flag. -func (fs *FlagSet) StringVar(p *string, names []string, value string, usage string) { - fs.Var(newStringValue(value, p), names, usage) -} - -// StringVar defines a string flag with specified name, default value, and usage string. -// The argument p points to a string variable in which to store the value of the flag. -func StringVar(p *string, names []string, value string, usage string) { - CommandLine.Var(newStringValue(value, p), names, usage) -} - -// String defines a string flag with specified name, default value, and usage string. -// The return value is the address of a string variable that stores the value of the flag. -func (fs *FlagSet) String(names []string, value string, usage string) *string { - p := new(string) - fs.StringVar(p, names, value, usage) - return p -} - -// String defines a string flag with specified name, default value, and usage string. -// The return value is the address of a string variable that stores the value of the flag. -func String(names []string, value string, usage string) *string { - return CommandLine.String(names, value, usage) -} - -// Float64Var defines a float64 flag with specified name, default value, and usage string. -// The argument p points to a float64 variable in which to store the value of the flag. -func (fs *FlagSet) Float64Var(p *float64, names []string, value float64, usage string) { - fs.Var(newFloat64Value(value, p), names, usage) -} - -// Float64Var defines a float64 flag with specified name, default value, and usage string. -// The argument p points to a float64 variable in which to store the value of the flag. -func Float64Var(p *float64, names []string, value float64, usage string) { - CommandLine.Var(newFloat64Value(value, p), names, usage) -} - -// Float64 defines a float64 flag with specified name, default value, and usage string. -// The return value is the address of a float64 variable that stores the value of the flag. -func (fs *FlagSet) Float64(names []string, value float64, usage string) *float64 { - p := new(float64) - fs.Float64Var(p, names, value, usage) - return p -} - -// Float64 defines a float64 flag with specified name, default value, and usage string. -// The return value is the address of a float64 variable that stores the value of the flag. -func Float64(names []string, value float64, usage string) *float64 { - return CommandLine.Float64(names, value, usage) -} - -// DurationVar defines a time.Duration flag with specified name, default value, and usage string. -// The argument p points to a time.Duration variable in which to store the value of the flag. -func (fs *FlagSet) DurationVar(p *time.Duration, names []string, value time.Duration, usage string) { - fs.Var(newDurationValue(value, p), names, usage) -} - -// DurationVar defines a time.Duration flag with specified name, default value, and usage string. -// The argument p points to a time.Duration variable in which to store the value of the flag. -func DurationVar(p *time.Duration, names []string, value time.Duration, usage string) { - CommandLine.Var(newDurationValue(value, p), names, usage) -} - -// Duration defines a time.Duration flag with specified name, default value, and usage string. -// The return value is the address of a time.Duration variable that stores the value of the flag. -func (fs *FlagSet) Duration(names []string, value time.Duration, usage string) *time.Duration { - p := new(time.Duration) - fs.DurationVar(p, names, value, usage) - return p -} - -// Duration defines a time.Duration flag with specified name, default value, and usage string. -// The return value is the address of a time.Duration variable that stores the value of the flag. -func Duration(names []string, value time.Duration, usage string) *time.Duration { - return CommandLine.Duration(names, value, usage) -} - -// Var defines a flag with the specified name and usage string. The type and -// value of the flag are represented by the first argument, of type Value, which -// typically holds a user-defined implementation of Value. For instance, the -// caller could create a flag that turns a comma-separated string into a slice -// of strings by giving the slice the methods of Value; in particular, Set would -// decompose the comma-separated string into the slice. -func (fs *FlagSet) Var(value Value, names []string, usage string) { - // Remember the default value as a string; it won't change. - flag := &Flag{names, usage, value, value.String()} - for _, name := range names { - name = strings.TrimPrefix(name, "#") - _, alreadythere := fs.formal[name] - if alreadythere { - var msg string - if fs.name == "" { - msg = fmt.Sprintf("flag redefined: %s", name) - } else { - msg = fmt.Sprintf("%s flag redefined: %s", fs.name, name) - } - fmt.Fprintln(fs.Out(), msg) - panic(msg) // Happens only if flags are declared with identical names - } - if fs.formal == nil { - fs.formal = make(map[string]*Flag) - } - fs.formal[name] = flag - } -} - -// Var defines a flag with the specified name and usage string. The type and -// value of the flag are represented by the first argument, of type Value, which -// typically holds a user-defined implementation of Value. For instance, the -// caller could create a flag that turns a comma-separated string into a slice -// of strings by giving the slice the methods of Value; in particular, Set would -// decompose the comma-separated string into the slice. -func Var(value Value, names []string, usage string) { - CommandLine.Var(value, names, usage) -} - -// failf prints to standard error a formatted error and usage message and -// returns the error. -func (fs *FlagSet) failf(format string, a ...interface{}) error { - err := fmt.Errorf(format, a...) - fmt.Fprintln(fs.Out(), err) - if os.Args[0] == fs.name { - fmt.Fprintf(fs.Out(), "See '%s --help'.\n", os.Args[0]) - } else { - fmt.Fprintf(fs.Out(), "See '%s %s --help'.\n", os.Args[0], fs.name) - } - return err -} - -// usage calls the Usage method for the flag set, or the usage function if -// the flag set is CommandLine. -func (fs *FlagSet) usage() { - if fs == CommandLine { - Usage() - } else if fs.Usage == nil { - defaultUsage(fs) - } else { - fs.Usage() - } -} - -func trimQuotes(str string) string { - if len(str) == 0 { - return str - } - type quote struct { - start, end byte - } - - // All valid quote types. - quotes := []quote{ - // Double quotes - { - start: '"', - end: '"', - }, - - // Single quotes - { - start: '\'', - end: '\'', - }, - } - - for _, quote := range quotes { - // Only strip if outermost match. - if str[0] == quote.start && str[len(str)-1] == quote.end { - str = str[1 : len(str)-1] - break - } - } - - return str -} - -// parseOne parses one flag. It reports whether a flag was seen. -func (fs *FlagSet) parseOne() (bool, string, error) { - if len(fs.args) == 0 { - return false, "", nil - } - s := fs.args[0] - if len(s) == 0 || s[0] != '-' || len(s) == 1 { - return false, "", nil - } - if s[1] == '-' && len(s) == 2 { // "--" terminates the flags - fs.args = fs.args[1:] - return false, "", nil - } - name := s[1:] - if len(name) == 0 || name[0] == '=' { - return false, "", fs.failf("bad flag syntax: %s", s) - } - - // it's a flag. does it have an argument? - fs.args = fs.args[1:] - hasValue := false - value := "" - if i := strings.Index(name, "="); i != -1 { - value = trimQuotes(name[i+1:]) - hasValue = true - name = name[:i] - } - - m := fs.formal - flag, alreadythere := m[name] // BUG - if !alreadythere { - if name == "-help" || name == "help" || name == "h" { // special case for nice help message. - fs.usage() - return false, "", ErrHelp - } - if len(name) > 0 && name[0] == '-' { - return false, "", fs.failf("flag provided but not defined: -%s", name) - } - return false, name, ErrRetry - } - if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg - if hasValue { - if err := fv.Set(value); err != nil { - return false, "", fs.failf("invalid boolean value %q for -%s: %v", value, name, err) - } - } else { - fv.Set("true") - } - } else { - // It must have a value, which might be the next argument. - if !hasValue && len(fs.args) > 0 { - // value is the next arg - hasValue = true - value, fs.args = fs.args[0], fs.args[1:] - } - if !hasValue { - return false, "", fs.failf("flag needs an argument: -%s", name) - } - if err := flag.Value.Set(value); err != nil { - return false, "", fs.failf("invalid value %q for flag -%s: %v", value, name, err) - } - } - if fs.actual == nil { - fs.actual = make(map[string]*Flag) - } - fs.actual[name] = flag - for i, n := range flag.Names { - if n == fmt.Sprintf("#%s", name) { - replacement := "" - for j := i; j < len(flag.Names); j++ { - if flag.Names[j][0] != '#' { - replacement = flag.Names[j] - break - } - } - if replacement != "" { - fmt.Fprintf(fs.Out(), "Warning: '-%s' is deprecated, it will be replaced by '-%s' soon. See usage.\n", name, replacement) - } else { - fmt.Fprintf(fs.Out(), "Warning: '-%s' is deprecated, it will be removed soon. See usage.\n", name) - } - } - } - return true, "", nil -} - -// Parse parses flag definitions from the argument list, which should not -// include the command name. Must be called after all flags in the FlagSet -// are defined and before flags are accessed by the program. -// The return value will be ErrHelp if -help was set but not defined. -func (fs *FlagSet) Parse(arguments []string) error { - fs.parsed = true - fs.args = arguments - for { - seen, name, err := fs.parseOne() - if seen { - continue - } - if err == nil { - break - } - if err == ErrRetry { - if len(name) > 1 { - err = nil - for _, letter := range strings.Split(name, "") { - fs.args = append([]string{"-" + letter}, fs.args...) - seen2, _, err2 := fs.parseOne() - if seen2 { - continue - } - if err2 != nil { - err = fs.failf("flag provided but not defined: -%s", name) - break - } - } - if err == nil { - continue - } - } else { - err = fs.failf("flag provided but not defined: -%s", name) - } - } - switch fs.errorHandling { - case ContinueOnError: - return err - case ExitOnError: - os.Exit(2) - case PanicOnError: - panic(err) - } - } - return nil -} - -// ParseFlags is a utility function that adds a help flag if withHelp is true, -// calls fs.Parse(args) and prints a relevant error message if there are -// incorrect number of arguments. It returns error only if error handling is -// set to ContinueOnError and parsing fails. If error handling is set to -// ExitOnError, it's safe to ignore the return value. -func (fs *FlagSet) ParseFlags(args []string, withHelp bool) error { - var help *bool - if withHelp { - help = fs.Bool([]string{"#help", "-help"}, false, "Print usage") - } - if err := fs.Parse(args); err != nil { - return err - } - if help != nil && *help { - fs.SetOutput(os.Stdout) - fs.Usage() - os.Exit(0) - } - if str := fs.CheckArgs(); str != "" { - fs.SetOutput(os.Stderr) - fs.ReportError(str, withHelp) - fs.ShortUsage() - os.Exit(1) - } - return nil -} - -// ReportError is a utility method that prints a user-friendly message -// containing the error that occured during parsing and a suggestion to get help -func (fs *FlagSet) ReportError(str string, withHelp bool) { - if withHelp { - if os.Args[0] == fs.Name() { - str += ".\nSee '" + os.Args[0] + " --help'" - } else { - str += ".\nSee '" + os.Args[0] + " " + fs.Name() + " --help'" - } - } - fmt.Fprintf(fs.Out(), "docker: %s.\n", str) -} - -// Parsed reports whether fs.Parse has been called. -func (fs *FlagSet) Parsed() bool { - return fs.parsed -} - -// Parse parses the command-line flags from os.Args[1:]. Must be called -// after all flags are defined and before flags are accessed by the program. -func Parse() { - // Ignore errors; CommandLine is set for ExitOnError. - CommandLine.Parse(os.Args[1:]) -} - -// Parsed returns true if the command-line flags have been parsed. -func Parsed() bool { - return CommandLine.Parsed() -} - -// CommandLine is the default set of command-line flags, parsed from os.Args. -// The top-level functions such as BoolVar, Arg, and on are wrappers for the -// methods of CommandLine. -var CommandLine = NewFlagSet(os.Args[0], ExitOnError) - -// NewFlagSet returns a new, empty flag set with the specified name and -// error handling property. -func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet { - f := &FlagSet{ - name: name, - errorHandling: errorHandling, - } - return f -} - -// Init sets the name and error handling property for a flag set. -// By default, the zero FlagSet uses an empty name and the -// ContinueOnError error handling policy. -func (fs *FlagSet) Init(name string, errorHandling ErrorHandling) { - fs.name = name - fs.errorHandling = errorHandling -} - -type mergeVal struct { - Value - key string - fset *FlagSet -} - -func (v mergeVal) Set(s string) error { - return v.fset.Set(v.key, s) -} - -func (v mergeVal) IsBoolFlag() bool { - if b, ok := v.Value.(boolFlag); ok { - return b.IsBoolFlag() - } - return false -} - -// Merge is an helper function that merges n FlagSets into a single dest FlagSet -// In case of name collision between the flagsets it will apply -// the destination FlagSet's errorHandling behaviour. -func Merge(dest *FlagSet, flagsets ...*FlagSet) error { - for _, fset := range flagsets { - for k, f := range fset.formal { - if _, ok := dest.formal[k]; ok { - var err error - if fset.name == "" { - err = fmt.Errorf("flag redefined: %s", k) - } else { - err = fmt.Errorf("%s flag redefined: %s", fset.name, k) - } - fmt.Fprintln(fset.Out(), err.Error()) - // Happens only if flags are declared with identical names - switch dest.errorHandling { - case ContinueOnError: - return err - case ExitOnError: - os.Exit(2) - case PanicOnError: - panic(err) - } - } - newF := *f - newF.Value = mergeVal{f.Value, k, fset} - dest.formal[k] = &newF - } - } - return nil -} - -// IsEmpty reports if the FlagSet is actually empty. -func (fs *FlagSet) IsEmpty() bool { - return len(fs.actual) == 0 -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/mflag/flag_test.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/mflag/flag_test.go deleted file mode 100644 index 85f32c8a..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/mflag/flag_test.go +++ /dev/null @@ -1,516 +0,0 @@ -// Copyright 2014-2015 The Docker & 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 mflag - -import ( - "bytes" - "fmt" - "os" - "sort" - "strings" - "testing" - "time" -) - -// ResetForTesting clears all flag state and sets the usage function as directed. -// After calling ResetForTesting, parse errors in flag handling will not -// exit the program. -func ResetForTesting(usage func()) { - CommandLine = NewFlagSet(os.Args[0], ContinueOnError) - Usage = usage -} -func boolString(s string) string { - if s == "0" { - return "false" - } - return "true" -} - -func TestEverything(t *testing.T) { - ResetForTesting(nil) - Bool([]string{"test_bool"}, false, "bool value") - Int([]string{"test_int"}, 0, "int value") - Int64([]string{"test_int64"}, 0, "int64 value") - Uint([]string{"test_uint"}, 0, "uint value") - Uint64([]string{"test_uint64"}, 0, "uint64 value") - String([]string{"test_string"}, "0", "string value") - Float64([]string{"test_float64"}, 0, "float64 value") - Duration([]string{"test_duration"}, 0, "time.Duration value") - - m := make(map[string]*Flag) - desired := "0" - visitor := func(f *Flag) { - for _, name := range f.Names { - if len(name) > 5 && name[0:5] == "test_" { - m[name] = f - ok := false - switch { - case f.Value.String() == desired: - ok = true - case name == "test_bool" && f.Value.String() == boolString(desired): - ok = true - case name == "test_duration" && f.Value.String() == desired+"s": - ok = true - } - if !ok { - t.Error("Visit: bad value", f.Value.String(), "for", name) - } - } - } - } - VisitAll(visitor) - if len(m) != 8 { - t.Error("VisitAll misses some flags") - for k, v := range m { - t.Log(k, *v) - } - } - m = make(map[string]*Flag) - Visit(visitor) - if len(m) != 0 { - t.Errorf("Visit sees unset flags") - for k, v := range m { - t.Log(k, *v) - } - } - // Now set all flags - Set("test_bool", "true") - Set("test_int", "1") - Set("test_int64", "1") - Set("test_uint", "1") - Set("test_uint64", "1") - Set("test_string", "1") - Set("test_float64", "1") - Set("test_duration", "1s") - desired = "1" - Visit(visitor) - if len(m) != 8 { - t.Error("Visit fails after set") - for k, v := range m { - t.Log(k, *v) - } - } - // Now test they're visited in sort order. - var flagNames []string - Visit(func(f *Flag) { - for _, name := range f.Names { - flagNames = append(flagNames, name) - } - }) - if !sort.StringsAreSorted(flagNames) { - t.Errorf("flag names not sorted: %v", flagNames) - } -} - -func TestGet(t *testing.T) { - ResetForTesting(nil) - Bool([]string{"test_bool"}, true, "bool value") - Int([]string{"test_int"}, 1, "int value") - Int64([]string{"test_int64"}, 2, "int64 value") - Uint([]string{"test_uint"}, 3, "uint value") - Uint64([]string{"test_uint64"}, 4, "uint64 value") - String([]string{"test_string"}, "5", "string value") - Float64([]string{"test_float64"}, 6, "float64 value") - Duration([]string{"test_duration"}, 7, "time.Duration value") - - visitor := func(f *Flag) { - for _, name := range f.Names { - if len(name) > 5 && name[0:5] == "test_" { - g, ok := f.Value.(Getter) - if !ok { - t.Errorf("Visit: value does not satisfy Getter: %T", f.Value) - return - } - switch name { - case "test_bool": - ok = g.Get() == true - case "test_int": - ok = g.Get() == int(1) - case "test_int64": - ok = g.Get() == int64(2) - case "test_uint": - ok = g.Get() == uint(3) - case "test_uint64": - ok = g.Get() == uint64(4) - case "test_string": - ok = g.Get() == "5" - case "test_float64": - ok = g.Get() == float64(6) - case "test_duration": - ok = g.Get() == time.Duration(7) - } - if !ok { - t.Errorf("Visit: bad value %T(%v) for %s", g.Get(), g.Get(), name) - } - } - } - } - VisitAll(visitor) -} - -func testParse(f *FlagSet, t *testing.T) { - if f.Parsed() { - t.Error("f.Parse() = true before Parse") - } - boolFlag := f.Bool([]string{"bool"}, false, "bool value") - bool2Flag := f.Bool([]string{"bool2"}, false, "bool2 value") - f.Bool([]string{"bool3"}, false, "bool3 value") - bool4Flag := f.Bool([]string{"bool4"}, false, "bool4 value") - intFlag := f.Int([]string{"-int"}, 0, "int value") - int64Flag := f.Int64([]string{"-int64"}, 0, "int64 value") - uintFlag := f.Uint([]string{"uint"}, 0, "uint value") - uint64Flag := f.Uint64([]string{"-uint64"}, 0, "uint64 value") - stringFlag := f.String([]string{"string"}, "0", "string value") - f.String([]string{"string2"}, "0", "string2 value") - singleQuoteFlag := f.String([]string{"squote"}, "", "single quoted value") - doubleQuoteFlag := f.String([]string{"dquote"}, "", "double quoted value") - mixedQuoteFlag := f.String([]string{"mquote"}, "", "mixed quoted value") - mixed2QuoteFlag := f.String([]string{"mquote2"}, "", "mixed2 quoted value") - nestedQuoteFlag := f.String([]string{"nquote"}, "", "nested quoted value") - nested2QuoteFlag := f.String([]string{"nquote2"}, "", "nested2 quoted value") - float64Flag := f.Float64([]string{"float64"}, 0, "float64 value") - durationFlag := f.Duration([]string{"duration"}, 5*time.Second, "time.Duration value") - extra := "one-extra-argument" - args := []string{ - "-bool", - "-bool2=true", - "-bool4=false", - "--int", "22", - "--int64", "0x23", - "-uint", "24", - "--uint64", "25", - "-string", "hello", - "-squote='single'", - `-dquote="double"`, - `-mquote='mixed"`, - `-mquote2="mixed2'`, - `-nquote="'single nested'"`, - `-nquote2='"double nested"'`, - "-float64", "2718e28", - "-duration", "2m", - extra, - } - if err := f.Parse(args); err != nil { - t.Fatal(err) - } - if !f.Parsed() { - t.Error("f.Parse() = false after Parse") - } - if *boolFlag != true { - t.Error("bool flag should be true, is ", *boolFlag) - } - if *bool2Flag != true { - t.Error("bool2 flag should be true, is ", *bool2Flag) - } - if !f.IsSet("bool2") { - t.Error("bool2 should be marked as set") - } - if f.IsSet("bool3") { - t.Error("bool3 should not be marked as set") - } - if !f.IsSet("bool4") { - t.Error("bool4 should be marked as set") - } - if *bool4Flag != false { - t.Error("bool4 flag should be false, is ", *bool4Flag) - } - if *intFlag != 22 { - t.Error("int flag should be 22, is ", *intFlag) - } - if *int64Flag != 0x23 { - t.Error("int64 flag should be 0x23, is ", *int64Flag) - } - if *uintFlag != 24 { - t.Error("uint flag should be 24, is ", *uintFlag) - } - if *uint64Flag != 25 { - t.Error("uint64 flag should be 25, is ", *uint64Flag) - } - if *stringFlag != "hello" { - t.Error("string flag should be `hello`, is ", *stringFlag) - } - if !f.IsSet("string") { - t.Error("string flag should be marked as set") - } - if f.IsSet("string2") { - t.Error("string2 flag should not be marked as set") - } - if *singleQuoteFlag != "single" { - t.Error("single quote string flag should be `single`, is ", *singleQuoteFlag) - } - if *doubleQuoteFlag != "double" { - t.Error("double quote string flag should be `double`, is ", *doubleQuoteFlag) - } - if *mixedQuoteFlag != `'mixed"` { - t.Error("mixed quote string flag should be `'mixed\"`, is ", *mixedQuoteFlag) - } - if *mixed2QuoteFlag != `"mixed2'` { - t.Error("mixed2 quote string flag should be `\"mixed2'`, is ", *mixed2QuoteFlag) - } - if *nestedQuoteFlag != "'single nested'" { - t.Error("nested quote string flag should be `'single nested'`, is ", *nestedQuoteFlag) - } - if *nested2QuoteFlag != `"double nested"` { - t.Error("double quote string flag should be `\"double nested\"`, is ", *nested2QuoteFlag) - } - if *float64Flag != 2718e28 { - t.Error("float64 flag should be 2718e28, is ", *float64Flag) - } - if *durationFlag != 2*time.Minute { - t.Error("duration flag should be 2m, is ", *durationFlag) - } - if len(f.Args()) != 1 { - t.Error("expected one argument, got", len(f.Args())) - } else if f.Args()[0] != extra { - t.Errorf("expected argument %q got %q", extra, f.Args()[0]) - } -} - -func testPanic(f *FlagSet, t *testing.T) { - f.Int([]string{"-int"}, 0, "int value") - if f.Parsed() { - t.Error("f.Parse() = true before Parse") - } - args := []string{ - "-int", "21", - } - f.Parse(args) -} - -func TestParsePanic(t *testing.T) { - ResetForTesting(func() {}) - testPanic(CommandLine, t) -} - -func TestParse(t *testing.T) { - ResetForTesting(func() { t.Error("bad parse") }) - testParse(CommandLine, t) -} - -func TestFlagSetParse(t *testing.T) { - testParse(NewFlagSet("test", ContinueOnError), t) -} - -// Declare a user-defined flag type. -type flagVar []string - -func (f *flagVar) String() string { - return fmt.Sprint([]string(*f)) -} - -func (f *flagVar) Set(value string) error { - *f = append(*f, value) - return nil -} - -func TestUserDefined(t *testing.T) { - var flags FlagSet - flags.Init("test", ContinueOnError) - var v flagVar - flags.Var(&v, []string{"v"}, "usage") - if err := flags.Parse([]string{"-v", "1", "-v", "2", "-v=3"}); err != nil { - t.Error(err) - } - if len(v) != 3 { - t.Fatal("expected 3 args; got ", len(v)) - } - expect := "[1 2 3]" - if v.String() != expect { - t.Errorf("expected value %q got %q", expect, v.String()) - } -} - -// Declare a user-defined boolean flag type. -type boolFlagVar struct { - count int -} - -func (b *boolFlagVar) String() string { - return fmt.Sprintf("%d", b.count) -} - -func (b *boolFlagVar) Set(value string) error { - if value == "true" { - b.count++ - } - return nil -} - -func (b *boolFlagVar) IsBoolFlag() bool { - return b.count < 4 -} - -func TestUserDefinedBool(t *testing.T) { - var flags FlagSet - flags.Init("test", ContinueOnError) - var b boolFlagVar - var err error - flags.Var(&b, []string{"b"}, "usage") - if err = flags.Parse([]string{"-b", "-b", "-b", "-b=true", "-b=false", "-b", "barg", "-b"}); err != nil { - if b.count < 4 { - t.Error(err) - } - } - - if b.count != 4 { - t.Errorf("want: %d; got: %d", 4, b.count) - } - - if err == nil { - t.Error("expected error; got none") - } -} - -func TestSetOutput(t *testing.T) { - var flags FlagSet - var buf bytes.Buffer - flags.SetOutput(&buf) - flags.Init("test", ContinueOnError) - flags.Parse([]string{"-unknown"}) - if out := buf.String(); !strings.Contains(out, "-unknown") { - t.Logf("expected output mentioning unknown; got %q", out) - } -} - -// This tests that one can reset the flags. This still works but not well, and is -// superseded by FlagSet. -func TestChangingArgs(t *testing.T) { - ResetForTesting(func() { t.Fatal("bad parse") }) - oldArgs := os.Args - defer func() { os.Args = oldArgs }() - os.Args = []string{"cmd", "-before", "subcmd", "-after", "args"} - before := Bool([]string{"before"}, false, "") - if err := CommandLine.Parse(os.Args[1:]); err != nil { - t.Fatal(err) - } - cmd := Arg(0) - os.Args = Args() - after := Bool([]string{"after"}, false, "") - Parse() - args := Args() - - if !*before || cmd != "subcmd" || !*after || len(args) != 1 || args[0] != "args" { - t.Fatalf("expected true subcmd true [args] got %v %v %v %v", *before, cmd, *after, args) - } -} - -// Test that -help invokes the usage message and returns ErrHelp. -func TestHelp(t *testing.T) { - var helpCalled = false - fs := NewFlagSet("help test", ContinueOnError) - fs.Usage = func() { helpCalled = true } - var flag bool - fs.BoolVar(&flag, []string{"flag"}, false, "regular flag") - // Regular flag invocation should work - err := fs.Parse([]string{"-flag=true"}) - if err != nil { - t.Fatal("expected no error; got ", err) - } - if !flag { - t.Error("flag was not set by -flag") - } - if helpCalled { - t.Error("help called for regular flag") - helpCalled = false // reset for next test - } - // Help flag should work as expected. - err = fs.Parse([]string{"-help"}) - if err == nil { - t.Fatal("error expected") - } - if err != ErrHelp { - t.Fatal("expected ErrHelp; got ", err) - } - if !helpCalled { - t.Fatal("help was not called") - } - // If we define a help flag, that should override. - var help bool - fs.BoolVar(&help, []string{"help"}, false, "help flag") - helpCalled = false - err = fs.Parse([]string{"-help"}) - if err != nil { - t.Fatal("expected no error for defined -help; got ", err) - } - if helpCalled { - t.Fatal("help was called; should not have been for defined help flag") - } -} - -// Test the flag count functions. -func TestFlagCounts(t *testing.T) { - fs := NewFlagSet("help test", ContinueOnError) - var flag bool - fs.BoolVar(&flag, []string{"flag1"}, false, "regular flag") - fs.BoolVar(&flag, []string{"#deprecated1"}, false, "regular flag") - fs.BoolVar(&flag, []string{"f", "flag2"}, false, "regular flag") - fs.BoolVar(&flag, []string{"#d", "#deprecated2"}, false, "regular flag") - fs.BoolVar(&flag, []string{"flag3"}, false, "regular flag") - fs.BoolVar(&flag, []string{"g", "#flag4", "-flag4"}, false, "regular flag") - - if fs.FlagCount() != 6 { - t.Fatal("FlagCount wrong. ", fs.FlagCount()) - } - if fs.FlagCountUndeprecated() != 4 { - t.Fatal("FlagCountUndeprecated wrong. ", fs.FlagCountUndeprecated()) - } - if fs.NFlag() != 0 { - t.Fatal("NFlag wrong. ", fs.NFlag()) - } - err := fs.Parse([]string{"-fd", "-g", "-flag4"}) - if err != nil { - t.Fatal("expected no error for defined -help; got ", err) - } - if fs.NFlag() != 4 { - t.Fatal("NFlag wrong. ", fs.NFlag()) - } -} - -// Show up bug in sortFlags -func TestSortFlags(t *testing.T) { - fs := NewFlagSet("help TestSortFlags", ContinueOnError) - - var err error - - var b bool - fs.BoolVar(&b, []string{"b", "-banana"}, false, "usage") - - err = fs.Parse([]string{"--banana=true"}) - if err != nil { - t.Fatal("expected no error; got ", err) - } - - count := 0 - - fs.VisitAll(func(flag *Flag) { - count++ - if flag == nil { - t.Fatal("VisitAll should not return a nil flag") - } - }) - flagcount := fs.FlagCount() - if flagcount != count { - t.Fatalf("FlagCount (%d) != number (%d) of elements visited", flagcount, count) - } - // Make sure its idempotent - if flagcount != fs.FlagCount() { - t.Fatalf("FlagCount (%d) != fs.FlagCount() (%d) of elements visited", flagcount, fs.FlagCount()) - } - - count = 0 - fs.Visit(func(flag *Flag) { - count++ - if flag == nil { - t.Fatal("Visit should not return a nil flag") - } - }) - nflag := fs.NFlag() - if nflag != count { - t.Fatalf("NFlag (%d) != number (%d) of elements visited", nflag, count) - } - if nflag != fs.NFlag() { - t.Fatalf("NFlag (%d) != fs.NFlag() (%d) of elements visited", nflag, fs.NFlag()) - } -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/volume/volume.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/volume/volume.go deleted file mode 100644 index d986207c..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/volume/volume.go +++ /dev/null @@ -1,172 +0,0 @@ -package volume - -import ( - "os" - "runtime" - "strings" - - "github.com/fsouza/go-dockerclient/external/github.com/Sirupsen/logrus" - derr "github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors" - "github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/system" -) - -// DefaultDriverName is the driver name used for the driver -// implemented in the local package. -const DefaultDriverName string = "local" - -// Driver is for creating and removing volumes. -type Driver interface { - // Name returns the name of the volume driver. - Name() string - // Create makes a new volume with the given id. - Create(name string, opts map[string]string) (Volume, error) - // Remove deletes the volume. - Remove(Volume) error -} - -// Volume is a place to store data. It is backed by a specific driver, and can be mounted. -type Volume interface { - // Name returns the name of the volume - Name() string - // DriverName returns the name of the driver which owns this volume. - DriverName() string - // Path returns the absolute path to the volume. - Path() string - // Mount mounts the volume and returns the absolute path to - // where it can be consumed. - Mount() (string, error) - // Unmount unmounts the volume when it is no longer in use. - Unmount() error -} - -// MountPoint is the intersection point between a volume and a container. It -// specifies which volume is to be used and where inside a container it should -// be mounted. -type MountPoint struct { - Source string // Container host directory - Destination string // Inside the container - RW bool // True if writable - Name string // Name set by user - Driver string // Volume driver to use - Volume Volume `json:"-"` - - // Note Mode is not used on Windows - Mode string `json:"Relabel"` // Originally field was `Relabel`" -} - -// Setup sets up a mount point by either mounting the volume if it is -// configured, or creating the source directory if supplied. -func (m *MountPoint) Setup() (string, error) { - if m.Volume != nil { - return m.Volume.Mount() - } - if len(m.Source) > 0 { - if _, err := os.Stat(m.Source); err != nil { - if !os.IsNotExist(err) { - return "", err - } - if runtime.GOOS != "windows" { // Windows does not have deprecation issues here - logrus.Warnf("Auto-creating non-existant volume host path %s, this is deprecated and will be removed soon", m.Source) - if err := system.MkdirAll(m.Source, 0755); err != nil { - return "", err - } - } - } - return m.Source, nil - } - return "", derr.ErrorCodeMountSetup -} - -// Path returns the path of a volume in a mount point. -func (m *MountPoint) Path() string { - if m.Volume != nil { - return m.Volume.Path() - } - return m.Source -} - -// ValidMountMode will make sure the mount mode is valid. -// returns if it's a valid mount mode or not. -func ValidMountMode(mode string) bool { - return roModes[strings.ToLower(mode)] || rwModes[strings.ToLower(mode)] -} - -// ReadWrite tells you if a mode string is a valid read-write mode or not. -func ReadWrite(mode string) bool { - return rwModes[strings.ToLower(mode)] -} - -// ParseVolumesFrom ensure that the supplied volumes-from is valid. -func ParseVolumesFrom(spec string) (string, string, error) { - if len(spec) == 0 { - return "", "", derr.ErrorCodeVolumeFromBlank.WithArgs(spec) - } - - specParts := strings.SplitN(spec, ":", 2) - id := specParts[0] - mode := "rw" - - if len(specParts) == 2 { - mode = specParts[1] - if !ValidMountMode(mode) { - return "", "", derr.ErrorCodeVolumeInvalidMode.WithArgs(mode) - } - } - return id, mode, nil -} - -// SplitN splits raw into a maximum of n parts, separated by a separator colon. -// A separator colon is the last `:` character in the regex `[/:\\]?[a-zA-Z]:` (note `\\` is `\` escaped). -// This allows to correctly split strings such as `C:\foo:D:\:rw`. -func SplitN(raw string, n int) []string { - var array []string - if len(raw) == 0 || raw[0] == ':' { - // invalid - return nil - } - // numberOfParts counts the number of parts separated by a separator colon - numberOfParts := 0 - // left represents the left-most cursor in raw, updated at every `:` character considered as a separator. - left := 0 - // right represents the right-most cursor in raw incremented with the loop. Note this - // starts at index 1 as index 0 is already handle above as a special case. - for right := 1; right < len(raw); right++ { - // stop parsing if reached maximum number of parts - if n >= 0 && numberOfParts >= n { - break - } - if raw[right] != ':' { - continue - } - potentialDriveLetter := raw[right-1] - if (potentialDriveLetter >= 'A' && potentialDriveLetter <= 'Z') || (potentialDriveLetter >= 'a' && potentialDriveLetter <= 'z') { - if right > 1 { - beforePotentialDriveLetter := raw[right-2] - if beforePotentialDriveLetter != ':' && beforePotentialDriveLetter != '/' && beforePotentialDriveLetter != '\\' { - // e.g. `C:` is not preceded by any delimiter, therefore it was not a drive letter but a path ending with `C:`. - array = append(array, raw[left:right]) - left = right + 1 - numberOfParts++ - } - // else, `C:` is considered as a drive letter and not as a delimiter, so we continue parsing. - } - // if right == 1, then `C:` is the beginning of the raw string, therefore `:` is again not considered a delimiter and we continue parsing. - } else { - // if `:` is not preceded by a potential drive letter, then consider it as a delimiter. - array = append(array, raw[left:right]) - left = right + 1 - numberOfParts++ - } - } - // need to take care of the last part - if left < len(raw) { - if n >= 0 && numberOfParts >= n { - // if the maximum number of parts is reached, just append the rest to the last part - // left-1 is at the last `:` that needs to be included since not considered a separator. - array[n-1] += raw[left-1:] - } else { - array = append(array, raw[left:]) - } - } - return array -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/volume/volume_test.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/volume/volume_test.go deleted file mode 100644 index 5ce3d9fa..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/volume/volume_test.go +++ /dev/null @@ -1,261 +0,0 @@ -package volume - -import ( - "runtime" - "strings" - "testing" -) - -func TestParseMountSpec(t *testing.T) { - var ( - valid []string - invalid map[string]string - ) - - if runtime.GOOS == "windows" { - valid = []string{ - `d:\`, - `d:`, - `d:\path`, - `d:\path with space`, - // TODO Windows post TP4 - readonly support `d:\pathandmode:ro`, - `c:\:d:\`, - `c:\windows\:d:`, - `c:\windows:d:\s p a c e`, - `c:\windows:d:\s p a c e:RW`, - `c:\program files:d:\s p a c e i n h o s t d i r`, - `0123456789name:d:`, - `MiXeDcAsEnAmE:d:`, - `name:D:`, - `name:D::rW`, - `name:D::RW`, - // TODO Windows post TP4 - readonly support `name:D::RO`, - `c:/:d:/forward/slashes/are/good/too`, - // TODO Windows post TP4 - readonly support `c:/:d:/including with/spaces:ro`, - `c:\Windows`, // With capital - `c:\Program Files (x86)`, // With capitals and brackets - } - invalid = map[string]string{ - ``: "Invalid volume specification: ", - `.`: "Invalid volume specification: ", - `..\`: "Invalid volume specification: ", - `c:\:..\`: "Invalid volume specification: ", - `c:\:d:\:xyzzy`: "Invalid volume specification: ", - `c:`: "cannot be c:", - `c:\`: `cannot be c:\`, - `c:\notexist:d:`: `The system cannot find the file specified`, - `c:\windows\system32\ntdll.dll:d:`: `Source 'c:\windows\system32\ntdll.dll' is not a directory`, - `name<:d:`: `Invalid volume specification`, - `name>:d:`: `Invalid volume specification`, - `name::d:`: `Invalid volume specification`, - `name":d:`: `Invalid volume specification`, - `name\:d:`: `Invalid volume specification`, - `name*:d:`: `Invalid volume specification`, - `name|:d:`: `Invalid volume specification`, - `name?:d:`: `Invalid volume specification`, - `name/:d:`: `Invalid volume specification`, - `d:\pathandmode:rw`: `Invalid volume specification`, - `con:d:`: `cannot be a reserved word for Windows filenames`, - `PRN:d:`: `cannot be a reserved word for Windows filenames`, - `aUx:d:`: `cannot be a reserved word for Windows filenames`, - `nul:d:`: `cannot be a reserved word for Windows filenames`, - `com1:d:`: `cannot be a reserved word for Windows filenames`, - `com2:d:`: `cannot be a reserved word for Windows filenames`, - `com3:d:`: `cannot be a reserved word for Windows filenames`, - `com4:d:`: `cannot be a reserved word for Windows filenames`, - `com5:d:`: `cannot be a reserved word for Windows filenames`, - `com6:d:`: `cannot be a reserved word for Windows filenames`, - `com7:d:`: `cannot be a reserved word for Windows filenames`, - `com8:d:`: `cannot be a reserved word for Windows filenames`, - `com9:d:`: `cannot be a reserved word for Windows filenames`, - `lpt1:d:`: `cannot be a reserved word for Windows filenames`, - `lpt2:d:`: `cannot be a reserved word for Windows filenames`, - `lpt3:d:`: `cannot be a reserved word for Windows filenames`, - `lpt4:d:`: `cannot be a reserved word for Windows filenames`, - `lpt5:d:`: `cannot be a reserved word for Windows filenames`, - `lpt6:d:`: `cannot be a reserved word for Windows filenames`, - `lpt7:d:`: `cannot be a reserved word for Windows filenames`, - `lpt8:d:`: `cannot be a reserved word for Windows filenames`, - `lpt9:d:`: `cannot be a reserved word for Windows filenames`, - } - - } else { - valid = []string{ - "/home", - "/home:/home", - "/home:/something/else", - "/with space", - "/home:/with space", - "relative:/absolute-path", - "hostPath:/containerPath:ro", - "/hostPath:/containerPath:rw", - "/rw:/ro", - } - invalid = map[string]string{ - "": "Invalid volume specification", - "./": "Invalid volume destination", - "../": "Invalid volume destination", - "/:../": "Invalid volume destination", - "/:path": "Invalid volume destination", - ":": "Invalid volume specification", - "/tmp:": "Invalid volume destination", - ":test": "Invalid volume specification", - ":/test": "Invalid volume specification", - "tmp:": "Invalid volume destination", - ":test:": "Invalid volume specification", - "::": "Invalid volume specification", - ":::": "Invalid volume specification", - "/tmp:::": "Invalid volume specification", - ":/tmp::": "Invalid volume specification", - "/path:rw": "Invalid volume specification", - "/path:ro": "Invalid volume specification", - "/rw:rw": "Invalid volume specification", - "path:ro": "Invalid volume specification", - "/path:/path:sw": "invalid mode: sw", - "/path:/path:rwz": "invalid mode: rwz", - } - } - - for _, path := range valid { - if _, err := ParseMountSpec(path, "local"); err != nil { - t.Fatalf("ParseMountSpec(`%q`) should succeed: error %q", path, err) - } - } - - for path, expectedError := range invalid { - if _, err := ParseMountSpec(path, "local"); err == nil { - t.Fatalf("ParseMountSpec(`%q`) should have failed validation. Err %v", path, err) - } else { - if !strings.Contains(err.Error(), expectedError) { - t.Fatalf("ParseMountSpec(`%q`) error should contain %q, got %v", path, expectedError, err.Error()) - } - } - } -} - -func TestSplitN(t *testing.T) { - for _, x := range []struct { - input string - n int - expected []string - }{ - {`C:\foo:d:`, -1, []string{`C:\foo`, `d:`}}, - {`:C:\foo:d:`, -1, nil}, - {`/foo:/bar:ro`, 3, []string{`/foo`, `/bar`, `ro`}}, - {`/foo:/bar:ro`, 2, []string{`/foo`, `/bar:ro`}}, - {`C:\foo\:/foo`, -1, []string{`C:\foo\`, `/foo`}}, - - {`d:\`, -1, []string{`d:\`}}, - {`d:`, -1, []string{`d:`}}, - {`d:\path`, -1, []string{`d:\path`}}, - {`d:\path with space`, -1, []string{`d:\path with space`}}, - {`d:\pathandmode:rw`, -1, []string{`d:\pathandmode`, `rw`}}, - {`c:\:d:\`, -1, []string{`c:\`, `d:\`}}, - {`c:\windows\:d:`, -1, []string{`c:\windows\`, `d:`}}, - {`c:\windows:d:\s p a c e`, -1, []string{`c:\windows`, `d:\s p a c e`}}, - {`c:\windows:d:\s p a c e:RW`, -1, []string{`c:\windows`, `d:\s p a c e`, `RW`}}, - {`c:\program files:d:\s p a c e i n h o s t d i r`, -1, []string{`c:\program files`, `d:\s p a c e i n h o s t d i r`}}, - {`0123456789name:d:`, -1, []string{`0123456789name`, `d:`}}, - {`MiXeDcAsEnAmE:d:`, -1, []string{`MiXeDcAsEnAmE`, `d:`}}, - {`name:D:`, -1, []string{`name`, `D:`}}, - {`name:D::rW`, -1, []string{`name`, `D:`, `rW`}}, - {`name:D::RW`, -1, []string{`name`, `D:`, `RW`}}, - {`c:/:d:/forward/slashes/are/good/too`, -1, []string{`c:/`, `d:/forward/slashes/are/good/too`}}, - {`c:\Windows`, -1, []string{`c:\Windows`}}, - {`c:\Program Files (x86)`, -1, []string{`c:\Program Files (x86)`}}, - - {``, -1, nil}, - {`.`, -1, []string{`.`}}, - {`..\`, -1, []string{`..\`}}, - {`c:\:..\`, -1, []string{`c:\`, `..\`}}, - {`c:\:d:\:xyzzy`, -1, []string{`c:\`, `d:\`, `xyzzy`}}, - } { - res := SplitN(x.input, x.n) - if len(res) < len(x.expected) { - t.Fatalf("input: %v, expected: %v, got: %v", x.input, x.expected, res) - } - for i, e := range res { - if e != x.expected[i] { - t.Fatalf("input: %v, expected: %v, got: %v", x.input, x.expected, res) - } - } - } -} - -// testParseMountSpec is a structure used by TestParseMountSpecSplit for -// specifying test cases for the ParseMountSpec() function. -type testParseMountSpec struct { - bind string - driver string - expDest string - expSource string - expName string - expDriver string - expRW bool - fail bool -} - -func TestParseMountSpecSplit(t *testing.T) { - var cases []testParseMountSpec - if runtime.GOOS == "windows" { - cases = []testParseMountSpec{ - {`c:\:d:`, "local", `d:`, `c:\`, ``, "", true, false}, - {`c:\:d:\`, "local", `d:\`, `c:\`, ``, "", true, false}, - // TODO Windows post TP4 - Add readonly support {`c:\:d:\:ro`, "local", `d:\`, `c:\`, ``, "", false, false}, - {`c:\:d:\:rw`, "local", `d:\`, `c:\`, ``, "", true, false}, - {`c:\:d:\:foo`, "local", `d:\`, `c:\`, ``, "", false, true}, - {`name:d::rw`, "local", `d:`, ``, `name`, "local", true, false}, - {`name:d:`, "local", `d:`, ``, `name`, "local", true, false}, - // TODO Windows post TP4 - Add readonly support {`name:d::ro`, "local", `d:`, ``, `name`, "local", false, false}, - {`name:c:`, "", ``, ``, ``, "", true, true}, - {`driver/name:c:`, "", ``, ``, ``, "", true, true}, - } - } else { - cases = []testParseMountSpec{ - {"/tmp:/tmp1", "", "/tmp1", "/tmp", "", "", true, false}, - {"/tmp:/tmp2:ro", "", "/tmp2", "/tmp", "", "", false, false}, - {"/tmp:/tmp3:rw", "", "/tmp3", "/tmp", "", "", true, false}, - {"/tmp:/tmp4:foo", "", "", "", "", "", false, true}, - {"name:/named1", "", "/named1", "", "name", "local", true, false}, - {"name:/named2", "external", "/named2", "", "name", "external", true, false}, - {"name:/named3:ro", "local", "/named3", "", "name", "local", false, false}, - {"local/name:/tmp:rw", "", "/tmp", "", "local/name", "local", true, false}, - {"/tmp:tmp", "", "", "", "", "", true, true}, - } - } - - for _, c := range cases { - m, err := ParseMountSpec(c.bind, c.driver) - if c.fail { - if err == nil { - t.Fatalf("Expected error, was nil, for spec %s\n", c.bind) - } - continue - } - - if m == nil || err != nil { - t.Fatalf("ParseMountSpec failed for spec %s driver %s error %v\n", c.bind, c.driver, err.Error()) - continue - } - - if m.Destination != c.expDest { - t.Fatalf("Expected destination %s, was %s, for spec %s\n", c.expDest, m.Destination, c.bind) - } - - if m.Source != c.expSource { - t.Fatalf("Expected source %s, was %s, for spec %s\n", c.expSource, m.Source, c.bind) - } - - if m.Name != c.expName { - t.Fatalf("Expected name %s, was %s for spec %s\n", c.expName, m.Name, c.bind) - } - - if m.Driver != c.expDriver { - t.Fatalf("Expected driver %s, was %s, for spec %s\n", c.expDriver, m.Driver, c.bind) - } - - if m.RW != c.expRW { - t.Fatalf("Expected RW %v, was %v for spec %s\n", c.expRW, m.RW, c.bind) - } - } -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/volume/volume_unix.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/volume/volume_unix.go deleted file mode 100644 index db0fea5b..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/volume/volume_unix.go +++ /dev/null @@ -1,132 +0,0 @@ -// +build linux freebsd darwin - -package volume - -import ( - "fmt" - "path/filepath" - "strings" - - derr "github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors" -) - -// read-write modes -var rwModes = map[string]bool{ - "rw": true, - "rw,Z": true, - "rw,z": true, - "z,rw": true, - "Z,rw": true, - "Z": true, - "z": true, -} - -// read-only modes -var roModes = map[string]bool{ - "ro": true, - "ro,Z": true, - "ro,z": true, - "z,ro": true, - "Z,ro": true, -} - -// BackwardsCompatible decides whether this mount point can be -// used in old versions of Docker or not. -// Only bind mounts and local volumes can be used in old versions of Docker. -func (m *MountPoint) BackwardsCompatible() bool { - return len(m.Source) > 0 || m.Driver == DefaultDriverName -} - -// HasResource checks whether the given absolute path for a container is in -// this mount point. If the relative path starts with `../` then the resource -// is outside of this mount point, but we can't simply check for this prefix -// because it misses `..` which is also outside of the mount, so check both. -func (m *MountPoint) HasResource(absolutePath string) bool { - relPath, err := filepath.Rel(m.Destination, absolutePath) - return err == nil && relPath != ".." && !strings.HasPrefix(relPath, fmt.Sprintf("..%c", filepath.Separator)) -} - -// ParseMountSpec validates the configuration of mount information is valid. -func ParseMountSpec(spec, volumeDriver string) (*MountPoint, error) { - spec = filepath.ToSlash(spec) - - mp := &MountPoint{ - RW: true, - } - if strings.Count(spec, ":") > 2 { - return nil, derr.ErrorCodeVolumeInvalid.WithArgs(spec) - } - - arr := strings.SplitN(spec, ":", 3) - if arr[0] == "" { - return nil, derr.ErrorCodeVolumeInvalid.WithArgs(spec) - } - - switch len(arr) { - case 1: - // Just a destination path in the container - mp.Destination = filepath.Clean(arr[0]) - case 2: - if isValid := ValidMountMode(arr[1]); isValid { - // Destination + Mode is not a valid volume - volumes - // cannot include a mode. eg /foo:rw - return nil, derr.ErrorCodeVolumeInvalid.WithArgs(spec) - } - // Host Source Path or Name + Destination - mp.Source = arr[0] - mp.Destination = arr[1] - case 3: - // HostSourcePath+DestinationPath+Mode - mp.Source = arr[0] - mp.Destination = arr[1] - mp.Mode = arr[2] // Mode field is used by SELinux to decide whether to apply label - if !ValidMountMode(mp.Mode) { - return nil, derr.ErrorCodeVolumeInvalidMode.WithArgs(mp.Mode) - } - mp.RW = ReadWrite(mp.Mode) - default: - return nil, derr.ErrorCodeVolumeInvalid.WithArgs(spec) - } - - //validate the volumes destination path - mp.Destination = filepath.Clean(mp.Destination) - if !filepath.IsAbs(mp.Destination) { - return nil, derr.ErrorCodeVolumeAbs.WithArgs(mp.Destination) - } - - // Destination cannot be "/" - if mp.Destination == "/" { - return nil, derr.ErrorCodeVolumeSlash.WithArgs(spec) - } - - name, source := ParseVolumeSource(mp.Source) - if len(source) == 0 { - mp.Source = "" // Clear it out as we previously assumed it was not a name - mp.Driver = volumeDriver - if len(mp.Driver) == 0 { - mp.Driver = DefaultDriverName - } - } else { - mp.Source = filepath.Clean(source) - } - - mp.Name = name - - return mp, nil -} - -// ParseVolumeSource parses the origin sources that's mounted into the container. -// It returns a name and a source. It looks to see if the spec passed in -// is an absolute file. If it is, it assumes the spec is a source. If not, -// it assumes the spec is a name. -func ParseVolumeSource(spec string) (string, string) { - if !filepath.IsAbs(spec) { - return spec, "" - } - return "", spec -} - -// IsVolumeNameValid checks a volume name in a platform specific manner. -func IsVolumeNameValid(name string) (bool, error) { - return true, nil -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/volume/volume_windows.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/volume/volume_windows.go deleted file mode 100644 index 3f027801..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/volume/volume_windows.go +++ /dev/null @@ -1,181 +0,0 @@ -package volume - -import ( - "os" - "path/filepath" - "regexp" - "strings" - - "github.com/fsouza/go-dockerclient/external/github.com/Sirupsen/logrus" - derr "github.com/fsouza/go-dockerclient/external/github.com/docker/docker/errors" -) - -// read-write modes -var rwModes = map[string]bool{ - "rw": true, -} - -// read-only modes -var roModes = map[string]bool{ - "ro": true, -} - -const ( - // Spec should be in the format [source:]destination[:mode] - // - // Examples: c:\foo bar:d:rw - // c:\foo:d:\bar - // myname:d: - // d:\ - // - // Explanation of this regex! Thanks @thaJeztah on IRC and gist for help. See - // https://gist.github.com/thaJeztah/6185659e4978789fb2b2. A good place to - // test is https://regex-golang.appspot.com/assets/html/index.html - // - // Useful link for referencing named capturing groups: - // http://stackoverflow.com/questions/20750843/using-named-matches-from-go-regex - // - // There are three match groups: source, destination and mode. - // - - // RXHostDir is the first option of a source - RXHostDir = `[a-z]:\\(?:[^\\/:*?"<>|\r\n]+\\?)*` - // RXName is the second option of a source - RXName = `[^\\/:*?"<>|\r\n]+` - // RXReservedNames are reserved names not possible on Windows - RXReservedNames = `(con)|(prn)|(nul)|(aux)|(com[1-9])|(lpt[1-9])` - - // RXSource is the combined possiblities for a source - RXSource = `((?P((` + RXHostDir + `)|(` + RXName + `))):)?` - - // Source. Can be either a host directory, a name, or omitted: - // HostDir: - // - Essentially using the folder solution from - // https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9781449327453/ch08s18.html - // but adding case insensitivity. - // - Must be an absolute path such as c:\path - // - Can include spaces such as `c:\program files` - // - And then followed by a colon which is not in the capture group - // - And can be optional - // Name: - // - Must not contain invalid NTFS filename characters (https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx) - // - And then followed by a colon which is not in the capture group - // - And can be optional - - // RXDestination is the regex expression for the mount destination - RXDestination = `(?P([a-z]):((?:\\[^\\/:*?"<>\r\n]+)*\\?))` - // Destination (aka container path): - // - Variation on hostdir but can be a drive followed by colon as well - // - If a path, must be absolute. Can include spaces - // - Drive cannot be c: (explicitly checked in code, not RegEx) - // - - // RXMode is the regex expression for the mode of the mount - RXMode = `(:(?P(?i)rw))?` - // Temporarily for TP4, disabling the use of ro as it's not supported yet - // in the platform. TODO Windows: `(:(?P(?i)ro|rw))?` - // mode (optional) - // - Hopefully self explanatory in comparison to above. - // - Colon is not in the capture group - // -) - -// ParseMountSpec validates the configuration of mount information is valid. -func ParseMountSpec(spec string, volumeDriver string) (*MountPoint, error) { - var specExp = regexp.MustCompile(`^` + RXSource + RXDestination + RXMode + `$`) - - // Ensure in platform semantics for matching. The CLI will send in Unix semantics. - match := specExp.FindStringSubmatch(filepath.FromSlash(strings.ToLower(spec))) - - // Must have something back - if len(match) == 0 { - return nil, derr.ErrorCodeVolumeInvalid.WithArgs(spec) - } - - // Pull out the sub expressions from the named capture groups - matchgroups := make(map[string]string) - for i, name := range specExp.SubexpNames() { - matchgroups[name] = strings.ToLower(match[i]) - } - - mp := &MountPoint{ - Source: matchgroups["source"], - Destination: matchgroups["destination"], - RW: true, - } - if strings.ToLower(matchgroups["mode"]) == "ro" { - mp.RW = false - } - - // Volumes cannot include an explicitly supplied mode eg c:\path:rw - if mp.Source == "" && mp.Destination != "" && matchgroups["mode"] != "" { - return nil, derr.ErrorCodeVolumeInvalid.WithArgs(spec) - } - - // Note: No need to check if destination is absolute as it must be by - // definition of matching the regex. - - if filepath.VolumeName(mp.Destination) == mp.Destination { - // Ensure the destination path, if a drive letter, is not the c drive - if strings.ToLower(mp.Destination) == "c:" { - return nil, derr.ErrorCodeVolumeDestIsC.WithArgs(spec) - } - } else { - // So we know the destination is a path, not drive letter. Clean it up. - mp.Destination = filepath.Clean(mp.Destination) - // Ensure the destination path, if a path, is not the c root directory - if strings.ToLower(mp.Destination) == `c:\` { - return nil, derr.ErrorCodeVolumeDestIsCRoot.WithArgs(spec) - } - } - - // See if the source is a name instead of a host directory - if len(mp.Source) > 0 { - validName, err := IsVolumeNameValid(mp.Source) - if err != nil { - return nil, err - } - if validName { - // OK, so the source is a name. - mp.Name = mp.Source - mp.Source = "" - - // Set the driver accordingly - mp.Driver = volumeDriver - if len(mp.Driver) == 0 { - mp.Driver = DefaultDriverName - } - } else { - // OK, so the source must be a host directory. Make sure it's clean. - mp.Source = filepath.Clean(mp.Source) - } - } - - // Ensure the host path source, if supplied, exists and is a directory - if len(mp.Source) > 0 { - var fi os.FileInfo - var err error - if fi, err = os.Stat(mp.Source); err != nil { - return nil, derr.ErrorCodeVolumeSourceNotFound.WithArgs(mp.Source, err) - } - if !fi.IsDir() { - return nil, derr.ErrorCodeVolumeSourceNotDirectory.WithArgs(mp.Source) - } - } - - logrus.Debugf("MP: Source '%s', Dest '%s', RW %t, Name '%s', Driver '%s'", mp.Source, mp.Destination, mp.RW, mp.Name, mp.Driver) - return mp, nil -} - -// IsVolumeNameValid checks a volume name in a platform specific manner. -func IsVolumeNameValid(name string) (bool, error) { - nameExp := regexp.MustCompile(`^` + RXName + `$`) - if !nameExp.MatchString(name) { - return false, nil - } - nameExp = regexp.MustCompile(`^` + RXReservedNames + `$`) - if nameExp.MatchString(name) { - return false, derr.ErrorCodeVolumeNameReservedWord.WithArgs(name) - } - return true, nil -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/libcontainer/user/MAINTAINERS b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/libcontainer/user/MAINTAINERS deleted file mode 100644 index edbe2006..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/libcontainer/user/MAINTAINERS +++ /dev/null @@ -1,2 +0,0 @@ -Tianon Gravi (@tianon) -Aleksa Sarai (@cyphar) diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/libcontainer/user/lookup.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/libcontainer/user/lookup.go deleted file mode 100644 index 6f8a982f..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/libcontainer/user/lookup.go +++ /dev/null @@ -1,108 +0,0 @@ -package user - -import ( - "errors" - "fmt" - "syscall" -) - -var ( - // The current operating system does not provide the required data for user lookups. - ErrUnsupported = errors.New("user lookup: operating system does not provide passwd-formatted data") -) - -func lookupUser(filter func(u User) bool) (User, error) { - // Get operating system-specific passwd reader-closer. - passwd, err := GetPasswd() - if err != nil { - return User{}, err - } - defer passwd.Close() - - // Get the users. - users, err := ParsePasswdFilter(passwd, filter) - if err != nil { - return User{}, err - } - - // No user entries found. - if len(users) == 0 { - return User{}, fmt.Errorf("no matching entries in passwd file") - } - - // Assume the first entry is the "correct" one. - return users[0], nil -} - -// CurrentUser looks up the current user by their user id in /etc/passwd. If the -// user cannot be found (or there is no /etc/passwd file on the filesystem), -// then CurrentUser returns an error. -func CurrentUser() (User, error) { - return LookupUid(syscall.Getuid()) -} - -// LookupUser looks up a user by their username in /etc/passwd. If the user -// cannot be found (or there is no /etc/passwd file on the filesystem), then -// LookupUser returns an error. -func LookupUser(username string) (User, error) { - return lookupUser(func(u User) bool { - return u.Name == username - }) -} - -// LookupUid looks up a user by their user id in /etc/passwd. If the user cannot -// be found (or there is no /etc/passwd file on the filesystem), then LookupId -// returns an error. -func LookupUid(uid int) (User, error) { - return lookupUser(func(u User) bool { - return u.Uid == uid - }) -} - -func lookupGroup(filter func(g Group) bool) (Group, error) { - // Get operating system-specific group reader-closer. - group, err := GetGroup() - if err != nil { - return Group{}, err - } - defer group.Close() - - // Get the users. - groups, err := ParseGroupFilter(group, filter) - if err != nil { - return Group{}, err - } - - // No user entries found. - if len(groups) == 0 { - return Group{}, fmt.Errorf("no matching entries in group file") - } - - // Assume the first entry is the "correct" one. - return groups[0], nil -} - -// CurrentGroup looks up the current user's group by their primary group id's -// entry in /etc/passwd. If the group cannot be found (or there is no -// /etc/group file on the filesystem), then CurrentGroup returns an error. -func CurrentGroup() (Group, error) { - return LookupGid(syscall.Getgid()) -} - -// LookupGroup looks up a group by its name in /etc/group. If the group cannot -// be found (or there is no /etc/group file on the filesystem), then LookupGroup -// returns an error. -func LookupGroup(groupname string) (Group, error) { - return lookupGroup(func(g Group) bool { - return g.Name == groupname - }) -} - -// LookupGid looks up a group by its group id in /etc/group. If the group cannot -// be found (or there is no /etc/group file on the filesystem), then LookupGid -// returns an error. -func LookupGid(gid int) (Group, error) { - return lookupGroup(func(g Group) bool { - return g.Gid == gid - }) -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/libcontainer/user/lookup_unix.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/libcontainer/user/lookup_unix.go deleted file mode 100644 index 758b734c..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/libcontainer/user/lookup_unix.go +++ /dev/null @@ -1,30 +0,0 @@ -// +build darwin dragonfly freebsd linux netbsd openbsd solaris - -package user - -import ( - "io" - "os" -) - -// Unix-specific path to the passwd and group formatted files. -const ( - unixPasswdPath = "/etc/passwd" - unixGroupPath = "/etc/group" -) - -func GetPasswdPath() (string, error) { - return unixPasswdPath, nil -} - -func GetPasswd() (io.ReadCloser, error) { - return os.Open(unixPasswdPath) -} - -func GetGroupPath() (string, error) { - return unixGroupPath, nil -} - -func GetGroup() (io.ReadCloser, error) { - return os.Open(unixGroupPath) -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/libcontainer/user/lookup_unsupported.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/libcontainer/user/lookup_unsupported.go deleted file mode 100644 index 72179488..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/libcontainer/user/lookup_unsupported.go +++ /dev/null @@ -1,21 +0,0 @@ -// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris - -package user - -import "io" - -func GetPasswdPath() (string, error) { - return "", ErrUnsupported -} - -func GetPasswd() (io.ReadCloser, error) { - return nil, ErrUnsupported -} - -func GetGroupPath() (string, error) { - return "", ErrUnsupported -} - -func GetGroup() (io.ReadCloser, error) { - return nil, ErrUnsupported -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/libcontainer/user/user.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/libcontainer/user/user.go deleted file mode 100644 index 13226dbf..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/libcontainer/user/user.go +++ /dev/null @@ -1,407 +0,0 @@ -package user - -import ( - "bufio" - "fmt" - "io" - "os" - "strconv" - "strings" -) - -const ( - minId = 0 - maxId = 1<<31 - 1 //for 32-bit systems compatibility -) - -var ( - ErrRange = fmt.Errorf("Uids and gids must be in range %d-%d", minId, maxId) -) - -type User struct { - Name string - Pass string - Uid int - Gid int - Gecos string - Home string - Shell string -} - -type Group struct { - Name string - Pass string - Gid int - List []string -} - -func parseLine(line string, v ...interface{}) { - if line == "" { - return - } - - parts := strings.Split(line, ":") - for i, p := range parts { - if len(v) <= i { - // if we have more "parts" than we have places to put them, bail for great "tolerance" of naughty configuration files - break - } - - switch e := v[i].(type) { - case *string: - // "root", "adm", "/bin/bash" - *e = p - case *int: - // "0", "4", "1000" - // ignore string to int conversion errors, for great "tolerance" of naughty configuration files - *e, _ = strconv.Atoi(p) - case *[]string: - // "", "root", "root,adm,daemon" - if p != "" { - *e = strings.Split(p, ",") - } else { - *e = []string{} - } - default: - // panic, because this is a programming/logic error, not a runtime one - panic("parseLine expects only pointers! argument " + strconv.Itoa(i) + " is not a pointer!") - } - } -} - -func ParsePasswdFile(path string) ([]User, error) { - passwd, err := os.Open(path) - if err != nil { - return nil, err - } - defer passwd.Close() - return ParsePasswd(passwd) -} - -func ParsePasswd(passwd io.Reader) ([]User, error) { - return ParsePasswdFilter(passwd, nil) -} - -func ParsePasswdFileFilter(path string, filter func(User) bool) ([]User, error) { - passwd, err := os.Open(path) - if err != nil { - return nil, err - } - defer passwd.Close() - return ParsePasswdFilter(passwd, filter) -} - -func ParsePasswdFilter(r io.Reader, filter func(User) bool) ([]User, error) { - if r == nil { - return nil, fmt.Errorf("nil source for passwd-formatted data") - } - - var ( - s = bufio.NewScanner(r) - out = []User{} - ) - - for s.Scan() { - if err := s.Err(); err != nil { - return nil, err - } - - text := strings.TrimSpace(s.Text()) - if text == "" { - continue - } - - // see: man 5 passwd - // name:password:UID:GID:GECOS:directory:shell - // Name:Pass:Uid:Gid:Gecos:Home:Shell - // root:x:0:0:root:/root:/bin/bash - // adm:x:3:4:adm:/var/adm:/bin/false - p := User{} - parseLine( - text, - &p.Name, &p.Pass, &p.Uid, &p.Gid, &p.Gecos, &p.Home, &p.Shell, - ) - - if filter == nil || filter(p) { - out = append(out, p) - } - } - - return out, nil -} - -func ParseGroupFile(path string) ([]Group, error) { - group, err := os.Open(path) - if err != nil { - return nil, err - } - defer group.Close() - return ParseGroup(group) -} - -func ParseGroup(group io.Reader) ([]Group, error) { - return ParseGroupFilter(group, nil) -} - -func ParseGroupFileFilter(path string, filter func(Group) bool) ([]Group, error) { - group, err := os.Open(path) - if err != nil { - return nil, err - } - defer group.Close() - return ParseGroupFilter(group, filter) -} - -func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) { - if r == nil { - return nil, fmt.Errorf("nil source for group-formatted data") - } - - var ( - s = bufio.NewScanner(r) - out = []Group{} - ) - - for s.Scan() { - if err := s.Err(); err != nil { - return nil, err - } - - text := s.Text() - if text == "" { - continue - } - - // see: man 5 group - // group_name:password:GID:user_list - // Name:Pass:Gid:List - // root:x:0:root - // adm:x:4:root,adm,daemon - p := Group{} - parseLine( - text, - &p.Name, &p.Pass, &p.Gid, &p.List, - ) - - if filter == nil || filter(p) { - out = append(out, p) - } - } - - return out, nil -} - -type ExecUser struct { - Uid, Gid int - Sgids []int - Home string -} - -// GetExecUserPath is a wrapper for GetExecUser. It reads data from each of the -// given file paths and uses that data as the arguments to GetExecUser. If the -// files cannot be opened for any reason, the error is ignored and a nil -// io.Reader is passed instead. -func GetExecUserPath(userSpec string, defaults *ExecUser, passwdPath, groupPath string) (*ExecUser, error) { - passwd, err := os.Open(passwdPath) - if err != nil { - passwd = nil - } else { - defer passwd.Close() - } - - group, err := os.Open(groupPath) - if err != nil { - group = nil - } else { - defer group.Close() - } - - return GetExecUser(userSpec, defaults, passwd, group) -} - -// GetExecUser parses a user specification string (using the passwd and group -// readers as sources for /etc/passwd and /etc/group data, respectively). In -// the case of blank fields or missing data from the sources, the values in -// defaults is used. -// -// GetExecUser will return an error if a user or group literal could not be -// found in any entry in passwd and group respectively. -// -// Examples of valid user specifications are: -// * "" -// * "user" -// * "uid" -// * "user:group" -// * "uid:gid -// * "user:gid" -// * "uid:group" -func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (*ExecUser, error) { - var ( - userArg, groupArg string - name string - ) - - if defaults == nil { - defaults = new(ExecUser) - } - - // Copy over defaults. - user := &ExecUser{ - Uid: defaults.Uid, - Gid: defaults.Gid, - Sgids: defaults.Sgids, - Home: defaults.Home, - } - - // Sgids slice *cannot* be nil. - if user.Sgids == nil { - user.Sgids = []int{} - } - - // allow for userArg to have either "user" syntax, or optionally "user:group" syntax - parseLine(userSpec, &userArg, &groupArg) - - users, err := ParsePasswdFilter(passwd, func(u User) bool { - if userArg == "" { - return u.Uid == user.Uid - } - return u.Name == userArg || strconv.Itoa(u.Uid) == userArg - }) - if err != nil && passwd != nil { - if userArg == "" { - userArg = strconv.Itoa(user.Uid) - } - return nil, fmt.Errorf("Unable to find user %v: %v", userArg, err) - } - - haveUser := users != nil && len(users) > 0 - if haveUser { - // if we found any user entries that matched our filter, let's take the first one as "correct" - name = users[0].Name - user.Uid = users[0].Uid - user.Gid = users[0].Gid - user.Home = users[0].Home - } else if userArg != "" { - // we asked for a user but didn't find them... let's check to see if we wanted a numeric user - user.Uid, err = strconv.Atoi(userArg) - if err != nil { - // not numeric - we have to bail - return nil, fmt.Errorf("Unable to find user %v", userArg) - } - - // Must be inside valid uid range. - if user.Uid < minId || user.Uid > maxId { - return nil, ErrRange - } - - // if userArg couldn't be found in /etc/passwd but is numeric, just roll with it - this is legit - } - - if groupArg != "" || name != "" { - groups, err := ParseGroupFilter(group, func(g Group) bool { - // Explicit group format takes precedence. - if groupArg != "" { - return g.Name == groupArg || strconv.Itoa(g.Gid) == groupArg - } - - // Check if user is a member. - for _, u := range g.List { - if u == name { - return true - } - } - - return false - }) - if err != nil && group != nil { - return nil, fmt.Errorf("Unable to find groups for user %v: %v", users[0].Name, err) - } - - haveGroup := groups != nil && len(groups) > 0 - if groupArg != "" { - if haveGroup { - // if we found any group entries that matched our filter, let's take the first one as "correct" - user.Gid = groups[0].Gid - } else { - // we asked for a group but didn't find id... let's check to see if we wanted a numeric group - user.Gid, err = strconv.Atoi(groupArg) - if err != nil { - // not numeric - we have to bail - return nil, fmt.Errorf("Unable to find group %v", groupArg) - } - - // Ensure gid is inside gid range. - if user.Gid < minId || user.Gid > maxId { - return nil, ErrRange - } - - // if groupArg couldn't be found in /etc/group but is numeric, just roll with it - this is legit - } - } else if haveGroup { - // If implicit group format, fill supplementary gids. - user.Sgids = make([]int, len(groups)) - for i, group := range groups { - user.Sgids[i] = group.Gid - } - } - } - - return user, nil -} - -// GetAdditionalGroupsPath looks up a list of groups by name or group id -// against the group file. If a group name cannot be found, an error will be -// returned. If a group id cannot be found, it will be returned as-is. -func GetAdditionalGroupsPath(additionalGroups []string, groupPath string) ([]int, error) { - groupReader, err := os.Open(groupPath) - if err != nil { - return nil, fmt.Errorf("Failed to open group file: %v", err) - } - defer groupReader.Close() - - groups, err := ParseGroupFilter(groupReader, func(g Group) bool { - for _, ag := range additionalGroups { - if g.Name == ag || strconv.Itoa(g.Gid) == ag { - return true - } - } - return false - }) - if err != nil { - return nil, fmt.Errorf("Unable to find additional groups %v: %v", additionalGroups, err) - } - - gidMap := make(map[int]struct{}) - for _, ag := range additionalGroups { - var found bool - for _, g := range groups { - // if we found a matched group either by name or gid, take the - // first matched as correct - if g.Name == ag || strconv.Itoa(g.Gid) == ag { - if _, ok := gidMap[g.Gid]; !ok { - gidMap[g.Gid] = struct{}{} - found = true - break - } - } - } - // we asked for a group but didn't find it. let's check to see - // if we wanted a numeric group - if !found { - gid, err := strconv.Atoi(ag) - if err != nil { - return nil, fmt.Errorf("Unable to find group %s", ag) - } - // Ensure gid is inside gid range. - if gid < minId || gid > maxId { - return nil, ErrRange - } - gidMap[gid] = struct{}{} - } - } - gids := []int{} - for gid := range gidMap { - gids = append(gids, gid) - } - return gids, nil -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/libcontainer/user/user_test.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/libcontainer/user/user_test.go deleted file mode 100644 index ffb0760e..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/libcontainer/user/user_test.go +++ /dev/null @@ -1,443 +0,0 @@ -package user - -import ( - "fmt" - "io" - "io/ioutil" - "reflect" - "sort" - "strconv" - "strings" - "testing" -) - -func TestUserParseLine(t *testing.T) { - var ( - a, b string - c []string - d int - ) - - parseLine("", &a, &b) - if a != "" || b != "" { - t.Fatalf("a and b should be empty ('%v', '%v')", a, b) - } - - parseLine("a", &a, &b) - if a != "a" || b != "" { - t.Fatalf("a should be 'a' and b should be empty ('%v', '%v')", a, b) - } - - parseLine("bad boys:corny cows", &a, &b) - if a != "bad boys" || b != "corny cows" { - t.Fatalf("a should be 'bad boys' and b should be 'corny cows' ('%v', '%v')", a, b) - } - - parseLine("", &c) - if len(c) != 0 { - t.Fatalf("c should be empty (%#v)", c) - } - - parseLine("d,e,f:g:h:i,j,k", &c, &a, &b, &c) - if a != "g" || b != "h" || len(c) != 3 || c[0] != "i" || c[1] != "j" || c[2] != "k" { - t.Fatalf("a should be 'g', b should be 'h', and c should be ['i','j','k'] ('%v', '%v', '%#v')", a, b, c) - } - - parseLine("::::::::::", &a, &b, &c) - if a != "" || b != "" || len(c) != 0 { - t.Fatalf("a, b, and c should all be empty ('%v', '%v', '%#v')", a, b, c) - } - - parseLine("not a number", &d) - if d != 0 { - t.Fatalf("d should be 0 (%v)", d) - } - - parseLine("b:12:c", &a, &d, &b) - if a != "b" || b != "c" || d != 12 { - t.Fatalf("a should be 'b' and b should be 'c', and d should be 12 ('%v', '%v', %v)", a, b, d) - } -} - -func TestUserParsePasswd(t *testing.T) { - users, err := ParsePasswdFilter(strings.NewReader(` -root:x:0:0:root:/root:/bin/bash -adm:x:3:4:adm:/var/adm:/bin/false -this is just some garbage data -`), nil) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if len(users) != 3 { - t.Fatalf("Expected 3 users, got %v", len(users)) - } - if users[0].Uid != 0 || users[0].Name != "root" { - t.Fatalf("Expected users[0] to be 0 - root, got %v - %v", users[0].Uid, users[0].Name) - } - if users[1].Uid != 3 || users[1].Name != "adm" { - t.Fatalf("Expected users[1] to be 3 - adm, got %v - %v", users[1].Uid, users[1].Name) - } -} - -func TestUserParseGroup(t *testing.T) { - groups, err := ParseGroupFilter(strings.NewReader(` -root:x:0:root -adm:x:4:root,adm,daemon -this is just some garbage data -`), nil) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if len(groups) != 3 { - t.Fatalf("Expected 3 groups, got %v", len(groups)) - } - if groups[0].Gid != 0 || groups[0].Name != "root" || len(groups[0].List) != 1 { - t.Fatalf("Expected groups[0] to be 0 - root - 1 member, got %v - %v - %v", groups[0].Gid, groups[0].Name, len(groups[0].List)) - } - if groups[1].Gid != 4 || groups[1].Name != "adm" || len(groups[1].List) != 3 { - t.Fatalf("Expected groups[1] to be 4 - adm - 3 members, got %v - %v - %v", groups[1].Gid, groups[1].Name, len(groups[1].List)) - } -} - -func TestValidGetExecUser(t *testing.T) { - const passwdContent = ` -root:x:0:0:root user:/root:/bin/bash -adm:x:42:43:adm:/var/adm:/bin/false -this is just some garbage data -` - const groupContent = ` -root:x:0:root -adm:x:43: -grp:x:1234:root,adm -this is just some garbage data -` - defaultExecUser := ExecUser{ - Uid: 8888, - Gid: 8888, - Sgids: []int{8888}, - Home: "/8888", - } - - tests := []struct { - ref string - expected ExecUser - }{ - { - ref: "root", - expected: ExecUser{ - Uid: 0, - Gid: 0, - Sgids: []int{0, 1234}, - Home: "/root", - }, - }, - { - ref: "adm", - expected: ExecUser{ - Uid: 42, - Gid: 43, - Sgids: []int{1234}, - Home: "/var/adm", - }, - }, - { - ref: "root:adm", - expected: ExecUser{ - Uid: 0, - Gid: 43, - Sgids: defaultExecUser.Sgids, - Home: "/root", - }, - }, - { - ref: "adm:1234", - expected: ExecUser{ - Uid: 42, - Gid: 1234, - Sgids: defaultExecUser.Sgids, - Home: "/var/adm", - }, - }, - { - ref: "42:1234", - expected: ExecUser{ - Uid: 42, - Gid: 1234, - Sgids: defaultExecUser.Sgids, - Home: "/var/adm", - }, - }, - { - ref: "1337:1234", - expected: ExecUser{ - Uid: 1337, - Gid: 1234, - Sgids: defaultExecUser.Sgids, - Home: defaultExecUser.Home, - }, - }, - { - ref: "1337", - expected: ExecUser{ - Uid: 1337, - Gid: defaultExecUser.Gid, - Sgids: defaultExecUser.Sgids, - Home: defaultExecUser.Home, - }, - }, - { - ref: "", - expected: ExecUser{ - Uid: defaultExecUser.Uid, - Gid: defaultExecUser.Gid, - Sgids: defaultExecUser.Sgids, - Home: defaultExecUser.Home, - }, - }, - } - - for _, test := range tests { - passwd := strings.NewReader(passwdContent) - group := strings.NewReader(groupContent) - - execUser, err := GetExecUser(test.ref, &defaultExecUser, passwd, group) - if err != nil { - t.Logf("got unexpected error when parsing '%s': %s", test.ref, err.Error()) - t.Fail() - continue - } - - if !reflect.DeepEqual(test.expected, *execUser) { - t.Logf("got: %#v", execUser) - t.Logf("expected: %#v", test.expected) - t.Fail() - continue - } - } -} - -func TestInvalidGetExecUser(t *testing.T) { - const passwdContent = ` -root:x:0:0:root user:/root:/bin/bash -adm:x:42:43:adm:/var/adm:/bin/false -this is just some garbage data -` - const groupContent = ` -root:x:0:root -adm:x:43: -grp:x:1234:root,adm -this is just some garbage data -` - - tests := []string{ - // No such user/group. - "notuser", - "notuser:notgroup", - "root:notgroup", - "notuser:adm", - "8888:notgroup", - "notuser:8888", - - // Invalid user/group values. - "-1:0", - "0:-3", - "-5:-2", - } - - for _, test := range tests { - passwd := strings.NewReader(passwdContent) - group := strings.NewReader(groupContent) - - execUser, err := GetExecUser(test, nil, passwd, group) - if err == nil { - t.Logf("got unexpected success when parsing '%s': %#v", test, execUser) - t.Fail() - continue - } - } -} - -func TestGetExecUserNilSources(t *testing.T) { - const passwdContent = ` -root:x:0:0:root user:/root:/bin/bash -adm:x:42:43:adm:/var/adm:/bin/false -this is just some garbage data -` - const groupContent = ` -root:x:0:root -adm:x:43: -grp:x:1234:root,adm -this is just some garbage data -` - - defaultExecUser := ExecUser{ - Uid: 8888, - Gid: 8888, - Sgids: []int{8888}, - Home: "/8888", - } - - tests := []struct { - ref string - passwd, group bool - expected ExecUser - }{ - { - ref: "", - passwd: false, - group: false, - expected: ExecUser{ - Uid: 8888, - Gid: 8888, - Sgids: []int{8888}, - Home: "/8888", - }, - }, - { - ref: "root", - passwd: true, - group: false, - expected: ExecUser{ - Uid: 0, - Gid: 0, - Sgids: []int{8888}, - Home: "/root", - }, - }, - { - ref: "0", - passwd: false, - group: false, - expected: ExecUser{ - Uid: 0, - Gid: 8888, - Sgids: []int{8888}, - Home: "/8888", - }, - }, - { - ref: "0:0", - passwd: false, - group: false, - expected: ExecUser{ - Uid: 0, - Gid: 0, - Sgids: []int{8888}, - Home: "/8888", - }, - }, - } - - for _, test := range tests { - var passwd, group io.Reader - - if test.passwd { - passwd = strings.NewReader(passwdContent) - } - - if test.group { - group = strings.NewReader(groupContent) - } - - execUser, err := GetExecUser(test.ref, &defaultExecUser, passwd, group) - if err != nil { - t.Logf("got unexpected error when parsing '%s': %s", test.ref, err.Error()) - t.Fail() - continue - } - - if !reflect.DeepEqual(test.expected, *execUser) { - t.Logf("got: %#v", execUser) - t.Logf("expected: %#v", test.expected) - t.Fail() - continue - } - } -} - -func TestGetAdditionalGroupsPath(t *testing.T) { - const groupContent = ` -root:x:0:root -adm:x:43: -grp:x:1234:root,adm -adm:x:4343:root,adm-duplicate -this is just some garbage data -` - tests := []struct { - groups []string - expected []int - hasError bool - }{ - { - // empty group - groups: []string{}, - expected: []int{}, - }, - { - // single group - groups: []string{"adm"}, - expected: []int{43}, - }, - { - // multiple groups - groups: []string{"adm", "grp"}, - expected: []int{43, 1234}, - }, - { - // invalid group - groups: []string{"adm", "grp", "not-exist"}, - expected: nil, - hasError: true, - }, - { - // group with numeric id - groups: []string{"43"}, - expected: []int{43}, - }, - { - // group with unknown numeric id - groups: []string{"adm", "10001"}, - expected: []int{43, 10001}, - }, - { - // groups specified twice with numeric and name - groups: []string{"adm", "43"}, - expected: []int{43}, - }, - { - // groups with too small id - groups: []string{"-1"}, - expected: nil, - hasError: true, - }, - { - // groups with too large id - groups: []string{strconv.Itoa(1 << 31)}, - expected: nil, - hasError: true, - }, - } - - for _, test := range tests { - tmpFile, err := ioutil.TempFile("", "get-additional-groups-path") - if err != nil { - t.Error(err) - } - fmt.Fprint(tmpFile, groupContent) - tmpFile.Close() - - gids, err := GetAdditionalGroupsPath(test.groups, tmpFile.Name()) - if test.hasError && err == nil { - t.Errorf("Parse(%#v) expects error but has none", test) - continue - } - if !test.hasError && err != nil { - t.Errorf("Parse(%#v) has error %v", test, err) - continue - } - sort.Sort(sort.IntSlice(gids)) - if !reflect.DeepEqual(gids, test.expected) { - t.Errorf("Gids(%v), expect %v from groups %v", gids, test.expected, test.groups) - } - } -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/context/LICENSE b/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/context/LICENSE deleted file mode 100644 index 0e5fb872..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/context/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2012 Rodrigo Moraes. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/context/README.md b/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/context/README.md deleted file mode 100644 index c60a31b0..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/context/README.md +++ /dev/null @@ -1,7 +0,0 @@ -context -======= -[![Build Status](https://travis-ci.org/gorilla/context.png?branch=master)](https://travis-ci.org/gorilla/context) - -gorilla/context is a general purpose registry for global request variables. - -Read the full documentation here: http://www.gorillatoolkit.org/pkg/context diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/context/context.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/context/context.go deleted file mode 100644 index 81cb128b..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/context/context.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2012 The Gorilla 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 context - -import ( - "net/http" - "sync" - "time" -) - -var ( - mutex sync.RWMutex - data = make(map[*http.Request]map[interface{}]interface{}) - datat = make(map[*http.Request]int64) -) - -// Set stores a value for a given key in a given request. -func Set(r *http.Request, key, val interface{}) { - mutex.Lock() - if data[r] == nil { - data[r] = make(map[interface{}]interface{}) - datat[r] = time.Now().Unix() - } - data[r][key] = val - mutex.Unlock() -} - -// Get returns a value stored for a given key in a given request. -func Get(r *http.Request, key interface{}) interface{} { - mutex.RLock() - if ctx := data[r]; ctx != nil { - value := ctx[key] - mutex.RUnlock() - return value - } - mutex.RUnlock() - return nil -} - -// GetOk returns stored value and presence state like multi-value return of map access. -func GetOk(r *http.Request, key interface{}) (interface{}, bool) { - mutex.RLock() - if _, ok := data[r]; ok { - value, ok := data[r][key] - mutex.RUnlock() - return value, ok - } - mutex.RUnlock() - return nil, false -} - -// GetAll returns all stored values for the request as a map. Nil is returned for invalid requests. -func GetAll(r *http.Request) map[interface{}]interface{} { - mutex.RLock() - if context, ok := data[r]; ok { - result := make(map[interface{}]interface{}, len(context)) - for k, v := range context { - result[k] = v - } - mutex.RUnlock() - return result - } - mutex.RUnlock() - return nil -} - -// GetAllOk returns all stored values for the request as a map and a boolean value that indicates if -// the request was registered. -func GetAllOk(r *http.Request) (map[interface{}]interface{}, bool) { - mutex.RLock() - context, ok := data[r] - result := make(map[interface{}]interface{}, len(context)) - for k, v := range context { - result[k] = v - } - mutex.RUnlock() - return result, ok -} - -// Delete removes a value stored for a given key in a given request. -func Delete(r *http.Request, key interface{}) { - mutex.Lock() - if data[r] != nil { - delete(data[r], key) - } - mutex.Unlock() -} - -// Clear removes all values stored for a given request. -// -// This is usually called by a handler wrapper to clean up request -// variables at the end of a request lifetime. See ClearHandler(). -func Clear(r *http.Request) { - mutex.Lock() - clear(r) - mutex.Unlock() -} - -// clear is Clear without the lock. -func clear(r *http.Request) { - delete(data, r) - delete(datat, r) -} - -// Purge removes request data stored for longer than maxAge, in seconds. -// It returns the amount of requests removed. -// -// If maxAge <= 0, all request data is removed. -// -// This is only used for sanity check: in case context cleaning was not -// properly set some request data can be kept forever, consuming an increasing -// amount of memory. In case this is detected, Purge() must be called -// periodically until the problem is fixed. -func Purge(maxAge int) int { - mutex.Lock() - count := 0 - if maxAge <= 0 { - count = len(data) - data = make(map[*http.Request]map[interface{}]interface{}) - datat = make(map[*http.Request]int64) - } else { - min := time.Now().Unix() - int64(maxAge) - for r := range data { - if datat[r] < min { - clear(r) - count++ - } - } - } - mutex.Unlock() - return count -} - -// ClearHandler wraps an http.Handler and clears request values at the end -// of a request lifetime. -func ClearHandler(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - defer Clear(r) - h.ServeHTTP(w, r) - }) -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/context/context_test.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/context/context_test.go deleted file mode 100644 index 9814c501..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/context/context_test.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2012 The Gorilla 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 context - -import ( - "net/http" - "testing" -) - -type keyType int - -const ( - key1 keyType = iota - key2 -) - -func TestContext(t *testing.T) { - assertEqual := func(val interface{}, exp interface{}) { - if val != exp { - t.Errorf("Expected %v, got %v.", exp, val) - } - } - - r, _ := http.NewRequest("GET", "http://localhost:8080/", nil) - emptyR, _ := http.NewRequest("GET", "http://localhost:8080/", nil) - - // Get() - assertEqual(Get(r, key1), nil) - - // Set() - Set(r, key1, "1") - assertEqual(Get(r, key1), "1") - assertEqual(len(data[r]), 1) - - Set(r, key2, "2") - assertEqual(Get(r, key2), "2") - assertEqual(len(data[r]), 2) - - //GetOk - value, ok := GetOk(r, key1) - assertEqual(value, "1") - assertEqual(ok, true) - - value, ok = GetOk(r, "not exists") - assertEqual(value, nil) - assertEqual(ok, false) - - Set(r, "nil value", nil) - value, ok = GetOk(r, "nil value") - assertEqual(value, nil) - assertEqual(ok, true) - - // GetAll() - values := GetAll(r) - assertEqual(len(values), 3) - - // GetAll() for empty request - values = GetAll(emptyR) - if values != nil { - t.Error("GetAll didn't return nil value for invalid request") - } - - // GetAllOk() - values, ok = GetAllOk(r) - assertEqual(len(values), 3) - assertEqual(ok, true) - - // GetAllOk() for empty request - values, ok = GetAllOk(emptyR) - assertEqual(value, nil) - assertEqual(ok, false) - - // Delete() - Delete(r, key1) - assertEqual(Get(r, key1), nil) - assertEqual(len(data[r]), 2) - - Delete(r, key2) - assertEqual(Get(r, key2), nil) - assertEqual(len(data[r]), 1) - - // Clear() - Clear(r) - assertEqual(len(data), 0) -} - -func parallelReader(r *http.Request, key string, iterations int, wait, done chan struct{}) { - <-wait - for i := 0; i < iterations; i++ { - Get(r, key) - } - done <- struct{}{} - -} - -func parallelWriter(r *http.Request, key, value string, iterations int, wait, done chan struct{}) { - <-wait - for i := 0; i < iterations; i++ { - Set(r, key, value) - } - done <- struct{}{} - -} - -func benchmarkMutex(b *testing.B, numReaders, numWriters, iterations int) { - - b.StopTimer() - r, _ := http.NewRequest("GET", "http://localhost:8080/", nil) - done := make(chan struct{}) - b.StartTimer() - - for i := 0; i < b.N; i++ { - wait := make(chan struct{}) - - for i := 0; i < numReaders; i++ { - go parallelReader(r, "test", iterations, wait, done) - } - - for i := 0; i < numWriters; i++ { - go parallelWriter(r, "test", "123", iterations, wait, done) - } - - close(wait) - - for i := 0; i < numReaders+numWriters; i++ { - <-done - } - - } - -} - -func BenchmarkMutexSameReadWrite1(b *testing.B) { - benchmarkMutex(b, 1, 1, 32) -} -func BenchmarkMutexSameReadWrite2(b *testing.B) { - benchmarkMutex(b, 2, 2, 32) -} -func BenchmarkMutexSameReadWrite4(b *testing.B) { - benchmarkMutex(b, 4, 4, 32) -} -func BenchmarkMutex1(b *testing.B) { - benchmarkMutex(b, 2, 8, 32) -} -func BenchmarkMutex2(b *testing.B) { - benchmarkMutex(b, 16, 4, 64) -} -func BenchmarkMutex3(b *testing.B) { - benchmarkMutex(b, 1, 2, 128) -} -func BenchmarkMutex4(b *testing.B) { - benchmarkMutex(b, 128, 32, 256) -} -func BenchmarkMutex5(b *testing.B) { - benchmarkMutex(b, 1024, 2048, 64) -} -func BenchmarkMutex6(b *testing.B) { - benchmarkMutex(b, 2048, 1024, 512) -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/context/doc.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/context/doc.go deleted file mode 100644 index 73c74003..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/context/doc.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2012 The Gorilla 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 context stores values shared during a request lifetime. - -For example, a router can set variables extracted from the URL and later -application handlers can access those values, or it can be used to store -sessions values to be saved at the end of a request. There are several -others common uses. - -The idea was posted by Brad Fitzpatrick to the go-nuts mailing list: - - http://groups.google.com/group/golang-nuts/msg/e2d679d303aa5d53 - -Here's the basic usage: first define the keys that you will need. The key -type is interface{} so a key can be of any type that supports equality. -Here we define a key using a custom int type to avoid name collisions: - - package foo - - import ( - "github.com/gorilla/context" - ) - - type key int - - const MyKey key = 0 - -Then set a variable. Variables are bound to an http.Request object, so you -need a request instance to set a value: - - context.Set(r, MyKey, "bar") - -The application can later access the variable using the same key you provided: - - func MyHandler(w http.ResponseWriter, r *http.Request) { - // val is "bar". - val := context.Get(r, foo.MyKey) - - // returns ("bar", true) - val, ok := context.GetOk(r, foo.MyKey) - // ... - } - -And that's all about the basic usage. We discuss some other ideas below. - -Any type can be stored in the context. To enforce a given type, make the key -private and wrap Get() and Set() to accept and return values of a specific -type: - - type key int - - const mykey key = 0 - - // GetMyKey returns a value for this package from the request values. - func GetMyKey(r *http.Request) SomeType { - if rv := context.Get(r, mykey); rv != nil { - return rv.(SomeType) - } - return nil - } - - // SetMyKey sets a value for this package in the request values. - func SetMyKey(r *http.Request, val SomeType) { - context.Set(r, mykey, val) - } - -Variables must be cleared at the end of a request, to remove all values -that were stored. This can be done in an http.Handler, after a request was -served. Just call Clear() passing the request: - - context.Clear(r) - -...or use ClearHandler(), which conveniently wraps an http.Handler to clear -variables at the end of a request lifetime. - -The Routers from the packages gorilla/mux and gorilla/pat call Clear() -so if you are using either of them you don't need to clear the context manually. -*/ -package context diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/LICENSE b/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/LICENSE deleted file mode 100644 index 0e5fb872..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2012 Rodrigo Moraes. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/README.md b/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/README.md deleted file mode 100644 index 9a046ff9..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/README.md +++ /dev/null @@ -1,235 +0,0 @@ -mux -=== -[![GoDoc](https://godoc.org/github.com/gorilla/securecookie?status.svg)](https://godoc.org/github.com/gorilla/securecookie) -[![Build Status](https://travis-ci.org/gorilla/mux.png?branch=master)](https://travis-ci.org/gorilla/mux) - -Package gorilla/mux implements a request router and dispatcher. - -The name mux stands for "HTTP request multiplexer". Like the standard -http.ServeMux, mux.Router matches incoming requests against a list of -registered routes and calls a handler for the route that matches the URL -or other conditions. The main features are: - - * Requests can be matched based on URL host, path, path prefix, schemes, - header and query values, HTTP methods or using custom matchers. - * URL hosts and paths can have variables with an optional regular - expression. - * Registered URLs can be built, or "reversed", which helps maintaining - references to resources. - * Routes can be used as subrouters: nested routes are only tested if the - parent route matches. This is useful to define groups of routes that - share common conditions like a host, a path prefix or other repeated - attributes. As a bonus, this optimizes request matching. - * It implements the http.Handler interface so it is compatible with the - standard http.ServeMux. - -Let's start registering a couple of URL paths and handlers: - - func main() { - r := mux.NewRouter() - r.HandleFunc("/", HomeHandler) - r.HandleFunc("/products", ProductsHandler) - r.HandleFunc("/articles", ArticlesHandler) - http.Handle("/", r) - } - -Here we register three routes mapping URL paths to handlers. This is -equivalent to how http.HandleFunc() works: if an incoming request URL matches -one of the paths, the corresponding handler is called passing -(http.ResponseWriter, *http.Request) as parameters. - -Paths can have variables. They are defined using the format {name} or -{name:pattern}. If a regular expression pattern is not defined, the matched -variable will be anything until the next slash. For example: - - r := mux.NewRouter() - r.HandleFunc("/products/{key}", ProductHandler) - r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler) - r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) - -The names are used to create a map of route variables which can be retrieved -calling mux.Vars(): - - vars := mux.Vars(request) - category := vars["category"] - -And this is all you need to know about the basic usage. More advanced options -are explained below. - -Routes can also be restricted to a domain or subdomain. Just define a host -pattern to be matched. They can also have variables: - - r := mux.NewRouter() - // Only matches if domain is "www.example.com". - r.Host("www.example.com") - // Matches a dynamic subdomain. - r.Host("{subdomain:[a-z]+}.domain.com") - -There are several other matchers that can be added. To match path prefixes: - - r.PathPrefix("/products/") - -...or HTTP methods: - - r.Methods("GET", "POST") - -...or URL schemes: - - r.Schemes("https") - -...or header values: - - r.Headers("X-Requested-With", "XMLHttpRequest") - -...or query values: - - r.Queries("key", "value") - -...or to use a custom matcher function: - - r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool { - return r.ProtoMajor == 0 - }) - -...and finally, it is possible to combine several matchers in a single route: - - r.HandleFunc("/products", ProductsHandler). - Host("www.example.com"). - Methods("GET"). - Schemes("http") - -Setting the same matching conditions again and again can be boring, so we have -a way to group several routes that share the same requirements. -We call it "subrouting". - -For example, let's say we have several URLs that should only match when the -host is `www.example.com`. Create a route for that host and get a "subrouter" -from it: - - r := mux.NewRouter() - s := r.Host("www.example.com").Subrouter() - -Then register routes in the subrouter: - - s.HandleFunc("/products/", ProductsHandler) - s.HandleFunc("/products/{key}", ProductHandler) - s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) - -The three URL paths we registered above will only be tested if the domain is -`www.example.com`, because the subrouter is tested first. This is not -only convenient, but also optimizes request matching. You can create -subrouters combining any attribute matchers accepted by a route. - -Subrouters can be used to create domain or path "namespaces": you define -subrouters in a central place and then parts of the app can register its -paths relatively to a given subrouter. - -There's one more thing about subroutes. When a subrouter has a path prefix, -the inner routes use it as base for their paths: - - r := mux.NewRouter() - s := r.PathPrefix("/products").Subrouter() - // "/products/" - s.HandleFunc("/", ProductsHandler) - // "/products/{key}/" - s.HandleFunc("/{key}/", ProductHandler) - // "/products/{key}/details" - s.HandleFunc("/{key}/details", ProductDetailsHandler) - -Now let's see how to build registered URLs. - -Routes can be named. All routes that define a name can have their URLs built, -or "reversed". We define a name calling Name() on a route. For example: - - r := mux.NewRouter() - r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). - Name("article") - -To build a URL, get the route and call the URL() method, passing a sequence of -key/value pairs for the route variables. For the previous route, we would do: - - url, err := r.Get("article").URL("category", "technology", "id", "42") - -...and the result will be a url.URL with the following path: - - "/articles/technology/42" - -This also works for host variables: - - r := mux.NewRouter() - r.Host("{subdomain}.domain.com"). - Path("/articles/{category}/{id:[0-9]+}"). - HandlerFunc(ArticleHandler). - Name("article") - - // url.String() will be "http://news.domain.com/articles/technology/42" - url, err := r.Get("article").URL("subdomain", "news", - "category", "technology", - "id", "42") - -All variables defined in the route are required, and their values must -conform to the corresponding patterns. These requirements guarantee that a -generated URL will always match a registered route -- the only exception is -for explicitly defined "build-only" routes which never match. - -Regex support also exists for matching Headers within a route. For example, we could do: - - r.HeadersRegexp("Content-Type", "application/(text|json)") - -...and the route will match both requests with a Content-Type of `application/json` as well as -`application/text` - -There's also a way to build only the URL host or path for a route: -use the methods URLHost() or URLPath() instead. For the previous route, -we would do: - - // "http://news.domain.com/" - host, err := r.Get("article").URLHost("subdomain", "news") - - // "/articles/technology/42" - path, err := r.Get("article").URLPath("category", "technology", "id", "42") - -And if you use subrouters, host and path defined separately can be built -as well: - - r := mux.NewRouter() - s := r.Host("{subdomain}.domain.com").Subrouter() - s.Path("/articles/{category}/{id:[0-9]+}"). - HandlerFunc(ArticleHandler). - Name("article") - - // "http://news.domain.com/articles/technology/42" - url, err := r.Get("article").URL("subdomain", "news", - "category", "technology", - "id", "42") - -## Full Example - -Here's a complete, runnable example of a small mux based server: - -```go -package main - -import ( - "net/http" - - "github.com/gorilla/mux" -) - -func YourHandler(w http.ResponseWriter, r *http.Request) { - w.Write([]byte("Gorilla!\n")) -} - -func main() { - r := mux.NewRouter() - // Routes consist of a path and a handler function. - r.HandleFunc("/", YourHandler) - - // Bind to a port and pass our router in - http.ListenAndServe(":8000", r) -} -``` - -## License - -BSD licensed. See the LICENSE file for details. diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/bench_test.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/bench_test.go deleted file mode 100644 index c5f97b2b..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/bench_test.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Gorilla 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 mux - -import ( - "net/http" - "testing" -) - -func BenchmarkMux(b *testing.B) { - router := new(Router) - handler := func(w http.ResponseWriter, r *http.Request) {} - router.HandleFunc("/v1/{v1}", handler) - - request, _ := http.NewRequest("GET", "/v1/anything", nil) - for i := 0; i < b.N; i++ { - router.ServeHTTP(nil, request) - } -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/doc.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/doc.go deleted file mode 100644 index 49798cb5..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/doc.go +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2012 The Gorilla 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 gorilla/mux implements a request router and dispatcher. - -The name mux stands for "HTTP request multiplexer". Like the standard -http.ServeMux, mux.Router matches incoming requests against a list of -registered routes and calls a handler for the route that matches the URL -or other conditions. The main features are: - - * Requests can be matched based on URL host, path, path prefix, schemes, - header and query values, HTTP methods or using custom matchers. - * URL hosts and paths can have variables with an optional regular - expression. - * Registered URLs can be built, or "reversed", which helps maintaining - references to resources. - * Routes can be used as subrouters: nested routes are only tested if the - parent route matches. This is useful to define groups of routes that - share common conditions like a host, a path prefix or other repeated - attributes. As a bonus, this optimizes request matching. - * It implements the http.Handler interface so it is compatible with the - standard http.ServeMux. - -Let's start registering a couple of URL paths and handlers: - - func main() { - r := mux.NewRouter() - r.HandleFunc("/", HomeHandler) - r.HandleFunc("/products", ProductsHandler) - r.HandleFunc("/articles", ArticlesHandler) - http.Handle("/", r) - } - -Here we register three routes mapping URL paths to handlers. This is -equivalent to how http.HandleFunc() works: if an incoming request URL matches -one of the paths, the corresponding handler is called passing -(http.ResponseWriter, *http.Request) as parameters. - -Paths can have variables. They are defined using the format {name} or -{name:pattern}. If a regular expression pattern is not defined, the matched -variable will be anything until the next slash. For example: - - r := mux.NewRouter() - r.HandleFunc("/products/{key}", ProductHandler) - r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler) - r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) - -The names are used to create a map of route variables which can be retrieved -calling mux.Vars(): - - vars := mux.Vars(request) - category := vars["category"] - -And this is all you need to know about the basic usage. More advanced options -are explained below. - -Routes can also be restricted to a domain or subdomain. Just define a host -pattern to be matched. They can also have variables: - - r := mux.NewRouter() - // Only matches if domain is "www.example.com". - r.Host("www.example.com") - // Matches a dynamic subdomain. - r.Host("{subdomain:[a-z]+}.domain.com") - -There are several other matchers that can be added. To match path prefixes: - - r.PathPrefix("/products/") - -...or HTTP methods: - - r.Methods("GET", "POST") - -...or URL schemes: - - r.Schemes("https") - -...or header values: - - r.Headers("X-Requested-With", "XMLHttpRequest") - -...or query values: - - r.Queries("key", "value") - -...or to use a custom matcher function: - - r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool { - return r.ProtoMajor == 0 - }) - -...and finally, it is possible to combine several matchers in a single route: - - r.HandleFunc("/products", ProductsHandler). - Host("www.example.com"). - Methods("GET"). - Schemes("http") - -Setting the same matching conditions again and again can be boring, so we have -a way to group several routes that share the same requirements. -We call it "subrouting". - -For example, let's say we have several URLs that should only match when the -host is "www.example.com". Create a route for that host and get a "subrouter" -from it: - - r := mux.NewRouter() - s := r.Host("www.example.com").Subrouter() - -Then register routes in the subrouter: - - s.HandleFunc("/products/", ProductsHandler) - s.HandleFunc("/products/{key}", ProductHandler) - s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) - -The three URL paths we registered above will only be tested if the domain is -"www.example.com", because the subrouter is tested first. This is not -only convenient, but also optimizes request matching. You can create -subrouters combining any attribute matchers accepted by a route. - -Subrouters can be used to create domain or path "namespaces": you define -subrouters in a central place and then parts of the app can register its -paths relatively to a given subrouter. - -There's one more thing about subroutes. When a subrouter has a path prefix, -the inner routes use it as base for their paths: - - r := mux.NewRouter() - s := r.PathPrefix("/products").Subrouter() - // "/products/" - s.HandleFunc("/", ProductsHandler) - // "/products/{key}/" - s.HandleFunc("/{key}/", ProductHandler) - // "/products/{key}/details" - s.HandleFunc("/{key}/details", ProductDetailsHandler) - -Now let's see how to build registered URLs. - -Routes can be named. All routes that define a name can have their URLs built, -or "reversed". We define a name calling Name() on a route. For example: - - r := mux.NewRouter() - r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). - Name("article") - -To build a URL, get the route and call the URL() method, passing a sequence of -key/value pairs for the route variables. For the previous route, we would do: - - url, err := r.Get("article").URL("category", "technology", "id", "42") - -...and the result will be a url.URL with the following path: - - "/articles/technology/42" - -This also works for host variables: - - r := mux.NewRouter() - r.Host("{subdomain}.domain.com"). - Path("/articles/{category}/{id:[0-9]+}"). - HandlerFunc(ArticleHandler). - Name("article") - - // url.String() will be "http://news.domain.com/articles/technology/42" - url, err := r.Get("article").URL("subdomain", "news", - "category", "technology", - "id", "42") - -All variables defined in the route are required, and their values must -conform to the corresponding patterns. These requirements guarantee that a -generated URL will always match a registered route -- the only exception is -for explicitly defined "build-only" routes which never match. - -Regex support also exists for matching Headers within a route. For example, we could do: - - r.HeadersRegexp("Content-Type", "application/(text|json)") - -...and the route will match both requests with a Content-Type of `application/json` as well as -`application/text` - -There's also a way to build only the URL host or path for a route: -use the methods URLHost() or URLPath() instead. For the previous route, -we would do: - - // "http://news.domain.com/" - host, err := r.Get("article").URLHost("subdomain", "news") - - // "/articles/technology/42" - path, err := r.Get("article").URLPath("category", "technology", "id", "42") - -And if you use subrouters, host and path defined separately can be built -as well: - - r := mux.NewRouter() - s := r.Host("{subdomain}.domain.com").Subrouter() - s.Path("/articles/{category}/{id:[0-9]+}"). - HandlerFunc(ArticleHandler). - Name("article") - - // "http://news.domain.com/articles/technology/42" - url, err := r.Get("article").URL("subdomain", "news", - "category", "technology", - "id", "42") -*/ -package mux diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/mux.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/mux.go deleted file mode 100644 index 21c9d9ae..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/mux.go +++ /dev/null @@ -1,474 +0,0 @@ -// Copyright 2012 The Gorilla 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 mux - -import ( - "errors" - "fmt" - "net/http" - "path" - "regexp" - - "github.com/fsouza/go-dockerclient/external/github.com/gorilla/context" -) - -// NewRouter returns a new router instance. -func NewRouter() *Router { - return &Router{namedRoutes: make(map[string]*Route), KeepContext: false} -} - -// Router registers routes to be matched and dispatches a handler. -// -// It implements the http.Handler interface, so it can be registered to serve -// requests: -// -// var router = mux.NewRouter() -// -// func main() { -// http.Handle("/", router) -// } -// -// Or, for Google App Engine, register it in a init() function: -// -// func init() { -// http.Handle("/", router) -// } -// -// This will send all incoming requests to the router. -type Router struct { - // Configurable Handler to be used when no route matches. - NotFoundHandler http.Handler - // Parent route, if this is a subrouter. - parent parentRoute - // Routes to be matched, in order. - routes []*Route - // Routes by name for URL building. - namedRoutes map[string]*Route - // See Router.StrictSlash(). This defines the flag for new routes. - strictSlash bool - // If true, do not clear the request context after handling the request - KeepContext bool -} - -// Match matches registered routes against the request. -func (r *Router) Match(req *http.Request, match *RouteMatch) bool { - for _, route := range r.routes { - if route.Match(req, match) { - return true - } - } - return false -} - -// ServeHTTP dispatches the handler registered in the matched route. -// -// When there is a match, the route variables can be retrieved calling -// mux.Vars(request). -func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { - // Clean path to canonical form and redirect. - if p := cleanPath(req.URL.Path); p != req.URL.Path { - - // Added 3 lines (Philip Schlump) - It was dropping the query string and #whatever from query. - // This matches with fix in go 1.2 r.c. 4 for same problem. Go Issue: - // http://code.google.com/p/go/issues/detail?id=5252 - url := *req.URL - url.Path = p - p = url.String() - - w.Header().Set("Location", p) - w.WriteHeader(http.StatusMovedPermanently) - return - } - var match RouteMatch - var handler http.Handler - if r.Match(req, &match) { - handler = match.Handler - setVars(req, match.Vars) - setCurrentRoute(req, match.Route) - } - if handler == nil { - handler = r.NotFoundHandler - if handler == nil { - handler = http.NotFoundHandler() - } - } - if !r.KeepContext { - defer context.Clear(req) - } - handler.ServeHTTP(w, req) -} - -// Get returns a route registered with the given name. -func (r *Router) Get(name string) *Route { - return r.getNamedRoutes()[name] -} - -// GetRoute returns a route registered with the given name. This method -// was renamed to Get() and remains here for backwards compatibility. -func (r *Router) GetRoute(name string) *Route { - return r.getNamedRoutes()[name] -} - -// StrictSlash defines the trailing slash behavior for new routes. The initial -// value is false. -// -// When true, if the route path is "/path/", accessing "/path" will redirect -// to the former and vice versa. In other words, your application will always -// see the path as specified in the route. -// -// When false, if the route path is "/path", accessing "/path/" will not match -// this route and vice versa. -// -// Special case: when a route sets a path prefix using the PathPrefix() method, -// strict slash is ignored for that route because the redirect behavior can't -// be determined from a prefix alone. However, any subrouters created from that -// route inherit the original StrictSlash setting. -func (r *Router) StrictSlash(value bool) *Router { - r.strictSlash = value - return r -} - -// ---------------------------------------------------------------------------- -// parentRoute -// ---------------------------------------------------------------------------- - -// getNamedRoutes returns the map where named routes are registered. -func (r *Router) getNamedRoutes() map[string]*Route { - if r.namedRoutes == nil { - if r.parent != nil { - r.namedRoutes = r.parent.getNamedRoutes() - } else { - r.namedRoutes = make(map[string]*Route) - } - } - return r.namedRoutes -} - -// getRegexpGroup returns regexp definitions from the parent route, if any. -func (r *Router) getRegexpGroup() *routeRegexpGroup { - if r.parent != nil { - return r.parent.getRegexpGroup() - } - return nil -} - -func (r *Router) buildVars(m map[string]string) map[string]string { - if r.parent != nil { - m = r.parent.buildVars(m) - } - return m -} - -// ---------------------------------------------------------------------------- -// Route factories -// ---------------------------------------------------------------------------- - -// NewRoute registers an empty route. -func (r *Router) NewRoute() *Route { - route := &Route{parent: r, strictSlash: r.strictSlash} - r.routes = append(r.routes, route) - return route -} - -// Handle registers a new route with a matcher for the URL path. -// See Route.Path() and Route.Handler(). -func (r *Router) Handle(path string, handler http.Handler) *Route { - return r.NewRoute().Path(path).Handler(handler) -} - -// HandleFunc registers a new route with a matcher for the URL path. -// See Route.Path() and Route.HandlerFunc(). -func (r *Router) HandleFunc(path string, f func(http.ResponseWriter, - *http.Request)) *Route { - return r.NewRoute().Path(path).HandlerFunc(f) -} - -// Headers registers a new route with a matcher for request header values. -// See Route.Headers(). -func (r *Router) Headers(pairs ...string) *Route { - return r.NewRoute().Headers(pairs...) -} - -// Host registers a new route with a matcher for the URL host. -// See Route.Host(). -func (r *Router) Host(tpl string) *Route { - return r.NewRoute().Host(tpl) -} - -// MatcherFunc registers a new route with a custom matcher function. -// See Route.MatcherFunc(). -func (r *Router) MatcherFunc(f MatcherFunc) *Route { - return r.NewRoute().MatcherFunc(f) -} - -// Methods registers a new route with a matcher for HTTP methods. -// See Route.Methods(). -func (r *Router) Methods(methods ...string) *Route { - return r.NewRoute().Methods(methods...) -} - -// Path registers a new route with a matcher for the URL path. -// See Route.Path(). -func (r *Router) Path(tpl string) *Route { - return r.NewRoute().Path(tpl) -} - -// PathPrefix registers a new route with a matcher for the URL path prefix. -// See Route.PathPrefix(). -func (r *Router) PathPrefix(tpl string) *Route { - return r.NewRoute().PathPrefix(tpl) -} - -// Queries registers a new route with a matcher for URL query values. -// See Route.Queries(). -func (r *Router) Queries(pairs ...string) *Route { - return r.NewRoute().Queries(pairs...) -} - -// Schemes registers a new route with a matcher for URL schemes. -// See Route.Schemes(). -func (r *Router) Schemes(schemes ...string) *Route { - return r.NewRoute().Schemes(schemes...) -} - -// BuildVars registers a new route with a custom function for modifying -// route variables before building a URL. -func (r *Router) BuildVarsFunc(f BuildVarsFunc) *Route { - return r.NewRoute().BuildVarsFunc(f) -} - -// Walk walks the router and all its sub-routers, calling walkFn for each route -// in the tree. The routes are walked in the order they were added. Sub-routers -// are explored depth-first. -func (r *Router) Walk(walkFn WalkFunc) error { - return r.walk(walkFn, []*Route{}) -} - -// SkipRouter is used as a return value from WalkFuncs to indicate that the -// router that walk is about to descend down to should be skipped. -var SkipRouter = errors.New("skip this router") - -// WalkFunc is the type of the function called for each route visited by Walk. -// At every invocation, it is given the current route, and the current router, -// and a list of ancestor routes that lead to the current route. -type WalkFunc func(route *Route, router *Router, ancestors []*Route) error - -func (r *Router) walk(walkFn WalkFunc, ancestors []*Route) error { - for _, t := range r.routes { - if t.regexp == nil || t.regexp.path == nil || t.regexp.path.template == "" { - continue - } - - err := walkFn(t, r, ancestors) - if err == SkipRouter { - continue - } - for _, sr := range t.matchers { - if h, ok := sr.(*Router); ok { - err := h.walk(walkFn, ancestors) - if err != nil { - return err - } - } - } - if h, ok := t.handler.(*Router); ok { - ancestors = append(ancestors, t) - err := h.walk(walkFn, ancestors) - if err != nil { - return err - } - ancestors = ancestors[:len(ancestors)-1] - } - } - return nil -} - -// ---------------------------------------------------------------------------- -// Context -// ---------------------------------------------------------------------------- - -// RouteMatch stores information about a matched route. -type RouteMatch struct { - Route *Route - Handler http.Handler - Vars map[string]string -} - -type contextKey int - -const ( - varsKey contextKey = iota - routeKey -) - -// Vars returns the route variables for the current request, if any. -func Vars(r *http.Request) map[string]string { - if rv := context.Get(r, varsKey); rv != nil { - return rv.(map[string]string) - } - return nil -} - -// CurrentRoute returns the matched route for the current request, if any. -// This only works when called inside the handler of the matched route -// because the matched route is stored in the request context which is cleared -// after the handler returns, unless the KeepContext option is set on the -// Router. -func CurrentRoute(r *http.Request) *Route { - if rv := context.Get(r, routeKey); rv != nil { - return rv.(*Route) - } - return nil -} - -func setVars(r *http.Request, val interface{}) { - context.Set(r, varsKey, val) -} - -func setCurrentRoute(r *http.Request, val interface{}) { - context.Set(r, routeKey, val) -} - -// ---------------------------------------------------------------------------- -// Helpers -// ---------------------------------------------------------------------------- - -// cleanPath returns the canonical path for p, eliminating . and .. elements. -// Borrowed from the net/http package. -func cleanPath(p string) string { - if p == "" { - return "/" - } - if p[0] != '/' { - p = "/" + p - } - np := path.Clean(p) - // path.Clean removes trailing slash except for root; - // put the trailing slash back if necessary. - if p[len(p)-1] == '/' && np != "/" { - np += "/" - } - return np -} - -// uniqueVars returns an error if two slices contain duplicated strings. -func uniqueVars(s1, s2 []string) error { - for _, v1 := range s1 { - for _, v2 := range s2 { - if v1 == v2 { - return fmt.Errorf("mux: duplicated route variable %q", v2) - } - } - } - return nil -} - -// checkPairs returns the count of strings passed in, and an error if -// the count is not an even number. -func checkPairs(pairs ...string) (int, error) { - length := len(pairs) - if length%2 != 0 { - return length, fmt.Errorf( - "mux: number of parameters must be multiple of 2, got %v", pairs) - } - return length, nil -} - -// mapFromPairsToString converts variadic string parameters to a -// string to string map. -func mapFromPairsToString(pairs ...string) (map[string]string, error) { - length, err := checkPairs(pairs...) - if err != nil { - return nil, err - } - m := make(map[string]string, length/2) - for i := 0; i < length; i += 2 { - m[pairs[i]] = pairs[i+1] - } - return m, nil -} - -// mapFromPairsToRegex converts variadic string paramers to a -// string to regex map. -func mapFromPairsToRegex(pairs ...string) (map[string]*regexp.Regexp, error) { - length, err := checkPairs(pairs...) - if err != nil { - return nil, err - } - m := make(map[string]*regexp.Regexp, length/2) - for i := 0; i < length; i += 2 { - regex, err := regexp.Compile(pairs[i+1]) - if err != nil { - return nil, err - } - m[pairs[i]] = regex - } - return m, nil -} - -// matchInArray returns true if the given string value is in the array. -func matchInArray(arr []string, value string) bool { - for _, v := range arr { - if v == value { - return true - } - } - return false -} - -// matchMapWithString returns true if the given key/value pairs exist in a given map. -func matchMapWithString(toCheck map[string]string, toMatch map[string][]string, canonicalKey bool) bool { - for k, v := range toCheck { - // Check if key exists. - if canonicalKey { - k = http.CanonicalHeaderKey(k) - } - if values := toMatch[k]; values == nil { - return false - } else if v != "" { - // If value was defined as an empty string we only check that the - // key exists. Otherwise we also check for equality. - valueExists := false - for _, value := range values { - if v == value { - valueExists = true - break - } - } - if !valueExists { - return false - } - } - } - return true -} - -// matchMapWithRegex returns true if the given key/value pairs exist in a given map compiled against -// the given regex -func matchMapWithRegex(toCheck map[string]*regexp.Regexp, toMatch map[string][]string, canonicalKey bool) bool { - for k, v := range toCheck { - // Check if key exists. - if canonicalKey { - k = http.CanonicalHeaderKey(k) - } - if values := toMatch[k]; values == nil { - return false - } else if v != nil { - // If value was defined as an empty string we only check that the - // key exists. Otherwise we also check for equality. - valueExists := false - for _, value := range values { - if v.MatchString(value) { - valueExists = true - break - } - } - if !valueExists { - return false - } - } - } - return true -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/mux_test.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/mux_test.go deleted file mode 100644 index 74cb98b8..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/mux_test.go +++ /dev/null @@ -1,1334 +0,0 @@ -// Copyright 2012 The Gorilla 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 mux - -import ( - "fmt" - "net/http" - "strings" - "testing" - - "github.com/fsouza/go-dockerclient/external/github.com/gorilla/context" -) - -func (r *Route) GoString() string { - matchers := make([]string, len(r.matchers)) - for i, m := range r.matchers { - matchers[i] = fmt.Sprintf("%#v", m) - } - return fmt.Sprintf("&Route{matchers:[]matcher{%s}}", strings.Join(matchers, ", ")) -} - -func (r *routeRegexp) GoString() string { - return fmt.Sprintf("&routeRegexp{template: %q, matchHost: %t, matchQuery: %t, strictSlash: %t, regexp: regexp.MustCompile(%q), reverse: %q, varsN: %v, varsR: %v", r.template, r.matchHost, r.matchQuery, r.strictSlash, r.regexp.String(), r.reverse, r.varsN, r.varsR) -} - -type routeTest struct { - title string // title of the test - route *Route // the route being tested - request *http.Request // a request to test the route - vars map[string]string // the expected vars of the match - host string // the expected host of the match - path string // the expected path of the match - shouldMatch bool // whether the request is expected to match the route at all - shouldRedirect bool // whether the request should result in a redirect -} - -func TestHost(t *testing.T) { - // newRequestHost a new request with a method, url, and host header - newRequestHost := func(method, url, host string) *http.Request { - req, err := http.NewRequest(method, url, nil) - if err != nil { - panic(err) - } - req.Host = host - return req - } - - tests := []routeTest{ - { - title: "Host route match", - route: new(Route).Host("aaa.bbb.ccc"), - request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{}, - host: "aaa.bbb.ccc", - path: "", - shouldMatch: true, - }, - { - title: "Host route, wrong host in request URL", - route: new(Route).Host("aaa.bbb.ccc"), - request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), - vars: map[string]string{}, - host: "aaa.bbb.ccc", - path: "", - shouldMatch: false, - }, - { - title: "Host route with port, match", - route: new(Route).Host("aaa.bbb.ccc:1234"), - request: newRequest("GET", "http://aaa.bbb.ccc:1234/111/222/333"), - vars: map[string]string{}, - host: "aaa.bbb.ccc:1234", - path: "", - shouldMatch: true, - }, - { - title: "Host route with port, wrong port in request URL", - route: new(Route).Host("aaa.bbb.ccc:1234"), - request: newRequest("GET", "http://aaa.bbb.ccc:9999/111/222/333"), - vars: map[string]string{}, - host: "aaa.bbb.ccc:1234", - path: "", - shouldMatch: false, - }, - { - title: "Host route, match with host in request header", - route: new(Route).Host("aaa.bbb.ccc"), - request: newRequestHost("GET", "/111/222/333", "aaa.bbb.ccc"), - vars: map[string]string{}, - host: "aaa.bbb.ccc", - path: "", - shouldMatch: true, - }, - { - title: "Host route, wrong host in request header", - route: new(Route).Host("aaa.bbb.ccc"), - request: newRequestHost("GET", "/111/222/333", "aaa.222.ccc"), - vars: map[string]string{}, - host: "aaa.bbb.ccc", - path: "", - shouldMatch: false, - }, - // BUG {new(Route).Host("aaa.bbb.ccc:1234"), newRequestHost("GET", "/111/222/333", "aaa.bbb.ccc:1234"), map[string]string{}, "aaa.bbb.ccc:1234", "", true}, - { - title: "Host route with port, wrong host in request header", - route: new(Route).Host("aaa.bbb.ccc:1234"), - request: newRequestHost("GET", "/111/222/333", "aaa.bbb.ccc:9999"), - vars: map[string]string{}, - host: "aaa.bbb.ccc:1234", - path: "", - shouldMatch: false, - }, - { - title: "Host route with pattern, match", - route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc"), - request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{"v1": "bbb"}, - host: "aaa.bbb.ccc", - path: "", - shouldMatch: true, - }, - { - title: "Host route with pattern, additional capturing group, match", - route: new(Route).Host("aaa.{v1:[a-z]{2}(b|c)}.ccc"), - request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{"v1": "bbb"}, - host: "aaa.bbb.ccc", - path: "", - shouldMatch: true, - }, - { - title: "Host route with pattern, wrong host in request URL", - route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc"), - request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), - vars: map[string]string{"v1": "bbb"}, - host: "aaa.bbb.ccc", - path: "", - shouldMatch: false, - }, - { - title: "Host route with multiple patterns, match", - route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}"), - request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc"}, - host: "aaa.bbb.ccc", - path: "", - shouldMatch: true, - }, - { - title: "Host route with multiple patterns, wrong host in request URL", - route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}"), - request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), - vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc"}, - host: "aaa.bbb.ccc", - path: "", - shouldMatch: false, - }, - { - title: "Host route with hyphenated name and pattern, match", - route: new(Route).Host("aaa.{v-1:[a-z]{3}}.ccc"), - request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{"v-1": "bbb"}, - host: "aaa.bbb.ccc", - path: "", - shouldMatch: true, - }, - { - title: "Host route with hyphenated name and pattern, additional capturing group, match", - route: new(Route).Host("aaa.{v-1:[a-z]{2}(b|c)}.ccc"), - request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{"v-1": "bbb"}, - host: "aaa.bbb.ccc", - path: "", - shouldMatch: true, - }, - { - title: "Host route with multiple hyphenated names and patterns, match", - route: new(Route).Host("{v-1:[a-z]{3}}.{v-2:[a-z]{3}}.{v-3:[a-z]{3}}"), - request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{"v-1": "aaa", "v-2": "bbb", "v-3": "ccc"}, - host: "aaa.bbb.ccc", - path: "", - shouldMatch: true, - }, - { - title: "Path route with single pattern with pipe, match", - route: new(Route).Path("/{category:a|b/c}"), - request: newRequest("GET", "http://localhost/a"), - vars: map[string]string{"category": "a"}, - host: "", - path: "/a", - shouldMatch: true, - }, - { - title: "Path route with single pattern with pipe, match", - route: new(Route).Path("/{category:a|b/c}"), - request: newRequest("GET", "http://localhost/b/c"), - vars: map[string]string{"category": "b/c"}, - host: "", - path: "/b/c", - shouldMatch: true, - }, - { - title: "Path route with multiple patterns with pipe, match", - route: new(Route).Path("/{category:a|b/c}/{product}/{id:[0-9]+}"), - request: newRequest("GET", "http://localhost/a/product_name/1"), - vars: map[string]string{"category": "a", "product": "product_name", "id": "1"}, - host: "", - path: "/a/product_name/1", - shouldMatch: true, - }, - { - title: "Path route with multiple patterns with pipe, match", - route: new(Route).Path("/{category:a|b/c}/{product}/{id:[0-9]+}"), - request: newRequest("GET", "http://localhost/b/c/product_name/1"), - vars: map[string]string{"category": "b/c", "product": "product_name", "id": "1"}, - host: "", - path: "/b/c/product_name/1", - shouldMatch: true, - }, - } - for _, test := range tests { - testRoute(t, test) - } -} - -func TestPath(t *testing.T) { - tests := []routeTest{ - { - title: "Path route, match", - route: new(Route).Path("/111/222/333"), - request: newRequest("GET", "http://localhost/111/222/333"), - vars: map[string]string{}, - host: "", - path: "/111/222/333", - shouldMatch: true, - }, - { - title: "Path route, match with trailing slash in request and path", - route: new(Route).Path("/111/"), - request: newRequest("GET", "http://localhost/111/"), - vars: map[string]string{}, - host: "", - path: "/111/", - shouldMatch: true, - }, - { - title: "Path route, do not match with trailing slash in path", - route: new(Route).Path("/111/"), - request: newRequest("GET", "http://localhost/111"), - vars: map[string]string{}, - host: "", - path: "/111", - shouldMatch: false, - }, - { - title: "Path route, do not match with trailing slash in request", - route: new(Route).Path("/111"), - request: newRequest("GET", "http://localhost/111/"), - vars: map[string]string{}, - host: "", - path: "/111/", - shouldMatch: false, - }, - { - title: "Path route, wrong path in request in request URL", - route: new(Route).Path("/111/222/333"), - request: newRequest("GET", "http://localhost/1/2/3"), - vars: map[string]string{}, - host: "", - path: "/111/222/333", - shouldMatch: false, - }, - { - title: "Path route with pattern, match", - route: new(Route).Path("/111/{v1:[0-9]{3}}/333"), - request: newRequest("GET", "http://localhost/111/222/333"), - vars: map[string]string{"v1": "222"}, - host: "", - path: "/111/222/333", - shouldMatch: true, - }, - { - title: "Path route with pattern, URL in request does not match", - route: new(Route).Path("/111/{v1:[0-9]{3}}/333"), - request: newRequest("GET", "http://localhost/111/aaa/333"), - vars: map[string]string{"v1": "222"}, - host: "", - path: "/111/222/333", - shouldMatch: false, - }, - { - title: "Path route with multiple patterns, match", - route: new(Route).Path("/{v1:[0-9]{3}}/{v2:[0-9]{3}}/{v3:[0-9]{3}}"), - request: newRequest("GET", "http://localhost/111/222/333"), - vars: map[string]string{"v1": "111", "v2": "222", "v3": "333"}, - host: "", - path: "/111/222/333", - shouldMatch: true, - }, - { - title: "Path route with multiple patterns, URL in request does not match", - route: new(Route).Path("/{v1:[0-9]{3}}/{v2:[0-9]{3}}/{v3:[0-9]{3}}"), - request: newRequest("GET", "http://localhost/111/aaa/333"), - vars: map[string]string{"v1": "111", "v2": "222", "v3": "333"}, - host: "", - path: "/111/222/333", - shouldMatch: false, - }, - { - title: "Path route with multiple patterns with pipe, match", - route: new(Route).Path("/{category:a|(b/c)}/{product}/{id:[0-9]+}"), - request: newRequest("GET", "http://localhost/a/product_name/1"), - vars: map[string]string{"category": "a", "product": "product_name", "id": "1"}, - host: "", - path: "/a/product_name/1", - shouldMatch: true, - }, - { - title: "Path route with hyphenated name and pattern, match", - route: new(Route).Path("/111/{v-1:[0-9]{3}}/333"), - request: newRequest("GET", "http://localhost/111/222/333"), - vars: map[string]string{"v-1": "222"}, - host: "", - path: "/111/222/333", - shouldMatch: true, - }, - { - title: "Path route with multiple hyphenated names and patterns, match", - route: new(Route).Path("/{v-1:[0-9]{3}}/{v-2:[0-9]{3}}/{v-3:[0-9]{3}}"), - request: newRequest("GET", "http://localhost/111/222/333"), - vars: map[string]string{"v-1": "111", "v-2": "222", "v-3": "333"}, - host: "", - path: "/111/222/333", - shouldMatch: true, - }, - { - title: "Path route with multiple hyphenated names and patterns with pipe, match", - route: new(Route).Path("/{product-category:a|(b/c)}/{product-name}/{product-id:[0-9]+}"), - request: newRequest("GET", "http://localhost/a/product_name/1"), - vars: map[string]string{"product-category": "a", "product-name": "product_name", "product-id": "1"}, - host: "", - path: "/a/product_name/1", - shouldMatch: true, - }, - } - - for _, test := range tests { - testRoute(t, test) - } -} - -func TestPathPrefix(t *testing.T) { - tests := []routeTest{ - { - title: "PathPrefix route, match", - route: new(Route).PathPrefix("/111"), - request: newRequest("GET", "http://localhost/111/222/333"), - vars: map[string]string{}, - host: "", - path: "/111", - shouldMatch: true, - }, - { - title: "PathPrefix route, match substring", - route: new(Route).PathPrefix("/1"), - request: newRequest("GET", "http://localhost/111/222/333"), - vars: map[string]string{}, - host: "", - path: "/1", - shouldMatch: true, - }, - { - title: "PathPrefix route, URL prefix in request does not match", - route: new(Route).PathPrefix("/111"), - request: newRequest("GET", "http://localhost/1/2/3"), - vars: map[string]string{}, - host: "", - path: "/111", - shouldMatch: false, - }, - { - title: "PathPrefix route with pattern, match", - route: new(Route).PathPrefix("/111/{v1:[0-9]{3}}"), - request: newRequest("GET", "http://localhost/111/222/333"), - vars: map[string]string{"v1": "222"}, - host: "", - path: "/111/222", - shouldMatch: true, - }, - { - title: "PathPrefix route with pattern, URL prefix in request does not match", - route: new(Route).PathPrefix("/111/{v1:[0-9]{3}}"), - request: newRequest("GET", "http://localhost/111/aaa/333"), - vars: map[string]string{"v1": "222"}, - host: "", - path: "/111/222", - shouldMatch: false, - }, - { - title: "PathPrefix route with multiple patterns, match", - route: new(Route).PathPrefix("/{v1:[0-9]{3}}/{v2:[0-9]{3}}"), - request: newRequest("GET", "http://localhost/111/222/333"), - vars: map[string]string{"v1": "111", "v2": "222"}, - host: "", - path: "/111/222", - shouldMatch: true, - }, - { - title: "PathPrefix route with multiple patterns, URL prefix in request does not match", - route: new(Route).PathPrefix("/{v1:[0-9]{3}}/{v2:[0-9]{3}}"), - request: newRequest("GET", "http://localhost/111/aaa/333"), - vars: map[string]string{"v1": "111", "v2": "222"}, - host: "", - path: "/111/222", - shouldMatch: false, - }, - } - - for _, test := range tests { - testRoute(t, test) - } -} - -func TestHostPath(t *testing.T) { - tests := []routeTest{ - { - title: "Host and Path route, match", - route: new(Route).Host("aaa.bbb.ccc").Path("/111/222/333"), - request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Host and Path route, wrong host in request URL", - route: new(Route).Host("aaa.bbb.ccc").Path("/111/222/333"), - request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: false, - }, - { - title: "Host and Path route with pattern, match", - route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc").Path("/111/{v2:[0-9]{3}}/333"), - request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{"v1": "bbb", "v2": "222"}, - host: "aaa.bbb.ccc", - path: "/111/222/333", - shouldMatch: true, - }, - { - title: "Host and Path route with pattern, URL in request does not match", - route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc").Path("/111/{v2:[0-9]{3}}/333"), - request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), - vars: map[string]string{"v1": "bbb", "v2": "222"}, - host: "aaa.bbb.ccc", - path: "/111/222/333", - shouldMatch: false, - }, - { - title: "Host and Path route with multiple patterns, match", - route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}").Path("/{v4:[0-9]{3}}/{v5:[0-9]{3}}/{v6:[0-9]{3}}"), - request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc", "v4": "111", "v5": "222", "v6": "333"}, - host: "aaa.bbb.ccc", - path: "/111/222/333", - shouldMatch: true, - }, - { - title: "Host and Path route with multiple patterns, URL in request does not match", - route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}").Path("/{v4:[0-9]{3}}/{v5:[0-9]{3}}/{v6:[0-9]{3}}"), - request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), - vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc", "v4": "111", "v5": "222", "v6": "333"}, - host: "aaa.bbb.ccc", - path: "/111/222/333", - shouldMatch: false, - }, - } - - for _, test := range tests { - testRoute(t, test) - } -} - -func TestHeaders(t *testing.T) { - // newRequestHeaders creates a new request with a method, url, and headers - newRequestHeaders := func(method, url string, headers map[string]string) *http.Request { - req, err := http.NewRequest(method, url, nil) - if err != nil { - panic(err) - } - for k, v := range headers { - req.Header.Add(k, v) - } - return req - } - - tests := []routeTest{ - { - title: "Headers route, match", - route: new(Route).Headers("foo", "bar", "baz", "ding"), - request: newRequestHeaders("GET", "http://localhost", map[string]string{"foo": "bar", "baz": "ding"}), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Headers route, bad header values", - route: new(Route).Headers("foo", "bar", "baz", "ding"), - request: newRequestHeaders("GET", "http://localhost", map[string]string{"foo": "bar", "baz": "dong"}), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: false, - }, - { - title: "Headers route, regex header values to match", - route: new(Route).Headers("foo", "ba[zr]"), - request: newRequestHeaders("GET", "http://localhost", map[string]string{"foo": "bar"}), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: false, - }, - { - title: "Headers route, regex header values to match", - route: new(Route).HeadersRegexp("foo", "ba[zr]"), - request: newRequestHeaders("GET", "http://localhost", map[string]string{"foo": "baz"}), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: true, - }, - } - - for _, test := range tests { - testRoute(t, test) - } - -} - -func TestMethods(t *testing.T) { - tests := []routeTest{ - { - title: "Methods route, match GET", - route: new(Route).Methods("GET", "POST"), - request: newRequest("GET", "http://localhost"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Methods route, match POST", - route: new(Route).Methods("GET", "POST"), - request: newRequest("POST", "http://localhost"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Methods route, bad method", - route: new(Route).Methods("GET", "POST"), - request: newRequest("PUT", "http://localhost"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: false, - }, - } - - for _, test := range tests { - testRoute(t, test) - } -} - -func TestQueries(t *testing.T) { - tests := []routeTest{ - { - title: "Queries route, match", - route: new(Route).Queries("foo", "bar", "baz", "ding"), - request: newRequest("GET", "http://localhost?foo=bar&baz=ding"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Queries route, match with a query string", - route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"), - request: newRequest("GET", "http://www.example.com/api?foo=bar&baz=ding"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Queries route, match with a query string out of order", - route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"), - request: newRequest("GET", "http://www.example.com/api?baz=ding&foo=bar"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Queries route, bad query", - route: new(Route).Queries("foo", "bar", "baz", "ding"), - request: newRequest("GET", "http://localhost?foo=bar&baz=dong"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: false, - }, - { - title: "Queries route with pattern, match", - route: new(Route).Queries("foo", "{v1}"), - request: newRequest("GET", "http://localhost?foo=bar"), - vars: map[string]string{"v1": "bar"}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Queries route with multiple patterns, match", - route: new(Route).Queries("foo", "{v1}", "baz", "{v2}"), - request: newRequest("GET", "http://localhost?foo=bar&baz=ding"), - vars: map[string]string{"v1": "bar", "v2": "ding"}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Queries route with regexp pattern, match", - route: new(Route).Queries("foo", "{v1:[0-9]+}"), - request: newRequest("GET", "http://localhost?foo=10"), - vars: map[string]string{"v1": "10"}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Queries route with regexp pattern, regexp does not match", - route: new(Route).Queries("foo", "{v1:[0-9]+}"), - request: newRequest("GET", "http://localhost?foo=a"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: false, - }, - { - title: "Queries route with regexp pattern with quantifier, match", - route: new(Route).Queries("foo", "{v1:[0-9]{1}}"), - request: newRequest("GET", "http://localhost?foo=1"), - vars: map[string]string{"v1": "1"}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Queries route with regexp pattern with quantifier, additional variable in query string, match", - route: new(Route).Queries("foo", "{v1:[0-9]{1}}"), - request: newRequest("GET", "http://localhost?bar=2&foo=1"), - vars: map[string]string{"v1": "1"}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Queries route with regexp pattern with quantifier, regexp does not match", - route: new(Route).Queries("foo", "{v1:[0-9]{1}}"), - request: newRequest("GET", "http://localhost?foo=12"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: false, - }, - { - title: "Queries route with regexp pattern with quantifier, additional capturing group", - route: new(Route).Queries("foo", "{v1:[0-9]{1}(a|b)}"), - request: newRequest("GET", "http://localhost?foo=1a"), - vars: map[string]string{"v1": "1a"}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Queries route with regexp pattern with quantifier, additional variable in query string, regexp does not match", - route: new(Route).Queries("foo", "{v1:[0-9]{1}}"), - request: newRequest("GET", "http://localhost?foo=12"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: false, - }, - { - title: "Queries route with hyphenated name, match", - route: new(Route).Queries("foo", "{v-1}"), - request: newRequest("GET", "http://localhost?foo=bar"), - vars: map[string]string{"v-1": "bar"}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Queries route with multiple hyphenated names, match", - route: new(Route).Queries("foo", "{v-1}", "baz", "{v-2}"), - request: newRequest("GET", "http://localhost?foo=bar&baz=ding"), - vars: map[string]string{"v-1": "bar", "v-2": "ding"}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Queries route with hyphenate name and pattern, match", - route: new(Route).Queries("foo", "{v-1:[0-9]+}"), - request: newRequest("GET", "http://localhost?foo=10"), - vars: map[string]string{"v-1": "10"}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Queries route with hyphenated name and pattern with quantifier, additional capturing group", - route: new(Route).Queries("foo", "{v-1:[0-9]{1}(a|b)}"), - request: newRequest("GET", "http://localhost?foo=1a"), - vars: map[string]string{"v-1": "1a"}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Queries route with empty value, should match", - route: new(Route).Queries("foo", ""), - request: newRequest("GET", "http://localhost?foo=bar"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Queries route with empty value and no parameter in request, should not match", - route: new(Route).Queries("foo", ""), - request: newRequest("GET", "http://localhost"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: false, - }, - { - title: "Queries route with empty value and empty parameter in request, should match", - route: new(Route).Queries("foo", ""), - request: newRequest("GET", "http://localhost?foo="), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Queries route with overlapping value, should not match", - route: new(Route).Queries("foo", "bar"), - request: newRequest("GET", "http://localhost?foo=barfoo"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: false, - }, - { - title: "Queries route with no parameter in request, should not match", - route: new(Route).Queries("foo", "{bar}"), - request: newRequest("GET", "http://localhost"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: false, - }, - { - title: "Queries route with empty parameter in request, should match", - route: new(Route).Queries("foo", "{bar}"), - request: newRequest("GET", "http://localhost?foo="), - vars: map[string]string{"foo": ""}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Queries route, bad submatch", - route: new(Route).Queries("foo", "bar", "baz", "ding"), - request: newRequest("GET", "http://localhost?fffoo=bar&baz=dingggg"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: false, - }, - } - - for _, test := range tests { - testRoute(t, test) - } -} - -func TestSchemes(t *testing.T) { - tests := []routeTest{ - // Schemes - { - title: "Schemes route, match https", - route: new(Route).Schemes("https", "ftp"), - request: newRequest("GET", "https://localhost"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Schemes route, match ftp", - route: new(Route).Schemes("https", "ftp"), - request: newRequest("GET", "ftp://localhost"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "Schemes route, bad scheme", - route: new(Route).Schemes("https", "ftp"), - request: newRequest("GET", "http://localhost"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: false, - }, - } - for _, test := range tests { - testRoute(t, test) - } -} - -func TestMatcherFunc(t *testing.T) { - m := func(r *http.Request, m *RouteMatch) bool { - if r.URL.Host == "aaa.bbb.ccc" { - return true - } - return false - } - - tests := []routeTest{ - { - title: "MatchFunc route, match", - route: new(Route).MatcherFunc(m), - request: newRequest("GET", "http://aaa.bbb.ccc"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: true, - }, - { - title: "MatchFunc route, non-match", - route: new(Route).MatcherFunc(m), - request: newRequest("GET", "http://aaa.222.ccc"), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: false, - }, - } - - for _, test := range tests { - testRoute(t, test) - } -} - -func TestBuildVarsFunc(t *testing.T) { - tests := []routeTest{ - { - title: "BuildVarsFunc set on route", - route: new(Route).Path(`/111/{v1:\d}{v2:.*}`).BuildVarsFunc(func(vars map[string]string) map[string]string { - vars["v1"] = "3" - vars["v2"] = "a" - return vars - }), - request: newRequest("GET", "http://localhost/111/2"), - path: "/111/3a", - shouldMatch: true, - }, - { - title: "BuildVarsFunc set on route and parent route", - route: new(Route).PathPrefix(`/{v1:\d}`).BuildVarsFunc(func(vars map[string]string) map[string]string { - vars["v1"] = "2" - return vars - }).Subrouter().Path(`/{v2:\w}`).BuildVarsFunc(func(vars map[string]string) map[string]string { - vars["v2"] = "b" - return vars - }), - request: newRequest("GET", "http://localhost/1/a"), - path: "/2/b", - shouldMatch: true, - }, - } - - for _, test := range tests { - testRoute(t, test) - } -} - -func TestSubRouter(t *testing.T) { - subrouter1 := new(Route).Host("{v1:[a-z]+}.google.com").Subrouter() - subrouter2 := new(Route).PathPrefix("/foo/{v1}").Subrouter() - - tests := []routeTest{ - { - route: subrouter1.Path("/{v2:[a-z]+}"), - request: newRequest("GET", "http://aaa.google.com/bbb"), - vars: map[string]string{"v1": "aaa", "v2": "bbb"}, - host: "aaa.google.com", - path: "/bbb", - shouldMatch: true, - }, - { - route: subrouter1.Path("/{v2:[a-z]+}"), - request: newRequest("GET", "http://111.google.com/111"), - vars: map[string]string{"v1": "aaa", "v2": "bbb"}, - host: "aaa.google.com", - path: "/bbb", - shouldMatch: false, - }, - { - route: subrouter2.Path("/baz/{v2}"), - request: newRequest("GET", "http://localhost/foo/bar/baz/ding"), - vars: map[string]string{"v1": "bar", "v2": "ding"}, - host: "", - path: "/foo/bar/baz/ding", - shouldMatch: true, - }, - { - route: subrouter2.Path("/baz/{v2}"), - request: newRequest("GET", "http://localhost/foo/bar"), - vars: map[string]string{"v1": "bar", "v2": "ding"}, - host: "", - path: "/foo/bar/baz/ding", - shouldMatch: false, - }, - } - - for _, test := range tests { - testRoute(t, test) - } -} - -func TestNamedRoutes(t *testing.T) { - r1 := NewRouter() - r1.NewRoute().Name("a") - r1.NewRoute().Name("b") - r1.NewRoute().Name("c") - - r2 := r1.NewRoute().Subrouter() - r2.NewRoute().Name("d") - r2.NewRoute().Name("e") - r2.NewRoute().Name("f") - - r3 := r2.NewRoute().Subrouter() - r3.NewRoute().Name("g") - r3.NewRoute().Name("h") - r3.NewRoute().Name("i") - - if r1.namedRoutes == nil || len(r1.namedRoutes) != 9 { - t.Errorf("Expected 9 named routes, got %v", r1.namedRoutes) - } else if r1.Get("i") == nil { - t.Errorf("Subroute name not registered") - } -} - -func TestStrictSlash(t *testing.T) { - r := NewRouter() - r.StrictSlash(true) - - tests := []routeTest{ - { - title: "Redirect path without slash", - route: r.NewRoute().Path("/111/"), - request: newRequest("GET", "http://localhost/111"), - vars: map[string]string{}, - host: "", - path: "/111/", - shouldMatch: true, - shouldRedirect: true, - }, - { - title: "Do not redirect path with slash", - route: r.NewRoute().Path("/111/"), - request: newRequest("GET", "http://localhost/111/"), - vars: map[string]string{}, - host: "", - path: "/111/", - shouldMatch: true, - shouldRedirect: false, - }, - { - title: "Redirect path with slash", - route: r.NewRoute().Path("/111"), - request: newRequest("GET", "http://localhost/111/"), - vars: map[string]string{}, - host: "", - path: "/111", - shouldMatch: true, - shouldRedirect: true, - }, - { - title: "Do not redirect path without slash", - route: r.NewRoute().Path("/111"), - request: newRequest("GET", "http://localhost/111"), - vars: map[string]string{}, - host: "", - path: "/111", - shouldMatch: true, - shouldRedirect: false, - }, - { - title: "Propagate StrictSlash to subrouters", - route: r.NewRoute().PathPrefix("/static/").Subrouter().Path("/images/"), - request: newRequest("GET", "http://localhost/static/images"), - vars: map[string]string{}, - host: "", - path: "/static/images/", - shouldMatch: true, - shouldRedirect: true, - }, - { - title: "Ignore StrictSlash for path prefix", - route: r.NewRoute().PathPrefix("/static/"), - request: newRequest("GET", "http://localhost/static/logo.png"), - vars: map[string]string{}, - host: "", - path: "/static/", - shouldMatch: true, - shouldRedirect: false, - }, - } - - for _, test := range tests { - testRoute(t, test) - } -} - -func TestWalkSingleDepth(t *testing.T) { - r0 := NewRouter() - r1 := NewRouter() - r2 := NewRouter() - - r0.Path("/g") - r0.Path("/o") - r0.Path("/d").Handler(r1) - r0.Path("/r").Handler(r2) - r0.Path("/a") - - r1.Path("/z") - r1.Path("/i") - r1.Path("/l") - r1.Path("/l") - - r2.Path("/i") - r2.Path("/l") - r2.Path("/l") - - paths := []string{"g", "o", "r", "i", "l", "l", "a"} - depths := []int{0, 0, 0, 1, 1, 1, 0} - i := 0 - err := r0.Walk(func(route *Route, router *Router, ancestors []*Route) error { - matcher := route.matchers[0].(*routeRegexp) - if matcher.template == "/d" { - return SkipRouter - } - if len(ancestors) != depths[i] { - t.Errorf(`Expected depth of %d at i = %d; got "%s"`, depths[i], i, len(ancestors)) - } - if matcher.template != "/"+paths[i] { - t.Errorf(`Expected "/%s" at i = %d; got "%s"`, paths[i], i, matcher.template) - } - i++ - return nil - }) - if err != nil { - panic(err) - } - if i != len(paths) { - t.Errorf("Expected %d routes, found %d", len(paths), i) - } -} - -func TestWalkNested(t *testing.T) { - router := NewRouter() - - g := router.Path("/g").Subrouter() - o := g.PathPrefix("/o").Subrouter() - r := o.PathPrefix("/r").Subrouter() - i := r.PathPrefix("/i").Subrouter() - l1 := i.PathPrefix("/l").Subrouter() - l2 := l1.PathPrefix("/l").Subrouter() - l2.Path("/a") - - paths := []string{"/g", "/g/o", "/g/o/r", "/g/o/r/i", "/g/o/r/i/l", "/g/o/r/i/l/l", "/g/o/r/i/l/l/a"} - idx := 0 - err := router.Walk(func(route *Route, router *Router, ancestors []*Route) error { - path := paths[idx] - tpl := route.regexp.path.template - if tpl != path { - t.Errorf(`Expected %s got %s`, path, tpl) - } - idx++ - return nil - }) - if err != nil { - panic(err) - } - if idx != len(paths) { - t.Errorf("Expected %d routes, found %d", len(paths), idx) - } -} - -// ---------------------------------------------------------------------------- -// Helpers -// ---------------------------------------------------------------------------- - -func getRouteTemplate(route *Route) string { - host, path := "none", "none" - if route.regexp != nil { - if route.regexp.host != nil { - host = route.regexp.host.template - } - if route.regexp.path != nil { - path = route.regexp.path.template - } - } - return fmt.Sprintf("Host: %v, Path: %v", host, path) -} - -func testRoute(t *testing.T, test routeTest) { - request := test.request - route := test.route - vars := test.vars - shouldMatch := test.shouldMatch - host := test.host - path := test.path - url := test.host + test.path - shouldRedirect := test.shouldRedirect - - var match RouteMatch - ok := route.Match(request, &match) - if ok != shouldMatch { - msg := "Should match" - if !shouldMatch { - msg = "Should not match" - } - t.Errorf("(%v) %v:\nRoute: %#v\nRequest: %#v\nVars: %v\n", test.title, msg, route, request, vars) - return - } - if shouldMatch { - if test.vars != nil && !stringMapEqual(test.vars, match.Vars) { - t.Errorf("(%v) Vars not equal: expected %v, got %v", test.title, vars, match.Vars) - return - } - if host != "" { - u, _ := test.route.URLHost(mapToPairs(match.Vars)...) - if host != u.Host { - t.Errorf("(%v) URLHost not equal: expected %v, got %v -- %v", test.title, host, u.Host, getRouteTemplate(route)) - return - } - } - if path != "" { - u, _ := route.URLPath(mapToPairs(match.Vars)...) - if path != u.Path { - t.Errorf("(%v) URLPath not equal: expected %v, got %v -- %v", test.title, path, u.Path, getRouteTemplate(route)) - return - } - } - if url != "" { - u, _ := route.URL(mapToPairs(match.Vars)...) - if url != u.Host+u.Path { - t.Errorf("(%v) URL not equal: expected %v, got %v -- %v", test.title, url, u.Host+u.Path, getRouteTemplate(route)) - return - } - } - if shouldRedirect && match.Handler == nil { - t.Errorf("(%v) Did not redirect", test.title) - return - } - if !shouldRedirect && match.Handler != nil { - t.Errorf("(%v) Unexpected redirect", test.title) - return - } - } -} - -// Tests that the context is cleared or not cleared properly depending on -// the configuration of the router -func TestKeepContext(t *testing.T) { - func1 := func(w http.ResponseWriter, r *http.Request) {} - - r := NewRouter() - r.HandleFunc("/", func1).Name("func1") - - req, _ := http.NewRequest("GET", "http://localhost/", nil) - context.Set(req, "t", 1) - - res := new(http.ResponseWriter) - r.ServeHTTP(*res, req) - - if _, ok := context.GetOk(req, "t"); ok { - t.Error("Context should have been cleared at end of request") - } - - r.KeepContext = true - - req, _ = http.NewRequest("GET", "http://localhost/", nil) - context.Set(req, "t", 1) - - r.ServeHTTP(*res, req) - if _, ok := context.GetOk(req, "t"); !ok { - t.Error("Context should NOT have been cleared at end of request") - } - -} - -type TestA301ResponseWriter struct { - hh http.Header - status int -} - -func (ho TestA301ResponseWriter) Header() http.Header { - return http.Header(ho.hh) -} - -func (ho TestA301ResponseWriter) Write(b []byte) (int, error) { - return 0, nil -} - -func (ho TestA301ResponseWriter) WriteHeader(code int) { - ho.status = code -} - -func Test301Redirect(t *testing.T) { - m := make(http.Header) - - func1 := func(w http.ResponseWriter, r *http.Request) {} - func2 := func(w http.ResponseWriter, r *http.Request) {} - - r := NewRouter() - r.HandleFunc("/api/", func2).Name("func2") - r.HandleFunc("/", func1).Name("func1") - - req, _ := http.NewRequest("GET", "http://localhost//api/?abc=def", nil) - - res := TestA301ResponseWriter{ - hh: m, - status: 0, - } - r.ServeHTTP(&res, req) - - if "http://localhost/api/?abc=def" != res.hh["Location"][0] { - t.Errorf("Should have complete URL with query string") - } -} - -// https://plus.google.com/101022900381697718949/posts/eWy6DjFJ6uW -func TestSubrouterHeader(t *testing.T) { - expected := "func1 response" - func1 := func(w http.ResponseWriter, r *http.Request) { - fmt.Fprint(w, expected) - } - func2 := func(http.ResponseWriter, *http.Request) {} - - r := NewRouter() - s := r.Headers("SomeSpecialHeader", "").Subrouter() - s.HandleFunc("/", func1).Name("func1") - r.HandleFunc("/", func2).Name("func2") - - req, _ := http.NewRequest("GET", "http://localhost/", nil) - req.Header.Add("SomeSpecialHeader", "foo") - match := new(RouteMatch) - matched := r.Match(req, match) - if !matched { - t.Errorf("Should match request") - } - if match.Route.GetName() != "func1" { - t.Errorf("Expecting func1 handler, got %s", match.Route.GetName()) - } - resp := NewRecorder() - match.Handler.ServeHTTP(resp, req) - if resp.Body.String() != expected { - t.Errorf("Expecting %q", expected) - } -} - -// mapToPairs converts a string map to a slice of string pairs -func mapToPairs(m map[string]string) []string { - var i int - p := make([]string, len(m)*2) - for k, v := range m { - p[i] = k - p[i+1] = v - i += 2 - } - return p -} - -// stringMapEqual checks the equality of two string maps -func stringMapEqual(m1, m2 map[string]string) bool { - nil1 := m1 == nil - nil2 := m2 == nil - if nil1 != nil2 || len(m1) != len(m2) { - return false - } - for k, v := range m1 { - if v != m2[k] { - return false - } - } - return true -} - -// newRequest is a helper function to create a new request with a method and url -func newRequest(method, url string) *http.Request { - req, err := http.NewRequest(method, url, nil) - if err != nil { - panic(err) - } - return req -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/old_test.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/old_test.go deleted file mode 100644 index 755db483..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/old_test.go +++ /dev/null @@ -1,714 +0,0 @@ -// Old tests ported to Go1. This is a mess. Want to drop it one day. - -// Copyright 2011 Gorilla 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 mux - -import ( - "bytes" - "net/http" - "testing" -) - -// ---------------------------------------------------------------------------- -// ResponseRecorder -// ---------------------------------------------------------------------------- -// Copyright 2009 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. - -// ResponseRecorder is an implementation of http.ResponseWriter that -// records its mutations for later inspection in tests. -type ResponseRecorder struct { - Code int // the HTTP response code from WriteHeader - HeaderMap http.Header // the HTTP response headers - Body *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to - Flushed bool -} - -// NewRecorder returns an initialized ResponseRecorder. -func NewRecorder() *ResponseRecorder { - return &ResponseRecorder{ - HeaderMap: make(http.Header), - Body: new(bytes.Buffer), - } -} - -// DefaultRemoteAddr is the default remote address to return in RemoteAddr if -// an explicit DefaultRemoteAddr isn't set on ResponseRecorder. -const DefaultRemoteAddr = "1.2.3.4" - -// Header returns the response headers. -func (rw *ResponseRecorder) Header() http.Header { - return rw.HeaderMap -} - -// Write always succeeds and writes to rw.Body, if not nil. -func (rw *ResponseRecorder) Write(buf []byte) (int, error) { - if rw.Body != nil { - rw.Body.Write(buf) - } - if rw.Code == 0 { - rw.Code = http.StatusOK - } - return len(buf), nil -} - -// WriteHeader sets rw.Code. -func (rw *ResponseRecorder) WriteHeader(code int) { - rw.Code = code -} - -// Flush sets rw.Flushed to true. -func (rw *ResponseRecorder) Flush() { - rw.Flushed = true -} - -// ---------------------------------------------------------------------------- - -func TestRouteMatchers(t *testing.T) { - var scheme, host, path, query, method string - var headers map[string]string - var resultVars map[bool]map[string]string - - router := NewRouter() - router.NewRoute().Host("{var1}.google.com"). - Path("/{var2:[a-z]+}/{var3:[0-9]+}"). - Queries("foo", "bar"). - Methods("GET"). - Schemes("https"). - Headers("x-requested-with", "XMLHttpRequest") - router.NewRoute().Host("www.{var4}.com"). - PathPrefix("/foo/{var5:[a-z]+}/{var6:[0-9]+}"). - Queries("baz", "ding"). - Methods("POST"). - Schemes("http"). - Headers("Content-Type", "application/json") - - reset := func() { - // Everything match. - scheme = "https" - host = "www.google.com" - path = "/product/42" - query = "?foo=bar" - method = "GET" - headers = map[string]string{"X-Requested-With": "XMLHttpRequest"} - resultVars = map[bool]map[string]string{ - true: {"var1": "www", "var2": "product", "var3": "42"}, - false: {}, - } - } - - reset2 := func() { - // Everything match. - scheme = "http" - host = "www.google.com" - path = "/foo/product/42/path/that/is/ignored" - query = "?baz=ding" - method = "POST" - headers = map[string]string{"Content-Type": "application/json"} - resultVars = map[bool]map[string]string{ - true: {"var4": "google", "var5": "product", "var6": "42"}, - false: {}, - } - } - - match := func(shouldMatch bool) { - url := scheme + "://" + host + path + query - request, _ := http.NewRequest(method, url, nil) - for key, value := range headers { - request.Header.Add(key, value) - } - - var routeMatch RouteMatch - matched := router.Match(request, &routeMatch) - if matched != shouldMatch { - // Need better messages. :) - if matched { - t.Errorf("Should match.") - } else { - t.Errorf("Should not match.") - } - } - - if matched { - currentRoute := routeMatch.Route - if currentRoute == nil { - t.Errorf("Expected a current route.") - } - vars := routeMatch.Vars - expectedVars := resultVars[shouldMatch] - if len(vars) != len(expectedVars) { - t.Errorf("Expected vars: %v Got: %v.", expectedVars, vars) - } - for name, value := range vars { - if expectedVars[name] != value { - t.Errorf("Expected vars: %v Got: %v.", expectedVars, vars) - } - } - } - } - - // 1st route -------------------------------------------------------------- - - // Everything match. - reset() - match(true) - - // Scheme doesn't match. - reset() - scheme = "http" - match(false) - - // Host doesn't match. - reset() - host = "www.mygoogle.com" - match(false) - - // Path doesn't match. - reset() - path = "/product/notdigits" - match(false) - - // Query doesn't match. - reset() - query = "?foo=baz" - match(false) - - // Method doesn't match. - reset() - method = "POST" - match(false) - - // Header doesn't match. - reset() - headers = map[string]string{} - match(false) - - // Everything match, again. - reset() - match(true) - - // 2nd route -------------------------------------------------------------- - - // Everything match. - reset2() - match(true) - - // Scheme doesn't match. - reset2() - scheme = "https" - match(false) - - // Host doesn't match. - reset2() - host = "sub.google.com" - match(false) - - // Path doesn't match. - reset2() - path = "/bar/product/42" - match(false) - - // Query doesn't match. - reset2() - query = "?foo=baz" - match(false) - - // Method doesn't match. - reset2() - method = "GET" - match(false) - - // Header doesn't match. - reset2() - headers = map[string]string{} - match(false) - - // Everything match, again. - reset2() - match(true) -} - -type headerMatcherTest struct { - matcher headerMatcher - headers map[string]string - result bool -} - -var headerMatcherTests = []headerMatcherTest{ - { - matcher: headerMatcher(map[string]string{"x-requested-with": "XMLHttpRequest"}), - headers: map[string]string{"X-Requested-With": "XMLHttpRequest"}, - result: true, - }, - { - matcher: headerMatcher(map[string]string{"x-requested-with": ""}), - headers: map[string]string{"X-Requested-With": "anything"}, - result: true, - }, - { - matcher: headerMatcher(map[string]string{"x-requested-with": "XMLHttpRequest"}), - headers: map[string]string{}, - result: false, - }, -} - -type hostMatcherTest struct { - matcher *Route - url string - vars map[string]string - result bool -} - -var hostMatcherTests = []hostMatcherTest{ - { - matcher: NewRouter().NewRoute().Host("{foo:[a-z][a-z][a-z]}.{bar:[a-z][a-z][a-z]}.{baz:[a-z][a-z][a-z]}"), - url: "http://abc.def.ghi/", - vars: map[string]string{"foo": "abc", "bar": "def", "baz": "ghi"}, - result: true, - }, - { - matcher: NewRouter().NewRoute().Host("{foo:[a-z][a-z][a-z]}.{bar:[a-z][a-z][a-z]}.{baz:[a-z][a-z][a-z]}"), - url: "http://a.b.c/", - vars: map[string]string{"foo": "abc", "bar": "def", "baz": "ghi"}, - result: false, - }, -} - -type methodMatcherTest struct { - matcher methodMatcher - method string - result bool -} - -var methodMatcherTests = []methodMatcherTest{ - { - matcher: methodMatcher([]string{"GET", "POST", "PUT"}), - method: "GET", - result: true, - }, - { - matcher: methodMatcher([]string{"GET", "POST", "PUT"}), - method: "POST", - result: true, - }, - { - matcher: methodMatcher([]string{"GET", "POST", "PUT"}), - method: "PUT", - result: true, - }, - { - matcher: methodMatcher([]string{"GET", "POST", "PUT"}), - method: "DELETE", - result: false, - }, -} - -type pathMatcherTest struct { - matcher *Route - url string - vars map[string]string - result bool -} - -var pathMatcherTests = []pathMatcherTest{ - { - matcher: NewRouter().NewRoute().Path("/{foo:[0-9][0-9][0-9]}/{bar:[0-9][0-9][0-9]}/{baz:[0-9][0-9][0-9]}"), - url: "http://localhost:8080/123/456/789", - vars: map[string]string{"foo": "123", "bar": "456", "baz": "789"}, - result: true, - }, - { - matcher: NewRouter().NewRoute().Path("/{foo:[0-9][0-9][0-9]}/{bar:[0-9][0-9][0-9]}/{baz:[0-9][0-9][0-9]}"), - url: "http://localhost:8080/1/2/3", - vars: map[string]string{"foo": "123", "bar": "456", "baz": "789"}, - result: false, - }, -} - -type schemeMatcherTest struct { - matcher schemeMatcher - url string - result bool -} - -var schemeMatcherTests = []schemeMatcherTest{ - { - matcher: schemeMatcher([]string{"http", "https"}), - url: "http://localhost:8080/", - result: true, - }, - { - matcher: schemeMatcher([]string{"http", "https"}), - url: "https://localhost:8080/", - result: true, - }, - { - matcher: schemeMatcher([]string{"https"}), - url: "http://localhost:8080/", - result: false, - }, - { - matcher: schemeMatcher([]string{"http"}), - url: "https://localhost:8080/", - result: false, - }, -} - -type urlBuildingTest struct { - route *Route - vars []string - url string -} - -var urlBuildingTests = []urlBuildingTest{ - { - route: new(Route).Host("foo.domain.com"), - vars: []string{}, - url: "http://foo.domain.com", - }, - { - route: new(Route).Host("{subdomain}.domain.com"), - vars: []string{"subdomain", "bar"}, - url: "http://bar.domain.com", - }, - { - route: new(Route).Host("foo.domain.com").Path("/articles"), - vars: []string{}, - url: "http://foo.domain.com/articles", - }, - { - route: new(Route).Path("/articles"), - vars: []string{}, - url: "/articles", - }, - { - route: new(Route).Path("/articles/{category}/{id:[0-9]+}"), - vars: []string{"category", "technology", "id", "42"}, - url: "/articles/technology/42", - }, - { - route: new(Route).Host("{subdomain}.domain.com").Path("/articles/{category}/{id:[0-9]+}"), - vars: []string{"subdomain", "foo", "category", "technology", "id", "42"}, - url: "http://foo.domain.com/articles/technology/42", - }, -} - -func TestHeaderMatcher(t *testing.T) { - for _, v := range headerMatcherTests { - request, _ := http.NewRequest("GET", "http://localhost:8080/", nil) - for key, value := range v.headers { - request.Header.Add(key, value) - } - var routeMatch RouteMatch - result := v.matcher.Match(request, &routeMatch) - if result != v.result { - if v.result { - t.Errorf("%#v: should match %v.", v.matcher, request.Header) - } else { - t.Errorf("%#v: should not match %v.", v.matcher, request.Header) - } - } - } -} - -func TestHostMatcher(t *testing.T) { - for _, v := range hostMatcherTests { - request, _ := http.NewRequest("GET", v.url, nil) - var routeMatch RouteMatch - result := v.matcher.Match(request, &routeMatch) - vars := routeMatch.Vars - if result != v.result { - if v.result { - t.Errorf("%#v: should match %v.", v.matcher, v.url) - } else { - t.Errorf("%#v: should not match %v.", v.matcher, v.url) - } - } - if result { - if len(vars) != len(v.vars) { - t.Errorf("%#v: vars length should be %v, got %v.", v.matcher, len(v.vars), len(vars)) - } - for name, value := range vars { - if v.vars[name] != value { - t.Errorf("%#v: expected value %v for key %v, got %v.", v.matcher, v.vars[name], name, value) - } - } - } else { - if len(vars) != 0 { - t.Errorf("%#v: vars length should be 0, got %v.", v.matcher, len(vars)) - } - } - } -} - -func TestMethodMatcher(t *testing.T) { - for _, v := range methodMatcherTests { - request, _ := http.NewRequest(v.method, "http://localhost:8080/", nil) - var routeMatch RouteMatch - result := v.matcher.Match(request, &routeMatch) - if result != v.result { - if v.result { - t.Errorf("%#v: should match %v.", v.matcher, v.method) - } else { - t.Errorf("%#v: should not match %v.", v.matcher, v.method) - } - } - } -} - -func TestPathMatcher(t *testing.T) { - for _, v := range pathMatcherTests { - request, _ := http.NewRequest("GET", v.url, nil) - var routeMatch RouteMatch - result := v.matcher.Match(request, &routeMatch) - vars := routeMatch.Vars - if result != v.result { - if v.result { - t.Errorf("%#v: should match %v.", v.matcher, v.url) - } else { - t.Errorf("%#v: should not match %v.", v.matcher, v.url) - } - } - if result { - if len(vars) != len(v.vars) { - t.Errorf("%#v: vars length should be %v, got %v.", v.matcher, len(v.vars), len(vars)) - } - for name, value := range vars { - if v.vars[name] != value { - t.Errorf("%#v: expected value %v for key %v, got %v.", v.matcher, v.vars[name], name, value) - } - } - } else { - if len(vars) != 0 { - t.Errorf("%#v: vars length should be 0, got %v.", v.matcher, len(vars)) - } - } - } -} - -func TestSchemeMatcher(t *testing.T) { - for _, v := range schemeMatcherTests { - request, _ := http.NewRequest("GET", v.url, nil) - var routeMatch RouteMatch - result := v.matcher.Match(request, &routeMatch) - if result != v.result { - if v.result { - t.Errorf("%#v: should match %v.", v.matcher, v.url) - } else { - t.Errorf("%#v: should not match %v.", v.matcher, v.url) - } - } - } -} - -func TestUrlBuilding(t *testing.T) { - - for _, v := range urlBuildingTests { - u, _ := v.route.URL(v.vars...) - url := u.String() - if url != v.url { - t.Errorf("expected %v, got %v", v.url, url) - /* - reversePath := "" - reverseHost := "" - if v.route.pathTemplate != nil { - reversePath = v.route.pathTemplate.Reverse - } - if v.route.hostTemplate != nil { - reverseHost = v.route.hostTemplate.Reverse - } - - t.Errorf("%#v:\nexpected: %q\ngot: %q\nreverse path: %q\nreverse host: %q", v.route, v.url, url, reversePath, reverseHost) - */ - } - } - - ArticleHandler := func(w http.ResponseWriter, r *http.Request) { - } - - router := NewRouter() - router.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).Name("article") - - url, _ := router.Get("article").URL("category", "technology", "id", "42") - expected := "/articles/technology/42" - if url.String() != expected { - t.Errorf("Expected %v, got %v", expected, url.String()) - } -} - -func TestMatchedRouteName(t *testing.T) { - routeName := "stock" - router := NewRouter() - route := router.NewRoute().Path("/products/").Name(routeName) - - url := "http://www.example.com/products/" - request, _ := http.NewRequest("GET", url, nil) - var rv RouteMatch - ok := router.Match(request, &rv) - - if !ok || rv.Route != route { - t.Errorf("Expected same route, got %+v.", rv.Route) - } - - retName := rv.Route.GetName() - if retName != routeName { - t.Errorf("Expected %q, got %q.", routeName, retName) - } -} - -func TestSubRouting(t *testing.T) { - // Example from docs. - router := NewRouter() - subrouter := router.NewRoute().Host("www.example.com").Subrouter() - route := subrouter.NewRoute().Path("/products/").Name("products") - - url := "http://www.example.com/products/" - request, _ := http.NewRequest("GET", url, nil) - var rv RouteMatch - ok := router.Match(request, &rv) - - if !ok || rv.Route != route { - t.Errorf("Expected same route, got %+v.", rv.Route) - } - - u, _ := router.Get("products").URL() - builtUrl := u.String() - // Yay, subroute aware of the domain when building! - if builtUrl != url { - t.Errorf("Expected %q, got %q.", url, builtUrl) - } -} - -func TestVariableNames(t *testing.T) { - route := new(Route).Host("{arg1}.domain.com").Path("/{arg1}/{arg2:[0-9]+}") - if route.err == nil { - t.Errorf("Expected error for duplicated variable names") - } -} - -func TestRedirectSlash(t *testing.T) { - var route *Route - var routeMatch RouteMatch - r := NewRouter() - - r.StrictSlash(false) - route = r.NewRoute() - if route.strictSlash != false { - t.Errorf("Expected false redirectSlash.") - } - - r.StrictSlash(true) - route = r.NewRoute() - if route.strictSlash != true { - t.Errorf("Expected true redirectSlash.") - } - - route = new(Route) - route.strictSlash = true - route.Path("/{arg1}/{arg2:[0-9]+}/") - request, _ := http.NewRequest("GET", "http://localhost/foo/123", nil) - routeMatch = RouteMatch{} - _ = route.Match(request, &routeMatch) - vars := routeMatch.Vars - if vars["arg1"] != "foo" { - t.Errorf("Expected foo.") - } - if vars["arg2"] != "123" { - t.Errorf("Expected 123.") - } - rsp := NewRecorder() - routeMatch.Handler.ServeHTTP(rsp, request) - if rsp.HeaderMap.Get("Location") != "http://localhost/foo/123/" { - t.Errorf("Expected redirect header.") - } - - route = new(Route) - route.strictSlash = true - route.Path("/{arg1}/{arg2:[0-9]+}") - request, _ = http.NewRequest("GET", "http://localhost/foo/123/", nil) - routeMatch = RouteMatch{} - _ = route.Match(request, &routeMatch) - vars = routeMatch.Vars - if vars["arg1"] != "foo" { - t.Errorf("Expected foo.") - } - if vars["arg2"] != "123" { - t.Errorf("Expected 123.") - } - rsp = NewRecorder() - routeMatch.Handler.ServeHTTP(rsp, request) - if rsp.HeaderMap.Get("Location") != "http://localhost/foo/123" { - t.Errorf("Expected redirect header.") - } -} - -// Test for the new regexp library, still not available in stable Go. -func TestNewRegexp(t *testing.T) { - var p *routeRegexp - var matches []string - - tests := map[string]map[string][]string{ - "/{foo:a{2}}": { - "/a": nil, - "/aa": {"aa"}, - "/aaa": nil, - "/aaaa": nil, - }, - "/{foo:a{2,}}": { - "/a": nil, - "/aa": {"aa"}, - "/aaa": {"aaa"}, - "/aaaa": {"aaaa"}, - }, - "/{foo:a{2,3}}": { - "/a": nil, - "/aa": {"aa"}, - "/aaa": {"aaa"}, - "/aaaa": nil, - }, - "/{foo:[a-z]{3}}/{bar:[a-z]{2}}": { - "/a": nil, - "/ab": nil, - "/abc": nil, - "/abcd": nil, - "/abc/ab": {"abc", "ab"}, - "/abc/abc": nil, - "/abcd/ab": nil, - }, - `/{foo:\w{3,}}/{bar:\d{2,}}`: { - "/a": nil, - "/ab": nil, - "/abc": nil, - "/abc/1": nil, - "/abc/12": {"abc", "12"}, - "/abcd/12": {"abcd", "12"}, - "/abcd/123": {"abcd", "123"}, - }, - } - - for pattern, paths := range tests { - p, _ = newRouteRegexp(pattern, false, false, false, false) - for path, result := range paths { - matches = p.regexp.FindStringSubmatch(path) - if result == nil { - if matches != nil { - t.Errorf("%v should not match %v.", pattern, path) - } - } else { - if len(matches) != len(result)+1 { - t.Errorf("Expected %v matches, got %v.", len(result)+1, len(matches)) - } else { - for k, v := range result { - if matches[k+1] != v { - t.Errorf("Expected %v, got %v.", v, matches[k+1]) - } - } - } - } - } - } -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/regexp.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/regexp.go deleted file mode 100644 index 06728dd5..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/regexp.go +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright 2012 The Gorilla 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 mux - -import ( - "bytes" - "fmt" - "net/http" - "net/url" - "regexp" - "strconv" - "strings" -) - -// newRouteRegexp parses a route template and returns a routeRegexp, -// used to match a host, a path or a query string. -// -// It will extract named variables, assemble a regexp to be matched, create -// a "reverse" template to build URLs and compile regexps to validate variable -// values used in URL building. -// -// Previously we accepted only Python-like identifiers for variable -// names ([a-zA-Z_][a-zA-Z0-9_]*), but currently the only restriction is that -// name and pattern can't be empty, and names can't contain a colon. -func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash bool) (*routeRegexp, error) { - // Check if it is well-formed. - idxs, errBraces := braceIndices(tpl) - if errBraces != nil { - return nil, errBraces - } - // Backup the original. - template := tpl - // Now let's parse it. - defaultPattern := "[^/]+" - if matchQuery { - defaultPattern = "[^?&]*" - } else if matchHost { - defaultPattern = "[^.]+" - matchPrefix = false - } - // Only match strict slash if not matching - if matchPrefix || matchHost || matchQuery { - strictSlash = false - } - // Set a flag for strictSlash. - endSlash := false - if strictSlash && strings.HasSuffix(tpl, "/") { - tpl = tpl[:len(tpl)-1] - endSlash = true - } - varsN := make([]string, len(idxs)/2) - varsR := make([]*regexp.Regexp, len(idxs)/2) - pattern := bytes.NewBufferString("") - pattern.WriteByte('^') - reverse := bytes.NewBufferString("") - var end int - var err error - for i := 0; i < len(idxs); i += 2 { - // Set all values we are interested in. - raw := tpl[end:idxs[i]] - end = idxs[i+1] - parts := strings.SplitN(tpl[idxs[i]+1:end-1], ":", 2) - name := parts[0] - patt := defaultPattern - if len(parts) == 2 { - patt = parts[1] - } - // Name or pattern can't be empty. - if name == "" || patt == "" { - return nil, fmt.Errorf("mux: missing name or pattern in %q", - tpl[idxs[i]:end]) - } - // Build the regexp pattern. - varIdx := i / 2 - fmt.Fprintf(pattern, "%s(?P<%s>%s)", regexp.QuoteMeta(raw), varGroupName(varIdx), patt) - // Build the reverse template. - fmt.Fprintf(reverse, "%s%%s", raw) - - // Append variable name and compiled pattern. - varsN[varIdx] = name - varsR[varIdx], err = regexp.Compile(fmt.Sprintf("^%s$", patt)) - if err != nil { - return nil, err - } - } - // Add the remaining. - raw := tpl[end:] - pattern.WriteString(regexp.QuoteMeta(raw)) - if strictSlash { - pattern.WriteString("[/]?") - } - if matchQuery { - // Add the default pattern if the query value is empty - if queryVal := strings.SplitN(template, "=", 2)[1]; queryVal == "" { - pattern.WriteString(defaultPattern) - } - } - if !matchPrefix { - pattern.WriteByte('$') - } - reverse.WriteString(raw) - if endSlash { - reverse.WriteByte('/') - } - // Compile full regexp. - reg, errCompile := regexp.Compile(pattern.String()) - if errCompile != nil { - return nil, errCompile - } - // Done! - return &routeRegexp{ - template: template, - matchHost: matchHost, - matchQuery: matchQuery, - strictSlash: strictSlash, - regexp: reg, - reverse: reverse.String(), - varsN: varsN, - varsR: varsR, - }, nil -} - -// routeRegexp stores a regexp to match a host or path and information to -// collect and validate route variables. -type routeRegexp struct { - // The unmodified template. - template string - // True for host match, false for path or query string match. - matchHost bool - // True for query string match, false for path and host match. - matchQuery bool - // The strictSlash value defined on the route, but disabled if PathPrefix was used. - strictSlash bool - // Expanded regexp. - regexp *regexp.Regexp - // Reverse template. - reverse string - // Variable names. - varsN []string - // Variable regexps (validators). - varsR []*regexp.Regexp -} - -// Match matches the regexp against the URL host or path. -func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool { - if !r.matchHost { - if r.matchQuery { - return r.matchQueryString(req) - } else { - return r.regexp.MatchString(req.URL.Path) - } - } - return r.regexp.MatchString(getHost(req)) -} - -// url builds a URL part using the given values. -func (r *routeRegexp) url(values map[string]string) (string, error) { - urlValues := make([]interface{}, len(r.varsN)) - for k, v := range r.varsN { - value, ok := values[v] - if !ok { - return "", fmt.Errorf("mux: missing route variable %q", v) - } - urlValues[k] = value - } - rv := fmt.Sprintf(r.reverse, urlValues...) - if !r.regexp.MatchString(rv) { - // The URL is checked against the full regexp, instead of checking - // individual variables. This is faster but to provide a good error - // message, we check individual regexps if the URL doesn't match. - for k, v := range r.varsN { - if !r.varsR[k].MatchString(values[v]) { - return "", fmt.Errorf( - "mux: variable %q doesn't match, expected %q", values[v], - r.varsR[k].String()) - } - } - } - return rv, nil -} - -// getUrlQuery returns a single query parameter from a request URL. -// For a URL with foo=bar&baz=ding, we return only the relevant key -// value pair for the routeRegexp. -func (r *routeRegexp) getUrlQuery(req *http.Request) string { - if !r.matchQuery { - return "" - } - templateKey := strings.SplitN(r.template, "=", 2)[0] - for key, vals := range req.URL.Query() { - if key == templateKey && len(vals) > 0 { - return key + "=" + vals[0] - } - } - return "" -} - -func (r *routeRegexp) matchQueryString(req *http.Request) bool { - return r.regexp.MatchString(r.getUrlQuery(req)) -} - -// braceIndices returns the first level curly brace indices from a string. -// It returns an error in case of unbalanced braces. -func braceIndices(s string) ([]int, error) { - var level, idx int - idxs := make([]int, 0) - for i := 0; i < len(s); i++ { - switch s[i] { - case '{': - if level++; level == 1 { - idx = i - } - case '}': - if level--; level == 0 { - idxs = append(idxs, idx, i+1) - } else if level < 0 { - return nil, fmt.Errorf("mux: unbalanced braces in %q", s) - } - } - } - if level != 0 { - return nil, fmt.Errorf("mux: unbalanced braces in %q", s) - } - return idxs, nil -} - -// varGroupName builds a capturing group name for the indexed variable. -func varGroupName(idx int) string { - return "v" + strconv.Itoa(idx) -} - -// ---------------------------------------------------------------------------- -// routeRegexpGroup -// ---------------------------------------------------------------------------- - -// routeRegexpGroup groups the route matchers that carry variables. -type routeRegexpGroup struct { - host *routeRegexp - path *routeRegexp - queries []*routeRegexp -} - -// setMatch extracts the variables from the URL once a route matches. -func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) { - // Store host variables. - if v.host != nil { - hostVars := v.host.regexp.FindStringSubmatch(getHost(req)) - if hostVars != nil { - subexpNames := v.host.regexp.SubexpNames() - varName := 0 - for i, name := range subexpNames[1:] { - if name != "" && name == varGroupName(varName) { - m.Vars[v.host.varsN[varName]] = hostVars[i+1] - varName++ - } - } - } - } - // Store path variables. - if v.path != nil { - pathVars := v.path.regexp.FindStringSubmatch(req.URL.Path) - if pathVars != nil { - subexpNames := v.path.regexp.SubexpNames() - varName := 0 - for i, name := range subexpNames[1:] { - if name != "" && name == varGroupName(varName) { - m.Vars[v.path.varsN[varName]] = pathVars[i+1] - varName++ - } - } - // Check if we should redirect. - if v.path.strictSlash { - p1 := strings.HasSuffix(req.URL.Path, "/") - p2 := strings.HasSuffix(v.path.template, "/") - if p1 != p2 { - u, _ := url.Parse(req.URL.String()) - if p1 { - u.Path = u.Path[:len(u.Path)-1] - } else { - u.Path += "/" - } - m.Handler = http.RedirectHandler(u.String(), 301) - } - } - } - } - // Store query string variables. - for _, q := range v.queries { - queryVars := q.regexp.FindStringSubmatch(q.getUrlQuery(req)) - if queryVars != nil { - subexpNames := q.regexp.SubexpNames() - varName := 0 - for i, name := range subexpNames[1:] { - if name != "" && name == varGroupName(varName) { - m.Vars[q.varsN[varName]] = queryVars[i+1] - varName++ - } - } - } - } -} - -// getHost tries its best to return the request host. -func getHost(r *http.Request) string { - if r.URL.IsAbs() { - return r.URL.Host - } - host := r.Host - // Slice off any port information. - if i := strings.Index(host, ":"); i != -1 { - host = host[:i] - } - return host - -} diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/route.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/route.go deleted file mode 100644 index 89013046..00000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/route.go +++ /dev/null @@ -1,603 +0,0 @@ -// Copyright 2012 The Gorilla 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 mux - -import ( - "errors" - "fmt" - "net/http" - "net/url" - "regexp" - "strings" -) - -// Route stores information to match a request and build URLs. -type Route struct { - // Parent where the route was registered (a Router). - parent parentRoute - // Request handler for the route. - handler http.Handler - // List of matchers. - matchers []matcher - // Manager for the variables from host and path. - regexp *routeRegexpGroup - // If true, when the path pattern is "/path/", accessing "/path" will - // redirect to the former and vice versa. - strictSlash bool - // If true, this route never matches: it is only used to build URLs. - buildOnly bool - // The name used to build URLs. - name string - // Error resulted from building a route. - err error - - buildVarsFunc BuildVarsFunc -} - -// Match matches the route against the request. -func (r *Route) Match(req *http.Request, match *RouteMatch) bool { - if r.buildOnly || r.err != nil { - return false - } - // Match everything. - for _, m := range r.matchers { - if matched := m.Match(req, match); !matched { - return false - } - } - // Yay, we have a match. Let's collect some info about it. - if match.Route == nil { - match.Route = r - } - if match.Handler == nil { - match.Handler = r.handler - } - if match.Vars == nil { - match.Vars = make(map[string]string) - } - // Set variables. - if r.regexp != nil { - r.regexp.setMatch(req, match, r) - } - return true -} - -// ---------------------------------------------------------------------------- -// Route attributes -// ---------------------------------------------------------------------------- - -// GetError returns an error resulted from building the route, if any. -func (r *Route) GetError() error { - return r.err -} - -// BuildOnly sets the route to never match: it is only used to build URLs. -func (r *Route) BuildOnly() *Route { - r.buildOnly = true - return r -} - -// Handler -------------------------------------------------------------------- - -// Handler sets a handler for the route. -func (r *Route) Handler(handler http.Handler) *Route { - if r.err == nil { - r.handler = handler - } - return r -} - -// HandlerFunc sets a handler function for the route. -func (r *Route) HandlerFunc(f func(http.ResponseWriter, *http.Request)) *Route { - return r.Handler(http.HandlerFunc(f)) -} - -// GetHandler returns the handler for the route, if any. -func (r *Route) GetHandler() http.Handler { - return r.handler -} - -// Name ----------------------------------------------------------------------- - -// Name sets the name for the route, used to build URLs. -// If the name was registered already it will be overwritten. -func (r *Route) Name(name string) *Route { - if r.name != "" { - r.err = fmt.Errorf("mux: route already has name %q, can't set %q", - r.name, name) - } - if r.err == nil { - r.name = name - r.getNamedRoutes()[name] = r - } - return r -} - -// GetName returns the name for the route, if any. -func (r *Route) GetName() string { - return r.name -} - -// ---------------------------------------------------------------------------- -// Matchers -// ---------------------------------------------------------------------------- - -// matcher types try to match a request. -type matcher interface { - Match(*http.Request, *RouteMatch) bool -} - -// addMatcher adds a matcher to the route. -func (r *Route) addMatcher(m matcher) *Route { - if r.err == nil { - r.matchers = append(r.matchers, m) - } - return r -} - -// addRegexpMatcher adds a host or path matcher and builder to a route. -func (r *Route) addRegexpMatcher(tpl string, matchHost, matchPrefix, matchQuery bool) error { - if r.err != nil { - return r.err - } - r.regexp = r.getRegexpGroup() - if !matchHost && !matchQuery { - if len(tpl) == 0 || tpl[0] != '/' { - return fmt.Errorf("mux: path must start with a slash, got %q", tpl) - } - if r.regexp.path != nil { - tpl = strings.TrimRight(r.regexp.path.template, "/") + tpl - } - } - rr, err := newRouteRegexp(tpl, matchHost, matchPrefix, matchQuery, r.strictSlash) - if err != nil { - return err - } - for _, q := range r.regexp.queries { - if err = uniqueVars(rr.varsN, q.varsN); err != nil { - return err - } - } - if matchHost { - if r.regexp.path != nil { - if err = uniqueVars(rr.varsN, r.regexp.path.varsN); err != nil { - return err - } - } - r.regexp.host = rr - } else { - if r.regexp.host != nil { - if err = uniqueVars(rr.varsN, r.regexp.host.varsN); err != nil { - return err - } - } - if matchQuery { - r.regexp.queries = append(r.regexp.queries, rr) - } else { - r.regexp.path = rr - } - } - r.addMatcher(rr) - return nil -} - -// Headers -------------------------------------------------------------------- - -// headerMatcher matches the request against header values. -type headerMatcher map[string]string - -func (m headerMatcher) Match(r *http.Request, match *RouteMatch) bool { - return matchMapWithString(m, r.Header, true) -} - -// Headers adds a matcher for request header values. -// It accepts a sequence of key/value pairs to be matched. For example: -// -// r := mux.NewRouter() -// r.Headers("Content-Type", "application/json", -// "X-Requested-With", "XMLHttpRequest") -// -// The above route will only match if both request header values match. -// Alternatively, you can provide a regular expression and match the header as follows: -// -// r.Headers("Content-Type", "application/(text|json)", -// "X-Requested-With", "XMLHttpRequest") -// -// The above route will the same as the previous example, with the addition of matching -// application/text as well. -// -// It the value is an empty string, it will match any value if the key is set. -func (r *Route) Headers(pairs ...string) *Route { - if r.err == nil { - var headers map[string]string - headers, r.err = mapFromPairsToString(pairs...) - return r.addMatcher(headerMatcher(headers)) - } - return r -} - -// headerRegexMatcher matches the request against the route given a regex for the header -type headerRegexMatcher map[string]*regexp.Regexp - -func (m headerRegexMatcher) Match(r *http.Request, match *RouteMatch) bool { - return matchMapWithRegex(m, r.Header, true) -} - -// Regular expressions can be used with headers as well. -// It accepts a sequence of key/value pairs, where the value has regex support. For example -// r := mux.NewRouter() -// r.HeadersRegexp("Content-Type", "application/(text|json)", -// "X-Requested-With", "XMLHttpRequest") -// -// The above route will only match if both the request header matches both regular expressions. -// It the value is an empty string, it will match any value if the key is set. -func (r *Route) HeadersRegexp(pairs ...string) *Route { - if r.err == nil { - var headers map[string]*regexp.Regexp - headers, r.err = mapFromPairsToRegex(pairs...) - return r.addMatcher(headerRegexMatcher(headers)) - } - return r -} - -// Host ----------------------------------------------------------------------- - -// Host adds a matcher for the URL host. -// It accepts a template with zero or more URL variables enclosed by {}. -// Variables can define an optional regexp pattern to be matched: -// -// - {name} matches anything until the next dot. -// -// - {name:pattern} matches the given regexp pattern. -// -// For example: -// -// r := mux.NewRouter() -// r.Host("www.example.com") -// r.Host("{subdomain}.domain.com") -// r.Host("{subdomain:[a-z]+}.domain.com") -// -// Variable names must be unique in a given route. They can be retrieved -// calling mux.Vars(request). -func (r *Route) Host(tpl string) *Route { - r.err = r.addRegexpMatcher(tpl, true, false, false) - return r -} - -// MatcherFunc ---------------------------------------------------------------- - -// MatcherFunc is the function signature used by custom matchers. -type MatcherFunc func(*http.Request, *RouteMatch) bool - -func (m MatcherFunc) Match(r *http.Request, match *RouteMatch) bool { - return m(r, match) -} - -// MatcherFunc adds a custom function to be used as request matcher. -func (r *Route) MatcherFunc(f MatcherFunc) *Route { - return r.addMatcher(f) -} - -// Methods -------------------------------------------------------------------- - -// methodMatcher matches the request against HTTP methods. -type methodMatcher []string - -func (m methodMatcher) Match(r *http.Request, match *RouteMatch) bool { - return matchInArray(m, r.Method) -} - -// Methods adds a matcher for HTTP methods. -// It accepts a sequence of one or more methods to be matched, e.g.: -// "GET", "POST", "PUT". -func (r *Route) Methods(methods ...string) *Route { - for k, v := range methods { - methods[k] = strings.ToUpper(v) - } - return r.addMatcher(methodMatcher(methods)) -} - -// Path ----------------------------------------------------------------------- - -// Path adds a matcher for the URL path. -// It accepts a template with zero or more URL variables enclosed by {}. The -// template must start with a "/". -// Variables can define an optional regexp pattern to be matched: -// -// - {name} matches anything until the next slash. -// -// - {name:pattern} matches the given regexp pattern. -// -// For example: -// -// r := mux.NewRouter() -// r.Path("/products/").Handler(ProductsHandler) -// r.Path("/products/{key}").Handler(ProductsHandler) -// r.Path("/articles/{category}/{id:[0-9]+}"). -// Handler(ArticleHandler) -// -// Variable names must be unique in a given route. They can be retrieved -// calling mux.Vars(request). -func (r *Route) Path(tpl string) *Route { - r.err = r.addRegexpMatcher(tpl, false, false, false) - return r -} - -// PathPrefix ----------------------------------------------------------------- - -// PathPrefix adds a matcher for the URL path prefix. This matches if the given -// template is a prefix of the full URL path. See Route.Path() for details on -// the tpl argument. -// -// Note that it does not treat slashes specially ("/foobar/" will be matched by -// the prefix "/foo") so you may want to use a trailing slash here. -// -// Also note that the setting of Router.StrictSlash() has no effect on routes -// with a PathPrefix matcher. -func (r *Route) PathPrefix(tpl string) *Route { - r.err = r.addRegexpMatcher(tpl, false, true, false) - return r -} - -// Query ---------------------------------------------------------------------- - -// Queries adds a matcher for URL query values. -// It accepts a sequence of key/value pairs. Values may define variables. -// For example: -// -// r := mux.NewRouter() -// r.Queries("foo", "bar", "id", "{id:[0-9]+}") -// -// The above route will only match if the URL contains the defined queries -// values, e.g.: ?foo=bar&id=42. -// -// It the value is an empty string, it will match any value if the key is set. -// -// Variables can define an optional regexp pattern to be matched: -// -// - {name} matches anything until the next slash. -// -// - {name:pattern} matches the given regexp pattern. -func (r *Route) Queries(pairs ...string) *Route { - length := len(pairs) - if length%2 != 0 { - r.err = fmt.Errorf( - "mux: number of parameters must be multiple of 2, got %v", pairs) - return nil - } - for i := 0; i < length; i += 2 { - if r.err = r.addRegexpMatcher(pairs[i]+"="+pairs[i+1], false, false, true); r.err != nil { - return r - } - } - - return r -} - -// Schemes -------------------------------------------------------------------- - -// schemeMatcher matches the request against URL schemes. -type schemeMatcher []string - -func (m schemeMatcher) Match(r *http.Request, match *RouteMatch) bool { - return matchInArray(m, r.URL.Scheme) -} - -// Schemes adds a matcher for URL schemes. -// It accepts a sequence of schemes to be matched, e.g.: "http", "https". -func (r *Route) Schemes(schemes ...string) *Route { - for k, v := range schemes { - schemes[k] = strings.ToLower(v) - } - return r.addMatcher(schemeMatcher(schemes)) -} - -// BuildVarsFunc -------------------------------------------------------------- - -// BuildVarsFunc is the function signature used by custom build variable -// functions (which can modify route variables before a route's URL is built). -type BuildVarsFunc func(map[string]string) map[string]string - -// BuildVarsFunc adds a custom function to be used to modify build variables -// before a route's URL is built. -func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route { - r.buildVarsFunc = f - return r -} - -// Subrouter ------------------------------------------------------------------ - -// Subrouter creates a subrouter for the route. -// -// It will test the inner routes only if the parent route matched. For example: -// -// r := mux.NewRouter() -// s := r.Host("www.example.com").Subrouter() -// s.HandleFunc("/products/", ProductsHandler) -// s.HandleFunc("/products/{key}", ProductHandler) -// s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) -// -// Here, the routes registered in the subrouter won't be tested if the host -// doesn't match. -func (r *Route) Subrouter() *Router { - router := &Router{parent: r, strictSlash: r.strictSlash} - r.addMatcher(router) - return router -} - -// ---------------------------------------------------------------------------- -// URL building -// ---------------------------------------------------------------------------- - -// URL builds a URL for the route. -// -// It accepts a sequence of key/value pairs for the route variables. For -// example, given this route: -// -// r := mux.NewRouter() -// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). -// Name("article") -// -// ...a URL for it can be built using: -// -// url, err := r.Get("article").URL("category", "technology", "id", "42") -// -// ...which will return an url.URL with the following path: -// -// "/articles/technology/42" -// -// This also works for host variables: -// -// r := mux.NewRouter() -// r.Host("{subdomain}.domain.com"). -// HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). -// Name("article") -// -// // url.String() will be "http://news.domain.com/articles/technology/42" -// url, err := r.Get("article").URL("subdomain", "news", -// "category", "technology", -// "id", "42") -// -// All variables defined in the route are required, and their values must -// conform to the corresponding patterns. -func (r *Route) URL(pairs ...string) (*url.URL, error) { - if r.err != nil { - return nil, r.err - } - if r.regexp == nil { - return nil, errors.New("mux: route doesn't have a host or path") - } - values, err := r.prepareVars(pairs...) - if err != nil { - return nil, err - } - var scheme, host, path string - if r.regexp.host != nil { - // Set a default scheme. - scheme = "http" - if host, err = r.regexp.host.url(values); err != nil { - return nil, err - } - } - if r.regexp.path != nil { - if path, err = r.regexp.path.url(values); err != nil { - return nil, err - } - } - return &url.URL{ - Scheme: scheme, - Host: host, - Path: path, - }, nil -} - -// URLHost builds the host part of the URL for a route. See Route.URL(). -// -// The route must have a host defined. -func (r *Route) URLHost(pairs ...string) (*url.URL, error) { - if r.err != nil { - return nil, r.err - } - if r.regexp == nil || r.regexp.host == nil { - return nil, errors.New("mux: route doesn't have a host") - } - values, err := r.prepareVars(pairs...) - if err != nil { - return nil, err - } - host, err := r.regexp.host.url(values) - if err != nil { - return nil, err - } - return &url.URL{ - Scheme: "http", - Host: host, - }, nil -} - -// URLPath builds the path part of the URL for a route. See Route.URL(). -// -// The route must have a path defined. -func (r *Route) URLPath(pairs ...string) (*url.URL, error) { - if r.err != nil { - return nil, r.err - } - if r.regexp == nil || r.regexp.path == nil { - return nil, errors.New("mux: route doesn't have a path") - } - values, err := r.prepareVars(pairs...) - if err != nil { - return nil, err - } - path, err := r.regexp.path.url(values) - if err != nil { - return nil, err - } - return &url.URL{ - Path: path, - }, nil -} - -// prepareVars converts the route variable pairs into a map. If the route has a -// BuildVarsFunc, it is invoked. -func (r *Route) prepareVars(pairs ...string) (map[string]string, error) { - m, err := mapFromPairsToString(pairs...) - if err != nil { - return nil, err - } - return r.buildVars(m), nil -} - -func (r *Route) buildVars(m map[string]string) map[string]string { - if r.parent != nil { - m = r.parent.buildVars(m) - } - if r.buildVarsFunc != nil { - m = r.buildVarsFunc(m) - } - return m -} - -// ---------------------------------------------------------------------------- -// parentRoute -// ---------------------------------------------------------------------------- - -// parentRoute allows routes to know about parent host and path definitions. -type parentRoute interface { - getNamedRoutes() map[string]*Route - getRegexpGroup() *routeRegexpGroup - buildVars(map[string]string) map[string]string -} - -// getNamedRoutes returns the map where named routes are registered. -func (r *Route) getNamedRoutes() map[string]*Route { - if r.parent == nil { - // During tests router is not always set. - r.parent = NewRouter() - } - return r.parent.getNamedRoutes() -} - -// getRegexpGroup returns regexp definitions from this route. -func (r *Route) getRegexpGroup() *routeRegexpGroup { - if r.regexp == nil { - if r.parent == nil { - // During tests router is not always set. - r.parent = NewRouter() - } - regexp := r.parent.getRegexpGroup() - if regexp == nil { - r.regexp = new(routeRegexpGroup) - } else { - // Copy. - r.regexp = &routeRegexpGroup{ - host: regexp.host, - path: regexp.path, - queries: regexp.queries, - } - } - } - return r.regexp -} diff --git a/vendor/github.com/guelfey/go.dbus/introspect/call.go b/vendor/github.com/guelfey/go.dbus/introspect/call.go deleted file mode 100644 index 180ba58d..00000000 --- a/vendor/github.com/guelfey/go.dbus/introspect/call.go +++ /dev/null @@ -1,27 +0,0 @@ -package introspect - -import ( - "encoding/xml" - "github.com/guelfey/go.dbus" - "strings" -) - -// Call calls org.freedesktop.Introspectable.Introspect on a remote object -// and returns the introspection data. -func Call(o *dbus.Object) (*Node, error) { - var xmldata string - var node Node - - err := o.Call("org.freedesktop.DBus.Introspectable.Introspect", 0).Store(&xmldata) - if err != nil { - return nil, err - } - err = xml.NewDecoder(strings.NewReader(xmldata)).Decode(&node) - if err != nil { - return nil, err - } - if node.Name == "" { - node.Name = string(o.Path()) - } - return &node, nil -} diff --git a/vendor/github.com/guelfey/go.dbus/introspect/introspect.go b/vendor/github.com/guelfey/go.dbus/introspect/introspect.go deleted file mode 100644 index dafcdb8b..00000000 --- a/vendor/github.com/guelfey/go.dbus/introspect/introspect.go +++ /dev/null @@ -1,80 +0,0 @@ -// Package introspect provides some utilities for dealing with the DBus -// introspection format. -package introspect - -import "encoding/xml" - -// The introspection data for the org.freedesktop.DBus.Introspectable interface. -var IntrospectData = Interface{ - Name: "org.freedesktop.DBus.Introspectable", - Methods: []Method{ - { - Name: "Introspect", - Args: []Arg{ - {"out", "s", "out"}, - }, - }, - }, -} - -// The introspection data for the org.freedesktop.DBus.Introspectable interface, -// as a string. -const IntrospectDataString = ` - - - - - -` - -// Node is the root element of an introspection. -type Node struct { - XMLName xml.Name `xml:"node"` - Name string `xml:"name,attr,omitempty"` - Interfaces []Interface `xml:"interface"` - Children []Node `xml:"node,omitempty"` -} - -// Interface describes a DBus interface that is available on the message bus. -type Interface struct { - Name string `xml:"name,attr"` - Methods []Method `xml:"method"` - Signals []Signal `xml:"signal"` - Properties []Property `xml:"property"` - Annotations []Annotation `xml:"annotation"` -} - -// Method describes a Method on an Interface as retured by an introspection. -type Method struct { - Name string `xml:"name,attr"` - Args []Arg `xml:"arg"` - Annotations []Annotation `xml:"annotation"` -} - -// Signal describes a Signal emitted on an Interface. -type Signal struct { - Name string `xml:"name,attr"` - Args []Arg `xml:"arg"` - Annotations []Annotation `xml:"annotation"` -} - -// Property describes a property of an Interface. -type Property struct { - Name string `xml:"name,attr"` - Type string `xml:"type,attr"` - Access string `xml:"access,attr"` - Annotations []Annotation `xml:"annotation"` -} - -// Arg represents an argument of a method or a signal. -type Arg struct { - Name string `xml:"name,attr,omitempty"` - Type string `xml:"type,attr"` - Direction string `xml:"direction,attr,omitempty"` -} - -// Annotation is an annotation in the introspection format. -type Annotation struct { - Name string `xml:"name,attr"` - Value string `xml:"value,attr"` -} diff --git a/vendor/github.com/guelfey/go.dbus/introspect/introspectable.go b/vendor/github.com/guelfey/go.dbus/introspect/introspectable.go deleted file mode 100644 index ca1f8b57..00000000 --- a/vendor/github.com/guelfey/go.dbus/introspect/introspectable.go +++ /dev/null @@ -1,74 +0,0 @@ -package introspect - -import ( - "encoding/xml" - "github.com/guelfey/go.dbus" - "reflect" -) - -// Introspectable implements org.freedesktop.Introspectable. -// -// You can create it by converting the XML-formatted introspection data from a -// string to an Introspectable or call NewIntrospectable with a Node. Then, -// export it as org.freedesktop.Introspectable on you object. -type Introspectable string - -// NewIntrospectable returns an Introspectable that returns the introspection -// data that corresponds to the given Node. If n.Interfaces doesn't contain the -// data for org.freedesktop.DBus.Introspectable, it is added automatically. -func NewIntrospectable(n *Node) Introspectable { - found := false - for _, v := range n.Interfaces { - if v.Name == "org.freedesktop.DBus.Introspectable" { - found = true - break - } - } - if !found { - n.Interfaces = append(n.Interfaces, IntrospectData) - } - b, err := xml.Marshal(n) - if err != nil { - panic(err) - } - return Introspectable(b) -} - -// Introspect implements org.freedesktop.Introspectable.Introspect. -func (i Introspectable) Introspect() (string, *dbus.Error) { - return string(i), nil -} - -// Methods returns the description of the methods of v. This can be used to -// create a Node which can be passed to NewIntrospectable. -func Methods(v interface{}) []Method { - t := reflect.TypeOf(v) - ms := make([]Method, 0, t.NumMethod()) - for i := 0; i < t.NumMethod(); i++ { - if t.Method(i).PkgPath != "" { - continue - } - mt := t.Method(i).Type - if mt.NumOut() == 0 || - mt.Out(mt.NumOut()-1) != reflect.TypeOf(&dbus.Error{"", nil}) { - - continue - } - var m Method - m.Name = t.Method(i).Name - m.Args = make([]Arg, 0, mt.NumIn()+mt.NumOut()-2) - for j := 1; j < mt.NumIn(); j++ { - if mt.In(j) != reflect.TypeOf((*dbus.Sender)(nil)).Elem() { - arg := Arg{"", dbus.SignatureOfType(mt.In(j)).String(), "in"} - m.Args = append(m.Args, arg) - } - } - for j := 0; j < mt.NumOut()-1; j++ { - arg := Arg{"", dbus.SignatureOfType(mt.Out(j)).String(), "out"} - m.Args = append(m.Args, arg) - } - m.Annotations = make([]Annotation, 0) - ms = append(ms, m) - } - return ms -} diff --git a/vendor/github.com/guelfey/go.dbus/prop/prop.go b/vendor/github.com/guelfey/go.dbus/prop/prop.go deleted file mode 100644 index bc695207..00000000 --- a/vendor/github.com/guelfey/go.dbus/prop/prop.go +++ /dev/null @@ -1,264 +0,0 @@ -// Package prop provides the Properties struct which can be used to implement -// org.freedesktop.DBus.Properties. -package prop - -import ( - "github.com/guelfey/go.dbus" - "github.com/guelfey/go.dbus/introspect" - "sync" -) - -// EmitType controls how org.freedesktop.DBus.Properties.PropertiesChanged is -// emitted for a property. If it is EmitTrue, the signal is emitted. If it is -// EmitInvalidates, the signal is also emitted, but the new value of the property -// is not disclosed. -type EmitType byte - -const ( - EmitFalse EmitType = iota - EmitTrue - EmitInvalidates -) - -// ErrIfaceNotFound is the error returned to peers who try to access properties -// on interfaces that aren't found. -var ErrIfaceNotFound = &dbus.Error{"org.freedesktop.DBus.Properties.Error.InterfaceNotFound", nil} - -// ErrPropNotFound is the error returned to peers trying to access properties -// that aren't found. -var ErrPropNotFound = &dbus.Error{"org.freedesktop.DBus.Properties.Error.PropertyNotFound", nil} - -// ErrReadOnly is the error returned to peers trying to set a read-only -// property. -var ErrReadOnly = &dbus.Error{"org.freedesktop.DBus.Properties.Error.ReadOnly", nil} - -// ErrInvalidArg is returned to peers if the type of the property that is being -// changed and the argument don't match. -var ErrInvalidArg = &dbus.Error{"org.freedesktop.DBus.Properties.Error.InvalidArg", nil} - -// The introspection data for the org.freedesktop.DBus.Properties interface. -var IntrospectData = introspect.Interface{ - Name: "org.freedesktop.DBus.Properties", - Methods: []introspect.Method{ - { - Name: "Get", - Args: []introspect.Arg{ - {"interface", "s", "in"}, - {"property", "s", "in"}, - {"value", "v", "out"}, - }, - }, - { - Name: "GetAll", - Args: []introspect.Arg{ - {"interface", "s", "in"}, - {"props", "a{sv}", "out"}, - }, - }, - { - Name: "Set", - Args: []introspect.Arg{ - {"interface", "s", "in"}, - {"property", "s", "in"}, - {"value", "v", "in"}, - }, - }, - }, - Signals: []introspect.Signal{ - { - Name: "PropertiesChanged", - Args: []introspect.Arg{ - {"interface", "s", "out"}, - {"changed_properties", "a{sv}", "out"}, - {"invalidates_properties", "as", "out"}, - }, - }, - }, -} - -// The introspection data for the org.freedesktop.DBus.Properties interface, as -// a string. -const IntrospectDataString = ` - - - - - - - - - - - - - - - - - - - - - -` - -// Prop represents a single property. It is used for creating a Properties -// value. -type Prop struct { - // Initial value. Must be a DBus-representable type. - Value interface{} - - // If true, the value can be modified by calls to Set. - Writable bool - - // Controls how org.freedesktop.DBus.Properties.PropertiesChanged is - // emitted if this property changes. - Emit EmitType - - // If not nil, anytime this property is changed by Set, this function is - // called with an appropiate Change as its argument. If the returned error - // is not nil, it is sent back to the caller of Set and the property is not - // changed. - Callback func(*Change) *dbus.Error -} - -// Change represents a change of a property by a call to Set. -type Change struct { - Props *Properties - Iface string - Name string - Value interface{} -} - -// Properties is a set of values that can be made available to the message bus -// using the org.freedesktop.DBus.Properties interface. It is safe for -// concurrent use by multiple goroutines. -type Properties struct { - m map[string]map[string]*Prop - mut sync.RWMutex - conn *dbus.Conn - path dbus.ObjectPath -} - -// New returns a new Properties structure that manages the given properties. -// The key for the first-level map of props is the name of the interface; the -// second-level key is the name of the property. The returned structure will be -// exported as org.freedesktop.DBus.Properties on path. -func New(conn *dbus.Conn, path dbus.ObjectPath, props map[string]map[string]*Prop) *Properties { - p := &Properties{m: props, conn: conn, path: path} - conn.Export(p, path, "org.freedesktop.DBus.Properties") - return p -} - -// Get implements org.freedesktop.DBus.Properties.Get. -func (p *Properties) Get(iface, property string) (dbus.Variant, *dbus.Error) { - p.mut.RLock() - defer p.mut.RUnlock() - m, ok := p.m[iface] - if !ok { - return dbus.Variant{}, ErrIfaceNotFound - } - prop, ok := m[property] - if !ok { - return dbus.Variant{}, ErrPropNotFound - } - return dbus.MakeVariant(prop.Value), nil -} - -// GetAll implements org.freedesktop.DBus.Properties.GetAll. -func (p *Properties) GetAll(iface string) (map[string]dbus.Variant, *dbus.Error) { - p.mut.RLock() - defer p.mut.RUnlock() - m, ok := p.m[iface] - if !ok { - return nil, ErrIfaceNotFound - } - rm := make(map[string]dbus.Variant, len(m)) - for k, v := range m { - rm[k] = dbus.MakeVariant(v.Value) - } - return rm, nil -} - -// GetMust returns the value of the given property and panics if either the -// interface or the property name are invalid. -func (p *Properties) GetMust(iface, property string) interface{} { - p.mut.RLock() - defer p.mut.RUnlock() - return p.m[iface][property].Value -} - -// Introspection returns the introspection data that represents the properties -// of iface. -func (p *Properties) Introspection(iface string) []introspect.Property { - p.mut.RLock() - defer p.mut.RUnlock() - m := p.m[iface] - s := make([]introspect.Property, 0, len(m)) - for k, v := range m { - p := introspect.Property{Name: k, Type: dbus.SignatureOf(v.Value).String()} - if v.Writable { - p.Access = "readwrite" - } else { - p.Access = "read" - } - s = append(s, p) - } - return s -} - -// set sets the given property and emits PropertyChanged if appropiate. p.mut -// must already be locked. -func (p *Properties) set(iface, property string, v interface{}) { - prop := p.m[iface][property] - prop.Value = v - switch prop.Emit { - case EmitFalse: - // do nothing - case EmitInvalidates: - p.conn.Emit(p.path, "org.freedesktop.DBus.Properties.PropertiesChanged", - iface, map[string]dbus.Variant{}, []string{property}) - case EmitTrue: - p.conn.Emit(p.path, "org.freedesktop.DBus.Properties.PropertiesChanged", - iface, map[string]dbus.Variant{property: dbus.MakeVariant(v)}, - []string{}) - default: - panic("invalid value for EmitType") - } -} - -// Set implements org.freedesktop.Properties.Set. -func (p *Properties) Set(iface, property string, newv dbus.Variant) *dbus.Error { - p.mut.Lock() - defer p.mut.Unlock() - m, ok := p.m[iface] - if !ok { - return ErrIfaceNotFound - } - prop, ok := m[property] - if !ok { - return ErrPropNotFound - } - if !prop.Writable { - return ErrReadOnly - } - if newv.Signature() != dbus.SignatureOf(prop.Value) { - return ErrInvalidArg - } - if prop.Callback != nil { - err := prop.Callback(&Change{p, iface, property, newv.Value()}) - if err != nil { - return err - } - } - p.set(iface, property, newv.Value()) - return nil -} - -// SetMust sets the value of the given property and panics if the interface or -// the property name are invalid. -func (p *Properties) SetMust(iface, property string, v interface{}) { - p.mut.Lock() - p.set(iface, property, v) - p.mut.Unlock() -} diff --git a/vendor/github.com/kless/term/Doc/AUTHORS.md b/vendor/github.com/kless/term/Doc/AUTHORS.md deleted file mode 100644 index 11cecb22..00000000 --- a/vendor/github.com/kless/term/Doc/AUTHORS.md +++ /dev/null @@ -1,16 +0,0 @@ -###### Notice - -*This is the official list of **Terminal** authors for copyright purposes.* - -*This file is distinct from the CONTRIBUTORS file. See the latter for an -explanation.* - -*Names should be added to this file as: `Organization`; -`[Name](web address)` or `Name ` for individuals* - -*Please keep the list sorted.* - -* * * - -[Jonas mg](https://github.com/kless) - diff --git a/vendor/github.com/kless/term/Doc/CONTRIBUTORS.md b/vendor/github.com/kless/term/Doc/CONTRIBUTORS.md deleted file mode 100644 index d7f483db..00000000 --- a/vendor/github.com/kless/term/Doc/CONTRIBUTORS.md +++ /dev/null @@ -1,26 +0,0 @@ -###### Notice - -*This is the official list of people who can contribute (and typically have -contributed) code to the **Terminal** repository.* - -*The AUTHORS file lists the copyright holders; this file lists people. For -example, the employees of an organization are listed here but not in AUTHORS, -because the organization holds the copyright.* - -*Names should be added to this file as: `[Name](web address)` or `Name `* - -*Please keep the list sorted.* - -* * * - -### Initial author - -[Jonas mg](https://github.com/kless) - -### Maintainer - - - -### Other authors - - diff --git a/vendor/github.com/kless/term/Doc/LICENSE-MPL.txt b/vendor/github.com/kless/term/Doc/LICENSE-MPL.txt deleted file mode 100644 index 52d13511..00000000 --- a/vendor/github.com/kless/term/Doc/LICENSE-MPL.txt +++ /dev/null @@ -1,374 +0,0 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. - diff --git a/vendor/github.com/kless/term/Doc/NEWS.md b/vendor/github.com/kless/term/Doc/NEWS.md deleted file mode 100644 index dec700b3..00000000 --- a/vendor/github.com/kless/term/Doc/NEWS.md +++ /dev/null @@ -1,15 +0,0 @@ -###### Notice - -*This file documents the changes in **Terminal** versions that are listed below.* - -*Items should be added to this file as:* - - ### YYYY-MM-DD Release - - + Additional changes. - - + More changes. - -* * * - - diff --git a/vendor/github.com/kless/term/readline/ansi.go b/vendor/github.com/kless/term/readline/ansi.go deleted file mode 100644 index 0dfcc283..00000000 --- a/vendor/github.com/kless/term/readline/ansi.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2010 Jonas mg -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// The references about ANSI Escape sequences have been got from -// http://ascii-table.com/ansi-escape-sequences.php and -// http://www.termsys.demon.co.uk/vtansi.htm - -package readline - -// ANSI terminal escape controls -const ( - // Cursor control - ANSI_CURSOR_UP = "\033[A" // Up - ANSI_CURSOR_DOWN = "\033[B" // Down - ANSI_CURSOR_FORWARD = "\033[C" // Forward - ANSI_CURSOR_BACKWARD = "\033[D" // Backward - - ANSI_NEXT_LINE = "\033[E" // To next line - ANSI_PREV_LINE = "\033[F" // To previous line - - // Erase - ANSI_DEL_LINE = "\033[2K" // Erase line - - // Graphics mode - ANSI_SET_BOLD = "\033[1m" // Bold on - ANSI_SET_OFF = "\033[0m" // All attributes off -) - -// ANSI terminal escape controls -var ( - // Cursor control - CursorUp = []byte(ANSI_CURSOR_UP) - CursorDown = []byte(ANSI_CURSOR_DOWN) - CursorForward = []byte(ANSI_CURSOR_FORWARD) - CursorBackward = []byte(ANSI_CURSOR_BACKWARD) - - ToNextLine = []byte(ANSI_NEXT_LINE) - ToPreviousLine = []byte(ANSI_PREV_LINE) - - // Erase Text - DelScreenToUpper = []byte("\033[2J\033[0;0H") // Erase the screen; move upper - - DelToRight = []byte("\033[0K") // Erase to right - DelLine_CR = []byte("\033[2K\r") // Erase line; carriage return - DelLine_cursorUp = []byte("\033[2K\033[A") // Erase line; cursor up - - //DelChar = []byte("\033[1X") // Erase character - DelChar = []byte("\033[P") // Delete character, from current position - DelBackspace = []byte("\033[D\033[P") - - // Misc. - //InsertChar = []byte("\033[@") // Insert CHaracter - //SetLineWrap = []byte("\033[?7h") // Enable Line Wrap -) - -// Characters -var ( - CR = []byte{13} // Carriage return -- \r - CRLF = []byte{13, 10} // CR+LF is used for a new line in raw mode -- \r\n - CtrlC = []rune("^C") - CtrlD = []rune("^D") -) diff --git a/vendor/github.com/kless/term/readline/buffer.go b/vendor/github.com/kless/term/readline/buffer.go deleted file mode 100644 index 75d56e4e..00000000 --- a/vendor/github.com/kless/term/readline/buffer.go +++ /dev/null @@ -1,380 +0,0 @@ -// Copyright 2010 Jonas mg -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -package readline - -import ( - "fmt" - "unicode/utf8" - - "github.com/kless/term" -) - -// Buffer size -var ( - BufferCap = 4096 - BufferLen = 64 // Initial length -) - -// == Init - -/*var lines, columns int - -func init() { - lines, columns = term.SizeInChar() -}*/ - -// == Type - -// A buffer represents the line buffer. -type buffer struct { - columns int // Number of columns for actual window - promptLen int - pos int // Pointer position into buffer - size int // Amount of characters added - data []rune // Text buffer -} - -func newBuffer(promptLen, columns int) *buffer { - b := new(buffer) - - b.columns = columns - b.promptLen = promptLen - b.data = make([]rune, BufferLen, BufferCap) - - return b -} - -// == Output - -// insertRune inserts a character in the cursor position. -func (b *buffer) insertRune(r rune) error { - var useRefresh bool - - b.grow(b.size + 1) // Check if there is free space for one more character - - // Avoid a full update of the line. - if b.pos == b.size { - char := make([]byte, utf8.UTFMax) - utf8.EncodeRune(char, r) - - if _, err := term.Output.Write(char); err != nil { - return outputError(err.Error()) - } - } else { - useRefresh = true - copy(b.data[b.pos+1:b.size+1], b.data[b.pos:b.size]) - } - - b.data[b.pos] = r - b.pos++ - b.size++ - - if useRefresh { - return b.refresh() - } - return nil -} - -// insertRunes inserts several characters. -func (b *buffer) insertRunes(runes []rune) error { - for _, r := range runes { - if err := b.insertRune(r); err != nil { - return err - } - } - return nil -} - -// toBytes returns a slice of the contents of the buffer. -func (b *buffer) toBytes() []byte { - chars := make([]byte, b.size*utf8.UTFMax) - var end, runeLen int - - // == Each character (as integer) is encoded to []byte - for i := 0; i < b.size; i++ { - if i != 0 { - runeLen = utf8.EncodeRune(chars[end:], b.data[i]) - end += runeLen - } else { - runeLen = utf8.EncodeRune(chars, b.data[i]) - end = runeLen - } - } - return chars[:end] -} - -// toString returns the contents of the buffer as a string. -func (b *buffer) toString() string { return string(b.data[b.promptLen:b.size]) } - -// refresh refreshes the line. -func (b *buffer) refresh() (err error) { - lastLine, _ := b.pos2xy(b.size) - posLine, posColumn := b.pos2xy(b.pos) - - // To the first line. - for ln := posLine; ln > 0; ln-- { - if _, err = term.Output.Write(ToPreviousLine); err != nil { - return outputError(err.Error()) - } - } - - // == Write the line - if _, err = term.Output.Write(CR); err != nil { - return outputError(err.Error()) - } - if _, err = term.Output.Write(b.toBytes()); err != nil { - return outputError(err.Error()) - } - if _, err = term.Output.Write(DelToRight); err != nil { - return outputError(err.Error()) - } - - // == Move cursor to original position. - for ln := lastLine; ln > posLine; ln-- { - if _, err = term.Output.Write(ToPreviousLine); err != nil { - return outputError(err.Error()) - } - } - if _, err = fmt.Fprintf(term.Output, "\r\033[%dC", posColumn); err != nil { - return outputError(err.Error()) - } - - return nil -} - -// == Movement - -// start moves the cursor at the start. -func (b *buffer) start() (err error) { - if b.pos == b.promptLen { - return - } - - for ln, _ := b.pos2xy(b.pos); ln > 0; ln-- { - if _, err = term.Output.Write(CursorUp); err != nil { - return outputError(err.Error()) - } - } - - if _, err = fmt.Fprintf(term.Output, "\r\033[%dC", b.promptLen); err != nil { - return outputError(err.Error()) - } - b.pos = b.promptLen - return -} - -// end moves the cursor at the end. -// Returns the number of lines that fill in the data. -func (b *buffer) end() (lines int, err error) { - if b.pos == b.size { - return - } - - lastLine, lastColumn := b.pos2xy(b.size) - - for ln, _ := b.pos2xy(b.pos); ln < lastLine; ln++ { - if _, err = term.Output.Write(CursorDown); err != nil { - return 0, outputError(err.Error()) - } - } - - if _, err = fmt.Fprintf(term.Output, "\r\033[%dC", lastColumn); err != nil { - return 0, outputError(err.Error()) - } - b.pos = b.size - return lastLine, nil -} - -// backward moves the cursor one character backward. -// Returns a boolean to know if the cursor is at the beginning of the line. -func (b *buffer) backward() (start bool, err error) { - if b.pos == b.promptLen { - return true, nil - } - b.pos-- - - // If position is on the same line. - if _, col := b.pos2xy(b.pos); col != 0 { - if _, err = term.Output.Write(CursorBackward); err != nil { - return false, outputError(err.Error()) - } - } else { - if _, err = term.Output.Write(CursorUp); err != nil { - return false, outputError(err.Error()) - } - if _, err = fmt.Fprintf(term.Output, "\033[%dC", b.columns); err != nil { - return false, outputError(err.Error()) - } - } - return -} - -// forward moves the cursor one character forward. -// Returns a boolean to know if the cursor is at the end of the line. -func (b *buffer) forward() (end bool, err error) { - if b.pos == b.size { - return true, nil - } - b.pos++ - - if _, col := b.pos2xy(b.pos); col != 0 { - if _, err = term.Output.Write(CursorForward); err != nil { - return false, outputError(err.Error()) - } - } else { - if _, err = term.Output.Write(ToNextLine); err != nil { - return false, outputError(err.Error()) - } - } - return -} - -// swap swaps the actual character by the previous one. If it is the end of the -// line then it is swapped the 2nd previous by the previous one. -func (b *buffer) swap() error { - if b.pos == b.promptLen { - return nil - } - - if b.pos < b.size { - aux := b.data[b.pos-1] - b.data[b.pos-1] = b.data[b.pos] - b.data[b.pos] = aux - b.pos++ - // End of line - } else { - aux := b.data[b.pos-2] - b.data[b.pos-2] = b.data[b.pos-1] - b.data[b.pos-1] = aux - } - return b.refresh() -} - -// wordBackward moves the cursor one word backward. -func (b *buffer) wordBackward() (err error) { - for start := false; ; { - start, err = b.backward() - if start == true || err != nil || b.data[b.pos-1] == 32 { - return - } - } -} - -// wordForward moves the cursor one word forward. -func (b *buffer) wordForward() (err error) { - for end := false; ; { - end, err = b.forward() - if end == true || err != nil || b.data[b.pos] == 32 { - return - } - } -} - -// == Delete - -// deleteChar deletes the character in cursor. -func (b *buffer) deleteChar() (err error) { - if b.pos == b.size { - return - } - - copy(b.data[b.pos:], b.data[b.pos+1:b.size]) - b.size-- - - if lastLine, _ := b.pos2xy(b.size); lastLine == 0 { - if _, err = term.Output.Write(DelChar); err != nil { - return outputError(err.Error()) - } - return nil - } - return b.refresh() -} - -// deleteCharPrev deletes the previous character from cursor. -func (b *buffer) deleteCharPrev() (err error) { - if b.pos == b.promptLen { - return - } - - copy(b.data[b.pos-1:], b.data[b.pos:b.size]) - b.pos-- - b.size-- - - if lastLine, _ := b.pos2xy(b.size); lastLine == 0 { - if _, err = term.Output.Write(DelBackspace); err != nil { - return outputError(err.Error()) - } - return nil - } - return b.refresh() -} - -// deleteToRight deletes from current position until to end of line. -func (b *buffer) deleteToRight() (err error) { - if b.pos == b.size { - return - } - - lastLine, _ := b.pos2xy(b.size) - posLine, _ := b.pos2xy(b.pos) - - // To the last line. - for ln := posLine; ln < lastLine; ln++ { - if _, err = term.Output.Write(CursorDown); err != nil { - return outputError(err.Error()) - } - } - // Delete all lines until the cursor position. - for ln := lastLine; ln > posLine; ln-- { - if _, err = term.Output.Write(DelLine_cursorUp); err != nil { - return outputError(err.Error()) - } - } - - if _, err = term.Output.Write(DelToRight); err != nil { - return outputError(err.Error()) - } - b.size = b.pos - return nil -} - -// deleteLine deletes full line. -func (b *buffer) deleteLine() error { - lines, err := b.end() - if err != nil { - return err - } - - for lines > 0 { - if _, err = term.Output.Write(DelLine_cursorUp); err != nil { - return outputError(err.Error()) - } - lines-- - } - return nil -} - -// == Utility - -// grow grows buffer to guarantee space for n more byte. -func (b *buffer) grow(n int) { - for n > len(b.data) { - b.data = b.data[:len(b.data)+BufferLen] - } -} - -// pos2xy returns the coordinates of a position for a line of size given in -// columns. -func (b *buffer) pos2xy(pos int) (line, column int) { - if pos < b.columns { - return 0, pos - } - - line = pos / b.columns - column = pos - (line * b.columns) //- 1 - return -} diff --git a/vendor/github.com/kless/term/readline/doc.go b/vendor/github.com/kless/term/readline/doc.go deleted file mode 100644 index e6332611..00000000 --- a/vendor/github.com/kless/term/readline/doc.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2010 Jonas mg -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -/* -Package readline provides simple functions for both line and screen editing. - -Features: - - Unicode support - History - Multi-line editing - -List of key sequences enabled (just like in GNU Readline): - - Backspace / Ctrl+h - - Delete - Home / Ctrl+a - End / Ctrl+e - - Left arrow / Ctrl+b - Right arrow / Ctrl+f - Up arrow / Ctrl+p - Down arrow / Ctrl+n - Ctrl+left arrow - Ctrl+right arrow - - Ctrl+t : swap actual character by the previous one - Ctrl+k : delete from current to end of line - Ctrl+u : delete the whole line - Ctrl+l : clear screen - - Ctrl+c - Ctrl+d : exit - -Note that There are several default values: - -+ For the buffer: BufferCap, BufferLen. - -+ For the history file: HistoryCap, HistoryPerm. - -Important: the TTY is set in "raw mode" so there is to use CR+LF ("\r\n") for -writing a new line. - -Note: the values for the input and output are got from the package base "term". -*/ -package readline diff --git a/vendor/github.com/kless/term/readline/error.go b/vendor/github.com/kless/term/readline/error.go deleted file mode 100644 index eb503781..00000000 --- a/vendor/github.com/kless/term/readline/error.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2010 Jonas mg -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -package readline - -import "errors" - -var ErrCtrlD = errors.New("Interrumpted (Ctrl+d)") - -// An inputError represents a failure on input. -type inputError string - -func (e inputError) Error() string { - return "could not read from input: " + string(e) -} - -// An outputError represents a failure in output. -type outputError string - -func (e outputError) Error() string { - return "could not write to output: " + string(e) -} diff --git a/vendor/github.com/kless/term/readline/history.go b/vendor/github.com/kless/term/readline/history.go deleted file mode 100644 index 5dfc7833..00000000 --- a/vendor/github.com/kless/term/readline/history.go +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright 2010 Jonas mg -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -package readline - -import ( - "bufio" - "container/list" - "errors" - "io" - "log" - "os" - "strconv" - "strings" -) - -// Values by default -var ( - HistoryCap = 500 // Capacity - HistoryPerm os.FileMode = 0600 // History file permission -) - -var ( - ErrEmptyHist = errors.New("history: empty") - ErrNilElement = errors.New("history: no more elements") -) - -// == Type - -type history struct { - Cap int - filename string - file *os.File - mark *list.Element // Pointer to the last element added. - li *list.List -} - -// _baseHistory is the base to create an history file. -func _baseHistory(fname string, size int) (*history, error) { - file, err := os.OpenFile(fname, os.O_CREATE|os.O_RDWR, HistoryPerm) - if err != nil { - return nil, err - } - - h := new(history) - h.Cap = size - h.filename = fname - h.file = file - h.li = list.New() - - return h, nil -} - -// NewHistory creates a new history using the maximum length by default. -func NewHistory(filename string) (*history, error) { - return _baseHistory(filename, HistoryCap) -} - -// NewHistoryOfSize creates a new history whose buffer has the specified size, -// which must be greater than zero. -func NewHistoryOfSize(filename string, size int) (*history, error) { - if size <= 0 { - return nil, errors.New("wrong history size: " + strconv.Itoa(size)) - } - - return _baseHistory(filename, size) -} - -// == Access to file - -// Load loads the history from the file. -func (h *history) Load() { - in := bufio.NewReader(h.file) - - for { - line, err := in.ReadString('\n') - if err == io.EOF { - break - } - - h.li.PushBack(strings.TrimRight(line, "\n")) - } - - h.mark = h.li.Back() // Point to an element. -} - -// Save saves all lines to the text file, excep when: -// + it starts with some space -// + it is an empty line -func (h *history) Save() (err error) { - if _, err = h.file.Seek(0, 0); err != nil { - return - } - - out := bufio.NewWriter(h.file) - element := h.li.Front() // Get the first element. - - for i := 0; i < h.li.Len(); i++ { - line := element.Value.(string) - - if strings.HasPrefix(line, " ") { - goto _next - } - if line = strings.TrimSpace(line); line == "" { - goto _next - } - if _, err = out.WriteString(line + "\n"); err != nil { - log.Println("history.Save:", err) - break - } - - _next: - if element = element.Next(); element == nil { - continue - } - } - - if err = out.Flush(); err != nil { - log.Println("history.Save:", err) - } - - h.close() - return -} - -// close Close the file descriptor. -func (h *history) close() { - h.file.Close() -} - -// openFile opens again the file. -/*func (h *history) openFile() { - file, err := os.Open(fname, os.O_CREATE|os.O_RDWR, HistoryPerm) - if err != nil { - log.Println("history.openFile:", err) - return - } - - h.file = file -}*/ - -// Add adds a new line to the buffer. -func (h *history) Add(line string) { - if h.li.Len() <= h.Cap { - h.mark = h.li.PushBack(line) - } else { - // TODO: overwrite lines - } -} - -// _baseNextPrev is the base to move between lines. -func (h *history) _baseNextPrev(c byte) (line []rune, err error) { - if h.li.Len() <= 0 { - return line, ErrEmptyHist - } - - new := new(list.Element) - if c == 'p' { - new = h.mark.Prev() - } else if c == 'n' { - new = h.mark.Next() - } else { - panic("history._baseNextPrev: wrong character choice") - } - - if new != nil { - h.mark = new - } else { - return nil, ErrNilElement - } - - return []rune(new.Value.(string)), nil -} - -// Next returns the next line. -func (h *history) Next() (line []rune, err error) { - return h._baseNextPrev('n') -} - -// Prev returns the previous line. -func (h *history) Prev() (line []rune, err error) { - return h._baseNextPrev('p') -} - -// == Utility - -// hasHistory checks whether has an history file. -func hasHistory(h *history) bool { - if h == nil { - return false - } - return true -} diff --git a/vendor/github.com/kless/term/readline/history_test.go b/vendor/github.com/kless/term/readline/history_test.go deleted file mode 100644 index 21129d3e..00000000 --- a/vendor/github.com/kless/term/readline/history_test.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2010 Jonas mg -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// +build !lookup - -package readline - -import ( - "os" - "path" - "strings" - "testing" -) - -var ( - historyFile = path.Join(os.TempDir(), "test_history") - historyLen int -) - -func TestHistSave(t *testing.T) { - hist, err := NewHistoryOfSize(historyFile, 10) - if err != nil { - t.Error("could not create history", err) - } - - if hist.li.Len() > hist.Cap { - t.Error("bad capacity size") - } - - hist.Add("1 line with trailing spaces ") - hist.Add("2 line without trailing spaces") - hist.Add("3 line without trailing spaces") - hist.Add("4 with trailing tabulator\t") - hist.Add("5 with trailing new line\n") - hist.Add(" ") // Not saved to file - hist.Add(" leading space") // Idem - hist.Add("") // Idem - hist.Add("9 line without trailing spaces") - hist.Add("10 line number 6") - hist.Save() - - historyLen = hist.li.Len() - 3 // 3 lines should not be saved -} - -func TestHistLoad(t *testing.T) { - hist, err := NewHistoryOfSize(historyFile, 10) - if err != nil { - t.Error("could not load history", err) - } - - hist.Load() - e := hist.li.Front() - - for i := 0; i < hist.li.Len(); i++ { - line := e.Value.(string) - - if strings.HasSuffix(line, "\n") || strings.HasSuffix(line, "\t") || - strings.HasSuffix(line, " ") { - t.Error("line saved with any trailing Unicode space") - } - } - - if hist.li.Len() != historyLen { - t.Error("length doesn't match with values saved") - } - - os.Remove(historyFile) -} diff --git a/vendor/github.com/kless/term/readline/read.go b/vendor/github.com/kless/term/readline/read.go deleted file mode 100644 index 9dd9cf4c..00000000 --- a/vendor/github.com/kless/term/readline/read.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2010 Jonas mg -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -package readline - -import "github.com/kless/term" - -// Default values for prompts. -const ( - PS1 = "$ " - PS2 = "> " -) - -// keyAction represents the action to run for a key or sequence of keys pressed. -type keyAction int - -const ( - _ keyAction = iota - _LEFT - _RIGHT - _UP - _DOWN - - _HOME - _END -) - -// To detect if has been pressed CTRL-C -var ChanCtrlC = make(chan byte) - -// To detect if has been pressed CTRL-D -var ChanCtrlD = make(chan byte) - -// A Line represents a line in the term. -type Line struct { - ter *term.Terminal - buf *buffer // Text buffer - hist *history // History file - - ps1 string // Primary prompt - ps2 string // Command continuations - lenPS1 int // Size of primary prompt - - useHistory bool -} - -// NewDefaultLine returns a line type using the prompt by default, and setting -// the terminal to raw mode. -// If the history is nil then it is not used. -func NewDefaultLine(hist *history) (*Line, error) { - ter, err := term.New() - if err != nil { - return nil, err - } - if err = ter.RawMode(); err != nil { - return nil, err - } - - _, col, err := ter.GetSize() - if err != nil { - return nil, err - } - - buf := newBuffer(len(PS1), col) - buf.insertRunes([]rune(PS1)) - - return &Line{ - ter: ter, - buf: buf, - hist: hist, - - ps1: PS1, - ps2: PS2, - lenPS1: len(PS1), - - useHistory: hasHistory(hist), - }, nil -} - -// Restore restores the terminal settings, so it is disabled the raw mode. -func (ln *Line) Restore() error { - return ln.ter.Restore() -} diff --git a/vendor/github.com/kless/term/readline/read_unix.go b/vendor/github.com/kless/term/readline/read_unix.go deleted file mode 100644 index 9b99e8a1..00000000 --- a/vendor/github.com/kless/term/readline/read_unix.go +++ /dev/null @@ -1,345 +0,0 @@ -// Copyright 2010 Jonas mg -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// +build !plan9,!windows - -package readline - -import ( - "bufio" - "fmt" - "strings" - - "github.com/kless/term" - "github.com/kless/term/sys" -) - -func init() { - if !term.SupportANSI() { - panic("Your terminal does not support ANSI") - } -} - -// NewLine returns a line using both prompts ps1 and ps2, and setting the given -// terminal to raw mode, if were necessary. -// lenAnsi is the length of ANSI codes that the prompt ps1 could have. -// If the history is nil then it is not used. -func NewLine(ter *term.Terminal, ps1, ps2 string, lenAnsi int, hist *history) (*Line, error) { - if ter.Mode()&term.RawMode == 0 { // the raw mode is not set - if err := ter.RawMode(); err != nil { - return nil, err - } - } - - lenPS1 := len(ps1) - lenAnsi - _, col, err := ter.GetSize() - if err != nil { - return nil, err - } - - buf := newBuffer(lenPS1, col) - buf.insertRunes([]rune(ps1)) - - return &Line{ - ter: ter, - buf: buf, - hist: hist, - - ps1: ps1, - ps2: ps2, - lenPS1: lenPS1, - - useHistory: hasHistory(hist), - }, nil -} - -// Prompt prints the primary prompt. -func (ln *Line) Prompt() (err error) { - if _, err = term.Output.Write(DelLine_CR); err != nil { - return outputError(err.Error()) - } - if _, err = fmt.Fprint(term.Output, ln.ps1); err != nil { - return outputError(err.Error()) - } - - ln.buf.pos, ln.buf.size = ln.lenPS1, ln.lenPS1 - return -} - -// Read reads charactes from input to write them to output, enabling line editing. -// The errors that could return are to indicate if Ctrl+D was pressed, and for -// both input/output errors. -func (ln *Line) Read() (line string, err error) { - var anotherLine []rune // For lines got from history. - var isHistoryUsed bool // If the history has been accessed. - var action keyAction - - in := bufio.NewReader(term.Input) // Read input. - esc := make([]byte, 2) // For escape sequences. - extEsc := make([]byte, 3) // Extended escape sequences. - - // Print the primary prompt. - if err = ln.Prompt(); err != nil { - return "", err - } - - // == Detect change of window size. - winSize := term.DetectWinSize() - - go func() { - for { - select { - case <-winSize.Change: // Wait for. - _, col, err := ln.ter.GetSize() - if err != nil { - ln.buf.columns = col - ln.buf.refresh() - } - } - } - }() - defer winSize.Close() - - for ; ; action = 0 { - char, _, err := in.ReadRune() - if err != nil { - return "", inputError(err.Error()) - } - - _S: - switch char { - default: - if err = ln.buf.insertRune(char); err != nil { - return "", err - } - continue - - case sys.K_RETURN: - line = ln.buf.toString() - - if ln.useHistory { - ln.hist.Add(line) - } - if _, err = term.Output.Write(CRLF); err != nil { - return "", outputError(err.Error()) - } - return strings.TrimSpace(line), nil - - case sys.K_TAB: - // TODO: disabled by now - continue - - case sys.K_BACK, sys.K_CTRL_H: - if err = ln.buf.deleteCharPrev(); err != nil { - return "", err - } - continue - - case sys.K_CTRL_C: - if err = ln.buf.insertRunes(CtrlC); err != nil { - return "", err - } - if _, err = term.Output.Write(CRLF); err != nil { - return "", outputError(err.Error()) - } - - ChanCtrlC <- 1 //TODO: is really necessary? - - if err = ln.Prompt(); err != nil { - return "", err - } - continue - case sys.K_CTRL_D: - if err = ln.buf.insertRunes(CtrlD); err != nil { - return "", err - } - if _, err = term.Output.Write(CRLF); err != nil { - return "", outputError(err.Error()) - } - - ln.Restore() - ChanCtrlD <- 1 - return "", ErrCtrlD - - // Escape sequence - case sys.K_ESCAPE: // Ctrl+[ ("\x1b" in hexadecimal, "033" in octal) - if _, err = in.Read(esc); err != nil { - return "", inputError(err.Error()) - } - - if esc[0] == 79 { // 'O' - switch esc[1] { - case 72: // Home: "\x1b O H" - action = _HOME - break _S - case 70: // End: "\x1b O F" - action = _END - break _S - } - } - - if esc[0] == 91 { // '[' - switch esc[1] { - case 65: // Up: "\x1b [ A" - if !ln.useHistory { - continue - } - action = _UP - break _S - case 66: // Down: "\x1b [ B" - if !ln.useHistory { - continue - } - action = _DOWN - break _S - case 68: // "\x1b [ D" - action = _LEFT - break _S - case 67: // "\x1b [ C" - action = _RIGHT - break _S - } - - // Extended escape. - if esc[1] > 48 && esc[1] < 55 { - if _, err = in.Read(extEsc); err != nil { - return "", inputError(err.Error()) - } - - if extEsc[0] == 126 { // '~' - switch esc[1] { - //case 50: // Insert: "\x1b [ 2 ~" - - case 51: // Delete: "\x1b [ 3 ~" - if err = ln.buf.deleteChar(); err != nil { - return "", err - } - continue - //case 53: // RePag: "\x1b [ 5 ~" - - //case 54: // AvPag: "\x1b [ 6 ~" - - } - } - if esc[1] == 49 && extEsc[0] == 59 && extEsc[1] == 53 { // "1;5" - switch extEsc[2] { - case 68: // Ctrl+left arrow: "\x1b [ 1 ; 5 D" - // move to last word - if err = ln.buf.wordBackward(); err != nil { - return "", err - } - continue - case 67: // Ctrl+right arrow: "\x1b [ 1 ; 5 C" - // move to next word - if err = ln.buf.wordForward(); err != nil { - return "", err - } - continue - } - } - } - } - continue - - case sys.K_CTRL_T: // Swap actual character by the previous one. - if err = ln.buf.swap(); err != nil { - return "", err - } - continue - - case sys.K_CTRL_L: // Clear screen. - if _, err = term.Output.Write(DelScreenToUpper); err != nil { - return "", err - } - if err = ln.Prompt(); err != nil { - return "", err - } - continue - case sys.K_CTRL_U: // Delete the whole line. - if err = ln.buf.deleteLine(); err != nil { - return "", err - } - if err = ln.Prompt(); err != nil { - return "", err - } - continue - case sys.K_CTRL_K: // Delete from current to end of line. - if err = ln.buf.deleteToRight(); err != nil { - return "", err - } - continue - - case sys.K_CTRL_P: // Up - if !ln.useHistory { - continue - } - action = _UP - case sys.K_CTRL_N: // Down - if !ln.useHistory { - continue - } - action = _DOWN - case sys.K_CTRL_B: // Left - action = _LEFT - case sys.K_CTRL_F: // Right - action = _RIGHT - - case sys.K_CTRL_A: // Start of line. - action = _HOME - case sys.K_CTRL_E: // End of line. - action = _END - } - - switch action { - case _UP, _DOWN: // Up and down arrow: history - if action == _UP { - anotherLine, err = ln.hist.Prev() - } else { - anotherLine, err = ln.hist.Next() - } - if err != nil { - continue - } - - // Update the current history entry before to overwrite it with - // the next one. - // TODO: it has to be removed before of to be saved the history - if !isHistoryUsed { - ln.hist.Add(ln.buf.toString()) - } - isHistoryUsed = true - - ln.buf.grow(len(anotherLine)) - ln.buf.size = len(anotherLine) + ln.buf.promptLen - copy(ln.buf.data[ln.lenPS1:], anotherLine) - - if err = ln.buf.refresh(); err != nil { - return "", err - } - continue - case _LEFT: - if _, err = ln.buf.backward(); err != nil { - return "", err - } - continue - case _RIGHT: - if _, err = ln.buf.forward(); err != nil { - return "", err - } - continue - case _HOME: - if err = ln.buf.start(); err != nil { - return "", err - } - continue - case _END: - if _, err = ln.buf.end(); err != nil { - return "", err - } - continue - } - } -} diff --git a/vendor/github.com/kless/term/test/runtest.go b/vendor/github.com/kless/term/test/runtest.go deleted file mode 100644 index 62c9ccb2..00000000 --- a/vendor/github.com/kless/term/test/runtest.go +++ /dev/null @@ -1,347 +0,0 @@ -// Copyright 2010 Jonas mg -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// Package test checks the functions that depend of the standard input, -// which is changed by `go test` to the standard error. -// -// Flags: -// -// -dbg-key=false: debug: print the decimal code at pressing a key -// -dbg-winsize=false: debug: to know how many signals are sent at maximizing a window -// -iact=false: interactive mode -// -t=2: time in seconds to wait to write in automatic mode -package main - -import ( - "bufio" - "flag" - "fmt" - "io" - "log" - "os" - "path/filepath" - "strconv" - "strings" - "time" - - "github.com/kless/term" - "github.com/kless/term/readline" -) - -var ( - IsInteractive = flag.Bool("iact", false, "interactive mode") - Time = flag.Uint("t", 2, "time in seconds to wait to write in automatic mode") - - DebugWinSize = flag.Bool("dbg-winsize", false, "debug: to know how many signals are sent at maximizing a window") - DebugKey = flag.Bool("dbg-key", false, "debug: print the decimal code at pressing a key") - - pr *io.PipeReader - pw *io.PipeWriter -) - -func main() { - flag.Parse() - log.SetFlags(0) - log.SetPrefix("--- FAIL: ") - - if *DebugKey { - Lookup() - return - } - if *DebugWinSize { - win := term.DetectWinSize() - defer win.Close() - fmt.Println("[Resize the window: should print a number every time]") - - for i := 0; i < 7; i++ { - select { - case <-win.Change: - fmt.Printf("%d ", i) - case <-time.After(13 * time.Second): - fmt.Print("\ntimed out\n") - return - } - } - return - } - - if !*IsInteractive { - pr, pw = io.Pipe() - term.Input = pr - } - - TestCharMode() - TestEchoMode() - if *IsInteractive { - TestPassword() - } - TestEditLine() - if *IsInteractive { - TestDetectSize() - } -} - -// TestCharMode tests terminal set to single character mode. -func TestCharMode() { - fmt.Print("\n=== RUN TestCharMode\n") - - ter, _ := term.New() - defer func() { - if err := ter.Restore(); err != nil { - log.Print(err) - } - }() - - if err := ter.CharMode(); err != nil { - log.Print("expected to set character mode:", err) - return - } - - buf := bufio.NewReaderSize(term.Input, 4) - reply := []string{"a", "€", "~"} - - if !*IsInteractive { - go func() { - for _, r := range reply { - time.Sleep(time.Duration(*Time) * time.Second) - fmt.Fprint(pw, r) - } - }() - } - - for i := 1; ; i++ { - fmt.Print(" Press key: ") - rune, _, err := buf.ReadRune() - if err != nil { - log.Print(err) - return - } - fmt.Printf("\n pressed: %q\n", string(rune)) - - if *IsInteractive || i == len(reply) { - break - } - } -} - -func TestEchoMode() { - fmt.Print("\n=== RUN TestEchoMode\n") - - ter, _ := term.New() - defer func() { - if err := ter.Restore(); err != nil { - log.Print(err) - } - }() - - if err := ter.EchoMode(false); err != nil { - log.Print("expected to set echo mode:", err) - return - } - fmt.Print(" + Mode to echo off\n") - buf := bufio.NewReader(term.Input) - - if !*IsInteractive { - go func() { - time.Sleep(time.Duration(*Time) * time.Second) - fmt.Fprint(pw, "Karma\n") - }() - } - fmt.Print(" Write (enter to finish): ") - line, err := buf.ReadString('\n') - if err != nil { - log.Print(err) - return - } - fmt.Printf("\n entered: %q\n", line) - - ter.EchoMode(true) - fmt.Print("\n + Mode to echo on\n") - - if !*IsInteractive { - go func() { - time.Sleep(time.Duration(*Time) * time.Second) - fmt.Fprint(pw, "hotel\n") - }() - } - fmt.Print(" Write (enter to finish): ") - line, _ = buf.ReadString('\n') - if !*IsInteractive { - fmt.Println() - } - fmt.Printf(" entered: %q\n", line) -} - -func TestPassword() { - fmt.Print("\n=== RUN TestPassword\n") - - fmt.Print(" Password (no echo): ") - pass := make([]byte, 8) - - n, err := term.ReadPassword(pass) - if err != nil { - log.Print(err) - return - } - fmt.Printf(" entered: %q\n number: %d\n", pass, n) - - term.PasswordShadowed = true - fmt.Print("\n Password (shadow character): ") - pass = make([]byte, 8) - - n, err = term.ReadPassword(pass) - if err != nil { - log.Print(err) - return - } - fmt.Printf(" entered: %q\n number: %d\n", pass, n) -} - -func TestDetectSize() { - fmt.Print("\n=== RUN TestDetectSize\n") - - ter, _ := term.New() - defer func() { - if err := ter.Restore(); err != nil { - log.Print(err) - } - }() - - row, col, err := ter.GetSize() - if err != nil { - panic(err) - } - - winSize := term.DetectWinSize() - fmt.Println("[Change the size of the terminal]") - - // I want to finish the test. - go func() { - time.Sleep(10 * time.Second) - winSize.Change <- true - }() - - <-winSize.Change - winSize.Close() - - row2, col2, err := ter.GetSize() - if err != nil { - panic(err) - } - if row == row2 && col == col2 { - log.Print("the terminal size got the same value") - return - } -} - -// Package readline - -func TestEditLine() { - fmt.Println("\n=== RUN TestEditLine") - - tempHistory := filepath.Join(os.TempDir(), "test_readline") - hist, err := readline.NewHistory(tempHistory) - if err != nil { - log.Print(err) - return - } - defer func() { - if err = os.Remove(tempHistory); err != nil { - log.Print(err) - } - }() - hist.Load() - - fmt.Printf("Press ^D to exit\n\n") - - ln, err := readline.NewDefaultLine(hist) - if err != nil { - log.Print(err) - return - } - defer func() { - if err = ln.Restore(); err != nil { - log.Print(err) - } - }() - - if !*IsInteractive { - reply := []string{ - "I have heard that the night is all magic", - "and that a goblin invites you to dream", - } - - go func() { - for _, r := range reply { - time.Sleep(time.Duration(*Time) * time.Second) - fmt.Fprintf(pw, "%s\r\n", r) - } - time.Sleep(time.Duration(*Time) * time.Second) - pw.Write([]byte{4}) // Ctrl+D - }() - } - - for { - if _, err = ln.Read(); err != nil { - if err == readline.ErrCtrlD { - hist.Save() - err = nil - } else { - log.Print(err) - return - } - break - } - } -} - -// Lookup prints the decimal code at pressing a key. -func Lookup() { - ter, err := term.New() - if err != nil { - log.Print(err) - return - } - defer func() { - if err = ter.Restore(); err != nil { - log.Print(err) - } - }() - - if err = ter.RawMode(); err != nil { - log.Print(err) - return - } else { - buf := bufio.NewReader(term.Input) - runes := make([]int32, 0) - chars := make([]string, 0) - - fmt.Print("[Press Enter to exit]\r\n") - fmt.Print("> ") - - L: - for { - rune_, _, err := buf.ReadRune() - if err != nil { - log.Print(err) - continue - } - - switch rune_ { - default: - fmt.Print(rune_, " ") - runes = append(runes, rune_) - char := strconv.QuoteRune(rune_) - chars = append(chars, char[1:len(char)-1]) - continue - - case 13: - fmt.Printf("\r\n\r\n%v\r\n\"%s\"\r\n", runes, strings.Join(chars, " ")) - break L - } - } - } -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/apply_raw.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/apply_raw.go deleted file mode 100644 index a0a93a4a..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/apply_raw.go +++ /dev/null @@ -1,333 +0,0 @@ -// +build linux - -package fs - -import ( - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strconv" - "sync" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -var ( - subsystems = map[string]subsystem{ - "devices": &DevicesGroup{}, - "memory": &MemoryGroup{}, - "cpu": &CpuGroup{}, - "cpuset": &CpusetGroup{}, - "cpuacct": &CpuacctGroup{}, - "blkio": &BlkioGroup{}, - "hugetlb": &HugetlbGroup{}, - "net_cls": &NetClsGroup{}, - "net_prio": &NetPrioGroup{}, - "perf_event": &PerfEventGroup{}, - "freezer": &FreezerGroup{}, - } - CgroupProcesses = "cgroup.procs" - HugePageSizes, _ = cgroups.GetHugePageSize() -) - -type subsystem interface { - // Returns the stats, as 'stats', corresponding to the cgroup under 'path'. - GetStats(path string, stats *cgroups.Stats) error - // Removes the cgroup represented by 'data'. - Remove(*data) error - // Creates and joins the cgroup represented by data. - Apply(*data) error - // Set the cgroup represented by cgroup. - Set(path string, cgroup *configs.Cgroup) error -} - -type Manager struct { - mu sync.Mutex - Cgroups *configs.Cgroup - Paths map[string]string -} - -// The absolute path to the root of the cgroup hierarchies. -var cgroupRootLock sync.Mutex -var cgroupRoot string - -// Gets the cgroupRoot. -func getCgroupRoot() (string, error) { - cgroupRootLock.Lock() - defer cgroupRootLock.Unlock() - - if cgroupRoot != "" { - return cgroupRoot, nil - } - - root, err := cgroups.FindCgroupMountpointDir() - if err != nil { - return "", err - } - - if _, err := os.Stat(root); err != nil { - return "", err - } - - cgroupRoot = root - return cgroupRoot, nil -} - -type data struct { - root string - cgroup string - c *configs.Cgroup - pid int -} - -func (m *Manager) Apply(pid int) (err error) { - if m.Cgroups == nil { - return nil - } - - var c = m.Cgroups - - d, err := getCgroupData(m.Cgroups, pid) - if err != nil { - return err - } - - paths := make(map[string]string) - defer func() { - if err != nil { - cgroups.RemovePaths(paths) - } - }() - for name, sys := range subsystems { - if err := sys.Apply(d); err != nil { - return err - } - // TODO: Apply should, ideally, be reentrant or be broken up into a separate - // create and join phase so that the cgroup hierarchy for a container can be - // created then join consists of writing the process pids to cgroup.procs - p, err := d.path(name) - if err != nil { - if cgroups.IsNotFound(err) { - continue - } - return err - } - paths[name] = p - } - m.Paths = paths - - if paths["cpu"] != "" { - if err := CheckCpushares(paths["cpu"], c.CpuShares); err != nil { - return err - } - } - - return nil -} - -func (m *Manager) Destroy() error { - m.mu.Lock() - defer m.mu.Unlock() - if err := cgroups.RemovePaths(m.Paths); err != nil { - return err - } - m.Paths = make(map[string]string) - return nil -} - -func (m *Manager) GetPaths() map[string]string { - m.mu.Lock() - paths := m.Paths - m.mu.Unlock() - return paths -} - -func (m *Manager) GetStats() (*cgroups.Stats, error) { - m.mu.Lock() - defer m.mu.Unlock() - stats := cgroups.NewStats() - for name, path := range m.Paths { - sys, ok := subsystems[name] - if !ok || !cgroups.PathExists(path) { - continue - } - if err := sys.GetStats(path, stats); err != nil { - return nil, err - } - } - - return stats, nil -} - -func (m *Manager) Set(container *configs.Config) error { - for name, path := range m.Paths { - sys, ok := subsystems[name] - if !ok || !cgroups.PathExists(path) { - continue - } - if err := sys.Set(path, container.Cgroups); err != nil { - return err - } - } - - return nil -} - -// Freeze toggles the container's freezer cgroup depending on the state -// provided -func (m *Manager) Freeze(state configs.FreezerState) error { - d, err := getCgroupData(m.Cgroups, 0) - if err != nil { - return err - } - - dir, err := d.path("freezer") - if err != nil { - return err - } - - prevState := m.Cgroups.Freezer - m.Cgroups.Freezer = state - - freezer := subsystems["freezer"] - err = freezer.Set(dir, m.Cgroups) - if err != nil { - m.Cgroups.Freezer = prevState - return err - } - - return nil -} - -func (m *Manager) GetPids() ([]int, error) { - d, err := getCgroupData(m.Cgroups, 0) - if err != nil { - return nil, err - } - - dir, err := d.path("devices") - if err != nil { - return nil, err - } - - return cgroups.GetPids(dir) -} - -func getCgroupData(c *configs.Cgroup, pid int) (*data, error) { - root, err := getCgroupRoot() - if err != nil { - return nil, err - } - - cgroup := c.Name - if c.Parent != "" { - cgroup = filepath.Join(c.Parent, cgroup) - } - - return &data{ - root: root, - cgroup: cgroup, - c: c, - pid: pid, - }, nil -} - -func (raw *data) parent(subsystem, mountpoint, root string) (string, error) { - initPath, err := cgroups.GetThisCgroupDir(subsystem) - if err != nil { - return "", err - } - relDir, err := filepath.Rel(root, initPath) - if err != nil { - return "", err - } - return filepath.Join(mountpoint, relDir), nil -} - -func (raw *data) path(subsystem string) (string, error) { - mnt, root, err := cgroups.FindCgroupMountpointAndRoot(subsystem) - // If we didn't mount the subsystem, there is no point we make the path. - if err != nil { - return "", err - } - - // If the cgroup name/path is absolute do not look relative to the cgroup of the init process. - if filepath.IsAbs(raw.cgroup) { - return filepath.Join(raw.root, filepath.Base(mnt), raw.cgroup), nil - } - - parent, err := raw.parent(subsystem, mnt, root) - if err != nil { - return "", err - } - - return filepath.Join(parent, raw.cgroup), nil -} - -func (raw *data) join(subsystem string) (string, error) { - path, err := raw.path(subsystem) - if err != nil { - return "", err - } - if err := os.MkdirAll(path, 0755); err != nil { - return "", err - } - if err := writeFile(path, CgroupProcesses, strconv.Itoa(raw.pid)); err != nil { - return "", err - } - return path, nil -} - -func writeFile(dir, file, data string) error { - // Normally dir should not be empty, one case is that cgroup subsystem - // is not mounted, we will get empty dir, and we want it fail here. - if dir == "" { - return fmt.Errorf("no such directory for %s.", file) - } - return ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700) -} - -func readFile(dir, file string) (string, error) { - data, err := ioutil.ReadFile(filepath.Join(dir, file)) - return string(data), err -} - -func removePath(p string, err error) error { - if err != nil { - return err - } - if p != "" { - return os.RemoveAll(p) - } - return nil -} - -func CheckCpushares(path string, c int64) error { - var cpuShares int64 - - if c == 0 { - return nil - } - - fd, err := os.Open(filepath.Join(path, "cpu.shares")) - if err != nil { - return err - } - defer fd.Close() - - _, err = fmt.Fscanf(fd, "%d", &cpuShares) - if err != nil && err != io.EOF { - return err - } - - if c > cpuShares { - return fmt.Errorf("The maximum allowed cpu-shares is %d", cpuShares) - } else if c < cpuShares { - return fmt.Errorf("The minimum allowed cpu-shares is %d", cpuShares) - } - - return nil -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/blkio.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/blkio.go deleted file mode 100644 index db886bcf..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/blkio.go +++ /dev/null @@ -1,238 +0,0 @@ -// +build linux - -package fs - -import ( - "bufio" - "fmt" - "os" - "path/filepath" - "strconv" - "strings" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -type BlkioGroup struct { -} - -func (s *BlkioGroup) Apply(d *data) error { - dir, err := d.join("blkio") - if err != nil && !cgroups.IsNotFound(err) { - return err - } - - if err := s.Set(dir, d.c); err != nil { - return err - } - - return nil -} - -func (s *BlkioGroup) Set(path string, cgroup *configs.Cgroup) error { - if cgroup.BlkioWeight != 0 { - if err := writeFile(path, "blkio.weight", strconv.FormatUint(uint64(cgroup.BlkioWeight), 10)); err != nil { - return err - } - } - - if cgroup.BlkioLeafWeight != 0 { - if err := writeFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(cgroup.BlkioLeafWeight), 10)); err != nil { - return err - } - } - for _, wd := range cgroup.BlkioWeightDevice { - if err := writeFile(path, "blkio.weight_device", wd.WeightString()); err != nil { - return err - } - if err := writeFile(path, "blkio.leaf_weight_device", wd.LeafWeightString()); err != nil { - return err - } - } - for _, td := range cgroup.BlkioThrottleReadBpsDevice { - if err := writeFile(path, "blkio.throttle.read_bps_device", td.String()); err != nil { - return err - } - } - for _, td := range cgroup.BlkioThrottleWriteBpsDevice { - if err := writeFile(path, "blkio.throttle.write_bps_device", td.String()); err != nil { - return err - } - } - for _, td := range cgroup.BlkioThrottleReadIOPSDevice { - if err := writeFile(path, "blkio.throttle.read_iops_device", td.String()); err != nil { - return err - } - } - for _, td := range cgroup.BlkioThrottleWriteIOPSDevice { - if err := writeFile(path, "blkio.throttle.write_iops_device", td.String()); err != nil { - return err - } - } - - return nil -} - -func (s *BlkioGroup) Remove(d *data) error { - return removePath(d.path("blkio")) -} - -/* -examples: - - blkio.sectors - 8:0 6792 - - blkio.io_service_bytes - 8:0 Read 1282048 - 8:0 Write 2195456 - 8:0 Sync 2195456 - 8:0 Async 1282048 - 8:0 Total 3477504 - Total 3477504 - - blkio.io_serviced - 8:0 Read 124 - 8:0 Write 104 - 8:0 Sync 104 - 8:0 Async 124 - 8:0 Total 228 - Total 228 - - blkio.io_queued - 8:0 Read 0 - 8:0 Write 0 - 8:0 Sync 0 - 8:0 Async 0 - 8:0 Total 0 - Total 0 -*/ - -func splitBlkioStatLine(r rune) bool { - return r == ' ' || r == ':' -} - -func getBlkioStat(path string) ([]cgroups.BlkioStatEntry, error) { - var blkioStats []cgroups.BlkioStatEntry - f, err := os.Open(path) - if err != nil { - if os.IsNotExist(err) { - return blkioStats, nil - } - return nil, err - } - defer f.Close() - - sc := bufio.NewScanner(f) - for sc.Scan() { - // format: dev type amount - fields := strings.FieldsFunc(sc.Text(), splitBlkioStatLine) - if len(fields) < 3 { - if len(fields) == 2 && fields[0] == "Total" { - // skip total line - continue - } else { - return nil, fmt.Errorf("Invalid line found while parsing %s: %s", path, sc.Text()) - } - } - - v, err := strconv.ParseUint(fields[0], 10, 64) - if err != nil { - return nil, err - } - major := v - - v, err = strconv.ParseUint(fields[1], 10, 64) - if err != nil { - return nil, err - } - minor := v - - op := "" - valueField := 2 - if len(fields) == 4 { - op = fields[2] - valueField = 3 - } - v, err = strconv.ParseUint(fields[valueField], 10, 64) - if err != nil { - return nil, err - } - blkioStats = append(blkioStats, cgroups.BlkioStatEntry{Major: major, Minor: minor, Op: op, Value: v}) - } - - return blkioStats, nil -} - -func (s *BlkioGroup) GetStats(path string, stats *cgroups.Stats) error { - // Try to read CFQ stats available on all CFQ enabled kernels first - if blkioStats, err := getBlkioStat(filepath.Join(path, "blkio.io_serviced_recursive")); err == nil && blkioStats != nil { - return getCFQStats(path, stats) - } - return getStats(path, stats) // Use generic stats as fallback -} - -func getCFQStats(path string, stats *cgroups.Stats) error { - var blkioStats []cgroups.BlkioStatEntry - var err error - - if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.sectors_recursive")); err != nil { - return err - } - stats.BlkioStats.SectorsRecursive = blkioStats - - if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.io_service_bytes_recursive")); err != nil { - return err - } - stats.BlkioStats.IoServiceBytesRecursive = blkioStats - - if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.io_serviced_recursive")); err != nil { - return err - } - stats.BlkioStats.IoServicedRecursive = blkioStats - - if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.io_queued_recursive")); err != nil { - return err - } - stats.BlkioStats.IoQueuedRecursive = blkioStats - - if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.io_service_time_recursive")); err != nil { - return err - } - stats.BlkioStats.IoServiceTimeRecursive = blkioStats - - if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.io_wait_time_recursive")); err != nil { - return err - } - stats.BlkioStats.IoWaitTimeRecursive = blkioStats - - if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.io_merged_recursive")); err != nil { - return err - } - stats.BlkioStats.IoMergedRecursive = blkioStats - - if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.time_recursive")); err != nil { - return err - } - stats.BlkioStats.IoTimeRecursive = blkioStats - - return nil -} - -func getStats(path string, stats *cgroups.Stats) error { - var blkioStats []cgroups.BlkioStatEntry - var err error - - if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.throttle.io_service_bytes")); err != nil { - return err - } - stats.BlkioStats.IoServiceBytesRecursive = blkioStats - - if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.throttle.io_serviced")); err != nil { - return err - } - stats.BlkioStats.IoServicedRecursive = blkioStats - - return nil -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/blkio_test.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/blkio_test.go deleted file mode 100644 index ba312f3a..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/blkio_test.go +++ /dev/null @@ -1,636 +0,0 @@ -// +build linux - -package fs - -import ( - "strconv" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -const ( - sectorsRecursiveContents = `8:0 1024` - serviceBytesRecursiveContents = `8:0 Read 100 -8:0 Write 200 -8:0 Sync 300 -8:0 Async 500 -8:0 Total 500 -Total 500` - servicedRecursiveContents = `8:0 Read 10 -8:0 Write 40 -8:0 Sync 20 -8:0 Async 30 -8:0 Total 50 -Total 50` - queuedRecursiveContents = `8:0 Read 1 -8:0 Write 4 -8:0 Sync 2 -8:0 Async 3 -8:0 Total 5 -Total 5` - serviceTimeRecursiveContents = `8:0 Read 173959 -8:0 Write 0 -8:0 Sync 0 -8:0 Async 173959 -8:0 Total 17395 -Total 17395` - waitTimeRecursiveContents = `8:0 Read 15571 -8:0 Write 0 -8:0 Sync 0 -8:0 Async 15571 -8:0 Total 15571` - mergedRecursiveContents = `8:0 Read 5 -8:0 Write 10 -8:0 Sync 0 -8:0 Async 0 -8:0 Total 15 -Total 15` - timeRecursiveContents = `8:0 8` - throttleServiceBytes = `8:0 Read 11030528 -8:0 Write 23 -8:0 Sync 42 -8:0 Async 11030528 -8:0 Total 11030528 -252:0 Read 11030528 -252:0 Write 23 -252:0 Sync 42 -252:0 Async 11030528 -252:0 Total 11030528 -Total 22061056` - throttleServiced = `8:0 Read 164 -8:0 Write 23 -8:0 Sync 42 -8:0 Async 164 -8:0 Total 164 -252:0 Read 164 -252:0 Write 23 -252:0 Sync 42 -252:0 Async 164 -252:0 Total 164 -Total 328` -) - -func appendBlkioStatEntry(blkioStatEntries *[]cgroups.BlkioStatEntry, major, minor, value uint64, op string) { - *blkioStatEntries = append(*blkioStatEntries, cgroups.BlkioStatEntry{Major: major, Minor: minor, Value: value, Op: op}) -} - -func TestBlkioSetWeight(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - - const ( - weightBefore = 100 - weightAfter = 200 - ) - - helper.writeFileContents(map[string]string{ - "blkio.weight": strconv.Itoa(weightBefore), - }) - - helper.CgroupData.c.BlkioWeight = weightAfter - blkio := &BlkioGroup{} - if err := blkio.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamUint(helper.CgroupPath, "blkio.weight") - if err != nil { - t.Fatalf("Failed to parse blkio.weight - %s", err) - } - - if value != weightAfter { - t.Fatal("Got the wrong value, set blkio.weight failed.") - } -} - -func TestBlkioSetWeightDevice(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - - const ( - weightDeviceBefore = "8:0 400" - ) - - wd := configs.NewWeightDevice(8, 0, 500, 0) - weightDeviceAfter := wd.WeightString() - - helper.writeFileContents(map[string]string{ - "blkio.weight_device": weightDeviceBefore, - }) - - helper.CgroupData.c.BlkioWeightDevice = []*configs.WeightDevice{wd} - blkio := &BlkioGroup{} - if err := blkio.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "blkio.weight_device") - if err != nil { - t.Fatalf("Failed to parse blkio.weight_device - %s", err) - } - - if value != weightDeviceAfter { - t.Fatal("Got the wrong value, set blkio.weight_device failed.") - } -} - -// regression #274 -func TestBlkioSetMultipleWeightDevice(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - - const ( - weightDeviceBefore = "8:0 400" - ) - - wd1 := configs.NewWeightDevice(8, 0, 500, 0) - wd2 := configs.NewWeightDevice(8, 16, 500, 0) - // we cannot actually set and check both because normal ioutil.WriteFile - // when writing to cgroup file will overwrite the whole file content instead - // of updating it as the kernel is doing. Just check the second device - // is present will suffice for the test to ensure multiple writes are done. - weightDeviceAfter := wd2.WeightString() - - helper.writeFileContents(map[string]string{ - "blkio.weight_device": weightDeviceBefore, - }) - - helper.CgroupData.c.BlkioWeightDevice = []*configs.WeightDevice{wd1, wd2} - blkio := &BlkioGroup{} - if err := blkio.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "blkio.weight_device") - if err != nil { - t.Fatalf("Failed to parse blkio.weight_device - %s", err) - } - - if value != weightDeviceAfter { - t.Fatal("Got the wrong value, set blkio.weight_device failed.") - } -} - -func TestBlkioStats(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatal(err) - } - - // Verify expected stats. - expectedStats := cgroups.BlkioStats{} - appendBlkioStatEntry(&expectedStats.SectorsRecursive, 8, 0, 1024, "") - - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 100, "Read") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 200, "Write") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 300, "Sync") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 500, "Async") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 500, "Total") - - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 10, "Read") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 40, "Write") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 20, "Sync") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 30, "Async") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 50, "Total") - - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 1, "Read") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 4, "Write") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 2, "Sync") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 3, "Async") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 5, "Total") - - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 173959, "Read") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 0, "Write") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 0, "Sync") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 173959, "Async") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 17395, "Total") - - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 15571, "Read") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 0, "Write") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 0, "Sync") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 15571, "Async") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 15571, "Total") - - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 5, "Read") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 10, "Write") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 0, "Sync") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 0, "Async") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 15, "Total") - - appendBlkioStatEntry(&expectedStats.IoTimeRecursive, 8, 0, 8, "") - - expectBlkioStatsEquals(t, expectedStats, actualStats.BlkioStats) -} - -func TestBlkioStatsNoSectorsFile(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatalf("Failed unexpectedly: %s", err) - } -} - -func TestBlkioStatsNoServiceBytesFile(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatalf("Failed unexpectedly: %s", err) - } -} - -func TestBlkioStatsNoServicedFile(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatalf("Failed unexpectedly: %s", err) - } -} - -func TestBlkioStatsNoQueuedFile(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatalf("Failed unexpectedly: %s", err) - } -} - -func TestBlkioStatsNoServiceTimeFile(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatalf("Failed unexpectedly: %s", err) - } -} - -func TestBlkioStatsNoWaitTimeFile(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatalf("Failed unexpectedly: %s", err) - } -} - -func TestBlkioStatsNoMergedFile(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatalf("Failed unexpectedly: %s", err) - } -} - -func TestBlkioStatsNoTimeFile(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatalf("Failed unexpectedly: %s", err) - } -} - -func TestBlkioStatsUnexpectedNumberOfFields(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": "8:0 Read 100 100", - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected to fail, but did not") - } -} - -func TestBlkioStatsUnexpectedFieldType(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": "8:0 Read Write", - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected to fail, but did not") - } -} - -func TestNonCFQBlkioStats(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": "", - "blkio.io_serviced_recursive": "", - "blkio.io_queued_recursive": "", - "blkio.sectors_recursive": "", - "blkio.io_service_time_recursive": "", - "blkio.io_wait_time_recursive": "", - "blkio.io_merged_recursive": "", - "blkio.time_recursive": "", - "blkio.throttle.io_service_bytes": throttleServiceBytes, - "blkio.throttle.io_serviced": throttleServiced, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatal(err) - } - - // Verify expected stats. - expectedStats := cgroups.BlkioStats{} - - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 11030528, "Read") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 23, "Write") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 42, "Sync") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 11030528, "Async") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 11030528, "Total") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 11030528, "Read") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 23, "Write") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 42, "Sync") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 11030528, "Async") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 11030528, "Total") - - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 164, "Read") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 23, "Write") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 42, "Sync") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 164, "Async") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 164, "Total") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 164, "Read") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 23, "Write") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 42, "Sync") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 164, "Async") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 164, "Total") - - expectBlkioStatsEquals(t, expectedStats, actualStats.BlkioStats) -} - -func TestBlkioSetThrottleReadBpsDevice(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - - const ( - throttleBefore = `8:0 1024` - ) - - td := configs.NewThrottleDevice(8, 0, 2048) - throttleAfter := td.String() - - helper.writeFileContents(map[string]string{ - "blkio.throttle.read_bps_device": throttleBefore, - }) - - helper.CgroupData.c.BlkioThrottleReadBpsDevice = []*configs.ThrottleDevice{td} - blkio := &BlkioGroup{} - if err := blkio.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "blkio.throttle.read_bps_device") - if err != nil { - t.Fatalf("Failed to parse blkio.throttle.read_bps_device - %s", err) - } - - if value != throttleAfter { - t.Fatal("Got the wrong value, set blkio.throttle.read_bps_device failed.") - } -} -func TestBlkioSetThrottleWriteBpsDevice(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - - const ( - throttleBefore = `8:0 1024` - ) - - td := configs.NewThrottleDevice(8, 0, 2048) - throttleAfter := td.String() - - helper.writeFileContents(map[string]string{ - "blkio.throttle.write_bps_device": throttleBefore, - }) - - helper.CgroupData.c.BlkioThrottleWriteBpsDevice = []*configs.ThrottleDevice{td} - blkio := &BlkioGroup{} - if err := blkio.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "blkio.throttle.write_bps_device") - if err != nil { - t.Fatalf("Failed to parse blkio.throttle.write_bps_device - %s", err) - } - - if value != throttleAfter { - t.Fatal("Got the wrong value, set blkio.throttle.write_bps_device failed.") - } -} -func TestBlkioSetThrottleReadIOpsDevice(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - - const ( - throttleBefore = `8:0 1024` - ) - - td := configs.NewThrottleDevice(8, 0, 2048) - throttleAfter := td.String() - - helper.writeFileContents(map[string]string{ - "blkio.throttle.read_iops_device": throttleBefore, - }) - - helper.CgroupData.c.BlkioThrottleReadIOPSDevice = []*configs.ThrottleDevice{td} - blkio := &BlkioGroup{} - if err := blkio.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "blkio.throttle.read_iops_device") - if err != nil { - t.Fatalf("Failed to parse blkio.throttle.read_iops_device - %s", err) - } - - if value != throttleAfter { - t.Fatal("Got the wrong value, set blkio.throttle.read_iops_device failed.") - } -} -func TestBlkioSetThrottleWriteIOpsDevice(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - - const ( - throttleBefore = `8:0 1024` - ) - - td := configs.NewThrottleDevice(8, 0, 2048) - throttleAfter := td.String() - - helper.writeFileContents(map[string]string{ - "blkio.throttle.write_iops_device": throttleBefore, - }) - - helper.CgroupData.c.BlkioThrottleWriteIOPSDevice = []*configs.ThrottleDevice{td} - blkio := &BlkioGroup{} - if err := blkio.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "blkio.throttle.write_iops_device") - if err != nil { - t.Fatalf("Failed to parse blkio.throttle.write_iops_device - %s", err) - } - - if value != throttleAfter { - t.Fatal("Got the wrong value, set blkio.throttle.write_iops_device failed.") - } -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go deleted file mode 100644 index 5afd5b8d..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go +++ /dev/null @@ -1,95 +0,0 @@ -// +build linux - -package fs - -import ( - "bufio" - "os" - "path/filepath" - "strconv" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -type CpuGroup struct { -} - -func (s *CpuGroup) Apply(d *data) error { - // We always want to join the cpu group, to allow fair cpu scheduling - // on a container basis - dir, err := d.join("cpu") - if err != nil && !cgroups.IsNotFound(err) { - return err - } - - if err := s.Set(dir, d.c); err != nil { - return err - } - - return nil -} - -func (s *CpuGroup) Set(path string, cgroup *configs.Cgroup) error { - if cgroup.CpuShares != 0 { - if err := writeFile(path, "cpu.shares", strconv.FormatInt(cgroup.CpuShares, 10)); err != nil { - return err - } - } - if cgroup.CpuPeriod != 0 { - if err := writeFile(path, "cpu.cfs_period_us", strconv.FormatInt(cgroup.CpuPeriod, 10)); err != nil { - return err - } - } - if cgroup.CpuQuota != 0 { - if err := writeFile(path, "cpu.cfs_quota_us", strconv.FormatInt(cgroup.CpuQuota, 10)); err != nil { - return err - } - } - if cgroup.CpuRtPeriod != 0 { - if err := writeFile(path, "cpu.rt_period_us", strconv.FormatInt(cgroup.CpuRtPeriod, 10)); err != nil { - return err - } - } - if cgroup.CpuRtRuntime != 0 { - if err := writeFile(path, "cpu.rt_runtime_us", strconv.FormatInt(cgroup.CpuRtRuntime, 10)); err != nil { - return err - } - } - - return nil -} - -func (s *CpuGroup) Remove(d *data) error { - return removePath(d.path("cpu")) -} - -func (s *CpuGroup) GetStats(path string, stats *cgroups.Stats) error { - f, err := os.Open(filepath.Join(path, "cpu.stat")) - if err != nil { - if os.IsNotExist(err) { - return nil - } - return err - } - defer f.Close() - - sc := bufio.NewScanner(f) - for sc.Scan() { - t, v, err := getCgroupParamKeyValue(sc.Text()) - if err != nil { - return err - } - switch t { - case "nr_periods": - stats.CpuStats.ThrottlingData.Periods = v - - case "nr_throttled": - stats.CpuStats.ThrottlingData.ThrottledPeriods = v - - case "throttled_time": - stats.CpuStats.ThrottlingData.ThrottledTime = v - } - } - return nil -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu_test.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu_test.go deleted file mode 100644 index f3c1782e..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu_test.go +++ /dev/null @@ -1,163 +0,0 @@ -// +build linux - -package fs - -import ( - "fmt" - "strconv" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -func TestCpuSetShares(t *testing.T) { - helper := NewCgroupTestUtil("cpu", t) - defer helper.cleanup() - - const ( - sharesBefore = 1024 - sharesAfter = 512 - ) - - helper.writeFileContents(map[string]string{ - "cpu.shares": strconv.Itoa(sharesBefore), - }) - - helper.CgroupData.c.CpuShares = sharesAfter - cpu := &CpuGroup{} - if err := cpu.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamUint(helper.CgroupPath, "cpu.shares") - if err != nil { - t.Fatalf("Failed to parse cpu.shares - %s", err) - } - - if value != sharesAfter { - t.Fatal("Got the wrong value, set cpu.shares failed.") - } -} - -func TestCpuSetBandWidth(t *testing.T) { - helper := NewCgroupTestUtil("cpu", t) - defer helper.cleanup() - - const ( - quotaBefore = 8000 - quotaAfter = 5000 - periodBefore = 10000 - periodAfter = 7000 - rtRuntimeBefore = 8000 - rtRuntimeAfter = 5000 - rtPeriodBefore = 10000 - rtPeriodAfter = 7000 - ) - - helper.writeFileContents(map[string]string{ - "cpu.cfs_quota_us": strconv.Itoa(quotaBefore), - "cpu.cfs_period_us": strconv.Itoa(periodBefore), - "cpu.rt_runtime_us": strconv.Itoa(rtRuntimeBefore), - "cpu.rt_period_us": strconv.Itoa(rtPeriodBefore), - }) - - helper.CgroupData.c.CpuQuota = quotaAfter - helper.CgroupData.c.CpuPeriod = periodAfter - helper.CgroupData.c.CpuRtRuntime = rtRuntimeAfter - helper.CgroupData.c.CpuRtPeriod = rtPeriodAfter - cpu := &CpuGroup{} - if err := cpu.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - quota, err := getCgroupParamUint(helper.CgroupPath, "cpu.cfs_quota_us") - if err != nil { - t.Fatalf("Failed to parse cpu.cfs_quota_us - %s", err) - } - if quota != quotaAfter { - t.Fatal("Got the wrong value, set cpu.cfs_quota_us failed.") - } - - period, err := getCgroupParamUint(helper.CgroupPath, "cpu.cfs_period_us") - if err != nil { - t.Fatalf("Failed to parse cpu.cfs_period_us - %s", err) - } - if period != periodAfter { - t.Fatal("Got the wrong value, set cpu.cfs_period_us failed.") - } - rtRuntime, err := getCgroupParamUint(helper.CgroupPath, "cpu.rt_runtime_us") - if err != nil { - t.Fatalf("Failed to parse cpu.rt_runtime_us - %s", err) - } - if rtRuntime != rtRuntimeAfter { - t.Fatal("Got the wrong value, set cpu.rt_runtime_us failed.") - } - rtPeriod, err := getCgroupParamUint(helper.CgroupPath, "cpu.rt_period_us") - if err != nil { - t.Fatalf("Failed to parse cpu.rt_period_us - %s", err) - } - if rtPeriod != rtPeriodAfter { - t.Fatal("Got the wrong value, set cpu.rt_period_us failed.") - } -} - -func TestCpuStats(t *testing.T) { - helper := NewCgroupTestUtil("cpu", t) - defer helper.cleanup() - - const ( - kNrPeriods = 2000 - kNrThrottled = 200 - kThrottledTime = uint64(18446744073709551615) - ) - - cpuStatContent := fmt.Sprintf("nr_periods %d\n nr_throttled %d\n throttled_time %d\n", - kNrPeriods, kNrThrottled, kThrottledTime) - helper.writeFileContents(map[string]string{ - "cpu.stat": cpuStatContent, - }) - - cpu := &CpuGroup{} - actualStats := *cgroups.NewStats() - err := cpu.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatal(err) - } - - expectedStats := cgroups.ThrottlingData{ - Periods: kNrPeriods, - ThrottledPeriods: kNrThrottled, - ThrottledTime: kThrottledTime} - - expectThrottlingDataEquals(t, expectedStats, actualStats.CpuStats.ThrottlingData) -} - -func TestNoCpuStatFile(t *testing.T) { - helper := NewCgroupTestUtil("cpu", t) - defer helper.cleanup() - - cpu := &CpuGroup{} - actualStats := *cgroups.NewStats() - err := cpu.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatal("Expected not to fail, but did") - } -} - -func TestInvalidCpuStat(t *testing.T) { - helper := NewCgroupTestUtil("cpu", t) - defer helper.cleanup() - cpuStatContent := `nr_periods 2000 - nr_throttled 200 - throttled_time fortytwo` - helper.writeFileContents(map[string]string{ - "cpu.stat": cpuStatContent, - }) - - cpu := &CpuGroup{} - actualStats := *cgroups.NewStats() - err := cpu.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failed stat parsing.") - } -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuacct.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuacct.go deleted file mode 100644 index 4ff4fefe..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuacct.go +++ /dev/null @@ -1,117 +0,0 @@ -// +build linux - -package fs - -import ( - "fmt" - "io/ioutil" - "path/filepath" - "strconv" - "strings" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" - "github.com/opencontainers/runc/libcontainer/system" -) - -const ( - cgroupCpuacctStat = "cpuacct.stat" - nanosecondsInSecond = 1000000000 -) - -var clockTicks = uint64(system.GetClockTicks()) - -type CpuacctGroup struct { -} - -func (s *CpuacctGroup) Apply(d *data) error { - // we just want to join this group even though we don't set anything - if _, err := d.join("cpuacct"); err != nil && !cgroups.IsNotFound(err) { - return err - } - - return nil -} - -func (s *CpuacctGroup) Set(path string, cgroup *configs.Cgroup) error { - return nil -} - -func (s *CpuacctGroup) Remove(d *data) error { - return removePath(d.path("cpuacct")) -} - -func (s *CpuacctGroup) GetStats(path string, stats *cgroups.Stats) error { - userModeUsage, kernelModeUsage, err := getCpuUsageBreakdown(path) - if err != nil { - return err - } - - totalUsage, err := getCgroupParamUint(path, "cpuacct.usage") - if err != nil { - return err - } - - percpuUsage, err := getPercpuUsage(path) - if err != nil { - return err - } - - stats.CpuStats.CpuUsage.TotalUsage = totalUsage - stats.CpuStats.CpuUsage.PercpuUsage = percpuUsage - stats.CpuStats.CpuUsage.UsageInUsermode = userModeUsage - stats.CpuStats.CpuUsage.UsageInKernelmode = kernelModeUsage - return nil -} - -// Returns user and kernel usage breakdown in nanoseconds. -func getCpuUsageBreakdown(path string) (uint64, uint64, error) { - userModeUsage := uint64(0) - kernelModeUsage := uint64(0) - const ( - userField = "user" - systemField = "system" - ) - - // Expected format: - // user - // system - data, err := ioutil.ReadFile(filepath.Join(path, cgroupCpuacctStat)) - if err != nil { - return 0, 0, err - } - fields := strings.Fields(string(data)) - if len(fields) != 4 { - return 0, 0, fmt.Errorf("failure - %s is expected to have 4 fields", filepath.Join(path, cgroupCpuacctStat)) - } - if fields[0] != userField { - return 0, 0, fmt.Errorf("unexpected field %q in %q, expected %q", fields[0], cgroupCpuacctStat, userField) - } - if fields[2] != systemField { - return 0, 0, fmt.Errorf("unexpected field %q in %q, expected %q", fields[2], cgroupCpuacctStat, systemField) - } - if userModeUsage, err = strconv.ParseUint(fields[1], 10, 64); err != nil { - return 0, 0, err - } - if kernelModeUsage, err = strconv.ParseUint(fields[3], 10, 64); err != nil { - return 0, 0, err - } - - return (userModeUsage * nanosecondsInSecond) / clockTicks, (kernelModeUsage * nanosecondsInSecond) / clockTicks, nil -} - -func getPercpuUsage(path string) ([]uint64, error) { - percpuUsage := []uint64{} - data, err := ioutil.ReadFile(filepath.Join(path, "cpuacct.usage_percpu")) - if err != nil { - return percpuUsage, err - } - for _, value := range strings.Fields(string(data)) { - value, err := strconv.ParseUint(value, 10, 64) - if err != nil { - return percpuUsage, fmt.Errorf("Unable to convert param value to uint64: %s", err) - } - percpuUsage = append(percpuUsage, value) - } - return percpuUsage, nil -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset.go deleted file mode 100644 index f3ec2c3e..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset.go +++ /dev/null @@ -1,135 +0,0 @@ -// +build linux - -package fs - -import ( - "bytes" - "io/ioutil" - "os" - "path/filepath" - "strconv" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -type CpusetGroup struct { -} - -func (s *CpusetGroup) Apply(d *data) error { - dir, err := d.path("cpuset") - if err != nil && !cgroups.IsNotFound(err) { - return err - } - return s.ApplyDir(dir, d.c, d.pid) -} - -func (s *CpusetGroup) Set(path string, cgroup *configs.Cgroup) error { - if cgroup.CpusetCpus != "" { - if err := writeFile(path, "cpuset.cpus", cgroup.CpusetCpus); err != nil { - return err - } - } - if cgroup.CpusetMems != "" { - if err := writeFile(path, "cpuset.mems", cgroup.CpusetMems); err != nil { - return err - } - } - return nil -} - -func (s *CpusetGroup) Remove(d *data) error { - return removePath(d.path("cpuset")) -} - -func (s *CpusetGroup) GetStats(path string, stats *cgroups.Stats) error { - return nil -} - -func (s *CpusetGroup) ApplyDir(dir string, cgroup *configs.Cgroup, pid int) error { - // This might happen if we have no cpuset cgroup mounted. - // Just do nothing and don't fail. - if dir == "" { - return nil - } - root, err := getCgroupRoot() - if err != nil { - return err - } - if err := s.ensureParent(dir, root); err != nil { - return err - } - // because we are not using d.join we need to place the pid into the procs file - // unlike the other subsystems - if err := writeFile(dir, "cgroup.procs", strconv.Itoa(pid)); err != nil { - return err - } - - // the default values inherit from parent cgroup are already set in - // s.ensureParent, cover these if we have our own - if err := s.Set(dir, cgroup); err != nil { - return err - } - - return nil -} - -func (s *CpusetGroup) getSubsystemSettings(parent string) (cpus []byte, mems []byte, err error) { - if cpus, err = ioutil.ReadFile(filepath.Join(parent, "cpuset.cpus")); err != nil { - return - } - if mems, err = ioutil.ReadFile(filepath.Join(parent, "cpuset.mems")); err != nil { - return - } - return cpus, mems, nil -} - -// ensureParent makes sure that the parent directory of current is created -// and populated with the proper cpus and mems files copied from -// it's parent. -func (s *CpusetGroup) ensureParent(current, root string) error { - parent := filepath.Dir(current) - if filepath.Clean(parent) == root { - return nil - } - if err := s.ensureParent(parent, root); err != nil { - return err - } - if err := os.MkdirAll(current, 0755); err != nil { - return err - } - return s.copyIfNeeded(current, parent) -} - -// copyIfNeeded copies the cpuset.cpus and cpuset.mems from the parent -// directory to the current directory if the file's contents are 0 -func (s *CpusetGroup) copyIfNeeded(current, parent string) error { - var ( - err error - currentCpus, currentMems []byte - parentCpus, parentMems []byte - ) - - if currentCpus, currentMems, err = s.getSubsystemSettings(current); err != nil { - return err - } - if parentCpus, parentMems, err = s.getSubsystemSettings(parent); err != nil { - return err - } - - if s.isEmpty(currentCpus) { - if err := writeFile(current, "cpuset.cpus", string(parentCpus)); err != nil { - return err - } - } - if s.isEmpty(currentMems) { - if err := writeFile(current, "cpuset.mems", string(parentMems)); err != nil { - return err - } - } - return nil -} - -func (s *CpusetGroup) isEmpty(b []byte) bool { - return len(bytes.Trim(b, "\n")) == 0 -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset_test.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset_test.go deleted file mode 100644 index 44b2f943..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset_test.go +++ /dev/null @@ -1,65 +0,0 @@ -// +build linux - -package fs - -import ( - "testing" -) - -func TestCpusetSetCpus(t *testing.T) { - helper := NewCgroupTestUtil("cpuset", t) - defer helper.cleanup() - - const ( - cpusBefore = "0" - cpusAfter = "1-3" - ) - - helper.writeFileContents(map[string]string{ - "cpuset.cpus": cpusBefore, - }) - - helper.CgroupData.c.CpusetCpus = cpusAfter - cpuset := &CpusetGroup{} - if err := cpuset.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "cpuset.cpus") - if err != nil { - t.Fatalf("Failed to parse cpuset.cpus - %s", err) - } - - if value != cpusAfter { - t.Fatal("Got the wrong value, set cpuset.cpus failed.") - } -} - -func TestCpusetSetMems(t *testing.T) { - helper := NewCgroupTestUtil("cpuset", t) - defer helper.cleanup() - - const ( - memsBefore = "0" - memsAfter = "1" - ) - - helper.writeFileContents(map[string]string{ - "cpuset.mems": memsBefore, - }) - - helper.CgroupData.c.CpusetMems = memsAfter - cpuset := &CpusetGroup{} - if err := cpuset.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "cpuset.mems") - if err != nil { - t.Fatalf("Failed to parse cpuset.mems - %s", err) - } - - if value != memsAfter { - t.Fatal("Got the wrong value, set cpuset.mems failed.") - } -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices.go deleted file mode 100644 index d621d275..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices.go +++ /dev/null @@ -1,61 +0,0 @@ -// +build linux - -package fs - -import ( - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -type DevicesGroup struct { -} - -func (s *DevicesGroup) Apply(d *data) error { - dir, err := d.join("devices") - if err != nil { - // We will return error even it's `not found` error, devices - // cgroup is hard requirement for container's security. - return err - } - - if err := s.Set(dir, d.c); err != nil { - return err - } - - return nil -} - -func (s *DevicesGroup) Set(path string, cgroup *configs.Cgroup) error { - if !cgroup.AllowAllDevices { - if err := writeFile(path, "devices.deny", "a"); err != nil { - return err - } - - for _, dev := range cgroup.AllowedDevices { - if err := writeFile(path, "devices.allow", dev.CgroupString()); err != nil { - return err - } - } - return nil - } - - if err := writeFile(path, "devices.allow", "a"); err != nil { - return err - } - - for _, dev := range cgroup.DeniedDevices { - if err := writeFile(path, "devices.deny", dev.CgroupString()); err != nil { - return err - } - } - - return nil -} - -func (s *DevicesGroup) Remove(d *data) error { - return removePath(d.path("devices")) -} - -func (s *DevicesGroup) GetStats(path string, stats *cgroups.Stats) error { - return nil -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices_test.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices_test.go deleted file mode 100644 index f8422644..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices_test.go +++ /dev/null @@ -1,84 +0,0 @@ -// +build linux - -package fs - -import ( - "testing" - - "github.com/opencontainers/runc/libcontainer/configs" -) - -var ( - allowedDevices = []*configs.Device{ - { - Path: "/dev/zero", - Type: 'c', - Major: 1, - Minor: 5, - Permissions: "rwm", - FileMode: 0666, - }, - } - allowedList = "c 1:5 rwm" - deniedDevices = []*configs.Device{ - { - Path: "/dev/null", - Type: 'c', - Major: 1, - Minor: 3, - Permissions: "rwm", - FileMode: 0666, - }, - } - deniedList = "c 1:3 rwm" -) - -func TestDevicesSetAllow(t *testing.T) { - helper := NewCgroupTestUtil("devices", t) - defer helper.cleanup() - - helper.writeFileContents(map[string]string{ - "devices.deny": "a", - }) - - helper.CgroupData.c.AllowAllDevices = false - helper.CgroupData.c.AllowedDevices = allowedDevices - devices := &DevicesGroup{} - if err := devices.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "devices.allow") - if err != nil { - t.Fatalf("Failed to parse devices.allow - %s", err) - } - - if value != allowedList { - t.Fatal("Got the wrong value, set devices.allow failed.") - } -} - -func TestDevicesSetDeny(t *testing.T) { - helper := NewCgroupTestUtil("devices", t) - defer helper.cleanup() - - helper.writeFileContents(map[string]string{ - "devices.allow": "a", - }) - - helper.CgroupData.c.AllowAllDevices = true - helper.CgroupData.c.DeniedDevices = deniedDevices - devices := &DevicesGroup{} - if err := devices.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "devices.deny") - if err != nil { - t.Fatalf("Failed to parse devices.deny - %s", err) - } - - if value != deniedList { - t.Fatal("Got the wrong value, set devices.deny failed.") - } -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/freezer.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/freezer.go deleted file mode 100644 index 47f74395..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/freezer.go +++ /dev/null @@ -1,62 +0,0 @@ -// +build linux - -package fs - -import ( - "fmt" - "strings" - "time" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -type FreezerGroup struct { -} - -func (s *FreezerGroup) Apply(d *data) error { - dir, err := d.join("freezer") - if err != nil && !cgroups.IsNotFound(err) { - return err - } - - if err := s.Set(dir, d.c); err != nil { - return err - } - - return nil -} - -func (s *FreezerGroup) Set(path string, cgroup *configs.Cgroup) error { - switch cgroup.Freezer { - case configs.Frozen, configs.Thawed: - if err := writeFile(path, "freezer.state", string(cgroup.Freezer)); err != nil { - return err - } - - for { - state, err := readFile(path, "freezer.state") - if err != nil { - return err - } - if strings.TrimSpace(state) == string(cgroup.Freezer) { - break - } - time.Sleep(1 * time.Millisecond) - } - case configs.Undefined: - return nil - default: - return fmt.Errorf("Invalid argument '%s' to freezer.state", string(cgroup.Freezer)) - } - - return nil -} - -func (s *FreezerGroup) Remove(d *data) error { - return removePath(d.path("freezer")) -} - -func (s *FreezerGroup) GetStats(path string, stats *cgroups.Stats) error { - return nil -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/freezer_test.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/freezer_test.go deleted file mode 100644 index 88abb675..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/freezer_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package fs - -import ( - "testing" - - "github.com/opencontainers/runc/libcontainer/configs" -) - -func TestFreezerSetState(t *testing.T) { - helper := NewCgroupTestUtil("freezer", t) - defer helper.cleanup() - - helper.writeFileContents(map[string]string{ - "freezer.state": string(configs.Frozen), - }) - - helper.CgroupData.c.Freezer = configs.Thawed - freezer := &FreezerGroup{} - if err := freezer.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "freezer.state") - if err != nil { - t.Fatalf("Failed to parse freezer.state - %s", err) - } - if value != string(configs.Thawed) { - t.Fatal("Got the wrong value, set freezer.state failed.") - } -} - -func TestFreezerSetInvalidState(t *testing.T) { - helper := NewCgroupTestUtil("freezer", t) - defer helper.cleanup() - - const ( - invalidArg configs.FreezerState = "Invalid" - ) - - helper.CgroupData.c.Freezer = invalidArg - freezer := &FreezerGroup{} - if err := freezer.Set(helper.CgroupPath, helper.CgroupData.c); err == nil { - t.Fatal("Failed to return invalid argument error") - } -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/fs_unsupported.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/fs_unsupported.go deleted file mode 100644 index 3ef9e031..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/fs_unsupported.go +++ /dev/null @@ -1,3 +0,0 @@ -// +build !linux - -package fs diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/hugetlb.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/hugetlb.go deleted file mode 100644 index a7d3a870..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/hugetlb.go +++ /dev/null @@ -1,72 +0,0 @@ -// +build linux - -package fs - -import ( - "fmt" - "strconv" - "strings" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -type HugetlbGroup struct { -} - -func (s *HugetlbGroup) Apply(d *data) error { - dir, err := d.join("hugetlb") - if err != nil && !cgroups.IsNotFound(err) { - return err - } - - if err := s.Set(dir, d.c); err != nil { - return err - } - - return nil -} - -func (s *HugetlbGroup) Set(path string, cgroup *configs.Cgroup) error { - for _, hugetlb := range cgroup.HugetlbLimit { - if err := writeFile(path, strings.Join([]string{"hugetlb", hugetlb.Pagesize, "limit_in_bytes"}, "."), strconv.FormatUint(hugetlb.Limit, 10)); err != nil { - return err - } - } - - return nil -} - -func (s *HugetlbGroup) Remove(d *data) error { - return removePath(d.path("hugetlb")) -} - -func (s *HugetlbGroup) GetStats(path string, stats *cgroups.Stats) error { - hugetlbStats := cgroups.HugetlbStats{} - for _, pageSize := range HugePageSizes { - usage := strings.Join([]string{"hugetlb", pageSize, "usage_in_bytes"}, ".") - value, err := getCgroupParamUint(path, usage) - if err != nil { - return fmt.Errorf("failed to parse %s - %v", usage, err) - } - hugetlbStats.Usage = value - - maxUsage := strings.Join([]string{"hugetlb", pageSize, "max_usage_in_bytes"}, ".") - value, err = getCgroupParamUint(path, maxUsage) - if err != nil { - return fmt.Errorf("failed to parse %s - %v", maxUsage, err) - } - hugetlbStats.MaxUsage = value - - failcnt := strings.Join([]string{"hugetlb", pageSize, "failcnt"}, ".") - value, err = getCgroupParamUint(path, failcnt) - if err != nil { - return fmt.Errorf("failed to parse %s - %v", failcnt, err) - } - hugetlbStats.Failcnt = value - - stats.HugetlbStats[pageSize] = hugetlbStats - } - - return nil -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/hugetlb_test.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/hugetlb_test.go deleted file mode 100644 index a4c2588b..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/hugetlb_test.go +++ /dev/null @@ -1,152 +0,0 @@ -package fs - -import ( - "fmt" - "strconv" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -const ( - hugetlbUsageContents = "128\n" - hugetlbMaxUsageContents = "256\n" - hugetlbFailcnt = "100\n" -) - -var ( - usage = "hugetlb.%s.usage_in_bytes" - limit = "hugetlb.%s.limit_in_bytes" - maxUsage = "hugetlb.%s.max_usage_in_bytes" - failcnt = "hugetlb.%s.failcnt" -) - -func TestHugetlbSetHugetlb(t *testing.T) { - helper := NewCgroupTestUtil("hugetlb", t) - defer helper.cleanup() - - const ( - hugetlbBefore = 256 - hugetlbAfter = 512 - ) - - for _, pageSize := range HugePageSizes { - helper.writeFileContents(map[string]string{ - fmt.Sprintf(limit, pageSize): strconv.Itoa(hugetlbBefore), - }) - } - - for _, pageSize := range HugePageSizes { - helper.CgroupData.c.HugetlbLimit = []*configs.HugepageLimit{ - { - Pagesize: pageSize, - Limit: hugetlbAfter, - }, - } - hugetlb := &HugetlbGroup{} - if err := hugetlb.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - } - - for _, pageSize := range HugePageSizes { - limit := fmt.Sprintf(limit, pageSize) - value, err := getCgroupParamUint(helper.CgroupPath, limit) - if err != nil { - t.Fatalf("Failed to parse %s - %s", limit, err) - } - if value != hugetlbAfter { - t.Fatalf("Set hugetlb.limit_in_bytes failed. Expected: %v, Got: %v", hugetlbAfter, value) - } - } -} - -func TestHugetlbStats(t *testing.T) { - helper := NewCgroupTestUtil("hugetlb", t) - defer helper.cleanup() - for _, pageSize := range HugePageSizes { - helper.writeFileContents(map[string]string{ - fmt.Sprintf(usage, pageSize): hugetlbUsageContents, - fmt.Sprintf(maxUsage, pageSize): hugetlbMaxUsageContents, - fmt.Sprintf(failcnt, pageSize): hugetlbFailcnt, - }) - } - - hugetlb := &HugetlbGroup{} - actualStats := *cgroups.NewStats() - err := hugetlb.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatal(err) - } - expectedStats := cgroups.HugetlbStats{Usage: 128, MaxUsage: 256, Failcnt: 100} - for _, pageSize := range HugePageSizes { - expectHugetlbStatEquals(t, expectedStats, actualStats.HugetlbStats[pageSize]) - } -} - -func TestHugetlbStatsNoUsageFile(t *testing.T) { - helper := NewCgroupTestUtil("hugetlb", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - maxUsage: hugetlbMaxUsageContents, - }) - - hugetlb := &HugetlbGroup{} - actualStats := *cgroups.NewStats() - err := hugetlb.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestHugetlbStatsNoMaxUsageFile(t *testing.T) { - helper := NewCgroupTestUtil("hugetlb", t) - defer helper.cleanup() - for _, pageSize := range HugePageSizes { - helper.writeFileContents(map[string]string{ - fmt.Sprintf(usage, pageSize): hugetlbUsageContents, - }) - } - - hugetlb := &HugetlbGroup{} - actualStats := *cgroups.NewStats() - err := hugetlb.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestHugetlbStatsBadUsageFile(t *testing.T) { - helper := NewCgroupTestUtil("hugetlb", t) - defer helper.cleanup() - for _, pageSize := range HugePageSizes { - helper.writeFileContents(map[string]string{ - fmt.Sprintf(usage, pageSize): "bad", - maxUsage: hugetlbMaxUsageContents, - }) - } - - hugetlb := &HugetlbGroup{} - actualStats := *cgroups.NewStats() - err := hugetlb.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestHugetlbStatsBadMaxUsageFile(t *testing.T) { - helper := NewCgroupTestUtil("hugetlb", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - usage: hugetlbUsageContents, - maxUsage: "bad", - }) - - hugetlb := &HugetlbGroup{} - actualStats := *cgroups.NewStats() - err := hugetlb.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go deleted file mode 100644 index 23c68f83..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go +++ /dev/null @@ -1,172 +0,0 @@ -// +build linux - -package fs - -import ( - "bufio" - "fmt" - "os" - "path/filepath" - "strconv" - "strings" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -type MemoryGroup struct { -} - -func (s *MemoryGroup) Apply(d *data) (err error) { - path, err := d.path("memory") - if err != nil { - if cgroups.IsNotFound(err) { - return nil - } - return err - } - if err := os.MkdirAll(path, 0755); err != nil { - return err - } - - defer func() { - if err != nil { - os.RemoveAll(path) - } - }() - - if err := s.Set(path, d.c); err != nil { - return err - } - - // We need to join memory cgroup after set memory limits, because - // kmem.limit_in_bytes can only be set when the cgroup is empty. - if _, err = d.join("memory"); err != nil { - return err - } - - return nil -} - -func (s *MemoryGroup) Set(path string, cgroup *configs.Cgroup) error { - if cgroup.Memory != 0 { - if err := writeFile(path, "memory.limit_in_bytes", strconv.FormatInt(cgroup.Memory, 10)); err != nil { - return err - } - } - if cgroup.MemoryReservation != 0 { - if err := writeFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(cgroup.MemoryReservation, 10)); err != nil { - return err - } - } - if cgroup.MemorySwap > 0 { - if err := writeFile(path, "memory.memsw.limit_in_bytes", strconv.FormatInt(cgroup.MemorySwap, 10)); err != nil { - return err - } - } - if cgroup.KernelMemory > 0 { - if err := writeFile(path, "memory.kmem.limit_in_bytes", strconv.FormatInt(cgroup.KernelMemory, 10)); err != nil { - return err - } - } - - if cgroup.OomKillDisable { - if err := writeFile(path, "memory.oom_control", "1"); err != nil { - return err - } - } - if cgroup.MemorySwappiness >= 0 && cgroup.MemorySwappiness <= 100 { - if err := writeFile(path, "memory.swappiness", strconv.FormatInt(cgroup.MemorySwappiness, 10)); err != nil { - return err - } - } else if cgroup.MemorySwappiness == -1 { - return nil - } else { - return fmt.Errorf("invalid value:%d. valid memory swappiness range is 0-100", cgroup.MemorySwappiness) - } - - return nil -} - -func (s *MemoryGroup) Remove(d *data) error { - return removePath(d.path("memory")) -} - -func (s *MemoryGroup) GetStats(path string, stats *cgroups.Stats) error { - // Set stats from memory.stat. - statsFile, err := os.Open(filepath.Join(path, "memory.stat")) - if err != nil { - if os.IsNotExist(err) { - return nil - } - return err - } - defer statsFile.Close() - - sc := bufio.NewScanner(statsFile) - for sc.Scan() { - t, v, err := getCgroupParamKeyValue(sc.Text()) - if err != nil { - return fmt.Errorf("failed to parse memory.stat (%q) - %v", sc.Text(), err) - } - stats.MemoryStats.Stats[t] = v - } - stats.MemoryStats.Cache = stats.MemoryStats.Stats["cache"] - - memoryUsage, err := getMemoryData(path, "") - if err != nil { - return err - } - stats.MemoryStats.Usage = memoryUsage - swapUsage, err := getMemoryData(path, "memsw") - if err != nil { - return err - } - stats.MemoryStats.SwapUsage = swapUsage - kernelUsage, err := getMemoryData(path, "kmem") - if err != nil { - return err - } - stats.MemoryStats.KernelUsage = kernelUsage - - return nil -} - -func getMemoryData(path, name string) (cgroups.MemoryData, error) { - memoryData := cgroups.MemoryData{} - - moduleName := "memory" - if name != "" { - moduleName = strings.Join([]string{"memory", name}, ".") - } - usage := strings.Join([]string{moduleName, "usage_in_bytes"}, ".") - maxUsage := strings.Join([]string{moduleName, "max_usage_in_bytes"}, ".") - failcnt := strings.Join([]string{moduleName, "failcnt"}, ".") - - value, err := getCgroupParamUint(path, usage) - if err != nil { - if moduleName != "memory" && os.IsNotExist(err) { - return cgroups.MemoryData{}, nil - } - return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", usage, err) - } - memoryData.Usage = value - value, err = getCgroupParamUint(path, maxUsage) - if err != nil { - if moduleName != "memory" && os.IsNotExist(err) { - return cgroups.MemoryData{}, nil - } - return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", maxUsage, err) - } - memoryData.MaxUsage = value - value, err = getCgroupParamUint(path, failcnt) - if err != nil { - if moduleName != "memory" && os.IsNotExist(err) { - return cgroups.MemoryData{}, nil - } - return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", failcnt, err) - } - memoryData.Failcnt = value - - return memoryData, nil -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory_test.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory_test.go deleted file mode 100644 index d7b5e5f4..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory_test.go +++ /dev/null @@ -1,294 +0,0 @@ -// +build linux - -package fs - -import ( - "strconv" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -const ( - memoryStatContents = `cache 512 -rss 1024` - memoryUsageContents = "2048\n" - memoryMaxUsageContents = "4096\n" - memoryFailcnt = "100\n" -) - -func TestMemorySetMemory(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - - const ( - memoryBefore = 314572800 // 300M - memoryAfter = 524288000 // 500M - reservationBefore = 209715200 // 200M - reservationAfter = 314572800 // 300M - ) - - helper.writeFileContents(map[string]string{ - "memory.limit_in_bytes": strconv.Itoa(memoryBefore), - "memory.soft_limit_in_bytes": strconv.Itoa(reservationBefore), - }) - - helper.CgroupData.c.Memory = memoryAfter - helper.CgroupData.c.MemoryReservation = reservationAfter - memory := &MemoryGroup{} - if err := memory.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamUint(helper.CgroupPath, "memory.limit_in_bytes") - if err != nil { - t.Fatalf("Failed to parse memory.limit_in_bytes - %s", err) - } - if value != memoryAfter { - t.Fatal("Got the wrong value, set memory.limit_in_bytes failed.") - } - - value, err = getCgroupParamUint(helper.CgroupPath, "memory.soft_limit_in_bytes") - if err != nil { - t.Fatalf("Failed to parse memory.soft_limit_in_bytes - %s", err) - } - if value != reservationAfter { - t.Fatal("Got the wrong value, set memory.soft_limit_in_bytes failed.") - } -} - -func TestMemorySetMemoryswap(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - - const ( - memoryswapBefore = 314572800 // 300M - memoryswapAfter = 524288000 // 500M - ) - - helper.writeFileContents(map[string]string{ - "memory.memsw.limit_in_bytes": strconv.Itoa(memoryswapBefore), - }) - - helper.CgroupData.c.MemorySwap = memoryswapAfter - memory := &MemoryGroup{} - if err := memory.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamUint(helper.CgroupPath, "memory.memsw.limit_in_bytes") - if err != nil { - t.Fatalf("Failed to parse memory.memsw.limit_in_bytes - %s", err) - } - if value != memoryswapAfter { - t.Fatal("Got the wrong value, set memory.memsw.limit_in_bytes failed.") - } -} - -func TestMemorySetKernelMemory(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - - const ( - kernelMemoryBefore = 314572800 // 300M - kernelMemoryAfter = 524288000 // 500M - ) - - helper.writeFileContents(map[string]string{ - "memory.kmem.limit_in_bytes": strconv.Itoa(kernelMemoryBefore), - }) - - helper.CgroupData.c.KernelMemory = kernelMemoryAfter - memory := &MemoryGroup{} - if err := memory.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamUint(helper.CgroupPath, "memory.kmem.limit_in_bytes") - if err != nil { - t.Fatalf("Failed to parse memory.kmem.limit_in_bytes - %s", err) - } - if value != kernelMemoryAfter { - t.Fatal("Got the wrong value, set memory.kmem.limit_in_bytes failed.") - } -} - -func TestMemorySetMemorySwappinessDefault(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - - const ( - swappinessBefore = 60 //deafult is 60 - swappinessAfter = 0 - ) - - helper.writeFileContents(map[string]string{ - "memory.swappiness": strconv.Itoa(swappinessBefore), - }) - - helper.CgroupData.c.Memory = swappinessAfter - memory := &MemoryGroup{} - if err := memory.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamUint(helper.CgroupPath, "memory.swappiness") - if err != nil { - t.Fatalf("Failed to parse memory.swappiness - %s", err) - } - if value != swappinessAfter { - t.Fatal("Got the wrong value, set memory.swappiness failed.") - } -} - -func TestMemoryStats(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "memory.stat": memoryStatContents, - "memory.usage_in_bytes": memoryUsageContents, - "memory.max_usage_in_bytes": memoryMaxUsageContents, - "memory.failcnt": memoryFailcnt, - "memory.memsw.usage_in_bytes": memoryUsageContents, - "memory.memsw.max_usage_in_bytes": memoryMaxUsageContents, - "memory.memsw.failcnt": memoryFailcnt, - "memory.kmem.usage_in_bytes": memoryUsageContents, - "memory.kmem.max_usage_in_bytes": memoryMaxUsageContents, - "memory.kmem.failcnt": memoryFailcnt, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatal(err) - } - expectedStats := cgroups.MemoryStats{Cache: 512, Usage: cgroups.MemoryData{Usage: 2048, MaxUsage: 4096, Failcnt: 100}, SwapUsage: cgroups.MemoryData{Usage: 2048, MaxUsage: 4096, Failcnt: 100}, KernelUsage: cgroups.MemoryData{Usage: 2048, MaxUsage: 4096, Failcnt: 100}, Stats: map[string]uint64{"cache": 512, "rss": 1024}} - expectMemoryStatEquals(t, expectedStats, actualStats.MemoryStats) -} - -func TestMemoryStatsNoStatFile(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "memory.usage_in_bytes": memoryUsageContents, - "memory.max_usage_in_bytes": memoryMaxUsageContents, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatal(err) - } -} - -func TestMemoryStatsNoUsageFile(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "memory.stat": memoryStatContents, - "memory.max_usage_in_bytes": memoryMaxUsageContents, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestMemoryStatsNoMaxUsageFile(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "memory.stat": memoryStatContents, - "memory.usage_in_bytes": memoryUsageContents, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestMemoryStatsBadStatFile(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "memory.stat": "rss rss", - "memory.usage_in_bytes": memoryUsageContents, - "memory.max_usage_in_bytes": memoryMaxUsageContents, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestMemoryStatsBadUsageFile(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "memory.stat": memoryStatContents, - "memory.usage_in_bytes": "bad", - "memory.max_usage_in_bytes": memoryMaxUsageContents, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestMemoryStatsBadMaxUsageFile(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "memory.stat": memoryStatContents, - "memory.usage_in_bytes": memoryUsageContents, - "memory.max_usage_in_bytes": "bad", - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestMemorySetOomControl(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - - const ( - oom_kill_disable = 1 // disable oom killer, default is 0 - ) - - helper.writeFileContents(map[string]string{ - "memory.oom_control": strconv.Itoa(oom_kill_disable), - }) - - memory := &MemoryGroup{} - if err := memory.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamUint(helper.CgroupPath, "memory.oom_control") - if err != nil { - t.Fatalf("Failed to parse memory.oom_control - %s", err) - } - - if value != oom_kill_disable { - t.Fatalf("Got the wrong value, set memory.oom_control failed.") - } -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/name.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/name.go deleted file mode 100644 index 99913802..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/name.go +++ /dev/null @@ -1,25 +0,0 @@ -package fs - -import ( - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -type NameGroup struct { -} - -func (s *NameGroup) Apply(d *data) error { - return nil -} - -func (s *NameGroup) Set(path string, cgroup *configs.Cgroup) error { - return nil -} - -func (s *NameGroup) Remove(d *data) error { - return nil -} - -func (s *NameGroup) GetStats(path string, stats *cgroups.Stats) error { - return nil -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_cls.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_cls.go deleted file mode 100644 index 23335dd7..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_cls.go +++ /dev/null @@ -1,40 +0,0 @@ -package fs - -import ( - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -type NetClsGroup struct { -} - -func (s *NetClsGroup) Apply(d *data) error { - dir, err := d.join("net_cls") - if err != nil && !cgroups.IsNotFound(err) { - return err - } - - if err := s.Set(dir, d.c); err != nil { - return err - } - - return nil -} - -func (s *NetClsGroup) Set(path string, cgroup *configs.Cgroup) error { - if cgroup.NetClsClassid != "" { - if err := writeFile(path, "net_cls.classid", cgroup.NetClsClassid); err != nil { - return err - } - } - - return nil -} - -func (s *NetClsGroup) Remove(d *data) error { - return removePath(d.path("net_cls")) -} - -func (s *NetClsGroup) GetStats(path string, stats *cgroups.Stats) error { - return nil -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_cls_test.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_cls_test.go deleted file mode 100644 index c24ee037..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_cls_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package fs - -import ( - "testing" -) - -const ( - classidBefore = "0x100002" - classidAfter = "0x100001" -) - -func TestNetClsSetClassid(t *testing.T) { - helper := NewCgroupTestUtil("net_cls", t) - defer helper.cleanup() - - helper.writeFileContents(map[string]string{ - "net_cls.classid": classidBefore, - }) - - helper.CgroupData.c.NetClsClassid = classidAfter - netcls := &NetClsGroup{} - if err := netcls.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - // As we are in mock environment, we can't get correct value of classid from - // net_cls.classid. - // So. we just judge if we successfully write classid into file - value, err := getCgroupParamString(helper.CgroupPath, "net_cls.classid") - if err != nil { - t.Fatalf("Failed to parse net_cls.classid - %s", err) - } - if value != classidAfter { - t.Fatal("Got the wrong value, set net_cls.classid failed.") - } -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_prio.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_prio.go deleted file mode 100644 index 88f2ea8b..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_prio.go +++ /dev/null @@ -1,40 +0,0 @@ -package fs - -import ( - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -type NetPrioGroup struct { -} - -func (s *NetPrioGroup) Apply(d *data) error { - dir, err := d.join("net_prio") - if err != nil && !cgroups.IsNotFound(err) { - return err - } - - if err := s.Set(dir, d.c); err != nil { - return err - } - - return nil -} - -func (s *NetPrioGroup) Set(path string, cgroup *configs.Cgroup) error { - for _, prioMap := range cgroup.NetPrioIfpriomap { - if err := writeFile(path, "net_prio.ifpriomap", prioMap.CgroupString()); err != nil { - return err - } - } - - return nil -} - -func (s *NetPrioGroup) Remove(d *data) error { - return removePath(d.path("net_prio")) -} - -func (s *NetPrioGroup) GetStats(path string, stats *cgroups.Stats) error { - return nil -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_prio_test.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_prio_test.go deleted file mode 100644 index 0ef4955b..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_prio_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package fs - -import ( - "strings" - "testing" - - "github.com/opencontainers/runc/libcontainer/configs" -) - -var ( - prioMap = []*configs.IfPrioMap{ - { - Interface: "test", - Priority: 5, - }, - } -) - -func TestNetPrioSetIfPrio(t *testing.T) { - helper := NewCgroupTestUtil("net_prio", t) - defer helper.cleanup() - - helper.CgroupData.c.NetPrioIfpriomap = prioMap - netPrio := &NetPrioGroup{} - if err := netPrio.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "net_prio.ifpriomap") - if err != nil { - t.Fatalf("Failed to parse net_prio.ifpriomap - %s", err) - } - if !strings.Contains(value, "test 5") { - t.Fatal("Got the wrong value, set net_prio.ifpriomap failed.") - } -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/perf_event.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/perf_event.go deleted file mode 100644 index 30be9e56..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/perf_event.go +++ /dev/null @@ -1,31 +0,0 @@ -// +build linux - -package fs - -import ( - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -type PerfEventGroup struct { -} - -func (s *PerfEventGroup) Apply(d *data) error { - // we just want to join this group even though we don't set anything - if _, err := d.join("perf_event"); err != nil && !cgroups.IsNotFound(err) { - return err - } - return nil -} - -func (s *PerfEventGroup) Set(path string, cgroup *configs.Cgroup) error { - return nil -} - -func (s *PerfEventGroup) Remove(d *data) error { - return removePath(d.path("perf_event")) -} - -func (s *PerfEventGroup) GetStats(path string, stats *cgroups.Stats) error { - return nil -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/stats_util_test.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/stats_util_test.go deleted file mode 100644 index b1777cc0..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/stats_util_test.go +++ /dev/null @@ -1,113 +0,0 @@ -// +build linux - -package fs - -import ( - "fmt" - "testing" - - "github.com/Sirupsen/logrus" - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -func blkioStatEntryEquals(expected, actual []cgroups.BlkioStatEntry) error { - if len(expected) != len(actual) { - return fmt.Errorf("blkioStatEntries length do not match") - } - for i, expValue := range expected { - actValue := actual[i] - if expValue != actValue { - return fmt.Errorf("Expected blkio stat entry %v but found %v", expValue, actValue) - } - } - return nil -} - -func expectBlkioStatsEquals(t *testing.T, expected, actual cgroups.BlkioStats) { - if err := blkioStatEntryEquals(expected.IoServiceBytesRecursive, actual.IoServiceBytesRecursive); err != nil { - logrus.Printf("blkio IoServiceBytesRecursive do not match - %s\n", err) - t.Fail() - } - - if err := blkioStatEntryEquals(expected.IoServicedRecursive, actual.IoServicedRecursive); err != nil { - logrus.Printf("blkio IoServicedRecursive do not match - %s\n", err) - t.Fail() - } - - if err := blkioStatEntryEquals(expected.IoQueuedRecursive, actual.IoQueuedRecursive); err != nil { - logrus.Printf("blkio IoQueuedRecursive do not match - %s\n", err) - t.Fail() - } - - if err := blkioStatEntryEquals(expected.SectorsRecursive, actual.SectorsRecursive); err != nil { - logrus.Printf("blkio SectorsRecursive do not match - %s\n", err) - t.Fail() - } - - if err := blkioStatEntryEquals(expected.IoServiceTimeRecursive, actual.IoServiceTimeRecursive); err != nil { - logrus.Printf("blkio IoServiceTimeRecursive do not match - %s\n", err) - t.Fail() - } - - if err := blkioStatEntryEquals(expected.IoWaitTimeRecursive, actual.IoWaitTimeRecursive); err != nil { - logrus.Printf("blkio IoWaitTimeRecursive do not match - %s\n", err) - t.Fail() - } - - if err := blkioStatEntryEquals(expected.IoMergedRecursive, actual.IoMergedRecursive); err != nil { - logrus.Printf("blkio IoMergedRecursive do not match - %v vs %v\n", expected.IoMergedRecursive, actual.IoMergedRecursive) - t.Fail() - } - - if err := blkioStatEntryEquals(expected.IoTimeRecursive, actual.IoTimeRecursive); err != nil { - logrus.Printf("blkio IoTimeRecursive do not match - %s\n", err) - t.Fail() - } -} - -func expectThrottlingDataEquals(t *testing.T, expected, actual cgroups.ThrottlingData) { - if expected != actual { - logrus.Printf("Expected throttling data %v but found %v\n", expected, actual) - t.Fail() - } -} - -func expectHugetlbStatEquals(t *testing.T, expected, actual cgroups.HugetlbStats) { - if expected != actual { - logrus.Printf("Expected hugetlb stats %v but found %v\n", expected, actual) - t.Fail() - } -} - -func expectMemoryStatEquals(t *testing.T, expected, actual cgroups.MemoryStats) { - expectMemoryDataEquals(t, expected.Usage, actual.Usage) - expectMemoryDataEquals(t, expected.SwapUsage, actual.SwapUsage) - expectMemoryDataEquals(t, expected.KernelUsage, actual.KernelUsage) - - for key, expValue := range expected.Stats { - actValue, ok := actual.Stats[key] - if !ok { - logrus.Printf("Expected memory stat key %s not found\n", key) - t.Fail() - } - if expValue != actValue { - logrus.Printf("Expected memory stat value %d but found %d\n", expValue, actValue) - t.Fail() - } - } -} - -func expectMemoryDataEquals(t *testing.T, expected, actual cgroups.MemoryData) { - if expected.Usage != actual.Usage { - logrus.Printf("Expected memory usage %d but found %d\n", expected.Usage, actual.Usage) - t.Fail() - } - if expected.MaxUsage != actual.MaxUsage { - logrus.Printf("Expected memory max usage %d but found %d\n", expected.MaxUsage, actual.MaxUsage) - t.Fail() - } - if expected.Failcnt != actual.Failcnt { - logrus.Printf("Expected memory failcnt %d but found %d\n", expected.Failcnt, actual.Failcnt) - t.Fail() - } -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/util_test.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/util_test.go deleted file mode 100644 index 0f362560..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/util_test.go +++ /dev/null @@ -1,66 +0,0 @@ -// +build linux - -/* -Utility for testing cgroup operations. - -Creates a mock of the cgroup filesystem for the duration of the test. -*/ -package fs - -import ( - "io/ioutil" - "os" - "path/filepath" - "testing" - - "github.com/opencontainers/runc/libcontainer/configs" -) - -type cgroupTestUtil struct { - // data to use in tests. - CgroupData *data - - // Path to the mock cgroup directory. - CgroupPath string - - // Temporary directory to store mock cgroup filesystem. - tempDir string - t *testing.T -} - -// Creates a new test util for the specified subsystem -func NewCgroupTestUtil(subsystem string, t *testing.T) *cgroupTestUtil { - d := &data{ - c: &configs.Cgroup{}, - } - tempDir, err := ioutil.TempDir("", "cgroup_test") - if err != nil { - t.Fatal(err) - } - d.root = tempDir - testCgroupPath := filepath.Join(d.root, subsystem) - if err != nil { - t.Fatal(err) - } - - // Ensure the full mock cgroup path exists. - err = os.MkdirAll(testCgroupPath, 0755) - if err != nil { - t.Fatal(err) - } - return &cgroupTestUtil{CgroupData: d, CgroupPath: testCgroupPath, tempDir: tempDir, t: t} -} - -func (c *cgroupTestUtil) cleanup() { - os.RemoveAll(c.tempDir) -} - -// Write the specified contents on the mock of the specified cgroup files. -func (c *cgroupTestUtil) writeFileContents(fileContents map[string]string) { - for file, contents := range fileContents { - err := writeFile(c.CgroupPath, file, contents) - if err != nil { - c.t.Fatal(err) - } - } -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/utils.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/utils.go deleted file mode 100644 index 3a6eec79..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/utils.go +++ /dev/null @@ -1,74 +0,0 @@ -// +build linux - -package fs - -import ( - "errors" - "fmt" - "io/ioutil" - "path/filepath" - "strconv" - "strings" -) - -var ( - ErrNotSupportStat = errors.New("stats are not supported for subsystem") - ErrNotValidFormat = errors.New("line is not a valid key value format") -) - -// Saturates negative values at zero and returns a uint64. -// Due to kernel bugs, some of the memory cgroup stats can be negative. -func parseUint(s string, base, bitSize int) (uint64, error) { - value, err := strconv.ParseUint(s, base, bitSize) - if err != nil { - intValue, intErr := strconv.ParseInt(s, base, bitSize) - // 1. Handle negative values greater than MinInt64 (and) - // 2. Handle negative values lesser than MinInt64 - if intErr == nil && intValue < 0 { - return 0, nil - } else if intErr != nil && intErr.(*strconv.NumError).Err == strconv.ErrRange && intValue < 0 { - return 0, nil - } - - return value, err - } - - return value, nil -} - -// Parses a cgroup param and returns as name, value -// i.e. "io_service_bytes 1234" will return as io_service_bytes, 1234 -func getCgroupParamKeyValue(t string) (string, uint64, error) { - parts := strings.Fields(t) - switch len(parts) { - case 2: - value, err := parseUint(parts[1], 10, 64) - if err != nil { - return "", 0, fmt.Errorf("Unable to convert param value (%q) to uint64: %v", parts[1], err) - } - - return parts[0], value, nil - default: - return "", 0, ErrNotValidFormat - } -} - -// Gets a single uint64 value from the specified cgroup file. -func getCgroupParamUint(cgroupPath, cgroupFile string) (uint64, error) { - contents, err := ioutil.ReadFile(filepath.Join(cgroupPath, cgroupFile)) - if err != nil { - return 0, err - } - - return parseUint(strings.TrimSpace(string(contents)), 10, 64) -} - -// Gets a string value from the specified cgroup file -func getCgroupParamString(cgroupPath, cgroupFile string) (string, error) { - contents, err := ioutil.ReadFile(filepath.Join(cgroupPath, cgroupFile)) - if err != nil { - return "", err - } - - return strings.TrimSpace(string(contents)), nil -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/utils_test.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/utils_test.go deleted file mode 100644 index 99cdc18e..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/utils_test.go +++ /dev/null @@ -1,97 +0,0 @@ -// +build linux - -package fs - -import ( - "io/ioutil" - "math" - "os" - "path/filepath" - "strconv" - "testing" -) - -const ( - cgroupFile = "cgroup.file" - floatValue = 2048.0 - floatString = "2048" -) - -func TestGetCgroupParamsInt(t *testing.T) { - // Setup tempdir. - tempDir, err := ioutil.TempDir("", "cgroup_utils_test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tempDir) - tempFile := filepath.Join(tempDir, cgroupFile) - - // Success. - err = ioutil.WriteFile(tempFile, []byte(floatString), 0755) - if err != nil { - t.Fatal(err) - } - value, err := getCgroupParamUint(tempDir, cgroupFile) - if err != nil { - t.Fatal(err) - } else if value != floatValue { - t.Fatalf("Expected %d to equal %f", value, floatValue) - } - - // Success with new line. - err = ioutil.WriteFile(tempFile, []byte(floatString+"\n"), 0755) - if err != nil { - t.Fatal(err) - } - value, err = getCgroupParamUint(tempDir, cgroupFile) - if err != nil { - t.Fatal(err) - } else if value != floatValue { - t.Fatalf("Expected %d to equal %f", value, floatValue) - } - - // Success with negative values - err = ioutil.WriteFile(tempFile, []byte("-12345"), 0755) - if err != nil { - t.Fatal(err) - } - value, err = getCgroupParamUint(tempDir, cgroupFile) - if err != nil { - t.Fatal(err) - } else if value != 0 { - t.Fatalf("Expected %d to equal %d", value, 0) - } - - // Success with negative values lesser than min int64 - s := strconv.FormatFloat(math.MinInt64, 'f', -1, 64) - err = ioutil.WriteFile(tempFile, []byte(s), 0755) - if err != nil { - t.Fatal(err) - } - value, err = getCgroupParamUint(tempDir, cgroupFile) - if err != nil { - t.Fatal(err) - } else if value != 0 { - t.Fatalf("Expected %d to equal %d", value, 0) - } - - // Not a float. - err = ioutil.WriteFile(tempFile, []byte("not-a-float"), 0755) - if err != nil { - t.Fatal(err) - } - _, err = getCgroupParamUint(tempDir, cgroupFile) - if err == nil { - t.Fatal("Expecting error, got none") - } - - // Unknown file. - err = os.Remove(tempFile) - if err != nil { - t.Fatal(err) - } - _, err = getCgroupParamUint(tempDir, cgroupFile) - if err == nil { - t.Fatal("Expecting error, got none") - } -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_nosystemd.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_nosystemd.go deleted file mode 100644 index fa3485f1..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_nosystemd.go +++ /dev/null @@ -1,51 +0,0 @@ -// +build !linux - -package systemd - -import ( - "fmt" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -type Manager struct { - Cgroups *configs.Cgroup - Paths map[string]string -} - -func UseSystemd() bool { - return false -} - -func (m *Manager) Apply(pid int) error { - return fmt.Errorf("Systemd not supported") -} - -func (m *Manager) GetPids() ([]int, error) { - return nil, fmt.Errorf("Systemd not supported") -} - -func (m *Manager) Destroy() error { - return fmt.Errorf("Systemd not supported") -} - -func (m *Manager) GetPaths() map[string]string { - return nil -} - -func (m *Manager) GetStats() (*cgroups.Stats, error) { - return nil, fmt.Errorf("Systemd not supported") -} - -func (m *Manager) Set(container *configs.Config) error { - return nil, fmt.Errorf("Systemd not supported") -} - -func (m *Manager) Freeze(state configs.FreezerState) error { - return fmt.Errorf("Systemd not supported") -} - -func Freeze(c *configs.Cgroup, state configs.FreezerState) error { - return fmt.Errorf("Systemd not supported") -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_systemd.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_systemd.go deleted file mode 100644 index d878be9c..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_systemd.go +++ /dev/null @@ -1,616 +0,0 @@ -// +build linux - -package systemd - -import ( - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strconv" - "strings" - "sync" - "time" - - systemdDbus "github.com/coreos/go-systemd/dbus" - systemdUtil "github.com/coreos/go-systemd/util" - "github.com/godbus/dbus" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fs" - "github.com/opencontainers/runc/libcontainer/configs" -) - -type Manager struct { - mu sync.Mutex - Cgroups *configs.Cgroup - Paths map[string]string -} - -type subsystem interface { - // Returns the stats, as 'stats', corresponding to the cgroup under 'path'. - GetStats(path string, stats *cgroups.Stats) error - // Set the cgroup represented by cgroup. - Set(path string, cgroup *configs.Cgroup) error -} - -var subsystems = map[string]subsystem{ - "devices": &fs.DevicesGroup{}, - "memory": &fs.MemoryGroup{}, - "cpu": &fs.CpuGroup{}, - "cpuset": &fs.CpusetGroup{}, - "cpuacct": &fs.CpuacctGroup{}, - "blkio": &fs.BlkioGroup{}, - "hugetlb": &fs.HugetlbGroup{}, - "perf_event": &fs.PerfEventGroup{}, - "freezer": &fs.FreezerGroup{}, - "net_prio": &fs.NetPrioGroup{}, - "net_cls": &fs.NetClsGroup{}, - "name=systemd": &fs.NameGroup{}, -} - -const ( - testScopeWait = 4 -) - -var ( - connLock sync.Mutex - theConn *systemdDbus.Conn - hasStartTransientUnit bool - hasTransientDefaultDependencies bool -) - -func newProp(name string, units interface{}) systemdDbus.Property { - return systemdDbus.Property{ - Name: name, - Value: dbus.MakeVariant(units), - } -} - -func UseSystemd() bool { - if !systemdUtil.IsRunningSystemd() { - return false - } - - connLock.Lock() - defer connLock.Unlock() - - if theConn == nil { - var err error - theConn, err = systemdDbus.New() - if err != nil { - return false - } - - // Assume we have StartTransientUnit - hasStartTransientUnit = true - - // But if we get UnknownMethod error we don't - if _, err := theConn.StartTransientUnit("test.scope", "invalid", nil, nil); err != nil { - if dbusError, ok := err.(dbus.Error); ok { - if dbusError.Name == "org.freedesktop.DBus.Error.UnknownMethod" { - hasStartTransientUnit = false - return hasStartTransientUnit - } - } - } - - // Ensure the scope name we use doesn't exist. Use the Pid to - // avoid collisions between multiple libcontainer users on a - // single host. - scope := fmt.Sprintf("libcontainer-%d-systemd-test-default-dependencies.scope", os.Getpid()) - testScopeExists := true - for i := 0; i <= testScopeWait; i++ { - if _, err := theConn.StopUnit(scope, "replace", nil); err != nil { - if dbusError, ok := err.(dbus.Error); ok { - if strings.Contains(dbusError.Name, "org.freedesktop.systemd1.NoSuchUnit") { - testScopeExists = false - break - } - } - } - time.Sleep(time.Millisecond) - } - - // Bail out if we can't kill this scope without testing for DefaultDependencies - if testScopeExists { - return hasStartTransientUnit - } - - // Assume StartTransientUnit on a scope allows DefaultDependencies - hasTransientDefaultDependencies = true - ddf := newProp("DefaultDependencies", false) - if _, err := theConn.StartTransientUnit(scope, "replace", []systemdDbus.Property{ddf}, nil); err != nil { - if dbusError, ok := err.(dbus.Error); ok { - if strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.PropertyReadOnly") { - hasTransientDefaultDependencies = false - } - } - } - - // Not critical because of the stop unit logic above. - theConn.StopUnit(scope, "replace", nil) - } - return hasStartTransientUnit -} - -func getIfaceForUnit(unitName string) string { - if strings.HasSuffix(unitName, ".scope") { - return "Scope" - } - if strings.HasSuffix(unitName, ".service") { - return "Service" - } - return "Unit" -} - -func (m *Manager) Apply(pid int) error { - var ( - c = m.Cgroups - unitName = getUnitName(c) - slice = "system.slice" - properties []systemdDbus.Property - ) - - if c.Slice != "" { - slice = c.Slice - } - - properties = append(properties, - systemdDbus.PropSlice(slice), - systemdDbus.PropDescription("docker container "+c.Name), - newProp("PIDs", []uint32{uint32(pid)}), - ) - - // Always enable accounting, this gets us the same behaviour as the fs implementation, - // plus the kernel has some problems with joining the memory cgroup at a later time. - properties = append(properties, - newProp("MemoryAccounting", true), - newProp("CPUAccounting", true), - newProp("BlockIOAccounting", true)) - - if hasTransientDefaultDependencies { - properties = append(properties, - newProp("DefaultDependencies", false)) - } - - if c.Memory != 0 { - properties = append(properties, - newProp("MemoryLimit", uint64(c.Memory))) - } - - if c.CpuShares != 0 { - properties = append(properties, - newProp("CPUShares", uint64(c.CpuShares))) - } - - if c.BlkioWeight != 0 { - properties = append(properties, - newProp("BlockIOWeight", uint64(c.BlkioWeight))) - } - - // We need to set kernel memory before processes join cgroup because - // kmem.limit_in_bytes can only be set when the cgroup is empty. - // And swap memory limit needs to be set after memory limit, only - // memory limit is handled by systemd, so it's kind of ugly here. - if c.KernelMemory > 0 { - if err := setKernelMemory(c); err != nil { - return err - } - } - - if _, err := theConn.StartTransientUnit(unitName, "replace", properties, nil); err != nil { - return err - } - - if err := joinDevices(c, pid); err != nil { - return err - } - - // TODO: CpuQuota and CpuPeriod not available in systemd - // we need to manually join the cpu.cfs_quota_us and cpu.cfs_period_us - if err := joinCpu(c, pid); err != nil { - return err - } - - // TODO: MemoryReservation and MemorySwap not available in systemd - if err := joinMemory(c, pid); err != nil { - return err - } - - // we need to manually join the freezer, net_cls, net_prio and cpuset cgroup in systemd - // because it does not currently support it via the dbus api. - if err := joinFreezer(c, pid); err != nil { - return err - } - - if err := joinNetPrio(c, pid); err != nil { - return err - } - if err := joinNetCls(c, pid); err != nil { - return err - } - - if err := joinCpuset(c, pid); err != nil { - return err - } - - if err := joinHugetlb(c, pid); err != nil { - return err - } - - if err := joinPerfEvent(c, pid); err != nil { - return err - } - // FIXME: Systemd does have `BlockIODeviceWeight` property, but we got problem - // using that (at least on systemd 208, see https://github.com/opencontainers/runc/libcontainer/pull/354), - // so use fs work around for now. - if err := joinBlkio(c, pid); err != nil { - return err - } - - paths := make(map[string]string) - for sysname := range subsystems { - subsystemPath, err := getSubsystemPath(m.Cgroups, sysname) - if err != nil { - // Don't fail if a cgroup hierarchy was not found, just skip this subsystem - if cgroups.IsNotFound(err) { - continue - } - return err - } - paths[sysname] = subsystemPath - } - m.Paths = paths - - if paths["cpu"] != "" { - if err := fs.CheckCpushares(paths["cpu"], c.CpuShares); err != nil { - return err - } - } - - return nil -} - -func (m *Manager) Destroy() error { - m.mu.Lock() - defer m.mu.Unlock() - theConn.StopUnit(getUnitName(m.Cgroups), "replace", nil) - if err := cgroups.RemovePaths(m.Paths); err != nil { - return err - } - m.Paths = make(map[string]string) - return nil -} - -func (m *Manager) GetPaths() map[string]string { - m.mu.Lock() - paths := m.Paths - m.mu.Unlock() - return paths -} - -func writeFile(dir, file, data string) error { - // Normally dir should not be empty, one case is that cgroup subsystem - // is not mounted, we will get empty dir, and we want it fail here. - if dir == "" { - return fmt.Errorf("no such directory for %s.", file) - } - return ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700) -} - -func join(c *configs.Cgroup, subsystem string, pid int) (string, error) { - path, err := getSubsystemPath(c, subsystem) - if err != nil { - return "", err - } - if err := os.MkdirAll(path, 0755); err != nil { - return "", err - } - if err := writeFile(path, "cgroup.procs", strconv.Itoa(pid)); err != nil { - return "", err - } - - return path, nil -} - -func joinCpu(c *configs.Cgroup, pid int) error { - path, err := getSubsystemPath(c, "cpu") - if err != nil && !cgroups.IsNotFound(err) { - return err - } - if c.CpuQuota != 0 { - if err = writeFile(path, "cpu.cfs_quota_us", strconv.FormatInt(c.CpuQuota, 10)); err != nil { - return err - } - } - if c.CpuPeriod != 0 { - if err = writeFile(path, "cpu.cfs_period_us", strconv.FormatInt(c.CpuPeriod, 10)); err != nil { - return err - } - } - if c.CpuRtPeriod != 0 { - if err = writeFile(path, "cpu.rt_period_us", strconv.FormatInt(c.CpuRtPeriod, 10)); err != nil { - return err - } - } - if c.CpuRtRuntime != 0 { - if err = writeFile(path, "cpu.rt_runtime_us", strconv.FormatInt(c.CpuRtRuntime, 10)); err != nil { - return err - } - } - - return nil -} - -func joinFreezer(c *configs.Cgroup, pid int) error { - path, err := join(c, "freezer", pid) - if err != nil && !cgroups.IsNotFound(err) { - return err - } - - freezer := subsystems["freezer"] - return freezer.Set(path, c) -} - -func joinNetPrio(c *configs.Cgroup, pid int) error { - path, err := join(c, "net_prio", pid) - if err != nil && !cgroups.IsNotFound(err) { - return err - } - netPrio := subsystems["net_prio"] - - return netPrio.Set(path, c) -} - -func joinNetCls(c *configs.Cgroup, pid int) error { - path, err := join(c, "net_cls", pid) - if err != nil && !cgroups.IsNotFound(err) { - return err - } - netcls := subsystems["net_cls"] - - return netcls.Set(path, c) -} - -func getSubsystemPath(c *configs.Cgroup, subsystem string) (string, error) { - mountpoint, err := cgroups.FindCgroupMountpoint(subsystem) - if err != nil { - return "", err - } - - initPath, err := cgroups.GetInitCgroupDir(subsystem) - if err != nil { - return "", err - } - - slice := "system.slice" - if c.Slice != "" { - slice = c.Slice - } - - return filepath.Join(mountpoint, initPath, slice, getUnitName(c)), nil -} - -func (m *Manager) Freeze(state configs.FreezerState) error { - path, err := getSubsystemPath(m.Cgroups, "freezer") - if err != nil { - return err - } - - prevState := m.Cgroups.Freezer - m.Cgroups.Freezer = state - - freezer := subsystems["freezer"] - err = freezer.Set(path, m.Cgroups) - if err != nil { - m.Cgroups.Freezer = prevState - return err - } - - return nil -} - -func (m *Manager) GetPids() ([]int, error) { - path, err := getSubsystemPath(m.Cgroups, "devices") - if err != nil { - return nil, err - } - return cgroups.GetPids(path) -} - -func (m *Manager) GetStats() (*cgroups.Stats, error) { - m.mu.Lock() - defer m.mu.Unlock() - stats := cgroups.NewStats() - for name, path := range m.Paths { - sys, ok := subsystems[name] - if !ok || !cgroups.PathExists(path) { - continue - } - if err := sys.GetStats(path, stats); err != nil { - return nil, err - } - } - - return stats, nil -} - -func (m *Manager) Set(container *configs.Config) error { - for name, path := range m.Paths { - sys, ok := subsystems[name] - if !ok || !cgroups.PathExists(path) { - continue - } - if err := sys.Set(path, container.Cgroups); err != nil { - return err - } - } - - return nil -} - -func getUnitName(c *configs.Cgroup) string { - return fmt.Sprintf("%s-%s.scope", c.Parent, c.Name) -} - -// Atm we can't use the systemd device support because of two missing things: -// * Support for wildcards to allow mknod on any device -// * Support for wildcards to allow /dev/pts support -// -// The second is available in more recent systemd as "char-pts", but not in e.g. v208 which is -// in wide use. When both these are available we will be able to switch, but need to keep the old -// implementation for backwards compat. -// -// Note: we can't use systemd to set up the initial limits, and then change the cgroup -// because systemd will re-write the device settings if it needs to re-apply the cgroup context. -// This happens at least for v208 when any sibling unit is started. -func joinDevices(c *configs.Cgroup, pid int) error { - path, err := join(c, "devices", pid) - // Even if it's `not found` error, we'll return err because devices cgroup - // is hard requirement for container security. - if err != nil { - return err - } - - devices := subsystems["devices"] - return devices.Set(path, c) -} - -func setKernelMemory(c *configs.Cgroup) error { - path, err := getSubsystemPath(c, "memory") - if err != nil && !cgroups.IsNotFound(err) { - return err - } - - if err := os.MkdirAll(path, 0755); err != nil { - return err - } - - if c.KernelMemory > 0 { - err = writeFile(path, "memory.kmem.limit_in_bytes", strconv.FormatInt(c.KernelMemory, 10)) - if err != nil { - return err - } - } - - return nil -} - -func joinMemory(c *configs.Cgroup, pid int) error { - path, err := getSubsystemPath(c, "memory") - if err != nil && !cgroups.IsNotFound(err) { - return err - } - - // -1 disables memoryswap - if c.MemorySwap > 0 { - err = writeFile(path, "memory.memsw.limit_in_bytes", strconv.FormatInt(c.MemorySwap, 10)) - if err != nil { - return err - } - } - if c.MemoryReservation > 0 { - err = writeFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(c.MemoryReservation, 10)) - if err != nil { - return err - } - } - if c.OomKillDisable { - if err := writeFile(path, "memory.oom_control", "1"); err != nil { - return err - } - } - - if c.MemorySwappiness >= 0 && c.MemorySwappiness <= 100 { - err = writeFile(path, "memory.swappiness", strconv.FormatInt(c.MemorySwappiness, 10)) - if err != nil { - return err - } - } else if c.MemorySwappiness == -1 { - return nil - } else { - return fmt.Errorf("invalid value:%d. valid memory swappiness range is 0-100", c.MemorySwappiness) - } - - return nil -} - -// systemd does not atm set up the cpuset controller, so we must manually -// join it. Additionally that is a very finicky controller where each -// level must have a full setup as the default for a new directory is "no cpus" -func joinCpuset(c *configs.Cgroup, pid int) error { - path, err := getSubsystemPath(c, "cpuset") - if err != nil && !cgroups.IsNotFound(err) { - return err - } - - s := &fs.CpusetGroup{} - - return s.ApplyDir(path, c, pid) -} - -// `BlockIODeviceWeight` property of systemd does not work properly, and systemd -// expects device path instead of major minor numbers, which is also confusing -// for users. So we use fs work around for now. -func joinBlkio(c *configs.Cgroup, pid int) error { - path, err := getSubsystemPath(c, "blkio") - if err != nil { - return err - } - // systemd doesn't directly support this in the dbus properties - if c.BlkioLeafWeight != 0 { - if err := writeFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(c.BlkioLeafWeight), 10)); err != nil { - return err - } - } - for _, wd := range c.BlkioWeightDevice { - if err := writeFile(path, "blkio.weight_device", wd.WeightString()); err != nil { - return err - } - if err := writeFile(path, "blkio.leaf_weight_device", wd.LeafWeightString()); err != nil { - return err - } - } - for _, td := range c.BlkioThrottleReadBpsDevice { - if err := writeFile(path, "blkio.throttle.read_bps_device", td.String()); err != nil { - return err - } - } - for _, td := range c.BlkioThrottleWriteBpsDevice { - if err := writeFile(path, "blkio.throttle.write_bps_device", td.String()); err != nil { - return err - } - } - for _, td := range c.BlkioThrottleReadIOPSDevice { - if err := writeFile(path, "blkio.throttle.read_iops_device", td.String()); err != nil { - return err - } - } - for _, td := range c.BlkioThrottleWriteIOPSDevice { - if err := writeFile(path, "blkio.throttle.write_iops_device", td.String()); err != nil { - return err - } - } - - return nil -} - -func joinHugetlb(c *configs.Cgroup, pid int) error { - path, err := join(c, "hugetlb", pid) - if err != nil && !cgroups.IsNotFound(err) { - return err - } - - hugetlb := subsystems["hugetlb"] - return hugetlb.Set(path, c) -} - -func joinPerfEvent(c *configs.Cgroup, pid int) error { - path, err := join(c, "perf_event", pid) - if err != nil && !cgroups.IsNotFound(err) { - return err - } - - perfEvent := subsystems["perf_event"] - return perfEvent.Set(path, c) -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/validate/config.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/validate/config.go deleted file mode 100644 index 848a67c3..00000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/configs/validate/config.go +++ /dev/null @@ -1,93 +0,0 @@ -package validate - -import ( - "fmt" - "os" - "path/filepath" - - "github.com/opencontainers/runc/libcontainer/configs" -) - -type Validator interface { - Validate(*configs.Config) error -} - -func New() Validator { - return &ConfigValidator{} -} - -type ConfigValidator struct { -} - -func (v *ConfigValidator) Validate(config *configs.Config) error { - if err := v.rootfs(config); err != nil { - return err - } - if err := v.network(config); err != nil { - return err - } - if err := v.hostname(config); err != nil { - return err - } - if err := v.security(config); err != nil { - return err - } - if err := v.usernamespace(config); err != nil { - return err - } - return nil -} - -// rootfs validates the the rootfs is an absolute path and is not a symlink -// to the container's root filesystem. -func (v *ConfigValidator) rootfs(config *configs.Config) error { - cleaned, err := filepath.Abs(config.Rootfs) - if err != nil { - return err - } - if cleaned, err = filepath.EvalSymlinks(cleaned); err != nil { - return err - } - if config.Rootfs != cleaned { - return fmt.Errorf("%s is not an absolute path or is a symlink", config.Rootfs) - } - return nil -} - -func (v *ConfigValidator) network(config *configs.Config) error { - if !config.Namespaces.Contains(configs.NEWNET) { - if len(config.Networks) > 0 || len(config.Routes) > 0 { - return fmt.Errorf("unable to apply network settings without a private NET namespace") - } - } - return nil -} - -func (v *ConfigValidator) hostname(config *configs.Config) error { - if config.Hostname != "" && !config.Namespaces.Contains(configs.NEWUTS) { - return fmt.Errorf("unable to set hostname without a private UTS namespace") - } - return nil -} - -func (v *ConfigValidator) security(config *configs.Config) error { - // restrict sys without mount namespace - if (len(config.MaskPaths) > 0 || len(config.ReadonlyPaths) > 0) && - !config.Namespaces.Contains(configs.NEWNS) { - return fmt.Errorf("unable to restrict sys entries without a private MNT namespace") - } - return nil -} - -func (v *ConfigValidator) usernamespace(config *configs.Config) error { - if config.Namespaces.Contains(configs.NEWUSER) { - if _, err := os.Stat("/proc/self/ns/user"); os.IsNotExist(err) { - return fmt.Errorf("USER namespaces aren't enabled in the kernel") - } - } else { - if config.UidMappings != nil || config.GidMappings != nil { - return fmt.Errorf("User namespace mappings specified, but USER namespace isn't enabled in the config") - } - } - return nil -} diff --git a/vendor/google.golang.org/cloud/internal/datastore/datastore_v1.pb.go b/vendor/google.golang.org/cloud/internal/datastore/datastore_v1.pb.go deleted file mode 100644 index 9cb9be52..00000000 --- a/vendor/google.golang.org/cloud/internal/datastore/datastore_v1.pb.go +++ /dev/null @@ -1,1633 +0,0 @@ -// Code generated by protoc-gen-go. -// source: datastore_v1.proto -// DO NOT EDIT! - -/* -Package datastore is a generated protocol buffer package. - -It is generated from these files: - datastore_v1.proto - -It has these top-level messages: - PartitionId - Key - Value - Property - Entity - EntityResult - Query - KindExpression - PropertyReference - PropertyExpression - PropertyOrder - Filter - CompositeFilter - PropertyFilter - GqlQuery - GqlQueryArg - QueryResultBatch - Mutation - MutationResult - ReadOptions - LookupRequest - LookupResponse - RunQueryRequest - RunQueryResponse - BeginTransactionRequest - BeginTransactionResponse - RollbackRequest - RollbackResponse - CommitRequest - CommitResponse - AllocateIdsRequest - AllocateIdsResponse -*/ -package datastore - -import proto "github.com/golang/protobuf/proto" -import math "math" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = math.Inf - -// Specifies what data the 'entity' field contains. -// A ResultType is either implied (for example, in LookupResponse.found it -// is always FULL) or specified by context (for example, in message -// QueryResultBatch, field 'entity_result_type' specifies a ResultType -// for all the values in field 'entity_result'). -type EntityResult_ResultType int32 - -const ( - EntityResult_FULL EntityResult_ResultType = 1 - EntityResult_PROJECTION EntityResult_ResultType = 2 - // The entity may have no key. - // A property value may have meaning 18. - EntityResult_KEY_ONLY EntityResult_ResultType = 3 -) - -var EntityResult_ResultType_name = map[int32]string{ - 1: "FULL", - 2: "PROJECTION", - 3: "KEY_ONLY", -} -var EntityResult_ResultType_value = map[string]int32{ - "FULL": 1, - "PROJECTION": 2, - "KEY_ONLY": 3, -} - -func (x EntityResult_ResultType) Enum() *EntityResult_ResultType { - p := new(EntityResult_ResultType) - *p = x - return p -} -func (x EntityResult_ResultType) String() string { - return proto.EnumName(EntityResult_ResultType_name, int32(x)) -} -func (x *EntityResult_ResultType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(EntityResult_ResultType_value, data, "EntityResult_ResultType") - if err != nil { - return err - } - *x = EntityResult_ResultType(value) - return nil -} - -type PropertyExpression_AggregationFunction int32 - -const ( - PropertyExpression_FIRST PropertyExpression_AggregationFunction = 1 -) - -var PropertyExpression_AggregationFunction_name = map[int32]string{ - 1: "FIRST", -} -var PropertyExpression_AggregationFunction_value = map[string]int32{ - "FIRST": 1, -} - -func (x PropertyExpression_AggregationFunction) Enum() *PropertyExpression_AggregationFunction { - p := new(PropertyExpression_AggregationFunction) - *p = x - return p -} -func (x PropertyExpression_AggregationFunction) String() string { - return proto.EnumName(PropertyExpression_AggregationFunction_name, int32(x)) -} -func (x *PropertyExpression_AggregationFunction) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(PropertyExpression_AggregationFunction_value, data, "PropertyExpression_AggregationFunction") - if err != nil { - return err - } - *x = PropertyExpression_AggregationFunction(value) - return nil -} - -type PropertyOrder_Direction int32 - -const ( - PropertyOrder_ASCENDING PropertyOrder_Direction = 1 - PropertyOrder_DESCENDING PropertyOrder_Direction = 2 -) - -var PropertyOrder_Direction_name = map[int32]string{ - 1: "ASCENDING", - 2: "DESCENDING", -} -var PropertyOrder_Direction_value = map[string]int32{ - "ASCENDING": 1, - "DESCENDING": 2, -} - -func (x PropertyOrder_Direction) Enum() *PropertyOrder_Direction { - p := new(PropertyOrder_Direction) - *p = x - return p -} -func (x PropertyOrder_Direction) String() string { - return proto.EnumName(PropertyOrder_Direction_name, int32(x)) -} -func (x *PropertyOrder_Direction) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(PropertyOrder_Direction_value, data, "PropertyOrder_Direction") - if err != nil { - return err - } - *x = PropertyOrder_Direction(value) - return nil -} - -type CompositeFilter_Operator int32 - -const ( - CompositeFilter_AND CompositeFilter_Operator = 1 -) - -var CompositeFilter_Operator_name = map[int32]string{ - 1: "AND", -} -var CompositeFilter_Operator_value = map[string]int32{ - "AND": 1, -} - -func (x CompositeFilter_Operator) Enum() *CompositeFilter_Operator { - p := new(CompositeFilter_Operator) - *p = x - return p -} -func (x CompositeFilter_Operator) String() string { - return proto.EnumName(CompositeFilter_Operator_name, int32(x)) -} -func (x *CompositeFilter_Operator) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(CompositeFilter_Operator_value, data, "CompositeFilter_Operator") - if err != nil { - return err - } - *x = CompositeFilter_Operator(value) - return nil -} - -type PropertyFilter_Operator int32 - -const ( - PropertyFilter_LESS_THAN PropertyFilter_Operator = 1 - PropertyFilter_LESS_THAN_OR_EQUAL PropertyFilter_Operator = 2 - PropertyFilter_GREATER_THAN PropertyFilter_Operator = 3 - PropertyFilter_GREATER_THAN_OR_EQUAL PropertyFilter_Operator = 4 - PropertyFilter_EQUAL PropertyFilter_Operator = 5 - PropertyFilter_HAS_ANCESTOR PropertyFilter_Operator = 11 -) - -var PropertyFilter_Operator_name = map[int32]string{ - 1: "LESS_THAN", - 2: "LESS_THAN_OR_EQUAL", - 3: "GREATER_THAN", - 4: "GREATER_THAN_OR_EQUAL", - 5: "EQUAL", - 11: "HAS_ANCESTOR", -} -var PropertyFilter_Operator_value = map[string]int32{ - "LESS_THAN": 1, - "LESS_THAN_OR_EQUAL": 2, - "GREATER_THAN": 3, - "GREATER_THAN_OR_EQUAL": 4, - "EQUAL": 5, - "HAS_ANCESTOR": 11, -} - -func (x PropertyFilter_Operator) Enum() *PropertyFilter_Operator { - p := new(PropertyFilter_Operator) - *p = x - return p -} -func (x PropertyFilter_Operator) String() string { - return proto.EnumName(PropertyFilter_Operator_name, int32(x)) -} -func (x *PropertyFilter_Operator) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(PropertyFilter_Operator_value, data, "PropertyFilter_Operator") - if err != nil { - return err - } - *x = PropertyFilter_Operator(value) - return nil -} - -// The possible values for the 'more_results' field. -type QueryResultBatch_MoreResultsType int32 - -const ( - QueryResultBatch_NOT_FINISHED QueryResultBatch_MoreResultsType = 1 - QueryResultBatch_MORE_RESULTS_AFTER_LIMIT QueryResultBatch_MoreResultsType = 2 - // results after the limit. - QueryResultBatch_NO_MORE_RESULTS QueryResultBatch_MoreResultsType = 3 -) - -var QueryResultBatch_MoreResultsType_name = map[int32]string{ - 1: "NOT_FINISHED", - 2: "MORE_RESULTS_AFTER_LIMIT", - 3: "NO_MORE_RESULTS", -} -var QueryResultBatch_MoreResultsType_value = map[string]int32{ - "NOT_FINISHED": 1, - "MORE_RESULTS_AFTER_LIMIT": 2, - "NO_MORE_RESULTS": 3, -} - -func (x QueryResultBatch_MoreResultsType) Enum() *QueryResultBatch_MoreResultsType { - p := new(QueryResultBatch_MoreResultsType) - *p = x - return p -} -func (x QueryResultBatch_MoreResultsType) String() string { - return proto.EnumName(QueryResultBatch_MoreResultsType_name, int32(x)) -} -func (x *QueryResultBatch_MoreResultsType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(QueryResultBatch_MoreResultsType_value, data, "QueryResultBatch_MoreResultsType") - if err != nil { - return err - } - *x = QueryResultBatch_MoreResultsType(value) - return nil -} - -type ReadOptions_ReadConsistency int32 - -const ( - ReadOptions_DEFAULT ReadOptions_ReadConsistency = 0 - ReadOptions_STRONG ReadOptions_ReadConsistency = 1 - ReadOptions_EVENTUAL ReadOptions_ReadConsistency = 2 -) - -var ReadOptions_ReadConsistency_name = map[int32]string{ - 0: "DEFAULT", - 1: "STRONG", - 2: "EVENTUAL", -} -var ReadOptions_ReadConsistency_value = map[string]int32{ - "DEFAULT": 0, - "STRONG": 1, - "EVENTUAL": 2, -} - -func (x ReadOptions_ReadConsistency) Enum() *ReadOptions_ReadConsistency { - p := new(ReadOptions_ReadConsistency) - *p = x - return p -} -func (x ReadOptions_ReadConsistency) String() string { - return proto.EnumName(ReadOptions_ReadConsistency_name, int32(x)) -} -func (x *ReadOptions_ReadConsistency) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(ReadOptions_ReadConsistency_value, data, "ReadOptions_ReadConsistency") - if err != nil { - return err - } - *x = ReadOptions_ReadConsistency(value) - return nil -} - -type BeginTransactionRequest_IsolationLevel int32 - -const ( - BeginTransactionRequest_SNAPSHOT BeginTransactionRequest_IsolationLevel = 0 - // conflict if their mutations conflict. For example: - // Read(A),Write(B) may not conflict with Read(B),Write(A), - // but Read(B),Write(B) does conflict with Read(B),Write(B). - BeginTransactionRequest_SERIALIZABLE BeginTransactionRequest_IsolationLevel = 1 -) - -var BeginTransactionRequest_IsolationLevel_name = map[int32]string{ - 0: "SNAPSHOT", - 1: "SERIALIZABLE", -} -var BeginTransactionRequest_IsolationLevel_value = map[string]int32{ - "SNAPSHOT": 0, - "SERIALIZABLE": 1, -} - -func (x BeginTransactionRequest_IsolationLevel) Enum() *BeginTransactionRequest_IsolationLevel { - p := new(BeginTransactionRequest_IsolationLevel) - *p = x - return p -} -func (x BeginTransactionRequest_IsolationLevel) String() string { - return proto.EnumName(BeginTransactionRequest_IsolationLevel_name, int32(x)) -} -func (x *BeginTransactionRequest_IsolationLevel) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(BeginTransactionRequest_IsolationLevel_value, data, "BeginTransactionRequest_IsolationLevel") - if err != nil { - return err - } - *x = BeginTransactionRequest_IsolationLevel(value) - return nil -} - -type CommitRequest_Mode int32 - -const ( - CommitRequest_TRANSACTIONAL CommitRequest_Mode = 1 - CommitRequest_NON_TRANSACTIONAL CommitRequest_Mode = 2 -) - -var CommitRequest_Mode_name = map[int32]string{ - 1: "TRANSACTIONAL", - 2: "NON_TRANSACTIONAL", -} -var CommitRequest_Mode_value = map[string]int32{ - "TRANSACTIONAL": 1, - "NON_TRANSACTIONAL": 2, -} - -func (x CommitRequest_Mode) Enum() *CommitRequest_Mode { - p := new(CommitRequest_Mode) - *p = x - return p -} -func (x CommitRequest_Mode) String() string { - return proto.EnumName(CommitRequest_Mode_name, int32(x)) -} -func (x *CommitRequest_Mode) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(CommitRequest_Mode_value, data, "CommitRequest_Mode") - if err != nil { - return err - } - *x = CommitRequest_Mode(value) - return nil -} - -// An identifier for a particular subset of entities. -// -// Entities are partitioned into various subsets, each used by different -// datasets and different namespaces within a dataset and so forth. -// -// All input partition IDs are normalized before use. -// A partition ID is normalized as follows: -// If the partition ID is unset or is set to an empty partition ID, replace it -// with the context partition ID. -// Otherwise, if the partition ID has no dataset ID, assign it the context -// partition ID's dataset ID. -// Unless otherwise documented, the context partition ID has the dataset ID set -// to the context dataset ID and no other partition dimension set. -// -// A partition ID is empty if all of its fields are unset. -// -// Partition dimension: -// A dimension may be unset. -// A dimension's value must never be "". -// A dimension's value must match [A-Za-z\d\.\-_]{1,100} -// If the value of any dimension matches regex "__.*__", -// the partition is reserved/read-only. -// A reserved/read-only partition ID is forbidden in certain documented contexts. -// -// Dataset ID: -// A dataset id's value must never be "". -// A dataset id's value must match -// ([a-z\d\-]{1,100}~)?([a-z\d][a-z\d\-\.]{0,99}:)?([a-z\d][a-z\d\-]{0,99} -type PartitionId struct { - // The dataset ID. - DatasetId *string `protobuf:"bytes,3,opt,name=dataset_id" json:"dataset_id,omitempty"` - // The namespace. - Namespace *string `protobuf:"bytes,4,opt,name=namespace" json:"namespace,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *PartitionId) Reset() { *m = PartitionId{} } -func (m *PartitionId) String() string { return proto.CompactTextString(m) } -func (*PartitionId) ProtoMessage() {} - -func (m *PartitionId) GetDatasetId() string { - if m != nil && m.DatasetId != nil { - return *m.DatasetId - } - return "" -} - -func (m *PartitionId) GetNamespace() string { - if m != nil && m.Namespace != nil { - return *m.Namespace - } - return "" -} - -// A unique identifier for an entity. -// If a key's partition id or any of its path kinds or names are -// reserved/read-only, the key is reserved/read-only. -// A reserved/read-only key is forbidden in certain documented contexts. -type Key struct { - // Entities are partitioned into subsets, currently identified by a dataset - // (usually implicitly specified by the project) and namespace ID. - // Queries are scoped to a single partition. - PartitionId *PartitionId `protobuf:"bytes,1,opt,name=partition_id" json:"partition_id,omitempty"` - // The entity path. - // An entity path consists of one or more elements composed of a kind and a - // string or numerical identifier, which identify entities. The first - // element identifies a root entity, the second element identifies - // a child of the root entity, the third element a child of the - // second entity, and so forth. The entities identified by all prefixes of - // the path are called the element's ancestors. - // An entity path is always fully complete: ALL of the entity's ancestors - // are required to be in the path along with the entity identifier itself. - // The only exception is that in some documented cases, the identifier in the - // last path element (for the entity) itself may be omitted. A path can never - // be empty. - PathElement []*Key_PathElement `protobuf:"bytes,2,rep,name=path_element" json:"path_element,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Key) Reset() { *m = Key{} } -func (m *Key) String() string { return proto.CompactTextString(m) } -func (*Key) ProtoMessage() {} - -func (m *Key) GetPartitionId() *PartitionId { - if m != nil { - return m.PartitionId - } - return nil -} - -func (m *Key) GetPathElement() []*Key_PathElement { - if m != nil { - return m.PathElement - } - return nil -} - -// A (kind, ID/name) pair used to construct a key path. -// -// At most one of name or ID may be set. -// If either is set, the element is complete. -// If neither is set, the element is incomplete. -type Key_PathElement struct { - // The kind of the entity. - // A kind matching regex "__.*__" is reserved/read-only. - // A kind must not contain more than 500 characters. - // Cannot be "". - Kind *string `protobuf:"bytes,1,req,name=kind" json:"kind,omitempty"` - // The ID of the entity. - // Never equal to zero. Values less than zero are discouraged and will not - // be supported in the future. - Id *int64 `protobuf:"varint,2,opt,name=id" json:"id,omitempty"` - // The name of the entity. - // A name matching regex "__.*__" is reserved/read-only. - // A name must not be more than 500 characters. - // Cannot be "". - Name *string `protobuf:"bytes,3,opt,name=name" json:"name,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Key_PathElement) Reset() { *m = Key_PathElement{} } -func (m *Key_PathElement) String() string { return proto.CompactTextString(m) } -func (*Key_PathElement) ProtoMessage() {} - -func (m *Key_PathElement) GetKind() string { - if m != nil && m.Kind != nil { - return *m.Kind - } - return "" -} - -func (m *Key_PathElement) GetId() int64 { - if m != nil && m.Id != nil { - return *m.Id - } - return 0 -} - -func (m *Key_PathElement) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -// A message that can hold any of the supported value types and associated -// metadata. -// -// At most one of the Value fields may be set. -// If none are set the value is "null". -// -type Value struct { - // A boolean value. - BooleanValue *bool `protobuf:"varint,1,opt,name=boolean_value" json:"boolean_value,omitempty"` - // An integer value. - IntegerValue *int64 `protobuf:"varint,2,opt,name=integer_value" json:"integer_value,omitempty"` - // A double value. - DoubleValue *float64 `protobuf:"fixed64,3,opt,name=double_value" json:"double_value,omitempty"` - // A timestamp value. - TimestampMicrosecondsValue *int64 `protobuf:"varint,4,opt,name=timestamp_microseconds_value" json:"timestamp_microseconds_value,omitempty"` - // A key value. - KeyValue *Key `protobuf:"bytes,5,opt,name=key_value" json:"key_value,omitempty"` - // A blob key value. - BlobKeyValue *string `protobuf:"bytes,16,opt,name=blob_key_value" json:"blob_key_value,omitempty"` - // A UTF-8 encoded string value. - StringValue *string `protobuf:"bytes,17,opt,name=string_value" json:"string_value,omitempty"` - // A blob value. - BlobValue []byte `protobuf:"bytes,18,opt,name=blob_value" json:"blob_value,omitempty"` - // An entity value. - // May have no key. - // May have a key with an incomplete key path. - // May have a reserved/read-only key. - EntityValue *Entity `protobuf:"bytes,6,opt,name=entity_value" json:"entity_value,omitempty"` - // A list value. - // Cannot contain another list value. - // Cannot also have a meaning and indexing set. - ListValue []*Value `protobuf:"bytes,7,rep,name=list_value" json:"list_value,omitempty"` - // The meaning field is reserved and should not be used. - Meaning *int32 `protobuf:"varint,14,opt,name=meaning" json:"meaning,omitempty"` - // If the value should be indexed. - // - // The indexed property may be set for a - // null value. - // When indexed is true, stringValue - // is limited to 500 characters and the blob value is limited to 500 bytes. - // Exception: If meaning is set to 2, string_value is limited to 2038 - // characters regardless of indexed. - // When indexed is true, meaning 15 and 22 are not allowed, and meaning 16 - // will be ignored on input (and will never be set on output). - // Input values by default have indexed set to - // true; however, you can explicitly set indexed to - // true if you want. (An output value never has - // indexed explicitly set to true.) If a value is - // itself an entity, it cannot have indexed set to - // true. - // Exception: An entity value with meaning 9, 20 or 21 may be indexed. - Indexed *bool `protobuf:"varint,15,opt,name=indexed,def=1" json:"indexed,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Value) Reset() { *m = Value{} } -func (m *Value) String() string { return proto.CompactTextString(m) } -func (*Value) ProtoMessage() {} - -const Default_Value_Indexed bool = true - -func (m *Value) GetBooleanValue() bool { - if m != nil && m.BooleanValue != nil { - return *m.BooleanValue - } - return false -} - -func (m *Value) GetIntegerValue() int64 { - if m != nil && m.IntegerValue != nil { - return *m.IntegerValue - } - return 0 -} - -func (m *Value) GetDoubleValue() float64 { - if m != nil && m.DoubleValue != nil { - return *m.DoubleValue - } - return 0 -} - -func (m *Value) GetTimestampMicrosecondsValue() int64 { - if m != nil && m.TimestampMicrosecondsValue != nil { - return *m.TimestampMicrosecondsValue - } - return 0 -} - -func (m *Value) GetKeyValue() *Key { - if m != nil { - return m.KeyValue - } - return nil -} - -func (m *Value) GetBlobKeyValue() string { - if m != nil && m.BlobKeyValue != nil { - return *m.BlobKeyValue - } - return "" -} - -func (m *Value) GetStringValue() string { - if m != nil && m.StringValue != nil { - return *m.StringValue - } - return "" -} - -func (m *Value) GetBlobValue() []byte { - if m != nil { - return m.BlobValue - } - return nil -} - -func (m *Value) GetEntityValue() *Entity { - if m != nil { - return m.EntityValue - } - return nil -} - -func (m *Value) GetListValue() []*Value { - if m != nil { - return m.ListValue - } - return nil -} - -func (m *Value) GetMeaning() int32 { - if m != nil && m.Meaning != nil { - return *m.Meaning - } - return 0 -} - -func (m *Value) GetIndexed() bool { - if m != nil && m.Indexed != nil { - return *m.Indexed - } - return Default_Value_Indexed -} - -// An entity property. -type Property struct { - // The name of the property. - // A property name matching regex "__.*__" is reserved. - // A reserved property name is forbidden in certain documented contexts. - // The name must not contain more than 500 characters. - // Cannot be "". - Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"` - // The value(s) of the property. - // Each value can have only one value property populated. For example, - // you cannot have a values list of { value: { integerValue: 22, - // stringValue: "a" } }, but you can have { value: { listValue: - // [ { integerValue: 22 }, { stringValue: "a" } ] }. - Value *Value `protobuf:"bytes,4,req,name=value" json:"value,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Property) Reset() { *m = Property{} } -func (m *Property) String() string { return proto.CompactTextString(m) } -func (*Property) ProtoMessage() {} - -func (m *Property) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *Property) GetValue() *Value { - if m != nil { - return m.Value - } - return nil -} - -// An entity. -// -// An entity is limited to 1 megabyte when stored. That roughly -// corresponds to a limit of 1 megabyte for the serialized form of this -// message. -type Entity struct { - // The entity's key. - // - // An entity must have a key, unless otherwise documented (for example, - // an entity in Value.entityValue may have no key). - // An entity's kind is its key's path's last element's kind, - // or null if it has no key. - Key *Key `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` - // The entity's properties. - // Each property's name must be unique for its entity. - Property []*Property `protobuf:"bytes,2,rep,name=property" json:"property,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Entity) Reset() { *m = Entity{} } -func (m *Entity) String() string { return proto.CompactTextString(m) } -func (*Entity) ProtoMessage() {} - -func (m *Entity) GetKey() *Key { - if m != nil { - return m.Key - } - return nil -} - -func (m *Entity) GetProperty() []*Property { - if m != nil { - return m.Property - } - return nil -} - -// The result of fetching an entity from the datastore. -type EntityResult struct { - // The resulting entity. - Entity *Entity `protobuf:"bytes,1,req,name=entity" json:"entity,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *EntityResult) Reset() { *m = EntityResult{} } -func (m *EntityResult) String() string { return proto.CompactTextString(m) } -func (*EntityResult) ProtoMessage() {} - -func (m *EntityResult) GetEntity() *Entity { - if m != nil { - return m.Entity - } - return nil -} - -// A query. -type Query struct { - // The projection to return. If not set the entire entity is returned. - Projection []*PropertyExpression `protobuf:"bytes,2,rep,name=projection" json:"projection,omitempty"` - // The kinds to query (if empty, returns entities from all kinds). - Kind []*KindExpression `protobuf:"bytes,3,rep,name=kind" json:"kind,omitempty"` - // The filter to apply (optional). - Filter *Filter `protobuf:"bytes,4,opt,name=filter" json:"filter,omitempty"` - // The order to apply to the query results (if empty, order is unspecified). - Order []*PropertyOrder `protobuf:"bytes,5,rep,name=order" json:"order,omitempty"` - // The properties to group by (if empty, no grouping is applied to the - // result set). - GroupBy []*PropertyReference `protobuf:"bytes,6,rep,name=group_by" json:"group_by,omitempty"` - // A starting point for the query results. Optional. Query cursors are - // returned in query result batches. - StartCursor []byte `protobuf:"bytes,7,opt,name=start_cursor" json:"start_cursor,omitempty"` - // An ending point for the query results. Optional. Query cursors are - // returned in query result batches. - EndCursor []byte `protobuf:"bytes,8,opt,name=end_cursor" json:"end_cursor,omitempty"` - // The number of results to skip. Applies before limit, but after all other - // constraints (optional, defaults to 0). - Offset *int32 `protobuf:"varint,10,opt,name=offset,def=0" json:"offset,omitempty"` - // The maximum number of results to return. Applies after all other - // constraints. Optional. - Limit *int32 `protobuf:"varint,11,opt,name=limit" json:"limit,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Query) Reset() { *m = Query{} } -func (m *Query) String() string { return proto.CompactTextString(m) } -func (*Query) ProtoMessage() {} - -const Default_Query_Offset int32 = 0 - -func (m *Query) GetProjection() []*PropertyExpression { - if m != nil { - return m.Projection - } - return nil -} - -func (m *Query) GetKind() []*KindExpression { - if m != nil { - return m.Kind - } - return nil -} - -func (m *Query) GetFilter() *Filter { - if m != nil { - return m.Filter - } - return nil -} - -func (m *Query) GetOrder() []*PropertyOrder { - if m != nil { - return m.Order - } - return nil -} - -func (m *Query) GetGroupBy() []*PropertyReference { - if m != nil { - return m.GroupBy - } - return nil -} - -func (m *Query) GetStartCursor() []byte { - if m != nil { - return m.StartCursor - } - return nil -} - -func (m *Query) GetEndCursor() []byte { - if m != nil { - return m.EndCursor - } - return nil -} - -func (m *Query) GetOffset() int32 { - if m != nil && m.Offset != nil { - return *m.Offset - } - return Default_Query_Offset -} - -func (m *Query) GetLimit() int32 { - if m != nil && m.Limit != nil { - return *m.Limit - } - return 0 -} - -// A representation of a kind. -type KindExpression struct { - // The name of the kind. - Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *KindExpression) Reset() { *m = KindExpression{} } -func (m *KindExpression) String() string { return proto.CompactTextString(m) } -func (*KindExpression) ProtoMessage() {} - -func (m *KindExpression) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -// A reference to a property relative to the kind expressions. -// exactly. -type PropertyReference struct { - // The name of the property. - Name *string `protobuf:"bytes,2,req,name=name" json:"name,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *PropertyReference) Reset() { *m = PropertyReference{} } -func (m *PropertyReference) String() string { return proto.CompactTextString(m) } -func (*PropertyReference) ProtoMessage() {} - -func (m *PropertyReference) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -// A representation of a property in a projection. -type PropertyExpression struct { - // The property to project. - Property *PropertyReference `protobuf:"bytes,1,req,name=property" json:"property,omitempty"` - // The aggregation function to apply to the property. Optional. - // Can only be used when grouping by at least one property. Must - // then be set on all properties in the projection that are not - // being grouped by. - AggregationFunction *PropertyExpression_AggregationFunction `protobuf:"varint,2,opt,name=aggregation_function,enum=datastore.PropertyExpression_AggregationFunction" json:"aggregation_function,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *PropertyExpression) Reset() { *m = PropertyExpression{} } -func (m *PropertyExpression) String() string { return proto.CompactTextString(m) } -func (*PropertyExpression) ProtoMessage() {} - -func (m *PropertyExpression) GetProperty() *PropertyReference { - if m != nil { - return m.Property - } - return nil -} - -func (m *PropertyExpression) GetAggregationFunction() PropertyExpression_AggregationFunction { - if m != nil && m.AggregationFunction != nil { - return *m.AggregationFunction - } - return PropertyExpression_FIRST -} - -// The desired order for a specific property. -type PropertyOrder struct { - // The property to order by. - Property *PropertyReference `protobuf:"bytes,1,req,name=property" json:"property,omitempty"` - // The direction to order by. - Direction *PropertyOrder_Direction `protobuf:"varint,2,opt,name=direction,enum=datastore.PropertyOrder_Direction,def=1" json:"direction,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *PropertyOrder) Reset() { *m = PropertyOrder{} } -func (m *PropertyOrder) String() string { return proto.CompactTextString(m) } -func (*PropertyOrder) ProtoMessage() {} - -const Default_PropertyOrder_Direction PropertyOrder_Direction = PropertyOrder_ASCENDING - -func (m *PropertyOrder) GetProperty() *PropertyReference { - if m != nil { - return m.Property - } - return nil -} - -func (m *PropertyOrder) GetDirection() PropertyOrder_Direction { - if m != nil && m.Direction != nil { - return *m.Direction - } - return Default_PropertyOrder_Direction -} - -// A holder for any type of filter. Exactly one field should be specified. -type Filter struct { - // A composite filter. - CompositeFilter *CompositeFilter `protobuf:"bytes,1,opt,name=composite_filter" json:"composite_filter,omitempty"` - // A filter on a property. - PropertyFilter *PropertyFilter `protobuf:"bytes,2,opt,name=property_filter" json:"property_filter,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Filter) Reset() { *m = Filter{} } -func (m *Filter) String() string { return proto.CompactTextString(m) } -func (*Filter) ProtoMessage() {} - -func (m *Filter) GetCompositeFilter() *CompositeFilter { - if m != nil { - return m.CompositeFilter - } - return nil -} - -func (m *Filter) GetPropertyFilter() *PropertyFilter { - if m != nil { - return m.PropertyFilter - } - return nil -} - -// A filter that merges the multiple other filters using the given operation. -type CompositeFilter struct { - // The operator for combining multiple filters. - Operator *CompositeFilter_Operator `protobuf:"varint,1,req,name=operator,enum=datastore.CompositeFilter_Operator" json:"operator,omitempty"` - // The list of filters to combine. - // Must contain at least one filter. - Filter []*Filter `protobuf:"bytes,2,rep,name=filter" json:"filter,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *CompositeFilter) Reset() { *m = CompositeFilter{} } -func (m *CompositeFilter) String() string { return proto.CompactTextString(m) } -func (*CompositeFilter) ProtoMessage() {} - -func (m *CompositeFilter) GetOperator() CompositeFilter_Operator { - if m != nil && m.Operator != nil { - return *m.Operator - } - return CompositeFilter_AND -} - -func (m *CompositeFilter) GetFilter() []*Filter { - if m != nil { - return m.Filter - } - return nil -} - -// A filter on a specific property. -type PropertyFilter struct { - // The property to filter by. - Property *PropertyReference `protobuf:"bytes,1,req,name=property" json:"property,omitempty"` - // The operator to filter by. - Operator *PropertyFilter_Operator `protobuf:"varint,2,req,name=operator,enum=datastore.PropertyFilter_Operator" json:"operator,omitempty"` - // The value to compare the property to. - Value *Value `protobuf:"bytes,3,req,name=value" json:"value,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *PropertyFilter) Reset() { *m = PropertyFilter{} } -func (m *PropertyFilter) String() string { return proto.CompactTextString(m) } -func (*PropertyFilter) ProtoMessage() {} - -func (m *PropertyFilter) GetProperty() *PropertyReference { - if m != nil { - return m.Property - } - return nil -} - -func (m *PropertyFilter) GetOperator() PropertyFilter_Operator { - if m != nil && m.Operator != nil { - return *m.Operator - } - return PropertyFilter_LESS_THAN -} - -func (m *PropertyFilter) GetValue() *Value { - if m != nil { - return m.Value - } - return nil -} - -// A GQL query. -type GqlQuery struct { - QueryString *string `protobuf:"bytes,1,req,name=query_string" json:"query_string,omitempty"` - // When false, the query string must not contain a literal. - AllowLiteral *bool `protobuf:"varint,2,opt,name=allow_literal,def=0" json:"allow_literal,omitempty"` - // A named argument must set field GqlQueryArg.name. - // No two named arguments may have the same name. - // For each non-reserved named binding site in the query string, - // there must be a named argument with that name, - // but not necessarily the inverse. - NameArg []*GqlQueryArg `protobuf:"bytes,3,rep,name=name_arg" json:"name_arg,omitempty"` - // Numbered binding site @1 references the first numbered argument, - // effectively using 1-based indexing, rather than the usual 0. - // A numbered argument must NOT set field GqlQueryArg.name. - // For each binding site numbered i in query_string, - // there must be an ith numbered argument. - // The inverse must also be true. - NumberArg []*GqlQueryArg `protobuf:"bytes,4,rep,name=number_arg" json:"number_arg,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GqlQuery) Reset() { *m = GqlQuery{} } -func (m *GqlQuery) String() string { return proto.CompactTextString(m) } -func (*GqlQuery) ProtoMessage() {} - -const Default_GqlQuery_AllowLiteral bool = false - -func (m *GqlQuery) GetQueryString() string { - if m != nil && m.QueryString != nil { - return *m.QueryString - } - return "" -} - -func (m *GqlQuery) GetAllowLiteral() bool { - if m != nil && m.AllowLiteral != nil { - return *m.AllowLiteral - } - return Default_GqlQuery_AllowLiteral -} - -func (m *GqlQuery) GetNameArg() []*GqlQueryArg { - if m != nil { - return m.NameArg - } - return nil -} - -func (m *GqlQuery) GetNumberArg() []*GqlQueryArg { - if m != nil { - return m.NumberArg - } - return nil -} - -// A binding argument for a GQL query. -// Exactly one of fields value and cursor must be set. -type GqlQueryArg struct { - // Must match regex "[A-Za-z_$][A-Za-z_$0-9]*". - // Must not match regex "__.*__". - // Must not be "". - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - Value *Value `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` - Cursor []byte `protobuf:"bytes,3,opt,name=cursor" json:"cursor,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GqlQueryArg) Reset() { *m = GqlQueryArg{} } -func (m *GqlQueryArg) String() string { return proto.CompactTextString(m) } -func (*GqlQueryArg) ProtoMessage() {} - -func (m *GqlQueryArg) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *GqlQueryArg) GetValue() *Value { - if m != nil { - return m.Value - } - return nil -} - -func (m *GqlQueryArg) GetCursor() []byte { - if m != nil { - return m.Cursor - } - return nil -} - -// A batch of results produced by a query. -type QueryResultBatch struct { - // The result type for every entity in entityResults. - EntityResultType *EntityResult_ResultType `protobuf:"varint,1,req,name=entity_result_type,enum=datastore.EntityResult_ResultType" json:"entity_result_type,omitempty"` - // The results for this batch. - EntityResult []*EntityResult `protobuf:"bytes,2,rep,name=entity_result" json:"entity_result,omitempty"` - // A cursor that points to the position after the last result in the batch. - // May be absent. - EndCursor []byte `protobuf:"bytes,4,opt,name=end_cursor" json:"end_cursor,omitempty"` - // The state of the query after the current batch. - MoreResults *QueryResultBatch_MoreResultsType `protobuf:"varint,5,req,name=more_results,enum=datastore.QueryResultBatch_MoreResultsType" json:"more_results,omitempty"` - // The number of results skipped because of Query.offset. - SkippedResults *int32 `protobuf:"varint,6,opt,name=skipped_results" json:"skipped_results,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *QueryResultBatch) Reset() { *m = QueryResultBatch{} } -func (m *QueryResultBatch) String() string { return proto.CompactTextString(m) } -func (*QueryResultBatch) ProtoMessage() {} - -func (m *QueryResultBatch) GetEntityResultType() EntityResult_ResultType { - if m != nil && m.EntityResultType != nil { - return *m.EntityResultType - } - return EntityResult_FULL -} - -func (m *QueryResultBatch) GetEntityResult() []*EntityResult { - if m != nil { - return m.EntityResult - } - return nil -} - -func (m *QueryResultBatch) GetEndCursor() []byte { - if m != nil { - return m.EndCursor - } - return nil -} - -func (m *QueryResultBatch) GetMoreResults() QueryResultBatch_MoreResultsType { - if m != nil && m.MoreResults != nil { - return *m.MoreResults - } - return QueryResultBatch_NOT_FINISHED -} - -func (m *QueryResultBatch) GetSkippedResults() int32 { - if m != nil && m.SkippedResults != nil { - return *m.SkippedResults - } - return 0 -} - -// A set of changes to apply. -// -// No entity in this message may have a reserved property name, -// not even a property in an entity in a value. -// No value in this message may have meaning 18, -// not even a value in an entity in another value. -// -// If entities with duplicate keys are present, an arbitrary choice will -// be made as to which is written. -type Mutation struct { - // Entities to upsert. - // Each upserted entity's key must have a complete path and - // must not be reserved/read-only. - Upsert []*Entity `protobuf:"bytes,1,rep,name=upsert" json:"upsert,omitempty"` - // Entities to update. - // Each updated entity's key must have a complete path and - // must not be reserved/read-only. - Update []*Entity `protobuf:"bytes,2,rep,name=update" json:"update,omitempty"` - // Entities to insert. - // Each inserted entity's key must have a complete path and - // must not be reserved/read-only. - Insert []*Entity `protobuf:"bytes,3,rep,name=insert" json:"insert,omitempty"` - // Insert entities with a newly allocated ID. - // Each inserted entity's key must omit the final identifier in its path and - // must not be reserved/read-only. - InsertAutoId []*Entity `protobuf:"bytes,4,rep,name=insert_auto_id" json:"insert_auto_id,omitempty"` - // Keys of entities to delete. - // Each key must have a complete key path and must not be reserved/read-only. - Delete []*Key `protobuf:"bytes,5,rep,name=delete" json:"delete,omitempty"` - // Ignore a user specified read-only period. Optional. - Force *bool `protobuf:"varint,6,opt,name=force" json:"force,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Mutation) Reset() { *m = Mutation{} } -func (m *Mutation) String() string { return proto.CompactTextString(m) } -func (*Mutation) ProtoMessage() {} - -func (m *Mutation) GetUpsert() []*Entity { - if m != nil { - return m.Upsert - } - return nil -} - -func (m *Mutation) GetUpdate() []*Entity { - if m != nil { - return m.Update - } - return nil -} - -func (m *Mutation) GetInsert() []*Entity { - if m != nil { - return m.Insert - } - return nil -} - -func (m *Mutation) GetInsertAutoId() []*Entity { - if m != nil { - return m.InsertAutoId - } - return nil -} - -func (m *Mutation) GetDelete() []*Key { - if m != nil { - return m.Delete - } - return nil -} - -func (m *Mutation) GetForce() bool { - if m != nil && m.Force != nil { - return *m.Force - } - return false -} - -// The result of applying a mutation. -type MutationResult struct { - // Number of index writes. - IndexUpdates *int32 `protobuf:"varint,1,req,name=index_updates" json:"index_updates,omitempty"` - // Keys for insertAutoId entities. One per entity from the - // request, in the same order. - InsertAutoIdKey []*Key `protobuf:"bytes,2,rep,name=insert_auto_id_key" json:"insert_auto_id_key,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MutationResult) Reset() { *m = MutationResult{} } -func (m *MutationResult) String() string { return proto.CompactTextString(m) } -func (*MutationResult) ProtoMessage() {} - -func (m *MutationResult) GetIndexUpdates() int32 { - if m != nil && m.IndexUpdates != nil { - return *m.IndexUpdates - } - return 0 -} - -func (m *MutationResult) GetInsertAutoIdKey() []*Key { - if m != nil { - return m.InsertAutoIdKey - } - return nil -} - -// Options shared by read requests. -type ReadOptions struct { - // The read consistency to use. - // Cannot be set when transaction is set. - // Lookup and ancestor queries default to STRONG, global queries default to - // EVENTUAL and cannot be set to STRONG. - ReadConsistency *ReadOptions_ReadConsistency `protobuf:"varint,1,opt,name=read_consistency,enum=datastore.ReadOptions_ReadConsistency,def=0" json:"read_consistency,omitempty"` - // The transaction to use. Optional. - Transaction []byte `protobuf:"bytes,2,opt,name=transaction" json:"transaction,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *ReadOptions) Reset() { *m = ReadOptions{} } -func (m *ReadOptions) String() string { return proto.CompactTextString(m) } -func (*ReadOptions) ProtoMessage() {} - -const Default_ReadOptions_ReadConsistency ReadOptions_ReadConsistency = ReadOptions_DEFAULT - -func (m *ReadOptions) GetReadConsistency() ReadOptions_ReadConsistency { - if m != nil && m.ReadConsistency != nil { - return *m.ReadConsistency - } - return Default_ReadOptions_ReadConsistency -} - -func (m *ReadOptions) GetTransaction() []byte { - if m != nil { - return m.Transaction - } - return nil -} - -// The request for Lookup. -type LookupRequest struct { - // Options for this lookup request. Optional. - ReadOptions *ReadOptions `protobuf:"bytes,1,opt,name=read_options" json:"read_options,omitempty"` - // Keys of entities to look up from the datastore. - Key []*Key `protobuf:"bytes,3,rep,name=key" json:"key,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *LookupRequest) Reset() { *m = LookupRequest{} } -func (m *LookupRequest) String() string { return proto.CompactTextString(m) } -func (*LookupRequest) ProtoMessage() {} - -func (m *LookupRequest) GetReadOptions() *ReadOptions { - if m != nil { - return m.ReadOptions - } - return nil -} - -func (m *LookupRequest) GetKey() []*Key { - if m != nil { - return m.Key - } - return nil -} - -// The response for Lookup. -type LookupResponse struct { - // Entities found as ResultType.FULL entities. - Found []*EntityResult `protobuf:"bytes,1,rep,name=found" json:"found,omitempty"` - // Entities not found as ResultType.KEY_ONLY entities. - Missing []*EntityResult `protobuf:"bytes,2,rep,name=missing" json:"missing,omitempty"` - // A list of keys that were not looked up due to resource constraints. - Deferred []*Key `protobuf:"bytes,3,rep,name=deferred" json:"deferred,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *LookupResponse) Reset() { *m = LookupResponse{} } -func (m *LookupResponse) String() string { return proto.CompactTextString(m) } -func (*LookupResponse) ProtoMessage() {} - -func (m *LookupResponse) GetFound() []*EntityResult { - if m != nil { - return m.Found - } - return nil -} - -func (m *LookupResponse) GetMissing() []*EntityResult { - if m != nil { - return m.Missing - } - return nil -} - -func (m *LookupResponse) GetDeferred() []*Key { - if m != nil { - return m.Deferred - } - return nil -} - -// The request for RunQuery. -type RunQueryRequest struct { - // The options for this query. - ReadOptions *ReadOptions `protobuf:"bytes,1,opt,name=read_options" json:"read_options,omitempty"` - // Entities are partitioned into subsets, identified by a dataset (usually - // implicitly specified by the project) and namespace ID. Queries are scoped - // to a single partition. - // This partition ID is normalized with the standard default context - // partition ID, but all other partition IDs in RunQueryRequest are - // normalized with this partition ID as the context partition ID. - PartitionId *PartitionId `protobuf:"bytes,2,opt,name=partition_id" json:"partition_id,omitempty"` - // The query to run. - // Either this field or field gql_query must be set, but not both. - Query *Query `protobuf:"bytes,3,opt,name=query" json:"query,omitempty"` - // The GQL query to run. - // Either this field or field query must be set, but not both. - GqlQuery *GqlQuery `protobuf:"bytes,7,opt,name=gql_query" json:"gql_query,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *RunQueryRequest) Reset() { *m = RunQueryRequest{} } -func (m *RunQueryRequest) String() string { return proto.CompactTextString(m) } -func (*RunQueryRequest) ProtoMessage() {} - -func (m *RunQueryRequest) GetReadOptions() *ReadOptions { - if m != nil { - return m.ReadOptions - } - return nil -} - -func (m *RunQueryRequest) GetPartitionId() *PartitionId { - if m != nil { - return m.PartitionId - } - return nil -} - -func (m *RunQueryRequest) GetQuery() *Query { - if m != nil { - return m.Query - } - return nil -} - -func (m *RunQueryRequest) GetGqlQuery() *GqlQuery { - if m != nil { - return m.GqlQuery - } - return nil -} - -// The response for RunQuery. -type RunQueryResponse struct { - // A batch of query results (always present). - Batch *QueryResultBatch `protobuf:"bytes,1,opt,name=batch" json:"batch,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *RunQueryResponse) Reset() { *m = RunQueryResponse{} } -func (m *RunQueryResponse) String() string { return proto.CompactTextString(m) } -func (*RunQueryResponse) ProtoMessage() {} - -func (m *RunQueryResponse) GetBatch() *QueryResultBatch { - if m != nil { - return m.Batch - } - return nil -} - -// The request for BeginTransaction. -type BeginTransactionRequest struct { - // The transaction isolation level. - IsolationLevel *BeginTransactionRequest_IsolationLevel `protobuf:"varint,1,opt,name=isolation_level,enum=datastore.BeginTransactionRequest_IsolationLevel,def=0" json:"isolation_level,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *BeginTransactionRequest) Reset() { *m = BeginTransactionRequest{} } -func (m *BeginTransactionRequest) String() string { return proto.CompactTextString(m) } -func (*BeginTransactionRequest) ProtoMessage() {} - -const Default_BeginTransactionRequest_IsolationLevel BeginTransactionRequest_IsolationLevel = BeginTransactionRequest_SNAPSHOT - -func (m *BeginTransactionRequest) GetIsolationLevel() BeginTransactionRequest_IsolationLevel { - if m != nil && m.IsolationLevel != nil { - return *m.IsolationLevel - } - return Default_BeginTransactionRequest_IsolationLevel -} - -// The response for BeginTransaction. -type BeginTransactionResponse struct { - // The transaction identifier (always present). - Transaction []byte `protobuf:"bytes,1,opt,name=transaction" json:"transaction,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *BeginTransactionResponse) Reset() { *m = BeginTransactionResponse{} } -func (m *BeginTransactionResponse) String() string { return proto.CompactTextString(m) } -func (*BeginTransactionResponse) ProtoMessage() {} - -func (m *BeginTransactionResponse) GetTransaction() []byte { - if m != nil { - return m.Transaction - } - return nil -} - -// The request for Rollback. -type RollbackRequest struct { - // The transaction identifier, returned by a call to - // beginTransaction. - Transaction []byte `protobuf:"bytes,1,req,name=transaction" json:"transaction,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *RollbackRequest) Reset() { *m = RollbackRequest{} } -func (m *RollbackRequest) String() string { return proto.CompactTextString(m) } -func (*RollbackRequest) ProtoMessage() {} - -func (m *RollbackRequest) GetTransaction() []byte { - if m != nil { - return m.Transaction - } - return nil -} - -// The response for Rollback. -type RollbackResponse struct { - XXX_unrecognized []byte `json:"-"` -} - -func (m *RollbackResponse) Reset() { *m = RollbackResponse{} } -func (m *RollbackResponse) String() string { return proto.CompactTextString(m) } -func (*RollbackResponse) ProtoMessage() {} - -// The request for Commit. -type CommitRequest struct { - // The transaction identifier, returned by a call to - // beginTransaction. Must be set when mode is TRANSACTIONAL. - Transaction []byte `protobuf:"bytes,1,opt,name=transaction" json:"transaction,omitempty"` - // The mutation to perform. Optional. - Mutation *Mutation `protobuf:"bytes,2,opt,name=mutation" json:"mutation,omitempty"` - // The type of commit to perform. Either TRANSACTIONAL or NON_TRANSACTIONAL. - Mode *CommitRequest_Mode `protobuf:"varint,5,opt,name=mode,enum=datastore.CommitRequest_Mode,def=1" json:"mode,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *CommitRequest) Reset() { *m = CommitRequest{} } -func (m *CommitRequest) String() string { return proto.CompactTextString(m) } -func (*CommitRequest) ProtoMessage() {} - -const Default_CommitRequest_Mode CommitRequest_Mode = CommitRequest_TRANSACTIONAL - -func (m *CommitRequest) GetTransaction() []byte { - if m != nil { - return m.Transaction - } - return nil -} - -func (m *CommitRequest) GetMutation() *Mutation { - if m != nil { - return m.Mutation - } - return nil -} - -func (m *CommitRequest) GetMode() CommitRequest_Mode { - if m != nil && m.Mode != nil { - return *m.Mode - } - return Default_CommitRequest_Mode -} - -// The response for Commit. -type CommitResponse struct { - // The result of performing the mutation (if any). - MutationResult *MutationResult `protobuf:"bytes,1,opt,name=mutation_result" json:"mutation_result,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *CommitResponse) Reset() { *m = CommitResponse{} } -func (m *CommitResponse) String() string { return proto.CompactTextString(m) } -func (*CommitResponse) ProtoMessage() {} - -func (m *CommitResponse) GetMutationResult() *MutationResult { - if m != nil { - return m.MutationResult - } - return nil -} - -// The request for AllocateIds. -type AllocateIdsRequest struct { - // A list of keys with incomplete key paths to allocate IDs for. - // No key may be reserved/read-only. - Key []*Key `protobuf:"bytes,1,rep,name=key" json:"key,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *AllocateIdsRequest) Reset() { *m = AllocateIdsRequest{} } -func (m *AllocateIdsRequest) String() string { return proto.CompactTextString(m) } -func (*AllocateIdsRequest) ProtoMessage() {} - -func (m *AllocateIdsRequest) GetKey() []*Key { - if m != nil { - return m.Key - } - return nil -} - -// The response for AllocateIds. -type AllocateIdsResponse struct { - // The keys specified in the request (in the same order), each with - // its key path completed with a newly allocated ID. - Key []*Key `protobuf:"bytes,1,rep,name=key" json:"key,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *AllocateIdsResponse) Reset() { *m = AllocateIdsResponse{} } -func (m *AllocateIdsResponse) String() string { return proto.CompactTextString(m) } -func (*AllocateIdsResponse) ProtoMessage() {} - -func (m *AllocateIdsResponse) GetKey() []*Key { - if m != nil { - return m.Key - } - return nil -} - -func init() { - proto.RegisterEnum("datastore.EntityResult_ResultType", EntityResult_ResultType_name, EntityResult_ResultType_value) - proto.RegisterEnum("datastore.PropertyExpression_AggregationFunction", PropertyExpression_AggregationFunction_name, PropertyExpression_AggregationFunction_value) - proto.RegisterEnum("datastore.PropertyOrder_Direction", PropertyOrder_Direction_name, PropertyOrder_Direction_value) - proto.RegisterEnum("datastore.CompositeFilter_Operator", CompositeFilter_Operator_name, CompositeFilter_Operator_value) - proto.RegisterEnum("datastore.PropertyFilter_Operator", PropertyFilter_Operator_name, PropertyFilter_Operator_value) - proto.RegisterEnum("datastore.QueryResultBatch_MoreResultsType", QueryResultBatch_MoreResultsType_name, QueryResultBatch_MoreResultsType_value) - proto.RegisterEnum("datastore.ReadOptions_ReadConsistency", ReadOptions_ReadConsistency_name, ReadOptions_ReadConsistency_value) - proto.RegisterEnum("datastore.BeginTransactionRequest_IsolationLevel", BeginTransactionRequest_IsolationLevel_name, BeginTransactionRequest_IsolationLevel_value) - proto.RegisterEnum("datastore.CommitRequest_Mode", CommitRequest_Mode_name, CommitRequest_Mode_value) -} diff --git a/vendor/google.golang.org/cloud/internal/datastore/datastore_v1.proto b/vendor/google.golang.org/cloud/internal/datastore/datastore_v1.proto deleted file mode 100644 index 36bb9df7..00000000 --- a/vendor/google.golang.org/cloud/internal/datastore/datastore_v1.proto +++ /dev/null @@ -1,594 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// The datastore v1 service proto definitions - -syntax = "proto2"; - -package datastore; -option java_package = "com.google.api.services.datastore"; - - -// An identifier for a particular subset of entities. -// -// Entities are partitioned into various subsets, each used by different -// datasets and different namespaces within a dataset and so forth. -// -// All input partition IDs are normalized before use. -// A partition ID is normalized as follows: -// If the partition ID is unset or is set to an empty partition ID, replace it -// with the context partition ID. -// Otherwise, if the partition ID has no dataset ID, assign it the context -// partition ID's dataset ID. -// Unless otherwise documented, the context partition ID has the dataset ID set -// to the context dataset ID and no other partition dimension set. -// -// A partition ID is empty if all of its fields are unset. -// -// Partition dimension: -// A dimension may be unset. -// A dimension's value must never be "". -// A dimension's value must match [A-Za-z\d\.\-_]{1,100} -// If the value of any dimension matches regex "__.*__", -// the partition is reserved/read-only. -// A reserved/read-only partition ID is forbidden in certain documented contexts. -// -// Dataset ID: -// A dataset id's value must never be "". -// A dataset id's value must match -// ([a-z\d\-]{1,100}~)?([a-z\d][a-z\d\-\.]{0,99}:)?([a-z\d][a-z\d\-]{0,99} -message PartitionId { - // The dataset ID. - optional string dataset_id = 3; - // The namespace. - optional string namespace = 4; -} - -// A unique identifier for an entity. -// If a key's partition id or any of its path kinds or names are -// reserved/read-only, the key is reserved/read-only. -// A reserved/read-only key is forbidden in certain documented contexts. -message Key { - // Entities are partitioned into subsets, currently identified by a dataset - // (usually implicitly specified by the project) and namespace ID. - // Queries are scoped to a single partition. - optional PartitionId partition_id = 1; - - // A (kind, ID/name) pair used to construct a key path. - // - // At most one of name or ID may be set. - // If either is set, the element is complete. - // If neither is set, the element is incomplete. - message PathElement { - // The kind of the entity. - // A kind matching regex "__.*__" is reserved/read-only. - // A kind must not contain more than 500 characters. - // Cannot be "". - required string kind = 1; - // The ID of the entity. - // Never equal to zero. Values less than zero are discouraged and will not - // be supported in the future. - optional int64 id = 2; - // The name of the entity. - // A name matching regex "__.*__" is reserved/read-only. - // A name must not be more than 500 characters. - // Cannot be "". - optional string name = 3; - } - - // The entity path. - // An entity path consists of one or more elements composed of a kind and a - // string or numerical identifier, which identify entities. The first - // element identifies a root entity, the second element identifies - // a child of the root entity, the third element a child of the - // second entity, and so forth. The entities identified by all prefixes of - // the path are called the element's ancestors. - // An entity path is always fully complete: ALL of the entity's ancestors - // are required to be in the path along with the entity identifier itself. - // The only exception is that in some documented cases, the identifier in the - // last path element (for the entity) itself may be omitted. A path can never - // be empty. - repeated PathElement path_element = 2; -} - -// A message that can hold any of the supported value types and associated -// metadata. -// -// At most one of the Value fields may be set. -// If none are set the value is "null". -// -message Value { - // A boolean value. - optional bool boolean_value = 1; - // An integer value. - optional int64 integer_value = 2; - // A double value. - optional double double_value = 3; - // A timestamp value. - optional int64 timestamp_microseconds_value = 4; - // A key value. - optional Key key_value = 5; - // A blob key value. - optional string blob_key_value = 16; - // A UTF-8 encoded string value. - optional string string_value = 17; - // A blob value. - optional bytes blob_value = 18; - // An entity value. - // May have no key. - // May have a key with an incomplete key path. - // May have a reserved/read-only key. - optional Entity entity_value = 6; - // A list value. - // Cannot contain another list value. - // Cannot also have a meaning and indexing set. - repeated Value list_value = 7; - - // The meaning field is reserved and should not be used. - optional int32 meaning = 14; - - // If the value should be indexed. - // - // The indexed property may be set for a - // null value. - // When indexed is true, stringValue - // is limited to 500 characters and the blob value is limited to 500 bytes. - // Exception: If meaning is set to 2, string_value is limited to 2038 - // characters regardless of indexed. - // When indexed is true, meaning 15 and 22 are not allowed, and meaning 16 - // will be ignored on input (and will never be set on output). - // Input values by default have indexed set to - // true; however, you can explicitly set indexed to - // true if you want. (An output value never has - // indexed explicitly set to true.) If a value is - // itself an entity, it cannot have indexed set to - // true. - // Exception: An entity value with meaning 9, 20 or 21 may be indexed. - optional bool indexed = 15 [default = true]; -} - -// An entity property. -message Property { - // The name of the property. - // A property name matching regex "__.*__" is reserved. - // A reserved property name is forbidden in certain documented contexts. - // The name must not contain more than 500 characters. - // Cannot be "". - required string name = 1; - - // The value(s) of the property. - // Each value can have only one value property populated. For example, - // you cannot have a values list of { value: { integerValue: 22, - // stringValue: "a" } }, but you can have { value: { listValue: - // [ { integerValue: 22 }, { stringValue: "a" } ] }. - required Value value = 4; -} - -// An entity. -// -// An entity is limited to 1 megabyte when stored. That roughly -// corresponds to a limit of 1 megabyte for the serialized form of this -// message. -message Entity { - // The entity's key. - // - // An entity must have a key, unless otherwise documented (for example, - // an entity in Value.entityValue may have no key). - // An entity's kind is its key's path's last element's kind, - // or null if it has no key. - optional Key key = 1; - // The entity's properties. - // Each property's name must be unique for its entity. - repeated Property property = 2; -} - -// The result of fetching an entity from the datastore. -message EntityResult { - // Specifies what data the 'entity' field contains. - // A ResultType is either implied (for example, in LookupResponse.found it - // is always FULL) or specified by context (for example, in message - // QueryResultBatch, field 'entity_result_type' specifies a ResultType - // for all the values in field 'entity_result'). - enum ResultType { - FULL = 1; // The entire entity. - PROJECTION = 2; // A projected subset of properties. - // The entity may have no key. - // A property value may have meaning 18. - KEY_ONLY = 3; // Only the key. - } - - // The resulting entity. - required Entity entity = 1; -} - -// A query. -message Query { - // The projection to return. If not set the entire entity is returned. - repeated PropertyExpression projection = 2; - - // The kinds to query (if empty, returns entities from all kinds). - repeated KindExpression kind = 3; - - // The filter to apply (optional). - optional Filter filter = 4; - - // The order to apply to the query results (if empty, order is unspecified). - repeated PropertyOrder order = 5; - - // The properties to group by (if empty, no grouping is applied to the - // result set). - repeated PropertyReference group_by = 6; - - // A starting point for the query results. Optional. Query cursors are - // returned in query result batches. - optional bytes /* serialized QueryCursor */ start_cursor = 7; - - // An ending point for the query results. Optional. Query cursors are - // returned in query result batches. - optional bytes /* serialized QueryCursor */ end_cursor = 8; - - // The number of results to skip. Applies before limit, but after all other - // constraints (optional, defaults to 0). - optional int32 offset = 10 [default=0]; - - // The maximum number of results to return. Applies after all other - // constraints. Optional. - optional int32 limit = 11; -} - -// A representation of a kind. -message KindExpression { - // The name of the kind. - required string name = 1; -} - -// A reference to a property relative to the kind expressions. -// exactly. -message PropertyReference { - // The name of the property. - required string name = 2; -} - -// A representation of a property in a projection. -message PropertyExpression { - enum AggregationFunction { - FIRST = 1; - } - // The property to project. - required PropertyReference property = 1; - // The aggregation function to apply to the property. Optional. - // Can only be used when grouping by at least one property. Must - // then be set on all properties in the projection that are not - // being grouped by. - optional AggregationFunction aggregation_function = 2; -} - -// The desired order for a specific property. -message PropertyOrder { - enum Direction { - ASCENDING = 1; - DESCENDING = 2; - } - // The property to order by. - required PropertyReference property = 1; - // The direction to order by. - optional Direction direction = 2 [default=ASCENDING]; -} - -// A holder for any type of filter. Exactly one field should be specified. -message Filter { - // A composite filter. - optional CompositeFilter composite_filter = 1; - // A filter on a property. - optional PropertyFilter property_filter = 2; -} - -// A filter that merges the multiple other filters using the given operation. -message CompositeFilter { - enum Operator { - AND = 1; - } - - // The operator for combining multiple filters. - required Operator operator = 1; - // The list of filters to combine. - // Must contain at least one filter. - repeated Filter filter = 2; -} - -// A filter on a specific property. -message PropertyFilter { - enum Operator { - LESS_THAN = 1; - LESS_THAN_OR_EQUAL = 2; - GREATER_THAN = 3; - GREATER_THAN_OR_EQUAL = 4; - EQUAL = 5; - - HAS_ANCESTOR = 11; - } - - // The property to filter by. - required PropertyReference property = 1; - // The operator to filter by. - required Operator operator = 2; - // The value to compare the property to. - required Value value = 3; -} - -// A GQL query. -message GqlQuery { - required string query_string = 1; - // When false, the query string must not contain a literal. - optional bool allow_literal = 2 [default = false]; - // A named argument must set field GqlQueryArg.name. - // No two named arguments may have the same name. - // For each non-reserved named binding site in the query string, - // there must be a named argument with that name, - // but not necessarily the inverse. - repeated GqlQueryArg name_arg = 3; - // Numbered binding site @1 references the first numbered argument, - // effectively using 1-based indexing, rather than the usual 0. - // A numbered argument must NOT set field GqlQueryArg.name. - // For each binding site numbered i in query_string, - // there must be an ith numbered argument. - // The inverse must also be true. - repeated GqlQueryArg number_arg = 4; -} - -// A binding argument for a GQL query. -// Exactly one of fields value and cursor must be set. -message GqlQueryArg { - // Must match regex "[A-Za-z_$][A-Za-z_$0-9]*". - // Must not match regex "__.*__". - // Must not be "". - optional string name = 1; - optional Value value = 2; - optional bytes cursor = 3; -} - -// A batch of results produced by a query. -message QueryResultBatch { - // The possible values for the 'more_results' field. - enum MoreResultsType { - NOT_FINISHED = 1; // There are additional batches to fetch from this query. - MORE_RESULTS_AFTER_LIMIT = 2; // The query is finished, but there are more - // results after the limit. - NO_MORE_RESULTS = 3; // The query has been exhausted. - } - - // The result type for every entity in entityResults. - required EntityResult.ResultType entity_result_type = 1; - // The results for this batch. - repeated EntityResult entity_result = 2; - - // A cursor that points to the position after the last result in the batch. - // May be absent. - optional bytes /* serialized QueryCursor */ end_cursor = 4; - - // The state of the query after the current batch. - required MoreResultsType more_results = 5; - - // The number of results skipped because of Query.offset. - optional int32 skipped_results = 6; -} - -// A set of changes to apply. -// -// No entity in this message may have a reserved property name, -// not even a property in an entity in a value. -// No value in this message may have meaning 18, -// not even a value in an entity in another value. -// -// If entities with duplicate keys are present, an arbitrary choice will -// be made as to which is written. -message Mutation { - // Entities to upsert. - // Each upserted entity's key must have a complete path and - // must not be reserved/read-only. - repeated Entity upsert = 1; - // Entities to update. - // Each updated entity's key must have a complete path and - // must not be reserved/read-only. - repeated Entity update = 2; - // Entities to insert. - // Each inserted entity's key must have a complete path and - // must not be reserved/read-only. - repeated Entity insert = 3; - // Insert entities with a newly allocated ID. - // Each inserted entity's key must omit the final identifier in its path and - // must not be reserved/read-only. - repeated Entity insert_auto_id = 4; - // Keys of entities to delete. - // Each key must have a complete key path and must not be reserved/read-only. - repeated Key delete = 5; - // Ignore a user specified read-only period. Optional. - optional bool force = 6; -} - -// The result of applying a mutation. -message MutationResult { - // Number of index writes. - required int32 index_updates = 1; - // Keys for insertAutoId entities. One per entity from the - // request, in the same order. - repeated Key insert_auto_id_key = 2; -} - -// Options shared by read requests. -message ReadOptions { - enum ReadConsistency { - DEFAULT = 0; - STRONG = 1; - EVENTUAL = 2; - } - - // The read consistency to use. - // Cannot be set when transaction is set. - // Lookup and ancestor queries default to STRONG, global queries default to - // EVENTUAL and cannot be set to STRONG. - optional ReadConsistency read_consistency = 1 [default=DEFAULT]; - - // The transaction to use. Optional. - optional bytes /* serialized Transaction */ transaction = 2; -} - -// The request for Lookup. -message LookupRequest { - - // Options for this lookup request. Optional. - optional ReadOptions read_options = 1; - // Keys of entities to look up from the datastore. - repeated Key key = 3; -} - -// The response for Lookup. -message LookupResponse { - - // The order of results in these fields is undefined and has no relation to - // the order of the keys in the input. - - // Entities found as ResultType.FULL entities. - repeated EntityResult found = 1; - - // Entities not found as ResultType.KEY_ONLY entities. - repeated EntityResult missing = 2; - - // A list of keys that were not looked up due to resource constraints. - repeated Key deferred = 3; -} - - -// The request for RunQuery. -message RunQueryRequest { - - // The options for this query. - optional ReadOptions read_options = 1; - - // Entities are partitioned into subsets, identified by a dataset (usually - // implicitly specified by the project) and namespace ID. Queries are scoped - // to a single partition. - // This partition ID is normalized with the standard default context - // partition ID, but all other partition IDs in RunQueryRequest are - // normalized with this partition ID as the context partition ID. - optional PartitionId partition_id = 2; - - // The query to run. - // Either this field or field gql_query must be set, but not both. - optional Query query = 3; - // The GQL query to run. - // Either this field or field query must be set, but not both. - optional GqlQuery gql_query = 7; -} - -// The response for RunQuery. -message RunQueryResponse { - - // A batch of query results (always present). - optional QueryResultBatch batch = 1; - -} - -// The request for BeginTransaction. -message BeginTransactionRequest { - - enum IsolationLevel { - SNAPSHOT = 0; // Read from a consistent snapshot. Concurrent transactions - // conflict if their mutations conflict. For example: - // Read(A),Write(B) may not conflict with Read(B),Write(A), - // but Read(B),Write(B) does conflict with Read(B),Write(B). - SERIALIZABLE = 1; // Read from a consistent snapshot. Concurrent - // transactions conflict if they cannot be serialized. - // For example Read(A),Write(B) does conflict with - // Read(B),Write(A) but Read(A) may not conflict with - // Write(A). - } - - // The transaction isolation level. - optional IsolationLevel isolation_level = 1 [default=SNAPSHOT]; -} - -// The response for BeginTransaction. -message BeginTransactionResponse { - - // The transaction identifier (always present). - optional bytes /* serialized Transaction */ transaction = 1; -} - -// The request for Rollback. -message RollbackRequest { - - // The transaction identifier, returned by a call to - // beginTransaction. - required bytes /* serialized Transaction */ transaction = 1; -} - -// The response for Rollback. -message RollbackResponse { -// Empty -} - -// The request for Commit. -message CommitRequest { - - enum Mode { - TRANSACTIONAL = 1; - NON_TRANSACTIONAL = 2; - } - - // The transaction identifier, returned by a call to - // beginTransaction. Must be set when mode is TRANSACTIONAL. - optional bytes /* serialized Transaction */ transaction = 1; - // The mutation to perform. Optional. - optional Mutation mutation = 2; - // The type of commit to perform. Either TRANSACTIONAL or NON_TRANSACTIONAL. - optional Mode mode = 5 [default=TRANSACTIONAL]; -} - -// The response for Commit. -message CommitResponse { - - // The result of performing the mutation (if any). - optional MutationResult mutation_result = 1; -} - -// The request for AllocateIds. -message AllocateIdsRequest { - - // A list of keys with incomplete key paths to allocate IDs for. - // No key may be reserved/read-only. - repeated Key key = 1; -} - -// The response for AllocateIds. -message AllocateIdsResponse { - - // The keys specified in the request (in the same order), each with - // its key path completed with a newly allocated ID. - repeated Key key = 1; -} - -// Each rpc normalizes the partition IDs of the keys in its input entities, -// and always returns entities with keys with normalized partition IDs. -// (Note that applies to all entities, including entities in values.) -service DatastoreService { - // Look up some entities by key. - rpc Lookup(LookupRequest) returns (LookupResponse) { - }; - // Query for entities. - rpc RunQuery(RunQueryRequest) returns (RunQueryResponse) { - }; - // Begin a new transaction. - rpc BeginTransaction(BeginTransactionRequest) returns (BeginTransactionResponse) { - }; - // Commit a transaction, optionally creating, deleting or modifying some - // entities. - rpc Commit(CommitRequest) returns (CommitResponse) { - }; - // Roll back a transaction. - rpc Rollback(RollbackRequest) returns (RollbackResponse) { - }; - // Allocate IDs for incomplete keys (useful for referencing an entity before - // it is inserted). - rpc AllocateIds(AllocateIdsRequest) returns (AllocateIdsResponse) { - }; -} diff --git a/vendor/google.golang.org/cloud/internal/testutil/context.go b/vendor/google.golang.org/cloud/internal/testutil/context.go deleted file mode 100644 index aafd6838..00000000 --- a/vendor/google.golang.org/cloud/internal/testutil/context.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package testutil contains helper functions for writing tests. -package testutil - -import ( - "io/ioutil" - "log" - "net/http" - "os" - - "golang.org/x/net/context" - "golang.org/x/oauth2" - "golang.org/x/oauth2/google" - "google.golang.org/cloud" -) - -const ( - envProjID = "GCLOUD_TESTS_GOLANG_PROJECT_ID" - envPrivateKey = "GCLOUD_TESTS_GOLANG_KEY" -) - -func Context(scopes ...string) context.Context { - key, projID := os.Getenv(envPrivateKey), os.Getenv(envProjID) - if key == "" || projID == "" { - log.Fatal("GCLOUD_TESTS_GOLANG_KEY and GCLOUD_TESTS_GOLANG_PROJECT_ID must be set. See CONTRIBUTING.md for details.") - } - jsonKey, err := ioutil.ReadFile(key) - if err != nil { - log.Fatalf("Cannot read the JSON key file, err: %v", err) - } - conf, err := google.JWTConfigFromJSON(jsonKey, scopes...) - if err != nil { - log.Fatal(err) - } - return cloud.NewContext(projID, conf.Client(oauth2.NoContext)) -} - -func NoAuthContext() context.Context { - projID := os.Getenv(envProjID) - if projID == "" { - log.Fatal("GCLOUD_TESTS_GOLANG_PROJECT_ID must be set. See CONTRIBUTING.md for details.") - } - return cloud.NewContext(projID, &http.Client{Transport: http.DefaultTransport}) -}