mirror of https://github.com/docker/compose.git
Merge pull request #180 from docker/unknown_comand_error
Display friendly message if unknown command is available in default context
This commit is contained in:
commit
4700364667
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
@ -12,6 +13,9 @@ import (
|
||||||
"github.com/docker/api/context/store"
|
"github.com/docker/api/context/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ClassicCliName name of the classic cli binary
|
||||||
|
const ClassicCliName = "docker-classic"
|
||||||
|
|
||||||
// Exec delegates to docker-classic
|
// Exec delegates to docker-classic
|
||||||
func Exec(ctx context.Context) {
|
func Exec(ctx context.Context) {
|
||||||
currentContext := apicontext.CurrentContext(ctx)
|
currentContext := apicontext.CurrentContext(ctx)
|
||||||
|
@ -21,13 +25,12 @@ func Exec(ctx context.Context) {
|
||||||
// Only run original docker command if the current context is not
|
// Only run original docker command if the current context is not
|
||||||
// ours.
|
// ours.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd := exec.CommandContext(ctx, "docker-classic", os.Args[1:]...)
|
cmd := exec.CommandContext(ctx, ClassicCliName, os.Args[1:]...)
|
||||||
cmd.Stdin = os.Stdin
|
cmd.Stdin = os.Stdin
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
if exiterr, ok := err.(*exec.ExitError); ok {
|
if exiterr, ok := err.(*exec.ExitError); ok {
|
||||||
fmt.Fprintln(os.Stderr, exiterr.Error())
|
|
||||||
os.Exit(exiterr.ExitCode())
|
os.Exit(exiterr.ExitCode())
|
||||||
}
|
}
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
@ -42,3 +45,15 @@ func ExecCmd(command *cobra.Command) error {
|
||||||
Exec(command.Context())
|
Exec(command.Context())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsDefaultContextCommand checks if the command exists in the classic cli (issues a shellout --help)
|
||||||
|
func IsDefaultContextCommand(dockerCommand string) bool {
|
||||||
|
cmd := exec.Command(ClassicCliName, dockerCommand, "--help")
|
||||||
|
b, e := cmd.CombinedOutput()
|
||||||
|
if e != nil {
|
||||||
|
fmt.Println(e)
|
||||||
|
}
|
||||||
|
output := string(b)
|
||||||
|
contains := strings.Contains(output, "Usage:\tdocker "+dockerCommand)
|
||||||
|
return contains
|
||||||
|
}
|
||||||
|
|
18
cli/main.go
18
cli/main.go
|
@ -34,6 +34,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -171,11 +172,26 @@ func main() {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
dockerclassic.Exec(ctx)
|
dockerclassic.Exec(ctx)
|
||||||
fmt.Println(err)
|
|
||||||
|
checkIfUnknownCommandExistInDefaultContext(err, currentContext)
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkIfUnknownCommandExistInDefaultContext(err error, currentContext string) {
|
||||||
|
re := regexp.MustCompile(`unknown command "([^"]*)"`)
|
||||||
|
submatch := re.FindSubmatch([]byte(err.Error()))
|
||||||
|
if len(submatch) == 2 {
|
||||||
|
dockerCommand := string(submatch[1])
|
||||||
|
|
||||||
|
if dockerclassic.IsDefaultContextCommand(dockerCommand) {
|
||||||
|
fmt.Fprintf(os.Stderr, "Command \"%s\" not available in current context (%s), you can use the \"default\" context to run this command\n", dockerCommand, currentContext)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func newSigContext() (context.Context, func()) {
|
func newSigContext() (context.Context, func()) {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
s := make(chan os.Signal)
|
s := make(chan os.Signal)
|
||||||
|
|
|
@ -156,6 +156,19 @@ func (s *E2eSuite) TestLegacy() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *E2eSuite) TestLeaveLegacyErrorMessagesUnchanged() {
|
||||||
|
output, err := s.NewDockerCommand("foo").Exec()
|
||||||
|
golden.Assert(s.T(), output, "unknown-foo-command.golden")
|
||||||
|
Expect(err).NotTo(BeNil())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *E2eSuite) TestDisplayFriendlyErrorMessageForLegacyCommands() {
|
||||||
|
s.NewDockerCommand("context", "create", "test-example", "example").ExecOrDie()
|
||||||
|
output, err := s.NewDockerCommand("--context", "test-example", "images").Exec()
|
||||||
|
Expect(output).To(Equal("Command \"images\" not available in current context (test-example), you can use the \"default\" context to run this command\n"))
|
||||||
|
Expect(err).NotTo(BeNil())
|
||||||
|
}
|
||||||
|
|
||||||
func (s *E2eSuite) TestMockBackend() {
|
func (s *E2eSuite) TestMockBackend() {
|
||||||
It("creates a new test context to hardcoded example backend", func() {
|
It("creates a new test context to hardcoded example backend", func() {
|
||||||
s.NewDockerCommand("context", "create", "test-example", "example").ExecOrDie()
|
s.NewDockerCommand("context", "create", "test-example", "example").ExecOrDie()
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
docker: 'foo' is not a docker command.
|
||||||
|
See 'docker --help'
|
Loading…
Reference in New Issue