diff --git a/Dockerfile b/Dockerfile index 257cf673b..fcdb81bc5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # syntax = docker/dockerfile:experimental -ARG GO_VERSION=1.14.3-alpine3.11 +ARG GO_VERSION=1.14.3-alpine FROM golang:${GO_VERSION} AS base ARG TARGET_OS=unknown @@ -7,7 +7,7 @@ ARG TARGET_ARCH=unknown ARG PWD=/api ENV GO111MODULE=on -RUN apk update && apk add docker make +RUN apk update && apk add -U docker make WORKDIR ${PWD} ADD go.* ${PWD} diff --git a/cli/cmd/context/ls_test.go b/cli/cmd/context/ls_test.go index 31bb114b6..861e9156c 100644 --- a/cli/cmd/context/ls_test.go +++ b/cli/cmd/context/ls_test.go @@ -1,76 +1,23 @@ package context import ( - "context" - "io/ioutil" - "os" "testing" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "gotest.tools/v3/golden" - apicontext "github.com/docker/api/context" - "github.com/docker/api/context/store" + "github.com/docker/api/tests/framework" ) type ContextSuite struct { - suite.Suite - ctx context.Context - writer *os.File - reader *os.File - originalStdout *os.File - storeRoot string -} - -func (sut *ContextSuite) BeforeTest(suiteName, testName string) { - ctx := context.Background() - ctx = apicontext.WithCurrentContext(ctx, "example") - dir, err := ioutil.TempDir("", "store") - require.Nil(sut.T(), err) - s, err := store.New( - store.WithRoot(dir), - ) - require.Nil(sut.T(), err) - - err = s.Create("example", store.TypedContext{ - Type: "example", - }) - require.Nil(sut.T(), err) - - sut.storeRoot = dir - - ctx = store.WithContextStore(ctx, s) - sut.ctx = ctx - - sut.originalStdout = os.Stdout - r, w, err := os.Pipe() - require.Nil(sut.T(), err) - - os.Stdout = w - sut.writer = w - sut.reader = r -} - -func (sut *ContextSuite) getStdOut() string { - err := sut.writer.Close() - require.Nil(sut.T(), err) - - out, _ := ioutil.ReadAll(sut.reader) - - return string(out) -} - -func (sut *ContextSuite) AfterTest(suiteName, testName string) { - os.Stdout = sut.originalStdout - err := os.RemoveAll(sut.storeRoot) - require.Nil(sut.T(), err) + framework.CliSuite } func (sut *ContextSuite) TestLs() { - err := runList(sut.ctx) + err := runList(sut.Context()) require.Nil(sut.T(), err) - golden.Assert(sut.T(), sut.getStdOut(), "ls-out.golden") + golden.Assert(sut.T(), sut.GetStdOut(), "ls-out.golden") } func TestPs(t *testing.T) { diff --git a/cli/cmd/ps_test.go b/cli/cmd/ps_test.go index ed90bfa99..4d7ffd56a 100644 --- a/cli/cmd/ps_test.go +++ b/cli/cmd/ps_test.go @@ -1,72 +1,18 @@ package cmd import ( - "context" - "io/ioutil" - "os" "testing" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "gotest.tools/v3/golden" - apicontext "github.com/docker/api/context" - "github.com/docker/api/context/store" _ "github.com/docker/api/example" + "github.com/docker/api/tests/framework" ) type PsSuite struct { - suite.Suite - ctx context.Context - writer *os.File - reader *os.File - originalStdout *os.File - storeRoot string -} - -func (sut *PsSuite) BeforeTest(suiteName, testName string) { - ctx := context.Background() - ctx = apicontext.WithCurrentContext(ctx, "example") - dir, err := ioutil.TempDir("", "store") - require.Nil(sut.T(), err) - s, err := store.New( - store.WithRoot(dir), - ) - require.Nil(sut.T(), err) - - err = s.Create("example", store.TypedContext{ - Type: "example", - }) - require.Nil(sut.T(), err) - - sut.storeRoot = dir - - ctx = store.WithContextStore(ctx, s) - sut.ctx = ctx - - sut.originalStdout = os.Stdout - r, w, err := os.Pipe() - require.Nil(sut.T(), err) - - os.Stdout = w - sut.writer = w - sut.reader = r -} - -func (sut *PsSuite) getStdOut() string { - err := sut.writer.Close() - require.Nil(sut.T(), err) - - out, _ := ioutil.ReadAll(sut.reader) - - return string(out) -} - -func (sut *PsSuite) AfterTest(suiteName, testName string) { - os.Stdout = sut.originalStdout - err := os.RemoveAll(sut.storeRoot) - require.Nil(sut.T(), err) + framework.CliSuite } func (sut *PsSuite) TestPs() { @@ -74,10 +20,10 @@ func (sut *PsSuite) TestPs() { quiet: false, } - err := runPs(sut.ctx, opts) - assert.Nil(sut.T(), err) + err := runPs(sut.Context(), opts) + require.Nil(sut.T(), err) - golden.Assert(sut.T(), sut.getStdOut(), "ps-out.golden") + golden.Assert(sut.T(), sut.GetStdOut(), "ps-out.golden") } func (sut *PsSuite) TestPsQuiet() { @@ -85,10 +31,10 @@ func (sut *PsSuite) TestPsQuiet() { quiet: true, } - err := runPs(sut.ctx, opts) - assert.Nil(sut.T(), err) + err := runPs(sut.Context(), opts) + require.Nil(sut.T(), err) - golden.Assert(sut.T(), sut.getStdOut(), "ps-out-quiet.golden") + golden.Assert(sut.T(), sut.GetStdOut(), "ps-out-quiet.golden") } func TestPs(t *testing.T) { diff --git a/context/store/store.go b/context/store/store.go index 441419f22..9583d6c3b 100644 --- a/context/store/store.go +++ b/context/store/store.go @@ -146,12 +146,12 @@ func read(meta string, getter func() interface{}) (*Metadata, error) { } var um untypedMetadata - if err := marshalTyped(bytes, &um); err != nil { + if err := json.Unmarshal(bytes, &um); err != nil { return nil, err } var uc untypedContext - if err := marshalTyped(um.Metadata, &uc); err != nil { + if err := json.Unmarshal(um.Metadata, &uc); err != nil { return nil, err } if uc.Type == "" { @@ -178,10 +178,6 @@ func read(meta string, getter func() interface{}) (*Metadata, error) { }, nil } -func marshalTyped(in []byte, val interface{}) error { - return json.Unmarshal(in, val) -} - func parse(payload []byte, getter func() interface{}) (interface{}, error) { if getter == nil { var res map[string]interface{} @@ -266,7 +262,7 @@ func (s *store) List() ([]*Metadata, error) { // The default context is not stored in the store, it is in-memory only // so we need a special case for it. - dockerDefault, err := dockerGefaultContext() + dockerDefault, err := dockerDefaultContext() if err != nil { return nil, err } diff --git a/context/store/storedefault.go b/context/store/storedefault.go index fb656ae3f..61283d3fc 100644 --- a/context/store/storedefault.go +++ b/context/store/storedefault.go @@ -31,7 +31,7 @@ type endpoint struct { DefaultNamespace string } -func dockerGefaultContext() (*Metadata, error) { +func dockerDefaultContext() (*Metadata, error) { cmd := exec.Command("docker", "context", "inspect", "default") var stdout bytes.Buffer cmd.Stdout = &stdout diff --git a/context/store/storedefault_test.go b/context/store/storedefault_test.go index 3a0daf50a..7d25e874f 100644 --- a/context/store/storedefault_test.go +++ b/context/store/storedefault_test.go @@ -7,7 +7,7 @@ import ( ) func TestDefaultContext(t *testing.T) { - s, err := dockerGefaultContext() + s, err := dockerDefaultContext() assert.Nil(t, err) assert.Equal(t, "default", s.Name) } diff --git a/tests/framework/clisuite.go b/tests/framework/clisuite.go new file mode 100644 index 000000000..fafae5041 --- /dev/null +++ b/tests/framework/clisuite.go @@ -0,0 +1,77 @@ +package framework + +import ( + "context" + "io/ioutil" + "os" + + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + + apicontext "github.com/docker/api/context" + "github.com/docker/api/context/store" +) + +// CliSuite is a helper struct that creates a configured context +// and captures the output of a command. it should be used in the +// same way as testify.suite.Suite +type CliSuite struct { + suite.Suite + ctx context.Context + writer *os.File + reader *os.File + OriginalStdout *os.File + storeRoot string +} + +// BeforeTest is called by testify.suite +func (sut *CliSuite) BeforeTest(suiteName, testName string) { + ctx := context.Background() + ctx = apicontext.WithCurrentContext(ctx, "example") + dir, err := ioutil.TempDir("", "store") + require.Nil(sut.T(), err) + s, err := store.New( + store.WithRoot(dir), + ) + require.Nil(sut.T(), err) + + err = s.Create("example", store.TypedContext{ + Type: "example", + }) + require.Nil(sut.T(), err) + + sut.storeRoot = dir + + ctx = store.WithContextStore(ctx, s) + sut.ctx = ctx + + sut.OriginalStdout = os.Stdout + r, w, err := os.Pipe() + require.Nil(sut.T(), err) + + os.Stdout = w + sut.writer = w + sut.reader = r +} + +// Context returns a configured context +func (sut *CliSuite) Context() context.Context { + return sut.ctx +} + +// GetStdOut returns the output of the command +func (sut *CliSuite) GetStdOut() string { + err := sut.writer.Close() + require.Nil(sut.T(), err) + + out, _ := ioutil.ReadAll(sut.reader) + + return string(out) +} + +// AfterTest is called by testify.suite +func (sut *CliSuite) AfterTest(suiteName, testName string) { + os.Stdout = sut.OriginalStdout + err := os.RemoveAll(sut.storeRoot) + require.Nil(sut.T(), err) +}