Merge branch 'master' into fix_8730
This commit is contained in:
commit
631f402d1e
|
@ -36,7 +36,7 @@ commands:
|
||||||
type: string
|
type: string
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- run: GOOS=<< parameters.GOOS >> go build -ldflags="-s -w" -o ./pkg/packer_<< parameters.GOOS >>_$(go env GOARCH) .
|
- run: GOOS=<< parameters.GOOS >> go build -ldflags="-s -w -X github.com/hashicorp/packer/version.GitCommit=${CIRCLE_SHA1}" -o ./pkg/packer_<< parameters.GOOS >>_$(go env GOARCH) .
|
||||||
- run: zip ./pkg/packer_<< parameters.GOOS >>_$(go env GOARCH).zip ./pkg/packer_<< parameters.GOOS >>_$(go env GOARCH)
|
- run: zip ./pkg/packer_<< parameters.GOOS >>_$(go env GOARCH).zip ./pkg/packer_<< parameters.GOOS >>_$(go env GOARCH)
|
||||||
- run: rm ./pkg/packer_<< parameters.GOOS >>_$(go env GOARCH)
|
- run: rm ./pkg/packer_<< parameters.GOOS >>_$(go env GOARCH)
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
|
|
|
@ -300,7 +300,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag)
|
||||||
if len(createOutput.Errors) > 0 {
|
if len(createOutput.Errors) > 0 {
|
||||||
errString := fmt.Sprintf("Error waiting for fleet request (%s) to become ready:", *createOutput.FleetId)
|
errString := fmt.Sprintf("Error waiting for fleet request (%s) to become ready:", *createOutput.FleetId)
|
||||||
for _, outErr := range createOutput.Errors {
|
for _, outErr := range createOutput.Errors {
|
||||||
errString = errString + fmt.Sprintf("%s", *outErr.ErrorMessage)
|
errString = errString + aws.StringValue(outErr.ErrorMessage)
|
||||||
}
|
}
|
||||||
err = fmt.Errorf(errString)
|
err = fmt.Errorf(errString)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
|
|
|
@ -186,12 +186,9 @@ func (c *Communicator) UploadDir(dst string, src string, exclude []string) error
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var dockerSource string
|
dockerSource := src
|
||||||
|
|
||||||
if src[len(src)-1] == '/' {
|
if src[len(src)-1] == '/' {
|
||||||
dockerSource = fmt.Sprintf("%s.", src)
|
dockerSource = fmt.Sprintf("%s.", src)
|
||||||
} else {
|
|
||||||
dockerSource = fmt.Sprintf("%s", src)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the directory, then copy into it
|
// Make the directory, then copy into it
|
||||||
|
|
|
@ -18,7 +18,7 @@ func (s *stepCopyDisk) Run(ctx context.Context, state multistep.StateBag) multis
|
||||||
driver := state.Get("driver").(Driver)
|
driver := state.Get("driver").(Driver)
|
||||||
isoPath := state.Get("iso_path").(string)
|
isoPath := state.Get("iso_path").(string)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
path := filepath.Join(config.OutputDir, fmt.Sprintf("%s", config.VMName))
|
path := filepath.Join(config.OutputDir, config.VMName)
|
||||||
|
|
||||||
command := []string{
|
command := []string{
|
||||||
"convert",
|
"convert",
|
||||||
|
|
|
@ -29,13 +29,13 @@ func (s *stepCreateDisk) Run(ctx context.Context, state multistep.StateBag) mult
|
||||||
ui.Say("Creating required virtual machine disks")
|
ui.Say("Creating required virtual machine disks")
|
||||||
// The 'main' or 'default' disk
|
// The 'main' or 'default' disk
|
||||||
diskFullPaths = append(diskFullPaths, filepath.Join(config.OutputDir, name))
|
diskFullPaths = append(diskFullPaths, filepath.Join(config.OutputDir, name))
|
||||||
diskSizes = append(diskSizes, fmt.Sprintf("%s", config.DiskSize))
|
diskSizes = append(diskSizes, config.DiskSize)
|
||||||
// Additional disks
|
// Additional disks
|
||||||
if len(config.AdditionalDiskSize) > 0 {
|
if len(config.AdditionalDiskSize) > 0 {
|
||||||
for i, diskSize := range config.AdditionalDiskSize {
|
for i, diskSize := range config.AdditionalDiskSize {
|
||||||
path := filepath.Join(config.OutputDir, fmt.Sprintf("%s-%d", name, i+1))
|
path := filepath.Join(config.OutputDir, fmt.Sprintf("%s-%d", name, i+1))
|
||||||
diskFullPaths = append(diskFullPaths, path)
|
diskFullPaths = append(diskFullPaths, path)
|
||||||
size := fmt.Sprintf("%s", diskSize)
|
size := diskSize
|
||||||
diskSizes = append(diskSizes, size)
|
diskSizes = append(diskSizes, size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ func (s *stepResizeDisk) Run(ctx context.Context, state multistep.StateBag) mult
|
||||||
"resize",
|
"resize",
|
||||||
"-f", config.Format,
|
"-f", config.Format,
|
||||||
path,
|
path,
|
||||||
fmt.Sprintf("%s", config.DiskSize),
|
config.DiskSize,
|
||||||
}
|
}
|
||||||
if config.DiskImage == false {
|
if config.DiskImage == false {
|
||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
|
|
|
@ -25,6 +25,9 @@ type Driver interface {
|
||||||
// Create an NVME controller
|
// Create an NVME controller
|
||||||
CreateNVMeController(vm string, controller string, portcount int) error
|
CreateNVMeController(vm string, controller string, portcount int) error
|
||||||
|
|
||||||
|
// Delete all floppy controllers
|
||||||
|
RemoveFloppyControllers(vm string) error
|
||||||
|
|
||||||
// Delete a VM by name
|
// Delete a VM by name
|
||||||
Delete(string) error
|
Delete(string) error
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,55 @@ func (d *VBox42Driver) CreateSCSIController(vmName string, name string) error {
|
||||||
return d.VBoxManage(command...)
|
return d.VBoxManage(command...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *VBox42Driver) RemoveFloppyControllers(vmName string) error {
|
||||||
|
var stdout bytes.Buffer
|
||||||
|
|
||||||
|
cmd := exec.Command(d.VBoxManagePath, "showvminfo", vmName, "--machinereadable")
|
||||||
|
cmd.Stdout = &stdout
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
StorageControllerTypeRe := regexp.MustCompile("^storagecontrollertype([0-9]+)=\"(.+)\"$")
|
||||||
|
StorageControllerNameRe := regexp.MustCompile("^storagecontrollername([0-9]+)=\"(.+)\"$")
|
||||||
|
|
||||||
|
storageControllerNames := make(map[string]string)
|
||||||
|
storageControllerIdx := ""
|
||||||
|
|
||||||
|
for _, line := range strings.Split(stdout.String(), "\n") {
|
||||||
|
// Need to trim off CR character when running in windows
|
||||||
|
// Trimming whitespaces at this point helps to filter out empty value
|
||||||
|
line = strings.TrimRight(line, " \r")
|
||||||
|
|
||||||
|
matches := StorageControllerTypeRe.FindStringSubmatch(line)
|
||||||
|
if matches != nil {
|
||||||
|
// Floppy controllers are of a type I82078
|
||||||
|
if matches[2] == "I82078" {
|
||||||
|
// VirtualBox supports only one floppy controller per VM
|
||||||
|
storageControllerIdx = matches[1]
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
matches = StorageControllerNameRe.FindStringSubmatch(line)
|
||||||
|
if matches != nil {
|
||||||
|
storageControllerNames[matches[1]] = matches[2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if storageControllerIdx == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
command := []string{
|
||||||
|
"storagectl", vmName,
|
||||||
|
"--name", storageControllerNames[storageControllerIdx],
|
||||||
|
"--remove",
|
||||||
|
}
|
||||||
|
|
||||||
|
return d.VBoxManage(command...)
|
||||||
|
}
|
||||||
|
|
||||||
func (d *VBox42Driver) Delete(name string) error {
|
func (d *VBox42Driver) Delete(name string) error {
|
||||||
return d.VBoxManage("unregistervm", name, "--delete")
|
return d.VBoxManage("unregistervm", name, "--delete")
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,9 @@ type DriverMock struct {
|
||||||
CreateNVMeControllerController string
|
CreateNVMeControllerController string
|
||||||
CreateNVMeControllerErr error
|
CreateNVMeControllerErr error
|
||||||
|
|
||||||
|
RemoveFloppyControllersVM string
|
||||||
|
RemoveFloppyControllersErr error
|
||||||
|
|
||||||
DeleteCalled bool
|
DeleteCalled bool
|
||||||
DeleteName string
|
DeleteName string
|
||||||
DeleteErr error
|
DeleteErr error
|
||||||
|
@ -81,6 +84,11 @@ func (d *DriverMock) CreateNVMeController(vm string, controller string, portcoun
|
||||||
return d.CreateNVMeControllerErr
|
return d.CreateNVMeControllerErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *DriverMock) RemoveFloppyControllers(vm string) error {
|
||||||
|
d.RemoveFloppyControllersVM = vm
|
||||||
|
return d.RemoveFloppyControllersErr
|
||||||
|
}
|
||||||
|
|
||||||
func (d *DriverMock) Delete(name string) error {
|
func (d *DriverMock) Delete(name string) error {
|
||||||
d.DeleteCalled = true
|
d.DeleteCalled = true
|
||||||
d.DeleteName = name
|
d.DeleteName = name
|
||||||
|
|
|
@ -48,6 +48,12 @@ func (s *StepAttachFloppy) Run(ctx context.Context, state multistep.StateBag) mu
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
vmName := state.Get("vmName").(string)
|
vmName := state.Get("vmName").(string)
|
||||||
|
|
||||||
|
ui.Say("Deleting any current floppy disk...")
|
||||||
|
if err := driver.RemoveFloppyControllers(vmName); err != nil {
|
||||||
|
state.Put("error", fmt.Errorf("Error deleting existing floppy controllers: %s", err))
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
|
||||||
ui.Say("Attaching floppy disk...")
|
ui.Say("Attaching floppy disk...")
|
||||||
|
|
||||||
// Create the floppy disk controller
|
// Create the floppy disk controller
|
||||||
|
|
|
@ -38,6 +38,10 @@ func TestStepAttachFloppy(t *testing.T) {
|
||||||
t.Fatal("should NOT have error")
|
t.Fatal("should NOT have error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if driver.RemoveFloppyControllersVM == "" {
|
||||||
|
t.Fatal("RemoveFloppyControllers was not called")
|
||||||
|
}
|
||||||
|
|
||||||
if len(driver.VBoxManageCalls) != 2 {
|
if len(driver.VBoxManageCalls) != 2 {
|
||||||
t.Fatal("not enough calls to VBoxManage")
|
t.Fatal("not enough calls to VBoxManage")
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ func (s *StepConfigureVRDP) Run(ctx context.Context, state multistep.StateBag) m
|
||||||
|
|
||||||
command := []string{
|
command := []string{
|
||||||
"modifyvm", vmName,
|
"modifyvm", vmName,
|
||||||
"--vrdeaddress", fmt.Sprintf("%s", s.VRDPBindAddress),
|
"--vrdeaddress", s.VRDPBindAddress,
|
||||||
"--vrdeauthtype", "null",
|
"--vrdeauthtype", "null",
|
||||||
"--vrde", "on",
|
"--vrde", "on",
|
||||||
"--vrdeport",
|
"--vrdeport",
|
||||||
|
|
|
@ -102,7 +102,7 @@ func (s *StepExport) Run(ctx context.Context, state multistep.StateBag) multiste
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.Message(fmt.Sprintf("%s", out.String()))
|
ui.Message(out.String())
|
||||||
|
|
||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,10 +52,7 @@ type NIC struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateConfig struct {
|
type CreateConfig struct {
|
||||||
DiskThinProvisioned bool
|
DiskControllerType string // example: "scsi", "pvscsi"
|
||||||
DiskEagerlyScrub bool
|
|
||||||
DiskControllerType string // example: "scsi", "pvscsi"
|
|
||||||
DiskSize int64
|
|
||||||
|
|
||||||
Annotation string
|
Annotation string
|
||||||
Name string
|
Name string
|
||||||
|
@ -69,6 +66,13 @@ type CreateConfig struct {
|
||||||
USBController bool
|
USBController bool
|
||||||
Version uint // example: 10
|
Version uint // example: 10
|
||||||
Firmware string // efi or bios
|
Firmware string // efi or bios
|
||||||
|
Storage []Disk
|
||||||
|
}
|
||||||
|
|
||||||
|
type Disk struct {
|
||||||
|
DiskSize int64
|
||||||
|
DiskEagerlyScrub bool
|
||||||
|
DiskThinProvisioned bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) NewVM(ref *types.ManagedObjectReference) *VirtualMachine {
|
func (d *Driver) NewVM(ref *types.ManagedObjectReference) *VirtualMachine {
|
||||||
|
@ -488,6 +492,10 @@ func (vm *VirtualMachine) GetDir() (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func addDisk(_ *Driver, devices object.VirtualDeviceList, config *CreateConfig) (object.VirtualDeviceList, error) {
|
func addDisk(_ *Driver, devices object.VirtualDeviceList, config *CreateConfig) (object.VirtualDeviceList, error) {
|
||||||
|
if len(config.Storage) == 0 {
|
||||||
|
return nil, errors.New("no storage devices have been defined")
|
||||||
|
}
|
||||||
|
|
||||||
device, err := devices.CreateSCSIController(config.DiskControllerType)
|
device, err := devices.CreateSCSIController(config.DiskControllerType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -498,20 +506,22 @@ func addDisk(_ *Driver, devices object.VirtualDeviceList, config *CreateConfig)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
disk := &types.VirtualDisk{
|
for _, dc := range config.Storage {
|
||||||
VirtualDevice: types.VirtualDevice{
|
disk := &types.VirtualDisk{
|
||||||
Key: devices.NewKey(),
|
VirtualDevice: types.VirtualDevice{
|
||||||
Backing: &types.VirtualDiskFlatVer2BackingInfo{
|
Key: devices.NewKey(),
|
||||||
DiskMode: string(types.VirtualDiskModePersistent),
|
Backing: &types.VirtualDiskFlatVer2BackingInfo{
|
||||||
ThinProvisioned: types.NewBool(config.DiskThinProvisioned),
|
DiskMode: string(types.VirtualDiskModePersistent),
|
||||||
EagerlyScrub: types.NewBool(config.DiskEagerlyScrub),
|
ThinProvisioned: types.NewBool(dc.DiskThinProvisioned),
|
||||||
|
EagerlyScrub: types.NewBool(dc.DiskEagerlyScrub),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
CapacityInKB: dc.DiskSize * 1024,
|
||||||
CapacityInKB: config.DiskSize * 1024,
|
}
|
||||||
}
|
|
||||||
|
|
||||||
devices.AssignController(disk, controller)
|
devices.AssignController(disk, controller)
|
||||||
devices = append(devices, disk)
|
devices = append(devices, disk)
|
||||||
|
}
|
||||||
|
|
||||||
return devices, nil
|
return devices, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//go:generate struct-markdown
|
||||||
//go:generate mapstructure-to-hcl2 -type Config
|
//go:generate mapstructure-to-hcl2 -type Config
|
||||||
|
|
||||||
package iso
|
package iso
|
||||||
|
@ -33,7 +34,10 @@ type Config struct {
|
||||||
|
|
||||||
common.ShutdownConfig `mapstructure:",squash"`
|
common.ShutdownConfig `mapstructure:",squash"`
|
||||||
|
|
||||||
CreateSnapshot bool `mapstructure:"create_snapshot"`
|
// Create a snapshot when set to `true`, so the VM can be used as a base
|
||||||
|
// for linked clones. Defaults to `false`.
|
||||||
|
CreateSnapshot bool `mapstructure:"create_snapshot"`
|
||||||
|
// Convert VM to a template. Defaults to `false`.
|
||||||
ConvertToTemplate bool `mapstructure:"convert_to_template"`
|
ConvertToTemplate bool `mapstructure:"convert_to_template"`
|
||||||
|
|
||||||
ctx interpolate.Context
|
ctx interpolate.Context
|
||||||
|
|
|
@ -31,6 +31,7 @@ type FlatConfig struct {
|
||||||
DiskSize *int64 `mapstructure:"disk_size" cty:"disk_size"`
|
DiskSize *int64 `mapstructure:"disk_size" cty:"disk_size"`
|
||||||
DiskThinProvisioned *bool `mapstructure:"disk_thin_provisioned" cty:"disk_thin_provisioned"`
|
DiskThinProvisioned *bool `mapstructure:"disk_thin_provisioned" cty:"disk_thin_provisioned"`
|
||||||
DiskEagerlyScrub *bool `mapstructure:"disk_eagerly_scrub" cty:"disk_eagerly_scrub"`
|
DiskEagerlyScrub *bool `mapstructure:"disk_eagerly_scrub" cty:"disk_eagerly_scrub"`
|
||||||
|
Storage []FlatDiskConfig `mapstructure:"storage" cty:"storage"`
|
||||||
Network *string `mapstructure:"network" cty:"network"`
|
Network *string `mapstructure:"network" cty:"network"`
|
||||||
NetworkCard *string `mapstructure:"network_card" cty:"network_card"`
|
NetworkCard *string `mapstructure:"network_card" cty:"network_card"`
|
||||||
NICs []FlatNIC `mapstructure:"network_adapters" cty:"network_adapters"`
|
NICs []FlatNIC `mapstructure:"network_adapters" cty:"network_adapters"`
|
||||||
|
@ -153,6 +154,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||||
"disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.Number, Required: false},
|
"disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.Number, Required: false},
|
||||||
"disk_thin_provisioned": &hcldec.AttrSpec{Name: "disk_thin_provisioned", Type: cty.Bool, Required: false},
|
"disk_thin_provisioned": &hcldec.AttrSpec{Name: "disk_thin_provisioned", Type: cty.Bool, Required: false},
|
||||||
"disk_eagerly_scrub": &hcldec.AttrSpec{Name: "disk_eagerly_scrub", Type: cty.Bool, Required: false},
|
"disk_eagerly_scrub": &hcldec.AttrSpec{Name: "disk_eagerly_scrub", Type: cty.Bool, Required: false},
|
||||||
|
"storage": &hcldec.BlockListSpec{TypeName: "storage", Nested: hcldec.ObjectSpec((*FlatDiskConfig)(nil).HCL2Spec())},
|
||||||
"network": &hcldec.AttrSpec{Name: "network", Type: cty.String, Required: false},
|
"network": &hcldec.AttrSpec{Name: "network", Type: cty.String, Required: false},
|
||||||
"network_card": &hcldec.AttrSpec{Name: "network_card", Type: cty.String, Required: false},
|
"network_card": &hcldec.AttrSpec{Name: "network_card", Type: cty.String, Required: false},
|
||||||
"network_adapters": &hcldec.BlockListSpec{TypeName: "network_adapters", Nested: hcldec.ObjectSpec((*FlatNIC)(nil).HCL2Spec())},
|
"network_adapters": &hcldec.BlockListSpec{TypeName: "network_adapters", Nested: hcldec.ObjectSpec((*FlatNIC)(nil).HCL2Spec())},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//go:generate struct-markdown
|
//go:generate struct-markdown
|
||||||
//go:generate mapstructure-to-hcl2 -type NIC,CreateConfig
|
//go:generate mapstructure-to-hcl2 -type NIC,CreateConfig,DiskConfig
|
||||||
|
|
||||||
package iso
|
package iso
|
||||||
|
|
||||||
|
@ -24,6 +24,15 @@ type NIC struct {
|
||||||
Passthrough *bool `mapstructure:"passthrough"`
|
Passthrough *bool `mapstructure:"passthrough"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DiskConfig struct {
|
||||||
|
// Set the size of the disk
|
||||||
|
DiskSize int64 `mapstructure:"disk_size" required:"true"`
|
||||||
|
// Enable VMDK thin provisioning for VM. Defaults to `false`.
|
||||||
|
DiskThinProvisioned bool `mapstructure:"disk_thin_provisioned"`
|
||||||
|
// Enable VMDK eager scrubbing for VM. Defaults to `false`.
|
||||||
|
DiskEagerlyScrub bool `mapstructure:"disk_eagerly_scrub"`
|
||||||
|
}
|
||||||
|
|
||||||
type CreateConfig struct {
|
type CreateConfig struct {
|
||||||
// Set VM hardware version. Defaults to the most current VM hardware
|
// Set VM hardware version. Defaults to the most current VM hardware
|
||||||
// version supported by vCenter. See
|
// version supported by vCenter. See
|
||||||
|
@ -31,7 +40,7 @@ type CreateConfig struct {
|
||||||
// the full list of supported VM hardware versions.
|
// the full list of supported VM hardware versions.
|
||||||
Version uint `mapstructure:"vm_version"`
|
Version uint `mapstructure:"vm_version"`
|
||||||
// Set VM OS type. Defaults to `otherGuest`. See [
|
// Set VM OS type. Defaults to `otherGuest`. See [
|
||||||
// here](https://pubs.vmware.com/vsphere-6-5/index.jsp?topic=%2Fcom.vmware.wssdk.apiref.doc%2Fvim.vm.GuestOsDescriptor.GuestOsIdentifier.html)
|
// here](https://code.vmware.com/apis/358/vsphere/doc/vim.vm.GuestOsDescriptor.GuestOsIdentifier.html)
|
||||||
// for a full list of possible values.
|
// for a full list of possible values.
|
||||||
GuestOSType string `mapstructure:"guest_os_type"`
|
GuestOSType string `mapstructure:"guest_os_type"`
|
||||||
// Set the Firmware at machine creation. Example `efi`. Defaults to `bios`.
|
// Set the Firmware at machine creation. Example `efi`. Defaults to `bios`.
|
||||||
|
@ -44,6 +53,8 @@ type CreateConfig struct {
|
||||||
DiskThinProvisioned bool `mapstructure:"disk_thin_provisioned"`
|
DiskThinProvisioned bool `mapstructure:"disk_thin_provisioned"`
|
||||||
// Enable VMDK eager scrubbing for VM. Defaults to `false`.
|
// Enable VMDK eager scrubbing for VM. Defaults to `false`.
|
||||||
DiskEagerlyScrub bool `mapstructure:"disk_eagerly_scrub"`
|
DiskEagerlyScrub bool `mapstructure:"disk_eagerly_scrub"`
|
||||||
|
// A collection of one or more disks to be provisioned along with the VM.
|
||||||
|
Storage []DiskConfig `mapstructure:"storage"`
|
||||||
// Set network VM will be connected to.
|
// Set network VM will be connected to.
|
||||||
Network string `mapstructure:"network"`
|
Network string `mapstructure:"network"`
|
||||||
// Set VM network card type. Example `vmxnet3`.
|
// Set VM network card type. Example `vmxnet3`.
|
||||||
|
@ -115,23 +126,38 @@ func (s *StepCreateVM) Run(_ context.Context, state multistep.StateBag) multiste
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add disk as the first drive for backwards compatibility if the type is defined
|
||||||
|
var disks []driver.Disk
|
||||||
|
if s.Config.DiskSize != 0 {
|
||||||
|
disks = append(disks, driver.Disk{
|
||||||
|
DiskSize: s.Config.DiskSize,
|
||||||
|
DiskEagerlyScrub: s.Config.DiskEagerlyScrub,
|
||||||
|
DiskThinProvisioned: s.Config.DiskThinProvisioned,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
for _, disk := range s.Config.Storage {
|
||||||
|
disks = append(disks, driver.Disk{
|
||||||
|
DiskSize: disk.DiskSize,
|
||||||
|
DiskEagerlyScrub: disk.DiskEagerlyScrub,
|
||||||
|
DiskThinProvisioned: disk.DiskThinProvisioned,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
vm, err = d.CreateVM(&driver.CreateConfig{
|
vm, err = d.CreateVM(&driver.CreateConfig{
|
||||||
DiskThinProvisioned: s.Config.DiskThinProvisioned,
|
DiskControllerType: s.Config.DiskControllerType,
|
||||||
DiskEagerlyScrub: s.Config.DiskEagerlyScrub,
|
Storage: disks,
|
||||||
DiskControllerType: s.Config.DiskControllerType,
|
Annotation: s.Config.Notes,
|
||||||
DiskSize: s.Config.DiskSize,
|
Name: s.Location.VMName,
|
||||||
Name: s.Location.VMName,
|
Folder: s.Location.Folder,
|
||||||
Folder: s.Location.Folder,
|
Cluster: s.Location.Cluster,
|
||||||
Cluster: s.Location.Cluster,
|
Host: s.Location.Host,
|
||||||
Host: s.Location.Host,
|
ResourcePool: s.Location.ResourcePool,
|
||||||
ResourcePool: s.Location.ResourcePool,
|
Datastore: s.Location.Datastore,
|
||||||
Datastore: s.Location.Datastore,
|
GuestOS: s.Config.GuestOSType,
|
||||||
GuestOS: s.Config.GuestOSType,
|
NICs: networkCards,
|
||||||
NICs: networkCards,
|
USBController: s.Config.USBController,
|
||||||
USBController: s.Config.USBController,
|
Version: s.Config.Version,
|
||||||
Version: s.Config.Version,
|
Firmware: s.Config.Firmware,
|
||||||
Firmware: s.Config.Firmware,
|
|
||||||
Annotation: s.Config.Notes,
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
state.Put("error", fmt.Errorf("error creating vm: %v", err))
|
state.Put("error", fmt.Errorf("error creating vm: %v", err))
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Code generated by "mapstructure-to-hcl2 -type NIC,CreateConfig"; DO NOT EDIT.
|
// Code generated by "mapstructure-to-hcl2 -type NIC,CreateConfig,DiskConfig"; DO NOT EDIT.
|
||||||
package iso
|
package iso
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -9,18 +9,19 @@ import (
|
||||||
// FlatCreateConfig is an auto-generated flat version of CreateConfig.
|
// FlatCreateConfig is an auto-generated flat version of CreateConfig.
|
||||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||||
type FlatCreateConfig struct {
|
type FlatCreateConfig struct {
|
||||||
Version *uint `mapstructure:"vm_version" cty:"vm_version"`
|
Version *uint `mapstructure:"vm_version" cty:"vm_version"`
|
||||||
GuestOSType *string `mapstructure:"guest_os_type" cty:"guest_os_type"`
|
GuestOSType *string `mapstructure:"guest_os_type" cty:"guest_os_type"`
|
||||||
Firmware *string `mapstructure:"firmware" cty:"firmware"`
|
Firmware *string `mapstructure:"firmware" cty:"firmware"`
|
||||||
DiskControllerType *string `mapstructure:"disk_controller_type" cty:"disk_controller_type"`
|
DiskControllerType *string `mapstructure:"disk_controller_type" cty:"disk_controller_type"`
|
||||||
DiskSize *int64 `mapstructure:"disk_size" cty:"disk_size"`
|
DiskSize *int64 `mapstructure:"disk_size" cty:"disk_size"`
|
||||||
DiskThinProvisioned *bool `mapstructure:"disk_thin_provisioned" cty:"disk_thin_provisioned"`
|
DiskThinProvisioned *bool `mapstructure:"disk_thin_provisioned" cty:"disk_thin_provisioned"`
|
||||||
DiskEagerlyScrub *bool `mapstructure:"disk_eagerly_scrub" cty:"disk_eagerly_scrub"`
|
DiskEagerlyScrub *bool `mapstructure:"disk_eagerly_scrub" cty:"disk_eagerly_scrub"`
|
||||||
Network *string `mapstructure:"network" cty:"network"`
|
Storage []FlatDiskConfig `mapstructure:"storage" cty:"storage"`
|
||||||
NetworkCard *string `mapstructure:"network_card" cty:"network_card"`
|
Network *string `mapstructure:"network" cty:"network"`
|
||||||
NICs []FlatNIC `mapstructure:"network_adapters" cty:"network_adapters"`
|
NetworkCard *string `mapstructure:"network_card" cty:"network_card"`
|
||||||
USBController *bool `mapstructure:"usb_controller" cty:"usb_controller"`
|
NICs []FlatNIC `mapstructure:"network_adapters" cty:"network_adapters"`
|
||||||
Notes *string `mapstructure:"notes" cty:"notes"`
|
USBController *bool `mapstructure:"usb_controller" cty:"usb_controller"`
|
||||||
|
Notes *string `mapstructure:"notes" cty:"notes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlatMapstructure returns a new FlatCreateConfig.
|
// FlatMapstructure returns a new FlatCreateConfig.
|
||||||
|
@ -42,6 +43,7 @@ func (*FlatCreateConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||||
"disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.Number, Required: false},
|
"disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.Number, Required: false},
|
||||||
"disk_thin_provisioned": &hcldec.AttrSpec{Name: "disk_thin_provisioned", Type: cty.Bool, Required: false},
|
"disk_thin_provisioned": &hcldec.AttrSpec{Name: "disk_thin_provisioned", Type: cty.Bool, Required: false},
|
||||||
"disk_eagerly_scrub": &hcldec.AttrSpec{Name: "disk_eagerly_scrub", Type: cty.Bool, Required: false},
|
"disk_eagerly_scrub": &hcldec.AttrSpec{Name: "disk_eagerly_scrub", Type: cty.Bool, Required: false},
|
||||||
|
"storage": &hcldec.BlockListSpec{TypeName: "storage", Nested: hcldec.ObjectSpec((*FlatDiskConfig)(nil).HCL2Spec())},
|
||||||
"network": &hcldec.AttrSpec{Name: "network", Type: cty.String, Required: false},
|
"network": &hcldec.AttrSpec{Name: "network", Type: cty.String, Required: false},
|
||||||
"network_card": &hcldec.AttrSpec{Name: "network_card", Type: cty.String, Required: false},
|
"network_card": &hcldec.AttrSpec{Name: "network_card", Type: cty.String, Required: false},
|
||||||
"network_adapters": &hcldec.BlockListSpec{TypeName: "network_adapters", Nested: hcldec.ObjectSpec((*FlatNIC)(nil).HCL2Spec())},
|
"network_adapters": &hcldec.BlockListSpec{TypeName: "network_adapters", Nested: hcldec.ObjectSpec((*FlatNIC)(nil).HCL2Spec())},
|
||||||
|
@ -51,6 +53,33 @@ func (*FlatCreateConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FlatDiskConfig is an auto-generated flat version of DiskConfig.
|
||||||
|
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||||
|
type FlatDiskConfig struct {
|
||||||
|
DiskSize *int64 `mapstructure:"disk_size" required:"true" cty:"disk_size"`
|
||||||
|
DiskThinProvisioned *bool `mapstructure:"disk_thin_provisioned" cty:"disk_thin_provisioned"`
|
||||||
|
DiskEagerlyScrub *bool `mapstructure:"disk_eagerly_scrub" cty:"disk_eagerly_scrub"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlatMapstructure returns a new FlatDiskConfig.
|
||||||
|
// FlatDiskConfig is an auto-generated flat version of DiskConfig.
|
||||||
|
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||||
|
func (*DiskConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||||
|
return new(FlatDiskConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HCL2Spec returns the hcl spec of a DiskConfig.
|
||||||
|
// This spec is used by HCL to read the fields of DiskConfig.
|
||||||
|
// The decoded values from this spec will then be applied to a FlatDiskConfig.
|
||||||
|
func (*FlatDiskConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||||
|
s := map[string]hcldec.Spec{
|
||||||
|
"disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.Number, Required: false},
|
||||||
|
"disk_thin_provisioned": &hcldec.AttrSpec{Name: "disk_thin_provisioned", Type: cty.Bool, Required: false},
|
||||||
|
"disk_eagerly_scrub": &hcldec.AttrSpec{Name: "disk_eagerly_scrub", Type: cty.Bool, Required: false},
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
// FlatNIC is an auto-generated flat version of NIC.
|
// FlatNIC is an auto-generated flat version of NIC.
|
||||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||||
type FlatNIC struct {
|
type FlatNIC struct {
|
||||||
|
|
|
@ -165,8 +165,8 @@ func createFlattenedEnvVars(config *Config) (string, error) {
|
||||||
envVars := make(map[string]string)
|
envVars := make(map[string]string)
|
||||||
|
|
||||||
// Always available Packer provided env vars
|
// Always available Packer provided env vars
|
||||||
envVars["PACKER_BUILD_NAME"] = fmt.Sprintf("%s", config.PackerBuildName)
|
envVars["PACKER_BUILD_NAME"] = config.PackerBuildName
|
||||||
envVars["PACKER_BUILDER_TYPE"] = fmt.Sprintf("%s", config.PackerBuilderType)
|
envVars["PACKER_BUILDER_TYPE"] = config.PackerBuilderType
|
||||||
|
|
||||||
// expose ip address variables
|
// expose ip address variables
|
||||||
httpAddr := common.GetHTTPAddr()
|
httpAddr := common.GetHTTPAddr()
|
||||||
|
|
|
@ -94,7 +94,7 @@ func GetHTTPPort() string {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s", port)
|
return port
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetHTTPIP() string {
|
func GetHTTPIP() string {
|
||||||
|
@ -102,7 +102,7 @@ func GetHTTPIP() string {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s", ip)
|
return ip
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StepHTTPServer) Cleanup(multistep.StateBag) {
|
func (s *StepHTTPServer) Cleanup(multistep.StateBag) {
|
||||||
|
|
|
@ -61,8 +61,8 @@ func PopulateProvisionHookData(state multistep.StateBag) map[string]interface{}
|
||||||
hookData["User"] = commConf.User()
|
hookData["User"] = commConf.User()
|
||||||
hookData["Password"] = commConf.Password()
|
hookData["Password"] = commConf.Password()
|
||||||
hookData["ConnType"] = commConf.Type
|
hookData["ConnType"] = commConf.Type
|
||||||
hookData["SSHPublicKey"] = commConf.SSHPublicKey
|
hookData["SSHPublicKey"] = string(commConf.SSHPublicKey)
|
||||||
hookData["SSHPrivateKey"] = commConf.SSHPrivateKey
|
hookData["SSHPrivateKey"] = string(commConf.SSHPrivateKey)
|
||||||
|
|
||||||
// Backwards compatibility; in practice, WinRMPassword is fulfilled by
|
// Backwards compatibility; in practice, WinRMPassword is fulfilled by
|
||||||
// Password.
|
// Password.
|
||||||
|
|
|
@ -83,13 +83,11 @@ func TestPopulateProvisionHookData(t *testing.T) {
|
||||||
if hookData["ConnType"] != commConfig.Type {
|
if hookData["ConnType"] != commConfig.Type {
|
||||||
t.Fatalf("Bad: Expecting hookData[\"ConnType\"] was %s but actual value was %s", commConfig.Type, hookData["ConnType"])
|
t.Fatalf("Bad: Expecting hookData[\"ConnType\"] was %s but actual value was %s", commConfig.Type, hookData["ConnType"])
|
||||||
}
|
}
|
||||||
sshPublicKey := fmt.Sprintf("%v", hookData["SSHPublicKey"].(interface{}))
|
if hookData["SSHPublicKey"] != string(commConfig.SSHPublicKey) {
|
||||||
if sshPublicKey == string(commConfig.SSHPublicKey) {
|
t.Fatalf("Bad: Expecting hookData[\"SSHPublicKey\"] was %s but actual value was %s", string(commConfig.SSHPublicKey), hookData["SSHPublicKey"])
|
||||||
t.Fatalf("Bad: Expecting hookData[\"SSHPublicKey\"] was %s but actual value was %s", string(commConfig.SSHPublicKey), sshPublicKey)
|
|
||||||
}
|
}
|
||||||
sshPrivateKey := fmt.Sprintf("%v", hookData["SSHPrivateKey"].(interface{}))
|
if hookData["SSHPrivateKey"] != string(commConfig.SSHPrivateKey) {
|
||||||
if sshPrivateKey == string(commConfig.SSHPrivateKey) {
|
t.Fatalf("Bad: Expecting hookData[\"SSHPrivateKey\"] was %s but actual value was %s", string(commConfig.SSHPrivateKey), hookData["SSHPrivateKey"])
|
||||||
t.Fatalf("Bad: Expecting hookData[\"SSHPrivateKey\"] was %s but actual value was %s", string(commConfig.SSHPrivateKey), sshPrivateKey)
|
|
||||||
}
|
}
|
||||||
if hookData["WinRMPassword"] != commConfig.WinRMPassword {
|
if hookData["WinRMPassword"] != commConfig.WinRMPassword {
|
||||||
t.Fatalf("Bad: Expecting hookData[\"WinRMPassword\"] was %s but actual value was %s", commConfig.WinRMPassword, hookData["WinRMPassword"])
|
t.Fatalf("Bad: Expecting hookData[\"WinRMPassword\"] was %s but actual value was %s", commConfig.WinRMPassword, hookData["WinRMPassword"])
|
||||||
|
|
|
@ -177,7 +177,6 @@ func (variables *Variables) decodeVariableBlock(block *hcl.Block, ectx *hcl.Eval
|
||||||
}
|
}
|
||||||
|
|
||||||
res.Type = tp
|
res.Type = tp
|
||||||
delete(attrs, "type")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if def, ok := attrs["default"]; ok {
|
if def, ok := attrs["default"]; ok {
|
||||||
|
@ -203,6 +202,13 @@ func (variables *Variables) decodeVariableBlock(block *hcl.Block, ectx *hcl.Eval
|
||||||
}
|
}
|
||||||
|
|
||||||
res.DefaultValue = defaultValue
|
res.DefaultValue = defaultValue
|
||||||
|
|
||||||
|
// It's possible no type attribute was assigned so lets make
|
||||||
|
// sure we have a valid type otherwise there will be issues parsing the value.
|
||||||
|
if res.Type == cty.NilType {
|
||||||
|
res.Type = res.DefaultValue.Type()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if len(attrs) > 0 {
|
if len(attrs) > 0 {
|
||||||
keys := []string{}
|
keys := []string{}
|
||||||
|
@ -252,7 +258,7 @@ func (cfg *PackerConfig) collectInputVariableValues(env []string, files []*hcl.F
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeFilename := fmt.Sprintf("<value for var.%s from env>", name)
|
fakeFilename := fmt.Sprintf("<value for var.%s from env>", name)
|
||||||
expr, moreDiags := hclsyntax.ParseExpression([]byte(value), fakeFilename, hcl.Pos{Line: 1, Column: 1})
|
expr, moreDiags := expressionFromVariableDefinition(fakeFilename, value, variable.Type)
|
||||||
diags = append(diags, moreDiags...)
|
diags = append(diags, moreDiags...)
|
||||||
if moreDiags.HasErrors() {
|
if moreDiags.HasErrors() {
|
||||||
continue
|
continue
|
||||||
|
@ -260,7 +266,6 @@ func (cfg *PackerConfig) collectInputVariableValues(env []string, files []*hcl.F
|
||||||
|
|
||||||
val, valDiags := expr.Value(nil)
|
val, valDiags := expr.Value(nil)
|
||||||
diags = append(diags, valDiags...)
|
diags = append(diags, valDiags...)
|
||||||
|
|
||||||
if variable.Type != cty.NilType {
|
if variable.Type != cty.NilType {
|
||||||
var err error
|
var err error
|
||||||
val, err = convert.Convert(val, variable.Type)
|
val, err = convert.Convert(val, variable.Type)
|
||||||
|
@ -274,7 +279,6 @@ func (cfg *PackerConfig) collectInputVariableValues(env []string, files []*hcl.F
|
||||||
val = cty.DynamicVal
|
val = cty.DynamicVal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable.EnvValue = val
|
variable.EnvValue = val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,11 +384,12 @@ func (cfg *PackerConfig) collectInputVariableValues(env []string, files []*hcl.F
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeFilename := fmt.Sprintf("<value for var.%s from arguments>", name)
|
fakeFilename := fmt.Sprintf("<value for var.%s from arguments>", name)
|
||||||
expr, moreDiags := hclsyntax.ParseExpression([]byte(value), fakeFilename, hcl.Pos{Line: 1, Column: 1})
|
expr, moreDiags := expressionFromVariableDefinition(fakeFilename, value, variable.Type)
|
||||||
diags = append(diags, moreDiags...)
|
diags = append(diags, moreDiags...)
|
||||||
if moreDiags.HasErrors() {
|
if moreDiags.HasErrors() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
val, valDiags := expr.Value(nil)
|
val, valDiags := expr.Value(nil)
|
||||||
diags = append(diags, valDiags...)
|
diags = append(diags, valDiags...)
|
||||||
|
|
||||||
|
@ -407,3 +412,14 @@ func (cfg *PackerConfig) collectInputVariableValues(env []string, files []*hcl.F
|
||||||
|
|
||||||
return diags
|
return diags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// expressionFromVariableDefinition creates an hclsyntax.Expression that is capable of evaluating the specified value for a given cty.Type.
|
||||||
|
// The specified filename is to identify the source of where value originated from in the diagnostics report, if there is an error.
|
||||||
|
func expressionFromVariableDefinition(filename string, value string, variableType cty.Type) (hclsyntax.Expression, hcl.Diagnostics) {
|
||||||
|
switch variableType {
|
||||||
|
case cty.String, cty.Number:
|
||||||
|
return &hclsyntax.LiteralValueExpr{Val: cty.StringVal(value)}, nil
|
||||||
|
default:
|
||||||
|
return hclsyntax.ParseExpression([]byte(value), filename, hcl.Pos{Line: 1, Column: 1})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -262,15 +262,18 @@ func TestVariables_collectVariableValues(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
|
|
||||||
{name: "string",
|
{name: "string",
|
||||||
variables: Variables{"used_string": &Variable{DefaultValue: cty.StringVal("default_value")}},
|
variables: Variables{"used_string": &Variable{
|
||||||
|
DefaultValue: cty.StringVal("default_value"),
|
||||||
|
Type: cty.String,
|
||||||
|
}},
|
||||||
args: args{
|
args: args{
|
||||||
env: []string{`PKR_VAR_used_string="env_value"`},
|
env: []string{`PKR_VAR_used_string=env_value`},
|
||||||
hclFiles: []string{
|
hclFiles: []string{
|
||||||
`used_string="xy"`,
|
`used_string="xy"`,
|
||||||
`used_string="varfile_value"`,
|
`used_string="varfile_value"`,
|
||||||
},
|
},
|
||||||
argv: map[string]string{
|
argv: map[string]string{
|
||||||
"used_string": `"cmd_value"`,
|
"used_string": `cmd_value`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -278,6 +281,7 @@ func TestVariables_collectVariableValues(t *testing.T) {
|
||||||
wantDiags: false,
|
wantDiags: false,
|
||||||
wantVariables: Variables{
|
wantVariables: Variables{
|
||||||
"used_string": &Variable{
|
"used_string": &Variable{
|
||||||
|
Type: cty.String,
|
||||||
CmdValue: cty.StringVal("cmd_value"),
|
CmdValue: cty.StringVal("cmd_value"),
|
||||||
VarfileValue: cty.StringVal("varfile_value"),
|
VarfileValue: cty.StringVal("varfile_value"),
|
||||||
EnvValue: cty.StringVal("env_value"),
|
EnvValue: cty.StringVal("env_value"),
|
||||||
|
@ -289,6 +293,38 @@ func TestVariables_collectVariableValues(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{name: "quoted string",
|
||||||
|
variables: Variables{"quoted_string": &Variable{
|
||||||
|
DefaultValue: cty.StringVal(`"default_value"`),
|
||||||
|
Type: cty.String,
|
||||||
|
}},
|
||||||
|
args: args{
|
||||||
|
env: []string{`PKR_VAR_quoted_string="env_value"`},
|
||||||
|
hclFiles: []string{
|
||||||
|
`quoted_string="\"xy\""`,
|
||||||
|
`quoted_string="\"varfile_value\""`,
|
||||||
|
},
|
||||||
|
argv: map[string]string{
|
||||||
|
"quoted_string": `"cmd_value"`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// output
|
||||||
|
wantDiags: false,
|
||||||
|
wantVariables: Variables{
|
||||||
|
"quoted_string": &Variable{
|
||||||
|
Type: cty.String,
|
||||||
|
CmdValue: cty.StringVal(`"cmd_value"`),
|
||||||
|
VarfileValue: cty.StringVal(`"varfile_value"`),
|
||||||
|
EnvValue: cty.StringVal(`"env_value"`),
|
||||||
|
DefaultValue: cty.StringVal(`"default_value"`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantValues: map[string]cty.Value{
|
||||||
|
"quoted_string": cty.StringVal(`"cmd_value"`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
{name: "array of strings",
|
{name: "array of strings",
|
||||||
variables: Variables{"used_strings": &Variable{
|
variables: Variables{"used_strings": &Variable{
|
||||||
DefaultValue: stringListVal("default_value_1"),
|
DefaultValue: stringListVal("default_value_1"),
|
||||||
|
@ -321,8 +357,42 @@ func TestVariables_collectVariableValues(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{name: "bool",
|
||||||
|
variables: Variables{"enabled": &Variable{
|
||||||
|
DefaultValue: cty.False,
|
||||||
|
Type: cty.Bool,
|
||||||
|
}},
|
||||||
|
args: args{
|
||||||
|
env: []string{`PKR_VAR_enabled=true`},
|
||||||
|
hclFiles: []string{
|
||||||
|
`enabled="false"`,
|
||||||
|
},
|
||||||
|
argv: map[string]string{
|
||||||
|
"enabled": `true`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// output
|
||||||
|
wantDiags: false,
|
||||||
|
wantVariables: Variables{
|
||||||
|
"enabled": &Variable{
|
||||||
|
Type: cty.Bool,
|
||||||
|
CmdValue: cty.True,
|
||||||
|
VarfileValue: cty.False,
|
||||||
|
EnvValue: cty.True,
|
||||||
|
DefaultValue: cty.False,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantValues: map[string]cty.Value{
|
||||||
|
"enabled": cty.True,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
{name: "invalid env var",
|
{name: "invalid env var",
|
||||||
variables: Variables{"used_string": &Variable{DefaultValue: cty.StringVal("default_value")}},
|
variables: Variables{"used_string": &Variable{
|
||||||
|
DefaultValue: cty.StringVal("default_value"),
|
||||||
|
Type: cty.String,
|
||||||
|
}},
|
||||||
args: args{
|
args: args{
|
||||||
env: []string{`PKR_VAR_used_string`},
|
env: []string{`PKR_VAR_used_string`},
|
||||||
},
|
},
|
||||||
|
@ -331,6 +401,7 @@ func TestVariables_collectVariableValues(t *testing.T) {
|
||||||
wantDiags: false,
|
wantDiags: false,
|
||||||
wantVariables: Variables{
|
wantVariables: Variables{
|
||||||
"used_string": &Variable{
|
"used_string": &Variable{
|
||||||
|
Type: cty.String,
|
||||||
DefaultValue: cty.StringVal("default_value"),
|
DefaultValue: cty.StringVal("default_value"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -398,11 +469,11 @@ func TestVariables_collectVariableValues(t *testing.T) {
|
||||||
{name: "value not corresponding to type - env",
|
{name: "value not corresponding to type - env",
|
||||||
variables: Variables{
|
variables: Variables{
|
||||||
"used_string": &Variable{
|
"used_string": &Variable{
|
||||||
Type: cty.String,
|
Type: cty.List(cty.String),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
env: []string{`PKR_VAR_used_string=["string"]`},
|
env: []string{`PKR_VAR_used_string="string"`},
|
||||||
},
|
},
|
||||||
|
|
||||||
// output
|
// output
|
||||||
|
@ -410,7 +481,7 @@ func TestVariables_collectVariableValues(t *testing.T) {
|
||||||
wantDiagsHasError: true,
|
wantDiagsHasError: true,
|
||||||
wantVariables: Variables{
|
wantVariables: Variables{
|
||||||
"used_string": &Variable{
|
"used_string": &Variable{
|
||||||
Type: cty.String,
|
Type: cty.List(cty.String),
|
||||||
EnvValue: cty.DynamicVal,
|
EnvValue: cty.DynamicVal,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -422,7 +493,7 @@ func TestVariables_collectVariableValues(t *testing.T) {
|
||||||
{name: "value not corresponding to type - cfg file",
|
{name: "value not corresponding to type - cfg file",
|
||||||
variables: Variables{
|
variables: Variables{
|
||||||
"used_string": &Variable{
|
"used_string": &Variable{
|
||||||
Type: cty.String,
|
Type: cty.Bool,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
|
@ -434,7 +505,7 @@ func TestVariables_collectVariableValues(t *testing.T) {
|
||||||
wantDiagsHasError: true,
|
wantDiagsHasError: true,
|
||||||
wantVariables: Variables{
|
wantVariables: Variables{
|
||||||
"used_string": &Variable{
|
"used_string": &Variable{
|
||||||
Type: cty.String,
|
Type: cty.Bool,
|
||||||
VarfileValue: cty.DynamicVal,
|
VarfileValue: cty.DynamicVal,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -446,12 +517,12 @@ func TestVariables_collectVariableValues(t *testing.T) {
|
||||||
{name: "value not corresponding to type - argv",
|
{name: "value not corresponding to type - argv",
|
||||||
variables: Variables{
|
variables: Variables{
|
||||||
"used_string": &Variable{
|
"used_string": &Variable{
|
||||||
Type: cty.String,
|
Type: cty.Bool,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
argv: map[string]string{
|
argv: map[string]string{
|
||||||
"used_string": `["string"]`,
|
"used_string": `["true"]`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -460,7 +531,7 @@ func TestVariables_collectVariableValues(t *testing.T) {
|
||||||
wantDiagsHasError: true,
|
wantDiagsHasError: true,
|
||||||
wantVariables: Variables{
|
wantVariables: Variables{
|
||||||
"used_string": &Variable{
|
"used_string": &Variable{
|
||||||
Type: cty.String,
|
Type: cty.Bool,
|
||||||
CmdValue: cty.DynamicVal,
|
CmdValue: cty.DynamicVal,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -70,19 +70,3 @@ func (t *mockT) Skip(args ...interface{}) {
|
||||||
t.SkipArgs = args
|
t.SkipArgs = args
|
||||||
t.f = true
|
t.f = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *mockT) failed() bool {
|
|
||||||
return t.f
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *mockT) failMessage() string {
|
|
||||||
if t.FatalCalled {
|
|
||||||
return t.FatalArgs[0].(string)
|
|
||||||
} else if t.ErrorCalled {
|
|
||||||
return t.ErrorArgs[0].(string)
|
|
||||||
} else if t.SkipCalled {
|
|
||||||
return t.SkipArgs[0].(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
return "unknown"
|
|
||||||
}
|
|
||||||
|
|
|
@ -326,7 +326,7 @@ func (c *Config) Port() int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Host returns the port that will be used for access based on config.
|
// Host returns the host that will be used for access based on config.
|
||||||
func (c *Config) Host() string {
|
func (c *Config) Host() string {
|
||||||
switch c.Type {
|
switch c.Type {
|
||||||
case "ssh":
|
case "ssh":
|
||||||
|
@ -338,7 +338,7 @@ func (c *Config) Host() string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// User returns the port that will be used for access based on config.
|
// User returns the user that will be used for access based on config.
|
||||||
func (c *Config) User() string {
|
func (c *Config) User() string {
|
||||||
switch c.Type {
|
switch c.Type {
|
||||||
case "ssh":
|
case "ssh":
|
||||||
|
@ -350,7 +350,7 @@ func (c *Config) User() string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Password returns the port that will be used for access based on config.
|
// Password returns the password that will be used for access based on config.
|
||||||
func (c *Config) Password() string {
|
func (c *Config) Password() string {
|
||||||
switch c.Type {
|
switch c.Type {
|
||||||
case "ssh":
|
case "ssh":
|
||||||
|
|
|
@ -217,8 +217,8 @@ func (p *PostProcessor) BuildArgs(source, ovftool_uri string) ([]string, error)
|
||||||
args = append(args, p.config.Options...)
|
args = append(args, p.config.Options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
args = append(args, fmt.Sprintf(`%s`, source))
|
args = append(args, source)
|
||||||
args = append(args, fmt.Sprintf(`%s`, ovftool_uri))
|
args = append(args, ovftool_uri)
|
||||||
|
|
||||||
return args, nil
|
return args, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -406,8 +406,8 @@ func (p *Provisioner) escapeEnvVars() ([]string, map[string]string) {
|
||||||
envVars := make(map[string]string)
|
envVars := make(map[string]string)
|
||||||
|
|
||||||
// Always available Packer provided env vars
|
// Always available Packer provided env vars
|
||||||
envVars["PACKER_BUILD_NAME"] = fmt.Sprintf("%s", p.config.PackerBuildName)
|
envVars["PACKER_BUILD_NAME"] = p.config.PackerBuildName
|
||||||
envVars["PACKER_BUILDER_TYPE"] = fmt.Sprintf("%s", p.config.PackerBuilderType)
|
envVars["PACKER_BUILDER_TYPE"] = p.config.PackerBuilderType
|
||||||
|
|
||||||
// expose ip address variables
|
// expose ip address variables
|
||||||
httpAddr := common.GetHTTPAddr()
|
httpAddr := common.GetHTTPAddr()
|
||||||
|
|
|
@ -43,6 +43,8 @@ references for [ISO](#iso-configuration),
|
||||||
configuration references, which are
|
configuration references, which are
|
||||||
necessary for this build to succeed and can be found further down the page.
|
necessary for this build to succeed and can be found further down the page.
|
||||||
|
|
||||||
|
<%= partial "partials/builder/vsphere/iso/Config-not-required" %>
|
||||||
|
|
||||||
### Connection Configuration
|
### Connection Configuration
|
||||||
<%= partial "partials/builder/vsphere/common/ConnectConfig-not-required" %>
|
<%= partial "partials/builder/vsphere/common/ConnectConfig-not-required" %>
|
||||||
|
|
||||||
|
@ -70,6 +72,10 @@ necessary for this build to succeed and can be found further down the page.
|
||||||
### Network Adapter Configuration
|
### Network Adapter Configuration
|
||||||
<%= partial "partials/builder/vsphere/iso/NIC-required" %>
|
<%= partial "partials/builder/vsphere/iso/NIC-required" %>
|
||||||
|
|
||||||
|
### Storage Configuration
|
||||||
|
<%= partial "partials/builder/vsphere/iso/DiskConfig-required" %>
|
||||||
|
<%= partial "partials/builder/vsphere/iso/DiskConfig-not-required" %>
|
||||||
|
|
||||||
### Floppy Configuration
|
### Floppy Configuration
|
||||||
<%= partial "partials/builder/vsphere/iso/FloppyConfig-not-required" %>
|
<%= partial "partials/builder/vsphere/iso/FloppyConfig-not-required" %>
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ However, if you are building from a brand-new and unconfigured operating system
|
||||||
image, you will almost always have to perform some extra work to configure SSH
|
image, you will almost always have to perform some extra work to configure SSH
|
||||||
on the guest machine. For most operating system distributions, this work will
|
on the guest machine. For most operating system distributions, this work will
|
||||||
be performed by a
|
be performed by a
|
||||||
(boot command)[/docs/builders/vmware-iso.html#boot-configuration]
|
[boot command](/docs/builders/vmware-iso.html#boot-configuration)
|
||||||
that references a file which provides answers to the normally-interactive
|
that references a file which provides answers to the normally-interactive
|
||||||
questions you get asked when installing an operating system. The name of this
|
questions you get asked when installing an operating system. The name of this
|
||||||
file varies by operating system; some common examples are the "preseed" file
|
file varies by operating system; some common examples are the "preseed" file
|
||||||
|
|
|
@ -27,7 +27,7 @@ DigitalOcean. Replace the mock `api_token` value with your own.
|
||||||
|
|
||||||
Example Packer template:
|
Example Packer template:
|
||||||
|
|
||||||
``` json
|
```json
|
||||||
{
|
{
|
||||||
"provisioners": [
|
"provisioners": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -74,15 +74,37 @@ Here is a full list of the available functions for reference.
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Valid variables to request are: "ID", "Host",
|
Valid variables to request are:
|
||||||
"Port", "User", "Password", "ConnType",
|
- __ID__: Represents the vm being provisioned. For example, in Amazon it is the instance id; in digitalocean,
|
||||||
"PackerRunUUID", "PackerHTTPAddr", "SSHPublicKey", and "SSHPrivateKey".
|
it is the droplet id; in Vmware, it is the vm name.
|
||||||
Depending on which communicator you are using, some of these values may be
|
|
||||||
empty -- for example, the public and private keys are unique to the SSH
|
- __Host__, __Port__, __User__ and __Password__: The host, port, user, and password that Packer uses to access the machine.
|
||||||
communicator. InstanceID represents the vm being provisioned. For example,
|
Useful for using the shell local provisioner to run Ansible or Inspec against the provisioned instance.
|
||||||
in Amazon it is the instance id; in digitalocean, it is the droplet id; in
|
|
||||||
Vmware, it is the vm name.
|
- __ConnType__: Type of communicator being used. For example, for SSH communicator this will be "ssh".
|
||||||
|
|
||||||
|
- __PackerRunUUID__: Current build's unique id. Can be used to specify build artifacts.
|
||||||
|
|
||||||
|
- __PackerHTTPAddr__: HTTP address of the file server Packer creates to serve items in the "http" dir to the vm, displayed in the format `IP:PORT`.
|
||||||
|
|
||||||
|
- __SSHPublicKey__ and __SSHPrivateKey__: The public and private key that Packer uses to connect to the instance.
|
||||||
|
These are unique to the SSH communicator and are unset when using other communicators.
|
||||||
|
__SSHPublicKey__ and __SSHPrivateKey__ can have escape sequences and special characters so their output should be single quoted to avoid surprises. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
...
|
||||||
|
"provisioners": [
|
||||||
|
{
|
||||||
|
"type": "shell",
|
||||||
|
"inline": [
|
||||||
|
"echo '{{ build `SSHPrivateKey`}}' > /tmp/packer-session.pem"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
For backwards compatability, `WinRMPassword` is also available through this
|
For backwards compatability, `WinRMPassword` is also available through this
|
||||||
engine, though it is no different than using the more general `Password`.
|
engine, though it is no different than using the more general `Password`.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
<!-- Code generated from the comments of the Config struct in builder/vsphere/iso/config.go; DO NOT EDIT MANUALLY -->
|
||||||
|
|
||||||
|
- `create_snapshot` (bool) - Create a snapshot when set to `true`, so the VM can be used as a base
|
||||||
|
for linked clones. Defaults to `false`.
|
||||||
|
|
||||||
|
- `convert_to_template` (bool) - Convert VM to a template. Defaults to `false`.
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
the full list of supported VM hardware versions.
|
the full list of supported VM hardware versions.
|
||||||
|
|
||||||
- `guest_os_type` (string) - Set VM OS type. Defaults to `otherGuest`. See [
|
- `guest_os_type` (string) - Set VM OS type. Defaults to `otherGuest`. See [
|
||||||
here](https://pubs.vmware.com/vsphere-6-5/index.jsp?topic=%2Fcom.vmware.wssdk.apiref.doc%2Fvim.vm.GuestOsDescriptor.GuestOsIdentifier.html)
|
here](https://code.vmware.com/apis/358/vsphere/doc/vim.vm.GuestOsDescriptor.GuestOsIdentifier.html)
|
||||||
for a full list of possible values.
|
for a full list of possible values.
|
||||||
|
|
||||||
- `firmware` (string) - Set the Firmware at machine creation. Example `efi`. Defaults to `bios`.
|
- `firmware` (string) - Set the Firmware at machine creation. Example `efi`. Defaults to `bios`.
|
||||||
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
- `disk_eagerly_scrub` (bool) - Enable VMDK eager scrubbing for VM. Defaults to `false`.
|
- `disk_eagerly_scrub` (bool) - Enable VMDK eager scrubbing for VM. Defaults to `false`.
|
||||||
|
|
||||||
|
- `storage` ([]DiskConfig) - A collection of one or more disks to be provisioned along with the VM.
|
||||||
|
|
||||||
- `network` (string) - Set network VM will be connected to.
|
- `network` (string) - Set network VM will be connected to.
|
||||||
|
|
||||||
- `network_card` (string) - Set VM network card type. Example `vmxnet3`.
|
- `network_card` (string) - Set VM network card type. Example `vmxnet3`.
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<!-- Code generated from the comments of the DiskConfig struct in builder/vsphere/iso/step_create.go; DO NOT EDIT MANUALLY -->
|
||||||
|
|
||||||
|
- `disk_thin_provisioned` (bool) - Enable VMDK thin provisioning for VM. Defaults to `false`.
|
||||||
|
|
||||||
|
- `disk_eagerly_scrub` (bool) - Enable VMDK eager scrubbing for VM. Defaults to `false`.
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
<!-- Code generated from the comments of the DiskConfig struct in builder/vsphere/iso/step_create.go; DO NOT EDIT MANUALLY -->
|
||||||
|
|
||||||
|
- `disk_size` (int64) - Set the size of the disk
|
||||||
|
|
Loading…
Reference in New Issue