Merge branch 'master' into fix_8730

This commit is contained in:
Adrien Delorme 2020-03-09 17:49:33 +01:00
commit 631f402d1e
36 changed files with 378 additions and 124 deletions

View File

@ -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:

View File

@ -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)

View File

@ -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

View File

@ -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",

View File

@ -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)
} }
} }

View File

@ -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

View File

@ -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

View File

@ -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")
} }

View File

@ -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

View File

@ -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

View File

@ -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")
} }

View File

@ -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",

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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

View File

@ -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())},

View File

@ -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))

View File

@ -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 {

View File

@ -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()

View File

@ -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) {

View File

@ -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.

View File

@ -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"])

View File

@ -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})
}
}

View File

@ -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,
}, },
}, },

View File

@ -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"
}

View File

@ -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":

View File

@ -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
} }

View File

@ -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()

View File

@ -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" %>

View File

@ -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

View 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": [
{ {

View File

@ -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`.

View File

@ -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`.

View File

@ -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`.

View File

@ -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`.

View File

@ -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