mirror of
https://github.com/hashicorp/packer.git
synced 2026-09-19 06:21:41 -04:00
* Updating the license from MPL to Business Source License Going forward, this project will be licensed under the Business Source License v1.1. Please see our blog post for more details at https://hashi.co/bsl-blog, FAQ at https://hashi.co/license-faq, and details of the license at www.hashicorp.com/bsl. * Update copyright file headers to BUSL-1.1 --------- Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
349 lines
7.6 KiB
Go
349 lines
7.6 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package packer
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
)
|
|
|
|
func TestProvisionHook_Impl(t *testing.T) {
|
|
var raw interface{}
|
|
raw = &ProvisionHook{}
|
|
if _, ok := raw.(packersdk.Hook); !ok {
|
|
t.Fatalf("must be a Hook")
|
|
}
|
|
}
|
|
|
|
func TestProvisionHook(t *testing.T) {
|
|
pA := &packersdk.MockProvisioner{}
|
|
pB := &packersdk.MockProvisioner{}
|
|
|
|
ui := testUi()
|
|
var comm packersdk.Communicator = new(packersdk.MockCommunicator)
|
|
var data interface{} = nil
|
|
|
|
hook := &ProvisionHook{
|
|
Provisioners: []*HookedProvisioner{
|
|
{pA, nil, ""},
|
|
{pB, nil, ""},
|
|
},
|
|
}
|
|
|
|
hook.Run(context.Background(), "foo", ui, comm, data)
|
|
|
|
if !pA.ProvCalled {
|
|
t.Error("provision should be called on pA")
|
|
}
|
|
|
|
if !pB.ProvCalled {
|
|
t.Error("provision should be called on pB")
|
|
}
|
|
}
|
|
|
|
func TestProvisionHook_nilComm(t *testing.T) {
|
|
pA := &packersdk.MockProvisioner{}
|
|
pB := &packersdk.MockProvisioner{}
|
|
|
|
ui := testUi()
|
|
var comm packersdk.Communicator = nil
|
|
var data interface{} = nil
|
|
|
|
hook := &ProvisionHook{
|
|
Provisioners: []*HookedProvisioner{
|
|
{pA, nil, ""},
|
|
{pB, nil, ""},
|
|
},
|
|
}
|
|
|
|
err := hook.Run(context.Background(), "foo", ui, comm, data)
|
|
if err == nil {
|
|
t.Fatal("should error")
|
|
}
|
|
}
|
|
|
|
func TestProvisionHook_cancel(t *testing.T) {
|
|
topCtx, topCtxCancel := context.WithCancel(context.Background())
|
|
|
|
p := &packersdk.MockProvisioner{
|
|
ProvFunc: func(ctx context.Context) error {
|
|
topCtxCancel()
|
|
<-ctx.Done()
|
|
return ctx.Err()
|
|
},
|
|
}
|
|
|
|
hook := &ProvisionHook{
|
|
Provisioners: []*HookedProvisioner{
|
|
{p, nil, ""},
|
|
},
|
|
}
|
|
|
|
err := hook.Run(topCtx, "foo", nil, new(packersdk.MockCommunicator), nil)
|
|
if err == nil {
|
|
t.Fatal("should have err")
|
|
}
|
|
}
|
|
|
|
// TODO(mitchellh): Test that they're run in the proper order
|
|
|
|
func TestPausedProvisioner_impl(t *testing.T) {
|
|
var _ packersdk.Provisioner = new(PausedProvisioner)
|
|
}
|
|
|
|
func TestPausedProvisionerPrepare(t *testing.T) {
|
|
mock := new(packersdk.MockProvisioner)
|
|
prov := &PausedProvisioner{
|
|
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 TestPausedProvisionerProvision(t *testing.T) {
|
|
mock := new(packersdk.MockProvisioner)
|
|
prov := &PausedProvisioner{
|
|
Provisioner: mock,
|
|
}
|
|
|
|
ui := testUi()
|
|
comm := new(packersdk.MockCommunicator)
|
|
prov.Provision(context.Background(), ui, comm, make(map[string]interface{}))
|
|
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 TestPausedProvisionerProvision_waits(t *testing.T) {
|
|
startTime := time.Now()
|
|
waitTime := 50 * time.Millisecond
|
|
|
|
prov := &PausedProvisioner{
|
|
PauseBefore: waitTime,
|
|
Provisioner: &packersdk.MockProvisioner{
|
|
ProvFunc: func(context.Context) error {
|
|
timeSinceStartTime := time.Since(startTime)
|
|
if timeSinceStartTime < waitTime {
|
|
return fmt.Errorf("Spent not enough time waiting: %s", timeSinceStartTime)
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
}
|
|
|
|
err := prov.Provision(context.Background(), testUi(), new(packersdk.MockCommunicator), make(map[string]interface{}))
|
|
|
|
if err != nil {
|
|
t.Fatalf("prov failed: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestPausedProvisionerCancel(t *testing.T) {
|
|
topCtx, cancelTopCtx := context.WithCancel(context.Background())
|
|
|
|
mock := new(packersdk.MockProvisioner)
|
|
prov := &PausedProvisioner{
|
|
Provisioner: mock,
|
|
}
|
|
|
|
mock.ProvFunc = func(ctx context.Context) error {
|
|
cancelTopCtx()
|
|
<-ctx.Done()
|
|
return ctx.Err()
|
|
}
|
|
|
|
err := prov.Provision(topCtx, testUi(), new(packersdk.MockCommunicator), make(map[string]interface{}))
|
|
if err == nil {
|
|
t.Fatal("should have err")
|
|
}
|
|
}
|
|
|
|
func TestDebuggedProvisioner_impl(t *testing.T) {
|
|
var _ packersdk.Provisioner = new(DebuggedProvisioner)
|
|
}
|
|
|
|
func TestDebuggedProvisionerPrepare(t *testing.T) {
|
|
mock := new(packersdk.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(packersdk.MockProvisioner)
|
|
prov := &DebuggedProvisioner{
|
|
Provisioner: mock,
|
|
}
|
|
|
|
ui := testUi()
|
|
comm := new(packersdk.MockCommunicator)
|
|
writeReader(ui, "\n")
|
|
prov.Provision(context.Background(), ui, comm, make(map[string]interface{}))
|
|
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) {
|
|
topCtx, topCtxCancel := context.WithCancel(context.Background())
|
|
|
|
mock := new(packersdk.MockProvisioner)
|
|
prov := &DebuggedProvisioner{
|
|
Provisioner: mock,
|
|
}
|
|
|
|
mock.ProvFunc = func(ctx context.Context) error {
|
|
topCtxCancel()
|
|
<-ctx.Done()
|
|
return ctx.Err()
|
|
}
|
|
|
|
err := prov.Provision(topCtx, testUi(), new(packersdk.MockCommunicator), make(map[string]interface{}))
|
|
if err == nil {
|
|
t.Fatal("should have error")
|
|
}
|
|
}
|
|
|
|
func TestRetriedProvisioner_impl(t *testing.T) {
|
|
var _ packersdk.Provisioner = new(RetriedProvisioner)
|
|
}
|
|
|
|
func TestRetriedProvisionerPrepare(t *testing.T) {
|
|
mock := new(packersdk.MockProvisioner)
|
|
prov := &RetriedProvisioner{
|
|
Provisioner: mock,
|
|
}
|
|
|
|
err := prov.Prepare(42)
|
|
if err != nil {
|
|
t.Fatal("should not have errored")
|
|
}
|
|
if !mock.PrepCalled {
|
|
t.Fatal("prepare should be called")
|
|
}
|
|
if mock.PrepConfigs[0] != 42 {
|
|
t.Fatal("should have proper configs")
|
|
}
|
|
}
|
|
|
|
func TestRetriedProvisionerProvision(t *testing.T) {
|
|
mock := &packersdk.MockProvisioner{
|
|
ProvFunc: func(ctx context.Context) error {
|
|
return errors.New("failed")
|
|
},
|
|
}
|
|
|
|
prov := &RetriedProvisioner{
|
|
MaxRetries: 2,
|
|
Provisioner: mock,
|
|
}
|
|
|
|
ui := testUi()
|
|
comm := new(packersdk.MockCommunicator)
|
|
err := prov.Provision(context.Background(), ui, comm, make(map[string]interface{}))
|
|
if err != nil {
|
|
t.Fatal("should not have errored")
|
|
}
|
|
if !mock.ProvCalled {
|
|
t.Fatal("prov should be called")
|
|
}
|
|
if !mock.ProvRetried {
|
|
t.Fatal("prov should be retried")
|
|
}
|
|
if mock.ProvUi != ui {
|
|
t.Fatal("should have proper ui")
|
|
}
|
|
if mock.ProvCommunicator != comm {
|
|
t.Fatal("should have proper comm")
|
|
}
|
|
}
|
|
|
|
func TestRetriedProvisionerCancelledProvision(t *testing.T) {
|
|
// Don't retry if context is cancelled
|
|
ctx, topCtxCancel := context.WithCancel(context.Background())
|
|
|
|
mock := &packersdk.MockProvisioner{
|
|
ProvFunc: func(ctx context.Context) error {
|
|
topCtxCancel()
|
|
<-ctx.Done()
|
|
return ctx.Err()
|
|
},
|
|
}
|
|
|
|
prov := &RetriedProvisioner{
|
|
MaxRetries: 2,
|
|
Provisioner: mock,
|
|
}
|
|
|
|
ui := testUi()
|
|
comm := new(packersdk.MockCommunicator)
|
|
err := prov.Provision(ctx, ui, comm, make(map[string]interface{}))
|
|
if err == nil {
|
|
t.Fatal("should have errored")
|
|
}
|
|
if !mock.ProvCalled {
|
|
t.Fatal("prov should be called")
|
|
}
|
|
if mock.ProvRetried {
|
|
t.Fatal("prov should NOT be retried")
|
|
}
|
|
if mock.ProvUi != ui {
|
|
t.Fatal("should have proper ui")
|
|
}
|
|
if mock.ProvCommunicator != comm {
|
|
t.Fatal("should have proper comm")
|
|
}
|
|
}
|
|
|
|
func TestRetriedProvisionerCancel(t *testing.T) {
|
|
topCtx, cancelTopCtx := context.WithCancel(context.Background())
|
|
|
|
mock := new(packersdk.MockProvisioner)
|
|
prov := &RetriedProvisioner{
|
|
Provisioner: mock,
|
|
}
|
|
|
|
mock.ProvFunc = func(ctx context.Context) error {
|
|
cancelTopCtx()
|
|
<-ctx.Done()
|
|
return ctx.Err()
|
|
}
|
|
|
|
err := prov.Provision(topCtx, testUi(), new(packersdk.MockCommunicator), make(map[string]interface{}))
|
|
if err == nil {
|
|
t.Fatal("should have err")
|
|
}
|
|
}
|