diff --git a/command/build/command.go b/command/build/command.go index 6132787ce..8d4924f24 100644 --- a/command/build/command.go +++ b/command/build/command.go @@ -10,6 +10,10 @@ import ( type Command byte +func (Command) Help() string { + return "help" +} + func (Command) Run(env packer.Environment, args []string) int { if len(args) != 1 { env.Ui().Error("A single template argument is required.") diff --git a/command/build/command_test.go b/command/build/command_test.go index 116f6eb42..c2f1cfb03 100644 --- a/command/build/command_test.go +++ b/command/build/command_test.go @@ -22,6 +22,13 @@ func testEnvironment() packer.Environment { return env } +func TestCommand_Implements(t *testing.T) { + assert := asserts.NewTestingAsserts(t, true) + + var actual packer.Command + assert.Implementor(new(Command), &actual, "should be a Command") +} + func TestCommand_Run_NoArgs(t *testing.T) { assert := asserts.NewTestingAsserts(t, true) command := new(Command) diff --git a/packer/command.go b/packer/command.go index 4f4f9ae35..d861347eb 100644 --- a/packer/command.go +++ b/packer/command.go @@ -6,14 +6,18 @@ package packer // // The mapping of command names to command interfaces is in the // Environment struct. -// -// Run should run the actual command with the given environmet and -// command-line arguments. It should return the exit status when it is -// finished. -// -// Synopsis should return a one-line, short synopsis of the command. -// This should be less than 50 characters ideally. type Command interface { + // Help should return long-form help text that includes the command-line + // usage, a brief few sentences explaining the function of the command, + // and the complete list of flags the command accepts. + Help() string + + // Run should run the actual command with the given environmet and + // command-line arguments. It should return the exit status when it is + // finished. Run(env Environment, args []string) int + + // Synopsis should return a one-line, short synopsis of the command. + // This should be less than 50 characters ideally. Synopsis() string } diff --git a/packer/command_test.go b/packer/command_test.go index 163c3803a..06348fdac 100644 --- a/packer/command_test.go +++ b/packer/command_test.go @@ -6,6 +6,10 @@ type TestCommand struct { runEnv Environment } +func (tc *TestCommand) Help() string { + return "bar" +} + func (tc *TestCommand) Run(env Environment, args []string) int { tc.runCalled = true tc.runArgs = args diff --git a/packer/plugin/command.go b/packer/plugin/command.go index 19c0996ba..7a4b2c19d 100644 --- a/packer/plugin/command.go +++ b/packer/plugin/command.go @@ -13,6 +13,16 @@ type cmdCommand struct { client *client } +func (c *cmdCommand) Help() (result string) { + defer func() { + r := recover() + c.checkExit(r, func() { result = "" }) + }() + + result = c.command.Help() + return +} + func (c *cmdCommand) Run(e packer.Environment, args []string) (exitCode int) { defer func() { r := recover() diff --git a/packer/plugin/command_test.go b/packer/plugin/command_test.go index 9091ec0ba..3e6816ade 100644 --- a/packer/plugin/command_test.go +++ b/packer/plugin/command_test.go @@ -7,11 +7,12 @@ import ( "testing" ) -// TODO: Test command cleanup functionality -// TODO: Test timeout functionality - type helperCommand byte +func (helperCommand) Help() string { + return "2" +} + func (helperCommand) Run(packer.Environment, []string) int { return 42 } @@ -37,6 +38,9 @@ func TestCommand_Good(t *testing.T) { if command != nil { result := command.Synopsis() assert.Equal(result, "1", "should return result") + + result = command.Help() + assert.Equal(result, "2", "should return result") } } diff --git a/packer/rpc/command.go b/packer/rpc/command.go index b754579f9..18cd5667e 100644 --- a/packer/rpc/command.go +++ b/packer/rpc/command.go @@ -28,6 +28,15 @@ func Command(client *rpc.Client) *command { return &command{client} } +func (c *command) Help() (result string) { + err := c.client.Call("Command.Help", new(interface{}), &result) + if err != nil { + panic(err) + } + + return +} + func (c *command) Run(env packer.Environment, args []string) (result int) { // Create and start the server for the Environment server := rpc.NewServer() @@ -51,6 +60,11 @@ func (c *command) Synopsis() (result string) { return } +func (c *CommandServer) Help(args *interface{}, reply *string) error { + *reply = c.command.Help() + return nil +} + func (c *CommandServer) Run(args *CommandRunArgs, reply *int) error { client, err := rpc.Dial("tcp", args.RPCAddress) if err != nil { diff --git a/packer/rpc/command_test.go b/packer/rpc/command_test.go index f61ca6188..e27ae7c1c 100644 --- a/packer/rpc/command_test.go +++ b/packer/rpc/command_test.go @@ -13,6 +13,10 @@ type TestCommand struct { runEnv packer.Environment } +func (tc *TestCommand) Help() string { + return "bar" +} + func (tc *TestCommand) Run(env packer.Environment, args []string) int { tc.runCalled = true tc.runArgs = args @@ -42,6 +46,10 @@ func TestRPCCommand(t *testing.T) { clientComm := Command(client) + //Test Help + help := clientComm.Help() + assert.Equal(help, "bar", "helps hould be correct") + // Test run runArgs := []string{"foo", "bar"} testEnv := &testEnvironment{} @@ -59,3 +67,12 @@ func TestRPCCommand(t *testing.T) { synopsis := clientComm.Synopsis() assert.Equal(synopsis, "foo", "Synopsis should be correct") } + +func TestCommand_Implements(t *testing.T) { + assert := asserts.NewTestingAsserts(t, true) + + var r packer.Command + c := Command(nil) + + assert.Implementor(c, &r, "should be a Builder") +} diff --git a/packer/version.go b/packer/version.go index 3733cef30..923e46e10 100644 --- a/packer/version.go +++ b/packer/version.go @@ -7,7 +7,13 @@ const Version = "0.1.0.dev" type versionCommand byte -// Implement the Command interface by simply showing the version +func (versionCommand) Help() string { + return `usage: packer version + +Outputs the version of Packer that is running. There are no additional +command-line flags for this command.` +} + func (versionCommand) Run(env Environment, args []string) int { env.Ui().Say(fmt.Sprintf("Packer v%v\n", Version)) return 0