Refactor provisioner acceptance tests to shell directly out to Packer rather than import the core. Modify test case formatting to more closely reflect the builder test cases.
This commit is contained in:
parent
bc7dae2dff
commit
76177b50ce
2
Makefile
2
Makefile
|
@ -140,7 +140,7 @@ test: mode-check vet ## Run unit tests
|
|||
@go test -count $(COUNT) $(TEST) $(TESTARGS) -timeout=3m
|
||||
|
||||
# acctest runs provisioners acceptance tests
|
||||
provisioners-acctest: install-build-deps generate
|
||||
provisioners-acctest: #install-build-deps generate
|
||||
ACC_TEST_BUILDERS=$(ACC_TEST_BUILDERS) ACC_TEST_PROVISIONERS=$(ACC_TEST_PROVISIONERS) go test ./provisioner/... -timeout=1h
|
||||
|
||||
# testacc runs acceptance tests
|
||||
|
|
|
@ -27,7 +27,7 @@ func (v *VirtualBoxISOAccTest) GetConfigs() (map[string]string, error) {
|
|||
|
||||
file, err := ioutil.ReadAll(config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Uneble to read %s", filePath)
|
||||
return nil, fmt.Errorf("Unable to read %s", filePath)
|
||||
}
|
||||
return map[string]string{"linux": string(file)}, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package provisioneracc
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/packer/packer-plugin-sdk/acctest/testutils"
|
||||
)
|
||||
|
||||
var AmasonEBSBuilderFixtureLinux = &BuilderFixture{
|
||||
Name: "Amazon-ebs Linux builder",
|
||||
TemplatePath: "amazon-ebs/amazon-ebs.txt",
|
||||
GuestOS: "linux",
|
||||
HostOS: "any",
|
||||
Teardown: func() error {
|
||||
// TODO
|
||||
// helper := AWSHelper{
|
||||
// Region: "us-east-1",
|
||||
// AMIName: "packer-acc-test",
|
||||
// }
|
||||
// return helper.CleanUpAmi()
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var AmasonEBSBuilderFixtureWindows = &BuilderFixture{
|
||||
Name: "Amazon-ebs Windows builder",
|
||||
TemplatePath: "amazon-ebs/amazon-ebs_windows.txt",
|
||||
GuestOS: "windows",
|
||||
HostOS: "any",
|
||||
Teardown: func() error {
|
||||
// TODO
|
||||
// helper := AWSHelper{
|
||||
// Region: "us-east-1",
|
||||
// AMIName: "packer-acc-test",
|
||||
// }
|
||||
// return helper.CleanUpAmi()
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var VirtualboxBuilderFixtureWindows = &BuilderFixture{
|
||||
Name: "Virtualbox Windows builder",
|
||||
TemplatePath: "virtualbox/virtualbox-iso.txt",
|
||||
GuestOS: "linux",
|
||||
HostOS: "any",
|
||||
Teardown: func() error {
|
||||
testutils.CleanupFiles("virtualbox-iso-packer-acc-test")
|
||||
testutils.CleanupFiles("packer_cache")
|
||||
return nil
|
||||
},
|
||||
}
|
|
@ -3,65 +3,243 @@ package provisioneracc
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
amazonEBS "github.com/hashicorp/packer/builder/amazon/ebs/acceptance"
|
||||
virtualboxISO "github.com/hashicorp/packer/builder/virtualbox/iso/acceptance"
|
||||
"github.com/hashicorp/packer/command"
|
||||
"github.com/hashicorp/packer/packer-plugin-sdk/acctest/testutils"
|
||||
builderT "github.com/hashicorp/packer/packer-plugin-sdk/acctest"
|
||||
packersdk "github.com/hashicorp/packer/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
func TestProvisionersAgainstBuilders(provisionerAcc ProvisionerAcceptance, t *testing.T) {
|
||||
provisioner := provisionerAcc.GetName()
|
||||
builders := checkBuilders(t)
|
||||
// ProvisionerTestCase is a single set of tests to run for a provisioner.
|
||||
// A ProvisionerTestCase should generally map 1:1 to each test method for your
|
||||
// acceptance tests.
|
||||
type ProvisionerTestCase struct {
|
||||
// Check is called after this step is executed in order to test that
|
||||
// the step executed successfully. If this is not set, then the next
|
||||
// step will be called
|
||||
Check func(*exec.Cmd, string) error
|
||||
// IsCompatible checks whether a provisioner is able to run against a
|
||||
// given builder type and guest operating system, and returns a boolean.
|
||||
// if it returns true, the test combination is okay to run. If false, the
|
||||
// test combination is not okay to run.
|
||||
IsCompatible func(builderType string, BuilderGuestOS string) bool
|
||||
// Name is the name of the test case. Be simple but unique and descriptive.
|
||||
Name string
|
||||
// Setup, if non-nil, will be called once before the test case
|
||||
// runs. This can be used for some setup like setting environment
|
||||
// variables, or for validation prior to the
|
||||
// test running. For example, you can use this to make sure certain
|
||||
// binaries are installed, or text fixtures are in place.
|
||||
Setup func() error
|
||||
// Teardown will be called before the test case is over regardless
|
||||
// of if the test succeeded or failed. This should return an error
|
||||
// in the case that the test can't guarantee all resources were
|
||||
// properly cleaned up.
|
||||
Teardown builderT.TestTeardownFunc
|
||||
// Template is the provisioner template to use.
|
||||
// The provisioner template fragment must be a json-formatted string
|
||||
// containing the provisioner definition but no other portions of a packer
|
||||
// template. For
|
||||
// example:
|
||||
//
|
||||
// ```json
|
||||
// {
|
||||
// "type": "shell-local",
|
||||
// "inline", ["echo hello world"]
|
||||
// }
|
||||
//```
|
||||
//
|
||||
// is a valid entry for "template" here, but the complete Packer template:
|
||||
//
|
||||
// ```json
|
||||
// {
|
||||
// "provisioners": [
|
||||
// {
|
||||
// "type": "shell-local",
|
||||
// "inline", ["echo hello world"]
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// is invalid as input.
|
||||
//
|
||||
// You may provide multiple provisioners in the same template. For example:
|
||||
// ```json
|
||||
// {
|
||||
// "type": "shell-local",
|
||||
// "inline", ["echo hello world"]
|
||||
// },
|
||||
// {
|
||||
// "type": "shell-local",
|
||||
// "inline", ["echo hello world 2"]
|
||||
// }
|
||||
// ```
|
||||
Template string
|
||||
// Type is the type of provisioner.
|
||||
Type string
|
||||
}
|
||||
|
||||
// build template file and run a build for each builder with the provisioner
|
||||
for _, builder := range builders {
|
||||
builderAcc := BuildersAccTest[builder]
|
||||
builderConfigs, err := builderAcc.GetConfigs()
|
||||
if err != nil {
|
||||
t.Fatalf("bad: failed to read builder config: %s", err.Error())
|
||||
}
|
||||
// BuilderFixtures are basic builder test configurations and metadata used
|
||||
// in provisioner acceptance testing. These are frameworks to be used by
|
||||
// provisioner tests, not tests in and of themselves. BuilderFixtures should
|
||||
// generally be simple and not contain excessive or complex configurations.
|
||||
// Instantiations of this struct are stored in the builders.go file in this
|
||||
// module.
|
||||
type BuilderFixture struct {
|
||||
// Name is the name of the builder fixture.
|
||||
// Be simple and descriptive.
|
||||
Name string
|
||||
// Setup creates necessary extra test fixtures, and renders their values
|
||||
// into the BuilderFixture.Template.
|
||||
Setup func()
|
||||
// Template is the path to a builder template fragment.
|
||||
// The builder template fragment must be a json-formatted file containing
|
||||
// the builder definition but no other portions of a packer template. For
|
||||
// example:
|
||||
//
|
||||
// ```json
|
||||
// {
|
||||
// "type": "null",
|
||||
// "communicator", "none"
|
||||
// }
|
||||
//```
|
||||
//
|
||||
// is a valid entry for "template" here, but the complete Packer template:
|
||||
//
|
||||
// ```json
|
||||
// {
|
||||
// "builders": [
|
||||
// "type": "null",
|
||||
// "communicator": "none"
|
||||
// ]
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// is invalid as input.
|
||||
//
|
||||
// Only provide one builder template fragment per file.
|
||||
TemplatePath string
|
||||
|
||||
for vmOS, builderConfig := range builderConfigs {
|
||||
if !provisionerAcc.IsCompatible(builder, vmOS) {
|
||||
// GuestOS says what guest os type the builder template fragment creates.
|
||||
// Valid values are "windows", "linux" or "darwin" guests.
|
||||
GuestOS string
|
||||
|
||||
// HostOS says what host os type the builder is capable of running on.
|
||||
// Valid values are "any", windows", or "posix". If you set "posix", then
|
||||
// this builder can run on a "linux" or "darwin" platform. If you set
|
||||
// "any", then this builder can be used on any platform.
|
||||
HostOS string
|
||||
|
||||
Teardown builderT.TestTeardownFunc
|
||||
}
|
||||
|
||||
func fixtureDir() string {
|
||||
_, file, _, _ := runtime.Caller(0)
|
||||
return filepath.Join(filepath.Dir(file), "test-fixtures")
|
||||
}
|
||||
|
||||
func LoadBuilderFragment(templateFragmentPath string) (string, error) {
|
||||
dir := fixtureDir()
|
||||
fragmentAbsPath := filepath.Join(dir, templateFragmentPath)
|
||||
fragmentFile, err := os.Open(fragmentAbsPath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Unable find %s", fragmentAbsPath)
|
||||
}
|
||||
defer fragmentFile.Close()
|
||||
|
||||
fragmentString, err := ioutil.ReadAll(fragmentFile)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Unable to read %s", fragmentAbsPath)
|
||||
}
|
||||
|
||||
return string(fragmentString), nil
|
||||
}
|
||||
|
||||
func RunProvisionerAccTest(testCase *ProvisionerTestCase, t *testing.T) {
|
||||
TestProvisionersPreCheck(testCase.Type, t)
|
||||
TestProvisionersAgainstBuilders(testCase, t)
|
||||
}
|
||||
|
||||
func TestProvisionersAgainstBuilders(testCase *ProvisionerTestCase, t *testing.T) {
|
||||
// retrieve user-desired builders.
|
||||
builderTypes := checkBuilders(t)
|
||||
|
||||
// Run this provisioner test case against each builder type requested.
|
||||
for _, builderType := range builderTypes {
|
||||
buildFixtures := BuildersAccTest[builderType]
|
||||
// loop over individual build templates, merge with provisioner
|
||||
// templates, and shell out to run test.
|
||||
for _, buildFixture := range buildFixtures {
|
||||
if !testCase.IsCompatible(builderType, buildFixture.GuestOS) {
|
||||
continue
|
||||
}
|
||||
|
||||
testName := fmt.Sprintf("testing %s builder against %s provisioner", builder, provisioner)
|
||||
testName := fmt.Sprintf("%s on %s", testCase.Name, buildFixture.Name)
|
||||
|
||||
if testCase.Setup != nil {
|
||||
err := testCase.Setup()
|
||||
if err != nil {
|
||||
t.Fatalf("test %s setup failed: %s", testName, err)
|
||||
}
|
||||
}
|
||||
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
provisionerConfig, err := provisionerAcc.GetConfig()
|
||||
builderFragment, err := LoadBuilderFragment(buildFixture.TemplatePath)
|
||||
if err != nil {
|
||||
t.Fatalf("bad: failed to read provisioner config: %s", err.Error())
|
||||
t.Fatalf("failed to load builder fragment: %s", err)
|
||||
}
|
||||
|
||||
// Write json template
|
||||
// Combine provisioner and builder template fragments; write to
|
||||
// file.
|
||||
out := bytes.NewBuffer(nil)
|
||||
fmt.Fprintf(out, `{"builders": [%s],"provisioners": [%s]}`, builderConfig, provisionerConfig)
|
||||
fileName := fmt.Sprintf("%s_%s.json", builder, provisioner)
|
||||
filePath := filepath.Join("./", fileName)
|
||||
writeJsonTemplate(out, filePath, t)
|
||||
fmt.Fprintf(out, `{"builders": [%s],"provisioners": [%s]}`,
|
||||
builderFragment, testCase.Template)
|
||||
templateName := fmt.Sprintf("%s_%s.json", builderType, testCase.Type)
|
||||
templatePath := filepath.Join("./", templateName)
|
||||
writeJsonTemplate(out, templatePath, t)
|
||||
logfile := fmt.Sprintf("packer_log_%s_%s.txt", builderType, testCase.Type)
|
||||
|
||||
// set pre-config with necessary builder and provisioner
|
||||
c := buildCommand(t, builderAcc, provisionerAcc)
|
||||
args := []string{
|
||||
filePath,
|
||||
// Run build
|
||||
// TODO: stream logs _and_ store in a logfile.
|
||||
buildCommand := exec.Command("packer", "build", "--machine-readable", templatePath)
|
||||
buildCommand.Env = append(buildCommand.Env, os.Environ()...)
|
||||
buildCommand.Env = append(buildCommand.Env, "PACKER_LOG=1",
|
||||
fmt.Sprintf("PACKER_LOG_PATH=%s", logfile))
|
||||
buildCommand.Run()
|
||||
|
||||
// Check for test custom pass/fail before we clean up
|
||||
var checkErr error
|
||||
if testCase.Check != nil {
|
||||
checkErr = testCase.Check(buildCommand, logfile)
|
||||
}
|
||||
|
||||
err = provisionerAcc.RunTest(c, args)
|
||||
// Cleanup created resources
|
||||
testutils.CleanupFiles(fileName)
|
||||
cleanErr := builderAcc.CleanUp()
|
||||
// preemptive cleanup
|
||||
defer os.Remove(templatePath)
|
||||
defer os.Remove(logfile)
|
||||
|
||||
// Cleanup stuff created by builder.
|
||||
cleanErr := buildFixture.Teardown()
|
||||
if cleanErr != nil {
|
||||
log.Printf("bad: failed to clean up resources: %s", cleanErr.Error())
|
||||
log.Printf("bad: failed to clean up builder-created resources: %s", cleanErr.Error())
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("bad: failed to to run build: %s", err.Error())
|
||||
// Clean up anything created in provisioner run
|
||||
if testCase.Teardown != nil {
|
||||
cleanErr = testCase.Teardown()
|
||||
if cleanErr != nil {
|
||||
log.Printf("bad: failed to clean up test-created resources: %s", cleanErr.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// Fail test if check failed.
|
||||
if checkErr != nil {
|
||||
t.Fatalf(checkErr.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -88,6 +266,8 @@ func TestProvisionersPreCheck(name string, t *testing.T) {
|
|||
|
||||
}
|
||||
|
||||
// checkBuilders retrieves all of the builders that the user has requested to
|
||||
// run acceptance tests against.
|
||||
func checkBuilders(t *testing.T) []string {
|
||||
b := os.Getenv("ACC_TEST_BUILDERS")
|
||||
// validate if we want to run provisioners acc tests
|
||||
|
@ -119,32 +299,52 @@ func writeJsonTemplate(out *bytes.Buffer, filePath string, t *testing.T) {
|
|||
outputFile.Sync()
|
||||
}
|
||||
|
||||
func buildCommand(t *testing.T, builder BuilderAcceptance, provisioner ProvisionerAcceptance) *command.BuildCommand {
|
||||
c := &command.BuildCommand{
|
||||
Meta: TestMetaFile(t),
|
||||
}
|
||||
c.CoreConfig.Components.BuilderStore = builder.GetBuilderStore()
|
||||
c.CoreConfig.Components.ProvisionerStore = provisioner.GetProvisionerStore()
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
type ProvisionerAcceptance interface {
|
||||
GetName() string
|
||||
GetConfig() (string, error)
|
||||
GetProvisionerStore() packersdk.MapOfProvisioner
|
||||
IsCompatible(builder string, vmOS string) bool
|
||||
RunTest(c *command.BuildCommand, args []string) error
|
||||
}
|
||||
|
||||
// BuilderAcceptance is specialized tooling implemented by individual builders
|
||||
// To add your builder to the provisioner testing framework, create a struct
|
||||
// that implements the this interface, add it to the BuildersAccTest map below.
|
||||
// TODO add this interface to the plugin server so that Packer can request it
|
||||
// From the plugin rather than importing it here.
|
||||
type BuilderAcceptance interface {
|
||||
// GetConfigs provides a mapping of guest OS architecture to builder
|
||||
// template fragment.
|
||||
// The builder template fragment must be a json-formatted string containing
|
||||
// the builder definition but no other portions of a packer template. For
|
||||
// example:
|
||||
//
|
||||
// ```json
|
||||
// {
|
||||
// "type": "null",
|
||||
// "communicator", "none"
|
||||
// }
|
||||
//```
|
||||
//
|
||||
// is a valid entry for "template" here, but the complete Packer template:
|
||||
//
|
||||
// ```json
|
||||
// {
|
||||
// "builders": [
|
||||
// "type": "null",
|
||||
// "communicator": "none"
|
||||
// ]
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// is invalid as input.
|
||||
//
|
||||
// Valid keys for the map are "linux" and "windows". These keys will be used
|
||||
// to determine whether a given builder template is compatible with a given
|
||||
// provisioner template.
|
||||
GetConfigs() (map[string]string, error)
|
||||
// GetBuilderStore() returns a MapOfBuilder that contains the actual builder
|
||||
// struct definition being used for this test.
|
||||
GetBuilderStore() packersdk.MapOfBuilder
|
||||
// CleanUp cleans up any side-effects of the builder not already cleaned up
|
||||
// by the builderT framework.
|
||||
CleanUp() error
|
||||
}
|
||||
|
||||
// List of all builders available for acceptance test
|
||||
var BuildersAccTest = map[string]BuilderAcceptance{
|
||||
"virtualbox-iso": new(virtualboxISO.VirtualBoxISOAccTest),
|
||||
"amazon-ebs": new(amazonEBS.AmazonEBSAccTest),
|
||||
// Mapping of all builder fixtures defined for a given builder type.
|
||||
var BuildersAccTest = map[string][]*BuilderFixture{
|
||||
"virtualbox-iso": []*BuilderFixture{VirtualboxBuilderFixtureWindows},
|
||||
"amazon-ebs": []*BuilderFixture{AmasonEBSBuilderFixtureLinux, AmasonEBSBuilderFixtureWindows},
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"type": "amazon-ebs",
|
||||
"ami_name": "packer-acc-test",
|
||||
"instance_type": "m1.small",
|
||||
"region": "us-east-1",
|
||||
"ssh_username": "ubuntu",
|
||||
"source_ami": "ami-0568456c",
|
||||
"force_deregister" : true,
|
||||
"tags": {
|
||||
"packer-test": "true"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"type": "amazon-ebs",
|
||||
"region": "us-east-1",
|
||||
"instance_type": "t2.micro",
|
||||
"source_ami_filter": {
|
||||
"filters": {
|
||||
"virtualization-type": "hvm",
|
||||
"name": "*Windows_Server-2012-R2*English-64Bit-Base*",
|
||||
"root-device-type": "ebs"
|
||||
},
|
||||
"most_recent": true,
|
||||
"owners": "amazon"
|
||||
},
|
||||
"ami_name": "packer-acc-test",
|
||||
"user_data_file": "../../builder/amazon/ebs/acceptance/test-fixtures/scripts/bootstrap_win.txt",
|
||||
"communicator": "winrm",
|
||||
"winrm_username": "Administrator",
|
||||
"winrm_password": "SuperS3cr3t!!!!",
|
||||
"force_deregister" : true,
|
||||
"tags": {
|
||||
"packer-test": "true"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
<powershell>
|
||||
# Set administrator password
|
||||
net user Administrator SuperS3cr3t!!!!
|
||||
wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE
|
||||
|
||||
# First, make sure WinRM can't be connected to
|
||||
netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=block
|
||||
|
||||
# Delete any existing WinRM listeners
|
||||
winrm delete winrm/config/listener?Address=*+Transport=HTTP 2>$Null
|
||||
winrm delete winrm/config/listener?Address=*+Transport=HTTPS 2>$Null
|
||||
|
||||
# Disable group policies which block basic authentication and unencrypted login
|
||||
|
||||
Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WinRM\Client -Name AllowBasic -Value 1
|
||||
Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WinRM\Client -Name AllowUnencryptedTraffic -Value 1
|
||||
Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WinRM\Service -Name AllowBasic -Value 1
|
||||
Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WinRM\Service -Name AllowUnencryptedTraffic -Value 1
|
||||
|
||||
|
||||
# Create a new WinRM listener and configure
|
||||
winrm create winrm/config/listener?Address=*+Transport=HTTP
|
||||
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="0"}'
|
||||
winrm set winrm/config '@{MaxTimeoutms="7200000"}'
|
||||
winrm set winrm/config/service '@{AllowUnencrypted="true"}'
|
||||
winrm set winrm/config/service '@{MaxConcurrentOperationsPerUser="12000"}'
|
||||
winrm set winrm/config/service/auth '@{Basic="true"}'
|
||||
winrm set winrm/config/client/auth '@{Basic="true"}'
|
||||
|
||||
# Configure UAC to allow privilege elevation in remote shells
|
||||
$Key = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System'
|
||||
$Setting = 'LocalAccountTokenFilterPolicy'
|
||||
Set-ItemProperty -Path $Key -Name $Setting -Value 1 -Force
|
||||
|
||||
# Configure and restart the WinRM Service; Enable the required firewall exception
|
||||
Stop-Service -Name WinRM
|
||||
Set-Service -Name WinRM -StartupType Automatic
|
||||
netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new action=allow localip=any remoteip=any
|
||||
Start-Service -Name WinRM
|
||||
</powershell>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
# Preseeding only locale sets language, country and locale.
|
||||
d-i debian-installer/locale string en_US
|
||||
|
||||
# Keyboard selection.
|
||||
d-i console-setup/ask_detect boolean false
|
||||
d-i keyboard-configuration/xkb-keymap select us
|
||||
|
||||
choose-mirror-bin mirror/http/proxy string
|
||||
d-i base-installer/kernel/override-image string linux-server
|
||||
d-i clock-setup/utc boolean true
|
||||
d-i clock-setup/utc-auto boolean true
|
||||
d-i finish-install/reboot_in_progress note
|
||||
d-i grub-installer/only_debian boolean true
|
||||
d-i grub-installer/with_other_os boolean true
|
||||
d-i mirror/country string manual
|
||||
d-i mirror/http/directory string /ubuntu/
|
||||
d-i mirror/http/hostname string archive.ubuntu.com
|
||||
d-i mirror/http/proxy string
|
||||
d-i partman-auto-lvm/guided_size string max
|
||||
d-i partman-auto/choose_recipe select atomic
|
||||
d-i partman-auto/method string lvm
|
||||
d-i partman-lvm/confirm boolean true
|
||||
d-i partman-lvm/confirm boolean true
|
||||
d-i partman-lvm/confirm_nooverwrite boolean true
|
||||
d-i partman-lvm/device_remove_lvm boolean true
|
||||
d-i partman/choose_partition select finish
|
||||
d-i partman/confirm boolean true
|
||||
d-i partman/confirm_nooverwrite boolean true
|
||||
d-i partman/confirm_write_new_label boolean true
|
||||
d-i passwd/user-fullname string vagrant
|
||||
d-i passwd/user-uid string 1000
|
||||
d-i passwd/user-password password vagrant
|
||||
d-i passwd/user-password-again password vagrant
|
||||
d-i passwd/username string vagrant
|
||||
d-i pkgsel/include string openssh-server cryptsetup build-essential libssl-dev libreadline-dev zlib1g-dev linux-source dkms nfs-kernel-server nfs-common linux-headers-$(uname -r) perl
|
||||
d-i pkgsel/install-language-support boolean false
|
||||
d-i pkgsel/update-policy select none
|
||||
d-i pkgsel/upgrade select full-upgrade
|
||||
d-i time/zone string UTC
|
||||
d-i user-setup/allow-password-weak boolean true
|
||||
d-i user-setup/encrypt-home boolean false
|
||||
tasksel tasksel/first multiselect standard, server
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"type": "virtualbox-iso",
|
||||
"iso_checksum": "sha256:946a6077af6f5f95a51f82fdc44051c7aa19f9cfc5f737954845a6050543d7c2",
|
||||
"iso_url": "http://old-releases.ubuntu.com/releases/14.04.1/ubuntu-14.04.1-server-amd64.iso",
|
||||
"disk_size": "40960",
|
||||
"guest_os_type": "Ubuntu_64",
|
||||
"headless" : "true",
|
||||
|
||||
"ssh_password": "vagrant",
|
||||
"ssh_username": "vagrant",
|
||||
"ssh_wait_timeout": "10000s",
|
||||
|
||||
"http_directory": "../../builder/virtualbox/iso/acceptance/test-fixtures/http",
|
||||
"boot_wait": "10s",
|
||||
"boot_command": [
|
||||
"<esc><wait>",
|
||||
"<esc><wait>",
|
||||
"<enter><wait>",
|
||||
"/install/vmlinuz<wait>",
|
||||
" auto<wait>",
|
||||
" console-setup/ask_detect=false<wait>",
|
||||
" console-setup/layoutcode=us<wait>",
|
||||
" console-setup/modelcode=pc105<wait>",
|
||||
" debconf/frontend=noninteractive<wait>",
|
||||
" debian-installer=en_US.UTF-8<wait>",
|
||||
" fb=false<wait>",
|
||||
" initrd=/install/initrd.gz<wait>",
|
||||
" kbd-chooser/method=us<wait>",
|
||||
" keyboard-configuration/layout=USA<wait>",
|
||||
" keyboard-configuration/variant=USA<wait>",
|
||||
" locale=en_US.UTF-8<wait>",
|
||||
" netcfg/get_domain=vm<wait>",
|
||||
" netcfg/get_hostname=vagrant<wait>",
|
||||
" noapic<wait>",
|
||||
" preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg<wait>",
|
||||
" -- <wait>",
|
||||
"<enter><wait>"
|
||||
],
|
||||
|
||||
"output_directory": "virtualbox-iso-packer-acc-test",
|
||||
"shutdown_command": "echo 'vagrant' | sudo -S shutdown -P now",
|
||||
"post_shutdown_delay": "60s"
|
||||
}
|
|
@ -1,94 +1,110 @@
|
|||
package powershell_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/go-uuid"
|
||||
"github.com/hashicorp/packer/command"
|
||||
"github.com/hashicorp/packer/packer-plugin-sdk/acctest/provisioneracc"
|
||||
packersdk "github.com/hashicorp/packer/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/provisioner/powershell"
|
||||
windowsshellprovisioner "github.com/hashicorp/packer/provisioner/windows-shell"
|
||||
)
|
||||
|
||||
const TestProvisionerName = "powershell"
|
||||
const TestProvisionerType = "powershell"
|
||||
|
||||
func TestAccPowershellProvisioner_basic(t *testing.T) {
|
||||
provisioneracc.TestProvisionersPreCheck(TestProvisionerName, t)
|
||||
|
||||
testProvisioner := PowershellProvisionerAccTest{"powershell-provisioner-cleanup.txt"}
|
||||
provisioneracc.TestProvisionersAgainstBuilders(&testProvisioner, t)
|
||||
}
|
||||
|
||||
func TestAccPowershellProvisioner_Inline(t *testing.T) {
|
||||
provisioneracc.TestProvisionersPreCheck(TestProvisionerName, t)
|
||||
|
||||
testProvisioner := PowershellProvisionerAccTest{"powershell-inline-provisioner.txt"}
|
||||
provisioneracc.TestProvisionersAgainstBuilders(&testProvisioner, t)
|
||||
}
|
||||
|
||||
func TestAccPowershellProvisioner_Script(t *testing.T) {
|
||||
provisioneracc.TestProvisionersPreCheck(TestProvisionerName, t)
|
||||
|
||||
testProvisioner := PowershellProvisionerAccTest{"powershell-script-provisioner.txt"}
|
||||
provisioneracc.TestProvisionersAgainstBuilders(&testProvisioner, t)
|
||||
}
|
||||
|
||||
type PowershellProvisionerAccTest struct {
|
||||
ConfigName string
|
||||
}
|
||||
|
||||
func (s *PowershellProvisionerAccTest) GetName() string {
|
||||
return TestProvisionerName
|
||||
}
|
||||
|
||||
func (s *PowershellProvisionerAccTest) GetConfig() (string, error) {
|
||||
filePath := filepath.Join("./test-fixtures", s.ConfigName)
|
||||
config, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("os.Open:%v", err)
|
||||
}
|
||||
defer config.Close()
|
||||
|
||||
file, err := ioutil.ReadAll(config)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("ioutil.ReadAll:%v", err)
|
||||
}
|
||||
return string(file), nil
|
||||
}
|
||||
|
||||
func (s *PowershellProvisionerAccTest) GetProvisionerStore() packersdk.MapOfProvisioner {
|
||||
return packersdk.MapOfProvisioner{
|
||||
TestProvisionerName: func() (packersdk.Provisioner, error) { return &powershell.Provisioner{}, nil },
|
||||
"windows-shell": func() (packersdk.Provisioner, error) { return &windowsshellprovisioner.Provisioner{}, nil },
|
||||
}
|
||||
}
|
||||
|
||||
func (s *PowershellProvisionerAccTest) IsCompatible(builder string, vmOS string) bool {
|
||||
func powershellIsCompatible(builder string, vmOS string) bool {
|
||||
return vmOS == "windows"
|
||||
}
|
||||
|
||||
func (s *PowershellProvisionerAccTest) RunTest(c *command.BuildCommand, args []string) error {
|
||||
UUID := os.Getenv("PACKER_RUN_UUID")
|
||||
if UUID == "" {
|
||||
UUID, _ = uuid.GenerateUUID()
|
||||
os.Setenv("PACKER_RUN_UUID", UUID)
|
||||
}
|
||||
|
||||
if code := c.Run(args); code != 0 {
|
||||
ui := c.Meta.Ui.(*packersdk.BasicUi)
|
||||
out := ui.Writer.(*bytes.Buffer)
|
||||
err := ui.ErrorWriter.(*bytes.Buffer)
|
||||
return fmt.Errorf(
|
||||
"Bad exit code.\n\nStdout:\n\n%s\n\nStderr:\n\n%s",
|
||||
out.String(),
|
||||
err.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
func fixtureDir() string {
|
||||
_, file, _, _ := runtime.Caller(0)
|
||||
return filepath.Join(filepath.Dir(file), "test-fixtures")
|
||||
}
|
||||
|
||||
func LoadProvisionerFragment(templateFragmentPath string) (string, error) {
|
||||
dir := fixtureDir()
|
||||
fragmentAbsPath := filepath.Join(dir, templateFragmentPath)
|
||||
fragmentFile, err := os.Open(fragmentAbsPath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Unable find %s", fragmentAbsPath)
|
||||
}
|
||||
defer fragmentFile.Close()
|
||||
|
||||
fragmentString, err := ioutil.ReadAll(fragmentFile)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Unable to read %s", fragmentAbsPath)
|
||||
}
|
||||
|
||||
return string(fragmentString), nil
|
||||
}
|
||||
|
||||
func TestAccPowershellProvisioner_basic(t *testing.T) {
|
||||
templateString, err := LoadProvisionerFragment("powershell-provisioner-cleanup.txt")
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't load test fixture; %s", err.Error())
|
||||
}
|
||||
testCase := &provisioneracc.ProvisionerTestCase{
|
||||
IsCompatible: powershellIsCompatible,
|
||||
Name: "powershell-provisioner-cleanup",
|
||||
Template: templateString,
|
||||
Type: TestProvisionerType,
|
||||
Check: func(buildcommand *exec.Cmd, logfile string) error {
|
||||
if buildcommand.ProcessState != nil {
|
||||
if buildcommand.ProcessState.ExitCode() != 0 {
|
||||
return fmt.Errorf("Bad exit code. Logfile: %s", logfile)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
provisioneracc.TestProvisionersAgainstBuilders(testCase, t)
|
||||
}
|
||||
|
||||
func TestAccPowershellProvisioner_Inline(t *testing.T) {
|
||||
templateString, err := LoadProvisionerFragment("powershell-inline-provisioner.txt")
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't load test fixture; %s", err.Error())
|
||||
}
|
||||
testCase := &provisioneracc.ProvisionerTestCase{
|
||||
IsCompatible: powershellIsCompatible,
|
||||
Name: "powershell-provisioner-inline",
|
||||
Template: templateString,
|
||||
Type: TestProvisionerType,
|
||||
Check: func(buildcommand *exec.Cmd, logfile string) error {
|
||||
if buildcommand.ProcessState != nil {
|
||||
if buildcommand.ProcessState.ExitCode() != 0 {
|
||||
return fmt.Errorf("Bad exit code. Logfile: %s", logfile)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
provisioneracc.TestProvisionersAgainstBuilders(testCase, t)
|
||||
}
|
||||
|
||||
func TestAccPowershellProvisioner_Script(t *testing.T) {
|
||||
templateString, err := LoadProvisionerFragment("powershell-script-provisioner.txt")
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't load test fixture; %s", err.Error())
|
||||
}
|
||||
testCase := &provisioneracc.ProvisionerTestCase{
|
||||
IsCompatible: powershellIsCompatible,
|
||||
Name: "powershell-provisioner-script",
|
||||
Template: templateString,
|
||||
Type: TestProvisionerType,
|
||||
Check: func(buildcommand *exec.Cmd, logfile string) error {
|
||||
if buildcommand.ProcessState != nil {
|
||||
if buildcommand.ProcessState.ExitCode() != 0 {
|
||||
return fmt.Errorf("Bad exit code. Logfile: %s", logfile)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
provisioneracc.TestProvisionersAgainstBuilders(testCase, t)
|
||||
}
|
||||
|
|
|
@ -1,65 +1,76 @@
|
|||
package shell_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer/packer-plugin-sdk/acctest/provisioneracc"
|
||||
|
||||
"github.com/hashicorp/packer/provisioner/shell"
|
||||
|
||||
packersdk "github.com/hashicorp/packer/packer-plugin-sdk/packer"
|
||||
|
||||
"github.com/hashicorp/packer/command"
|
||||
"github.com/hashicorp/packer/packer-plugin-sdk/acctest/testutils"
|
||||
)
|
||||
|
||||
func TestShellLocalProvisionerWithRetryOption(t *testing.T) {
|
||||
provisioneracc.TestProvisionersPreCheck("shell-local", t)
|
||||
provisioneracc.TestProvisionersAgainstBuilders(new(ShellLocalProvisionerAccTest), t)
|
||||
func fixtureDir() string {
|
||||
_, file, _, _ := runtime.Caller(0)
|
||||
return filepath.Join(filepath.Dir(file), "test-fixtures")
|
||||
}
|
||||
|
||||
type ShellLocalProvisionerAccTest struct{}
|
||||
|
||||
func (s *ShellLocalProvisionerAccTest) GetName() string {
|
||||
return "file"
|
||||
}
|
||||
|
||||
func (s *ShellLocalProvisionerAccTest) GetConfig() (string, error) {
|
||||
filePath := filepath.Join("./test-fixtures", "shell-local-provisioner.txt")
|
||||
config, err := os.Open(filePath)
|
||||
func loadFile(templateFragmentPath string) (string, error) {
|
||||
dir := fixtureDir()
|
||||
fragmentAbsPath := filepath.Join(dir, templateFragmentPath)
|
||||
fragmentFile, err := os.Open(fragmentAbsPath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Expected to find %s", filePath)
|
||||
return "", fmt.Errorf("Unable find %s", fragmentAbsPath)
|
||||
}
|
||||
defer config.Close()
|
||||
defer fragmentFile.Close()
|
||||
|
||||
file, err := ioutil.ReadAll(config)
|
||||
return string(file), err
|
||||
fragmentString, err := ioutil.ReadAll(fragmentFile)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Unable to read %s", fragmentAbsPath)
|
||||
}
|
||||
|
||||
return string(fragmentString), nil
|
||||
}
|
||||
|
||||
func (s *ShellLocalProvisionerAccTest) GetProvisionerStore() packersdk.MapOfProvisioner {
|
||||
return packersdk.MapOfProvisioner{
|
||||
"shell-local": func() (packersdk.Provisioner, error) { return &shell.Provisioner{}, nil },
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ShellLocalProvisionerAccTest) IsCompatible(builder string, vmOS string) bool {
|
||||
func IsCompatible(builder string, vmOS string) bool {
|
||||
return vmOS == "linux"
|
||||
}
|
||||
|
||||
func (s *ShellLocalProvisionerAccTest) RunTest(c *command.BuildCommand, args []string) error {
|
||||
if code := c.Run(args); code != 0 {
|
||||
ui := c.Meta.Ui.(*packersdk.BasicUi)
|
||||
out := ui.Writer.(*bytes.Buffer)
|
||||
err := ui.ErrorWriter.(*bytes.Buffer)
|
||||
return fmt.Errorf(
|
||||
"Bad exit code.\n\nStdout:\n\n%s\n\nStderr:\n\n%s",
|
||||
out.String(),
|
||||
err.String())
|
||||
func TestAccShellProvisioner_basic(t *testing.T) {
|
||||
templateString, err := loadFile("shell-local-provisioner.txt")
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't load test fixture; %s", err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
testCase := &provisioneracc.ProvisionerTestCase{
|
||||
IsCompatible: IsCompatible,
|
||||
Name: "shell-local-provisioner-basic",
|
||||
Teardown: func() error {
|
||||
testutils.CleanupFiles("test-fixtures/file.txt")
|
||||
return nil
|
||||
},
|
||||
Template: templateString,
|
||||
Type: "shell-local",
|
||||
Check: func(buildcommand *exec.Cmd, logfile string) error {
|
||||
if buildcommand.ProcessState != nil {
|
||||
if buildcommand.ProcessState.ExitCode() != 0 {
|
||||
return fmt.Errorf("Bad exit code. Logfile: %s", logfile)
|
||||
}
|
||||
}
|
||||
filecontents, err := loadFile("file.txt")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !strings.Contains(filecontents, "hello") {
|
||||
return fmt.Errorf("file contents were wrong: %s", filecontents)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
provisioneracc.TestProvisionersAgainstBuilders(testCase, t)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [[ ! -f file.txt ]] ; then
|
||||
echo 'hello' > file.txt
|
||||
# On first try, exits 1; on second try, passes.
|
||||
if [[ ! -f test-fixtures/file.txt ]] ; then
|
||||
echo 'hello' > test-fixtures/file.txt
|
||||
exit 1
|
||||
fi
|
|
@ -1,80 +1,77 @@
|
|||
package shell_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer/packer-plugin-sdk/acctest/provisioneracc"
|
||||
"github.com/hashicorp/packer/packer-plugin-sdk/acctest/testutils"
|
||||
"github.com/hashicorp/packer/provisioner/file"
|
||||
"github.com/hashicorp/packer/provisioner/shell"
|
||||
|
||||
packersdk "github.com/hashicorp/packer/packer-plugin-sdk/packer"
|
||||
|
||||
"github.com/hashicorp/go-uuid"
|
||||
"github.com/hashicorp/packer/command"
|
||||
)
|
||||
|
||||
func TestShellProvisioner(t *testing.T) {
|
||||
provisioneracc.TestProvisionersPreCheck("shell", t)
|
||||
provisioneracc.TestProvisionersAgainstBuilders(new(ShellProvisionerAccTest), t)
|
||||
func fixtureDir() string {
|
||||
_, file, _, _ := runtime.Caller(0)
|
||||
return filepath.Join(filepath.Dir(file), "test-fixtures")
|
||||
}
|
||||
|
||||
type ShellProvisionerAccTest struct{}
|
||||
|
||||
func (s *ShellProvisionerAccTest) GetName() string {
|
||||
return "shell"
|
||||
}
|
||||
|
||||
func (s *ShellProvisionerAccTest) GetConfig() (string, error) {
|
||||
filePath := filepath.Join("./test-fixtures", "shell-provisioner.txt")
|
||||
config, err := os.Open(filePath)
|
||||
func loadFile(templateFragmentPath string) (string, error) {
|
||||
dir := fixtureDir()
|
||||
fragmentAbsPath := filepath.Join(dir, templateFragmentPath)
|
||||
fragmentFile, err := os.Open(fragmentAbsPath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Expected to find %s", filePath)
|
||||
return "", fmt.Errorf("Unable find %s", fragmentAbsPath)
|
||||
}
|
||||
defer config.Close()
|
||||
defer fragmentFile.Close()
|
||||
|
||||
file, err := ioutil.ReadAll(config)
|
||||
return string(file), err
|
||||
fragmentString, err := ioutil.ReadAll(fragmentFile)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Unable to read %s", fragmentAbsPath)
|
||||
}
|
||||
|
||||
return string(fragmentString), nil
|
||||
}
|
||||
|
||||
func (s *ShellProvisionerAccTest) GetProvisionerStore() packersdk.MapOfProvisioner {
|
||||
return packersdk.MapOfProvisioner{
|
||||
"shell": func() (packersdk.Provisioner, error) { return &shell.Provisioner{}, nil },
|
||||
"file": func() (packersdk.Provisioner, error) { return &file.Provisioner{}, nil },
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ShellProvisionerAccTest) IsCompatible(builder string, vmOS string) bool {
|
||||
func IsCompatible(builder string, vmOS string) bool {
|
||||
return vmOS == "linux"
|
||||
}
|
||||
|
||||
func (s *ShellProvisionerAccTest) RunTest(c *command.BuildCommand, args []string) error {
|
||||
UUID := os.Getenv("PACKER_RUN_UUID")
|
||||
if UUID == "" {
|
||||
UUID, _ = uuid.GenerateUUID()
|
||||
os.Setenv("PACKER_RUN_UUID", UUID)
|
||||
func TestAccShellProvisioner_basic(t *testing.T) {
|
||||
templateString, err := loadFile("shell-provisioner.txt")
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't load test fixture; %s", err.Error())
|
||||
}
|
||||
|
||||
file := "provisioner.shell." + UUID + ".txt"
|
||||
defer testutils.CleanupFiles(file)
|
||||
|
||||
if code := c.Run(args); code != 0 {
|
||||
ui := c.Meta.Ui.(*packersdk.BasicUi)
|
||||
out := ui.Writer.(*bytes.Buffer)
|
||||
err := ui.ErrorWriter.(*bytes.Buffer)
|
||||
return fmt.Errorf(
|
||||
"Bad exit code.\n\nStdout:\n\n%s\n\nStderr:\n\n%s",
|
||||
out.String(),
|
||||
err.String())
|
||||
testCase := &provisioneracc.ProvisionerTestCase{
|
||||
IsCompatible: IsCompatible,
|
||||
Name: "shell-provisioner-basic",
|
||||
Teardown: func() error {
|
||||
testutils.CleanupFiles("test-fixtures/provisioner.shell.txt")
|
||||
return nil
|
||||
},
|
||||
Template: templateString,
|
||||
Type: "shell",
|
||||
Check: func(buildcommand *exec.Cmd, logfile string) error {
|
||||
if buildcommand.ProcessState != nil {
|
||||
if buildcommand.ProcessState.ExitCode() != 0 {
|
||||
return fmt.Errorf("Bad exit code. Logfile: %s", logfile)
|
||||
}
|
||||
}
|
||||
filecontents, err := loadFile("provisioner.shell.txt")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
re := regexp.MustCompile(`build ID is .* and build UUID is [[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}`)
|
||||
if !re.MatchString(filecontents) {
|
||||
return fmt.Errorf("Bad file contents \"%s\"", filecontents)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
if !testutils.FileExists(file) {
|
||||
return fmt.Errorf("Expected to find %s", file)
|
||||
}
|
||||
return nil
|
||||
provisioneracc.TestProvisionersAgainstBuilders(testCase, t)
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"type": "shell",
|
||||
"inline": [
|
||||
"echo {{ build `ID`}} > provisioner.{{ build `PackerRunUUID`}}.txt"
|
||||
"echo build ID is {{ build `ID`}} and build UUID is {{ build `PackerRunUUID` }}> provisioner.{{ build `PackerRunUUID`}}.txt"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"source": "provisioner.{{ build `PackerRunUUID`}}.txt",
|
||||
"destination": "provisioner.shell.{{ build `PackerRunUUID`}}.txt",
|
||||
"destination": "./test-fixtures/provisioner.shell.txt",
|
||||
"direction": "download"
|
||||
}
|
Loading…
Reference in New Issue