2019-04-04 10:37:46 -04:00
|
|
|
package packer
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
// TimeoutProvisioner is a Provisioner implementation that can timeout after a
|
|
|
|
// duration
|
|
|
|
type TimeoutProvisioner struct {
|
|
|
|
Provisioner
|
|
|
|
Timeout time.Duration
|
|
|
|
}
|
|
|
|
|
2019-10-04 14:36:57 -04:00
|
|
|
func (p *TimeoutProvisioner) Provision(ctx context.Context, ui Ui, comm Communicator, generatedData interface{}) error {
|
2019-04-04 10:37:46 -04:00
|
|
|
ctx, cancel := context.WithTimeout(ctx, p.Timeout)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
// Use a select to determine if we get cancelled during the wait
|
|
|
|
ui.Say(fmt.Sprintf("Setting a %s timeout for the next provisioner...", p.Timeout))
|
2019-04-09 09:29:07 -04:00
|
|
|
|
|
|
|
errC := make(chan interface{})
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
select {
|
|
|
|
case <-errC:
|
|
|
|
// all good
|
|
|
|
case <-ctx.Done():
|
|
|
|
switch ctx.Err() {
|
|
|
|
case context.DeadlineExceeded:
|
|
|
|
ui.Error("Cancelling provisioner after a timeout...")
|
|
|
|
default:
|
|
|
|
// the context also gets cancelled when the provisioner is
|
|
|
|
// successful
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2019-07-11 12:37:59 -04:00
|
|
|
err := p.Provisioner.Provision(ctx, ui, comm, generatedData)
|
2019-04-09 09:29:07 -04:00
|
|
|
close(errC)
|
|
|
|
return err
|
2019-04-04 10:37:46 -04:00
|
|
|
}
|