Merge pull request #4663 from marema31/debug-prompt-provisionner
Debug prompt between provisioner scripts
This commit is contained in:
commit
b4fd69a963
|
@ -200,10 +200,18 @@ func (b *coreBuild) Run(originalUi Ui, cache Cache) ([]Artifact, error) {
|
||||||
if len(p.config) > 0 {
|
if len(p.config) > 0 {
|
||||||
pConfig = p.config[0]
|
pConfig = p.config[0]
|
||||||
}
|
}
|
||||||
hookedProvisioners[i] = &HookedProvisioner{
|
if b.debug {
|
||||||
p.provisioner,
|
hookedProvisioners[i] = &HookedProvisioner{
|
||||||
pConfig,
|
&DebuggedProvisioner{Provisioner: p.provisioner},
|
||||||
p.pType,
|
pConfig,
|
||||||
|
p.pType,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hookedProvisioners[i] = &HookedProvisioner{
|
||||||
|
p.provisioner,
|
||||||
|
pConfig,
|
||||||
|
p.pType,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package packer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -168,3 +169,90 @@ func (p *PausedProvisioner) Cancel() {
|
||||||
func (p *PausedProvisioner) provision(result chan<- error, ui Ui, comm Communicator) {
|
func (p *PausedProvisioner) provision(result chan<- error, ui Ui, comm Communicator) {
|
||||||
result <- p.Provisioner.Provision(ui, comm)
|
result <- p.Provisioner.Provision(ui, comm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DebuggedProvisioner is a Provisioner implementation that waits until a key
|
||||||
|
// press before the provisioner is actually run.
|
||||||
|
type DebuggedProvisioner struct {
|
||||||
|
Provisioner Provisioner
|
||||||
|
|
||||||
|
cancelCh chan struct{}
|
||||||
|
doneCh chan struct{}
|
||||||
|
lock sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *DebuggedProvisioner) Prepare(raws ...interface{}) error {
|
||||||
|
return p.Provisioner.Prepare(raws...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *DebuggedProvisioner) Provision(ui Ui, comm Communicator) error {
|
||||||
|
p.lock.Lock()
|
||||||
|
cancelCh := make(chan struct{})
|
||||||
|
p.cancelCh = cancelCh
|
||||||
|
|
||||||
|
// Setup the done channel, which is trigger when we're done
|
||||||
|
doneCh := make(chan struct{})
|
||||||
|
defer close(doneCh)
|
||||||
|
p.doneCh = doneCh
|
||||||
|
p.lock.Unlock()
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
p.lock.Lock()
|
||||||
|
defer p.lock.Unlock()
|
||||||
|
if p.cancelCh == cancelCh {
|
||||||
|
p.cancelCh = nil
|
||||||
|
}
|
||||||
|
if p.doneCh == doneCh {
|
||||||
|
p.doneCh = nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Use a select to determine if we get cancelled during the wait
|
||||||
|
message := "Pausing before the next provisioner . Press enter to continue."
|
||||||
|
|
||||||
|
result := make(chan string, 1)
|
||||||
|
go func() {
|
||||||
|
line, err := ui.Ask(message)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error asking for input: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
result <- line
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-result:
|
||||||
|
case <-cancelCh:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
provDoneCh := make(chan error, 1)
|
||||||
|
go p.provision(provDoneCh, ui, comm)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case err := <-provDoneCh:
|
||||||
|
return err
|
||||||
|
case <-cancelCh:
|
||||||
|
p.Provisioner.Cancel()
|
||||||
|
return <-provDoneCh
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *DebuggedProvisioner) Cancel() {
|
||||||
|
var doneCh chan struct{}
|
||||||
|
|
||||||
|
p.lock.Lock()
|
||||||
|
if p.cancelCh != nil {
|
||||||
|
close(p.cancelCh)
|
||||||
|
p.cancelCh = nil
|
||||||
|
}
|
||||||
|
if p.doneCh != nil {
|
||||||
|
doneCh = p.doneCh
|
||||||
|
}
|
||||||
|
p.lock.Unlock()
|
||||||
|
|
||||||
|
<-doneCh
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *DebuggedProvisioner) provision(result chan<- error, ui Ui, comm Communicator) {
|
||||||
|
result <- p.Provisioner.Provision(ui, comm)
|
||||||
|
}
|
||||||
|
|
|
@ -197,3 +197,67 @@ func TestPausedProvisionerCancel(t *testing.T) {
|
||||||
t.Fatal("cancel should be called")
|
t.Fatal("cancel should be called")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDebuggedProvisioner_impl(t *testing.T) {
|
||||||
|
var _ Provisioner = new(DebuggedProvisioner)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDebuggedProvisionerPrepare(t *testing.T) {
|
||||||
|
mock := new(MockProvisioner)
|
||||||
|
prov := &DebuggedProvisioner{
|
||||||
|
Provisioner: mock,
|
||||||
|
}
|
||||||
|
|
||||||
|
prov.Prepare(42)
|
||||||
|
if !mock.PrepCalled {
|
||||||
|
t.Fatal("prepare should be called")
|
||||||
|
}
|
||||||
|
if mock.PrepConfigs[0] != 42 {
|
||||||
|
t.Fatal("should have proper configs")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDebuggedProvisionerProvision(t *testing.T) {
|
||||||
|
mock := new(MockProvisioner)
|
||||||
|
prov := &DebuggedProvisioner{
|
||||||
|
Provisioner: mock,
|
||||||
|
}
|
||||||
|
|
||||||
|
ui := testUi()
|
||||||
|
comm := new(MockCommunicator)
|
||||||
|
writeReader(ui, "\n")
|
||||||
|
prov.Provision(ui, comm)
|
||||||
|
if !mock.ProvCalled {
|
||||||
|
t.Fatal("prov should be called")
|
||||||
|
}
|
||||||
|
if mock.ProvUi != ui {
|
||||||
|
t.Fatal("should have proper ui")
|
||||||
|
}
|
||||||
|
if mock.ProvCommunicator != comm {
|
||||||
|
t.Fatal("should have proper comm")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDebuggedProvisionerCancel(t *testing.T) {
|
||||||
|
mock := new(MockProvisioner)
|
||||||
|
prov := &DebuggedProvisioner{
|
||||||
|
Provisioner: mock,
|
||||||
|
}
|
||||||
|
|
||||||
|
provCh := make(chan struct{})
|
||||||
|
mock.ProvFunc = func() error {
|
||||||
|
close(provCh)
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start provisioning and wait for it to start
|
||||||
|
go prov.Provision(testUi(), new(MockCommunicator))
|
||||||
|
<-provCh
|
||||||
|
|
||||||
|
// Cancel it
|
||||||
|
prov.Cancel()
|
||||||
|
if !mock.CancelCalled {
|
||||||
|
t.Fatal("cancel should be called")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue