Commit 80e8e09e authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

packer: Add Cancel() method to hook

parent d5c6b9fa
......@@ -13,7 +13,7 @@ func testBuild() *coreBuild {
builderConfig: 42,
builderType: "foo",
hooks: map[string][]Hook{
"foo": []Hook{&TestHook{}},
"foo": []Hook{&MockHook{}},
},
provisioners: []coreBuildProvisioner{
coreBuildProvisioner{&TestProvisioner{}, []interface{}{42}},
......@@ -187,9 +187,9 @@ func TestBuild_Run(t *testing.T) {
dispatchHook := builder.runHook
dispatchHook.Run("foo", nil, nil, 42)
hook := build.hooks["foo"][0].(*TestHook)
assert.True(hook.runCalled, "run should be called")
assert.Equal(hook.runData, 42, "should have correct data")
hook := build.hooks["foo"][0].(*MockHook)
assert.True(hook.RunCalled, "run should be called")
assert.Equal(hook.RunData, 42, "should have correct data")
// Verify provisioners run
dispatchHook.Run(HookProvision, nil, nil, 42)
......
......@@ -227,7 +227,7 @@ func TestEnvironment_DefaultCli_Version(t *testing.T) {
func TestEnvironment_Hook(t *testing.T) {
assert := asserts.NewTestingAsserts(t, true)
hook := &TestHook{}
hook := &MockHook{}
hooks := make(map[string]Hook)
hooks["foo"] = hook
......
......@@ -11,8 +11,14 @@ const HookProvision = "packer_provision"
// you must reference the documentation for the specific hook you're interested
// in. In addition to that, the Hook is given access to a UI so that it can
// output things to the user.
//
// Cancel is called when the hook needs to be cancelled. This will usually
// be called when Run is still in progress so the mechanism that handles this
// must be race-free. Cancel should attempt to cancel the hook in the
// quickest, safest way possible.
type Hook interface {
Run(string, Ui, Communicator, interface{}) error
Cancel()
}
// A Hook implementation that dispatches based on an internal mapping.
......@@ -38,3 +44,5 @@ func (h *DispatchHook) Run(name string, ui Ui, comm Communicator, data interface
return nil
}
func (h *DispatchHook) Cancel() {}
package packer
// MockHook is an implementation of Hook that can be used for tests.
type MockHook struct {
RunCalled bool
RunComm Communicator
RunData interface{}
RunName string
RunUi Ui
CancelCalled bool
}
func (t *MockHook) Run(name string, ui Ui, comm Communicator, data interface{}) error {
t.RunCalled = true
t.RunComm = comm
t.RunData = data
t.RunName = name
t.RunUi = ui
return nil
}
func (t *MockHook) Cancel() {
t.CancelCalled = true
}
......@@ -5,23 +5,6 @@ import (
"testing"
)
type TestHook struct {
runCalled bool
runComm Communicator
runData interface{}
runName string
runUi Ui
}
func (t *TestHook) Run(name string, ui Ui, comm Communicator, data interface{}) error {
t.runCalled = true
t.runComm = comm
t.runData = data
t.runName = name
t.runUi = ui
return nil
}
func TestDispatchHook_Implements(t *testing.T) {
assert := asserts.NewTestingAsserts(t, true)
......@@ -40,14 +23,14 @@ func TestDispatchHook_Run_NoHooks(t *testing.T) {
func TestDispatchHook_Run(t *testing.T) {
assert := asserts.NewTestingAsserts(t, true)
hook := &TestHook{}
hook := &MockHook{}
mapping := make(map[string][]Hook)
mapping["foo"] = []Hook{hook}
dh := &DispatchHook{mapping}
dh.Run("foo", nil, nil, 42)
assert.True(hook.runCalled, "run should be called")
assert.Equal(hook.runName, "foo", "should be proper event")
assert.Equal(hook.runData, 42, "should be correct data")
assert.True(hook.RunCalled, "run should be called")
assert.Equal(hook.RunName, "foo", "should be proper event")
assert.Equal(hook.RunData, 42, "should be correct data")
}
......@@ -19,8 +19,17 @@ func (c *cmdHook) Run(name string, ui packer.Ui, comm packer.Communicator, data
return c.hook.Run(name, ui, comm, data)
}
func (c *cmdHook) Cancel() {
defer func() {
r := recover()
c.checkExit(r, nil)
}()
c.hook.Cancel()
}
func (c *cmdHook) checkExit(p interface{}, cb func()) {
if c.client.Exited() {
if c.client.Exited() && cb != nil {
cb()
} else if p != nil && !Killed {
log.Panic(p)
......
package plugin
import (
"github.com/mitchellh/packer/packer"
"os/exec"
"testing"
)
type helperHook byte
func (helperHook) Run(string, packer.Ui, packer.Communicator, interface{}) error {
return nil
}
func TestHook_NoExist(t *testing.T) {
c := NewClient(&ClientConfig{Cmd: exec.Command("i-should-not-exist")})
defer c.Kill()
......
......@@ -2,6 +2,7 @@ package plugin
import (
"fmt"
"github.com/mitchellh/packer/packer"
"log"
"os"
"os/exec"
......@@ -54,7 +55,7 @@ func TestHelperProcess(*testing.T) {
case "command":
ServeCommand(new(helperCommand))
case "hook":
ServeHook(new(helperHook))
ServeHook(new(packer.MockHook))
case "invalid-rpc-address":
fmt.Println("lolinvalid")
case "mock":
......
......@@ -32,3 +32,8 @@ func (h *ProvisionHook) Run(name string, ui Ui, comm Communicator, data interfac
return nil
}
// Cancels the privisioners that are still running.
func (h *ProvisionHook) Cancel() {
// TODO(mitchellh): implement
}
......@@ -72,7 +72,7 @@ func TestBuilderRPC(t *testing.T) {
// Test Run
cache := new(testCache)
hook := &testHook{}
hook := &packer.MockHook{}
ui := &testUi{}
artifact, err := bClient.Run(ui, hook, cache)
assert.Nil(err, "should have no error")
......@@ -83,7 +83,7 @@ func TestBuilderRPC(t *testing.T) {
assert.True(cache.lockCalled, "lock should be called")
b.runHook.Run("foo", nil, nil, nil)
assert.True(hook.runCalled, "run should be called")
assert.True(hook.RunCalled, "run should be called")
b.runUi.Say("format")
assert.True(ui.sayCalled, "say should be called")
......
......@@ -37,6 +37,10 @@ func (h *hook) Run(name string, ui packer.Ui, comm packer.Communicator, data int
return h.client.Call("Hook.Run", args, new(interface{}))
}
func (h *hook) Cancel() {
// TODO(mitchellh): implement
}
func (h *HookServer) Run(args *HookRunArgs, reply *interface{}) error {
client, err := rpc.Dial("tcp", args.RPCAddress)
if err != nil {
......
......@@ -7,21 +7,11 @@ import (
"testing"
)
type testHook struct {
runCalled bool
runUi packer.Ui
}
func (h *testHook) Run(name string, ui packer.Ui, comm packer.Communicator, data interface{}) error {
h.runCalled = true
return nil
}
func TestHookRPC(t *testing.T) {
assert := asserts.NewTestingAsserts(t, true)
// Create the UI to test
h := new(testHook)
h := new(packer.MockHook)
// Serve
server := rpc.NewServer()
......@@ -37,7 +27,7 @@ func TestHookRPC(t *testing.T) {
// Test Run
ui := &testUi{}
hClient.Run("foo", ui, nil, 42)
assert.True(h.runCalled, "run should be called")
assert.True(h.RunCalled, "run should be called")
}
func TestHook_Implements(t *testing.T) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment