packer: Add Cancel() method to hook
This commit is contained in:
parent
d5c6b9fad3
commit
80e8e09ec7
|
@ -13,7 +13,7 @@ func testBuild() *coreBuild {
|
||||||
builderConfig: 42,
|
builderConfig: 42,
|
||||||
builderType: "foo",
|
builderType: "foo",
|
||||||
hooks: map[string][]Hook{
|
hooks: map[string][]Hook{
|
||||||
"foo": []Hook{&TestHook{}},
|
"foo": []Hook{&MockHook{}},
|
||||||
},
|
},
|
||||||
provisioners: []coreBuildProvisioner{
|
provisioners: []coreBuildProvisioner{
|
||||||
coreBuildProvisioner{&TestProvisioner{}, []interface{}{42}},
|
coreBuildProvisioner{&TestProvisioner{}, []interface{}{42}},
|
||||||
|
@ -187,9 +187,9 @@ func TestBuild_Run(t *testing.T) {
|
||||||
dispatchHook := builder.runHook
|
dispatchHook := builder.runHook
|
||||||
dispatchHook.Run("foo", nil, nil, 42)
|
dispatchHook.Run("foo", nil, nil, 42)
|
||||||
|
|
||||||
hook := build.hooks["foo"][0].(*TestHook)
|
hook := build.hooks["foo"][0].(*MockHook)
|
||||||
assert.True(hook.runCalled, "run should be called")
|
assert.True(hook.RunCalled, "run should be called")
|
||||||
assert.Equal(hook.runData, 42, "should have correct data")
|
assert.Equal(hook.RunData, 42, "should have correct data")
|
||||||
|
|
||||||
// Verify provisioners run
|
// Verify provisioners run
|
||||||
dispatchHook.Run(HookProvision, nil, nil, 42)
|
dispatchHook.Run(HookProvision, nil, nil, 42)
|
||||||
|
|
|
@ -227,7 +227,7 @@ func TestEnvironment_DefaultCli_Version(t *testing.T) {
|
||||||
func TestEnvironment_Hook(t *testing.T) {
|
func TestEnvironment_Hook(t *testing.T) {
|
||||||
assert := asserts.NewTestingAsserts(t, true)
|
assert := asserts.NewTestingAsserts(t, true)
|
||||||
|
|
||||||
hook := &TestHook{}
|
hook := &MockHook{}
|
||||||
hooks := make(map[string]Hook)
|
hooks := make(map[string]Hook)
|
||||||
hooks["foo"] = hook
|
hooks["foo"] = hook
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,14 @@ const HookProvision = "packer_provision"
|
||||||
// you must reference the documentation for the specific hook you're interested
|
// 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
|
// in. In addition to that, the Hook is given access to a UI so that it can
|
||||||
// output things to the user.
|
// 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 {
|
type Hook interface {
|
||||||
Run(string, Ui, Communicator, interface{}) error
|
Run(string, Ui, Communicator, interface{}) error
|
||||||
|
Cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Hook implementation that dispatches based on an internal mapping.
|
// 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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *DispatchHook) Cancel() {}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
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"
|
"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) {
|
func TestDispatchHook_Implements(t *testing.T) {
|
||||||
assert := asserts.NewTestingAsserts(t, true)
|
assert := asserts.NewTestingAsserts(t, true)
|
||||||
|
|
||||||
|
@ -40,14 +23,14 @@ func TestDispatchHook_Run_NoHooks(t *testing.T) {
|
||||||
func TestDispatchHook_Run(t *testing.T) {
|
func TestDispatchHook_Run(t *testing.T) {
|
||||||
assert := asserts.NewTestingAsserts(t, true)
|
assert := asserts.NewTestingAsserts(t, true)
|
||||||
|
|
||||||
hook := &TestHook{}
|
hook := &MockHook{}
|
||||||
|
|
||||||
mapping := make(map[string][]Hook)
|
mapping := make(map[string][]Hook)
|
||||||
mapping["foo"] = []Hook{hook}
|
mapping["foo"] = []Hook{hook}
|
||||||
dh := &DispatchHook{mapping}
|
dh := &DispatchHook{mapping}
|
||||||
dh.Run("foo", nil, nil, 42)
|
dh.Run("foo", nil, nil, 42)
|
||||||
|
|
||||||
assert.True(hook.runCalled, "run should be called")
|
assert.True(hook.RunCalled, "run should be called")
|
||||||
assert.Equal(hook.runName, "foo", "should be proper event")
|
assert.Equal(hook.RunName, "foo", "should be proper event")
|
||||||
assert.Equal(hook.runData, 42, "should be correct data")
|
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)
|
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()) {
|
func (c *cmdHook) checkExit(p interface{}, cb func()) {
|
||||||
if c.client.Exited() {
|
if c.client.Exited() && cb != nil {
|
||||||
cb()
|
cb()
|
||||||
} else if p != nil && !Killed {
|
} else if p != nil && !Killed {
|
||||||
log.Panic(p)
|
log.Panic(p)
|
||||||
|
|
|
@ -1,17 +1,10 @@
|
||||||
package plugin
|
package plugin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/mitchellh/packer/packer"
|
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type helperHook byte
|
|
||||||
|
|
||||||
func (helperHook) Run(string, packer.Ui, packer.Communicator, interface{}) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHook_NoExist(t *testing.T) {
|
func TestHook_NoExist(t *testing.T) {
|
||||||
c := NewClient(&ClientConfig{Cmd: exec.Command("i-should-not-exist")})
|
c := NewClient(&ClientConfig{Cmd: exec.Command("i-should-not-exist")})
|
||||||
defer c.Kill()
|
defer c.Kill()
|
||||||
|
|
|
@ -2,6 +2,7 @@ package plugin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/mitchellh/packer/packer"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
@ -54,7 +55,7 @@ func TestHelperProcess(*testing.T) {
|
||||||
case "command":
|
case "command":
|
||||||
ServeCommand(new(helperCommand))
|
ServeCommand(new(helperCommand))
|
||||||
case "hook":
|
case "hook":
|
||||||
ServeHook(new(helperHook))
|
ServeHook(new(packer.MockHook))
|
||||||
case "invalid-rpc-address":
|
case "invalid-rpc-address":
|
||||||
fmt.Println("lolinvalid")
|
fmt.Println("lolinvalid")
|
||||||
case "mock":
|
case "mock":
|
||||||
|
|
|
@ -32,3 +32,8 @@ func (h *ProvisionHook) Run(name string, ui Ui, comm Communicator, data interfac
|
||||||
|
|
||||||
return nil
|
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
|
// Test Run
|
||||||
cache := new(testCache)
|
cache := new(testCache)
|
||||||
hook := &testHook{}
|
hook := &packer.MockHook{}
|
||||||
ui := &testUi{}
|
ui := &testUi{}
|
||||||
artifact, err := bClient.Run(ui, hook, cache)
|
artifact, err := bClient.Run(ui, hook, cache)
|
||||||
assert.Nil(err, "should have no error")
|
assert.Nil(err, "should have no error")
|
||||||
|
@ -83,7 +83,7 @@ func TestBuilderRPC(t *testing.T) {
|
||||||
assert.True(cache.lockCalled, "lock should be called")
|
assert.True(cache.lockCalled, "lock should be called")
|
||||||
|
|
||||||
b.runHook.Run("foo", nil, nil, nil)
|
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")
|
b.runUi.Say("format")
|
||||||
assert.True(ui.sayCalled, "say should be called")
|
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{}))
|
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 {
|
func (h *HookServer) Run(args *HookRunArgs, reply *interface{}) error {
|
||||||
client, err := rpc.Dial("tcp", args.RPCAddress)
|
client, err := rpc.Dial("tcp", args.RPCAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -7,21 +7,11 @@ import (
|
||||||
"testing"
|
"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) {
|
func TestHookRPC(t *testing.T) {
|
||||||
assert := asserts.NewTestingAsserts(t, true)
|
assert := asserts.NewTestingAsserts(t, true)
|
||||||
|
|
||||||
// Create the UI to test
|
// Create the UI to test
|
||||||
h := new(testHook)
|
h := new(packer.MockHook)
|
||||||
|
|
||||||
// Serve
|
// Serve
|
||||||
server := rpc.NewServer()
|
server := rpc.NewServer()
|
||||||
|
@ -37,7 +27,7 @@ func TestHookRPC(t *testing.T) {
|
||||||
// Test Run
|
// Test Run
|
||||||
ui := &testUi{}
|
ui := &testUi{}
|
||||||
hClient.Run("foo", ui, nil, 42)
|
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) {
|
func TestHook_Implements(t *testing.T) {
|
||||||
|
|
Loading…
Reference in New Issue