packer: Add Cancel method to Provisioner
This commit is contained in:
parent
2e90660afc
commit
21171db836
|
@ -16,7 +16,7 @@ func testBuild() *coreBuild {
|
||||||
"foo": []Hook{&MockHook{}},
|
"foo": []Hook{&MockHook{}},
|
||||||
},
|
},
|
||||||
provisioners: []coreBuildProvisioner{
|
provisioners: []coreBuildProvisioner{
|
||||||
coreBuildProvisioner{&TestProvisioner{}, []interface{}{42}},
|
coreBuildProvisioner{&MockProvisioner{}, []interface{}{42}},
|
||||||
},
|
},
|
||||||
postProcessors: [][]coreBuildPostProcessor{
|
postProcessors: [][]coreBuildPostProcessor{
|
||||||
[]coreBuildPostProcessor{
|
[]coreBuildPostProcessor{
|
||||||
|
@ -59,9 +59,9 @@ func TestBuild_Prepare(t *testing.T) {
|
||||||
assert.Equal(builder.prepareConfig, []interface{}{42, packerConfig}, "prepare config should be 42")
|
assert.Equal(builder.prepareConfig, []interface{}{42, packerConfig}, "prepare config should be 42")
|
||||||
|
|
||||||
coreProv := build.provisioners[0]
|
coreProv := build.provisioners[0]
|
||||||
prov := coreProv.provisioner.(*TestProvisioner)
|
prov := coreProv.provisioner.(*MockProvisioner)
|
||||||
assert.True(prov.prepCalled, "prepare should be called")
|
assert.True(prov.PrepCalled, "prepare should be called")
|
||||||
assert.Equal(prov.prepConfigs, []interface{}{42, packerConfig}, "prepare should be called with proper config")
|
assert.Equal(prov.PrepConfigs, []interface{}{42, packerConfig}, "prepare should be called with proper config")
|
||||||
|
|
||||||
corePP := build.postProcessors[0][0]
|
corePP := build.postProcessors[0][0]
|
||||||
pp := corePP.processor.(*TestPostProcessor)
|
pp := corePP.processor.(*TestPostProcessor)
|
||||||
|
@ -104,9 +104,9 @@ func TestBuild_Prepare_Debug(t *testing.T) {
|
||||||
assert.Equal(builder.prepareConfig, []interface{}{42, packerConfig}, "prepare config should be 42")
|
assert.Equal(builder.prepareConfig, []interface{}{42, packerConfig}, "prepare config should be 42")
|
||||||
|
|
||||||
coreProv := build.provisioners[0]
|
coreProv := build.provisioners[0]
|
||||||
prov := coreProv.provisioner.(*TestProvisioner)
|
prov := coreProv.provisioner.(*MockProvisioner)
|
||||||
assert.True(prov.prepCalled, "prepare should be called")
|
assert.True(prov.PrepCalled, "prepare should be called")
|
||||||
assert.Equal(prov.prepConfigs, []interface{}{42, packerConfig}, "prepare should be called with proper config")
|
assert.Equal(prov.PrepConfigs, []interface{}{42, packerConfig}, "prepare should be called with proper config")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildPrepare_variables_default(t *testing.T) {
|
func TestBuildPrepare_variables_default(t *testing.T) {
|
||||||
|
@ -193,8 +193,8 @@ func TestBuild_Run(t *testing.T) {
|
||||||
|
|
||||||
// Verify provisioners run
|
// Verify provisioners run
|
||||||
dispatchHook.Run(HookProvision, nil, nil, 42)
|
dispatchHook.Run(HookProvision, nil, nil, 42)
|
||||||
prov := build.provisioners[0].provisioner.(*TestProvisioner)
|
prov := build.provisioners[0].provisioner.(*MockProvisioner)
|
||||||
assert.True(prov.provCalled, "provision should be called")
|
assert.True(prov.ProvCalled, "provision should be called")
|
||||||
|
|
||||||
// Verify post-processor was run
|
// Verify post-processor was run
|
||||||
pp := build.postProcessors[0][0].processor.(*TestPostProcessor)
|
pp := build.postProcessors[0][0].processor.(*TestPostProcessor)
|
||||||
|
|
|
@ -20,7 +20,7 @@ func init() {
|
||||||
func testComponentFinder() *ComponentFinder {
|
func testComponentFinder() *ComponentFinder {
|
||||||
builderFactory := func(n string) (Builder, error) { return testBuilder(), nil }
|
builderFactory := func(n string) (Builder, error) { return testBuilder(), nil }
|
||||||
ppFactory := func(n string) (PostProcessor, error) { return new(TestPostProcessor), nil }
|
ppFactory := func(n string) (PostProcessor, error) { return new(TestPostProcessor), nil }
|
||||||
provFactory := func(n string) (Provisioner, error) { return new(TestProvisioner), nil }
|
provFactory := func(n string) (Provisioner, error) { return new(MockProvisioner), nil }
|
||||||
return &ComponentFinder{
|
return &ComponentFinder{
|
||||||
Builder: builderFactory,
|
Builder: builderFactory,
|
||||||
PostProcessor: ppFactory,
|
PostProcessor: ppFactory,
|
||||||
|
@ -309,7 +309,7 @@ func TestEnvironment_PostProcessor_Error(t *testing.T) {
|
||||||
func TestEnvironmentProvisioner(t *testing.T) {
|
func TestEnvironmentProvisioner(t *testing.T) {
|
||||||
assert := asserts.NewTestingAsserts(t, true)
|
assert := asserts.NewTestingAsserts(t, true)
|
||||||
|
|
||||||
p := &TestProvisioner{}
|
p := &MockProvisioner{}
|
||||||
ps := make(map[string]Provisioner)
|
ps := make(map[string]Provisioner)
|
||||||
ps["foo"] = p
|
ps["foo"] = p
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ func TestHelperProcess(*testing.T) {
|
||||||
case "post-processor":
|
case "post-processor":
|
||||||
ServePostProcessor(new(helperPostProcessor))
|
ServePostProcessor(new(helperPostProcessor))
|
||||||
case "provisioner":
|
case "provisioner":
|
||||||
ServeProvisioner(new(helperProvisioner))
|
ServeProvisioner(new(packer.MockProvisioner))
|
||||||
case "start-timeout":
|
case "start-timeout":
|
||||||
time.Sleep(1 * time.Minute)
|
time.Sleep(1 * time.Minute)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
|
@ -28,6 +28,15 @@ func (c *cmdProvisioner) Provision(ui packer.Ui, comm packer.Communicator) error
|
||||||
return c.p.Provision(ui, comm)
|
return c.p.Provision(ui, comm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *cmdProvisioner) Cancel() {
|
||||||
|
defer func() {
|
||||||
|
r := recover()
|
||||||
|
c.checkExit(r, nil)
|
||||||
|
}()
|
||||||
|
|
||||||
|
c.p.Cancel()
|
||||||
|
}
|
||||||
|
|
||||||
func (c *cmdProvisioner) checkExit(p interface{}, cb func()) {
|
func (c *cmdProvisioner) checkExit(p interface{}, cb func()) {
|
||||||
if c.client.Exited() && cb != nil {
|
if c.client.Exited() && cb != nil {
|
||||||
cb()
|
cb()
|
||||||
|
|
|
@ -1,21 +1,10 @@
|
||||||
package plugin
|
package plugin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/mitchellh/packer/packer"
|
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type helperProvisioner byte
|
|
||||||
|
|
||||||
func (helperProvisioner) Prepare(...interface{}) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (helperProvisioner) Provision(packer.Ui, packer.Communicator) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestProvisioner_NoExist(t *testing.T) {
|
func TestProvisioner_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()
|
||||||
|
|
|
@ -13,6 +13,11 @@ type Provisioner interface {
|
||||||
// is guaranteed to be connected to some machine so that provisioning
|
// is guaranteed to be connected to some machine so that provisioning
|
||||||
// can be done.
|
// can be done.
|
||||||
Provision(Ui, Communicator) error
|
Provision(Ui, Communicator) error
|
||||||
|
|
||||||
|
// Cancel is called to cancel the provisioning. This is usually called
|
||||||
|
// while Provision is still being called. The Provisioner should act
|
||||||
|
// to stop its execution as quickly as possible in a race-free way.
|
||||||
|
Cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Hook implementation that runs the given provisioners.
|
// A Hook implementation that runs the given provisioners.
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package packer
|
||||||
|
|
||||||
|
// MockProvisioner is an implementation of Provisioner that can be
|
||||||
|
// used for tests.
|
||||||
|
type MockProvisioner struct {
|
||||||
|
PrepCalled bool
|
||||||
|
PrepConfigs []interface{}
|
||||||
|
ProvCalled bool
|
||||||
|
ProvUi Ui
|
||||||
|
CancelCalled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MockProvisioner) Prepare(configs ...interface{}) error {
|
||||||
|
t.PrepCalled = true
|
||||||
|
t.PrepConfigs = configs
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MockProvisioner) Provision(ui Ui, comm Communicator) error {
|
||||||
|
t.ProvCalled = true
|
||||||
|
t.ProvUi = ui
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MockProvisioner) Cancel() {
|
||||||
|
t.CancelCalled = true
|
||||||
|
}
|
|
@ -2,23 +2,6 @@ package packer
|
||||||
|
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
type TestProvisioner struct {
|
|
||||||
prepCalled bool
|
|
||||||
prepConfigs []interface{}
|
|
||||||
provCalled bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *TestProvisioner) Prepare(configs ...interface{}) error {
|
|
||||||
t.prepCalled = true
|
|
||||||
t.prepConfigs = configs
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *TestProvisioner) Provision(Ui, Communicator) error {
|
|
||||||
t.provCalled = true
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestProvisionHook_Impl(t *testing.T) {
|
func TestProvisionHook_Impl(t *testing.T) {
|
||||||
var raw interface{}
|
var raw interface{}
|
||||||
raw = &ProvisionHook{}
|
raw = &ProvisionHook{}
|
||||||
|
@ -28,8 +11,8 @@ func TestProvisionHook_Impl(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestProvisionHook(t *testing.T) {
|
func TestProvisionHook(t *testing.T) {
|
||||||
pA := &TestProvisioner{}
|
pA := &MockProvisioner{}
|
||||||
pB := &TestProvisioner{}
|
pB := &MockProvisioner{}
|
||||||
|
|
||||||
ui := testUi()
|
ui := testUi()
|
||||||
var comm Communicator = nil
|
var comm Communicator = nil
|
||||||
|
@ -38,11 +21,11 @@ func TestProvisionHook(t *testing.T) {
|
||||||
hook := &ProvisionHook{[]Provisioner{pA, pB}}
|
hook := &ProvisionHook{[]Provisioner{pA, pB}}
|
||||||
hook.Run("foo", ui, comm, data)
|
hook.Run("foo", ui, comm, data)
|
||||||
|
|
||||||
if !pA.provCalled {
|
if !pA.ProvCalled {
|
||||||
t.Error("provision should be called on pA")
|
t.Error("provision should be called on pA")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !pB.provCalled {
|
if !pB.ProvCalled {
|
||||||
t.Error("provision should be called on pB")
|
t.Error("provision should be called on pB")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
|
"log"
|
||||||
"net/rpc"
|
"net/rpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -47,6 +48,13 @@ func (p *provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
|
||||||
return p.client.Call("Provisioner.Provision", args, new(interface{}))
|
return p.client.Call("Provisioner.Provision", args, new(interface{}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *provisioner) Cancel() {
|
||||||
|
err := p.client.Call("Provisioner.Cancel", new(interface{}), new(interface{}))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Provisioner.Cancel err: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (p *ProvisionerServer) Prepare(args *ProvisionerPrepareArgs, reply *error) error {
|
func (p *ProvisionerServer) Prepare(args *ProvisionerPrepareArgs, reply *error) error {
|
||||||
*reply = p.p.Prepare(args.Configs...)
|
*reply = p.p.Prepare(args.Configs...)
|
||||||
if *reply != nil {
|
if *reply != nil {
|
||||||
|
@ -71,3 +79,8 @@ func (p *ProvisionerServer) Provision(args *ProvisionerProvisionArgs, reply *int
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *ProvisionerServer) Cancel(args *interface{}, reply *interface{}) error {
|
||||||
|
p.p.Cancel()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -7,32 +7,11 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type testProvisioner struct {
|
|
||||||
prepareCalled bool
|
|
||||||
prepareConfigs []interface{}
|
|
||||||
provCalled bool
|
|
||||||
provComm packer.Communicator
|
|
||||||
provUi packer.Ui
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *testProvisioner) Prepare(configs ...interface{}) error {
|
|
||||||
p.prepareCalled = true
|
|
||||||
p.prepareConfigs = configs
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *testProvisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
|
|
||||||
p.provCalled = true
|
|
||||||
p.provComm = comm
|
|
||||||
p.provUi = ui
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestProvisionerRPC(t *testing.T) {
|
func TestProvisionerRPC(t *testing.T) {
|
||||||
assert := asserts.NewTestingAsserts(t, true)
|
assert := asserts.NewTestingAsserts(t, true)
|
||||||
|
|
||||||
// Create the interface to test
|
// Create the interface to test
|
||||||
p := new(testProvisioner)
|
p := new(packer.MockProvisioner)
|
||||||
|
|
||||||
// Start the server
|
// Start the server
|
||||||
server := rpc.NewServer()
|
server := rpc.NewServer()
|
||||||
|
@ -47,17 +26,23 @@ func TestProvisionerRPC(t *testing.T) {
|
||||||
config := 42
|
config := 42
|
||||||
pClient := Provisioner(client)
|
pClient := Provisioner(client)
|
||||||
pClient.Prepare(config)
|
pClient.Prepare(config)
|
||||||
assert.True(p.prepareCalled, "prepare should be called")
|
assert.True(p.PrepCalled, "prepare should be called")
|
||||||
assert.Equal(p.prepareConfigs, []interface{}{42}, "prepare should be called with right arg")
|
assert.Equal(p.PrepConfigs, []interface{}{42}, "prepare should be called with right arg")
|
||||||
|
|
||||||
// Test Provision
|
// Test Provision
|
||||||
ui := &testUi{}
|
ui := &testUi{}
|
||||||
comm := new(packer.MockCommunicator)
|
comm := &packer.MockCommunicator{}
|
||||||
pClient.Provision(ui, comm)
|
pClient.Provision(ui, comm)
|
||||||
assert.True(p.provCalled, "provision should be called")
|
assert.True(p.ProvCalled, "provision should be called")
|
||||||
|
|
||||||
p.provUi.Say("foo")
|
p.ProvUi.Say("foo")
|
||||||
assert.True(ui.sayCalled, "say should be called")
|
assert.True(ui.sayCalled, "say should be called")
|
||||||
|
|
||||||
|
// Test Cancel
|
||||||
|
pClient.Cancel()
|
||||||
|
if !p.CancelCalled {
|
||||||
|
t.Fatal("cancel should be called")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestProvisioner_Implements(t *testing.T) {
|
func TestProvisioner_Implements(t *testing.T) {
|
||||||
|
|
|
@ -589,7 +589,7 @@ func TestTemplate_Build(t *testing.T) {
|
||||||
"test-builder": builder,
|
"test-builder": builder,
|
||||||
}
|
}
|
||||||
|
|
||||||
provisioner := &TestProvisioner{}
|
provisioner := &MockProvisioner{}
|
||||||
provisionerMap := map[string]Provisioner{
|
provisionerMap := map[string]Provisioner{
|
||||||
"test-prov": provisioner,
|
"test-prov": provisioner,
|
||||||
}
|
}
|
||||||
|
@ -677,7 +677,7 @@ func TestTemplate_Build_ProvisionerOverride(t *testing.T) {
|
||||||
"test-builder": builder,
|
"test-builder": builder,
|
||||||
}
|
}
|
||||||
|
|
||||||
provisioner := &TestProvisioner{}
|
provisioner := &MockProvisioner{}
|
||||||
provisionerMap := map[string]Provisioner{
|
provisionerMap := map[string]Provisioner{
|
||||||
"test-prov": provisioner,
|
"test-prov": provisioner,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue