context: produce consistent output on `context create`.

Refactor `RunCreate` slightly so that all three paths always produce the same
output, namely the name of the new context of `stdout` (for scripting) and the
success log message on `stderr`.

Validate by extending the existing unit tests to always check the output is as
expected.

Signed-off-by: Ian Campbell <ijc@docker.com>
This commit is contained in:
Ian Campbell 2019-05-13 16:22:02 +01:00
parent 53fc257292
commit ff44305c47
3 changed files with 37 additions and 9 deletions

View File

@ -78,13 +78,19 @@ func RunCreate(cli command.Cli, o *CreateOptions) error {
if err != nil { if err != nil {
return errors.Wrap(err, "unable to parse default-stack-orchestrator") return errors.Wrap(err, "unable to parse default-stack-orchestrator")
} }
if o.From == "" && o.Docker == nil && o.Kubernetes == nil { switch {
return createFromExistingContext(s, cli.CurrentContext(), stackOrchestrator, o) case o.From == "" && o.Docker == nil && o.Kubernetes == nil:
err = createFromExistingContext(s, cli.CurrentContext(), stackOrchestrator, o)
case o.From != "":
err = createFromExistingContext(s, o.From, stackOrchestrator, o)
default:
err = createNewContext(o, stackOrchestrator, cli, s)
} }
if o.From != "" { if err == nil {
return createFromExistingContext(s, o.From, stackOrchestrator, o) fmt.Fprintln(cli.Out(), o.Name)
fmt.Fprintf(cli.Err(), "Successfully created context %q\n", o.Name)
} }
return createNewContext(o, stackOrchestrator, cli, s) return err
} }
func createNewContext(o *CreateOptions, stackOrchestrator command.Orchestrator, cli command.Cli, s store.Writer) error { func createNewContext(o *CreateOptions, stackOrchestrator command.Orchestrator, cli command.Cli, s store.Writer) error {
@ -127,8 +133,6 @@ func createNewContext(o *CreateOptions, stackOrchestrator command.Orchestrator,
if err := s.ResetTLSMaterial(o.Name, &contextTLSData); err != nil { if err := s.ResetTLSMaterial(o.Name, &contextTLSData); err != nil {
return err return err
} }
fmt.Fprintln(cli.Out(), o.Name)
fmt.Fprintf(cli.Err(), "Successfully created context %q\n", o.Name)
return nil return nil
} }

View File

@ -1,6 +1,7 @@
package context package context
import ( import (
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"testing" "testing"
@ -131,6 +132,11 @@ func TestCreateInvalids(t *testing.T) {
} }
} }
func assertContextCreateLogging(t *testing.T, cli *test.FakeCli, n string) {
assert.Equal(t, n+"\n", cli.OutBuffer().String())
assert.Equal(t, fmt.Sprintf("Successfully created context %q\n", n), cli.ErrBuffer().String())
}
func TestCreateOrchestratorSwarm(t *testing.T) { func TestCreateOrchestratorSwarm(t *testing.T) {
cli, cleanup := makeFakeCli(t) cli, cleanup := makeFakeCli(t)
defer cleanup() defer cleanup()
@ -141,8 +147,7 @@ func TestCreateOrchestratorSwarm(t *testing.T) {
Docker: map[string]string{}, Docker: map[string]string{},
}) })
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, "test\n", cli.OutBuffer().String()) assertContextCreateLogging(t, cli, "test")
assert.Equal(t, "Successfully created context \"test\"\n", cli.ErrBuffer().String())
} }
func TestCreateOrchestratorEmpty(t *testing.T) { func TestCreateOrchestratorEmpty(t *testing.T) {
@ -154,6 +159,7 @@ func TestCreateOrchestratorEmpty(t *testing.T) {
Docker: map[string]string{}, Docker: map[string]string{},
}) })
assert.NilError(t, err) assert.NilError(t, err)
assertContextCreateLogging(t, cli, "test")
} }
func validateTestKubeEndpoint(t *testing.T, s store.Reader, name string) { func validateTestKubeEndpoint(t *testing.T, s store.Reader, name string) {
@ -189,6 +195,7 @@ func TestCreateOrchestratorAllKubernetesEndpointFromCurrent(t *testing.T) {
cli, cleanup := makeFakeCli(t) cli, cleanup := makeFakeCli(t)
defer cleanup() defer cleanup()
createTestContextWithKube(t, cli) createTestContextWithKube(t, cli)
assertContextCreateLogging(t, cli, "test")
validateTestKubeEndpoint(t, cli.ContextStore(), "test") validateTestKubeEndpoint(t, cli.ContextStore(), "test")
} }
@ -225,6 +232,7 @@ func TestCreateFromContext(t *testing.T) {
defer cleanup() defer cleanup()
revert := env.Patch(t, "KUBECONFIG", "./testdata/test-kubeconfig") revert := env.Patch(t, "KUBECONFIG", "./testdata/test-kubeconfig")
defer revert() defer revert()
cli.ResetOutputBuffers()
assert.NilError(t, RunCreate(cli, &CreateOptions{ assert.NilError(t, RunCreate(cli, &CreateOptions{
Name: "original", Name: "original",
Description: "original description", Description: "original description",
@ -236,6 +244,9 @@ func TestCreateFromContext(t *testing.T) {
}, },
DefaultStackOrchestrator: "swarm", DefaultStackOrchestrator: "swarm",
})) }))
assertContextCreateLogging(t, cli, "original")
cli.ResetOutputBuffers()
assert.NilError(t, RunCreate(cli, &CreateOptions{ assert.NilError(t, RunCreate(cli, &CreateOptions{
Name: "dummy", Name: "dummy",
Description: "dummy description", Description: "dummy description",
@ -247,11 +258,13 @@ func TestCreateFromContext(t *testing.T) {
}, },
DefaultStackOrchestrator: "swarm", DefaultStackOrchestrator: "swarm",
})) }))
assertContextCreateLogging(t, cli, "dummy")
cli.SetCurrentContext("dummy") cli.SetCurrentContext("dummy")
for _, c := range cases { for _, c := range cases {
t.Run(c.name, func(t *testing.T) { t.Run(c.name, func(t *testing.T) {
cli.ResetOutputBuffers()
err := RunCreate(cli, &CreateOptions{ err := RunCreate(cli, &CreateOptions{
From: "original", From: "original",
Name: c.name, Name: c.name,
@ -261,6 +274,7 @@ func TestCreateFromContext(t *testing.T) {
Kubernetes: c.kubernetes, Kubernetes: c.kubernetes,
}) })
assert.NilError(t, err) assert.NilError(t, err)
assertContextCreateLogging(t, cli, c.name)
newContext, err := cli.ContextStore().GetMetadata(c.name) newContext, err := cli.ContextStore().GetMetadata(c.name)
assert.NilError(t, err) assert.NilError(t, err)
newContextTyped, err := command.GetDockerContext(newContext) newContextTyped, err := command.GetDockerContext(newContext)
@ -308,6 +322,7 @@ func TestCreateFromCurrent(t *testing.T) {
defer cleanup() defer cleanup()
revert := env.Patch(t, "KUBECONFIG", "./testdata/test-kubeconfig") revert := env.Patch(t, "KUBECONFIG", "./testdata/test-kubeconfig")
defer revert() defer revert()
cli.ResetOutputBuffers()
assert.NilError(t, RunCreate(cli, &CreateOptions{ assert.NilError(t, RunCreate(cli, &CreateOptions{
Name: "original", Name: "original",
Description: "original description", Description: "original description",
@ -319,17 +334,20 @@ func TestCreateFromCurrent(t *testing.T) {
}, },
DefaultStackOrchestrator: "swarm", DefaultStackOrchestrator: "swarm",
})) }))
assertContextCreateLogging(t, cli, "original")
cli.SetCurrentContext("original") cli.SetCurrentContext("original")
for _, c := range cases { for _, c := range cases {
t.Run(c.name, func(t *testing.T) { t.Run(c.name, func(t *testing.T) {
cli.ResetOutputBuffers()
err := RunCreate(cli, &CreateOptions{ err := RunCreate(cli, &CreateOptions{
Name: c.name, Name: c.name,
Description: c.description, Description: c.description,
DefaultStackOrchestrator: c.orchestrator, DefaultStackOrchestrator: c.orchestrator,
}) })
assert.NilError(t, err) assert.NilError(t, err)
assertContextCreateLogging(t, cli, c.name)
newContext, err := cli.ContextStore().GetMetadata(c.name) newContext, err := cli.ContextStore().GetMetadata(c.name)
assert.NilError(t, err) assert.NilError(t, err)
newContextTyped, err := command.GetDockerContext(newContext) newContextTyped, err := command.GetDockerContext(newContext)

View File

@ -169,6 +169,12 @@ func (c *FakeCli) ErrBuffer() *bytes.Buffer {
return c.err return c.err
} }
// ResetOutputBuffers resets the .OutBuffer() and.ErrBuffer() back to empty
func (c *FakeCli) ResetOutputBuffers() {
c.outBuffer.Reset()
c.err.Reset()
}
// SetNotaryClient sets the internal getter for retrieving a NotaryClient // SetNotaryClient sets the internal getter for retrieving a NotaryClient
func (c *FakeCli) SetNotaryClient(notaryClientFunc NotaryClientFuncType) { func (c *FakeCli) SetNotaryClient(notaryClientFunc NotaryClientFuncType) {
c.notaryClientFunc = notaryClientFunc c.notaryClientFunc = notaryClientFunc