diff --git a/components/engine/Dockerfile b/components/engine/Dockerfile index 63e2dc3f00..c2e279505f 100644 --- a/components/engine/Dockerfile +++ b/components/engine/Dockerfile @@ -91,21 +91,6 @@ RUN set -x \ -FROM base AS notary -# Install notary and notary-server -ENV NOTARY_VERSION v0.5.0 -RUN set -x \ - && export GOPATH="$(mktemp -d)" \ - && git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \ - && (cd "$GOPATH/src/github.com/docker/notary" && git checkout -q "$NOTARY_VERSION") \ - && GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \ - go build -buildmode=pie -o /usr/local/bin/notary-server github.com/docker/notary/cmd/notary-server \ - && GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \ - go build -buildmode=pie -o /usr/local/bin/notary github.com/docker/notary/cmd/notary \ - && rm -rf "$GOPATH" - - - FROM base AS docker-py # Get the "docker-py" source so we can run their integration tests ENV DOCKER_PY_COMMIT 8b246db271a85d6541dc458838627e89c683e42f @@ -248,7 +233,6 @@ COPY --from=containerd /opt/containerd/ /usr/local/bin/ COPY --from=proxy /opt/proxy/ /usr/local/bin/ COPY --from=dockercli /opt/dockercli /usr/local/cli COPY --from=registry /usr/local/bin/registry* /usr/local/bin/ -COPY --from=notary /usr/local/bin/notary* /usr/local/bin/ COPY --from=criu /opt/criu/ /usr/local/ COPY --from=docker-py /docker-py /docker-py # TODO: This is for the docker-py tests, which shouldn't really be needed for diff --git a/components/engine/daemon/exec_linux.go b/components/engine/daemon/exec_linux.go index 1ed26c2fcc..cd52f4886f 100644 --- a/components/engine/daemon/exec_linux.go +++ b/components/engine/daemon/exec_linux.go @@ -34,6 +34,8 @@ func (daemon *Daemon) execSetPlatformOpt(c *container.Container, ec *exec.Config if c.AppArmorProfile != "" { appArmorProfile = c.AppArmorProfile } else if c.HostConfig.Privileged { + // `docker exec --privileged` does not currently disable AppArmor + // profiles. Privileged configuration of the container is inherited appArmorProfile = "unconfined" } else { appArmorProfile = "docker-default" @@ -50,6 +52,7 @@ func (daemon *Daemon) execSetPlatformOpt(c *container.Container, ec *exec.Config return err } } + p.ApparmorProfile = appArmorProfile } daemon.setRlimits(&specs.Spec{Process: p}, c) return nil diff --git a/components/engine/daemon/exec_linux_test.go b/components/engine/daemon/exec_linux_test.go new file mode 100644 index 0000000000..9e5496ae4b --- /dev/null +++ b/components/engine/daemon/exec_linux_test.go @@ -0,0 +1,53 @@ +// +build linux + +package daemon + +import ( + "testing" + + containertypes "github.com/docker/docker/api/types/container" + "github.com/docker/docker/container" + "github.com/docker/docker/daemon/exec" + "github.com/gotestyourself/gotestyourself/assert" + "github.com/opencontainers/runc/libcontainer/apparmor" + "github.com/opencontainers/runtime-spec/specs-go" +) + +func TestExecSetPlatformOpt(t *testing.T) { + if !apparmor.IsEnabled() { + t.Skip("requires AppArmor to be enabled") + } + d := &Daemon{} + c := &container.Container{AppArmorProfile: "my-custom-profile"} + ec := &exec.Config{} + p := &specs.Process{} + + err := d.execSetPlatformOpt(c, ec, p) + assert.NilError(t, err) + assert.Equal(t, "my-custom-profile", p.ApparmorProfile) +} + +// TestExecSetPlatformOptPrivileged verifies that `docker exec --privileged` +// does not disable AppArmor profiles. Exec currently inherits the `Privileged` +// configuration of the container. See https://github.com/moby/moby/pull/31773#discussion_r105586900 +// +// This behavior may change in future, but test for the behavior to prevent it +// from being changed accidentally. +func TestExecSetPlatformOptPrivileged(t *testing.T) { + if !apparmor.IsEnabled() { + t.Skip("requires AppArmor to be enabled") + } + d := &Daemon{} + c := &container.Container{AppArmorProfile: "my-custom-profile"} + ec := &exec.Config{Privileged: true} + p := &specs.Process{} + + err := d.execSetPlatformOpt(c, ec, p) + assert.NilError(t, err) + assert.Equal(t, "my-custom-profile", p.ApparmorProfile) + + c.HostConfig = &containertypes.HostConfig{Privileged: true} + err = d.execSetPlatformOpt(c, ec, p) + assert.NilError(t, err) + assert.Equal(t, "unconfined", p.ApparmorProfile) +} diff --git a/components/engine/daemon/logger/jsonfilelog/jsonfilelog.go b/components/engine/daemon/logger/jsonfilelog/jsonfilelog.go index 5a8045088f..2b1e91d063 100644 --- a/components/engine/daemon/logger/jsonfilelog/jsonfilelog.go +++ b/components/engine/daemon/logger/jsonfilelog/jsonfilelog.go @@ -49,6 +49,9 @@ func New(info logger.Info) (logger.Logger, error) { if err != nil { return nil, err } + if capval <= 0 { + return nil, fmt.Errorf("max-size should be a positive numbler") + } } var maxFiles = 1 if maxFileString, ok := info.Config["max-file"]; ok { @@ -62,6 +65,18 @@ func New(info logger.Info) (logger.Logger, error) { } } + var compress bool + if compressString, ok := info.Config["compress"]; ok { + var err error + compress, err = strconv.ParseBool(compressString) + if err != nil { + return nil, err + } + if compress && (maxFiles == 1 || capval == -1) { + return nil, fmt.Errorf("compress cannot be true when max-file is less than 2 or max-size is not set") + } + } + attrs, err := info.ExtraAttributes(nil) if err != nil { return nil, err @@ -95,7 +110,7 @@ func New(info logger.Info) (logger.Logger, error) { return b, nil } - writer, err := loggerutils.NewLogFile(info.LogPath, capval, maxFiles, marshalFunc, decodeFunc, 0640) + writer, err := loggerutils.NewLogFile(info.LogPath, capval, maxFiles, compress, marshalFunc, decodeFunc, 0640) if err != nil { return nil, err } @@ -139,6 +154,7 @@ func ValidateLogOpt(cfg map[string]string) error { switch key { case "max-file": case "max-size": + case "compress": case "labels": case "env": case "env-regex": diff --git a/components/engine/daemon/logger/jsonfilelog/jsonfilelog_test.go b/components/engine/daemon/logger/jsonfilelog/jsonfilelog_test.go index 0174d88c0d..2becd694b0 100644 --- a/components/engine/daemon/logger/jsonfilelog/jsonfilelog_test.go +++ b/components/engine/daemon/logger/jsonfilelog/jsonfilelog_test.go @@ -2,6 +2,7 @@ package jsonfilelog // import "github.com/docker/docker/daemon/logger/jsonfilelo import ( "bytes" + "compress/gzip" "encoding/json" "io/ioutil" "os" @@ -142,7 +143,7 @@ func TestJSONFileLoggerWithOpts(t *testing.T) { } defer os.RemoveAll(tmp) filename := filepath.Join(tmp, "container.log") - config := map[string]string{"max-file": "2", "max-size": "1k"} + config := map[string]string{"max-file": "3", "max-size": "1k", "compress": "true"} l, err := New(logger.Info{ ContainerID: cid, LogPath: filename, @@ -152,21 +153,55 @@ func TestJSONFileLoggerWithOpts(t *testing.T) { t.Fatal(err) } defer l.Close() - for i := 0; i < 20; i++ { + for i := 0; i < 36; i++ { if err := l.Log(&logger.Message{Line: []byte("line" + strconv.Itoa(i)), Source: "src1"}); err != nil { t.Fatal(err) } } + res, err := ioutil.ReadFile(filename) if err != nil { t.Fatal(err) } + penUlt, err := ioutil.ReadFile(filename + ".1") + if err != nil { + if !os.IsNotExist(err) { + t.Fatal(err) + } + + file, err := os.Open(filename + ".1.gz") + defer file.Close() + if err != nil { + t.Fatal(err) + } + zipReader, err := gzip.NewReader(file) + defer zipReader.Close() + if err != nil { + t.Fatal(err) + } + penUlt, err = ioutil.ReadAll(zipReader) + if err != nil { + t.Fatal(err) + } + } + + file, err := os.Open(filename + ".2.gz") + defer file.Close() + if err != nil { + t.Fatal(err) + } + zipReader, err := gzip.NewReader(file) + defer zipReader.Close() + if err != nil { + t.Fatal(err) + } + antepenult, err := ioutil.ReadAll(zipReader) if err != nil { t.Fatal(err) } - expectedPenultimate := `{"log":"line0\n","stream":"src1","time":"0001-01-01T00:00:00Z"} + expectedAntepenultimate := `{"log":"line0\n","stream":"src1","time":"0001-01-01T00:00:00Z"} {"log":"line1\n","stream":"src1","time":"0001-01-01T00:00:00Z"} {"log":"line2\n","stream":"src1","time":"0001-01-01T00:00:00Z"} {"log":"line3\n","stream":"src1","time":"0001-01-01T00:00:00Z"} @@ -183,10 +218,27 @@ func TestJSONFileLoggerWithOpts(t *testing.T) { {"log":"line14\n","stream":"src1","time":"0001-01-01T00:00:00Z"} {"log":"line15\n","stream":"src1","time":"0001-01-01T00:00:00Z"} ` - expected := `{"log":"line16\n","stream":"src1","time":"0001-01-01T00:00:00Z"} + expectedPenultimate := `{"log":"line16\n","stream":"src1","time":"0001-01-01T00:00:00Z"} {"log":"line17\n","stream":"src1","time":"0001-01-01T00:00:00Z"} {"log":"line18\n","stream":"src1","time":"0001-01-01T00:00:00Z"} {"log":"line19\n","stream":"src1","time":"0001-01-01T00:00:00Z"} +{"log":"line20\n","stream":"src1","time":"0001-01-01T00:00:00Z"} +{"log":"line21\n","stream":"src1","time":"0001-01-01T00:00:00Z"} +{"log":"line22\n","stream":"src1","time":"0001-01-01T00:00:00Z"} +{"log":"line23\n","stream":"src1","time":"0001-01-01T00:00:00Z"} +{"log":"line24\n","stream":"src1","time":"0001-01-01T00:00:00Z"} +{"log":"line25\n","stream":"src1","time":"0001-01-01T00:00:00Z"} +{"log":"line26\n","stream":"src1","time":"0001-01-01T00:00:00Z"} +{"log":"line27\n","stream":"src1","time":"0001-01-01T00:00:00Z"} +{"log":"line28\n","stream":"src1","time":"0001-01-01T00:00:00Z"} +{"log":"line29\n","stream":"src1","time":"0001-01-01T00:00:00Z"} +{"log":"line30\n","stream":"src1","time":"0001-01-01T00:00:00Z"} +{"log":"line31\n","stream":"src1","time":"0001-01-01T00:00:00Z"} +` + expected := `{"log":"line32\n","stream":"src1","time":"0001-01-01T00:00:00Z"} +{"log":"line33\n","stream":"src1","time":"0001-01-01T00:00:00Z"} +{"log":"line34\n","stream":"src1","time":"0001-01-01T00:00:00Z"} +{"log":"line35\n","stream":"src1","time":"0001-01-01T00:00:00Z"} ` if string(res) != expected { @@ -195,7 +247,9 @@ func TestJSONFileLoggerWithOpts(t *testing.T) { if string(penUlt) != expectedPenultimate { t.Fatalf("Wrong log content: %q, expected %q", penUlt, expectedPenultimate) } - + if string(antepenult) != expectedAntepenultimate { + t.Fatalf("Wrong log content: %q, expected %q", antepenult, expectedAntepenultimate) + } } func TestJSONFileLoggerWithLabelsEnv(t *testing.T) { diff --git a/components/engine/daemon/logger/loggerutils/logfile.go b/components/engine/daemon/logger/loggerutils/logfile.go index e646afc23d..b4148ce645 100644 --- a/components/engine/daemon/logger/loggerutils/logfile.go +++ b/components/engine/daemon/logger/loggerutils/logfile.go @@ -2,17 +2,21 @@ package loggerutils // import "github.com/docker/docker/daemon/logger/loggerutil import ( "bytes" + "compress/gzip" "context" + "encoding/json" "fmt" "io" "os" "strconv" + "strings" "sync" "time" "github.com/docker/docker/daemon/logger" "github.com/docker/docker/daemon/logger/loggerutils/multireader" "github.com/docker/docker/pkg/filenotify" + "github.com/docker/docker/pkg/pools" "github.com/docker/docker/pkg/pubsub" "github.com/docker/docker/pkg/tailfile" "github.com/fsnotify/fsnotify" @@ -20,24 +24,81 @@ import ( "github.com/sirupsen/logrus" ) +const tmpLogfileSuffix = ".tmp" + +// rotateFileMetadata is a metadata of the gzip header of the compressed log file +type rotateFileMetadata struct { + LastTime time.Time `json:"lastTime,omitempty"` +} + +// refCounter is a counter of logfile being referenced +type refCounter struct { + mu sync.Mutex + counter map[string]int +} + +// Reference increase the reference counter for specified logfile +func (rc *refCounter) GetReference(fileName string, openRefFile func(fileName string, exists bool) (*os.File, error)) (*os.File, error) { + rc.mu.Lock() + defer rc.mu.Unlock() + + var ( + file *os.File + err error + ) + _, ok := rc.counter[fileName] + file, err = openRefFile(fileName, ok) + if err != nil { + return nil, err + } + + if ok { + rc.counter[fileName]++ + } else if file != nil { + rc.counter[file.Name()] = 1 + } + + return file, nil +} + +// Dereference reduce the reference counter for specified logfile +func (rc *refCounter) Dereference(fileName string) error { + rc.mu.Lock() + defer rc.mu.Unlock() + + rc.counter[fileName]-- + if rc.counter[fileName] <= 0 { + delete(rc.counter, fileName) + err := os.Remove(fileName) + if err != nil { + return err + } + } + return nil +} + // LogFile is Logger implementation for default Docker logging. type LogFile struct { - f *os.File // store for closing - closed bool - mu sync.RWMutex - capacity int64 //maximum size of each file - currentSize int64 // current size of the latest file - maxFiles int //maximum number of files - notifyRotate *pubsub.Publisher - marshal logger.MarshalFunc - createDecoder makeDecoderFunc - perms os.FileMode + mu sync.RWMutex // protects the logfile access + f *os.File // store for closing + closed bool + rotateMu sync.Mutex // blocks the next rotation until the current rotation is completed + capacity int64 // maximum size of each file + currentSize int64 // current size of the latest file + maxFiles int // maximum number of files + compress bool // whether old versions of log files are compressed + lastTimestamp time.Time // timestamp of the last log + filesRefCounter refCounter // keep reference-counted of decompressed files + notifyRotate *pubsub.Publisher + marshal logger.MarshalFunc + createDecoder makeDecoderFunc + perms os.FileMode } type makeDecoderFunc func(rdr io.Reader) func() (*logger.Message, error) //NewLogFile creates new LogFile -func NewLogFile(logPath string, capacity int64, maxFiles int, marshaller logger.MarshalFunc, decodeFunc makeDecoderFunc, perms os.FileMode) (*LogFile, error) { +func NewLogFile(logPath string, capacity int64, maxFiles int, compress bool, marshaller logger.MarshalFunc, decodeFunc makeDecoderFunc, perms os.FileMode) (*LogFile, error) { log, err := os.OpenFile(logPath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, perms) if err != nil { return nil, err @@ -49,14 +110,16 @@ func NewLogFile(logPath string, capacity int64, maxFiles int, marshaller logger. } return &LogFile{ - f: log, - capacity: capacity, - currentSize: size, - maxFiles: maxFiles, - notifyRotate: pubsub.NewPublisher(0, 1), - marshal: marshaller, - createDecoder: decodeFunc, - perms: perms, + f: log, + capacity: capacity, + currentSize: size, + maxFiles: maxFiles, + compress: compress, + filesRefCounter: refCounter{counter: make(map[string]int)}, + notifyRotate: pubsub.NewPublisher(0, 1), + marshal: marshaller, + createDecoder: decodeFunc, + perms: perms, }, nil } @@ -84,6 +147,7 @@ func (w *LogFile) WriteLogEntry(msg *logger.Message) error { n, err := w.f.Write(b) if err == nil { w.currentSize += int64(n) + w.lastTimestamp = msg.Timestamp } w.mu.Unlock() return err @@ -95,43 +159,108 @@ func (w *LogFile) checkCapacityAndRotate() error { } if w.currentSize >= w.capacity { - name := w.f.Name() + w.rotateMu.Lock() + fname := w.f.Name() if err := w.f.Close(); err != nil { + w.rotateMu.Unlock() return errors.Wrap(err, "error closing file") } - if err := rotate(name, w.maxFiles); err != nil { + if err := rotate(fname, w.maxFiles, w.compress); err != nil { + w.rotateMu.Unlock() return err } - file, err := os.OpenFile(name, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, w.perms) + file, err := os.OpenFile(fname, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, w.perms) if err != nil { + w.rotateMu.Unlock() return err } w.f = file w.currentSize = 0 w.notifyRotate.Publish(struct{}{}) + + if w.maxFiles <= 1 || !w.compress { + w.rotateMu.Unlock() + return nil + } + + go func() { + compressFile(fname+".1", w.lastTimestamp) + w.rotateMu.Unlock() + }() } return nil } -func rotate(name string, maxFiles int) error { +func rotate(name string, maxFiles int, compress bool) error { if maxFiles < 2 { return nil } + + var extension string + if compress { + extension = ".gz" + } for i := maxFiles - 1; i > 1; i-- { - toPath := name + "." + strconv.Itoa(i) - fromPath := name + "." + strconv.Itoa(i-1) + toPath := name + "." + strconv.Itoa(i) + extension + fromPath := name + "." + strconv.Itoa(i-1) + extension if err := os.Rename(fromPath, toPath); err != nil && !os.IsNotExist(err) { - return errors.Wrap(err, "error rotating old log entries") + return err } } if err := os.Rename(name, name+".1"); err != nil && !os.IsNotExist(err) { - return errors.Wrap(err, "error rotating current log") + return err } + return nil } +func compressFile(fileName string, lastTimestamp time.Time) { + file, err := os.Open(fileName) + if err != nil { + logrus.Errorf("Failed to open log file: %v", err) + return + } + defer func() { + file.Close() + err := os.Remove(fileName) + if err != nil { + logrus.Errorf("Failed to remove source log file: %v", err) + } + }() + + outFile, err := os.OpenFile(fileName+".gz", os.O_CREATE|os.O_RDWR, 0640) + if err != nil { + logrus.Errorf("Failed to open or create gzip log file: %v", err) + return + } + defer func() { + outFile.Close() + if err != nil { + os.Remove(fileName + ".gz") + } + }() + + compressWriter := gzip.NewWriter(outFile) + defer compressWriter.Close() + + // Add the last log entry timestramp to the gzip header + extra := rotateFileMetadata{} + extra.LastTime = lastTimestamp + compressWriter.Header.Extra, err = json.Marshal(&extra) + if err != nil { + // Here log the error only and don't return since this is just an optimization. + logrus.Warningf("Failed to marshal JSON: %v", err) + } + + _, err = pools.Copy(compressWriter, file) + if err != nil { + logrus.WithError(err).WithField("module", "container.logs").WithField("file", fileName).Error("Error compressing log file") + return + } +} + // MaxFiles return maximum number of files func (w *LogFile) MaxFiles() int { return w.maxFiles @@ -154,18 +283,6 @@ func (w *LogFile) Close() error { // ReadLogs decodes entries from log files and sends them the passed in watcher func (w *LogFile) ReadLogs(config logger.ReadConfig, watcher *logger.LogWatcher) { w.mu.RLock() - files, err := w.openRotatedFiles() - if err != nil { - w.mu.RUnlock() - watcher.Err <- err - return - } - defer func() { - for _, f := range files { - f.Close() - } - }() - currentFile, err := os.Open(w.f.Name()) if err != nil { w.mu.RUnlock() @@ -175,14 +292,20 @@ func (w *LogFile) ReadLogs(config logger.ReadConfig, watcher *logger.LogWatcher) defer currentFile.Close() currentChunk, err := newSectionReader(currentFile) - w.mu.RUnlock() - if err != nil { + w.mu.RUnlock() watcher.Err <- err return } if config.Tail != 0 { + files, err := w.openRotatedFiles(config) + if err != nil { + w.mu.RUnlock() + watcher.Err <- err + return + } + w.mu.RUnlock() seekers := make([]io.ReadSeeker, 0, len(files)+1) for _, f := range files { seekers = append(seekers, f) @@ -193,9 +316,20 @@ func (w *LogFile) ReadLogs(config logger.ReadConfig, watcher *logger.LogWatcher) if len(seekers) > 0 { tailFile(multireader.MultiReadSeeker(seekers...), watcher, w.createDecoder, config) } + for _, f := range files { + f.Close() + fileName := f.Name() + if strings.HasSuffix(fileName, tmpLogfileSuffix) { + err := w.filesRefCounter.Dereference(fileName) + if err != nil { + logrus.Errorf("Failed to dereference the log file %q: %v", fileName, err) + } + } + } + + w.mu.RLock() } - w.mu.RLock() if !config.Follow || w.closed { w.mu.RUnlock() return @@ -207,13 +341,22 @@ func (w *LogFile) ReadLogs(config logger.ReadConfig, watcher *logger.LogWatcher) followLogs(currentFile, watcher, notifyRotate, w.createDecoder, config.Since, config.Until) } -func (w *LogFile) openRotatedFiles() (files []*os.File, err error) { +func (w *LogFile) openRotatedFiles(config logger.ReadConfig) (files []*os.File, err error) { + w.rotateMu.Lock() + defer w.rotateMu.Unlock() + defer func() { if err == nil { return } for _, f := range files { f.Close() + if strings.HasSuffix(f.Name(), tmpLogfileSuffix) { + err := os.Remove(f.Name()) + if err != nil && !os.IsNotExist(err) { + logrus.Warningf("Failed to remove the logfile %q: %v", f.Name, err) + } + } } }() @@ -223,6 +366,28 @@ func (w *LogFile) openRotatedFiles() (files []*os.File, err error) { if !os.IsNotExist(err) { return nil, err } + + fileName := fmt.Sprintf("%s.%d.gz", w.f.Name(), i-1) + decompressedFileName := fileName + tmpLogfileSuffix + tmpFile, err := w.filesRefCounter.GetReference(decompressedFileName, func(refFileName string, exists bool) (*os.File, error) { + if exists { + return os.Open(refFileName) + } + return decompressfile(fileName, refFileName, config.Since) + }) + + if err != nil { + if !os.IsNotExist(err) { + return nil, err + } + continue + } + if tmpFile == nil { + // The log before `config.Since` does not need to read + break + } + + files = append(files, tmpFile) continue } files = append(files, f) @@ -231,6 +396,44 @@ func (w *LogFile) openRotatedFiles() (files []*os.File, err error) { return files, nil } +func decompressfile(fileName, destFileName string, since time.Time) (*os.File, error) { + cf, err := os.Open(fileName) + if err != nil { + return nil, err + } + defer cf.Close() + + rc, err := gzip.NewReader(cf) + if err != nil { + return nil, err + } + defer rc.Close() + + // Extract the last log entry timestramp from the gzip header + extra := &rotateFileMetadata{} + err = json.Unmarshal(rc.Header.Extra, extra) + if err == nil && extra.LastTime.Before(since) { + return nil, nil + } + + rs, err := os.OpenFile(destFileName, os.O_CREATE|os.O_RDWR, 0640) + if err != nil { + return nil, err + } + + _, err = pools.Copy(rs, rc) + if err != nil { + rs.Close() + rErr := os.Remove(rs.Name()) + if rErr != nil && os.IsNotExist(rErr) { + logrus.Errorf("Failed to remove the logfile %q: %v", rs.Name(), rErr) + } + return nil, err + } + + return rs, nil +} + func newSectionReader(f *os.File) (*io.SectionReader, error) { // seek to the end to get the size // we'll leave this at the end of the file since section reader does not advance the reader diff --git a/components/engine/hack/test/e2e-run.sh b/components/engine/hack/test/e2e-run.sh index b80f7fc312..b1470d6547 100755 --- a/components/engine/hack/test/e2e-run.sh +++ b/components/engine/hack/test/e2e-run.sh @@ -13,8 +13,8 @@ export DOCKER_ENGINE_GOARCH=${DOCKER_ENGINE_GOARCH:-${ARCH}} : ${TESTDEBUG:=} integration_api_dirs=${TEST_INTEGRATION_DIR:-"$( - find ./integration -type d | - grep -vE '(^./integration($|/internal)|/testdata)')"} + find /tests/integration -type d | + grep -vE '(^/tests/integration($|/internal)|/testdata)')"} run_test_integration() { [[ "$TESTFLAGS" != *-check.f* ]] && run_test_integration_suites @@ -35,7 +35,7 @@ run_test_integration_suites() { run_test_integration_legacy_suites() { ( flags="-check.v -check.timeout=${TIMEOUT} -test.timeout=360m $TESTFLAGS" - cd test/integration-cli + cd /tests/integration-cli echo "Running $PWD" test_env ./test.main $flags ) diff --git a/components/engine/integration-cli/check_test.go b/components/engine/integration-cli/check_test.go index a9f94fb576..18d3d3780a 100644 --- a/components/engine/integration-cli/check_test.go +++ b/components/engine/integration-cli/check_test.go @@ -14,7 +14,6 @@ import ( "time" "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/cli/config" "github.com/docker/docker/integration-cli/checker" "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/cli/build/fakestorage" @@ -386,74 +385,6 @@ func (s *DockerSwarmSuite) TearDownTest(c *check.C) { s.ds.TearDownTest(c) } -func init() { - check.Suite(&DockerTrustSuite{ - ds: &DockerSuite{}, - }) -} - -type DockerTrustSuite struct { - ds *DockerSuite - reg *registry.V2 - not *testNotary -} - -func (s *DockerTrustSuite) OnTimeout(c *check.C) { - s.ds.OnTimeout(c) -} - -func (s *DockerTrustSuite) SetUpTest(c *check.C) { - testRequires(c, registry.Hosting, NotaryServerHosting) - s.reg = setupRegistry(c, false, "", "") - s.not = setupNotary(c) -} - -func (s *DockerTrustSuite) TearDownTest(c *check.C) { - if s.reg != nil { - s.reg.Close() - } - if s.not != nil { - s.not.Close() - } - - // Remove trusted keys and metadata after test - os.RemoveAll(filepath.Join(config.Dir(), "trust")) - s.ds.TearDownTest(c) -} - -func init() { - ds := &DockerSuite{} - check.Suite(&DockerTrustedSwarmSuite{ - trustSuite: DockerTrustSuite{ - ds: ds, - }, - swarmSuite: DockerSwarmSuite{ - ds: ds, - }, - }) -} - -type DockerTrustedSwarmSuite struct { - swarmSuite DockerSwarmSuite - trustSuite DockerTrustSuite - reg *registry.V2 - not *testNotary -} - -func (s *DockerTrustedSwarmSuite) SetUpTest(c *check.C) { - s.swarmSuite.SetUpTest(c) - s.trustSuite.SetUpTest(c) -} - -func (s *DockerTrustedSwarmSuite) TearDownTest(c *check.C) { - s.trustSuite.TearDownTest(c) - s.swarmSuite.TearDownTest(c) -} - -func (s *DockerTrustedSwarmSuite) OnTimeout(c *check.C) { - s.swarmSuite.OnTimeout(c) -} - func init() { check.Suite(&DockerPluginSuite{ ds: &DockerSuite{}, diff --git a/components/engine/integration-cli/docker_cli_build_test.go b/components/engine/integration-cli/docker_cli_build_test.go index fc2dafe411..65c63abdb6 100644 --- a/components/engine/integration-cli/docker_cli_build_test.go +++ b/components/engine/integration-cli/docker_cli_build_test.go @@ -4048,140 +4048,6 @@ func (s *DockerSuite) TestBuildRUNErrMsg(c *check.C) { }) } -func (s *DockerTrustSuite) TestTrustedBuild(c *check.C) { - repoName := s.setupTrustedImage(c, "trusted-build") - dockerFile := fmt.Sprintf(` - FROM %s - RUN [] - `, repoName) - - name := "testtrustedbuild" - - buildImage(name, trustedBuild, build.WithDockerfile(dockerFile)).Assert(c, icmd.Expected{ - Out: fmt.Sprintf("FROM %s@sha", repoName[:len(repoName)-7]), - }) - - // We should also have a tag reference for the image. - dockerCmd(c, "inspect", repoName) - - // We should now be able to remove the tag reference. - dockerCmd(c, "rmi", repoName) -} - -func (s *DockerTrustSuite) TestTrustedBuildUntrustedTag(c *check.C) { - repoName := fmt.Sprintf("%v/dockercli/build-untrusted-tag:latest", privateRegistryURL) - dockerFile := fmt.Sprintf(` - FROM %s - RUN [] - `, repoName) - - name := "testtrustedbuilduntrustedtag" - - buildImage(name, trustedBuild, build.WithDockerfile(dockerFile)).Assert(c, icmd.Expected{ - ExitCode: 1, - Err: "does not have trust data for", - }) -} - -// FIXME(vdemeester) should migrate to docker/cli e2e tests -func (s *DockerTrustSuite) TestBuildContextDirIsSymlink(c *check.C) { - testRequires(c, DaemonIsLinux) - tempDir, err := ioutil.TempDir("", "test-build-dir-is-symlink-") - c.Assert(err, check.IsNil) - defer os.RemoveAll(tempDir) - - // Make a real context directory in this temp directory with a simple - // Dockerfile. - realContextDirname := filepath.Join(tempDir, "context") - if err := os.Mkdir(realContextDirname, os.FileMode(0755)); err != nil { - c.Fatal(err) - } - - if err = ioutil.WriteFile( - filepath.Join(realContextDirname, "Dockerfile"), - []byte(` - FROM busybox - RUN echo hello world - `), - os.FileMode(0644), - ); err != nil { - c.Fatal(err) - } - - // Make a symlink to the real context directory. - contextSymlinkName := filepath.Join(tempDir, "context_link") - if err := os.Symlink(realContextDirname, contextSymlinkName); err != nil { - c.Fatal(err) - } - - // Executing the build with the symlink as the specified context should - // *not* fail. - dockerCmd(c, "build", contextSymlinkName) -} - -func (s *DockerTrustSuite) TestTrustedBuildTagFromReleasesRole(c *check.C) { - testRequires(c, NotaryHosting) - - latestTag := s.setupTrustedImage(c, "trusted-build-releases-role") - repoName := strings.TrimSuffix(latestTag, ":latest") - - // Now create the releases role - s.notaryCreateDelegation(c, repoName, "targets/releases", s.not.keys[0].Public) - s.notaryImportKey(c, repoName, "targets/releases", s.not.keys[0].Private) - s.notaryPublish(c, repoName) - - // push a different tag to the releases role - otherTag := fmt.Sprintf("%s:other", repoName) - cli.DockerCmd(c, "tag", "busybox", otherTag) - - cli.Docker(cli.Args("push", otherTag), trustedCmd).Assert(c, icmd.Success) - s.assertTargetInRoles(c, repoName, "other", "targets/releases") - s.assertTargetNotInRoles(c, repoName, "other", "targets") - - cli.DockerCmd(c, "rmi", otherTag) - - dockerFile := fmt.Sprintf(` - FROM %s - RUN [] - `, otherTag) - name := "testtrustedbuildreleasesrole" - cli.BuildCmd(c, name, trustedCmd, build.WithDockerfile(dockerFile)).Assert(c, icmd.Expected{ - Out: fmt.Sprintf("FROM %s@sha", repoName), - }) -} - -func (s *DockerTrustSuite) TestTrustedBuildTagIgnoresOtherDelegationRoles(c *check.C) { - testRequires(c, NotaryHosting) - - latestTag := s.setupTrustedImage(c, "trusted-build-releases-role") - repoName := strings.TrimSuffix(latestTag, ":latest") - - // Now create a non-releases delegation role - s.notaryCreateDelegation(c, repoName, "targets/other", s.not.keys[0].Public) - s.notaryImportKey(c, repoName, "targets/other", s.not.keys[0].Private) - s.notaryPublish(c, repoName) - - // push a different tag to the other role - otherTag := fmt.Sprintf("%s:other", repoName) - cli.DockerCmd(c, "tag", "busybox", otherTag) - - cli.Docker(cli.Args("push", otherTag), trustedCmd).Assert(c, icmd.Success) - s.assertTargetInRoles(c, repoName, "other", "targets/other") - s.assertTargetNotInRoles(c, repoName, "other", "targets") - - cli.DockerCmd(c, "rmi", otherTag) - - dockerFile := fmt.Sprintf(` - FROM %s - RUN [] - `, otherTag) - - name := "testtrustedbuildotherrole" - cli.Docker(cli.Build(name), trustedCmd, build.WithDockerfile(dockerFile)).Assert(c, icmd.Expected{ - ExitCode: 1, - }) -} - // Issue #15634: COPY fails when path starts with "null" func (s *DockerSuite) TestBuildNullStringInAddCopyVolume(c *check.C) { name := "testbuildnullstringinaddcopyvolume" @@ -6018,28 +5884,6 @@ func (s *DockerSuite) TestBuildMultiStageNameVariants(c *check.C) { cli.Docker(cli.Args("run", "build1", "cat", "f2")).Assert(c, icmd.Expected{Out: "bar2"}) } -func (s *DockerTrustSuite) TestBuildMultiStageTrusted(c *check.C) { - img1 := s.setupTrustedImage(c, "trusted-build1") - img2 := s.setupTrustedImage(c, "trusted-build2") - dockerFile := fmt.Sprintf(` - FROM %s AS build-base - RUN echo ok > /foo - FROM %s - COPY --from=build-base foo bar`, img1, img2) - - name := "testcopyfromtrustedbuild" - - r := buildImage(name, trustedBuild, build.WithDockerfile(dockerFile)) - r.Assert(c, icmd.Expected{ - Out: fmt.Sprintf("FROM %s@sha", img1[:len(img1)-7]), - }) - r.Assert(c, icmd.Expected{ - Out: fmt.Sprintf("FROM %s@sha", img2[:len(img2)-7]), - }) - - dockerCmdWithResult("run", name, "cat", "bar").Assert(c, icmd.Expected{Out: "ok"}) -} - func (s *DockerSuite) TestBuildMultiStageMultipleBuildsWindows(c *check.C) { testRequires(c, DaemonIsWindows) dockerfile := ` diff --git a/components/engine/integration-cli/docker_cli_create_test.go b/components/engine/integration-cli/docker_cli_create_test.go index 448af9f199..120b62bc0f 100644 --- a/components/engine/integration-cli/docker_cli_create_test.go +++ b/components/engine/integration-cli/docker_cli_create_test.go @@ -3,7 +3,6 @@ package main import ( "encoding/json" "fmt" - "io/ioutil" "os" "reflect" "strings" @@ -16,7 +15,6 @@ import ( "github.com/docker/docker/pkg/stringid" "github.com/docker/go-connections/nat" "github.com/go-check/check" - "github.com/gotestyourself/gotestyourself/icmd" ) // Make sure we can create a simple container with some args @@ -292,75 +290,6 @@ func (s *DockerSuite) TestCreateByImageID(c *check.C) { } } -func (s *DockerTrustSuite) TestTrustedCreate(c *check.C) { - repoName := s.setupTrustedImage(c, "trusted-create") - - // Try create - cli.Docker(cli.Args("create", repoName), trustedCmd).Assert(c, SuccessTagging) - cli.DockerCmd(c, "rmi", repoName) - - // Try untrusted create to ensure we pushed the tag to the registry - cli.Docker(cli.Args("create", "--disable-content-trust=true", repoName)).Assert(c, SuccessDownloadedOnStderr) -} - -func (s *DockerTrustSuite) TestUntrustedCreate(c *check.C) { - repoName := fmt.Sprintf("%v/dockercliuntrusted/createtest", privateRegistryURL) - withTagName := fmt.Sprintf("%s:latest", repoName) - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", withTagName) - cli.DockerCmd(c, "push", withTagName) - cli.DockerCmd(c, "rmi", withTagName) - - // Try trusted create on untrusted tag - cli.Docker(cli.Args("create", withTagName), trustedCmd).Assert(c, icmd.Expected{ - ExitCode: 1, - Err: fmt.Sprintf("does not have trust data for %s", repoName), - }) -} - -func (s *DockerTrustSuite) TestTrustedIsolatedCreate(c *check.C) { - repoName := s.setupTrustedImage(c, "trusted-isolated-create") - - // Try create - cli.Docker(cli.Args("--config", "/tmp/docker-isolated-create", "create", repoName), trustedCmd).Assert(c, SuccessTagging) - defer os.RemoveAll("/tmp/docker-isolated-create") - - cli.DockerCmd(c, "rmi", repoName) -} - -func (s *DockerTrustSuite) TestTrustedCreateFromBadTrustServer(c *check.C) { - repoName := fmt.Sprintf("%v/dockerclievilcreate/trusted:latest", privateRegistryURL) - evilLocalConfigDir, err := ioutil.TempDir("", "evilcreate-local-config-dir") - c.Assert(err, check.IsNil) - - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", repoName) - cli.Docker(cli.Args("push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing) - cli.DockerCmd(c, "rmi", repoName) - - // Try create - cli.Docker(cli.Args("create", repoName), trustedCmd).Assert(c, SuccessTagging) - cli.DockerCmd(c, "rmi", repoName) - - // Kill the notary server, start a new "evil" one. - s.not.Close() - s.not, err = newTestNotary(c) - c.Assert(err, check.IsNil) - - // In order to make an evil server, lets re-init a client (with a different trust dir) and push new data. - // tag an image and upload it to the private registry - cli.DockerCmd(c, "--config", evilLocalConfigDir, "tag", "busybox", repoName) - - // Push up to the new server - cli.Docker(cli.Args("--config", evilLocalConfigDir, "push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing) - - // Now, try creating with the original client from this new trust server. This should fail because the new root is invalid. - cli.Docker(cli.Args("create", repoName), trustedCmd).Assert(c, icmd.Expected{ - ExitCode: 1, - Err: "could not rotate trust to a new trusted root", - }) -} - func (s *DockerSuite) TestCreateStopSignal(c *check.C) { name := "test_create_stop_signal" dockerCmd(c, "create", "--name", name, "--stop-signal", "9", "busybox") diff --git a/components/engine/integration-cli/docker_cli_plugins_test.go b/components/engine/integration-cli/docker_cli_plugins_test.go index 8ca7254440..8a936e3e44 100644 --- a/components/engine/integration-cli/docker_cli_plugins_test.go +++ b/components/engine/integration-cli/docker_cli_plugins_test.go @@ -16,7 +16,6 @@ import ( "github.com/docker/docker/integration-cli/daemon" "github.com/docker/docker/integration-cli/fixtures/plugin" "github.com/go-check/check" - "github.com/gotestyourself/gotestyourself/icmd" "golang.org/x/net/context" ) @@ -352,51 +351,6 @@ func (s *DockerSuite) TestPluginInspectOnWindows(c *check.C) { c.Assert(err.Error(), checker.Contains, "plugins are not supported on this platform") } -func (s *DockerTrustSuite) TestPluginTrustedInstall(c *check.C) { - testRequires(c, DaemonIsLinux, IsAmd64, Network) - - trustedName := s.setupTrustedplugin(c, pNameWithTag, "trusted-plugin-install") - - cli.Docker(cli.Args("plugin", "install", "--grant-all-permissions", trustedName), trustedCmd).Assert(c, icmd.Expected{ - Out: trustedName, - }) - - out := cli.DockerCmd(c, "plugin", "ls").Combined() - c.Assert(out, checker.Contains, "true") - - out = cli.DockerCmd(c, "plugin", "disable", trustedName).Combined() - c.Assert(strings.TrimSpace(out), checker.Contains, trustedName) - - out = cli.DockerCmd(c, "plugin", "enable", trustedName).Combined() - c.Assert(strings.TrimSpace(out), checker.Contains, trustedName) - - out = cli.DockerCmd(c, "plugin", "rm", "-f", trustedName).Combined() - c.Assert(strings.TrimSpace(out), checker.Contains, trustedName) - - // Try untrusted pull to ensure we pushed the tag to the registry - cli.Docker(cli.Args("plugin", "install", "--disable-content-trust=true", "--grant-all-permissions", trustedName), trustedCmd).Assert(c, SuccessDownloaded) - - out = cli.DockerCmd(c, "plugin", "ls").Combined() - c.Assert(out, checker.Contains, "true") - -} - -func (s *DockerTrustSuite) TestPluginUntrustedInstall(c *check.C) { - testRequires(c, DaemonIsLinux, IsAmd64, Network) - - pluginName := fmt.Sprintf("%v/dockercliuntrusted/plugintest:latest", privateRegistryURL) - // install locally and push to private registry - cli.DockerCmd(c, "plugin", "install", "--grant-all-permissions", "--alias", pluginName, pNameWithTag) - cli.DockerCmd(c, "plugin", "push", pluginName) - cli.DockerCmd(c, "plugin", "rm", "-f", pluginName) - - // Try trusted install on untrusted plugin - cli.Docker(cli.Args("plugin", "install", "--grant-all-permissions", pluginName), trustedCmd).Assert(c, icmd.Expected{ - ExitCode: 1, - Err: "Error: remote trust data does not exist", - }) -} - func (ps *DockerPluginSuite) TestPluginIDPrefix(c *check.C) { name := "test" client := testEnv.APIClient() diff --git a/components/engine/integration-cli/docker_cli_pull_trusted_test.go b/components/engine/integration-cli/docker_cli_pull_trusted_test.go deleted file mode 100644 index 60e1c3db1d..0000000000 --- a/components/engine/integration-cli/docker_cli_pull_trusted_test.go +++ /dev/null @@ -1,222 +0,0 @@ -package main - -import ( - "fmt" - "io/ioutil" - - "github.com/docker/docker/integration-cli/checker" - "github.com/docker/docker/integration-cli/cli" - "github.com/docker/docker/integration-cli/cli/build" - "github.com/go-check/check" - "github.com/gotestyourself/gotestyourself/icmd" -) - -func (s *DockerTrustSuite) TestTrustedPull(c *check.C) { - repoName := s.setupTrustedImage(c, "trusted-pull") - - // Try pull - cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, SuccessTagging) - - cli.DockerCmd(c, "rmi", repoName) - // Try untrusted pull to ensure we pushed the tag to the registry - cli.Docker(cli.Args("pull", "--disable-content-trust=true", repoName), trustedCmd).Assert(c, SuccessDownloaded) -} - -func (s *DockerTrustSuite) TestTrustedIsolatedPull(c *check.C) { - repoName := s.setupTrustedImage(c, "trusted-isolated-pull") - - // Try pull (run from isolated directory without trust information) - cli.Docker(cli.Args("--config", "/tmp/docker-isolated", "pull", repoName), trustedCmd).Assert(c, SuccessTagging) - - cli.DockerCmd(c, "rmi", repoName) -} - -func (s *DockerTrustSuite) TestUntrustedPull(c *check.C) { - repoName := fmt.Sprintf("%v/dockercliuntrusted/pulltest:latest", privateRegistryURL) - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", repoName) - cli.DockerCmd(c, "push", repoName) - cli.DockerCmd(c, "rmi", repoName) - - // Try trusted pull on untrusted tag - cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, icmd.Expected{ - ExitCode: 1, - Err: "Error: remote trust data does not exist", - }) -} - -func (s *DockerTrustSuite) TestTrustedPullFromBadTrustServer(c *check.C) { - repoName := fmt.Sprintf("%v/dockerclievilpull/trusted:latest", privateRegistryURL) - evilLocalConfigDir, err := ioutil.TempDir("", "evil-local-config-dir") - if err != nil { - c.Fatalf("Failed to create local temp dir") - } - - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", repoName) - - cli.Docker(cli.Args("push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing) - cli.DockerCmd(c, "rmi", repoName) - - // Try pull - cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, SuccessTagging) - cli.DockerCmd(c, "rmi", repoName) - - // Kill the notary server, start a new "evil" one. - s.not.Close() - s.not, err = newTestNotary(c) - - c.Assert(err, check.IsNil, check.Commentf("Restarting notary server failed.")) - - // In order to make an evil server, lets re-init a client (with a different trust dir) and push new data. - // tag an image and upload it to the private registry - cli.DockerCmd(c, "--config", evilLocalConfigDir, "tag", "busybox", repoName) - - // Push up to the new server - cli.Docker(cli.Args("--config", evilLocalConfigDir, "push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing) - - // Now, try pulling with the original client from this new trust server. This should fail because the new root is invalid. - cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, icmd.Expected{ - ExitCode: 1, - Err: "could not rotate trust to a new trusted root", - }) -} - -func (s *DockerTrustSuite) TestTrustedOfflinePull(c *check.C) { - repoName := s.setupTrustedImage(c, "trusted-offline-pull") - - cli.Docker(cli.Args("pull", repoName), trustedCmdWithServer("https://invalidnotaryserver")).Assert(c, icmd.Expected{ - ExitCode: 1, - Err: "error contacting notary server", - }) - // Do valid trusted pull to warm cache - cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, SuccessTagging) - cli.DockerCmd(c, "rmi", repoName) - - // Try pull again with invalid notary server, should use cache - cli.Docker(cli.Args("pull", repoName), trustedCmdWithServer("https://invalidnotaryserver")).Assert(c, SuccessTagging) -} - -func (s *DockerTrustSuite) TestTrustedPullDelete(c *check.C) { - repoName := fmt.Sprintf("%v/dockercli/%s:latest", privateRegistryURL, "trusted-pull-delete") - // tag the image and upload it to the private registry - cli.BuildCmd(c, repoName, build.WithDockerfile(` - FROM busybox - CMD echo trustedpulldelete - `)) - cli.Docker(cli.Args("push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing) - - cli.DockerCmd(c, "rmi", repoName) - - // Try pull - result := cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, icmd.Success) - - matches := digestRegex.FindStringSubmatch(result.Combined()) - c.Assert(matches, checker.HasLen, 2, check.Commentf("unable to parse digest from pull output: %s", result.Combined())) - pullDigest := matches[1] - - imageID := inspectField(c, repoName, "Id") - - imageByDigest := repoName + "@" + pullDigest - byDigestID := inspectField(c, imageByDigest, "Id") - - c.Assert(byDigestID, checker.Equals, imageID) - - // rmi of tag should also remove the digest reference - cli.DockerCmd(c, "rmi", repoName) - - _, err := inspectFieldWithError(imageByDigest, "Id") - c.Assert(err, checker.NotNil, check.Commentf("digest reference should have been removed")) - - _, err = inspectFieldWithError(imageID, "Id") - c.Assert(err, checker.NotNil, check.Commentf("image should have been deleted")) -} - -func (s *DockerTrustSuite) TestTrustedPullReadsFromReleasesRole(c *check.C) { - testRequires(c, NotaryHosting) - repoName := fmt.Sprintf("%v/dockerclireleasesdelegationpulling/trusted", privateRegistryURL) - targetName := fmt.Sprintf("%s:latest", repoName) - - // Push with targets first, initializing the repo - cli.DockerCmd(c, "tag", "busybox", targetName) - cli.Docker(cli.Args("push", targetName), trustedCmd).Assert(c, icmd.Success) - s.assertTargetInRoles(c, repoName, "latest", "targets") - - // Try pull, check we retrieve from targets role - cli.Docker(cli.Args("-D", "pull", repoName), trustedCmd).Assert(c, icmd.Expected{ - Err: "retrieving target for targets role", - }) - - // Now we'll create the releases role, and try pushing and pulling - s.notaryCreateDelegation(c, repoName, "targets/releases", s.not.keys[0].Public) - s.notaryImportKey(c, repoName, "targets/releases", s.not.keys[0].Private) - s.notaryPublish(c, repoName) - - // try a pull, check that we can still pull because we can still read the - // old tag in the targets role - cli.Docker(cli.Args("-D", "pull", repoName), trustedCmd).Assert(c, icmd.Expected{ - Err: "retrieving target for targets role", - }) - - // try a pull -a, check that it succeeds because we can still pull from the - // targets role - cli.Docker(cli.Args("-D", "pull", "-a", repoName), trustedCmd).Assert(c, icmd.Success) - - // Push, should sign with targets/releases - cli.DockerCmd(c, "tag", "busybox", targetName) - cli.Docker(cli.Args("push", targetName), trustedCmd).Assert(c, icmd.Success) - s.assertTargetInRoles(c, repoName, "latest", "targets", "targets/releases") - - // Try pull, check we retrieve from targets/releases role - cli.Docker(cli.Args("-D", "pull", repoName), trustedCmd).Assert(c, icmd.Expected{ - Err: "retrieving target for targets/releases role", - }) - - // Create another delegation that we'll sign with - s.notaryCreateDelegation(c, repoName, "targets/other", s.not.keys[1].Public) - s.notaryImportKey(c, repoName, "targets/other", s.not.keys[1].Private) - s.notaryPublish(c, repoName) - - cli.DockerCmd(c, "tag", "busybox", targetName) - cli.Docker(cli.Args("push", targetName), trustedCmd).Assert(c, icmd.Success) - s.assertTargetInRoles(c, repoName, "latest", "targets", "targets/releases", "targets/other") - - // Try pull, check we retrieve from targets/releases role - cli.Docker(cli.Args("-D", "pull", repoName), trustedCmd).Assert(c, icmd.Expected{ - Err: "retrieving target for targets/releases role", - }) -} - -func (s *DockerTrustSuite) TestTrustedPullIgnoresOtherDelegationRoles(c *check.C) { - testRequires(c, NotaryHosting) - repoName := fmt.Sprintf("%v/dockerclipullotherdelegation/trusted", privateRegistryURL) - targetName := fmt.Sprintf("%s:latest", repoName) - - // We'll create a repo first with a non-release delegation role, so that when we - // push we'll sign it into the delegation role - s.notaryInitRepo(c, repoName) - s.notaryCreateDelegation(c, repoName, "targets/other", s.not.keys[0].Public) - s.notaryImportKey(c, repoName, "targets/other", s.not.keys[0].Private) - s.notaryPublish(c, repoName) - - // Push should write to the delegation role, not targets - cli.DockerCmd(c, "tag", "busybox", targetName) - cli.Docker(cli.Args("push", targetName), trustedCmd).Assert(c, icmd.Success) - s.assertTargetInRoles(c, repoName, "latest", "targets/other") - s.assertTargetNotInRoles(c, repoName, "latest", "targets") - - // Try pull - we should fail, since pull will only pull from the targets/releases - // role or the targets role - cli.DockerCmd(c, "tag", "busybox", targetName) - cli.Docker(cli.Args("-D", "pull", repoName), trustedCmd).Assert(c, icmd.Expected{ - ExitCode: 1, - Err: "No trust data for", - }) - - // try a pull -a: we should fail since pull will only pull from the targets/releases - // role or the targets role - cli.Docker(cli.Args("-D", "pull", "-a", repoName), trustedCmd).Assert(c, icmd.Expected{ - ExitCode: 1, - Err: "No trusted tags for", - }) -} diff --git a/components/engine/integration-cli/docker_cli_push_test.go b/components/engine/integration-cli/docker_cli_push_test.go index 94efa08eab..48d6be2ac1 100644 --- a/components/engine/integration-cli/docker_cli_push_test.go +++ b/components/engine/integration-cli/docker_cli_push_test.go @@ -7,14 +7,11 @@ import ( "net/http" "net/http/httptest" "os" - "path/filepath" "strings" "sync" "github.com/docker/distribution/reference" - "github.com/docker/docker/cli/config" "github.com/docker/docker/integration-cli/checker" - "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/cli/build" "github.com/go-check/check" "github.com/gotestyourself/gotestyourself/icmd" @@ -281,225 +278,6 @@ func (s *DockerSchema1RegistrySuite) TestCrossRepositoryLayerPushNotSupported(c c.Assert(out3, check.Equals, "hello world") } -func (s *DockerTrustSuite) TestTrustedPush(c *check.C) { - repoName := fmt.Sprintf("%v/dockerclitrusted/pushtest:latest", privateRegistryURL) - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", repoName) - - cli.Docker(cli.Args("push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing) - - // Try pull after push - cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, icmd.Expected{ - Out: "Status: Image is up to date", - }) - - // Assert that we rotated the snapshot key to the server by checking our local keystore - contents, err := ioutil.ReadDir(filepath.Join(config.Dir(), "trust/private/tuf_keys", privateRegistryURL, "dockerclitrusted/pushtest")) - c.Assert(err, check.IsNil, check.Commentf("Unable to read local tuf key files")) - // Check that we only have 1 key (targets key) - c.Assert(contents, checker.HasLen, 1) -} - -func (s *DockerTrustSuite) TestTrustedPushWithEnvPasswords(c *check.C) { - repoName := fmt.Sprintf("%v/dockerclienv/trusted:latest", privateRegistryURL) - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", repoName) - - cli.Docker(cli.Args("push", repoName), trustedCmdWithPassphrases("12345678", "12345678")).Assert(c, SuccessSigningAndPushing) - - // Try pull after push - cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, icmd.Expected{ - Out: "Status: Image is up to date", - }) -} - -func (s *DockerTrustSuite) TestTrustedPushWithFailingServer(c *check.C) { - repoName := fmt.Sprintf("%v/dockerclitrusted/failingserver:latest", privateRegistryURL) - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", repoName) - - // Using a name that doesn't resolve to an address makes this test faster - cli.Docker(cli.Args("push", repoName), trustedCmdWithServer("https://server.invalid:81/")).Assert(c, icmd.Expected{ - ExitCode: 1, - Err: "error contacting notary server", - }) -} - -func (s *DockerTrustSuite) TestTrustedPushWithoutServerAndUntrusted(c *check.C) { - repoName := fmt.Sprintf("%v/dockerclitrusted/trustedandnot:latest", privateRegistryURL) - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", repoName) - - result := cli.Docker(cli.Args("push", "--disable-content-trust", repoName), trustedCmdWithServer("https://server.invalid:81/")) - result.Assert(c, icmd.Success) - c.Assert(result.Combined(), check.Not(checker.Contains), "Error establishing connection to notary repository", check.Commentf("Missing expected output on trusted push with --disable-content-trust:")) -} - -func (s *DockerTrustSuite) TestTrustedPushWithExistingTag(c *check.C) { - repoName := fmt.Sprintf("%v/dockerclitag/trusted:latest", privateRegistryURL) - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", repoName) - cli.DockerCmd(c, "push", repoName) - - cli.Docker(cli.Args("push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing) - - // Try pull after push - cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, icmd.Expected{ - Out: "Status: Image is up to date", - }) -} - -func (s *DockerTrustSuite) TestTrustedPushWithExistingSignedTag(c *check.C) { - repoName := fmt.Sprintf("%v/dockerclipushpush/trusted:latest", privateRegistryURL) - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", repoName) - - // Do a trusted push - cli.Docker(cli.Args("push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing) - - // Do another trusted push - cli.Docker(cli.Args("push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing) - cli.DockerCmd(c, "rmi", repoName) - - // Try pull to ensure the double push did not break our ability to pull - cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, SuccessDownloaded) -} - -func (s *DockerTrustSuite) TestTrustedPushWithIncorrectPassphraseForNonRoot(c *check.C) { - repoName := fmt.Sprintf("%v/dockercliincorretpwd/trusted:latest", privateRegistryURL) - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", repoName) - - // Push with default passphrases - cli.Docker(cli.Args("push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing) - - // Push with wrong passphrases - cli.Docker(cli.Args("push", repoName), trustedCmdWithPassphrases("12345678", "87654321")).Assert(c, icmd.Expected{ - ExitCode: 1, - Err: "could not find necessary signing keys", - }) -} - -func (s *DockerTrustSuite) TestTrustedPushWithReleasesDelegationOnly(c *check.C) { - testRequires(c, NotaryHosting) - repoName := fmt.Sprintf("%v/dockerclireleasedelegationinitfirst/trusted", privateRegistryURL) - targetName := fmt.Sprintf("%s:latest", repoName) - s.notaryInitRepo(c, repoName) - s.notaryCreateDelegation(c, repoName, "targets/releases", s.not.keys[0].Public) - s.notaryPublish(c, repoName) - - s.notaryImportKey(c, repoName, "targets/releases", s.not.keys[0].Private) - - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", targetName) - - cli.Docker(cli.Args("push", targetName), trustedCmd).Assert(c, SuccessSigningAndPushing) - // check to make sure that the target has been added to targets/releases and not targets - s.assertTargetInRoles(c, repoName, "latest", "targets/releases") - s.assertTargetNotInRoles(c, repoName, "latest", "targets") - - // Try pull after push - os.RemoveAll(filepath.Join(config.Dir(), "trust")) - - cli.Docker(cli.Args("pull", targetName), trustedCmd).Assert(c, icmd.Expected{ - Out: "Status: Image is up to date", - }) -} - -func (s *DockerTrustSuite) TestTrustedPushSignsAllFirstLevelRolesWeHaveKeysFor(c *check.C) { - testRequires(c, NotaryHosting) - repoName := fmt.Sprintf("%v/dockerclimanyroles/trusted", privateRegistryURL) - targetName := fmt.Sprintf("%s:latest", repoName) - s.notaryInitRepo(c, repoName) - s.notaryCreateDelegation(c, repoName, "targets/role1", s.not.keys[0].Public) - s.notaryCreateDelegation(c, repoName, "targets/role2", s.not.keys[1].Public) - s.notaryCreateDelegation(c, repoName, "targets/role3", s.not.keys[2].Public) - - // import everything except the third key - s.notaryImportKey(c, repoName, "targets/role1", s.not.keys[0].Private) - s.notaryImportKey(c, repoName, "targets/role2", s.not.keys[1].Private) - - s.notaryCreateDelegation(c, repoName, "targets/role1/subrole", s.not.keys[3].Public) - s.notaryImportKey(c, repoName, "targets/role1/subrole", s.not.keys[3].Private) - - s.notaryPublish(c, repoName) - - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", targetName) - - cli.Docker(cli.Args("push", targetName), trustedCmd).Assert(c, SuccessSigningAndPushing) - - // check to make sure that the target has been added to targets/role1 and targets/role2, and - // not targets (because there are delegations) or targets/role3 (due to missing key) or - // targets/role1/subrole (due to it being a second level delegation) - s.assertTargetInRoles(c, repoName, "latest", "targets/role1", "targets/role2") - s.assertTargetNotInRoles(c, repoName, "latest", "targets") - - // Try pull after push - os.RemoveAll(filepath.Join(config.Dir(), "trust")) - - // pull should fail because none of these are the releases role - cli.Docker(cli.Args("pull", targetName), trustedCmd).Assert(c, icmd.Expected{ - ExitCode: 1, - }) -} - -func (s *DockerTrustSuite) TestTrustedPushSignsForRolesWithKeysAndValidPaths(c *check.C) { - repoName := fmt.Sprintf("%v/dockerclirolesbykeysandpaths/trusted", privateRegistryURL) - targetName := fmt.Sprintf("%s:latest", repoName) - s.notaryInitRepo(c, repoName) - s.notaryCreateDelegation(c, repoName, "targets/role1", s.not.keys[0].Public, "l", "z") - s.notaryCreateDelegation(c, repoName, "targets/role2", s.not.keys[1].Public, "x", "y") - s.notaryCreateDelegation(c, repoName, "targets/role3", s.not.keys[2].Public, "latest") - s.notaryCreateDelegation(c, repoName, "targets/role4", s.not.keys[3].Public, "latest") - - // import everything except the third key - s.notaryImportKey(c, repoName, "targets/role1", s.not.keys[0].Private) - s.notaryImportKey(c, repoName, "targets/role2", s.not.keys[1].Private) - s.notaryImportKey(c, repoName, "targets/role4", s.not.keys[3].Private) - - s.notaryPublish(c, repoName) - - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", targetName) - - cli.Docker(cli.Args("push", targetName), trustedCmd).Assert(c, SuccessSigningAndPushing) - - // check to make sure that the target has been added to targets/role1 and targets/role4, and - // not targets (because there are delegations) or targets/role2 (due to path restrictions) or - // targets/role3 (due to missing key) - s.assertTargetInRoles(c, repoName, "latest", "targets/role1", "targets/role4") - s.assertTargetNotInRoles(c, repoName, "latest", "targets") - - // Try pull after push - os.RemoveAll(filepath.Join(config.Dir(), "trust")) - - // pull should fail because none of these are the releases role - cli.Docker(cli.Args("pull", targetName), trustedCmd).Assert(c, icmd.Expected{ - ExitCode: 1, - }) -} - -func (s *DockerTrustSuite) TestTrustedPushDoesntSignTargetsIfDelegationsExist(c *check.C) { - testRequires(c, NotaryHosting) - repoName := fmt.Sprintf("%v/dockerclireleasedelegationnotsignable/trusted", privateRegistryURL) - targetName := fmt.Sprintf("%s:latest", repoName) - s.notaryInitRepo(c, repoName) - s.notaryCreateDelegation(c, repoName, "targets/role1", s.not.keys[0].Public) - s.notaryPublish(c, repoName) - - // do not import any delegations key - - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", targetName) - - cli.Docker(cli.Args("push", targetName), trustedCmd).Assert(c, icmd.Expected{ - ExitCode: 1, - Err: "no valid signing keys", - }) - s.assertTargetNotInRoles(c, repoName, "latest", "targets", "targets/role1") -} - func (s *DockerRegistryAuthHtpasswdSuite) TestPushNoCredentialsNoRetry(c *check.C) { repoName := fmt.Sprintf("%s/busybox", privateRegistryURL) dockerCmd(c, "tag", "busybox", repoName) diff --git a/components/engine/integration-cli/docker_cli_run_test.go b/components/engine/integration-cli/docker_cli_run_test.go index 7afbebaccb..a4984862ee 100644 --- a/components/engine/integration-cli/docker_cli_run_test.go +++ b/components/engine/integration-cli/docker_cli_run_test.go @@ -3140,75 +3140,6 @@ func (s *DockerSuite) TestRunNetworkFilesBindMountROFilesystem(c *check.C) { } } -func (s *DockerTrustSuite) TestTrustedRun(c *check.C) { - // Windows does not support this functionality - testRequires(c, DaemonIsLinux) - repoName := s.setupTrustedImage(c, "trusted-run") - - // Try run - cli.Docker(cli.Args("run", repoName), trustedCmd).Assert(c, SuccessTagging) - cli.DockerCmd(c, "rmi", repoName) - - // Try untrusted run to ensure we pushed the tag to the registry - cli.Docker(cli.Args("run", "--disable-content-trust=true", repoName), trustedCmd).Assert(c, SuccessDownloadedOnStderr) -} - -func (s *DockerTrustSuite) TestUntrustedRun(c *check.C) { - // Windows does not support this functionality - testRequires(c, DaemonIsLinux) - repoName := fmt.Sprintf("%v/dockercliuntrusted/runtest:latest", privateRegistryURL) - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", repoName) - cli.DockerCmd(c, "push", repoName) - cli.DockerCmd(c, "rmi", repoName) - - // Try trusted run on untrusted tag - cli.Docker(cli.Args("run", repoName), trustedCmd).Assert(c, icmd.Expected{ - ExitCode: 125, - Err: "does not have trust data for", - }) -} - -func (s *DockerTrustSuite) TestTrustedRunFromBadTrustServer(c *check.C) { - // Windows does not support this functionality - testRequires(c, DaemonIsLinux) - repoName := fmt.Sprintf("%v/dockerclievilrun/trusted:latest", privateRegistryURL) - evilLocalConfigDir, err := ioutil.TempDir("", "evilrun-local-config-dir") - if err != nil { - c.Fatalf("Failed to create local temp dir") - } - - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", repoName) - - cli.Docker(cli.Args("push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing) - cli.DockerCmd(c, "rmi", repoName) - - // Try run - cli.Docker(cli.Args("run", repoName), trustedCmd).Assert(c, SuccessTagging) - cli.DockerCmd(c, "rmi", repoName) - - // Kill the notary server, start a new "evil" one. - s.not.Close() - s.not, err = newTestNotary(c) - if err != nil { - c.Fatalf("Restarting notary server failed.") - } - - // In order to make an evil server, lets re-init a client (with a different trust dir) and push new data. - // tag an image and upload it to the private registry - cli.DockerCmd(c, "--config", evilLocalConfigDir, "tag", "busybox", repoName) - - // Push up to the new server - cli.Docker(cli.Args("--config", evilLocalConfigDir, "push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing) - - // Now, try running with the original client from this new trust server. This should fail because the new root is invalid. - cli.Docker(cli.Args("run", repoName), trustedCmd).Assert(c, icmd.Expected{ - ExitCode: 125, - Err: "could not rotate trust to a new trusted root", - }) -} - func (s *DockerSuite) TestPtraceContainerProcsFromHost(c *check.C) { // Not applicable on Windows as uses Unix specific functionality testRequires(c, DaemonIsLinux, SameHostDaemon) diff --git a/components/engine/integration-cli/docker_cli_swarm_test.go b/components/engine/integration-cli/docker_cli_swarm_test.go index 8add18e1ec..4b3358255f 100644 --- a/components/engine/integration-cli/docker_cli_swarm_test.go +++ b/components/engine/integration-cli/docker_cli_swarm_test.go @@ -1560,78 +1560,6 @@ func (s *DockerSwarmSuite) TestSwarmNetworkIPAMOptions(c *check.C) { c.Assert(strings.TrimSpace(out), checker.Contains, "com.docker.network.ipam.serial:true") } -func (s *DockerTrustedSwarmSuite) TestTrustedServiceCreate(c *check.C) { - d := s.swarmSuite.AddDaemon(c, true, true) - - // Attempt creating a service from an image that is known to notary. - repoName := s.trustSuite.setupTrustedImage(c, "trusted-pull") - - name := "trusted" - cli.Docker(cli.Args("-D", "service", "create", "--detach", "--no-resolve-image", "--name", name, repoName, "top"), trustedCmd, cli.Daemon(d.Daemon)).Assert(c, icmd.Expected{ - Err: "resolved image tag to", - }) - - out, err := d.Cmd("service", "inspect", "--pretty", name) - c.Assert(err, checker.IsNil, check.Commentf(out)) - c.Assert(out, checker.Contains, repoName+"@", check.Commentf(out)) - - // Try trusted service create on an untrusted tag. - - repoName = fmt.Sprintf("%v/untrustedservicecreate/createtest:latest", privateRegistryURL) - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", repoName) - cli.DockerCmd(c, "push", repoName) - cli.DockerCmd(c, "rmi", repoName) - - name = "untrusted" - cli.Docker(cli.Args("service", "create", "--detach", "--no-resolve-image", "--name", name, repoName, "top"), trustedCmd, cli.Daemon(d.Daemon)).Assert(c, icmd.Expected{ - ExitCode: 1, - Err: "Error: remote trust data does not exist", - }) - - out, err = d.Cmd("service", "inspect", "--pretty", name) - c.Assert(err, checker.NotNil, check.Commentf(out)) -} - -func (s *DockerTrustedSwarmSuite) TestTrustedServiceUpdate(c *check.C) { - d := s.swarmSuite.AddDaemon(c, true, true) - - // Attempt creating a service from an image that is known to notary. - repoName := s.trustSuite.setupTrustedImage(c, "trusted-pull") - - name := "myservice" - - // Create a service without content trust - cli.Docker(cli.Args("service", "create", "--detach", "--no-resolve-image", "--name", name, repoName, "top"), cli.Daemon(d.Daemon)).Assert(c, icmd.Success) - - result := cli.Docker(cli.Args("service", "inspect", "--pretty", name), cli.Daemon(d.Daemon)) - c.Assert(result.Error, checker.IsNil, check.Commentf(result.Combined())) - // Daemon won't insert the digest because this is disabled by - // DOCKER_SERVICE_PREFER_OFFLINE_IMAGE. - c.Assert(result.Combined(), check.Not(checker.Contains), repoName+"@", check.Commentf(result.Combined())) - - cli.Docker(cli.Args("-D", "service", "update", "--detach", "--no-resolve-image", "--image", repoName, name), trustedCmd, cli.Daemon(d.Daemon)).Assert(c, icmd.Expected{ - Err: "resolved image tag to", - }) - - cli.Docker(cli.Args("service", "inspect", "--pretty", name), cli.Daemon(d.Daemon)).Assert(c, icmd.Expected{ - Out: repoName + "@", - }) - - // Try trusted service update on an untrusted tag. - - repoName = fmt.Sprintf("%v/untrustedservicecreate/createtest:latest", privateRegistryURL) - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", repoName) - cli.DockerCmd(c, "push", repoName) - cli.DockerCmd(c, "rmi", repoName) - - cli.Docker(cli.Args("service", "update", "--detach", "--no-resolve-image", "--image", repoName, name), trustedCmd, cli.Daemon(d.Daemon)).Assert(c, icmd.Expected{ - ExitCode: 1, - Err: "Error: remote trust data does not exist", - }) -} - // Test case for issue #27866, which did not allow NW name that is the prefix of a swarm NW ID. // e.g. if the ingress ID starts with "n1", it was impossible to create a NW named "n1". func (s *DockerSwarmSuite) TestSwarmNetworkCreateIssue27866(c *check.C) { diff --git a/components/engine/integration-cli/docker_utils_test.go b/components/engine/integration-cli/docker_utils_test.go index ea780cc6e8..1475558239 100644 --- a/components/engine/integration-cli/docker_utils_test.go +++ b/components/engine/integration-cli/docker_utils_test.go @@ -202,12 +202,6 @@ func buildImage(name string, cmdOperators ...cli.CmdOperator) *icmd.Result { return cli.Docker(cli.Build(name), cmdOperators...) } -// Deprecated: use trustedcmd -func trustedBuild(cmd *icmd.Cmd) func() { - trustedCmd(cmd) - return nil -} - // Write `content` to the file at path `dst`, creating it if necessary, // as well as any missing directories. // The file is truncated if it already exists. @@ -306,13 +300,6 @@ func setupRegistry(c *check.C, schema1 bool, auth, tokenURL string) *registry.V2 return reg } -func setupNotary(c *check.C) *testNotary { - ts, err := newTestNotary(c) - c.Assert(err, check.IsNil) - - return ts -} - // appendBaseEnv appends the minimum set of environment variables to exec the // docker cli binary for testing with correct configuration to the given env // list. diff --git a/components/engine/integration-cli/requirements_test.go b/components/engine/integration-cli/requirements_test.go index 838977e70e..b0a95d42f8 100644 --- a/components/engine/integration-cli/requirements_test.go +++ b/components/engine/integration-cli/requirements_test.go @@ -112,22 +112,6 @@ func Apparmor() bool { return err == nil && len(buf) > 1 && buf[0] == 'Y' } -func NotaryHosting() bool { - // for now notary binary is built only if we're running inside - // container through `make test`. Figure that out by testing if - // notary-server binary is in PATH. - _, err := exec.LookPath(notaryServerBinary) - return err == nil -} - -func NotaryServerHosting() bool { - // for now notary-server binary is built only if we're running inside - // container through `make test`. Figure that out by testing if - // notary-server binary is in PATH. - _, err := exec.LookPath(notaryServerBinary) - return err == nil -} - func Devicemapper() bool { return strings.HasPrefix(testEnv.DaemonInfo.Driver, "devicemapper") } diff --git a/components/engine/integration-cli/trust_server_test.go b/components/engine/integration-cli/trust_server_test.go deleted file mode 100644 index f312083ee3..0000000000 --- a/components/engine/integration-cli/trust_server_test.go +++ /dev/null @@ -1,334 +0,0 @@ -package main - -import ( - "context" - "fmt" - "io/ioutil" - "net" - "net/http" - "os" - "os/exec" - "path/filepath" - "strings" - "time" - - "github.com/docker/docker/api/types" - cliconfig "github.com/docker/docker/cli/config" - "github.com/docker/docker/integration-cli/checker" - "github.com/docker/docker/integration-cli/cli" - "github.com/docker/docker/integration-cli/fixtures/plugin" - "github.com/docker/go-connections/tlsconfig" - "github.com/go-check/check" - "github.com/gotestyourself/gotestyourself/icmd" -) - -var notaryBinary = "notary" -var notaryServerBinary = "notary-server" - -type keyPair struct { - Public string - Private string -} - -type testNotary struct { - cmd *exec.Cmd - dir string - keys []keyPair -} - -const notaryHost = "localhost:4443" -const notaryURL = "https://" + notaryHost - -var SuccessTagging = icmd.Expected{ - Out: "Tagging", -} - -var SuccessSigningAndPushing = icmd.Expected{ - Out: "Signing and pushing trust metadata", -} - -var SuccessDownloaded = icmd.Expected{ - Out: "Status: Downloaded", -} - -var SuccessDownloadedOnStderr = icmd.Expected{ - Err: "Status: Downloaded", -} - -func newTestNotary(c *check.C) (*testNotary, error) { - // generate server config - template := `{ - "server": { - "http_addr": "%s", - "tls_key_file": "%s", - "tls_cert_file": "%s" - }, - "trust_service": { - "type": "local", - "hostname": "", - "port": "", - "key_algorithm": "ed25519" - }, - "logging": { - "level": "debug" - }, - "storage": { - "backend": "memory" - } -}` - tmp, err := ioutil.TempDir("", "notary-test-") - if err != nil { - return nil, err - } - confPath := filepath.Join(tmp, "config.json") - config, err := os.Create(confPath) - if err != nil { - return nil, err - } - defer config.Close() - - workingDir, err := os.Getwd() - if err != nil { - return nil, err - } - if _, err := fmt.Fprintf(config, template, notaryHost, filepath.Join(workingDir, "fixtures/notary/localhost.key"), filepath.Join(workingDir, "fixtures/notary/localhost.cert")); err != nil { - os.RemoveAll(tmp) - return nil, err - } - - // generate client config - clientConfPath := filepath.Join(tmp, "client-config.json") - clientConfig, err := os.Create(clientConfPath) - if err != nil { - return nil, err - } - defer clientConfig.Close() - - template = `{ - "trust_dir" : "%s", - "remote_server": { - "url": "%s", - "skipTLSVerify": true - } -}` - if _, err = fmt.Fprintf(clientConfig, template, filepath.Join(cliconfig.Dir(), "trust"), notaryURL); err != nil { - os.RemoveAll(tmp) - return nil, err - } - - // load key fixture filenames - var keys []keyPair - for i := 1; i < 5; i++ { - keys = append(keys, keyPair{ - Public: filepath.Join(workingDir, fmt.Sprintf("fixtures/notary/delgkey%v.crt", i)), - Private: filepath.Join(workingDir, fmt.Sprintf("fixtures/notary/delgkey%v.key", i)), - }) - } - - // run notary-server - cmd := exec.Command(notaryServerBinary, "-config", confPath) - if err := cmd.Start(); err != nil { - os.RemoveAll(tmp) - if os.IsNotExist(err) { - c.Skip(err.Error()) - } - return nil, err - } - - testNotary := &testNotary{ - cmd: cmd, - dir: tmp, - keys: keys, - } - - // Wait for notary to be ready to serve requests. - for i := 1; i <= 20; i++ { - if err = testNotary.Ping(); err == nil { - break - } - time.Sleep(10 * time.Millisecond * time.Duration(i*i)) - } - - if err != nil { - c.Fatalf("Timeout waiting for test notary to become available: %s", err) - } - - return testNotary, nil -} - -func (t *testNotary) Ping() error { - tlsConfig := tlsconfig.ClientDefault() - tlsConfig.InsecureSkipVerify = true - client := http.Client{ - Transport: &http.Transport{ - Proxy: http.ProxyFromEnvironment, - Dial: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - }).Dial, - TLSHandshakeTimeout: 10 * time.Second, - TLSClientConfig: tlsConfig, - }, - } - resp, err := client.Get(fmt.Sprintf("%s/v2/", notaryURL)) - if err != nil { - return err - } - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("notary ping replied with an unexpected status code %d", resp.StatusCode) - } - return nil -} - -func (t *testNotary) Close() { - t.cmd.Process.Kill() - t.cmd.Process.Wait() - os.RemoveAll(t.dir) -} - -func trustedCmd(cmd *icmd.Cmd) func() { - pwd := "12345678" - cmd.Env = append(cmd.Env, trustEnv(notaryURL, pwd, pwd)...) - return nil -} - -func trustedCmdWithServer(server string) func(*icmd.Cmd) func() { - return func(cmd *icmd.Cmd) func() { - pwd := "12345678" - cmd.Env = append(cmd.Env, trustEnv(server, pwd, pwd)...) - return nil - } -} - -func trustedCmdWithPassphrases(rootPwd, repositoryPwd string) func(*icmd.Cmd) func() { - return func(cmd *icmd.Cmd) func() { - cmd.Env = append(cmd.Env, trustEnv(notaryURL, rootPwd, repositoryPwd)...) - return nil - } -} - -func trustEnv(server, rootPwd, repositoryPwd string) []string { - env := append(os.Environ(), []string{ - "DOCKER_CONTENT_TRUST=1", - fmt.Sprintf("DOCKER_CONTENT_TRUST_SERVER=%s", server), - fmt.Sprintf("DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE=%s", rootPwd), - fmt.Sprintf("DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE=%s", repositoryPwd), - }...) - return env -} - -func (s *DockerTrustSuite) setupTrustedImage(c *check.C, name string) string { - repoName := fmt.Sprintf("%v/dockercli/%s:latest", privateRegistryURL, name) - // tag the image and upload it to the private registry - cli.DockerCmd(c, "tag", "busybox", repoName) - cli.Docker(cli.Args("push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing) - cli.DockerCmd(c, "rmi", repoName) - return repoName -} - -func (s *DockerTrustSuite) setupTrustedplugin(c *check.C, source, name string) string { - repoName := fmt.Sprintf("%v/dockercli/%s:latest", privateRegistryURL, name) - - client := testEnv.APIClient() - - ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) - err := plugin.Create(ctx, client, repoName) - cancel() - c.Assert(err, checker.IsNil, check.Commentf("could not create test plugin")) - - // tag the image and upload it to the private registry - // TODO: shouldn't need to use the CLI to do trust - cli.Docker(cli.Args("plugin", "push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing) - - ctx, cancel = context.WithTimeout(context.Background(), 60*time.Second) - err = client.PluginRemove(ctx, repoName, types.PluginRemoveOptions{Force: true}) - cancel() - c.Assert(err, checker.IsNil, check.Commentf("failed to cleanup test plugin for trust suite")) - return repoName -} - -func (s *DockerTrustSuite) notaryCmd(c *check.C, args ...string) string { - pwd := "12345678" - env := []string{ - fmt.Sprintf("NOTARY_ROOT_PASSPHRASE=%s", pwd), - fmt.Sprintf("NOTARY_TARGETS_PASSPHRASE=%s", pwd), - fmt.Sprintf("NOTARY_SNAPSHOT_PASSPHRASE=%s", pwd), - fmt.Sprintf("NOTARY_DELEGATION_PASSPHRASE=%s", pwd), - } - result := icmd.RunCmd(icmd.Cmd{ - Command: append([]string{notaryBinary, "-c", filepath.Join(s.not.dir, "client-config.json")}, args...), - Env: append(os.Environ(), env...), - }) - result.Assert(c, icmd.Success) - return result.Combined() -} - -func (s *DockerTrustSuite) notaryInitRepo(c *check.C, repoName string) { - s.notaryCmd(c, "init", repoName) -} - -func (s *DockerTrustSuite) notaryCreateDelegation(c *check.C, repoName, role string, pubKey string, paths ...string) { - pathsArg := "--all-paths" - if len(paths) > 0 { - pathsArg = "--paths=" + strings.Join(paths, ",") - } - - s.notaryCmd(c, "delegation", "add", repoName, role, pubKey, pathsArg) -} - -func (s *DockerTrustSuite) notaryPublish(c *check.C, repoName string) { - s.notaryCmd(c, "publish", repoName) -} - -func (s *DockerTrustSuite) notaryImportKey(c *check.C, repoName, role string, privKey string) { - s.notaryCmd(c, "key", "import", privKey, "-g", repoName, "-r", role) -} - -func (s *DockerTrustSuite) notaryListTargetsInRole(c *check.C, repoName, role string) map[string]string { - out := s.notaryCmd(c, "list", repoName, "-r", role) - - // should look something like: - // NAME DIGEST SIZE (BYTES) ROLE - // ------------------------------------------------------------------------------------------------------ - // latest 24a36bbc059b1345b7e8be0df20f1b23caa3602e85d42fff7ecd9d0bd255de56 1377 targets - - targets := make(map[string]string) - - // no target - lines := strings.Split(strings.TrimSpace(out), "\n") - if len(lines) == 1 && strings.Contains(out, "No targets present in this repository.") { - return targets - } - - // otherwise, there is at least one target - c.Assert(len(lines), checker.GreaterOrEqualThan, 3) - - for _, line := range lines[2:] { - tokens := strings.Fields(line) - c.Assert(tokens, checker.HasLen, 4) - targets[tokens[0]] = tokens[3] - } - - return targets -} - -func (s *DockerTrustSuite) assertTargetInRoles(c *check.C, repoName, target string, roles ...string) { - // check all the roles - for _, role := range roles { - targets := s.notaryListTargetsInRole(c, repoName, role) - roleName, ok := targets[target] - c.Assert(ok, checker.True) - c.Assert(roleName, checker.Equals, role) - } -} - -func (s *DockerTrustSuite) assertTargetNotInRoles(c *check.C, repoName, target string, roles ...string) { - targets := s.notaryListTargetsInRole(c, repoName, "targets") - - roleName, ok := targets[target] - if ok { - for _, role := range roles { - c.Assert(roleName, checker.Not(checker.Equals), role) - } - } -} diff --git a/components/engine/integration/build/build_test.go b/components/engine/integration/build/build_test.go index 9d396da865..d8cb298cd4 100644 --- a/components/engine/integration/build/build_test.go +++ b/components/engine/integration/build/build_test.go @@ -5,6 +5,7 @@ import ( "bytes" "context" "encoding/json" + "fmt" "io" "io/ioutil" "strings" @@ -12,11 +13,13 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/api/types/versions" "github.com/docker/docker/integration-cli/cli/build/fakecontext" "github.com/docker/docker/integration/internal/request" "github.com/docker/docker/pkg/jsonmessage" "github.com/gotestyourself/gotestyourself/assert" is "github.com/gotestyourself/gotestyourself/assert/cmp" + "github.com/gotestyourself/gotestyourself/skip" ) func TestBuildWithRemoveAndForceRemove(t *testing.T) { @@ -304,6 +307,9 @@ COPY bar /` // docker/for-linux#135 // #35641 func TestBuildMultiStageLayerLeak(t *testing.T) { + fmt.Println(testEnv.DaemonAPIVersion()) + skip.IfCondition(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.38"), + "Don't run on API lower than 1.38 as it has been fixed starting from that version") ctx := context.TODO() defer setupTest(t)() diff --git a/components/engine/integration/container/nat_test.go b/components/engine/integration/container/nat_test.go index 5574db779e..f4a3ea6f3a 100644 --- a/components/engine/integration/container/nat_test.go +++ b/components/engine/integration/container/nat_test.go @@ -59,6 +59,8 @@ func TestNetworkLocalhostTCPNat(t *testing.T) { func TestNetworkLoopbackNat(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon()) + defer setupTest(t)() + msg := "it works" startServerContainer(t, msg, 8080) diff --git a/components/engine/integration/internal/swarm/service.go b/components/engine/integration/internal/swarm/service.go index 0ec4d5175e..79705961a1 100644 --- a/components/engine/integration/internal/swarm/service.go +++ b/components/engine/integration/internal/swarm/service.go @@ -12,6 +12,7 @@ import ( "github.com/docker/docker/integration-cli/daemon" "github.com/docker/docker/internal/test/environment" "github.com/gotestyourself/gotestyourself/assert" + "github.com/gotestyourself/gotestyourself/skip" ) const ( @@ -21,6 +22,7 @@ const ( // NewSwarm creates a swarm daemon for testing func NewSwarm(t *testing.T, testEnv *environment.Execution) *daemon.Swarm { + skip.IfCondition(t, testEnv.IsRemoteDaemon()) d := &daemon.Swarm{ Daemon: daemon.New(t, "", dockerdBinary, daemon.Config{ Experimental: testEnv.DaemonInfo.ExperimentalBuild, diff --git a/components/engine/integration/network/inspect_test.go b/components/engine/integration/network/inspect_test.go index 3afdcf1ac4..ad4a344c49 100644 --- a/components/engine/integration/network/inspect_test.go +++ b/components/engine/integration/network/inspect_test.go @@ -1,16 +1,15 @@ package network // import "github.com/docker/docker/integration/network" import ( - "fmt" "runtime" "testing" "time" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" + swarmtypes "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/client" - "github.com/docker/docker/integration-cli/daemon" + "github.com/docker/docker/integration/internal/swarm" "github.com/gotestyourself/gotestyourself/assert" "github.com/gotestyourself/gotestyourself/poll" "golang.org/x/net/context" @@ -21,7 +20,7 @@ const dockerdBinary = "dockerd" func TestInspectNetwork(t *testing.T) { defer setupTest(t)() - d := newSwarm(t) + d := swarm.NewSwarm(t, testEnv) defer d.Stop(t) client, err := client.NewClientWithOpts(client.WithHost((d.Sock()))) assert.NilError(t, err) @@ -38,8 +37,9 @@ func TestInspectNetwork(t *testing.T) { var instances uint64 = 4 serviceName := "TestService" + // FIXME(vdemeester) consolidate with swarm.CreateService serviceSpec := swarmServiceSpec(serviceName, instances) - serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarm.NetworkAttachmentConfig{Target: overlayName}) + serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarmtypes.NetworkAttachmentConfig{Target: overlayName}) serviceResp, err := client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{ QueryRegistry: false, @@ -107,38 +107,19 @@ func TestInspectNetwork(t *testing.T) { poll.WaitOn(t, networkIsRemoved(client, overlayID), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second)) } -func newSwarm(t *testing.T) *daemon.Swarm { - d := &daemon.Swarm{ - Daemon: daemon.New(t, "", dockerdBinary, daemon.Config{ - Experimental: testEnv.DaemonInfo.ExperimentalBuild, - }), - // TODO: better method of finding an unused port - Port: defaultSwarmPort, - } - // TODO: move to a NewSwarm constructor - d.ListenAddr = fmt.Sprintf("0.0.0.0:%d", d.Port) - - // avoid networking conflicts - args := []string{"--iptables=false", "--swarm-default-advertise-addr=lo"} - d.StartWithBusybox(t, args...) - - assert.NilError(t, d.Init(swarm.InitRequest{})) - return d -} - -func swarmServiceSpec(name string, replicas uint64) swarm.ServiceSpec { - return swarm.ServiceSpec{ - Annotations: swarm.Annotations{ +func swarmServiceSpec(name string, replicas uint64) swarmtypes.ServiceSpec { + return swarmtypes.ServiceSpec{ + Annotations: swarmtypes.Annotations{ Name: name, }, - TaskTemplate: swarm.TaskSpec{ - ContainerSpec: &swarm.ContainerSpec{ + TaskTemplate: swarmtypes.TaskSpec{ + ContainerSpec: &swarmtypes.ContainerSpec{ Image: "busybox:latest", Command: []string{"/bin/top"}, }, }, - Mode: swarm.ServiceMode{ - Replicated: &swarm.ReplicatedService{ + Mode: swarmtypes.ServiceMode{ + Replicated: &swarmtypes.ReplicatedService{ Replicas: &replicas, }, }, @@ -157,7 +138,7 @@ func serviceRunningTasksCount(client client.ServiceAPIClient, serviceID string, return poll.Error(err) case len(tasks) == int(instances): for _, task := range tasks { - if task.Status.State != swarm.TaskStateRunning { + if task.Status.State != swarmtypes.TaskStateRunning { return poll.Continue("waiting for tasks to enter run state") } } diff --git a/components/engine/integration/network/service_test.go b/components/engine/integration/network/service_test.go index b8470a1e85..a9fccf9522 100644 --- a/components/engine/integration/network/service_test.go +++ b/components/engine/integration/network/service_test.go @@ -7,8 +7,9 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" + swarmtypes "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/client" + "github.com/docker/docker/integration/internal/swarm" "github.com/gotestyourself/gotestyourself/assert" "github.com/gotestyourself/gotestyourself/poll" "golang.org/x/net/context" @@ -16,7 +17,7 @@ import ( func TestServiceWithPredefinedNetwork(t *testing.T) { defer setupTest(t)() - d := newSwarm(t) + d := swarm.NewSwarm(t, testEnv) defer d.Stop(t) client, err := client.NewClientWithOpts(client.WithHost((d.Sock()))) assert.NilError(t, err) @@ -25,7 +26,7 @@ func TestServiceWithPredefinedNetwork(t *testing.T) { var instances uint64 = 1 serviceName := "TestService" serviceSpec := swarmServiceSpec(serviceName, instances) - serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarm.NetworkAttachmentConfig{Target: hostName}) + serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarmtypes.NetworkAttachmentConfig{Target: hostName}) serviceResp, err := client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{ QueryRegistry: false, @@ -60,7 +61,7 @@ const ingressNet = "ingress" func TestServiceWithIngressNetwork(t *testing.T) { defer setupTest(t)() - d := newSwarm(t) + d := swarm.NewSwarm(t, testEnv) defer d.Stop(t) client, err := client.NewClientWithOpts(client.WithHost((d.Sock()))) @@ -81,13 +82,13 @@ func TestServiceWithIngressNetwork(t *testing.T) { var instances uint64 = 1 serviceName := "TestIngressService" serviceSpec := swarmServiceSpec(serviceName, instances) - serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarm.NetworkAttachmentConfig{Target: ingressNet}) - serviceSpec.EndpointSpec = &swarm.EndpointSpec{ - Ports: []swarm.PortConfig{ + serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarmtypes.NetworkAttachmentConfig{Target: ingressNet}) + serviceSpec.EndpointSpec = &swarmtypes.EndpointSpec{ + Ports: []swarmtypes.PortConfig{ { - Protocol: swarm.PortConfigProtocolTCP, + Protocol: swarmtypes.PortConfigProtocolTCP, TargetPort: 80, - PublishMode: swarm.PortConfigPublishModeIngress, + PublishMode: swarmtypes.PortConfigPublishModeIngress, }, }, } diff --git a/components/engine/integration/plugin/authz/main_test.go b/components/engine/integration/plugin/authz/main_test.go index ea72a03f16..3d5f406b92 100644 --- a/components/engine/integration/plugin/authz/main_test.go +++ b/components/engine/integration/plugin/authz/main_test.go @@ -16,6 +16,7 @@ import ( "github.com/docker/docker/internal/test/environment" "github.com/docker/docker/pkg/authorization" "github.com/docker/docker/pkg/plugins" + "github.com/gotestyourself/gotestyourself/skip" ) var ( @@ -48,6 +49,7 @@ func TestMain(m *testing.M) { } func setupTest(t *testing.T) func() { + skip.IfCondition(t, testEnv.IsRemoteDaemon(), "cannot run daemon when remote daemon") environment.ProtectAll(t, testEnv) d = daemon.New(t, "", dockerdBinary, daemon.Config{ diff --git a/components/engine/integration/plugin/logging/helpers_test.go b/components/engine/integration/plugin/logging/helpers_test.go index 61b2f35f43..371d43d831 100644 --- a/components/engine/integration/plugin/logging/helpers_test.go +++ b/components/engine/integration/plugin/logging/helpers_test.go @@ -14,8 +14,6 @@ import ( "github.com/pkg/errors" ) -const dockerdBinary = "dockerd" - var pluginBuildLock = locker.New() func ensurePlugin(t *testing.T, name string) string { diff --git a/components/engine/integration/plugin/logging/main_test.go b/components/engine/integration/plugin/logging/main_test.go new file mode 100644 index 0000000000..b2446ca8c8 --- /dev/null +++ b/components/engine/integration/plugin/logging/main_test.go @@ -0,0 +1,31 @@ +package logging // import "github.com/docker/docker/integration/plugin/logging" + +import ( + "fmt" + "os" + "testing" + + "github.com/docker/docker/internal/test/environment" +) + +var ( + testEnv *environment.Execution +) + +const dockerdBinary = "dockerd" + +func TestMain(m *testing.M) { + var err error + testEnv, err = environment.New() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + err = environment.EnsureFrozenImagesLinux(testEnv) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + testEnv.Print() + os.Exit(m.Run()) +} diff --git a/components/engine/integration/plugin/logging/validation_test.go b/components/engine/integration/plugin/logging/validation_test.go index eb3fe7a029..f0d6e9e8b2 100644 --- a/components/engine/integration/plugin/logging/validation_test.go +++ b/components/engine/integration/plugin/logging/validation_test.go @@ -7,12 +7,14 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/integration-cli/daemon" "github.com/gotestyourself/gotestyourself/assert" + "github.com/gotestyourself/gotestyourself/skip" ) // Regression test for #35553 // Ensure that a daemon with a log plugin set as the default logger for containers // does not keep the daemon from starting. func TestDaemonStartWithLogOpt(t *testing.T) { + skip.IfCondition(t, testEnv.IsRemoteDaemon(), "cannot run daemon when remote daemon") t.Parallel() d := daemon.New(t, "", dockerdBinary, daemon.Config{}) diff --git a/components/engine/internal/test/environment/environment.go b/components/engine/internal/test/environment/environment.go index 16f6146334..8e6e2c72fa 100644 --- a/components/engine/internal/test/environment/environment.go +++ b/components/engine/internal/test/environment/environment.go @@ -121,6 +121,15 @@ func (e *Execution) IsRemoteDaemon() bool { return !e.IsLocalDaemon() } +// DaemonAPIVersion returns the negociated daemon api version +func (e *Execution) DaemonAPIVersion() string { + version, err := e.APIClient().ServerVersion(context.TODO()) + if err != nil { + return "" + } + return version.APIVersion +} + // Print the execution details to stdout // TODO: print everything func (e *Execution) Print() { diff --git a/components/engine/registry/config.go b/components/engine/registry/config.go index 68bd01c481..de5a526b69 100644 --- a/components/engine/registry/config.go +++ b/components/engine/registry/config.go @@ -45,9 +45,6 @@ var ( // IndexName is the name of the index IndexName = "docker.io" - // NotaryServer is the endpoint serving the Notary trust server - NotaryServer = "https://notary.docker.io" - // DefaultV2Registry is the URI of the default v2 registry DefaultV2Registry = &url.URL{ Scheme: "https",