Browse Source

Merge pull request #4314 from shykes/engine-commands

Engine: builtin command 'commands' returns a list of registered commands
Solomon Hykes 11 years ago
parent
commit
56584a92f4
2 changed files with 45 additions and 0 deletions
  1. 22 0
      engine/engine.go
  2. 23 0
      engine/engine_test.go

+ 22 - 0
engine/engine.go

@@ -9,6 +9,7 @@ import (
 	"os"
 	"path/filepath"
 	"runtime"
+	"sort"
 	"strings"
 )
 
@@ -29,6 +30,10 @@ func Register(name string, handler Handler) error {
 	return nil
 }
 
+func unregister(name string) {
+	delete(globalHandlers, name)
+}
+
 // The Engine is the core of Docker.
 // It acts as a store for *containers*, and allows manipulation of these
 // containers by executing *jobs*.
@@ -106,6 +111,12 @@ func New(root string) (*Engine, error) {
 		Stderr:   os.Stderr,
 		Stdin:    os.Stdin,
 	}
+	eng.Register("commands", func(job *Job) Status {
+		for _, name := range eng.commands() {
+			job.Printf("%s\n", name)
+		}
+		return StatusOK
+	})
 	// Copy existing global handlers
 	for k, v := range globalHandlers {
 		eng.handlers[k] = v
@@ -117,6 +128,17 @@ func (eng *Engine) String() string {
 	return fmt.Sprintf("%s|%s", eng.Root(), eng.id[:8])
 }
 
+// Commands returns a list of all currently registered commands,
+// sorted alphabetically.
+func (eng *Engine) commands() []string {
+	names := make([]string, 0, len(eng.handlers))
+	for name := range eng.handlers {
+		names = append(names, name)
+	}
+	sort.Strings(names)
+	return names
+}
+
 // Job creates a new job which can later be executed.
 // This function mimics `Command` from the standard os/exec package.
 func (eng *Engine) Job(name string, args ...string) *Job {

+ 23 - 0
engine/engine_test.go

@@ -1,6 +1,7 @@
 package engine
 
 import (
+	"bytes"
 	"io/ioutil"
 	"os"
 	"path"
@@ -17,6 +18,8 @@ func TestRegister(t *testing.T) {
 	if err := Register("dummy1", nil); err == nil {
 		t.Fatalf("Expecting error, got none")
 	}
+	// Register is global so let's cleanup to avoid conflicts
+	defer unregister("dummy1")
 
 	eng := newTestEngine(t)
 
@@ -33,6 +36,7 @@ func TestRegister(t *testing.T) {
 	if err := eng.Register("dummy2", nil); err == nil {
 		t.Fatalf("Expecting error, got none")
 	}
+	defer unregister("dummy2")
 }
 
 func TestJob(t *testing.T) {
@@ -49,6 +53,7 @@ func TestJob(t *testing.T) {
 	}
 
 	eng.Register("dummy2", h)
+	defer unregister("dummy2")
 	job2 := eng.Job("dummy2", "--level=awesome")
 
 	if job2.handler == nil {
@@ -60,6 +65,24 @@ func TestJob(t *testing.T) {
 	}
 }
 
+func TestEngineCommands(t *testing.T) {
+	eng := newTestEngine(t)
+	defer os.RemoveAll(eng.Root())
+	handler := func(job *Job) Status { return StatusOK }
+	eng.Register("foo", handler)
+	eng.Register("bar", handler)
+	eng.Register("echo", handler)
+	eng.Register("die", handler)
+	var output bytes.Buffer
+	commands := eng.Job("commands")
+	commands.Stdout.Add(&output)
+	commands.Run()
+	expected := "bar\ncommands\ndie\necho\nfoo\n"
+	if result := output.String(); result != expected {
+		t.Fatalf("Unexpected output:\nExpected = %v\nResult   = %v\n", expected, result)
+	}
+}
+
 func TestEngineRoot(t *testing.T) {
 	tmp, err := ioutil.TempDir("", "docker-test-TestEngineCreateDir")
 	if err != nil {